@solarains/va-cli 0.1.4 → 0.1.6
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 +2 -0
- package/dist/cli/help-copy.js +20 -2
- package/dist/cli/help.js +2 -0
- package/dist/cli/root-command.js +5 -1
- package/dist/cli/run-cli.js +36 -14
- package/dist/commands/intelligence/query-command.js +0 -4
- package/dist/commands/reports/get-command.js +3 -15
- package/dist/commands/reports/list-command.js +1 -2
- package/dist/commands/update/update-command.js +26 -0
- package/dist/commands/version/version-command.js +21 -0
- package/dist/features/daily-reports/daily-reports-output.js +5 -8
- package/dist/features/init/init-copy.js +4 -10
- package/dist/features/init/init-flow.js +4 -12
- package/dist/features/update/preflight.js +235 -32
- package/dist/features/usage/usage-output.js +2 -25
- package/package.json +1 -1
- package/skills/visionalpha-operator/references/daily-reports.md +3 -2
package/README.md
CHANGED
package/dist/cli/help-copy.js
CHANGED
|
@@ -9,11 +9,20 @@ const HELP_COPY = {
|
|
|
9
9
|
globalFlagsHeading: 'Global flags:',
|
|
10
10
|
helpFlag: 'Show help',
|
|
11
11
|
debugFlag: 'Enable debug logging',
|
|
12
|
+
versionFlag: 'Show CLI version',
|
|
12
13
|
commandHelp: {
|
|
13
14
|
'': {
|
|
14
|
-
summary: 'VAOne CLI with guided init, auth, assets, usage, daily reports, intelligence queries, and diagnostics.',
|
|
15
|
+
summary: 'VAOne CLI with versioning, self-update, guided init, auth, assets, usage, daily reports, intelligence queries, and diagnostics.',
|
|
15
16
|
usage: 'vaone <command> [subcommand] [options]',
|
|
16
17
|
},
|
|
18
|
+
'version': {
|
|
19
|
+
summary: 'Show the current VAOne CLI version.',
|
|
20
|
+
usage: 'vaone version',
|
|
21
|
+
},
|
|
22
|
+
'update': {
|
|
23
|
+
summary: 'Check for a newer packaged CLI release and sync VA-managed skill packs.',
|
|
24
|
+
usage: 'vaone update',
|
|
25
|
+
},
|
|
17
26
|
'init': {
|
|
18
27
|
summary: 'Install VisionAlpha operator skills with branded onboarding and optional browser login.',
|
|
19
28
|
usage: 'vaone init [.] [--agents codex,claude,openclaw] [--scope project|user] [--lang en|zh-CN] [--skip-login] [--force] [--yes]',
|
|
@@ -50,11 +59,20 @@ const HELP_COPY = {
|
|
|
50
59
|
globalFlagsHeading: '全局参数:',
|
|
51
60
|
helpFlag: '显示帮助',
|
|
52
61
|
debugFlag: '启用调试日志',
|
|
62
|
+
versionFlag: '显示 CLI 版本',
|
|
53
63
|
commandHelp: {
|
|
54
64
|
'': {
|
|
55
|
-
summary: 'VAOne CLI
|
|
65
|
+
summary: 'VAOne CLI,提供版本查看、自更新、引导式 init、认证、资产、usage、日报、intelligence 查询与诊断能力。',
|
|
56
66
|
usage: 'vaone <命令> [子命令] [参数]',
|
|
57
67
|
},
|
|
68
|
+
'version': {
|
|
69
|
+
summary: '显示当前 VAOne CLI 版本。',
|
|
70
|
+
usage: 'vaone version',
|
|
71
|
+
},
|
|
72
|
+
'update': {
|
|
73
|
+
summary: '检查新版 CLI,并同步所有 VA 受管 skill pack。',
|
|
74
|
+
usage: 'vaone update',
|
|
75
|
+
},
|
|
58
76
|
'init': {
|
|
59
77
|
summary: '通过带品牌感的引导流程安装 VisionAlpha operator skills,并可选串联浏览器登录。',
|
|
60
78
|
usage: 'vaone init [.] [--agents codex,claude,openclaw] [--scope project|user] [--lang en|zh-CN] [--skip-login] [--force] [--yes]',
|
package/dist/cli/help.js
CHANGED
|
@@ -25,5 +25,7 @@ function renderHelp(command, pathSegments = [], locale = 'en') {
|
|
|
25
25
|
lines.push(copy.globalFlagsHeading);
|
|
26
26
|
lines.push(` --help, -h ${copy.helpFlag}`);
|
|
27
27
|
lines.push(` --debug ${copy.debugFlag}`);
|
|
28
|
+
lines.push(` --version ${copy.versionFlag}`);
|
|
29
|
+
lines.push(` -V, -v ${copy.versionFlag}`);
|
|
28
30
|
return lines.join('\n');
|
|
29
31
|
}
|
package/dist/cli/root-command.js
CHANGED
|
@@ -7,13 +7,17 @@ const doctor_command_1 = require("../commands/doctor/doctor-command");
|
|
|
7
7
|
const init_command_1 = require("../commands/init/init-command");
|
|
8
8
|
const intelligence_command_1 = require("../commands/intelligence/intelligence-command");
|
|
9
9
|
const reports_command_1 = require("../commands/reports/reports-command");
|
|
10
|
+
const update_command_1 = require("../commands/update/update-command");
|
|
10
11
|
const uninstall_command_1 = require("../commands/uninstall/uninstall-command");
|
|
11
12
|
const usage_command_1 = require("../commands/usage/usage-command");
|
|
13
|
+
const version_command_1 = require("../commands/version/version-command");
|
|
12
14
|
exports.rootCommand = {
|
|
13
15
|
name: 'vaone',
|
|
14
|
-
summary: 'VAOne CLI with guided init, auth, assets, usage, daily reports, intelligence queries, and diagnostics.',
|
|
16
|
+
summary: 'VAOne CLI with versioning, self-update, guided init, auth, assets, usage, daily reports, intelligence queries, and diagnostics.',
|
|
15
17
|
usage: 'vaone <command> [subcommand] [options]',
|
|
16
18
|
children: [
|
|
19
|
+
version_command_1.versionCommand,
|
|
20
|
+
update_command_1.updateCommand,
|
|
17
21
|
init_command_1.initCommand,
|
|
18
22
|
uninstall_command_1.uninstallCommand,
|
|
19
23
|
auth_command_1.authCommand,
|
package/dist/cli/run-cli.js
CHANGED
|
@@ -11,10 +11,12 @@ const logger_1 = require("../shared/logger");
|
|
|
11
11
|
const help_1 = require("./help");
|
|
12
12
|
const help_copy_1 = require("./help-copy");
|
|
13
13
|
const root_command_1 = require("./root-command");
|
|
14
|
+
const version_command_1 = require("../commands/version/version-command");
|
|
14
15
|
function parseArgv(argv) {
|
|
15
16
|
const tokens = [];
|
|
16
17
|
let debug = false;
|
|
17
18
|
let help = false;
|
|
19
|
+
let version = false;
|
|
18
20
|
for (const token of argv) {
|
|
19
21
|
if (token === '--') {
|
|
20
22
|
continue;
|
|
@@ -27,6 +29,10 @@ function parseArgv(argv) {
|
|
|
27
29
|
help = true;
|
|
28
30
|
continue;
|
|
29
31
|
}
|
|
32
|
+
if (token === '--version' || token === '-V' || token === '-v') {
|
|
33
|
+
version = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
30
36
|
tokens.push(token);
|
|
31
37
|
}
|
|
32
38
|
if (tokens[0] === 'help') {
|
|
@@ -36,6 +42,7 @@ function parseArgv(argv) {
|
|
|
36
42
|
return {
|
|
37
43
|
debug,
|
|
38
44
|
help,
|
|
45
|
+
version,
|
|
39
46
|
tokens,
|
|
40
47
|
};
|
|
41
48
|
}
|
|
@@ -67,12 +74,24 @@ function printUnknownCommand(logger, command, path, token, locale) {
|
|
|
67
74
|
async function runCli(argv, env, deps = {}) {
|
|
68
75
|
const parsedArgv = parseArgv(argv);
|
|
69
76
|
const logger = new logger_1.Logger(parsedArgv.debug || env.VAONE_DEBUG === 'true');
|
|
77
|
+
if (parsedArgv.version) {
|
|
78
|
+
return (0, version_command_1.printCliVersion)(logger);
|
|
79
|
+
}
|
|
80
|
+
const resolvedCommand = resolveCommand(parsedArgv.tokens);
|
|
81
|
+
if (!parsedArgv.help && resolvedCommand.path[0] === 'version') {
|
|
82
|
+
try {
|
|
83
|
+
return await (0, version_command_1.printCliVersion)(logger, resolvedCommand.remainingArgs);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger.error(error instanceof Error ? error.message : 'Unknown CLI failure.');
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
70
90
|
const paths = (0, paths_1.createCliPaths)(env);
|
|
71
91
|
const runtimeConfig = await (0, runtime_config_1.loadRuntimeConfig)(env, paths);
|
|
72
92
|
logger.setDebugMode(parsedArgv.debug || runtimeConfig.debug);
|
|
73
93
|
const tokenStore = new token_store_1.TokenStore(paths.authStateFile);
|
|
74
94
|
const installationStore = new installation_store_1.InstallationStore(paths.installationStateFile);
|
|
75
|
-
const resolvedCommand = resolveCommand(parsedArgv.tokens);
|
|
76
95
|
const unknownToken = resolvedCommand.remainingArgs[0];
|
|
77
96
|
const canTraverseFurther = Boolean(resolvedCommand.command.children?.length && unknownToken);
|
|
78
97
|
const locale = runtimeConfig.locale;
|
|
@@ -96,19 +115,22 @@ async function runCli(argv, env, deps = {}) {
|
|
|
96
115
|
logger.plain((0, help_1.renderHelp)(resolvedCommand.command, resolvedCommand.path, locale));
|
|
97
116
|
return 0;
|
|
98
117
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
if (!((0, preflight_1.shouldSkipManagedSync)(resolvedCommand.path) &&
|
|
119
|
+
(0, preflight_1.shouldSkipCliUpdate)(resolvedCommand.path))) {
|
|
120
|
+
await (0, paths_1.ensureCliDirectories)(paths);
|
|
121
|
+
const preflightExitCode = await (deps.runStartupPreflight ?? preflight_1.runStartupPreflight)({
|
|
122
|
+
argv,
|
|
123
|
+
env,
|
|
124
|
+
logger,
|
|
125
|
+
paths,
|
|
126
|
+
runtimeConfig,
|
|
127
|
+
commandPath: resolvedCommand.path,
|
|
128
|
+
cwd: process.cwd(),
|
|
129
|
+
homeDir: (0, node_os_1.homedir)(),
|
|
130
|
+
});
|
|
131
|
+
if (typeof preflightExitCode === 'number') {
|
|
132
|
+
return preflightExitCode;
|
|
133
|
+
}
|
|
112
134
|
}
|
|
113
135
|
try {
|
|
114
136
|
return await resolvedCommand.command.run(context, resolvedCommand.remainingArgs);
|
|
@@ -95,10 +95,6 @@ exports.intelligenceQueryCommand = {
|
|
|
95
95
|
error.code === 'ASSET_INTELLIGENCE_ACCESS_DENIED') {
|
|
96
96
|
throw new Error('This account does not currently have paid asset-intelligence access.');
|
|
97
97
|
}
|
|
98
|
-
if (error instanceof authenticated_api_client_1.CliApiError &&
|
|
99
|
-
error.code === 'ASSET_INTELLIGENCE_QUOTA_EXCEEDED') {
|
|
100
|
-
throw new Error('The current intelligence query would exceed the daily paid usage quota.');
|
|
101
|
-
}
|
|
102
98
|
if (error instanceof authenticated_api_client_1.CliApiError && error.code === 'INVALID_CURSOR') {
|
|
103
99
|
await stateStore.clear();
|
|
104
100
|
throw new Error('The saved or provided query cursor is no longer valid. Restart the query without `--next`.');
|
|
@@ -13,16 +13,10 @@ function resolveAssetId(positionals, optionAssetId) {
|
|
|
13
13
|
return optionAssetId ?? positionals[0] ?? '';
|
|
14
14
|
}
|
|
15
15
|
function getSelectionMessage(input) {
|
|
16
|
-
if (input.previousSelectedReportKey === input.requestedReportKey) {
|
|
17
|
-
return 'This report is already the locked daily selection for the current product day.';
|
|
18
|
-
}
|
|
19
|
-
if (!input.previousSelectedReportKey && input.detailSelectedToday) {
|
|
20
|
-
return 'This read locked the account daily-report selection for the current product day.';
|
|
21
|
-
}
|
|
22
16
|
if (input.detailSelectedToday) {
|
|
23
|
-
return 'This report is
|
|
17
|
+
return 'This report is included in the current product day usage state. Repeat reads today do not consume another unit.';
|
|
24
18
|
}
|
|
25
|
-
return '
|
|
19
|
+
return 'This report did not consume a new daily-report unit.';
|
|
26
20
|
}
|
|
27
21
|
exports.reportsGetCommand = {
|
|
28
22
|
name: 'get',
|
|
@@ -38,10 +32,7 @@ exports.reportsGetCommand = {
|
|
|
38
32
|
const usageSummary = await (0, usage_api_client_1.getUsageSummary)(context);
|
|
39
33
|
try {
|
|
40
34
|
const report = await (0, daily_reports_api_client_1.getDailyReportDetail)(context, assetId, { date });
|
|
41
|
-
const requestedReportKey = `${report.assetId}:${report.date}`;
|
|
42
35
|
(0, daily_reports_output_1.renderDailyReportDetail)(context.logger, report, getSelectionMessage({
|
|
43
|
-
previousSelectedReportKey: usageSummary.dailyReport.selectedReportKey,
|
|
44
|
-
requestedReportKey,
|
|
45
36
|
detailSelectedToday: report.selectedToday,
|
|
46
37
|
}));
|
|
47
38
|
return 0;
|
|
@@ -49,10 +40,7 @@ exports.reportsGetCommand = {
|
|
|
49
40
|
catch (error) {
|
|
50
41
|
if (error instanceof authenticated_api_client_1.CliApiError &&
|
|
51
42
|
error.code === 'DAILY_REPORT_SELECTION_LIMIT_REACHED') {
|
|
52
|
-
|
|
53
|
-
throw new Error(selectedReportKey
|
|
54
|
-
? `Daily report selection is already locked for ${selectedReportKey}. Free accounts can only keep one report selection per product day.`
|
|
55
|
-
: 'Daily report selection is already locked for the current product day.');
|
|
43
|
+
throw new Error(`Daily report limit reached for the current product day. Remaining quota: ${usageSummary.dailyReport.remainingToday ?? 0}.`);
|
|
56
44
|
}
|
|
57
45
|
if (error instanceof authenticated_api_client_1.CliApiError &&
|
|
58
46
|
error.code === 'DAILY_REPORT_NOT_FOUND') {
|
|
@@ -7,7 +7,7 @@ const daily_reports_output_1 = require("../../features/daily-reports/daily-repor
|
|
|
7
7
|
const usage_api_client_1 = require("../../features/usage/usage-api-client");
|
|
8
8
|
exports.reportsListCommand = {
|
|
9
9
|
name: 'list',
|
|
10
|
-
summary: 'List normalized daily reports with current
|
|
10
|
+
summary: 'List normalized daily reports with current usage state.',
|
|
11
11
|
usage: 'vaone reports list [--asset-id <id>] [--category <category>] [--date-from <yyyy-mm-dd>] [--date-to <yyyy-mm-dd>] [--limit <n>]',
|
|
12
12
|
async run(context, args) {
|
|
13
13
|
const parsed = (0, argv_1.parseCommandArgs)(args);
|
|
@@ -26,7 +26,6 @@ exports.reportsListCommand = {
|
|
|
26
26
|
]);
|
|
27
27
|
(0, daily_reports_output_1.renderDailyReportList)(context.logger, reports, {
|
|
28
28
|
statusLabel: usageSummary.dailyReport.statusLabel,
|
|
29
|
-
selectedReportKey: usageSummary.dailyReport.selectedReportKey,
|
|
30
29
|
});
|
|
31
30
|
return 0;
|
|
32
31
|
},
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateCommand = void 0;
|
|
4
|
+
const node_os_1 = require("node:os");
|
|
5
|
+
const preflight_1 = require("../../features/update/preflight");
|
|
6
|
+
const argv_1 = require("../../shared/argv");
|
|
7
|
+
exports.updateCommand = {
|
|
8
|
+
name: 'update',
|
|
9
|
+
summary: 'Check for a newer packaged CLI release and sync VA-managed skill packs.',
|
|
10
|
+
usage: 'vaone update',
|
|
11
|
+
async run(context, args) {
|
|
12
|
+
const parsed = (0, argv_1.parseCommandArgs)(args);
|
|
13
|
+
if (parsed.positionals.length > 0) {
|
|
14
|
+
throw new Error('`vaone update` does not accept positional arguments.');
|
|
15
|
+
}
|
|
16
|
+
return (0, preflight_1.runExplicitUpdate)({
|
|
17
|
+
argv: context.argv,
|
|
18
|
+
env: process.env,
|
|
19
|
+
logger: context.logger,
|
|
20
|
+
paths: context.paths,
|
|
21
|
+
runtimeConfig: context.runtimeConfig,
|
|
22
|
+
cwd: process.cwd(),
|
|
23
|
+
homeDir: (0, node_os_1.homedir)(),
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.versionCommand = void 0;
|
|
4
|
+
exports.printCliVersion = printCliVersion;
|
|
5
|
+
const package_metadata_1 = require("../../features/runtime/package-metadata");
|
|
6
|
+
async function printCliVersion(logger, args = []) {
|
|
7
|
+
if (args.length > 0) {
|
|
8
|
+
throw new Error('`vaone version` does not accept positional arguments.');
|
|
9
|
+
}
|
|
10
|
+
const runtimePackage = await (0, package_metadata_1.resolveRuntimePackageInfo)();
|
|
11
|
+
logger.plain(runtimePackage.version);
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
exports.versionCommand = {
|
|
15
|
+
name: 'version',
|
|
16
|
+
summary: 'Show the current VAOne CLI version.',
|
|
17
|
+
usage: 'vaone version',
|
|
18
|
+
async run(context, args) {
|
|
19
|
+
return printCliVersion(context.logger, args);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -6,12 +6,9 @@ const output_1 = require("../../shared/output");
|
|
|
6
6
|
function formatAssetName(report) {
|
|
7
7
|
return report.assetNameZh || report.assetNameEn || report.assetId;
|
|
8
8
|
}
|
|
9
|
-
function renderDailyReportList(logger, reports,
|
|
10
|
-
(0, output_1.printSection)(logger, 'Daily report
|
|
11
|
-
(0, output_1.printKeyValue)(logger, 'Status',
|
|
12
|
-
if (selectionSummary.selectedReportKey) {
|
|
13
|
-
(0, output_1.printKeyValue)(logger, 'Locked report', selectionSummary.selectedReportKey);
|
|
14
|
-
}
|
|
9
|
+
function renderDailyReportList(logger, reports, usageSummary) {
|
|
10
|
+
(0, output_1.printSection)(logger, 'Daily report usage');
|
|
11
|
+
(0, output_1.printKeyValue)(logger, 'Status', usageSummary.statusLabel);
|
|
15
12
|
(0, output_1.printSection)(logger, 'Available reports');
|
|
16
13
|
if (!reports.length) {
|
|
17
14
|
logger.info('No reports matched the current filters.');
|
|
@@ -28,12 +25,12 @@ function renderDailyReportList(logger, reports, selectionSummary) {
|
|
|
28
25
|
(0, output_1.printList)(logger, [report.summary || 'No summary available.']);
|
|
29
26
|
});
|
|
30
27
|
}
|
|
31
|
-
function renderDailyReportDetail(logger, report,
|
|
28
|
+
function renderDailyReportDetail(logger, report, usageMessage) {
|
|
32
29
|
(0, output_1.printSection)(logger, 'Daily report');
|
|
33
30
|
(0, output_1.printKeyValue)(logger, 'Asset', `${formatAssetName(report)} (${report.assetId})`);
|
|
34
31
|
(0, output_1.printKeyValue)(logger, 'Date', report.date);
|
|
35
32
|
(0, output_1.printKeyValue)(logger, 'Category', report.category || 'unknown');
|
|
36
|
-
(0, output_1.printKeyValue)(logger, '
|
|
33
|
+
(0, output_1.printKeyValue)(logger, 'Usage', usageMessage);
|
|
37
34
|
(0, output_1.printSection)(logger, 'Summary');
|
|
38
35
|
(0, output_1.printList)(logger, [report.summary || 'No summary available.']);
|
|
39
36
|
(0, output_1.printSection)(logger, 'Content');
|
|
@@ -163,11 +163,8 @@ function getInitCopy(locale) {
|
|
|
163
163
|
summaryDailyReport(value) {
|
|
164
164
|
return `日报状态: ${value}`;
|
|
165
165
|
},
|
|
166
|
-
|
|
167
|
-
return
|
|
168
|
-
},
|
|
169
|
-
summaryIntelligence(value) {
|
|
170
|
-
return `情报额度: ${value}`;
|
|
166
|
+
summaryDailyReportUsed(value) {
|
|
167
|
+
return `今日日报已用: ${value}`;
|
|
171
168
|
},
|
|
172
169
|
summaryResetCadence(value) {
|
|
173
170
|
return `重置周期: ${value}`;
|
|
@@ -324,11 +321,8 @@ function getInitCopy(locale) {
|
|
|
324
321
|
summaryDailyReport(value) {
|
|
325
322
|
return `Daily report: ${value}`;
|
|
326
323
|
},
|
|
327
|
-
|
|
328
|
-
return `
|
|
329
|
-
},
|
|
330
|
-
summaryIntelligence(value) {
|
|
331
|
-
return `Intelligence quota: ${value}`;
|
|
324
|
+
summaryDailyReportUsed(value) {
|
|
325
|
+
return `Daily report used today: ${value}`;
|
|
332
326
|
},
|
|
333
327
|
summaryResetCadence(value) {
|
|
334
328
|
return `Reset cadence: ${value}`;
|
|
@@ -155,8 +155,7 @@ function extractUsageSummary(lines, copy) {
|
|
|
155
155
|
continue;
|
|
156
156
|
}
|
|
157
157
|
if (line === 'Plan' ||
|
|
158
|
-
line === 'Daily report'
|
|
159
|
-
line === 'Intelligence quota') {
|
|
158
|
+
line === 'Daily report') {
|
|
160
159
|
section = line;
|
|
161
160
|
continue;
|
|
162
161
|
}
|
|
@@ -173,19 +172,12 @@ function extractUsageSummary(lines, copy) {
|
|
|
173
172
|
}
|
|
174
173
|
if (section === 'Daily report') {
|
|
175
174
|
const status = extractValue([line], 'Status');
|
|
176
|
-
const
|
|
175
|
+
const usedToday = extractValue([line], 'Used today');
|
|
177
176
|
if (status) {
|
|
178
177
|
summary.push(copy.messages.summaryDailyReport(status));
|
|
179
178
|
}
|
|
180
|
-
if (
|
|
181
|
-
summary.push(copy.messages.
|
|
182
|
-
}
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
if (section === 'Intelligence quota') {
|
|
186
|
-
const status = extractValue([line], 'Status');
|
|
187
|
-
if (status) {
|
|
188
|
-
summary.push(copy.messages.summaryIntelligence(status));
|
|
179
|
+
if (usedToday) {
|
|
180
|
+
summary.push(copy.messages.summaryDailyReportUsed(usedToday));
|
|
189
181
|
continue;
|
|
190
182
|
}
|
|
191
183
|
const normalized = line.replace(/^- /, '');
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV = exports.EXPLICIT_UPDATE_REEXEC_ENV = exports.PREFLIGHT_GUARD_ENV = void 0;
|
|
4
|
+
exports.shouldSkipManagedSync = shouldSkipManagedSync;
|
|
5
|
+
exports.shouldSkipCliUpdate = shouldSkipCliUpdate;
|
|
6
|
+
exports.canPromptForUpdate = canPromptForUpdate;
|
|
7
|
+
exports.fetchLatestPublishedVersion = fetchLatestPublishedVersion;
|
|
8
|
+
exports.performSelfUpdate = performSelfUpdate;
|
|
9
|
+
exports.reexecCommand = reexecCommand;
|
|
3
10
|
exports.resolveUpdateAction = resolveUpdateAction;
|
|
11
|
+
exports.runExplicitUpdate = runExplicitUpdate;
|
|
4
12
|
exports.runStartupPreflight = runStartupPreflight;
|
|
5
13
|
const node_child_process_1 = require("node:child_process");
|
|
6
14
|
const paths_1 = require("../../state/paths");
|
|
@@ -11,9 +19,11 @@ const managed_pack_1 = require("../init/managed-pack");
|
|
|
11
19
|
const package_metadata_1 = require("../runtime/package-metadata");
|
|
12
20
|
const version_1 = require("./version");
|
|
13
21
|
const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
14
|
-
|
|
22
|
+
exports.PREFLIGHT_GUARD_ENV = 'VAONE_SKIP_PREFLIGHT';
|
|
23
|
+
exports.EXPLICIT_UPDATE_REEXEC_ENV = 'VAONE_EXPLICIT_UPDATE_REEXEC';
|
|
24
|
+
exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV = 'VAONE_EXPLICIT_UPDATE_TARGET_VERSION';
|
|
15
25
|
const UPDATE_COPY = {
|
|
16
|
-
en: {
|
|
26
|
+
'en': {
|
|
17
27
|
promptTitle(currentVersion, latestVersion) {
|
|
18
28
|
return `A newer VAOne CLI is available (${currentVersion} -> ${latestVersion}).`;
|
|
19
29
|
},
|
|
@@ -57,10 +67,14 @@ function shouldSkipManagedSync(commandPath) {
|
|
|
57
67
|
return (commandPath.length === 0 ||
|
|
58
68
|
commandPath[0] === 'init' ||
|
|
59
69
|
commandPath[0] === 'doctor' ||
|
|
60
|
-
commandPath[0] === 'uninstall'
|
|
70
|
+
commandPath[0] === 'uninstall' ||
|
|
71
|
+
commandPath[0] === 'update' ||
|
|
72
|
+
commandPath[0] === 'version');
|
|
61
73
|
}
|
|
62
74
|
function shouldSkipCliUpdate(commandPath) {
|
|
63
|
-
return commandPath[0] === 'doctor'
|
|
75
|
+
return (commandPath[0] === 'doctor' ||
|
|
76
|
+
commandPath[0] === 'update' ||
|
|
77
|
+
commandPath[0] === 'version');
|
|
64
78
|
}
|
|
65
79
|
function canPromptForUpdate(env) {
|
|
66
80
|
return (process.stdin.isTTY === true &&
|
|
@@ -101,7 +115,7 @@ async function performSelfUpdate(packageName, version) {
|
|
|
101
115
|
failureMessage: result.stderr?.trim() || result.stdout?.trim() || 'npm update failed.',
|
|
102
116
|
};
|
|
103
117
|
}
|
|
104
|
-
async function reexecCommand(argv) {
|
|
118
|
+
async function reexecCommand(argv, extraEnv) {
|
|
105
119
|
if (!process.argv[1]) {
|
|
106
120
|
return null;
|
|
107
121
|
}
|
|
@@ -109,7 +123,8 @@ async function reexecCommand(argv) {
|
|
|
109
123
|
stdio: 'inherit',
|
|
110
124
|
env: {
|
|
111
125
|
...process.env,
|
|
112
|
-
[PREFLIGHT_GUARD_ENV]: '1',
|
|
126
|
+
[exports.PREFLIGHT_GUARD_ENV]: '1',
|
|
127
|
+
...extraEnv,
|
|
113
128
|
},
|
|
114
129
|
});
|
|
115
130
|
if (typeof result.status === 'number') {
|
|
@@ -144,14 +159,17 @@ async function resolveUpdateAction(input) {
|
|
|
144
159
|
],
|
|
145
160
|
})
|
|
146
161
|
.then((choice) => ({ kind: 'choice', choice }), (error) => ({ kind: 'error', error }));
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
resolve
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
const result = input.timeoutMs === null
|
|
163
|
+
? await selectionPromise
|
|
164
|
+
: await Promise.race([
|
|
165
|
+
selectionPromise,
|
|
166
|
+
new Promise((resolve) => {
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
void prompt.close().catch(() => undefined);
|
|
169
|
+
resolve({ kind: 'timeout' });
|
|
170
|
+
}, input.timeoutMs ?? 5_000);
|
|
171
|
+
}),
|
|
172
|
+
]);
|
|
155
173
|
if (result.kind === 'timeout') {
|
|
156
174
|
input.logger.info(copy.timeoutNotice(input.latestVersion));
|
|
157
175
|
return 'update';
|
|
@@ -161,25 +179,211 @@ async function resolveUpdateAction(input) {
|
|
|
161
179
|
}
|
|
162
180
|
return result.choice;
|
|
163
181
|
}
|
|
182
|
+
function createUpdateStateStore(paths) {
|
|
183
|
+
return new update_state_store_1.UpdateStateStore((0, paths_1.resolveUpdateStateFile)(paths));
|
|
184
|
+
}
|
|
185
|
+
function formatManagedPackRefreshSummary(refreshed) {
|
|
186
|
+
return refreshed
|
|
187
|
+
.map((entry) => `${entry.target.displayName} (${entry.scope})`)
|
|
188
|
+
.join(', ');
|
|
189
|
+
}
|
|
190
|
+
async function syncManagedPacksForVersion(input) {
|
|
191
|
+
const refreshed = await (input.syncManagedPacksImpl ?? managed_pack_1.syncManagedPacks)({
|
|
192
|
+
cwd: input.cwd,
|
|
193
|
+
homeDir: input.homeDir,
|
|
194
|
+
currentVersion: input.currentVersion,
|
|
195
|
+
});
|
|
196
|
+
if (refreshed.length > 0) {
|
|
197
|
+
input.logger.info(`Refreshed stale managed skill packs: ${formatManagedPackRefreshSummary(refreshed)}.`);
|
|
198
|
+
}
|
|
199
|
+
return refreshed;
|
|
200
|
+
}
|
|
201
|
+
async function resolvePublishedUpdate(input) {
|
|
202
|
+
const updateStateStore = createUpdateStateStore(input.paths);
|
|
203
|
+
const updateState = (await updateStateStore.read()) ?? {};
|
|
204
|
+
try {
|
|
205
|
+
const latestVersion = await (input.fetchLatestVersionImpl ?? fetchLatestPublishedVersion)(input.packageName);
|
|
206
|
+
return {
|
|
207
|
+
latestVersion,
|
|
208
|
+
updateStateStore,
|
|
209
|
+
updateState,
|
|
210
|
+
nextState: {
|
|
211
|
+
...updateState,
|
|
212
|
+
lastCheckedAt: new Date(input.now()).toISOString(),
|
|
213
|
+
lastKnownLatestVersion: latestVersion,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
await updateStateStore.save({
|
|
219
|
+
...updateState,
|
|
220
|
+
lastCheckedAt: new Date(input.now()).toISOString(),
|
|
221
|
+
lastFailureCode: 'version_check_failed',
|
|
222
|
+
lastFailureMessage: error instanceof Error ? error.message : 'Version check failed.',
|
|
223
|
+
});
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function createExplicitRestartEnv(latestVersion) {
|
|
228
|
+
return {
|
|
229
|
+
[exports.EXPLICIT_UPDATE_REEXEC_ENV]: '1',
|
|
230
|
+
[exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV]: latestVersion,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async function runExplicitUpdate(input, deps = {}) {
|
|
234
|
+
const runtimePackage = (await deps.resolvePackageInfo?.()) ?? (await (0, package_metadata_1.resolveRuntimePackageInfo)());
|
|
235
|
+
if (input.env[exports.EXPLICIT_UPDATE_REEXEC_ENV] === '1') {
|
|
236
|
+
const updatedVersion = input.env[exports.EXPLICIT_UPDATE_TARGET_VERSION_ENV] ?? runtimePackage.version;
|
|
237
|
+
input.logger.info(`VAOne CLI updated to ${updatedVersion}.`);
|
|
238
|
+
try {
|
|
239
|
+
const refreshed = await syncManagedPacksForVersion({
|
|
240
|
+
logger: input.logger,
|
|
241
|
+
cwd: input.cwd,
|
|
242
|
+
homeDir: input.homeDir,
|
|
243
|
+
currentVersion: runtimePackage.version,
|
|
244
|
+
syncManagedPacksImpl: deps.syncManagedPacks,
|
|
245
|
+
});
|
|
246
|
+
if (refreshed.length === 0) {
|
|
247
|
+
input.logger.info('No stale VA-managed skill packs were found.');
|
|
248
|
+
}
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
input.logger.error(`Managed skill-pack sync failed after CLI update: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
253
|
+
return 1;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!runtimePackage.isPackagedInstall) {
|
|
257
|
+
input.logger.error('`vaone update` only works from the packaged npm install. Local repository runs must update dependencies manually.');
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
const now = deps.now ?? Date.now;
|
|
261
|
+
let publishedUpdate;
|
|
262
|
+
try {
|
|
263
|
+
publishedUpdate = await resolvePublishedUpdate({
|
|
264
|
+
now,
|
|
265
|
+
logger: input.logger,
|
|
266
|
+
paths: input.paths,
|
|
267
|
+
packageName: runtimePackage.name,
|
|
268
|
+
fetchLatestVersionImpl: deps.fetchLatestVersion,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
input.logger.error(`CLI update check failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
273
|
+
return 1;
|
|
274
|
+
}
|
|
275
|
+
const { latestVersion, nextState, updateStateStore } = publishedUpdate;
|
|
276
|
+
if ((0, version_1.isVersionNewer)(latestVersion, runtimePackage.version)) {
|
|
277
|
+
const interactive = canPromptForUpdate(input.env);
|
|
278
|
+
const action = interactive
|
|
279
|
+
? await resolveUpdateAction({
|
|
280
|
+
currentVersion: runtimePackage.version,
|
|
281
|
+
latestVersion,
|
|
282
|
+
locale: input.runtimeConfig.locale,
|
|
283
|
+
logger: input.logger,
|
|
284
|
+
promptFactory: deps.promptFactory,
|
|
285
|
+
timeoutMs: null,
|
|
286
|
+
})
|
|
287
|
+
: 'update';
|
|
288
|
+
if (!interactive) {
|
|
289
|
+
input.logger.info(`No interactive terminal detected. Updating VAOne CLI to ${latestVersion}.`);
|
|
290
|
+
}
|
|
291
|
+
if (action === 'defer') {
|
|
292
|
+
await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
|
|
293
|
+
updateDeferredUntilVersion: latestVersion,
|
|
294
|
+
});
|
|
295
|
+
input.runtimeConfig.updateDeferredUntilVersion = latestVersion;
|
|
296
|
+
await updateStateStore.save({
|
|
297
|
+
...nextState,
|
|
298
|
+
lastFailureCode: undefined,
|
|
299
|
+
lastFailureMessage: undefined,
|
|
300
|
+
});
|
|
301
|
+
input.logger.info(`Deferred CLI self-update until a version newer than ${latestVersion} is published.`);
|
|
302
|
+
}
|
|
303
|
+
else if (action === 'skip') {
|
|
304
|
+
await updateStateStore.save({
|
|
305
|
+
...nextState,
|
|
306
|
+
lastFailureCode: undefined,
|
|
307
|
+
lastFailureMessage: undefined,
|
|
308
|
+
});
|
|
309
|
+
input.logger.info('Skipped CLI self-update for this run.');
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
const copy = UPDATE_COPY[input.runtimeConfig.locale];
|
|
313
|
+
input.logger.info(copy.updatingNotice(latestVersion));
|
|
314
|
+
const result = await (deps.performSelfUpdate ?? performSelfUpdate)(runtimePackage.name, latestVersion);
|
|
315
|
+
if (!result.success) {
|
|
316
|
+
await updateStateStore.save({
|
|
317
|
+
...nextState,
|
|
318
|
+
lastAttemptedUpdateAt: new Date(now()).toISOString(),
|
|
319
|
+
lastAttemptedTargetVersion: latestVersion,
|
|
320
|
+
lastFailureCode: result.failureCode,
|
|
321
|
+
lastFailureMessage: result.failureMessage,
|
|
322
|
+
});
|
|
323
|
+
input.logger.error(result.failureMessage ?? 'CLI update failed.');
|
|
324
|
+
return 1;
|
|
325
|
+
}
|
|
326
|
+
await (0, runtime_config_1.saveRuntimeConfig)(input.paths, {
|
|
327
|
+
updateDeferredUntilVersion: undefined,
|
|
328
|
+
});
|
|
329
|
+
input.runtimeConfig.updateDeferredUntilVersion = undefined;
|
|
330
|
+
await updateStateStore.save({
|
|
331
|
+
...nextState,
|
|
332
|
+
lastAttemptedUpdateAt: new Date(now()).toISOString(),
|
|
333
|
+
lastAttemptedTargetVersion: latestVersion,
|
|
334
|
+
lastFailureCode: undefined,
|
|
335
|
+
lastFailureMessage: undefined,
|
|
336
|
+
});
|
|
337
|
+
input.logger.info(copy.restartingNotice);
|
|
338
|
+
const exitCode = await (deps.reexecCommand ?? reexecCommand)(input.argv, createExplicitRestartEnv(latestVersion));
|
|
339
|
+
if (typeof exitCode === 'number') {
|
|
340
|
+
return exitCode;
|
|
341
|
+
}
|
|
342
|
+
input.logger.error('CLI update completed, but restarting `vaone update` did not return an exit code.');
|
|
343
|
+
return 1;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
await updateStateStore.save({
|
|
348
|
+
...nextState,
|
|
349
|
+
lastFailureCode: undefined,
|
|
350
|
+
lastFailureMessage: undefined,
|
|
351
|
+
});
|
|
352
|
+
input.logger.info(`VAOne CLI is already up to date (${runtimePackage.version}).`);
|
|
353
|
+
}
|
|
354
|
+
try {
|
|
355
|
+
const refreshed = await syncManagedPacksForVersion({
|
|
356
|
+
logger: input.logger,
|
|
357
|
+
cwd: input.cwd,
|
|
358
|
+
homeDir: input.homeDir,
|
|
359
|
+
currentVersion: runtimePackage.version,
|
|
360
|
+
syncManagedPacksImpl: deps.syncManagedPacks,
|
|
361
|
+
});
|
|
362
|
+
if (refreshed.length === 0) {
|
|
363
|
+
input.logger.info('No stale VA-managed skill packs were found.');
|
|
364
|
+
}
|
|
365
|
+
return 0;
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
input.logger.error(`Managed skill-pack sync failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
369
|
+
return 1;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
164
372
|
async function runStartupPreflight(input, deps = {}) {
|
|
165
|
-
if (input.env[PREFLIGHT_GUARD_ENV] === '1') {
|
|
373
|
+
if (input.env[exports.PREFLIGHT_GUARD_ENV] === '1') {
|
|
166
374
|
return null;
|
|
167
375
|
}
|
|
168
376
|
const now = deps.now ?? Date.now;
|
|
169
377
|
const runtimePackage = (await deps.resolvePackageInfo?.()) ?? (await (0, package_metadata_1.resolveRuntimePackageInfo)());
|
|
170
378
|
if (!shouldSkipManagedSync(input.commandPath)) {
|
|
171
379
|
try {
|
|
172
|
-
|
|
380
|
+
await syncManagedPacksForVersion({
|
|
381
|
+
logger: input.logger,
|
|
173
382
|
cwd: input.cwd,
|
|
174
383
|
homeDir: input.homeDir,
|
|
175
384
|
currentVersion: runtimePackage.version,
|
|
385
|
+
syncManagedPacksImpl: deps.syncManagedPacks,
|
|
176
386
|
});
|
|
177
|
-
if (refreshed.length > 0) {
|
|
178
|
-
const summary = refreshed
|
|
179
|
-
.map((entry) => `${entry.target.displayName} (${entry.scope})`)
|
|
180
|
-
.join(', ');
|
|
181
|
-
input.logger.info(`Refreshed stale managed skill packs: ${summary}.`);
|
|
182
|
-
}
|
|
183
387
|
}
|
|
184
388
|
catch (error) {
|
|
185
389
|
input.logger.warn(`Managed skill-pack sync failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
@@ -191,7 +395,7 @@ async function runStartupPreflight(input, deps = {}) {
|
|
|
191
395
|
if (!runtimePackage.isPackagedInstall || !canPromptForUpdate(input.env)) {
|
|
192
396
|
return null;
|
|
193
397
|
}
|
|
194
|
-
const updateStateStore =
|
|
398
|
+
const updateStateStore = createUpdateStateStore(input.paths);
|
|
195
399
|
const updateState = (await updateStateStore.read()) ?? {};
|
|
196
400
|
const lastCheckedAt = updateState.lastCheckedAt
|
|
197
401
|
? Date.parse(updateState.lastCheckedAt)
|
|
@@ -202,15 +406,15 @@ async function runStartupPreflight(input, deps = {}) {
|
|
|
202
406
|
}
|
|
203
407
|
let latestVersion;
|
|
204
408
|
try {
|
|
205
|
-
latestVersion = await (
|
|
409
|
+
latestVersion = (await resolvePublishedUpdate({
|
|
410
|
+
now,
|
|
411
|
+
logger: input.logger,
|
|
412
|
+
paths: input.paths,
|
|
413
|
+
packageName: runtimePackage.name,
|
|
414
|
+
fetchLatestVersionImpl: deps.fetchLatestVersion,
|
|
415
|
+
})).latestVersion;
|
|
206
416
|
}
|
|
207
417
|
catch (error) {
|
|
208
|
-
await updateStateStore.save({
|
|
209
|
-
...updateState,
|
|
210
|
-
lastCheckedAt: new Date(now()).toISOString(),
|
|
211
|
-
lastFailureCode: 'version_check_failed',
|
|
212
|
-
lastFailureMessage: error instanceof Error ? error.message : 'Version check failed.',
|
|
213
|
-
});
|
|
214
418
|
input.logger.warn(`CLI update check failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
215
419
|
return null;
|
|
216
420
|
}
|
|
@@ -228,8 +432,7 @@ async function runStartupPreflight(input, deps = {}) {
|
|
|
228
432
|
return null;
|
|
229
433
|
}
|
|
230
434
|
const deferredBoundary = input.runtimeConfig.updateDeferredUntilVersion;
|
|
231
|
-
if (deferredBoundary &&
|
|
232
|
-
!(0, version_1.isVersionNewer)(latestVersion, deferredBoundary)) {
|
|
435
|
+
if (deferredBoundary && !(0, version_1.isVersionNewer)(latestVersion, deferredBoundary)) {
|
|
233
436
|
await updateStateStore.save(nextState);
|
|
234
437
|
return null;
|
|
235
438
|
}
|
|
@@ -2,22 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderUsageSummary = renderUsageSummary;
|
|
4
4
|
const output_1 = require("../../shared/output");
|
|
5
|
-
function formatQuotaLine(label, quota) {
|
|
6
|
-
if (!quota) {
|
|
7
|
-
return `${label}: not enabled`;
|
|
8
|
-
}
|
|
9
|
-
return `${label}: ${quota.used}/${quota.limit} used, ${quota.remaining} remaining`;
|
|
10
|
-
}
|
|
11
|
-
function formatSelectedReportKey(key) {
|
|
12
|
-
if (!key) {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
const [assetId, date] = key.split(':');
|
|
16
|
-
if (!assetId || !date) {
|
|
17
|
-
return key;
|
|
18
|
-
}
|
|
19
|
-
return `${assetId} on ${date}`;
|
|
20
|
-
}
|
|
21
5
|
function renderUsageSummary(logger, summary) {
|
|
22
6
|
(0, output_1.printSection)(logger, 'Plan');
|
|
23
7
|
(0, output_1.printKeyValue)(logger, 'Current plan', summary.plan.name);
|
|
@@ -38,15 +22,8 @@ function renderUsageSummary(logger, summary) {
|
|
|
38
22
|
(0, output_1.printKeyValue)(logger, 'Remaining selections today', summary.dailyReport.remainingToday === null
|
|
39
23
|
? 'not limited'
|
|
40
24
|
: String(summary.dailyReport.remainingToday));
|
|
41
|
-
|
|
42
|
-
if (selectedReport) {
|
|
43
|
-
(0, output_1.printKeyValue)(logger, 'Locked report', selectedReport);
|
|
44
|
-
}
|
|
45
|
-
(0, output_1.printSection)(logger, 'Intelligence quota');
|
|
46
|
-
(0, output_1.printKeyValue)(logger, 'Status', summary.intelligence.statusLabel);
|
|
25
|
+
(0, output_1.printKeyValue)(logger, 'Used today', String(summary.dailyReport.usedToday));
|
|
47
26
|
(0, output_1.printList)(logger, [
|
|
48
|
-
|
|
49
|
-
formatQuotaLine('Rows', summary.intelligence.rows),
|
|
50
|
-
`Reset cadence: ${summary.intelligence.resetCadence} (${summary.intelligence.resetTimezone})`,
|
|
27
|
+
`Reset cadence: ${summary.dailyReport.resetCadence} (${summary.dailyReport.resetTimezone})`,
|
|
51
28
|
]);
|
|
52
29
|
}
|
package/package.json
CHANGED
|
@@ -26,5 +26,6 @@ Use this reference when the user wants a report list, a specific report, or "tod
|
|
|
26
26
|
## Recovery notes
|
|
27
27
|
|
|
28
28
|
- If the CLI says login is required, run `vaone auth login`.
|
|
29
|
-
- If the CLI reports the daily report
|
|
30
|
-
|
|
29
|
+
- If the CLI reports that the daily report limit is reached, explain that free
|
|
30
|
+
accounts can access one unique report per product day and paid accounts can
|
|
31
|
+
access one hundred unique reports per product day.
|