@mintlify/cli 4.0.1123 → 4.0.1125
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/__test__/helpers.test.ts +30 -0
- package/bin/helpers.js +33 -13
- package/bin/score/client.js +16 -1
- package/bin/score/index.js +85 -20
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/helpers.tsx +32 -13
- package/src/score/client.ts +19 -2
- package/src/score/index.tsx +82 -23
- package/src/score/types.ts +16 -2
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LOCAL_LINKED_CLI_VERSION } from '@mintlify/previewing';
|
|
2
|
+
|
|
3
|
+
import { getCliVersion } from '../src/helpers.js';
|
|
4
|
+
|
|
5
|
+
describe('getCliVersion', () => {
|
|
6
|
+
const originalTestMode = process.env.CLI_TEST_MODE;
|
|
7
|
+
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
if (originalTestMode === undefined) {
|
|
10
|
+
delete process.env.CLI_TEST_MODE;
|
|
11
|
+
} else {
|
|
12
|
+
process.env.CLI_TEST_MODE = originalTestMode;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('returns a test marker when CLI_TEST_MODE is enabled', () => {
|
|
17
|
+
process.env.CLI_TEST_MODE = 'true';
|
|
18
|
+
expect(getCliVersion()).toBe('test-cli');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it(
|
|
22
|
+
'returns LOCAL_LINKED_CLI_VERSION when running from the monorepo source ' +
|
|
23
|
+
'(not inside node_modules)',
|
|
24
|
+
() => {
|
|
25
|
+
// Source lives outside node_modules, mirroring `npm link` / `yarn dev`. See #7121.
|
|
26
|
+
delete process.env.CLI_TEST_MODE;
|
|
27
|
+
expect(getCliVersion()).toBe(LOCAL_LINKED_CLI_VERSION);
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
});
|
package/bin/helpers.js
CHANGED
|
@@ -14,13 +14,14 @@ import { addLog, ErrorLog, getClientVersion, SuccessLog, InfoLog, SpinnerLog, re
|
|
|
14
14
|
import { upgradeToDocsConfig, validatePathWithinCwd } from '@mintlify/validation';
|
|
15
15
|
import detect from 'detect-port';
|
|
16
16
|
import fse from 'fs-extra';
|
|
17
|
-
import fs from 'fs/promises';
|
|
18
17
|
import inquirer from 'inquirer';
|
|
19
18
|
import yaml from 'js-yaml';
|
|
20
19
|
import { exec, execSync } from 'node:child_process';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
import fs from 'node:fs/promises';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
21
23
|
import { promisify } from 'node:util';
|
|
22
24
|
import path from 'path';
|
|
23
|
-
import yargs from 'yargs';
|
|
24
25
|
import { shutdownPostHog } from './telemetry/client.js';
|
|
25
26
|
export const CMD_EXEC_PATH = process.cwd();
|
|
26
27
|
export const checkPort = (argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -109,22 +110,41 @@ export const upgradeConfig = () => __awaiter(void 0, void 0, void 0, function* (
|
|
|
109
110
|
addLog(_jsx(ErrorLog, { message: err instanceof Error ? err.message : 'an unknown error occurred' }));
|
|
110
111
|
}
|
|
111
112
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
// Resolve the CLI's own package.json via `import.meta.url` so the version is
|
|
114
|
+
// always the one shipped with this package, regardless of cwd. See #7121.
|
|
115
|
+
const CLI_PACKAGE_JSON_PATH = (() => {
|
|
116
|
+
try {
|
|
117
|
+
return fileURLToPath(new URL('../package.json', import.meta.url));
|
|
118
|
+
}
|
|
119
|
+
catch (_a) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
})();
|
|
123
|
+
const readCliPackageVersion = () => {
|
|
124
|
+
if (!CLI_PACKAGE_JSON_PATH)
|
|
125
|
+
return undefined;
|
|
126
|
+
try {
|
|
127
|
+
const pkg = JSON.parse(readFileSync(CLI_PACKAGE_JSON_PATH, 'utf8'));
|
|
128
|
+
return typeof pkg.version === 'string' ? pkg.version : undefined;
|
|
129
|
+
}
|
|
130
|
+
catch (_a) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
// Outside `node_modules` means `yarn dev` or `npm link`: treat as linked. See #7121.
|
|
135
|
+
const isRunningFromLinkedBuild = () => {
|
|
136
|
+
if (!CLI_PACKAGE_JSON_PATH)
|
|
117
137
|
return false;
|
|
118
|
-
|
|
138
|
+
return !CLI_PACKAGE_JSON_PATH.split(path.sep).includes('node_modules');
|
|
139
|
+
};
|
|
140
|
+
export const getCliVersion = () => {
|
|
119
141
|
if (process.env.CLI_TEST_MODE === 'true') {
|
|
120
142
|
return 'test-cli';
|
|
121
143
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (version === 'unknown') {
|
|
125
|
-
version = LOCAL_LINKED_CLI_VERSION;
|
|
144
|
+
if (isRunningFromLinkedBuild()) {
|
|
145
|
+
return LOCAL_LINKED_CLI_VERSION;
|
|
126
146
|
}
|
|
127
|
-
return
|
|
147
|
+
return readCliPackageVersion();
|
|
128
148
|
};
|
|
129
149
|
export const getVersions = () => {
|
|
130
150
|
const cli = getCliVersion();
|
package/bin/score/client.js
CHANGED
|
@@ -9,13 +9,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { authenticatedFetch } from '../authenticatedFetch.js';
|
|
11
11
|
import { API_URL } from '../constants.js';
|
|
12
|
-
export function
|
|
12
|
+
export function resolveScoreForUrl(url) {
|
|
13
13
|
return __awaiter(this, void 0, void 0, function* () {
|
|
14
14
|
const endpoint = new URL(`${API_URL}/api/cli/score`);
|
|
15
15
|
endpoint.searchParams.set('url', url);
|
|
16
16
|
const res = yield authenticatedFetch(endpoint.toString(), {
|
|
17
17
|
headers: { Accept: 'application/json' },
|
|
18
18
|
});
|
|
19
|
+
if (res.status !== 200 && res.status !== 202) {
|
|
20
|
+
const body = yield res.text().catch(() => '');
|
|
21
|
+
throw new Error(`API error (${res.status}): ${body || res.statusText}`);
|
|
22
|
+
}
|
|
23
|
+
return res.json();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function fetchScoreBySlug(slug) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const endpoint = new URL(`${API_URL}/api/cli/score/${encodeURIComponent(slug)}`);
|
|
29
|
+
const res = yield authenticatedFetch(endpoint.toString(), {
|
|
30
|
+
headers: { Accept: 'application/json' },
|
|
31
|
+
});
|
|
32
|
+
if (res.status === 202)
|
|
33
|
+
return null;
|
|
19
34
|
if (!res.ok) {
|
|
20
35
|
const body = yield res.text().catch(() => '');
|
|
21
36
|
throw new Error(`API error (${res.status}): ${body || res.statusText}`);
|
package/bin/score/index.js
CHANGED
|
@@ -13,7 +13,9 @@ import chalk from 'chalk';
|
|
|
13
13
|
import { Text } from 'ink';
|
|
14
14
|
import { terminate } from '../helpers.js';
|
|
15
15
|
import { trackEvent } from '../telemetry/track.js';
|
|
16
|
-
import {
|
|
16
|
+
import { fetchScoreBySlug, resolveScoreForUrl } from './client.js';
|
|
17
|
+
const POLL_INTERVAL_MS = 3000;
|
|
18
|
+
const POLL_TIMEOUT_MS = 120000;
|
|
17
19
|
function resolveFormat(argv) {
|
|
18
20
|
if (argv.format === 'table' || argv.format === 'plain' || argv.format === 'json')
|
|
19
21
|
return argv.format;
|
|
@@ -49,6 +51,18 @@ function renderPlain(checks, prefix = '') {
|
|
|
49
51
|
}
|
|
50
52
|
return lines;
|
|
51
53
|
}
|
|
54
|
+
function renderTable(score, opts) {
|
|
55
|
+
const scoreColor = score.overallScore >= 70 ? 'green' : score.overallScore >= 40 ? 'yellow' : 'red';
|
|
56
|
+
const header = (opts === null || opts === void 0 ? void 0 : opts.stale)
|
|
57
|
+
? chalk.bold(`\nAgent Readiness Score — ${score.canonicalUrl}`) +
|
|
58
|
+
chalk.dim(` (last run ${new Date(score.computedAt).toLocaleString()})\n`)
|
|
59
|
+
: chalk.bold(`\nAgent Readiness Score — ${score.canonicalUrl}\n`);
|
|
60
|
+
const lines = [header];
|
|
61
|
+
lines.push(` Score: ${chalk[scoreColor].bold(`${score.overallScore}%`)}\n`);
|
|
62
|
+
lines.push(chalk.bold(' Checks'));
|
|
63
|
+
lines.push(...renderChecks(score.checks));
|
|
64
|
+
return lines.join('\n');
|
|
65
|
+
}
|
|
52
66
|
function output(format, text) {
|
|
53
67
|
if (format === 'table') {
|
|
54
68
|
addLog(_jsx(Text, { children: text }));
|
|
@@ -57,37 +71,88 @@ function output(format, text) {
|
|
|
57
71
|
process.stdout.write(text + '\n');
|
|
58
72
|
}
|
|
59
73
|
}
|
|
74
|
+
function sleep(ms) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function pollForScore(slug, afterIso, onAttempt) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
82
|
+
while (Date.now() < deadline) {
|
|
83
|
+
yield sleep(POLL_INTERVAL_MS);
|
|
84
|
+
onAttempt === null || onAttempt === void 0 ? void 0 : onAttempt();
|
|
85
|
+
const score = yield fetchScoreBySlug(slug);
|
|
86
|
+
if (!score)
|
|
87
|
+
continue;
|
|
88
|
+
if (afterIso === null)
|
|
89
|
+
return score;
|
|
90
|
+
if (new Date(score.computedAt).getTime() > new Date(afterIso).getTime())
|
|
91
|
+
return score;
|
|
92
|
+
}
|
|
93
|
+
throw new Error(`Score did not complete within ${POLL_TIMEOUT_MS / 1000}s`);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
60
96
|
export const scoreHandler = (argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
97
|
const format = resolveFormat(argv);
|
|
62
98
|
try {
|
|
63
99
|
if (format === 'table')
|
|
64
|
-
addLog(_jsx(SpinnerLog, { message: "
|
|
65
|
-
const
|
|
100
|
+
addLog(_jsx(SpinnerLog, { message: "Checking agent readiness..." }));
|
|
101
|
+
const resolved = yield resolveScoreForUrl(argv.url);
|
|
102
|
+
let final;
|
|
103
|
+
if (resolved.status === 'ready') {
|
|
104
|
+
const score = yield fetchScoreBySlug(resolved.slug);
|
|
105
|
+
if (format === 'table')
|
|
106
|
+
removeLastLog();
|
|
107
|
+
if (!score)
|
|
108
|
+
throw new Error('Score was unexpectedly unavailable');
|
|
109
|
+
final = score;
|
|
110
|
+
}
|
|
111
|
+
else if (resolved.status === 'stale_refresh_queued') {
|
|
112
|
+
const stale = yield fetchScoreBySlug(resolved.slug);
|
|
113
|
+
if (format === 'table')
|
|
114
|
+
removeLastLog();
|
|
115
|
+
if (!stale)
|
|
116
|
+
throw new Error('Stale score was unexpectedly unavailable');
|
|
117
|
+
if (format === 'table') {
|
|
118
|
+
output('table', renderTable(stale, { stale: true }));
|
|
119
|
+
addLog(_jsx(SpinnerLog, { message: "Refreshing score in the background..." }));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
process.stderr.write('Refreshing score in the background...\n');
|
|
123
|
+
}
|
|
124
|
+
final = yield pollForScore(resolved.slug, stale.computedAt);
|
|
125
|
+
if (format === 'table')
|
|
126
|
+
removeLastLog();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (format === 'table') {
|
|
130
|
+
removeLastLog();
|
|
131
|
+
addLog(_jsx(SpinnerLog, { message: "Queued a new scoring run. Waiting for first result..." }));
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
process.stderr.write('Queued a new scoring run. Waiting for first result...\n');
|
|
135
|
+
}
|
|
136
|
+
final = yield pollForScore(resolved.slug, null);
|
|
137
|
+
if (format === 'table')
|
|
138
|
+
removeLastLog();
|
|
139
|
+
}
|
|
66
140
|
void trackEvent('cli.score.executed', {
|
|
67
141
|
url: argv.url,
|
|
68
|
-
score:
|
|
142
|
+
score: final.overallScore,
|
|
69
143
|
format,
|
|
144
|
+
status: resolved.status,
|
|
70
145
|
});
|
|
71
|
-
if (format === 'table')
|
|
72
|
-
removeLastLog();
|
|
73
146
|
if (format === 'json') {
|
|
74
|
-
output(format, JSON.stringify(
|
|
75
|
-
yield terminate(0);
|
|
76
|
-
return;
|
|
147
|
+
output(format, JSON.stringify(final, null, 2));
|
|
77
148
|
}
|
|
78
|
-
if (format === 'plain') {
|
|
79
|
-
const lines = [`SCORE\t${
|
|
149
|
+
else if (format === 'plain') {
|
|
150
|
+
const lines = [`SCORE\t${final.overallScore}`, ...renderPlain(final.checks)];
|
|
80
151
|
output(format, lines.join('\n'));
|
|
81
|
-
yield terminate(0);
|
|
82
|
-
return;
|
|
83
152
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
lines.push(` Score: ${chalk[scoreColor].bold(`${data.overallScore}%`)}\n`);
|
|
88
|
-
lines.push(chalk.bold(' Checks'));
|
|
89
|
-
lines.push(...renderChecks(data.checks));
|
|
90
|
-
output(format, lines.join('\n'));
|
|
153
|
+
else {
|
|
154
|
+
output(format, renderTable(final));
|
|
155
|
+
}
|
|
91
156
|
yield terminate(0);
|
|
92
157
|
}
|
|
93
158
|
catch (err) {
|