@mintlify/cli 4.0.1812 → 4.1.1

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.
Files changed (274) hide show
  1. package/dist/assets/export-scripts/README.classic.md +15 -0
  2. package/dist/assets/export-scripts/README.md +14 -0
  3. package/dist/assets/export-scripts/serve.js +114 -0
  4. package/dist/assets/export-scripts/start-docs.bat +10 -0
  5. package/dist/assets/export-scripts/start-docs.sh +9 -0
  6. package/dist/assets/og/Inter-Bold.ttf +0 -0
  7. package/dist/assets/og/Inter-Medium.ttf +0 -0
  8. package/dist/assets/og/Inter-Regular.ttf +0 -0
  9. package/dist/assets/og/Inter-SemiBold.ttf +0 -0
  10. package/dist/assets/og/PaperMono-Regular.ttf +0 -0
  11. package/dist/assets/og/index_bg.wasm +0 -0
  12. package/dist/assets/openChrome.applescript +94 -0
  13. package/dist/assets/socket.io/socket.io.esm.min.js +7 -0
  14. package/dist/assets/socket.io/socket.io.esm.min.js.map +1 -0
  15. package/dist/assets/socket.io/socket.io.js +4907 -0
  16. package/dist/assets/socket.io/socket.io.js.map +1 -0
  17. package/dist/assets/socket.io/socket.io.min.js +7 -0
  18. package/dist/assets/socket.io/socket.io.min.js.map +1 -0
  19. package/dist/assets/socket.io/socket.io.msgpack.min.js +7 -0
  20. package/dist/assets/socket.io/socket.io.msgpack.min.js.map +1 -0
  21. package/dist/assets/xdg-open +1066 -0
  22. package/dist/assets/yargs-locales/be.json +46 -0
  23. package/dist/assets/yargs-locales/cs.json +51 -0
  24. package/dist/assets/yargs-locales/de.json +46 -0
  25. package/dist/assets/yargs-locales/en.json +55 -0
  26. package/dist/assets/yargs-locales/es.json +46 -0
  27. package/dist/assets/yargs-locales/fi.json +49 -0
  28. package/dist/assets/yargs-locales/fr.json +53 -0
  29. package/dist/assets/yargs-locales/hi.json +49 -0
  30. package/dist/assets/yargs-locales/hu.json +46 -0
  31. package/dist/assets/yargs-locales/id.json +50 -0
  32. package/dist/assets/yargs-locales/it.json +46 -0
  33. package/dist/assets/yargs-locales/ja.json +51 -0
  34. package/dist/assets/yargs-locales/ko.json +49 -0
  35. package/dist/assets/yargs-locales/nb.json +44 -0
  36. package/dist/assets/yargs-locales/nl.json +49 -0
  37. package/dist/assets/yargs-locales/nn.json +44 -0
  38. package/dist/assets/yargs-locales/pirate.json +13 -0
  39. package/dist/assets/yargs-locales/pl.json +49 -0
  40. package/dist/assets/yargs-locales/pt.json +45 -0
  41. package/dist/assets/yargs-locales/pt_BR.json +48 -0
  42. package/dist/assets/yargs-locales/ru.json +51 -0
  43. package/dist/assets/yargs-locales/th.json +46 -0
  44. package/dist/assets/yargs-locales/tr.json +48 -0
  45. package/dist/assets/yargs-locales/uk_UA.json +51 -0
  46. package/dist/assets/yargs-locales/uz.json +52 -0
  47. package/dist/assets/yargs-locales/zh_CN.json +48 -0
  48. package/dist/assets/yargs-locales/zh_TW.json +51 -0
  49. package/dist/converter-d8O3xkdU.js +102 -0
  50. package/dist/devtools-CGNZQKFV.js +24 -0
  51. package/dist/index.js +8 -0
  52. package/dist/rolldown-runtime-CEAe2Uac.js +7 -0
  53. package/dist/schemas-CBsmCNpK.js +372 -0
  54. package/dist/start.js +2310 -0
  55. package/package.json +43 -36
  56. package/.oxlintrc.json +0 -5
  57. package/.prettierignore +0 -2
  58. package/.turbo/turbo-build.log +0 -1
  59. package/CONTRIBUTING.md +0 -45
  60. package/__test__/agent-auth.test.ts +0 -114
  61. package/__test__/agent-claim.test.ts +0 -164
  62. package/__test__/agent-credentials.test.ts +0 -149
  63. package/__test__/agent-deployment.test.ts +0 -106
  64. package/__test__/agent-setup-config.test.ts +0 -324
  65. package/__test__/agent-setup.test.ts +0 -207
  66. package/__test__/agent.test.ts +0 -64
  67. package/__test__/analytics/client.test.ts +0 -180
  68. package/__test__/analytics/dates.test.ts +0 -12
  69. package/__test__/analytics/filters.test.ts +0 -116
  70. package/__test__/analytics/format.test.ts +0 -137
  71. package/__test__/authenticatedFetch.test.ts +0 -182
  72. package/__test__/brokenLinks.test.ts +0 -283
  73. package/__test__/checkPort.test.ts +0 -92
  74. package/__test__/deploy-github-actions.test.ts +0 -202
  75. package/__test__/deploy-github-setup.test.ts +0 -240
  76. package/__test__/deploy-instructions.test.ts +0 -155
  77. package/__test__/deploy.test.ts +0 -202
  78. package/__test__/feedback.test.ts +0 -34
  79. package/__test__/foreignSyntax.test.ts +0 -73
  80. package/__test__/format.test.ts +0 -72
  81. package/__test__/helpers.test.ts +0 -52
  82. package/__test__/init.test.ts +0 -119
  83. package/__test__/instructions.test.ts +0 -53
  84. package/__test__/keyring.test.ts +0 -82
  85. package/__test__/mdxAccessibility.test.ts +0 -81
  86. package/__test__/migrate.test.ts +0 -186
  87. package/__test__/openApiCheck.test.ts +0 -185
  88. package/__test__/pathValidation.test.ts +0 -25
  89. package/__test__/resolveFiles.test.ts +0 -70
  90. package/__test__/sessionId.test.ts +0 -46
  91. package/__test__/signup.test.ts +0 -36
  92. package/__test__/update.test.ts +0 -117
  93. package/__test__/utils.ts +0 -25
  94. package/__test__/validateCommand.test.ts +0 -647
  95. package/__test__/validateEngine.test.ts +0 -245
  96. package/__test__/validateRules.test.ts +0 -1275
  97. package/__test__/welcome.test.ts +0 -15
  98. package/__test__/workflows/client.test.ts +0 -126
  99. package/bin/accessibility.js +0 -111
  100. package/bin/accessibilityCheck.js +0 -82
  101. package/bin/addDomain.js +0 -130
  102. package/bin/agent-auth.js +0 -104
  103. package/bin/agent-claim.js +0 -97
  104. package/bin/agent-credentials.js +0 -124
  105. package/bin/agent-deployment.js +0 -96
  106. package/bin/agent-http.js +0 -45
  107. package/bin/agent-setup-config.js +0 -141
  108. package/bin/agent-setup.js +0 -146
  109. package/bin/agent.js +0 -42
  110. package/bin/analytics/client.js +0 -60
  111. package/bin/analytics/dates.js +0 -6
  112. package/bin/analytics/filters.js +0 -27
  113. package/bin/analytics/format.js +0 -13
  114. package/bin/analytics/index.js +0 -496
  115. package/bin/analytics/output.js +0 -75
  116. package/bin/analytics/types.js +0 -1
  117. package/bin/authenticatedFetch.js +0 -46
  118. package/bin/brokenLinks.js +0 -122
  119. package/bin/callbackServer.js +0 -65
  120. package/bin/cli.js +0 -813
  121. package/bin/comingSoon.js +0 -26
  122. package/bin/config.js +0 -78
  123. package/bin/constants.js +0 -16
  124. package/bin/deploy-base.js +0 -20
  125. package/bin/deploy-github-actions.js +0 -102
  126. package/bin/deploy-github-setup.js +0 -165
  127. package/bin/deploy-instructions.js +0 -71
  128. package/bin/deploy.js +0 -123
  129. package/bin/feedback.js +0 -36
  130. package/bin/format.js +0 -121
  131. package/bin/helpers.js +0 -238
  132. package/bin/idToken.js +0 -14
  133. package/bin/index.js +0 -102
  134. package/bin/init.js +0 -182
  135. package/bin/instructions.js +0 -101
  136. package/bin/keyring.js +0 -78
  137. package/bin/login.js +0 -123
  138. package/bin/logout.js +0 -18
  139. package/bin/mdxAccessibility.js +0 -113
  140. package/bin/mdxLinter.js +0 -55
  141. package/bin/middlewares/subdomainMiddleware.js +0 -28
  142. package/bin/middlewares/telemetryMiddleware.js +0 -61
  143. package/bin/migrate.js +0 -54
  144. package/bin/og.js +0 -145
  145. package/bin/openApiCheck.js +0 -99
  146. package/bin/resolveFiles.js +0 -114
  147. package/bin/score/client.js +0 -40
  148. package/bin/score/index.js +0 -211
  149. package/bin/score/types.js +0 -1
  150. package/bin/signup.js +0 -118
  151. package/bin/start.js +0 -36
  152. package/bin/status.js +0 -106
  153. package/bin/telemetry/client.js +0 -53
  154. package/bin/telemetry/distinctId.js +0 -68
  155. package/bin/telemetry/sessionId.js +0 -36
  156. package/bin/telemetry/track.js +0 -149
  157. package/bin/templates.js +0 -127
  158. package/bin/tokenRefresh.js +0 -50
  159. package/bin/tsconfig.build.tsbuildinfo +0 -1
  160. package/bin/update.js +0 -65
  161. package/bin/validate/command.js +0 -127
  162. package/bin/validate/engine.js +0 -154
  163. package/bin/validate/files.js +0 -163
  164. package/bin/validate/mdx.js +0 -238
  165. package/bin/validate/output.js +0 -44
  166. package/bin/validate/report.js +0 -11
  167. package/bin/validate/rules/build.js +0 -102
  168. package/bin/validate/rules/content/duplicateH1.js +0 -57
  169. package/bin/validate/rules/content/foreignSyntax.js +0 -120
  170. package/bin/validate/rules/content/katex.js +0 -34
  171. package/bin/validate/rules/content/missingSnippet.js +0 -34
  172. package/bin/validate/rules/content/undefinedVariable.js +0 -13
  173. package/bin/validate/rules/content/unknownComponent.js +0 -121
  174. package/bin/validate/rules/content/voidTags.js +0 -38
  175. package/bin/validate/rules/index.js +0 -21
  176. package/bin/validate/rules/openapi.js +0 -50
  177. package/bin/validate/rules/parseError.js +0 -7
  178. package/bin/validate/site.js +0 -57
  179. package/bin/validate/types.js +0 -1
  180. package/bin/vendor/converter.js +0 -30882
  181. package/bin/welcome.js +0 -108
  182. package/bin/workflows/client.js +0 -34
  183. package/bin/workflows/index.js +0 -269
  184. package/bin/workflows/types.js +0 -11
  185. package/scripts/bundle-converter.mjs +0 -26
  186. package/scripts/generate-logo.mjs +0 -79
  187. package/src/accessibility.ts +0 -180
  188. package/src/accessibilityCheck.tsx +0 -150
  189. package/src/addDomain.tsx +0 -206
  190. package/src/agent-auth.ts +0 -119
  191. package/src/agent-claim.ts +0 -124
  192. package/src/agent-credentials.ts +0 -104
  193. package/src/agent-deployment.ts +0 -116
  194. package/src/agent-http.ts +0 -34
  195. package/src/agent-setup-config.ts +0 -144
  196. package/src/agent-setup.ts +0 -165
  197. package/src/agent.ts +0 -56
  198. package/src/analytics/client.ts +0 -153
  199. package/src/analytics/dates.ts +0 -6
  200. package/src/analytics/filters.ts +0 -50
  201. package/src/analytics/format.ts +0 -13
  202. package/src/analytics/index.tsx +0 -599
  203. package/src/analytics/output.ts +0 -99
  204. package/src/analytics/types.ts +0 -145
  205. package/src/authenticatedFetch.ts +0 -42
  206. package/src/brokenLinks.tsx +0 -152
  207. package/src/callbackServer.ts +0 -64
  208. package/src/cli.tsx +0 -1105
  209. package/src/comingSoon.tsx +0 -29
  210. package/src/config.ts +0 -75
  211. package/src/constants.ts +0 -28
  212. package/src/deploy-base.ts +0 -18
  213. package/src/deploy-github-actions.ts +0 -139
  214. package/src/deploy-github-setup.ts +0 -189
  215. package/src/deploy-instructions.ts +0 -76
  216. package/src/deploy.ts +0 -165
  217. package/src/feedback.tsx +0 -31
  218. package/src/format.tsx +0 -82
  219. package/src/helpers.tsx +0 -279
  220. package/src/idToken.ts +0 -17
  221. package/src/index.ts +0 -109
  222. package/src/init.tsx +0 -237
  223. package/src/instructions.ts +0 -99
  224. package/src/keyring.ts +0 -65
  225. package/src/login.tsx +0 -166
  226. package/src/logout.tsx +0 -8
  227. package/src/mdxAccessibility.ts +0 -134
  228. package/src/mdxLinter.tsx +0 -88
  229. package/src/middlewares/subdomainMiddleware.ts +0 -20
  230. package/src/middlewares/telemetryMiddleware.ts +0 -55
  231. package/src/migrate.ts +0 -76
  232. package/src/og.tsx +0 -185
  233. package/src/openApiCheck.tsx +0 -125
  234. package/src/resolveFiles.ts +0 -101
  235. package/src/score/client.ts +0 -36
  236. package/src/score/index.tsx +0 -205
  237. package/src/score/types.ts +0 -15
  238. package/src/signup.tsx +0 -172
  239. package/src/start.ts +0 -27
  240. package/src/status.tsx +0 -129
  241. package/src/telemetry/client.ts +0 -46
  242. package/src/telemetry/distinctId.ts +0 -70
  243. package/src/telemetry/sessionId.ts +0 -40
  244. package/src/telemetry/track.ts +0 -163
  245. package/src/templates.tsx +0 -143
  246. package/src/tokenRefresh.ts +0 -53
  247. package/src/update.tsx +0 -89
  248. package/src/validate/command.tsx +0 -135
  249. package/src/validate/engine.ts +0 -210
  250. package/src/validate/files.ts +0 -249
  251. package/src/validate/mdx.ts +0 -290
  252. package/src/validate/output.tsx +0 -76
  253. package/src/validate/report.ts +0 -40
  254. package/src/validate/rules/build.ts +0 -146
  255. package/src/validate/rules/content/duplicateH1.ts +0 -78
  256. package/src/validate/rules/content/foreignSyntax.ts +0 -144
  257. package/src/validate/rules/content/katex.ts +0 -33
  258. package/src/validate/rules/content/missingSnippet.ts +0 -36
  259. package/src/validate/rules/content/undefinedVariable.ts +0 -20
  260. package/src/validate/rules/content/unknownComponent.ts +0 -130
  261. package/src/validate/rules/content/voidTags.ts +0 -43
  262. package/src/validate/rules/index.ts +0 -23
  263. package/src/validate/rules/openapi.ts +0 -59
  264. package/src/validate/rules/parseError.ts +0 -9
  265. package/src/validate/site.ts +0 -53
  266. package/src/validate/types.ts +0 -102
  267. package/src/vendor/converter.ts +0 -1
  268. package/src/welcome.ts +0 -154
  269. package/src/workflows/client.ts +0 -39
  270. package/src/workflows/index.tsx +0 -287
  271. package/src/workflows/types.ts +0 -73
  272. package/tsconfig.build.json +0 -4
  273. package/tsconfig.json +0 -10
  274. package/vitest.config.ts +0 -9
