@ganakailabs/cloudeval-cli 0.18.4 → 0.19.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/README.md +99 -8
- package/dist/{App-64BACPSQ.js → App-CPX5VUMP.js} +2 -2
- package/dist/{Banner-BIUMDX72.js → Banner-RTNNHPNK.js} +2 -2
- package/dist/{chunk-GY4W535V.js → chunk-T5TH36K2.js} +1 -1
- package/dist/{chunk-RQ2GBK43.js → chunk-ULQTRACZ.js} +1 -1
- package/dist/cli.js +343 -56
- package/package.json +22 -3
- package/sbom.spdx.json +1 -1
package/README.md
CHANGED
|
@@ -1,23 +1,114 @@
|
|
|
1
1
|
# CloudEval CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/ganakailabs/cloudeval-cli/main/docs/assets/cloudeval-cli-banner.png" alt="CloudEval CLI terminal banner" width="100%">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/@ganakailabs/cloudeval-cli"><img alt="npm" src="https://img.shields.io/npm/v/@ganakailabs/cloudeval-cli?style=flat-square"></a>
|
|
9
|
+
<a href="https://github.com/ganakailabs/cloudeval-cli/releases"><img alt="release" src="https://img.shields.io/github/v/release/ganakailabs/cloudeval-cli?sort=semver&style=flat-square"></a>
|
|
10
|
+
<a href="https://github.com/ganakailabs/cloudeval-cli/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/badge/license-CloudEval%20CLI%20License-blue?style=flat-square"></a>
|
|
11
|
+
<a href="https://docs.cloudeval.ai/reference/cli-overview"><img alt="docs" src="https://img.shields.io/badge/docs-docs.cloudeval.ai-2d6cdf?style=flat-square"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
CloudEval CLI brings CloudEval into your terminal, scripts, and agent tools. It
|
|
15
|
+
supports cloud chat, Agent mode, Agent Profiles, project and report inspection,
|
|
16
|
+
template validation, recipes, local hooks, and MCP server workflows.
|
|
17
|
+
|
|
18
|
+
[CloudEval](https://cloudeval.ai) | [Docs](https://docs.cloudeval.ai/reference/cli-overview) | [GitHub](https://github.com/ganakailabs/cloudeval-cli) | [Issues](https://github.com/ganakailabs/cloudeval-cli/issues) | [Releases](https://github.com/ganakailabs/cloudeval-cli/releases)
|
|
19
|
+
|
|
20
|
+
## Install
|
|
4
21
|
|
|
5
22
|
```bash
|
|
6
23
|
npm install -g @ganakailabs/cloudeval-cli
|
|
7
24
|
cloudeval --help
|
|
8
25
|
```
|
|
9
26
|
|
|
10
|
-
The package installs
|
|
27
|
+
The npm package requires Node.js 20 or newer and installs these command aliases:
|
|
11
28
|
|
|
12
29
|
- `cloudeval`
|
|
13
|
-
- `eva`
|
|
14
30
|
- `cloud`
|
|
31
|
+
- `eva`
|
|
32
|
+
|
|
33
|
+
For standalone macOS, Linux, and Windows binaries, use the GitHub releases or
|
|
34
|
+
the shell installer:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
curl -fsSL https://cli.cloudeval.ai/install.sh | bash
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Common Commands
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cloudeval # Terminal UI
|
|
44
|
+
cloudeval login # Browser device login
|
|
45
|
+
cloudeval status # Account, API, and local CLI status
|
|
46
|
+
cloudeval ask "Summarize my cloud risk" --format json
|
|
47
|
+
cloudeval agent "Find cost and architecture risks" --format json
|
|
48
|
+
cloudeval agents list
|
|
49
|
+
cloudeval agents run cost --project <project-id> --format json
|
|
50
|
+
cloudeval projects list
|
|
51
|
+
cloudeval reports list
|
|
52
|
+
cloudeval mcp serve --toolset readonly
|
|
53
|
+
cloudeval capabilities --format json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Uninstall
|
|
57
|
+
|
|
58
|
+
To remove local installer-owned artifacts while keeping CloudEval config,
|
|
59
|
+
sessions, and auth:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cloudeval uninstall --yes
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
To preview cleanup first:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cloudeval uninstall --dry-run
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
To remove local config and session state too:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cloudeval uninstall --yes --remove-config
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If you installed through npm, remove the npm package as the final step:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm uninstall -g @ganakailabs/cloudeval-cli
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## What It Covers
|
|
84
|
+
|
|
85
|
+
- Terminal UI for chat, Agent mode, projects, reports, billing, and settings.
|
|
86
|
+
- Scriptable commands with `json`, `ndjson`, `markdown`, and text output.
|
|
87
|
+
- Agent Profiles: `architecture`, `cost`, `triage`, and `remediation`.
|
|
88
|
+
- MCP tools for Codex, Cursor, Claude, VS Code, and other stdio JSON-RPC hosts.
|
|
89
|
+
- Project graph, report, recipe, rules, and validation workflows.
|
|
90
|
+
- Local opt-in hooks for CLI and Agent Profile events.
|
|
91
|
+
|
|
92
|
+
## Authentication
|
|
93
|
+
|
|
94
|
+
Use `cloudeval login` for local development. For CI or hosted agents, create a
|
|
95
|
+
scoped CloudEval access key in the app or with `cloudeval credentials create`,
|
|
96
|
+
then provide it as `CLOUDEVAL_ACCESS_KEY`.
|
|
15
97
|
|
|
16
|
-
|
|
17
|
-
the shell installer, see the GitHub releases:
|
|
98
|
+
## Documentation
|
|
18
99
|
|
|
19
|
-
<https://
|
|
100
|
+
- CLI overview: <https://docs.cloudeval.ai/reference/cli-overview>
|
|
101
|
+
- Command reference: <https://docs.cloudeval.ai/reference/cli-command-reference>
|
|
102
|
+
- MCP setup: <https://docs.cloudeval.ai/reference/mcp-client-setup>
|
|
103
|
+
- Release smoke tests: <https://github.com/ganakailabs/cloudeval-cli/blob/main/docs/release-smoke-tests.md>
|
|
20
104
|
|
|
21
|
-
|
|
105
|
+
## License And Notices
|
|
22
106
|
|
|
23
|
-
|
|
107
|
+
CloudEval CLI first-party code is provided under the
|
|
108
|
+
[CloudEval CLI License](https://github.com/ganakailabs/cloudeval-cli/blob/main/LICENSE).
|
|
109
|
+
Production third-party package attribution is published in
|
|
110
|
+
[THIRD_PARTY_NOTICES.md](https://github.com/ganakailabs/cloudeval-cli/blob/main/THIRD_PARTY_NOTICES.md),
|
|
111
|
+
and the release SBOM is published as
|
|
112
|
+
[sbom.spdx.json](https://github.com/ganakailabs/cloudeval-cli/blob/main/sbom.spdx.json).
|
|
113
|
+
Installer releases also place these notice files under
|
|
114
|
+
`~/.local/share/cloudeval/licenses`.
|
|
@@ -31,10 +31,10 @@ import {
|
|
|
31
31
|
} from "./chunk-4QIKW5TJ.js";
|
|
32
32
|
import {
|
|
33
33
|
Banner
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-T5TH36K2.js";
|
|
35
35
|
import {
|
|
36
36
|
CLI_VERSION
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-ULQTRACZ.js";
|
|
38
38
|
import {
|
|
39
39
|
raisedButtonStyle,
|
|
40
40
|
terminalTheme
|
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./chunk-4QIKW5TJ.js";
|
|
17
17
|
import {
|
|
18
18
|
CLI_VERSION
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-ULQTRACZ.js";
|
|
20
20
|
|
|
21
21
|
// src/runtime/prepareInk.ts
|
|
22
22
|
import fs from "fs";
|
|
@@ -115,9 +115,9 @@ ensureInkRuntimeEnvironment();
|
|
|
115
115
|
// src/cli.tsx
|
|
116
116
|
import React from "react";
|
|
117
117
|
import { Command } from "commander";
|
|
118
|
-
import { promises as
|
|
119
|
-
import
|
|
120
|
-
import
|
|
118
|
+
import { promises as fs12 } from "fs";
|
|
119
|
+
import os5 from "os";
|
|
120
|
+
import path10 from "path";
|
|
121
121
|
|
|
122
122
|
// src/shellCompletion.ts
|
|
123
123
|
var normalizeCompletionShell = (shell) => {
|
|
@@ -780,6 +780,25 @@ var cliCommands = [
|
|
|
780
780
|
],
|
|
781
781
|
workflows: ["update"]
|
|
782
782
|
},
|
|
783
|
+
{
|
|
784
|
+
name: "uninstall",
|
|
785
|
+
description: "Remove local CloudEval CLI installation artifacts",
|
|
786
|
+
domain: "setup",
|
|
787
|
+
options: [
|
|
788
|
+
"--yes",
|
|
789
|
+
"-y",
|
|
790
|
+
"--dry-run",
|
|
791
|
+
"--keep-config",
|
|
792
|
+
"--remove-config",
|
|
793
|
+
"--format",
|
|
794
|
+
"-f",
|
|
795
|
+
"--output",
|
|
796
|
+
"-o",
|
|
797
|
+
"--profile",
|
|
798
|
+
"--help"
|
|
799
|
+
],
|
|
800
|
+
workflows: ["uninstall"]
|
|
801
|
+
},
|
|
783
802
|
{
|
|
784
803
|
name: "banner",
|
|
785
804
|
description: "Preview the startup banner and terminal capabilities",
|
|
@@ -1371,10 +1390,10 @@ var writeFormattedOutput = async (input) => {
|
|
|
1371
1390
|
process.stdout.write(text);
|
|
1372
1391
|
};
|
|
1373
1392
|
var writePrivateOutputFile = async (output, text) => {
|
|
1374
|
-
const
|
|
1375
|
-
await
|
|
1393
|
+
const fs13 = await import("fs/promises");
|
|
1394
|
+
await fs13.writeFile(output, text, { encoding: "utf8", mode: 384 });
|
|
1376
1395
|
if (process.platform !== "win32") {
|
|
1377
|
-
await
|
|
1396
|
+
await fs13.chmod(output, 384);
|
|
1378
1397
|
}
|
|
1379
1398
|
};
|
|
1380
1399
|
|
|
@@ -1722,8 +1741,8 @@ var writeReport = async (report, options, tuiDefault) => {
|
|
|
1722
1741
|
const textFormat = format === "text" || format === "table" ? "summary" : format;
|
|
1723
1742
|
const text = serializeReportOutput(report, { format: textFormat, mode });
|
|
1724
1743
|
if (options.output) {
|
|
1725
|
-
const
|
|
1726
|
-
await
|
|
1744
|
+
const fs13 = await import("fs/promises");
|
|
1745
|
+
await fs13.writeFile(options.output, text, "utf8");
|
|
1727
1746
|
return;
|
|
1728
1747
|
}
|
|
1729
1748
|
process.stdout.write(text);
|
|
@@ -1758,16 +1777,16 @@ var writeDownloadPayload = async (input) => {
|
|
|
1758
1777
|
);
|
|
1759
1778
|
return [];
|
|
1760
1779
|
}
|
|
1761
|
-
const
|
|
1762
|
-
const
|
|
1763
|
-
await
|
|
1780
|
+
const fs13 = await import("fs/promises");
|
|
1781
|
+
const path11 = await import("path");
|
|
1782
|
+
await fs13.mkdir(path11.dirname(input.output), { recursive: true });
|
|
1764
1783
|
const text = formatOutput({
|
|
1765
1784
|
command: input.command,
|
|
1766
1785
|
data: input.payload,
|
|
1767
1786
|
format: input.format,
|
|
1768
1787
|
frontendUrl: input.frontendUrl
|
|
1769
1788
|
});
|
|
1770
|
-
await
|
|
1789
|
+
await fs13.writeFile(input.output, text, "utf8");
|
|
1771
1790
|
return [input.output];
|
|
1772
1791
|
};
|
|
1773
1792
|
var resolveMachineFormat = (requested) => {
|
|
@@ -1916,14 +1935,14 @@ var registerReportsCommand = (program2, deps) => {
|
|
|
1916
1935
|
);
|
|
1917
1936
|
const data = reportTypes.length === 1 ? payload[reportTypes[0] === "architecture" ? "waf" : reportTypes[0]] : payload;
|
|
1918
1937
|
if (options.output && reportTypes.length > 1) {
|
|
1919
|
-
const
|
|
1920
|
-
const
|
|
1921
|
-
const stat = await
|
|
1922
|
-
if (stat?.isDirectory() || !
|
|
1923
|
-
await
|
|
1938
|
+
const fs13 = await import("fs/promises");
|
|
1939
|
+
const path11 = await import("path");
|
|
1940
|
+
const stat = await fs13.stat(options.output).catch(() => void 0);
|
|
1941
|
+
if (stat?.isDirectory() || !path11.extname(options.output)) {
|
|
1942
|
+
await fs13.mkdir(options.output, { recursive: true });
|
|
1924
1943
|
const files = [];
|
|
1925
1944
|
for (const [key, value] of Object.entries(payload)) {
|
|
1926
|
-
const file =
|
|
1945
|
+
const file = path11.join(options.output, `${projectId}-${key}-report.json`);
|
|
1927
1946
|
files.push(
|
|
1928
1947
|
...await writeDownloadPayload({
|
|
1929
1948
|
command: "reports download",
|
|
@@ -4668,12 +4687,12 @@ var responseErrorMessage = async (response) => {
|
|
|
4668
4687
|
var fetchCloudEvalJson = async ({
|
|
4669
4688
|
baseUrl,
|
|
4670
4689
|
authToken,
|
|
4671
|
-
path:
|
|
4690
|
+
path: path11,
|
|
4672
4691
|
method = "GET",
|
|
4673
4692
|
query = {},
|
|
4674
4693
|
body
|
|
4675
4694
|
}) => {
|
|
4676
|
-
const url = new URL(`${normalizeApiBase(baseUrl)}${
|
|
4695
|
+
const url = new URL(`${normalizeApiBase(baseUrl)}${path11}`);
|
|
4677
4696
|
for (const [key, value] of Object.entries(query)) {
|
|
4678
4697
|
if (value !== void 0 && value !== null && value !== "") {
|
|
4679
4698
|
url.searchParams.set(key, String(value));
|
|
@@ -5264,8 +5283,8 @@ var writeConnectionsListOutput = async ({
|
|
|
5264
5283
|
if (format === "text") {
|
|
5265
5284
|
const text = renderConnectionsListText(data);
|
|
5266
5285
|
if (options.output) {
|
|
5267
|
-
const
|
|
5268
|
-
await
|
|
5286
|
+
const fs13 = await import("fs/promises");
|
|
5287
|
+
await fs13.writeFile(options.output, text, "utf8");
|
|
5269
5288
|
return;
|
|
5270
5289
|
}
|
|
5271
5290
|
process.stdout.write(text);
|
|
@@ -5599,8 +5618,8 @@ var write = async (command, data, options, frontendUrl) => {
|
|
|
5599
5618
|
const text = renderBillingText(command, data);
|
|
5600
5619
|
if (text) {
|
|
5601
5620
|
if (options.output) {
|
|
5602
|
-
const
|
|
5603
|
-
await
|
|
5621
|
+
const fs13 = await import("fs/promises");
|
|
5622
|
+
await fs13.writeFile(options.output, text, "utf8");
|
|
5604
5623
|
return;
|
|
5605
5624
|
}
|
|
5606
5625
|
process.stdout.write(text);
|
|
@@ -11450,10 +11469,10 @@ var registerConfigCommand = (program2) => {
|
|
|
11450
11469
|
const profile = resolveProfile(options, command);
|
|
11451
11470
|
const current = await loadCliConfig(profile);
|
|
11452
11471
|
const next = writeCliConfigValue(current, key, value);
|
|
11453
|
-
const
|
|
11472
|
+
const path11 = await saveCliConfig(next, profile);
|
|
11454
11473
|
await writeFormattedOutput({
|
|
11455
11474
|
command: "config set",
|
|
11456
|
-
data: { profile, path:
|
|
11475
|
+
data: { profile, path: path11, config: next },
|
|
11457
11476
|
format: options.format,
|
|
11458
11477
|
output: options.output
|
|
11459
11478
|
});
|
|
@@ -11464,10 +11483,10 @@ var registerConfigCommand = (program2) => {
|
|
|
11464
11483
|
const profile = resolveProfile(options, command);
|
|
11465
11484
|
const current = await loadCliConfig(profile);
|
|
11466
11485
|
const next = unsetCliConfigValue(current, key);
|
|
11467
|
-
const
|
|
11486
|
+
const path11 = await saveCliConfig(next, profile);
|
|
11468
11487
|
await writeFormattedOutput({
|
|
11469
11488
|
command: "config unset",
|
|
11470
|
-
data: { profile, path:
|
|
11489
|
+
data: { profile, path: path11, config: next },
|
|
11471
11490
|
format: options.format,
|
|
11472
11491
|
output: options.output
|
|
11473
11492
|
});
|
|
@@ -11764,8 +11783,8 @@ var writeModelsListOutput = async (input) => {
|
|
|
11764
11783
|
defaultModel: input.defaultModel
|
|
11765
11784
|
});
|
|
11766
11785
|
if (input.options.output) {
|
|
11767
|
-
const
|
|
11768
|
-
await
|
|
11786
|
+
const fs13 = await import("fs/promises");
|
|
11787
|
+
await fs13.writeFile(input.options.output, text, "utf8");
|
|
11769
11788
|
return;
|
|
11770
11789
|
}
|
|
11771
11790
|
process.stdout.write(text);
|
|
@@ -11831,10 +11850,10 @@ var registerModelsCommand = (program2, deps) => {
|
|
|
11831
11850
|
const profile = options.profile || getActiveConfigProfile(command);
|
|
11832
11851
|
const config = await loadCliConfig(profile);
|
|
11833
11852
|
const next = { ...config, model };
|
|
11834
|
-
const
|
|
11853
|
+
const path11 = await saveCliConfig(next, profile);
|
|
11835
11854
|
await writeFormattedOutput({
|
|
11836
11855
|
command: "models default set",
|
|
11837
|
-
data: { profile, path:
|
|
11856
|
+
data: { profile, path: path11, model },
|
|
11838
11857
|
format: options.format,
|
|
11839
11858
|
output: options.output
|
|
11840
11859
|
});
|
|
@@ -11877,8 +11896,8 @@ var writeSessionTableOutput = async (command, data, options) => {
|
|
|
11877
11896
|
if (format === "text") {
|
|
11878
11897
|
const text = renderSessionsTable(data);
|
|
11879
11898
|
if (options.output) {
|
|
11880
|
-
const
|
|
11881
|
-
await
|
|
11899
|
+
const fs13 = await import("fs/promises");
|
|
11900
|
+
await fs13.writeFile(options.output, text, "utf8");
|
|
11882
11901
|
return;
|
|
11883
11902
|
}
|
|
11884
11903
|
process.stdout.write(text);
|
|
@@ -12050,12 +12069,12 @@ var registerSetupCommand = (program2, defaultBaseUrl = CLOUD_BASE_URL) => {
|
|
|
12050
12069
|
rl.close();
|
|
12051
12070
|
}
|
|
12052
12071
|
}
|
|
12053
|
-
const
|
|
12072
|
+
const path11 = await saveCliConfig(next, profile);
|
|
12054
12073
|
await writeFormattedOutput({
|
|
12055
12074
|
command: "setup",
|
|
12056
12075
|
data: {
|
|
12057
12076
|
profile,
|
|
12058
|
-
path:
|
|
12077
|
+
path: path11,
|
|
12059
12078
|
config: next,
|
|
12060
12079
|
nextSteps: [
|
|
12061
12080
|
"Run `cloudeval auth status` to inspect authentication.",
|
|
@@ -12380,6 +12399,7 @@ var handleUpdateCommand = async (options, deps = {}) => {
|
|
|
12380
12399
|
};
|
|
12381
12400
|
var suppressedNudgeCommands = /* @__PURE__ */ new Set([
|
|
12382
12401
|
"update",
|
|
12402
|
+
"uninstall",
|
|
12383
12403
|
"completion",
|
|
12384
12404
|
"help",
|
|
12385
12405
|
"capabilities",
|
|
@@ -12470,8 +12490,274 @@ var registerUpdateCommand = (program2) => {
|
|
|
12470
12490
|
});
|
|
12471
12491
|
};
|
|
12472
12492
|
|
|
12473
|
-
// src/
|
|
12493
|
+
// src/uninstallCommand.ts
|
|
12494
|
+
import fs11 from "fs/promises";
|
|
12495
|
+
import os4 from "os";
|
|
12496
|
+
import path9 from "path";
|
|
12474
12497
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
12498
|
+
var pathExists = async (candidate) => {
|
|
12499
|
+
try {
|
|
12500
|
+
await fs11.lstat(candidate);
|
|
12501
|
+
return true;
|
|
12502
|
+
} catch (error) {
|
|
12503
|
+
if (error?.code === "ENOENT") {
|
|
12504
|
+
return false;
|
|
12505
|
+
}
|
|
12506
|
+
throw error;
|
|
12507
|
+
}
|
|
12508
|
+
};
|
|
12509
|
+
var installerBinDir = (home) => path9.join(home, ".local", "bin");
|
|
12510
|
+
var completionPaths = (home) => [
|
|
12511
|
+
path9.join(home, ".local", "share", "bash-completion", "completions", "cloudeval"),
|
|
12512
|
+
path9.join(home, ".zsh", "completions", "_cloudeval"),
|
|
12513
|
+
path9.join(home, ".config", "fish", "completions", "cloudeval.fish"),
|
|
12514
|
+
path9.join(home, ".config", "powershell", "cloudeval-completion.ps1")
|
|
12515
|
+
];
|
|
12516
|
+
var installerArtifactTargets = (home, platform) => {
|
|
12517
|
+
const binDir = installerBinDir(home);
|
|
12518
|
+
const executableName = platform === "win32" ? "cloudeval.exe" : "cloudeval";
|
|
12519
|
+
const targets = [
|
|
12520
|
+
{
|
|
12521
|
+
label: "cloudeval binary",
|
|
12522
|
+
path: path9.join(binDir, executableName),
|
|
12523
|
+
kind: "file",
|
|
12524
|
+
status: "missing"
|
|
12525
|
+
},
|
|
12526
|
+
{
|
|
12527
|
+
label: "cloudeval binary",
|
|
12528
|
+
path: path9.join(binDir, "cloudeval"),
|
|
12529
|
+
kind: "file",
|
|
12530
|
+
status: "missing"
|
|
12531
|
+
},
|
|
12532
|
+
{
|
|
12533
|
+
label: "eva alias",
|
|
12534
|
+
path: path9.join(binDir, "eva"),
|
|
12535
|
+
kind: "file",
|
|
12536
|
+
status: "missing"
|
|
12537
|
+
},
|
|
12538
|
+
{
|
|
12539
|
+
label: "cloud alias",
|
|
12540
|
+
path: path9.join(binDir, "cloud"),
|
|
12541
|
+
kind: "file",
|
|
12542
|
+
status: "missing"
|
|
12543
|
+
},
|
|
12544
|
+
{
|
|
12545
|
+
label: "Ink runtime asset",
|
|
12546
|
+
path: path9.join(binDir, "yoga.wasm"),
|
|
12547
|
+
kind: "file",
|
|
12548
|
+
status: "missing"
|
|
12549
|
+
},
|
|
12550
|
+
{
|
|
12551
|
+
label: "license notices",
|
|
12552
|
+
path: path9.join(home, ".local", "share", "cloudeval", "licenses"),
|
|
12553
|
+
kind: "directory",
|
|
12554
|
+
status: "missing"
|
|
12555
|
+
},
|
|
12556
|
+
...completionPaths(home).map((completionPath) => ({
|
|
12557
|
+
label: "shell completion",
|
|
12558
|
+
path: completionPath,
|
|
12559
|
+
kind: "file",
|
|
12560
|
+
status: "missing"
|
|
12561
|
+
}))
|
|
12562
|
+
];
|
|
12563
|
+
return targets.filter(
|
|
12564
|
+
(target, index) => targets.findIndex((candidate) => candidate.path === target.path) === index
|
|
12565
|
+
);
|
|
12566
|
+
};
|
|
12567
|
+
var shellProfilePaths = (home) => [
|
|
12568
|
+
path9.join(home, ".bashrc"),
|
|
12569
|
+
path9.join(home, ".bash_profile"),
|
|
12570
|
+
path9.join(home, ".zshrc"),
|
|
12571
|
+
path9.join(home, ".profile"),
|
|
12572
|
+
path9.join(home, ".config", "fish", "config.fish")
|
|
12573
|
+
];
|
|
12574
|
+
var removeInstallerPathSnippet = (content, binDir) => {
|
|
12575
|
+
const exportLine = `export PATH="${binDir}:$PATH"`;
|
|
12576
|
+
const fishLine = `set -gx PATH "${binDir}" $PATH`;
|
|
12577
|
+
const lines = content.split(/\r?\n/);
|
|
12578
|
+
let changed = false;
|
|
12579
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
12580
|
+
if (lines[index] === "# Cloudeval CLI" && (lines[index + 1] === exportLine || lines[index + 1] === fishLine)) {
|
|
12581
|
+
const removeFrom = index > 0 && lines[index - 1] === "" ? index - 1 : index;
|
|
12582
|
+
lines.splice(removeFrom, index - removeFrom + 2);
|
|
12583
|
+
changed = true;
|
|
12584
|
+
index = Math.max(removeFrom - 1, -1);
|
|
12585
|
+
}
|
|
12586
|
+
}
|
|
12587
|
+
if (!changed) {
|
|
12588
|
+
return void 0;
|
|
12589
|
+
}
|
|
12590
|
+
return lines.join("\n");
|
|
12591
|
+
};
|
|
12592
|
+
var removeTarget = async (target, dryRun) => {
|
|
12593
|
+
if (!await pathExists(target.path)) {
|
|
12594
|
+
return { ...target, status: "missing" };
|
|
12595
|
+
}
|
|
12596
|
+
if (dryRun) {
|
|
12597
|
+
return { ...target, status: "would_remove" };
|
|
12598
|
+
}
|
|
12599
|
+
await fs11.rm(target.path, { recursive: target.kind === "directory", force: true });
|
|
12600
|
+
return { ...target, status: "removed" };
|
|
12601
|
+
};
|
|
12602
|
+
var updateShellProfile = async (profilePath, home, dryRun) => {
|
|
12603
|
+
if (!await pathExists(profilePath)) {
|
|
12604
|
+
return {
|
|
12605
|
+
label: "shell profile PATH entry",
|
|
12606
|
+
path: profilePath,
|
|
12607
|
+
kind: "shell-profile",
|
|
12608
|
+
status: "missing"
|
|
12609
|
+
};
|
|
12610
|
+
}
|
|
12611
|
+
const content = await fs11.readFile(profilePath, "utf8");
|
|
12612
|
+
const updated = removeInstallerPathSnippet(content, installerBinDir(home));
|
|
12613
|
+
if (updated === void 0) {
|
|
12614
|
+
return {
|
|
12615
|
+
label: "shell profile PATH entry",
|
|
12616
|
+
path: profilePath,
|
|
12617
|
+
kind: "shell-profile",
|
|
12618
|
+
status: "missing"
|
|
12619
|
+
};
|
|
12620
|
+
}
|
|
12621
|
+
if (dryRun) {
|
|
12622
|
+
return {
|
|
12623
|
+
label: "shell profile PATH entry",
|
|
12624
|
+
path: profilePath,
|
|
12625
|
+
kind: "shell-profile",
|
|
12626
|
+
status: "would_update"
|
|
12627
|
+
};
|
|
12628
|
+
}
|
|
12629
|
+
await fs11.writeFile(profilePath, updated, "utf8");
|
|
12630
|
+
return {
|
|
12631
|
+
label: "shell profile PATH entry",
|
|
12632
|
+
path: profilePath,
|
|
12633
|
+
kind: "shell-profile",
|
|
12634
|
+
status: "updated"
|
|
12635
|
+
};
|
|
12636
|
+
};
|
|
12637
|
+
var confirmUninstall = async ({
|
|
12638
|
+
input = process.stdin,
|
|
12639
|
+
output = process.stderr
|
|
12640
|
+
}) => {
|
|
12641
|
+
const rl = createInterface3({ input, output });
|
|
12642
|
+
try {
|
|
12643
|
+
const answer = await rl.question(
|
|
12644
|
+
"Remove CloudEval CLI local installation artifacts? Config is kept unless --remove-config is set. [y/N] "
|
|
12645
|
+
);
|
|
12646
|
+
return /^(y|yes)$/i.test(answer.trim());
|
|
12647
|
+
} finally {
|
|
12648
|
+
rl.close();
|
|
12649
|
+
}
|
|
12650
|
+
};
|
|
12651
|
+
var handleUninstallCommand = async (options, deps = {}) => {
|
|
12652
|
+
const home = deps.home ?? os4.homedir();
|
|
12653
|
+
const platform = deps.platform ?? process.platform;
|
|
12654
|
+
const dryRun = Boolean(options.dryRun);
|
|
12655
|
+
const removeConfig = Boolean(options.removeConfig);
|
|
12656
|
+
const input = deps.input ?? process.stdin;
|
|
12657
|
+
const output = deps.output ?? process.stderr;
|
|
12658
|
+
const inputIsTTY = deps.inputIsTTY ?? ("isTTY" in input ? Boolean(input.isTTY) : false);
|
|
12659
|
+
if (!dryRun && !options.yes) {
|
|
12660
|
+
if (!inputIsTTY) {
|
|
12661
|
+
throw new Error(
|
|
12662
|
+
"CloudEval uninstall requires confirmation. Re-run with --yes for non-interactive removal."
|
|
12663
|
+
);
|
|
12664
|
+
}
|
|
12665
|
+
const confirmed = await confirmUninstall({ input, output });
|
|
12666
|
+
if (!confirmed) {
|
|
12667
|
+
throw new Error("CloudEval uninstall cancelled.");
|
|
12668
|
+
}
|
|
12669
|
+
}
|
|
12670
|
+
const actions = [];
|
|
12671
|
+
for (const target of installerArtifactTargets(home, platform)) {
|
|
12672
|
+
actions.push(await removeTarget(target, dryRun));
|
|
12673
|
+
}
|
|
12674
|
+
for (const profilePath of shellProfilePaths(home)) {
|
|
12675
|
+
const action = await updateShellProfile(profilePath, home, dryRun);
|
|
12676
|
+
if (action.status !== "missing") {
|
|
12677
|
+
actions.push(action);
|
|
12678
|
+
}
|
|
12679
|
+
}
|
|
12680
|
+
const configTarget = {
|
|
12681
|
+
label: "config",
|
|
12682
|
+
path: path9.join(home, ".config", "cloudeval"),
|
|
12683
|
+
kind: "directory",
|
|
12684
|
+
status: "kept"
|
|
12685
|
+
};
|
|
12686
|
+
if (removeConfig) {
|
|
12687
|
+
actions.push(await removeTarget(configTarget, dryRun));
|
|
12688
|
+
} else {
|
|
12689
|
+
actions.push(configTarget);
|
|
12690
|
+
}
|
|
12691
|
+
return {
|
|
12692
|
+
dryRun,
|
|
12693
|
+
removeConfig,
|
|
12694
|
+
actions,
|
|
12695
|
+
notes: [
|
|
12696
|
+
"If you installed the npm package globally, finish with `npm uninstall -g @ganakailabs/cloudeval-cli`.",
|
|
12697
|
+
"MCP client configuration is left untouched. Update or remove MCP entries from each client if needed."
|
|
12698
|
+
]
|
|
12699
|
+
};
|
|
12700
|
+
};
|
|
12701
|
+
var formatUninstallResultText = (result) => {
|
|
12702
|
+
const lines = [
|
|
12703
|
+
"CloudEval CLI Uninstall",
|
|
12704
|
+
`Mode: ${result.dryRun ? "dry run" : "applied"}`,
|
|
12705
|
+
`Config: ${result.removeConfig ? "removed when present" : "kept"}`
|
|
12706
|
+
];
|
|
12707
|
+
const changed = result.actions.filter(
|
|
12708
|
+
(action) => ["removed", "updated", "would_remove", "would_update"].includes(action.status)
|
|
12709
|
+
);
|
|
12710
|
+
const kept = result.actions.filter((action) => action.status === "kept");
|
|
12711
|
+
if (changed.length) {
|
|
12712
|
+
lines.push("", result.dryRun ? "Would clean:" : "Cleaned:");
|
|
12713
|
+
for (const action of changed) {
|
|
12714
|
+
lines.push(`- ${action.label}: ${action.path}`);
|
|
12715
|
+
}
|
|
12716
|
+
} else {
|
|
12717
|
+
lines.push("", "Cleaned: nothing found");
|
|
12718
|
+
}
|
|
12719
|
+
if (kept.length) {
|
|
12720
|
+
lines.push("", "Kept:");
|
|
12721
|
+
for (const action of kept) {
|
|
12722
|
+
lines.push(`- ${action.label}: ${action.path}`);
|
|
12723
|
+
}
|
|
12724
|
+
}
|
|
12725
|
+
if (result.notes.length) {
|
|
12726
|
+
lines.push("", "Notes:");
|
|
12727
|
+
for (const note of result.notes) {
|
|
12728
|
+
lines.push(`- ${note}`);
|
|
12729
|
+
}
|
|
12730
|
+
}
|
|
12731
|
+
return `${lines.join("\n")}
|
|
12732
|
+
`;
|
|
12733
|
+
};
|
|
12734
|
+
var registerUninstallCommand = (program2) => {
|
|
12735
|
+
program2.command("uninstall").description("Remove local CloudEval CLI installation artifacts").option("-y, --yes", "Remove without prompting for confirmation", false).option("--dry-run", "Show what would be removed without deleting files", false).option("--keep-config", "Keep ~/.config/cloudeval settings, sessions, and auth (default)", true).option("--remove-config", "Also remove ~/.config/cloudeval settings, sessions, and auth", false).option(
|
|
12736
|
+
"-f, --format <format>",
|
|
12737
|
+
"Output format: text, json, ndjson, markdown",
|
|
12738
|
+
"text"
|
|
12739
|
+
).option("-o, --output <file>", "Output file").action(async (options) => {
|
|
12740
|
+
const result = await handleUninstallCommand(options);
|
|
12741
|
+
if (options.format === "text" || !options.format) {
|
|
12742
|
+
const text = formatUninstallResultText(result);
|
|
12743
|
+
if (options.output) {
|
|
12744
|
+
await fs11.writeFile(options.output, text, "utf8");
|
|
12745
|
+
return;
|
|
12746
|
+
}
|
|
12747
|
+
process.stdout.write(text);
|
|
12748
|
+
return;
|
|
12749
|
+
}
|
|
12750
|
+
await writeFormattedOutput({
|
|
12751
|
+
command: "uninstall",
|
|
12752
|
+
data: result,
|
|
12753
|
+
format: options.format,
|
|
12754
|
+
output: options.output
|
|
12755
|
+
});
|
|
12756
|
+
});
|
|
12757
|
+
};
|
|
12758
|
+
|
|
12759
|
+
// src/hitlPrompt.ts
|
|
12760
|
+
import { createInterface as createInterface4 } from "readline/promises";
|
|
12475
12761
|
var HITL_REQUIRED_EXIT_CODE = 6;
|
|
12476
12762
|
var recommendedOption = (question) => question.options?.find((option) => option.id === question.recommended_option_id) ?? question.options?.find((option) => option.recommended) ?? question.options?.[0];
|
|
12477
12763
|
var optionLines = (question) => (question.options ?? []).map((option, index) => {
|
|
@@ -12540,7 +12826,7 @@ var answerHitlQuestions = async (questions, ask) => {
|
|
|
12540
12826
|
return responses;
|
|
12541
12827
|
};
|
|
12542
12828
|
var promptForHitlResponses = async (questions, input = process.stdin, output = process.stderr) => {
|
|
12543
|
-
const rl =
|
|
12829
|
+
const rl = createInterface4({ input, output });
|
|
12544
12830
|
try {
|
|
12545
12831
|
return await answerHitlQuestions(questions, (prompt2) => rl.question(prompt2));
|
|
12546
12832
|
} finally {
|
|
@@ -12598,24 +12884,24 @@ var assertNoLegacyApiKeyUsage = () => {
|
|
|
12598
12884
|
};
|
|
12599
12885
|
assertNoLegacyApiKeyUsage();
|
|
12600
12886
|
var completionScriptPath = (shell) => {
|
|
12601
|
-
const home =
|
|
12887
|
+
const home = os5.homedir();
|
|
12602
12888
|
switch (shell) {
|
|
12603
12889
|
case "bash":
|
|
12604
|
-
return
|
|
12890
|
+
return path10.join(home, ".local", "share", "bash-completion", "completions", "cloudeval");
|
|
12605
12891
|
case "zsh":
|
|
12606
|
-
return
|
|
12892
|
+
return path10.join(home, ".zsh", "completions", "_cloudeval");
|
|
12607
12893
|
case "fish":
|
|
12608
|
-
return
|
|
12894
|
+
return path10.join(home, ".config", "fish", "completions", "cloudeval.fish");
|
|
12609
12895
|
case "powershell":
|
|
12610
|
-
return
|
|
12896
|
+
return path10.join(home, ".config", "powershell", "cloudeval-completion.ps1");
|
|
12611
12897
|
}
|
|
12612
12898
|
};
|
|
12613
12899
|
var ZSH_FPATH_MARKER = "CloudEval CLI completions";
|
|
12614
12900
|
var ensureZshCompletionFpath = async () => {
|
|
12615
|
-
const zshrc =
|
|
12901
|
+
const zshrc = path10.join(os5.homedir(), ".zshrc");
|
|
12616
12902
|
let existing = "";
|
|
12617
12903
|
try {
|
|
12618
|
-
existing = await
|
|
12904
|
+
existing = await fs12.readFile(zshrc, "utf8");
|
|
12619
12905
|
} catch {
|
|
12620
12906
|
existing = "";
|
|
12621
12907
|
}
|
|
@@ -12626,12 +12912,12 @@ var ensureZshCompletionFpath = async () => {
|
|
|
12626
12912
|
# ${ZSH_FPATH_MARKER}
|
|
12627
12913
|
fpath=("$HOME/.zsh/completions" $fpath)
|
|
12628
12914
|
`;
|
|
12629
|
-
await
|
|
12915
|
+
await fs12.appendFile(zshrc, snippet, "utf8");
|
|
12630
12916
|
};
|
|
12631
12917
|
var installCompletionScript = async (shell, binaryName) => {
|
|
12632
12918
|
const scriptPath = completionScriptPath(shell);
|
|
12633
|
-
await
|
|
12634
|
-
await
|
|
12919
|
+
await fs12.mkdir(path10.dirname(scriptPath), { recursive: true });
|
|
12920
|
+
await fs12.writeFile(scriptPath, buildCompletionScript(shell, binaryName), "utf8");
|
|
12635
12921
|
if (shell === "zsh") {
|
|
12636
12922
|
await ensureZshCompletionFpath();
|
|
12637
12923
|
}
|
|
@@ -12639,7 +12925,7 @@ var installCompletionScript = async (shell, binaryName) => {
|
|
|
12639
12925
|
};
|
|
12640
12926
|
var uninstallCompletionScript = async (shell) => {
|
|
12641
12927
|
const scriptPath = completionScriptPath(shell);
|
|
12642
|
-
await
|
|
12928
|
+
await fs12.rm(scriptPath, { force: true });
|
|
12643
12929
|
return scriptPath;
|
|
12644
12930
|
};
|
|
12645
12931
|
var runInteractiveLoginOnboarding = async (baseUrl, token) => {
|
|
@@ -13164,6 +13450,7 @@ registerMcpCommand(program, {
|
|
|
13164
13450
|
resolveBaseUrl
|
|
13165
13451
|
});
|
|
13166
13452
|
registerUpdateCommand(program);
|
|
13453
|
+
registerUninstallCommand(program);
|
|
13167
13454
|
program.command("__complete").description("Internal completion endpoint").argument("[words...]", "Completion words").action((words = []) => {
|
|
13168
13455
|
const candidates = completeCliWords(words);
|
|
13169
13456
|
for (const candidate of candidates) {
|
|
@@ -13222,7 +13509,7 @@ program.command("tui").description("Open the CloudEval Terminal UI").option(
|
|
|
13222
13509
|
const { assertSecureBaseUrl } = await import("./dist-I4IPYCRC.js");
|
|
13223
13510
|
const [{ render }, { App }] = await Promise.all([
|
|
13224
13511
|
import("ink"),
|
|
13225
|
-
import("./App-
|
|
13512
|
+
import("./App-CPX5VUMP.js")
|
|
13226
13513
|
]);
|
|
13227
13514
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
13228
13515
|
assertSecureBaseUrl(baseUrl);
|
|
@@ -13272,7 +13559,7 @@ program.command("chat").description("Start an interactive chat session").option(
|
|
|
13272
13559
|
const { assertSecureBaseUrl } = await import("./dist-I4IPYCRC.js");
|
|
13273
13560
|
const [{ render }, { App }] = await Promise.all([
|
|
13274
13561
|
import("ink"),
|
|
13275
|
-
import("./App-
|
|
13562
|
+
import("./App-CPX5VUMP.js")
|
|
13276
13563
|
]);
|
|
13277
13564
|
const baseUrl = await resolveBaseUrl(options, command);
|
|
13278
13565
|
assertSecureBaseUrl(baseUrl);
|
|
@@ -13378,7 +13665,7 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13378
13665
|
});
|
|
13379
13666
|
}
|
|
13380
13667
|
try {
|
|
13381
|
-
const
|
|
13668
|
+
const fs13 = await import("fs");
|
|
13382
13669
|
const fsPromises = await import("fs/promises");
|
|
13383
13670
|
const { randomUUID: randomUUID5 } = await import("crypto");
|
|
13384
13671
|
const core = await import("./dist-I4IPYCRC.js");
|
|
@@ -13568,11 +13855,11 @@ program.command("ask").alias("agent").description("Ask a single question or run
|
|
|
13568
13855
|
console.error(`[${commandName}] Thread ID: ${threadId}`);
|
|
13569
13856
|
}
|
|
13570
13857
|
if (streamTextOutput && options.output) {
|
|
13571
|
-
fileOutputStream =
|
|
13858
|
+
fileOutputStream = fs13.createWriteStream(options.output, { encoding: "utf-8" });
|
|
13572
13859
|
outputStream = fileOutputStream;
|
|
13573
13860
|
}
|
|
13574
13861
|
if (ndjsonOutput && options.output) {
|
|
13575
|
-
ndjsonOutputStream =
|
|
13862
|
+
ndjsonOutputStream = fs13.createWriteStream(options.output, { encoding: "utf-8" });
|
|
13576
13863
|
}
|
|
13577
13864
|
const writeAskDataEvent = (event) => {
|
|
13578
13865
|
const line = `${JSON.stringify(event)}
|
|
@@ -14006,7 +14293,7 @@ Error: ${errorMsg}
|
|
|
14006
14293
|
program.command("banner").description("Preview the startup banner and terminal capabilities").action(async () => {
|
|
14007
14294
|
const { render } = await import("ink");
|
|
14008
14295
|
const BannerPreview = React.lazy(async () => ({
|
|
14009
|
-
default: (await import("./Banner-
|
|
14296
|
+
default: (await import("./Banner-RTNNHPNK.js")).Banner
|
|
14010
14297
|
}));
|
|
14011
14298
|
render(
|
|
14012
14299
|
/* @__PURE__ */ jsx(React.Suspense, { fallback: null, children: /* @__PURE__ */ jsx(BannerPreview, { disable: false }) })
|
package/package.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ganakailabs/cloudeval-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "CloudEval
|
|
6
|
+
"description": "CloudEval CLI for cloud architecture, cost, report, automation, and MCP workflows.",
|
|
7
|
+
"author": "Ganak AI Labs (https://cloudeval.ai)",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"cloudeval",
|
|
10
|
+
"cloud",
|
|
11
|
+
"azure",
|
|
12
|
+
"cli",
|
|
13
|
+
"mcp",
|
|
14
|
+
"agents",
|
|
15
|
+
"automation",
|
|
16
|
+
"iac",
|
|
17
|
+
"arm-template",
|
|
18
|
+
"well-architected",
|
|
19
|
+
"cost",
|
|
20
|
+
"architecture",
|
|
21
|
+
"devops"
|
|
22
|
+
],
|
|
7
23
|
"homepage": "https://docs.cloudeval.ai/reference/cli-overview",
|
|
8
24
|
"repository": {
|
|
9
25
|
"type": "git",
|
|
@@ -21,6 +37,9 @@
|
|
|
21
37
|
"cloud": "dist/cli.js",
|
|
22
38
|
"eva": "dist/cli.js"
|
|
23
39
|
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20"
|
|
42
|
+
},
|
|
24
43
|
"files": [
|
|
25
44
|
"dist",
|
|
26
45
|
"README.md",
|
|
@@ -44,7 +63,7 @@
|
|
|
44
63
|
"run": "node dist/cli.js",
|
|
45
64
|
"dev": "tsx src/cli.tsx",
|
|
46
65
|
"lint": "pnpm -C ../shared build && pnpm -C ../core build && tsc --noEmit -p tsconfig.json",
|
|
47
|
-
"test": "pnpm -C ../shared build && pnpm -C ../core build && tsx --test src/askProgress.test.ts src/hitlPrompt.test.ts src/baseUrl.test.ts src/frontendLinks.test.ts src/outputFormatter.test.ts src/localHooks.test.ts src/projectDiagramImage.test.ts src/loginOnboardingMode.test.ts src/runtime/prepareInk.test.ts src/ui/animationPolicy.test.ts src/ui/components/Banner.test.ts src/ui/components/InputBox.test.ts src/ui/components/Transcript.test.ts src/ui/billingSummary.test.ts src/ui/inputSanitizer.test.ts src/ui/inputViewport.test.ts src/ui/keyBindings.test.ts src/ui/layout.test.ts src/ui/scrollBehavior.test.ts src/ui/promptSuggestions.test.ts src/ui/commandCompletion.test.ts src/ui/interactionModel.test.ts src/ui/userDisplayName.test.ts src/ui/workspaceTabs.test.ts src/ui/workspaceDataStore.test.ts src/ui/overviewDashboard.test.ts src/ui/reportsDashboard.test.ts src/completionEngine.test.ts src/shellCompletion.test.ts src/updateCommand.test.ts src/mcpSetupCommand.test.ts src/mcpCommand.test.ts src/sessionsStore.test.ts src/recipes/catalog.test.ts src/reports/reportRender.test.ts src/reports/reportCommand.test.ts",
|
|
66
|
+
"test": "pnpm -C ../shared build && pnpm -C ../core build && tsx --test src/askProgress.test.ts src/hitlPrompt.test.ts src/baseUrl.test.ts src/frontendLinks.test.ts src/outputFormatter.test.ts src/localHooks.test.ts src/projectDiagramImage.test.ts src/loginOnboardingMode.test.ts src/runtime/prepareInk.test.ts src/ui/animationPolicy.test.ts src/ui/components/Banner.test.ts src/ui/components/InputBox.test.ts src/ui/components/Transcript.test.ts src/ui/billingSummary.test.ts src/ui/inputSanitizer.test.ts src/ui/inputViewport.test.ts src/ui/keyBindings.test.ts src/ui/layout.test.ts src/ui/scrollBehavior.test.ts src/ui/promptSuggestions.test.ts src/ui/commandCompletion.test.ts src/ui/interactionModel.test.ts src/ui/userDisplayName.test.ts src/ui/workspaceTabs.test.ts src/ui/workspaceDataStore.test.ts src/ui/overviewDashboard.test.ts src/ui/reportsDashboard.test.ts src/completionEngine.test.ts src/shellCompletion.test.ts src/updateCommand.test.ts src/uninstallCommand.test.ts src/mcpSetupCommand.test.ts src/mcpCommand.test.ts src/sessionsStore.test.ts src/recipes/catalog.test.ts src/reports/reportRender.test.ts src/reports/reportCommand.test.ts",
|
|
48
67
|
"test:cli:noninteractive": "pnpm -C ../shared build && pnpm -C ../core build && tsx --test src/nonInteractiveCli.test.ts",
|
|
49
68
|
"test:cli:noninteractive:packaged": "pnpm build:executable:current && CLOUDEVAL_CLI_BIN=./dist/bin/cloudeval pnpm test:cli:noninteractive",
|
|
50
69
|
"test:cli:noninteractive:live": "pnpm build:executable:current && CLOUDEVAL_CLI_BIN=./dist/bin/cloudeval tsx --test src/liveNonInteractiveCli.test.ts",
|
package/sbom.spdx.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"SPDXID": "SPDXRef-Package-CloudEval-CLI",
|
|
16
16
|
"name": "CloudEval CLI",
|
|
17
|
-
"versionInfo": "0.
|
|
17
|
+
"versionInfo": "0.19.0",
|
|
18
18
|
"downloadLocation": "https://github.com/ganakailabs/cloudeval-cli",
|
|
19
19
|
"filesAnalyzed": false,
|
|
20
20
|
"licenseConcluded": "LicenseRef-CloudEval-CLI",
|