import { setTimeout } from 'node:timers/promises'; import { z } from 'zod'; import { agentRequest, agentResponse } from './agent-http.js'; const readySchema = z.object({ status: z.literal('ready'), deploymentId: z.string().min(1), subdomain: z.string().min(1), remote: z.url(), branch: z.literal('main'), expiresAt: z.iso.datetime(), }); const existingSchema = z.discriminatedUnion('status', [ readySchema.extend({ code: z.literal('deployment_already_exists') }), z.object({ status: z.literal('provisioning'), code: z.literal('deployment_already_exists'), deploymentId: z.string().optional(), subdomain: z.string().optional(), }), z.object({ status: z.literal('expired'), code: z.literal('deployment_already_exists'), deploymentId: z.string(), subdomain: z.string(), expiresAt: z.iso.datetime().optional(), }), ]); const writeTokenSchema = z.object({ remote: z.url(), branch: z.literal('main'), token: z.string().min(1), tokenExpiresAt: z.iso.datetime(), }); export type AgentSite = z.infer; export type AgentWriteToken = z.infer; export type AgentSiteSettings = { subdomain: string; orgName?: string }; export async function provisionAgentSite( apiUrl: string, accessToken: string, settings: AgentSiteSettings ) { for (let attempt = 0; attempt < 4; attempt++) { const response = await agentRequest(`${apiUrl}/api/agent/deployments/provision`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ...settings, docsPath: '' }), }); if (response.status !== 409) { return { ...(await agentResponse(response, readySchema)), created: true }; } const body: unknown = await response.json().catch(() => null); const parsed = existingSchema.safeParse(body); if (!parsed.success) throw new Error('The deployment service returned an unexpected response.'); if (parsed.data.status !== 'provisioning') return { ...parsed.data, created: false }; if (attempt < 3) await setTimeout(1000 * (attempt + 1)); } throw new Error('Your site is still provisioning. Run the same command again.'); } export async function getAgentWriteToken( apiUrl: string, accessToken: string ): Promise { return agentResponse( await agentRequest(`${apiUrl}/api/agent/deployments/token`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}` }, }), writeTokenSchema ); }