import { createHash } from 'node:crypto'; import path from 'node:path'; import { z } from 'zod'; import { getKeytar } from './keyring.js'; const service = 'mintlify-agent'; export const agentCredentialsSchema = z.object({ registrationId: z.string().min(1), issuer: z.url(), assertion: z.string().min(1), claimToken: z.string().min(1), claimVerified: z.boolean().optional(), accessToken: z.string().min(1).optional(), accessTokenExpiresAt: z.number().optional(), }); export type AgentCredentials = z.infer; function projectAccount(apiUrl: string, directory: string): string { return `project:${createHash('sha256') .update(JSON.stringify([new URL(apiUrl).origin, path.resolve(directory)])) .digest('hex')}`; } function registrationAccount(apiUrl: string, registrationId: string): string { return `${new URL(apiUrl).origin}:${registrationId}`; } export async function loadAgentCredentials( apiUrl: string, directory: string ): Promise { const keytar = await getKeytar(); const registrationId = await keytar.getPassword(service, projectAccount(apiUrl, directory)); if (!registrationId) return null; const value = await keytar.getPassword(service, registrationAccount(apiUrl, registrationId)); if (!value) throw new Error('Saved agent credentials are missing. Use --new to create another site.'); const credentials = agentCredentialsSchema.parse(JSON.parse(value)); if (credentials.registrationId !== registrationId) { throw new Error('Saved agent credentials do not match this project.'); } return credentials; } export async function saveAgentCredentials( apiUrl: string, directory: string, credentials: AgentCredentials ): Promise { const value = agentCredentialsSchema.parse(credentials); const keytar = await getKeytar(); await keytar.setPassword( service, registrationAccount(apiUrl, value.registrationId), JSON.stringify(value) ); await keytar.setPassword(service, projectAccount(apiUrl, directory), value.registrationId); }