@mintlify/cli 4.0.1109 → 4.0.1110
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/bin/cli.js +13 -0
- package/bin/score/client.js +25 -0
- package/bin/score/index.js +98 -0
- package/bin/score/types.js +1 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/cli.tsx +20 -1
- package/src/score/client.ts +19 -0
- package/src/score/index.tsx +98 -0
- package/src/score/types.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/cli",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1110",
|
|
4
4
|
"description": "The Mintlify CLI",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"vitest": "2.1.9",
|
|
94
94
|
"vitest-mock-process": "1.0.4"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "f976151a777e02bf8190efa6389757169e8b4ef1"
|
|
97
97
|
}
|
package/src/cli.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { render, Text } from 'ink';
|
|
16
16
|
import fs from 'node:fs/promises';
|
|
17
17
|
import path from 'path';
|
|
18
|
-
import yargs from 'yargs';
|
|
18
|
+
import yargs, { type Argv } from 'yargs';
|
|
19
19
|
import { hideBin } from 'yargs/helpers';
|
|
20
20
|
|
|
21
21
|
import { accessibilityCheck } from './accessibilityCheck.js';
|
|
@@ -40,6 +40,7 @@ import { logout } from './logout.js';
|
|
|
40
40
|
import { mdxLinter } from './mdxLinter.js';
|
|
41
41
|
import { createTelemetryMiddleware } from './middlewares/telemetryMiddleware.js';
|
|
42
42
|
import { checkOpenApiFile, getOpenApiFilenamesFromDocsConfig } from './openApiCheck.js';
|
|
43
|
+
import { scoreHandler } from './score/index.js';
|
|
43
44
|
import { status, getCliSubdomains } from './status.js';
|
|
44
45
|
import { trackTelemetryPreferenceChange } from './telemetry/track.js';
|
|
45
46
|
import { update } from './update.js';
|
|
@@ -570,6 +571,24 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
|
|
|
570
571
|
}
|
|
571
572
|
)
|
|
572
573
|
.command('analytics', 'View analytics for your documentation', analyticsBuilder)
|
|
574
|
+
.command(
|
|
575
|
+
'score <url>',
|
|
576
|
+
'Run agent readiness checks on a docs site',
|
|
577
|
+
(yargs: Argv) =>
|
|
578
|
+
yargs
|
|
579
|
+
.positional('url', {
|
|
580
|
+
type: 'string',
|
|
581
|
+
demandOption: true,
|
|
582
|
+
description: 'URL of the docs site to check',
|
|
583
|
+
})
|
|
584
|
+
.option('format', {
|
|
585
|
+
type: 'string',
|
|
586
|
+
choices: ['table', 'plain', 'json'] as const,
|
|
587
|
+
description: 'Output format',
|
|
588
|
+
})
|
|
589
|
+
.example('mint score docs.example.com', 'Run agent readiness checks'),
|
|
590
|
+
scoreHandler
|
|
591
|
+
)
|
|
573
592
|
// Coming soon commands — visible in help, tracked via telemetry to gauge interest.
|
|
574
593
|
.command(
|
|
575
594
|
'ai',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { authenticatedFetch } from '../authenticatedFetch.js';
|
|
2
|
+
import { API_URL } from '../constants.js';
|
|
3
|
+
import type { ScoreResponse } from './types.js';
|
|
4
|
+
|
|
5
|
+
export async function getScore(url: string): Promise<ScoreResponse> {
|
|
6
|
+
const endpoint = new URL(`${API_URL}/api/cli/score`);
|
|
7
|
+
endpoint.searchParams.set('url', url);
|
|
8
|
+
|
|
9
|
+
const res = await authenticatedFetch(endpoint.toString(), {
|
|
10
|
+
headers: { Accept: 'application/json' },
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (!res.ok) {
|
|
14
|
+
const body = await res.text().catch(() => '');
|
|
15
|
+
throw new Error(`API error (${res.status}): ${body || res.statusText}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return res.json() as Promise<ScoreResponse>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { addLog, ErrorLog, SpinnerLog, removeLastLog } from '@mintlify/previewing';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Text } from 'ink';
|
|
4
|
+
|
|
5
|
+
import { terminate } from '../helpers.js';
|
|
6
|
+
import { getScore } from './client.js';
|
|
7
|
+
import type { Check } from './types.js';
|
|
8
|
+
|
|
9
|
+
type OutputFormat = 'table' | 'plain' | 'json';
|
|
10
|
+
|
|
11
|
+
function resolveFormat(argv: { format?: string }): OutputFormat {
|
|
12
|
+
if (argv.format === 'table' || argv.format === 'plain' || argv.format === 'json')
|
|
13
|
+
return argv.format;
|
|
14
|
+
return 'table';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function statusIcon(pass: boolean): string {
|
|
18
|
+
return pass ? chalk.green('✓') : chalk.red('✗');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function formatCheckName(name: string): string {
|
|
22
|
+
return name
|
|
23
|
+
.replace(/([A-Z])/g, ' $1')
|
|
24
|
+
.replace(/^./, (c) => c.toUpperCase())
|
|
25
|
+
.trim();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function renderChecks(checks: Check[], indent = 0): string[] {
|
|
29
|
+
const lines: string[] = [];
|
|
30
|
+
const pad = ' '.repeat(indent + 1);
|
|
31
|
+
for (const check of checks) {
|
|
32
|
+
lines.push(`${pad}${statusIcon(check.pass)} ${formatCheckName(check.name)}`);
|
|
33
|
+
if (check.children && check.children.length > 0) {
|
|
34
|
+
lines.push(...renderChecks(check.children, indent + 1));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return lines;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function renderPlain(checks: Check[], prefix = ''): string[] {
|
|
41
|
+
const lines: string[] = [];
|
|
42
|
+
for (const check of checks) {
|
|
43
|
+
lines.push(`${prefix}${check.pass ? 'PASS' : 'FAIL'}\t${check.name}`);
|
|
44
|
+
if (check.children && check.children.length > 0) {
|
|
45
|
+
lines.push(...renderPlain(check.children, prefix + ' '));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return lines;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function output(format: OutputFormat, text: string) {
|
|
52
|
+
if (format === 'table') {
|
|
53
|
+
addLog(<Text>{text}</Text>);
|
|
54
|
+
} else {
|
|
55
|
+
process.stdout.write(text + '\n');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const scoreHandler = async (argv: { url: string; format?: string }) => {
|
|
60
|
+
const format = resolveFormat(argv);
|
|
61
|
+
try {
|
|
62
|
+
if (format === 'table') addLog(<SpinnerLog message="Running agent readiness checks..." />);
|
|
63
|
+
const data = await getScore(argv.url);
|
|
64
|
+
if (format === 'table') removeLastLog();
|
|
65
|
+
|
|
66
|
+
if (format === 'json') {
|
|
67
|
+
output(format, JSON.stringify(data, null, 2));
|
|
68
|
+
await terminate(0);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (format === 'plain') {
|
|
73
|
+
const lines = [`SCORE\t${data.overallScore}`, ...renderPlain(data.checks)];
|
|
74
|
+
output(format, lines.join('\n'));
|
|
75
|
+
await terminate(0);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const scoreColor =
|
|
80
|
+
data.overallScore >= 70 ? 'green' : data.overallScore >= 40 ? 'yellow' : 'red';
|
|
81
|
+
const lines: string[] = [];
|
|
82
|
+
lines.push(chalk.bold(`\nAgent Readiness Score — ${data.url}\n`));
|
|
83
|
+
lines.push(` Score: ${chalk[scoreColor].bold(`${data.overallScore}%`)}\n`);
|
|
84
|
+
lines.push(chalk.bold(' Checks'));
|
|
85
|
+
lines.push(...renderChecks(data.checks));
|
|
86
|
+
output(format, lines.join('\n'));
|
|
87
|
+
await terminate(0);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
const message = err instanceof Error ? err.message : 'unknown error';
|
|
90
|
+
if (format === 'table') {
|
|
91
|
+
removeLastLog();
|
|
92
|
+
addLog(<ErrorLog message={message} />);
|
|
93
|
+
} else {
|
|
94
|
+
process.stderr.write(`Error: ${message}\n`);
|
|
95
|
+
}
|
|
96
|
+
await terminate(1);
|
|
97
|
+
}
|
|
98
|
+
};
|