@@ -1,124 +0,0 @@
1
- import { z } from 'zod';
2
-
3
- import {
4
- agentIdentityAssertionSchema,
5
- discoverAgentAuth,
6
- exchangeAgentToken,
7
- } from './agent-auth.js';
8
- import {
9
- loadAgentCredentials,
10
- saveAgentCredentials,
11
- type AgentCredentials,
12
- } from './agent-credentials.js';
13
- import { AgentApiError, agentRequest, agentResponse } from './agent-http.js';
14
- import { DASHBOARD_URL } from './constants.js';
15
- import { trackEvent } from './telemetry/track.js';
16
-
17
- const claimAttemptSchema = z.object({ attempt: z.object({ verification_uri: z.url() }) });
18
-
19
- export async function createAgentClaimLink(
20
- apiUrl: string,
21
- credentials: AgentCredentials,
22
- email: string
23
- ): Promise<string> {
24
- const loginHint = z.email().parse(email);
25
- const discovery = await discoverAgentAuth(apiUrl);
26
- if (new URL(discovery.issuer).origin !== new URL(credentials.issuer).origin) {
27
- throw new Error('Saved agent credentials belong to another issuer.');
28
- }
29
- const claim = await agentResponse(
30
- await agentRequest(discovery.agent_auth.claim_endpoint, {
31
- method: 'POST',
32
- headers: { 'Content-Type': 'application/json' },
33
- body: JSON.stringify({
34
- type: 'service_auth',
35
- claim_token: credentials.claimToken,
36
- login_hint: loginHint,
37
- }),
38
- }),
39
- claimAttemptSchema
40
- ).catch((error: unknown) => {
41
- if (error instanceof AgentApiError && error.code === 'too_many_attempts') {
42
- throw new Error(
43
- 'Too many claim links are still pending. Send the user the last claim link, or wait 5 minutes and retry.'
44
- );
45
- }
46
- throw error;
47
- });
48
- const token = z
49
- .string()
50
- .min(1)
51
- .parse(new URL(claim.attempt.verification_uri).searchParams.get('token'));
52
- const claimUrl = new URL('/agent-claim', DASHBOARD_URL);
53
- claimUrl.searchParams.set('token', token);
54
- claimUrl.searchParams.set('registration', credentials.registrationId);
55
- void trackEvent('agent_signup.claim_started', { registration_id: credentials.registrationId });
56
- return claimUrl.toString();
57
- }
58
-
59
- const completedClaimSchema = z.object({
60
- identity: agentIdentityAssertionSchema,
61
- });
62
- const signupSchema = z.object({ orgId: z.string().min(1), claimed: z.literal(true) });
63
-
64
- export async function claimDeployment(
65
- options: { apiUrl: string; directory: string; code?: string; email?: string },
66
- progress: (message: string) => void = () => {}
67
- ): Promise<string> {
68
- const { apiUrl, directory } = options;
69
- const code = options.code?.trim();
70
- const email = options.email?.trim();
71
- if ((!code && !email) || (code && email)) {
72
- throw new Error(
73
- 'Provide either --email <email> for a claim link or --code <code> to finish the claim.'
74
- );
75
- }
76
- let credentials = await loadAgentCredentials(apiUrl, directory);
77
- if (!credentials)
78
- throw new Error(
79
- 'No saved agent registration. Run from the directory used for mint deploy, or pass --directory.'
80
- );
81
- if (email && !credentials.claimVerified) {
82
- progress('Creating the claim link...');
83
- const link = await createAgentClaimLink(apiUrl, credentials, email);
84
- return `Claim link for the user: ${link}\nAsk the user to open it, sign in, and return the displayed code. Then run mint claim --code <code> from the same directory (or repeat --directory).`;
85
- }
86
- const discovery = await discoverAgentAuth(apiUrl);
87
- if (new URL(discovery.issuer).origin !== new URL(credentials.issuer).origin) {
88
- throw new Error('Saved agent credentials belong to another issuer.');
89
- }
90
- const save = (value: AgentCredentials) => saveAgentCredentials(apiUrl, directory, value);
91
- if (!credentials.claimVerified) {
92
- progress('Completing the WorkOS claim...');
93
- const completed = await agentResponse(
94
- await agentRequest(`${discovery.agent_auth.claim_endpoint.replace(/\/$/, '')}/complete`, {
95
- method: 'POST',
96
- headers: { 'Content-Type': 'application/json' },
97
- body: JSON.stringify({ claim_token: credentials.claimToken, user_code: code }),
98
- }),
99
- completedClaimSchema
100
- );
101
- void trackEvent('agent_signup.claim_completed', {
102
- registration_id: credentials.registrationId,
103
- });
104
- credentials = {
105
- ...credentials,
106
- assertion: completed.identity.assertion,
107
- claimVerified: true,
108
- accessToken: undefined,
109
- accessTokenExpiresAt: undefined,
110
- };
111
- await save(credentials);
112
- }
113
- progress('Finishing the site claim...');
114
- const authenticated = await exchangeAgentToken(discovery, credentials);
115
- await agentResponse(
116
- await agentRequest(`${apiUrl}/api/agent/signup`, {
117
- method: 'POST',
118
- headers: { Authorization: `Bearer ${authenticated.accessToken}` },
119
- }),
120
- signupSchema
121
- );
122
- await save(authenticated);
123
- return 'Site claimed successfully. The user can now manage it in the Mintlify dashboard.';
124
- }
@@ -1,104 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { z } from 'zod';
5
-
6
- import { CONFIG_DIR } from './constants.js';
7
- import { getKeytar } from './keyring.js';
8
-
9
- const service = 'mintlify-agent';
10
- const fallbackFile = () => path.join(CONFIG_DIR, 'agent-credentials.json');
11
-
12
- export const agentCredentialsSchema = z.object({
13
- registrationId: z.string().min(1),
14
- issuer: z.url(),
15
- assertion: z.string().min(1),
16
- claimToken: z.string().min(1),
17
- claimVerified: z.boolean().optional(),
18
- accessToken: z.string().min(1).optional(),
19
- accessTokenExpiresAt: z.number().optional(),
20
- });
21
-
22
- export type AgentCredentials = z.infer<typeof agentCredentialsSchema>;
23
-
24
- function projectAccount(apiUrl: string, directory: string): string {
25
- return `project:${createHash('sha256')
26
- .update(JSON.stringify([new URL(apiUrl).origin, path.resolve(directory)]))
27
- .digest('hex')}`;
28
- }
29
-
30
- function registrationAccount(apiUrl: string, registrationId: string): string {
31
- return `${new URL(apiUrl).origin}:${registrationId}`;
32
- }
33
-
34
- async function readFallback(): Promise<Record<string, string>> {
35
- try {
36
- return z
37
- .record(z.string(), z.string())
38
- .parse(JSON.parse(await fs.readFile(fallbackFile(), 'utf-8')));
39
- } catch {
40
- return {};
41
- }
42
- }
43
-
44
- async function writeFallback(entries: Record<string, string>): Promise<void> {
45
- await fs.mkdir(CONFIG_DIR, { recursive: true });
46
- const temp = `${fallbackFile()}.${process.pid}.tmp`;
47
- await fs.writeFile(temp, JSON.stringify(entries, null, 2), { mode: 0o600 });
48
- await fs.chmod(temp, 0o600);
49
- await fs.rename(temp, fallbackFile());
50
- }
51
-
52
- async function getSecret(account: string): Promise<string | null> {
53
- let keyringError: unknown;
54
- try {
55
- const value = await (await getKeytar()).getPassword(service, account);
56
- if (value) return value;
57
- } catch (error) {
58
- keyringError = error;
59
- }
60
- const value = (await readFallback())[account];
61
- if (value) return value;
62
- if (keyringError) throw keyringError;
63
- return null;
64
- }
65
-
66
- async function setSecret(account: string, value: string): Promise<void> {
67
- try {
68
- await (await getKeytar()).setPassword(service, account, value);
69
- } catch {
70
- await writeFallback({ ...(await readFallback()), [account]: value });
71
- await getKeytar()
72
- .then((keytar) => keytar.deletePassword(service, account))
73
- .catch(() => {});
74
- return;
75
- }
76
- const { [account]: stale, ...rest } = await readFallback();
77
- if (stale) await writeFallback(rest).catch(() => {});
78
- }
79
-
80
- export async function loadAgentCredentials(
81
- apiUrl: string,
82
- directory: string
83
- ): Promise<AgentCredentials | null> {
84
- const registrationId = await getSecret(projectAccount(apiUrl, directory));
85
- if (!registrationId) return null;
86
- const value = await getSecret(registrationAccount(apiUrl, registrationId));
87
- if (!value)
88
- throw new Error('Saved agent credentials are missing. Use --new to create another site.');
89
- const credentials = agentCredentialsSchema.parse(JSON.parse(value));
90
- if (credentials.registrationId !== registrationId) {
91
- throw new Error('Saved agent credentials do not match this project.');
92
- }
93
- return credentials;
94
- }
95
-
96
- export async function saveAgentCredentials(
97
- apiUrl: string,
98
- directory: string,
99
- credentials: AgentCredentials
100
- ): Promise<void> {
101
- const value = agentCredentialsSchema.parse(credentials);
102
- await setSecret(registrationAccount(apiUrl, value.registrationId), JSON.stringify(value));
103
- await setSecret(projectAccount(apiUrl, directory), value.registrationId);
104
- }
@@ -1,116 +0,0 @@
1
- import { setTimeout } from 'node:timers/promises';
2
- import { z } from 'zod';
3
-
4
- import { agentRequest, agentResponse } from './agent-http.js';
5
-
6
- const readySchema = z.object({
7
- status: z.literal('ready'),
8
- deploymentId: z.string().min(1),
9
- subdomain: z.string().min(1),
10
- remote: z.url(),
11
- branch: z.literal('main'),
12
- expiresAt: z.iso.datetime(),
13
- orgSlug: z.string().min(1).optional(),
14
- });
15
- const existingSchema = z.discriminatedUnion('status', [
16
- readySchema.extend({ code: z.literal('deployment_already_exists') }),
17
- z.object({
18
- status: z.literal('provisioning'),
19
- code: z.literal('deployment_already_exists'),
20
- deploymentId: z.string().optional(),
21
- subdomain: z.string().optional(),
22
- }),
23
- z.object({
24
- status: z.literal('expired'),
25
- code: z.enum(['deployment_already_exists', 'deployment_claim_expired']),
26
- deploymentId: z.string(),
27
- subdomain: z.string(),
28
- expiresAt: z.iso.datetime().optional(),
29
- }),
30
- ]);
31
- const writeTokenSchema = z.object({
32
- remote: z.url(),
33
- branch: z.literal('main'),
34
- token: z.string().min(1),
35
- tokenExpiresAt: z.iso.datetime(),
36
- });
37
-
38
- const trustedReposSchema = z.object({
39
- subdomain: z.string().min(1),
40
- trustedRepos: z.array(
41
- z.object({ repositoryId: z.string(), repository: z.string(), branch: z.string() })
42
- ),
43
- });
44
-
45
- export type AgentSite = z.infer<typeof readySchema>;
46
- export type AgentWriteToken = z.infer<typeof writeTokenSchema>;
47
- export type AgentProjectType = 'site' | 'workspace';
48
- export type AgentSiteSettings = {
49
- subdomain: string;
50
- orgName?: string;
51
- projectType?: AgentProjectType;
52
- };
53
-
54
- export async function provisionAgentSite(
55
- apiUrl: string,
56
- accessToken: string,
57
- settings: AgentSiteSettings
58
- ) {
59
- for (let attempt = 0; attempt < 4; attempt++) {
60
- const response = await agentRequest(`${apiUrl}/api/agent/deployments/provision`, {
61
- method: 'POST',
62
- headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
63
- body: JSON.stringify({ ...settings, docsPath: '' }),
64
- });
65
- if (response.status !== 409) {
66
- return { ...(await agentResponse(response, readySchema)), created: true };
67
- }
68
- const body: unknown = await response.json().catch(() => null);
69
- const parsed = existingSchema.safeParse(body);
70
- if (!parsed.success) throw new Error('The deployment service returned an unexpected response.');
71
- if (parsed.data.status !== 'provisioning') return { ...parsed.data, created: false };
72
- if (attempt < 3) await setTimeout(1000 * (attempt + 1));
73
- }
74
- throw new Error('Your site is still provisioning. Run the same command again.');
75
- }
76
-
77
- export async function getAgentWriteToken(
78
- apiUrl: string,
79
- accessToken: string
80
- ): Promise<AgentWriteToken> {
81
- return agentResponse(
82
- await agentRequest(`${apiUrl}/api/agent/deployments/token`, {
83
- method: 'POST',
84
- headers: { Authorization: `Bearer ${accessToken}` },
85
- }),
86
- writeTokenSchema
87
- );
88
- }
89
-
90
- export async function getGithubActionsWriteToken(
91
- apiUrl: string,
92
- oidcToken: string,
93
- subdomain: string
94
- ): Promise<AgentWriteToken> {
95
- return agentResponse(
96
- await agentRequest(`${apiUrl}/api/agent/deployments/github-actions/token`, {
97
- method: 'POST',
98
- headers: { Authorization: `Bearer ${oidcToken}`, 'Content-Type': 'application/json' },
99
- body: JSON.stringify({ subdomain }),
100
- }),
101
- writeTokenSchema
102
- );
103
- }
104
-
105
- export type TrustedRepo = { repositoryId: string; repository: string; branch: string };
106
-
107
- export async function trustGithubRepo(apiUrl: string, accessToken: string, repo: TrustedRepo) {
108
- return agentResponse(
109
- await agentRequest(`${apiUrl}/api/agent/deployments/trusted-repos`, {
110
- method: 'POST',
111
- headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
112
- body: JSON.stringify(repo),
113
- }),
114
- trustedReposSchema
115
- );
116
- }
package/src/agent-http.ts DELETED
@@ -1,34 +0,0 @@
1
- import { z } from 'zod';
2
-
3
- const errorSchema = z.object({ code: z.string().optional(), error: z.string().optional() });
4
-
5
- export class AgentApiError extends Error {
6
- constructor(
7
- public readonly status: number,
8
- public readonly code?: string
9
- ) {
10
- super(`Agent request failed (HTTP ${status}).${code ? ` Code: ${code}.` : ''}`);
11
- }
12
- }
13
-
14
- export async function agentRequest(url: string, init?: RequestInit): Promise<Response> {
15
- try {
16
- const timeout = AbortSignal.timeout(30_000);
17
- const signal = init?.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
18
- return await fetch(url, { ...init, redirect: 'error', signal });
19
- } catch {
20
- throw new Error('Could not reach the agent service. Retry the same command.');
21
- }
22
- }
23
-
24
- export async function agentResponse<T>(response: Response, schema: z.ZodType<T>): Promise<T> {
25
- const body: unknown = await response.json().catch(() => null);
26
- if (!response.ok) {
27
- const error = errorSchema.safeParse(body);
28
- const code = error.success ? (error.data.code ?? error.data.error) : undefined;
29
- throw new AgentApiError(response.status, code?.match(/^[a-z_]{1,80}$/)?.[0]);
30
- }
31
- const parsed = schema.safeParse(body);
32
- if (!parsed.success) throw new Error('The agent service returned an unexpected response.');
33
- return parsed.data;
34
- }
@@ -1,144 +0,0 @@
1
- import { applyEdits, modify, parse, type ParseError } from 'jsonc-parser';
2
- import { randomUUID } from 'node:crypto';
3
- import fs from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { parse as parseToml } from 'smol-toml';
6
-
7
- export type SetupAgent = 'claude-code' | 'codex' | 'cursor';
8
-
9
- export const ADMIN_MCP_NAME = 'mintlify-admin';
10
- export const ADMIN_MCP_URL = 'https://mcp.mintlify.com';
11
-
12
- type ConfigLocation = {
13
- cwd: string;
14
- homeDir: string;
15
- global: boolean;
16
- env?: NodeJS.ProcessEnv;
17
- };
18
-
19
- type McpConfigPlan = {
20
- path: string;
21
- original: string | undefined;
22
- contents: string | undefined;
23
- };
24
-
25
- function isRecord(value: unknown): value is Record<string, unknown> {
26
- return typeof value === 'object' && value !== null && !Array.isArray(value);
27
- }
28
-
29
- async function readConfig(file: string): Promise<string | undefined> {
30
- try {
31
- return await fs.readFile(file, 'utf8');
32
- } catch (error) {
33
- if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined;
34
- throw error;
35
- }
36
- }
37
-
38
- function configPath(agent: SetupAgent, options: ConfigLocation): string {
39
- const env = options.env ?? process.env;
40
- if (agent === 'codex') {
41
- let directory = path.join(options.cwd, '.codex');
42
- if (options.global) directory = env.CODEX_HOME || path.join(options.homeDir, '.codex');
43
- return path.join(directory, 'config.toml');
44
- }
45
- if (agent === 'cursor') {
46
- const directory = options.global ? options.homeDir : options.cwd;
47
- return path.join(directory, '.cursor', 'mcp.json');
48
- }
49
- if (options.global) {
50
- if (env.CLAUDE_CONFIG_DIR) {
51
- throw new Error(
52
- 'CLAUDE_CONFIG_DIR is set. Configure Claude Code with: claude mcp add --scope user --transport http mintlify-admin https://mcp.mintlify.com'
53
- );
54
- }
55
- return path.join(options.homeDir, '.claude.json');
56
- }
57
- return path.join(options.cwd, '.mcp.json');
58
- }
59
-
60
- export async function prepareMcpConfig(
61
- agent: SetupAgent,
62
- options: ConfigLocation
63
- ): Promise<McpConfigPlan> {
64
- const requestedPath = configPath(agent, options);
65
- const file = await fs.realpath(requestedPath).catch((error: unknown) => {
66
- if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return requestedPath;
67
- throw error;
68
- });
69
- const original = await readConfig(file);
70
- const source = original ?? '';
71
- const key = agent === 'codex' ? 'mcp_servers' : 'mcpServers';
72
- let config: unknown;
73
- try {
74
- if (agent === 'codex') {
75
- config = parseToml(source);
76
- } else {
77
- const errors: ParseError[] = [];
78
- config = parse(source || '{}', errors, { allowTrailingComma: true });
79
- if (errors.length > 0) throw new Error('Invalid JSON');
80
- }
81
- } catch {
82
- throw new Error(`Cannot parse ${file}. Fix its configuration before running setup.`);
83
- }
84
- if (!isRecord(config)) throw new Error(`Expected an object in ${file}.`);
85
- const servers = config[key];
86
- if (servers !== undefined && !isRecord(servers)) {
87
- throw new Error(`Expected ${key} to be an object in ${file}.`);
88
- }
89
- const existing = servers?.[ADMIN_MCP_NAME];
90
- if (existing !== undefined) {
91
- if (!isRecord(existing) || existing.url !== ADMIN_MCP_URL || existing.command !== undefined) {
92
- throw new Error(
93
- `${ADMIN_MCP_NAME} already has a different configuration in ${file}. Rename or remove that entry before running setup.`
94
- );
95
- }
96
- if (agent === 'claude-code' && existing.type !== 'http') {
97
- throw new Error(`Set type to "http" for ${ADMIN_MCP_NAME} in ${file} before running setup.`);
98
- }
99
- return { path: file, original, contents: undefined };
100
- }
101
- const newline = source.includes('\r\n') ? '\r\n' : '\n';
102
- let contents: string;
103
- if (agent === 'codex') {
104
- contents = `${source}${newline}[mcp_servers.${ADMIN_MCP_NAME}]${newline}url = "${ADMIN_MCP_URL}"${newline}`;
105
- try {
106
- parseToml(contents);
107
- } catch {
108
- throw new Error(
109
- `Cannot safely extend ${file}. Add a ${ADMIN_MCP_NAME} entry with url = "${ADMIN_MCP_URL}" to mcp_servers manually.`
110
- );
111
- }
112
- } else {
113
- const server: Record<string, string> = { url: ADMIN_MCP_URL };
114
- if (agent === 'claude-code') server.type = 'http';
115
- contents = applyEdits(
116
- source || '{}',
117
- modify(source || '{}', [key, ADMIN_MCP_NAME], server, {
118
- formattingOptions: { insertSpaces: true, tabSize: 2, eol: newline },
119
- })
120
- );
121
- if (!contents.endsWith(newline)) contents += newline;
122
- }
123
- return { path: file, original, contents };
124
- }
125
-
126
- export async function writeMcpConfig(plan: McpConfigPlan): Promise<void> {
127
- if ((await readConfig(plan.path)) !== plan.original) {
128
- throw new Error(
129
- `${plan.path} changed during setup. Run setup again to preserve those changes.`
130
- );
131
- }
132
- if (plan.contents === undefined) return;
133
- await fs.mkdir(path.dirname(plan.path), { recursive: true, mode: 0o700 });
134
- let mode = 0o600;
135
- if (plan.original !== undefined) mode = (await fs.stat(plan.path)).mode;
136
- const temporaryPath = `${plan.path}.${randomUUID()}.tmp`;
137
- try {
138
- await fs.writeFile(temporaryPath, plan.contents, { mode, flag: 'wx' });
139
- if (plan.original !== undefined) await fs.chmod(temporaryPath, mode);
140
- await fs.rename(temporaryPath, plan.path);
141
- } finally {
142
- await fs.rm(temporaryPath, { force: true });
143
- }
144
- }
@@ -1,165 +0,0 @@
1
- import { checkbox } from '@inquirer/prompts';
2
- import { spawn } from 'node:child_process';
3
- import { existsSync } from 'node:fs';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { stripVTControlCharacters } from 'node:util';
7
-
8
- import {
9
- ADMIN_MCP_NAME,
10
- ADMIN_MCP_URL,
11
- prepareMcpConfig,
12
- writeMcpConfig,
13
- type SetupAgent,
14
- } from './agent-setup-config.js';
15
- import { detectAgent } from './agent.js';
16
-
17
- export const SETUP_AGENTS: SetupAgent[] = ['claude-code', 'codex', 'cursor'];
18
-
19
- const AGENT_LABELS: Record<SetupAgent, string> = {
20
- 'claude-code': 'Claude Code',
21
- codex: 'Codex',
22
- cursor: 'Cursor',
23
- };
24
-
25
- type SetupOptions = {
26
- agents?: string[];
27
- global: boolean;
28
- };
29
-
30
- function isSetupAgent(value: string): value is SetupAgent {
31
- return SETUP_AGENTS.some((agent) => agent === value);
32
- }
33
-
34
- function detectedAgents(): SetupAgent[] {
35
- const homeDir = os.homedir();
36
- const current = detectAgent();
37
- return SETUP_AGENTS.filter((agent) => {
38
- if (agent === 'codex') {
39
- return (
40
- current === 'codex_cli' ||
41
- existsSync(process.env.CODEX_HOME || path.join(homeDir, '.codex'))
42
- );
43
- }
44
- if (agent === 'claude-code') {
45
- return (
46
- current === 'claude_code' ||
47
- existsSync(process.env.CLAUDE_CONFIG_DIR || path.join(homeDir, '.claude'))
48
- );
49
- }
50
- return (
51
- current === 'cursor' || current === 'cursor-cli' || existsSync(path.join(homeDir, '.cursor'))
52
- );
53
- });
54
- }
55
-
56
- export function installSkills(agents: SetupAgent[], global: boolean): Promise<void> {
57
- const args = [
58
- '--yes',
59
- 'skills@1.7.4',
60
- 'add',
61
- 'https://mintlify.com/docs',
62
- '--agent',
63
- ...agents,
64
- '--yes',
65
- ];
66
- if (global) args.push('--global');
67
- return new Promise((resolve, reject) => {
68
- const child = spawn('npx', args, {
69
- stdio: ['ignore', 'pipe', 'pipe'],
70
- shell: process.platform === 'win32',
71
- });
72
- let output = '';
73
- const recordOutput = (chunk: Buffer) => {
74
- output = (output + chunk.toString()).slice(-65_536);
75
- };
76
- child.stdout.on('data', (chunk: Buffer) => {
77
- recordOutput(chunk);
78
- process.stdout.write(chunk.toString());
79
- });
80
- child.stderr.on('data', (chunk: Buffer) => {
81
- recordOutput(chunk);
82
- process.stderr.write(chunk.toString());
83
- });
84
- child.on('error', () =>
85
- reject(new Error('Could not run npx. Install npm and run setup again.'))
86
- );
87
- child.on('close', (code, signal) => {
88
- if (code !== 0 || /Failed to install\s+\d+/.test(stripVTControlCharacters(output))) {
89
- reject(
90
- new Error(
91
- `Skills installation failed (${signal ?? code}). Review the installer output and run setup again.`
92
- )
93
- );
94
- } else {
95
- resolve();
96
- }
97
- });
98
- });
99
- }
100
-
101
- export async function setupAgent(options: SetupOptions): Promise<void> {
102
- const [major = 0, minor = 0] = process.versions.node.split('.').map(Number);
103
- if (major < 22 || (major === 22 && minor < 20)) {
104
- throw new Error(
105
- 'mint agent setup requires Node.js 22.20 or later to install skills. Upgrade Node.js and try again.'
106
- );
107
- }
108
- const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
109
- let agents: SetupAgent[] = [];
110
- for (const agent of options.agents ?? []) {
111
- if (!isSetupAgent(agent)) throw new Error(`Unsupported agent: ${agent}`);
112
- if (!agents.includes(agent)) agents.push(agent);
113
- }
114
- if (agents.length === 0) {
115
- const detected = detectedAgents();
116
- if (!interactive) {
117
- agents = detected;
118
- } else {
119
- agents = await checkbox({
120
- message: 'Which agents should use Mintlify?',
121
- choices: SETUP_AGENTS.map((agent) => ({
122
- name: AGENT_LABELS[agent],
123
- value: agent,
124
- checked: detected.includes(agent),
125
- })),
126
- required: true,
127
- });
128
- }
129
- }
130
- if (agents.length === 0) {
131
- throw new Error('No supported agents detected. Pass --agent claude-code, codex, or cursor.');
132
- }
133
- const location = { cwd: process.cwd(), homeDir: os.homedir(), global: options.global };
134
- const plans = await Promise.all(agents.map((agent) => prepareMcpConfig(agent, location)));
135
- const scope = options.global ? 'your user account' : 'this project';
136
- process.stdout.write(`Setting up Mintlify skills and Admin MCP for ${scope}.\n`);
137
- await installSkills(agents, options.global);
138
- for (const plan of plans) {
139
- await writeMcpConfig(plan);
140
- const action = plan.contents === undefined ? 'Already configured' : 'Configured';
141
- process.stdout.write(`${action}: ${plan.path}\n`);
142
- }
143
- process.stdout.write(
144
- '\nAdmin MCP is configured. Complete OAuth sign-in to grant account and project access:\n'
145
- );
146
- for (const agent of agents) {
147
- if (agent === 'codex') {
148
- let command = `codex mcp login ${ADMIN_MCP_NAME}`;
149
- if (!options.global) {
150
- const config = `mcp_servers.${ADMIN_MCP_NAME}.url='${ADMIN_MCP_URL}'`;
151
- command = `codex -c "${config}" mcp login ${ADMIN_MCP_NAME}`;
152
- }
153
- process.stdout.write(
154
- ` Codex: run ${command}. Trust the project before using its MCP configuration.\n`
155
- );
156
- } else if (agent === 'claude-code') {
157
- process.stdout.write(
158
- ` Claude Code: open /mcp and authenticate ${ADMIN_MCP_NAME}. Approve the project server if prompted.\n`
159
- );
160
- } else {
161
- process.stdout.write(` Cursor: open MCP settings and connect ${ADMIN_MCP_NAME}.\n`);
162
- }
163
- }
164
- process.stdout.write('Setup: https://mintlify.com/docs/ai/mintlify-mcp\n');
165
- }