@mintlify/cli 4.0.1734 → 4.0.1735

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mintlify/cli",
3
- "version": "4.0.1734",
3
+ "version": "4.0.1735",
4
4
  "description": "The Mintlify CLI",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -101,5 +101,5 @@
101
101
  "vitest": "2.1.9",
102
102
  "vitest-mock-process": "1.0.4"
103
103
  },
104
- "gitHead": "ae7819bfab79f6c765d39aed34bf33363f4be72a"
104
+ "gitHead": "06c165289d14569110e9510ffca7470891ba2722"
105
105
  }
@@ -56,7 +56,6 @@ const signupSchema = z.object({ orgId: z.string().min(1), claimed: z.literal(tru
56
56
 
57
57
  export async function claimDeployment(
58
58
  options: { apiUrl: string; directory: string; code?: string; email?: string },
59
- warn: (message: string) => void,
60
59
  progress: (message: string) => void = () => {}
61
60
  ): Promise<string> {
62
61
  const { apiUrl, directory } = options;
@@ -81,15 +80,7 @@ export async function claimDeployment(
81
80
  if (new URL(discovery.issuer).origin !== new URL(credentials.issuer).origin) {
82
81
  throw new Error('Saved agent credentials belong to another issuer.');
83
82
  }
84
- const save = async (value: AgentCredentials) => {
85
- try {
86
- await saveAgentCredentials(apiUrl, directory, value);
87
- } catch {
88
- warn(
89
- 'Could not save claimed credentials to the keyring. Continuing for this run; a retry may not recover the completed claim.'
90
- );
91
- }
92
- };
83
+ const save = (value: AgentCredentials) => saveAgentCredentials(apiUrl, directory, value);
93
84
  if (!credentials.claimVerified) {
94
85
  progress('Completing the WorkOS claim...');
95
86
  const completed = await agentResponse(
@@ -1,10 +1,13 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import fs from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import { z } from 'zod';
4
5
 
6
+ import { CONFIG_DIR } from './constants.js';
5
7
  import { getKeytar } from './keyring.js';
6
8
 
7
9
  const service = 'mintlify-agent';
10
+ const fallbackFile = () => path.join(CONFIG_DIR, 'agent-credentials.json');
8
11
 
9
12
  export const agentCredentialsSchema = z.object({
10
13
  registrationId: z.string().min(1),
@@ -28,14 +31,59 @@ function registrationAccount(apiUrl: string, registrationId: string): string {
28
31
  return `${new URL(apiUrl).origin}:${registrationId}`;
29
32
  }
30
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
+
31
80
  export async function loadAgentCredentials(
32
81
  apiUrl: string,
33
82
  directory: string
34
83
  ): Promise<AgentCredentials | null> {
35
- const keytar = await getKeytar();
36
- const registrationId = await keytar.getPassword(service, projectAccount(apiUrl, directory));
84
+ const registrationId = await getSecret(projectAccount(apiUrl, directory));
37
85
  if (!registrationId) return null;
38
- const value = await keytar.getPassword(service, registrationAccount(apiUrl, registrationId));
86
+ const value = await getSecret(registrationAccount(apiUrl, registrationId));
39
87
  if (!value)
40
88
  throw new Error('Saved agent credentials are missing. Use --new to create another site.');
41
89
  const credentials = agentCredentialsSchema.parse(JSON.parse(value));
@@ -51,11 +99,6 @@ export async function saveAgentCredentials(
51
99
  credentials: AgentCredentials
52
100
  ): Promise<void> {
53
101
  const value = agentCredentialsSchema.parse(credentials);
54
- const keytar = await getKeytar();
55
- await keytar.setPassword(
56
- service,
57
- registrationAccount(apiUrl, value.registrationId),
58
- JSON.stringify(value)
59
- );
60
- await keytar.setPassword(service, projectAccount(apiUrl, directory), value.registrationId);
102
+ await setSecret(registrationAccount(apiUrl, value.registrationId), JSON.stringify(value));
103
+ await setSecret(projectAccount(apiUrl, directory), value.registrationId);
61
104
  }
package/src/cli.tsx CHANGED
@@ -143,7 +143,6 @@ export const cli = ({ packageName = 'mint' }: { packageName?: string }) => {
143
143
  try {
144
144
  const message = await claimDeployment(
145
145
  { apiUrl: API_URL, directory: argv.directory, code: argv.code, email: argv.email },
146
- (message) => process.stderr.write(`Warning: ${message}\n`),
147
146
  (message) => process.stderr.write(`${message}\n`)
148
147
  );
149
148
  process.stdout.write(`${message}\n`);
package/src/deploy.ts CHANGED
@@ -62,15 +62,8 @@ export async function prepareAgentDeployment(
62
62
  if (!subdomain) throw new Error('Choose a site name with --subdomain <name>.');
63
63
  const discovery = await discoverAgentAuth(apiUrl);
64
64
 
65
- const save = async (credentials: AgentCredentials) => {
66
- try {
67
- await saveAgentCredentials(apiUrl, directory, credentials);
68
- } catch {
69
- warn(
70
- 'Could not save agent credentials to the keyring. Continuing for this run; later commands may not recover access.'
71
- );
72
- }
73
- };
65
+ const save = (credentials: AgentCredentials) =>
66
+ saveAgentCredentials(apiUrl, directory, credentials);
74
67
 
75
68
  for (let attempt = 0; attempt < 2; attempt++) {
76
69
  const credentials = saved ?? (await registerAgent(discovery));