import {z} from 'zod' export type AssistImage = {data_base64: string, media_type: 'image/png' | 'image/jpeg', width_px: number, height_px: number}; export type AssistTransform = {a: number, b: number, c: number, d: number, e: number, f: number}; export type RescueCandidate = {far_point: Array, angle_deg: number}; export type RescueContext = {stop_point: Array, heading_deg: number, goal_point: Array | null, candidates: Array, bridge_point: Array | null}; export type CompleteContext = {placed_vertices: Array>, tool: 'polyline' | 'polygon'}; export type AutocompleteAssistRequest = {kind: 'rescue' | 'complete', image: AssistImage, transform: AssistTransform, rescue?: (RescueContext | null) | undefined, complete?: (CompleteContext | null) | undefined}; export type CreateApiApiV1PagesPageIdAutocompleteAssistArgs = {page_id: string, body: AutocompleteAssistRequest}; export type CreateApiApiV1PagesPageIdAutocompleteAssistOptions = {baseUrl: string, fetch?: typeof fetch | undefined}; export const rescueAssistResult = z.object({kind: z.literal("rescue").optional(), choice: z.union([z.number().int(), z.enum(["bridge", "none"])])}); export const completeAssistResult = z.object({kind: z.literal("complete").optional(), vertices_pdf: z.array(z.array(z.unknown())), confidence: z.enum(["high", "low"])}); export const autocompleteAssistResponse = z.object({assist: z.union([rescueAssistResult, completeAssistResult]).nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Autocomplete Assist * * POST /api/v1/pages/{page_id}/autocomplete-assist */ export const createApiApiV1PagesPageIdAutocompleteAssist = async (args: CreateApiApiV1PagesPageIdAutocompleteAssistArgs, options: CreateApiApiV1PagesPageIdAutocompleteAssistOptions) => { const {baseUrl, fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/api/v1/pages/${encodeURIComponent(String(args.page_id))}/autocomplete-assist${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(autocompleteAssistResponse, await res.json()) };