@mintlify/cli 4.0.1765 → 4.0.1767
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__/instructions.test.ts +53 -0
- package/bin/cli.js +27 -0
- package/bin/instructions.js +101 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/bin/welcome.js +1 -0
- package/package.json +4 -4
- package/src/cli.tsx +32 -0
- package/src/instructions.ts +99 -0
- package/src/welcome.ts +1 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchInstructions,
|
|
3
|
+
instructionsUrl,
|
|
4
|
+
INSTRUCTIONS_URL,
|
|
5
|
+
TOPICS,
|
|
6
|
+
} from '../src/instructions.js';
|
|
7
|
+
|
|
8
|
+
const docsMarkdown = [
|
|
9
|
+
'> ## Documentation Index',
|
|
10
|
+
'> Fetch the complete documentation index at: https://www.mintlify.com/docs/llms.txt',
|
|
11
|
+
'',
|
|
12
|
+
'> ## Agent Instructions',
|
|
13
|
+
'> Follow the quickstart.',
|
|
14
|
+
'',
|
|
15
|
+
'# Custom domain',
|
|
16
|
+
'',
|
|
17
|
+
'> Set up a custom domain.',
|
|
18
|
+
'',
|
|
19
|
+
'Body',
|
|
20
|
+
].join('\n');
|
|
21
|
+
|
|
22
|
+
describe('instructions', () => {
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
vi.unstubAllGlobals();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('maps topics to docs page paths', () => {
|
|
28
|
+
expect(instructionsUrl(['publish'])).toBe(`${INSTRUCTIONS_URL}/publish.md`);
|
|
29
|
+
expect(instructionsUrl(['publish', 'domain'])).toBe(`${INSTRUCTIONS_URL}/publish/domain.md`);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('lists only topics that map to distinct pages', () => {
|
|
33
|
+
const urls = TOPICS.map(({ name }) => instructionsUrl(name.split(' ')));
|
|
34
|
+
expect(new Set(urls).size).toBe(TOPICS.length);
|
|
35
|
+
expect(TOPICS.every(({ name }) => name.split(' ').length <= 2)).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('returns the page without the docs site preamble', async () => {
|
|
39
|
+
const fetchMock = vi.fn().mockResolvedValue(new Response(docsMarkdown));
|
|
40
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
41
|
+
|
|
42
|
+
const markdown = await fetchInstructions(['publish', 'domain']);
|
|
43
|
+
|
|
44
|
+
expect(fetchMock).toHaveBeenCalledWith(`${INSTRUCTIONS_URL}/publish/domain.md`);
|
|
45
|
+
expect(markdown).toBe('# Custom domain\n\n> Set up a custom domain.\n\nBody');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('rejects unknown topics', async () => {
|
|
49
|
+
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(new Response('', { status: 404 })));
|
|
50
|
+
|
|
51
|
+
await expect(fetchInstructions(['nope'])).rejects.toThrow();
|
|
52
|
+
});
|
|
53
|
+
});
|
package/bin/cli.js
CHANGED
|
@@ -30,6 +30,7 @@ import { formatDeployment, prepareAgentDeployment } from './deploy.js';
|
|
|
30
30
|
import { formatHandler } from './format.js';
|
|
31
31
|
import { checkPort, checkNodeVersion, autoUpgradeIfNeeded, getVersions, isAI, suppressConsoleWarnings, terminate, } from './helpers.js';
|
|
32
32
|
import { init } from './init.js';
|
|
33
|
+
import { fetchInstructions, formatTopics } from './instructions.js';
|
|
33
34
|
import { getAccessToken } from './keyring.js';
|
|
34
35
|
import { login } from './login.js';
|
|
35
36
|
import { logout } from './logout.js';
|
|
@@ -471,6 +472,32 @@ export const cli = ({ packageName = 'mint' }) => {
|
|
|
471
472
|
})
|
|
472
473
|
.example('mint broken-links --files introduction.mdx', 'Check a specific page')
|
|
473
474
|
.example('mint broken-links --files "guides/**/*.mdx"', 'Check pages matching a glob'), (argv) => brokenLinksHandler(argv))
|
|
475
|
+
.command('instructions [topics..]', 'Print Mintlify workflow instructions for agents', (yargs) => yargs
|
|
476
|
+
.positional('topics', {
|
|
477
|
+
type: 'string',
|
|
478
|
+
array: true,
|
|
479
|
+
default: [],
|
|
480
|
+
description: 'Topic and optional subtopic',
|
|
481
|
+
})
|
|
482
|
+
.example('mint instructions', 'List topics')
|
|
483
|
+
.example('mint instructions publish domain', 'Custom domain instructions'), (_a) => __awaiter(void 0, [_a], void 0, function* ({ topics }) {
|
|
484
|
+
if (topics.length === 0) {
|
|
485
|
+
process.stdout.write(formatTopics());
|
|
486
|
+
yield terminate(0);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
let markdown;
|
|
490
|
+
try {
|
|
491
|
+
markdown = yield fetchInstructions(topics);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
addLog(_jsx(ErrorLog, { message: error instanceof Error ? error.message : String(error) }));
|
|
495
|
+
yield terminate(1);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
yield new Promise((resolve) => process.stdout.write(markdown, () => resolve()));
|
|
499
|
+
yield terminate(0);
|
|
500
|
+
}))
|
|
474
501
|
.command('status', 'View current authentication status', () => undefined, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
475
502
|
yield status();
|
|
476
503
|
yield terminate(0);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export const INSTRUCTIONS_URL = 'https://www.mintlify.com/docs/mint-instructions';
|
|
11
|
+
export const TOPICS = [
|
|
12
|
+
{
|
|
13
|
+
name: 'overview',
|
|
14
|
+
when: 'Start here: how Mintlify works and facts agents most often get wrong',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'new-site',
|
|
18
|
+
when: 'New docs site, first publish, no account, claim a site, login, no docs.json yet',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'write',
|
|
22
|
+
when: 'Before creating a page or writing more than a sentence or two; changelogs',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'write components',
|
|
26
|
+
when: 'Adding or changing components: callouts, cards, steps, tabs, accordions, fields',
|
|
27
|
+
},
|
|
28
|
+
{ name: 'configure', when: 'Changing docs.json: theme, colors, logo, favicon, required fields' },
|
|
29
|
+
{
|
|
30
|
+
name: 'configure navigation',
|
|
31
|
+
when: 'Changing navigation: groups, tabs, anchors, dropdowns, products, versions, languages',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'configure settings',
|
|
35
|
+
when: 'navbar, footer, banner, SEO, search, integrations, contextual menu, redirects, 404',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'configure customization',
|
|
39
|
+
when: 'Themes, fonts, CSS, JavaScript, or React snippets',
|
|
40
|
+
},
|
|
41
|
+
{ name: 'api-docs', when: 'API documentation: OpenAPI, AsyncAPI, GraphQL, playground' },
|
|
42
|
+
{
|
|
43
|
+
name: 'api-docs sdk',
|
|
44
|
+
when: 'SDK reference pages, x-codeSamples, oneOf/anyOf, multiple responses, hiding endpoints',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'publish',
|
|
48
|
+
when: 'Deploying, "is it live", previews, rollbacks, MCP, llms.txt, skill.md, Markdown export',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'publish domain',
|
|
52
|
+
when: 'Custom domain (mint add-domain), /docs subpath, reverse proxy, CSP',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'publish repo',
|
|
56
|
+
when: 'Monorepo, multi-repo, GitHub/GitLab/Bitbucket, offline export, self-host',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'publish analytics',
|
|
60
|
+
when: 'mint analytics, feedback, search data, analytics integrations',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'publish assistant',
|
|
64
|
+
when: 'AI assistant, widget, Assistant.md, skills, narration, own model',
|
|
65
|
+
},
|
|
66
|
+
{ name: 'access', when: 'Private docs, reader login, user groups, personalization' },
|
|
67
|
+
{ name: 'access team', when: 'Team members, roles, SSO, SCIM, audit logs, session security' },
|
|
68
|
+
{
|
|
69
|
+
name: 'automate',
|
|
70
|
+
when: 'Keep docs in sync with code: agent, Autopilot, automations, Slack, CI',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'migrate',
|
|
74
|
+
when: 'Moving docs from Docusaurus, GitBook, ReadMe, Fern, Document360, Confluence, Markdown',
|
|
75
|
+
},
|
|
76
|
+
{ name: 'troubleshoot', when: 'An error, a failed build or deploy, or the site looks wrong' },
|
|
77
|
+
];
|
|
78
|
+
export const formatTopics = () => {
|
|
79
|
+
const width = Math.max(...TOPICS.map(({ name }) => name.length)) + 2;
|
|
80
|
+
return [
|
|
81
|
+
'Usage: mint instructions <topic> [subtopic]',
|
|
82
|
+
'',
|
|
83
|
+
...TOPICS.map(({ name, when }) => ` ${name.padEnd(width)}${when}`),
|
|
84
|
+
'',
|
|
85
|
+
].join('\n');
|
|
86
|
+
};
|
|
87
|
+
export const instructionsUrl = (topics) => `${INSTRUCTIONS_URL}/${topics.map(encodeURIComponent).join('/')}.md`;
|
|
88
|
+
export const stripDocsPreamble = (markdown) => markdown.replace(/^(?:>.*\n|\s*\n)*/, '');
|
|
89
|
+
export function fetchInstructions(topics) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
const url = instructionsUrl(topics);
|
|
92
|
+
const response = yield fetch(url);
|
|
93
|
+
if (response.status === 404) {
|
|
94
|
+
throw new Error(`no instructions for "${topics.join(' ')}". Run \`mint instructions\` to list topics.`);
|
|
95
|
+
}
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
throw new Error(`failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
98
|
+
}
|
|
99
|
+
return stripDocsPreamble(yield response.text());
|
|
100
|
+
});
|
|
101
|
+
}
|