@lovable.dev/sdk 0.1.10 → 1.1.0
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/README.md +71 -40
- package/dist/index.d.ts +5281 -9468
- package/dist/index.js +737 -419
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +4174 -0
- package/dist/schemas.js +2031 -0
- package/dist/schemas.js.map +1 -0
- package/package.json +27 -2
- package/src/client.ts +1597 -0
- package/src/generated/paths.ts +7743 -0
- package/src/generated/zod/zod.gen.ts +2018 -0
- package/src/index.ts +93 -0
- package/src/retryFetch.ts +44 -0
- package/src/schemas.ts +22 -0
- package/src/types.ts +493 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/types.ts"],"sourcesContent":["import type { Client, Middleware } from \"openapi-fetch\";\n\nimport createClient from \"openapi-fetch\";\n\nimport type { paths } from \"./generated/paths.js\";\nimport type {\n LovableClientOptions,\n CreateProjectOptions,\n InviteCollaboratorOptions,\n ChatMessageOptions,\n WaitOptions,\n WorkspaceWithMembership,\n ProjectResponse,\n WorkspaceMembershipResponse,\n CreateProjectBody,\n AddUserToWorkspaceInputBody,\n GetWorkspacesResponse,\n DeploymentResponse,\n ChatResponse,\n ChatResponseOptions,\n UnscopedFile,\n FileInput,\n RemixProjectOptions,\n RemixInitBody,\n RemixInitResponse,\n RemixProgressResponse,\n RemixResult,\n RemixWaitOptions,\n MeResponse,\n DatabaseStatus,\n EnableDatabaseResult,\n DatabaseQueryResult,\n SendMessageResponse,\n GetMessageResponse,\n ListMessagesResponse,\n MessageCompletionResult,\n MessageCompletionOptions,\n KnowledgeResponse,\n FileUploadUrlResponse,\n GitDiffResponse,\n GitFilesResponse,\n EditsResponse,\n ListProjectsResponse,\n ListProjectsOptions,\n ConnectorResponse,\n AvailableConnectorEntry,\n AddConnectorBody,\n StandardConnectorItem,\n SeamlessConnectorItem,\n MCPConnectorItem,\n ConnectionItem,\n ProjectAnalyticsResponse,\n ProjectAnalyticsTrendResponse,\n LibraryProjectResponse,\n TemplateProjectResponse,\n ListWorkspaceSkillsResponse,\n WorkspaceSkillResponse,\n WorkspaceSkillWriteResponse,\n WorkspaceSkillDeleteResponse,\n ListProjectSkillsResponse,\n ProjectSkillResponse,\n} from \"./types.js\";\n\nimport { ApiError } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.lovable.dev\";\n\nfunction normalizeBaseUrl(url: string | undefined): string {\n if (!url) return DEFAULT_BASE_URL;\n\n const normalized = url.replace(/\\/$/, \"\");\n\n if (!normalized.startsWith(\"http://\") && !normalized.startsWith(\"https://\")) {\n throw new Error(`baseUrl must include a protocol (http:// or https://). Got: \"${url}\"`);\n }\n\n return normalized;\n}\n\n/**\n * openapi-fetch middleware that converts non-2xx Response objects into the\n * SDK's ApiError, preserving the existing error contract (status/type/detail/\n * props) used by every other method in this client.\n */\nconst errorMiddleware: Middleware = {\n async onResponse({ response }) {\n if (response.ok) return;\n let errorBody:\n | {\n type?: string;\n title?: string;\n message?: string;\n detail?: string;\n details?: string;\n props?: Record<string, unknown>;\n }\n | undefined;\n try {\n errorBody = (await response.clone().json()) as typeof errorBody;\n } catch {\n // Ignore JSON parse errors\n }\n const message = buildErrorMessage(errorBody, response.status, response.statusText);\n const type = errorBody?.type ?? errorBody?.title;\n const detail = errorBody?.detail ?? errorBody?.details;\n throw new ApiError(response.status, message, type, detail, errorBody?.props);\n },\n};\n\n// HTTP/2 leaves response.statusText empty, and some Go API endpoints return\n// `{message: \"\"}` / `{title: \"\"}` bodies on errors. `??` would preserve the\n// empty string and produce an ApiError with no usable message; consumers\n// downstream (MCP, logs, UI) then render an unlabeled failure.\nfunction buildErrorMessage(\n body: { message?: string; title?: string } | undefined,\n status: number,\n statusText: string,\n): string {\n return body?.message || body?.title || (statusText ? `HTTP ${status}: ${statusText}` : `HTTP ${status}`);\n}\n\nexport class LovableClient {\n private readonly authHeaders: Record<string, string>;\n private readonly baseUrl: string;\n private readonly extraHeaders: Record<string, string>;\n private readonly clientSource: string;\n private readonly typedClient: Client<paths>;\n\n constructor(options: LovableClientOptions) {\n const hasApiKey = !!options.apiKey;\n const hasBearerToken = !!options.bearerToken;\n\n if (!hasApiKey && !hasBearerToken) {\n throw new Error(\"Either apiKey or bearerToken is required\");\n }\n if (hasApiKey && hasBearerToken) {\n throw new Error(\"Provide either apiKey or bearerToken, not both\");\n }\n\n this.authHeaders = hasApiKey\n ? { \"Lovable-API-Key\": options.apiKey! }\n : { Authorization: `Bearer ${options.bearerToken}` };\n\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n this.extraHeaders = options.headers ?? {};\n this.clientSource = options.clientSource ?? \"sdk\";\n\n this.typedClient = createClient<paths>({\n baseUrl: this.baseUrl,\n headers: {\n \"X-Client-Source\": this.clientSource,\n ...this.authHeaders,\n ...this.extraHeaders,\n Accept: \"application/json\",\n },\n });\n this.typedClient.use(errorMiddleware);\n }\n\n /**\n * Type-safe access to any documented API route, driven by the auto-generated\n * OpenAPI schema. Path / query params and request bodies are checked at compile\n * time; calling an unknown path is a type error.\n *\n * Non-2xx responses throw `ApiError`; on success, `data` is set on the result.\n */\n get typed(): Client<paths> {\n return this.typedClient;\n }\n\n private async rawRequest(\n method: string,\n path: string,\n body?: unknown,\n init?: { headers?: Record<string, string>; signal?: AbortSignal },\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n // init.headers can ADD per-request headers but must NOT override built-in\n // auth/client identification — spread it first so authHeaders win.\n const headers: Record<string, string> = {\n \"X-Client-Source\": this.clientSource,\n ...init?.headers,\n ...this.authHeaders,\n ...this.extraHeaders,\n Accept: \"application/json\",\n };\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: init?.signal,\n });\n\n if (!response.ok) {\n let errorBody:\n | {\n type?: string;\n title?: string;\n message?: string;\n detail?: string;\n details?: string;\n props?: Record<string, unknown>;\n }\n | undefined;\n try {\n errorBody = (await response.json()) as typeof errorBody;\n } catch {\n // Ignore JSON parse errors\n }\n\n const message = buildErrorMessage(errorBody, response.status, response.statusText);\n const type = errorBody?.type ?? errorBody?.title;\n const detail = errorBody?.detail ?? errorBody?.details;\n throw new ApiError(response.status, message, type, detail, errorBody?.props);\n }\n\n return response;\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const response = await this.rawRequest(method, path, body);\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n\n private async requestText(method: string, path: string): Promise<string> {\n const response = await this.rawRequest(method, path);\n return response.text();\n }\n\n /**\n * Get the current authenticated user and their workspaces.\n * Useful for validating an API key and discovering workspace IDs.\n */\n async me(): Promise<MeResponse> {\n const { data } = await this.typed.GET(\"/v1/me\");\n return { ...data!, workspaces: data!.workspaces ?? [] };\n }\n\n /**\n * List all workspaces the authenticated user has access to\n */\n async listWorkspaces(): Promise<WorkspaceWithMembership[]> {\n const response = await this.request<GetWorkspacesResponse>(\"GET\", \"/v1/workspaces\");\n return response.workspaces ?? [];\n }\n\n /**\n * Get a specific workspace by ID\n */\n async getWorkspace(workspaceId: string): Promise<WorkspaceWithMembership> {\n const response = await this.request<{ workspace: WorkspaceWithMembership }>(\"GET\", `/v1/workspaces/${workspaceId}`);\n return response.workspace;\n }\n\n /**\n * List projects in a workspace.\n * Supports full-text search, filtering by visibility/publish status/folder/creator,\n * and pagination via offset or cursor.\n */\n async listProjects(workspaceId: string, options?: ListProjectsOptions): Promise<ListProjectsResponse> {\n const params = new URLSearchParams();\n if (options?.query) params.set(\"q\", options.query);\n if (options?.visibility) params.set(\"visibility\", options.visibility);\n if (options?.publish_status) params.set(\"publish_status\", options.publish_status);\n if (options?.folder_id) params.set(\"folder_id\", options.folder_id);\n if (options?.user_id) params.set(\"user_id\", options.user_id);\n if (options?.sort_by) params.set(\"sort_by\", options.sort_by);\n if (options?.sort_order) params.set(\"sort_order\", options.sort_order);\n if (options?.viewed_by_me) params.set(\"viewed_by_me\", \"true\");\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined) params.set(\"offset\", String(options.offset));\n if (options?.cursor) params.set(\"cursor\", options.cursor);\n\n const query = params.toString();\n const path = `/v1/workspaces/${workspaceId}/projects${query ? `?${query}` : \"\"}`;\n\n return this.request<ListProjectsResponse>(\"GET\", path);\n }\n\n /**\n * Create a new project in a workspace\n */\n async createProject(workspaceId: string, options: CreateProjectOptions): Promise<ProjectResponse> {\n let fileRefs: UnscopedFile[] | undefined;\n if (options.uploadedFiles?.length) {\n fileRefs = options.uploadedFiles;\n } else if (options.files?.length) {\n fileRefs = await this.uploadFiles(options.files);\n }\n\n const body: CreateProjectBody = {\n description: options.description,\n template_project_id: options.templateProjectId,\n };\n if (options.visibility) {\n body.visibility = options.visibility;\n }\n if (options.techStack) {\n body.tech_stack = options.techStack;\n }\n if (options.selectedLibraries?.length) {\n body.selected_libraries = options.selectedLibraries;\n }\n\n if (options.initialMessage) {\n body.initial_message = options.initialMessage;\n }\n if (fileRefs?.length) {\n body.files = fileRefs;\n }\n\n const project = await this.request<ProjectResponse>(\"POST\", `/v1/workspaces/${workspaceId}/projects`, body);\n\n return project;\n }\n\n /**\n * Send a chat message to a project.\n *\n * The API accepts the message and processes it in the background.\n * Returns the message ID and status. Use `waitForMessageCompletion()`\n * to poll for the AI response, or `waitForResponse()` for SSE streaming.\n */\n async chat(projectId: string, options: ChatMessageOptions): Promise<SendMessageResponse> {\n let fileRefs: UnscopedFile[] | undefined;\n if (options.uploadedFiles?.length) {\n fileRefs = options.uploadedFiles;\n } else if (options.files?.length) {\n fileRefs = await this.uploadFiles(options.files);\n }\n\n const body: {\n message: string;\n files?: UnscopedFile[];\n plan_mode?: boolean;\n custom_model_endpoint?: string;\n custom_model_api_key?: string;\n custom_model_name?: string;\n custom_model_disable_race?: boolean;\n continuation?: string;\n } = {\n message: options.message,\n };\n if (fileRefs) {\n body.files = fileRefs;\n }\n if (options.planMode) {\n body.plan_mode = true;\n }\n if (options.customModel) {\n body.custom_model_endpoint = options.customModel.endpoint;\n body.custom_model_api_key = options.customModel.apiKey;\n body.custom_model_name = options.customModel.modelName;\n }\n if (options.customModelDisableRace) {\n body.custom_model_disable_race = true;\n }\n if (options.continuation) {\n body.continuation = options.continuation;\n }\n\n return this.request<SendMessageResponse>(\"POST\", `/v1/projects/${projectId}/messages`, body);\n }\n\n /**\n * Invite a user to a workspace as a collaborator\n */\n async inviteCollaborator(\n workspaceId: string,\n options: InviteCollaboratorOptions,\n ): Promise<WorkspaceMembershipResponse> {\n const body: AddUserToWorkspaceInputBody = {\n email: options.email,\n role: options.role ?? \"member\",\n };\n\n return this.request<WorkspaceMembershipResponse>(\"POST\", `/workspaces/${workspaceId}/memberships`, body);\n }\n\n /**\n * List members of a workspace\n */\n async listWorkspaceMembers(workspaceId: string): Promise<WorkspaceMembershipResponse[]> {\n const response = await this.request<{\n memberships: WorkspaceMembershipResponse[] | null;\n }>(\"GET\", `/workspaces/${workspaceId}/memberships`);\n return response.memberships ?? [];\n }\n\n /**\n * Remove a member from a workspace\n */\n async removeWorkspaceMember(workspaceId: string, userId: string): Promise<void> {\n await this.request<void>(\"DELETE\", `/workspaces/${workspaceId}/memberships/${userId}`);\n }\n\n /**\n * Get project details by ID\n */\n async getProject(projectId: string): Promise<ProjectResponse> {\n return this.request<ProjectResponse>(\"GET\", `/v1/projects/${projectId}`);\n }\n\n /**\n * Get the preview URL for a project.\n *\n * The preview URL is available once the project reaches \"completed\" status.\n * This URL allows viewing the project in development mode.\n *\n * @param projectId - The project ID\n * @returns The preview URL\n */\n getPreviewUrl(projectId: string): string {\n return `https://id-preview--${projectId}.lovable.app`;\n }\n\n /**\n * Get the published URL for a project (if published).\n *\n * Returns the public URL if the project has been published, or null if not.\n *\n * @param projectId - The project ID\n * @returns The published URL or null if not published\n */\n async getPublishedUrl(projectId: string): Promise<string | null> {\n const project = await this.getProject(projectId);\n return project.is_published && project.url ? project.url : null;\n }\n\n /**\n * Get the cloud database status for a project.\n *\n * @param projectId - The project ID\n * @returns Whether the database is enabled and which stack is used\n */\n async getDatabaseStatus(projectId: string): Promise<DatabaseStatus> {\n return this.request<DatabaseStatus>(\"GET\", `/v1/projects/${projectId}/database`);\n }\n\n /**\n * Enable (provision) a cloud database for a project.\n *\n * This triggers database provisioning which takes 30-60 seconds.\n * The call blocks until provisioning completes.\n *\n * @param projectId - The project ID\n * @returns The database status after enablement\n */\n async enableDatabase(projectId: string): Promise<EnableDatabaseResult> {\n return this.request<EnableDatabaseResult>(\"POST\", `/v1/projects/${projectId}/database/enable`);\n }\n\n /**\n * Execute a SQL query against the project's cloud database.\n *\n * Supports SELECT, INSERT, UPDATE, DELETE, and DDL statements.\n * The database must be enabled first (see enableDatabase).\n *\n * @param projectId - The project ID\n * @param sql - SQL query to execute\n * @returns Query result rows as JSON objects\n */\n async queryDatabase(projectId: string, sql: string): Promise<DatabaseQueryResult> {\n return this.request<DatabaseQueryResult>(\"POST\", `/v1/projects/${projectId}/database/query`, { sql });\n }\n\n // ---------------------------------------------------------------------------\n // Messages\n // ---------------------------------------------------------------------------\n\n /**\n * Get a message by ID. Returns the message content, status, and (for user messages)\n * the AI response if available. Use to poll for completion after `chat()`.\n */\n async getMessage(projectId: string, messageId: string): Promise<GetMessageResponse> {\n return this.request<GetMessageResponse>(\"GET\", `/v1/projects/${projectId}/messages/${messageId}`);\n }\n\n /**\n * List recent messages in a project, newest first. Use `before` (a message ID\n * from a prior page) to paginate backwards through history.\n */\n async listMessages(projectId: string, params?: { limit?: number; before?: string }): Promise<ListMessagesResponse> {\n const qs = new URLSearchParams();\n if (params?.limit !== undefined) qs.set(\"limit\", String(params.limit));\n if (params?.before) qs.set(\"before\", params.before);\n const suffix = qs.toString() ? `?${qs.toString()}` : \"\";\n return this.request<ListMessagesResponse>(\"GET\", `/v1/projects/${projectId}/messages${suffix}`);\n }\n\n /**\n * Poll for message completion. Waits until the AI response reaches a terminal\n * status (completed, stopped) or the timeout expires.\n *\n * Handles edge cases: 404 grace period for race conditions between queue\n * dequeue and event creation, and queue pause detection.\n */\n async waitForMessageCompletion(\n projectId: string,\n messageId: string,\n options?: MessageCompletionOptions,\n ): Promise<MessageCompletionResult> {\n const pollInterval = options?.pollInterval ?? 3000;\n const timeout = options?.timeout ?? 600_000;\n const deadline = Date.now() + timeout;\n let notFoundSince: number | null = null;\n const notFoundGraceMs = 15_000;\n\n while (Date.now() < deadline) {\n try {\n const msg = await this.getMessage(projectId, messageId);\n notFoundSince = null;\n\n if (msg.status === \"queued\") {\n if (msg.queue_paused && msg.queue_pause_reason !== \"hitl_tool\") {\n return {\n status: \"error\",\n message_id: messageId,\n content: \"\",\n error:\n `Message is queued (position ${msg.queue_position ?? \"unknown\"}) but the queue is paused` +\n (msg.queue_pause_reason ? ` (reason: ${msg.queue_pause_reason})` : \"\") +\n `. Unpause the queue in the Lovable editor, or use wait=false to return immediately.`,\n };\n }\n await sleep(pollInterval);\n continue;\n }\n\n const ai = msg.response;\n if (ai) {\n if (ai.status === \"completed\" || ai.status === \"stopped\") {\n return {\n status: ai.status === \"completed\" ? \"completed\" : \"error\",\n message_id: ai.message_id,\n content: ai.content,\n edit_id: ai.edit_id,\n commit_sha: ai.commit_sha,\n summary: ai.summary,\n cost_credits: ai.cost_credits,\n };\n }\n }\n\n if (msg.role === \"assistant\") {\n if (msg.status === \"completed\" || msg.status === \"stopped\") {\n return {\n status: msg.status === \"completed\" ? \"completed\" : \"error\",\n message_id: msg.message_id,\n content: msg.content,\n edit_id: msg.edit_id,\n commit_sha: msg.commit_sha,\n summary: msg.summary,\n cost_credits: msg.cost_credits,\n };\n }\n }\n\n await sleep(pollInterval);\n } catch (err) {\n if (err instanceof ApiError && err.status === 404) {\n if (notFoundSince === null) {\n notFoundSince = Date.now();\n }\n if (Date.now() - notFoundSince < notFoundGraceMs) {\n await sleep(pollInterval);\n continue;\n }\n return {\n status: \"error\",\n message_id: messageId,\n content: \"\",\n error: \"Message not found. It may have been deleted from the queue.\",\n };\n }\n await sleep(pollInterval);\n }\n }\n\n return {\n status: \"timeout\",\n message_id: messageId,\n content: \"\",\n error: `Agent did not finish within ${timeout / 1000}s`,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Knowledge\n // ---------------------------------------------------------------------------\n\n /** Get workspace knowledge (custom instructions for the AI agent). */\n async getWorkspaceKnowledge(workspaceId: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/knowledge\", {\n params: { path: { workspace_id: workspaceId } },\n });\n return data!;\n }\n\n /** Set workspace knowledge. Max 10,000 characters. */\n async setWorkspaceKnowledge(workspaceId: string, content: string): Promise<KnowledgeResponse> {\n return this.request<KnowledgeResponse>(\"PUT\", `/v1/workspaces/${workspaceId}/knowledge`, { content });\n }\n\n // ---------------------------------------------------------------------------\n // Workspace skills\n // ---------------------------------------------------------------------------\n\n /** List workspace skills. */\n async listWorkspaceSkills(\n workspaceId: string,\n options?: { includeMarkdown?: boolean },\n ): Promise<ListWorkspaceSkillsResponse> {\n const qs = new URLSearchParams();\n if (options?.includeMarkdown) qs.set(\"include_markdown\", \"true\");\n const suffix = qs.toString() ? `?${qs.toString()}` : \"\";\n return this.request<ListWorkspaceSkillsResponse>(\"GET\", `/v1/workspaces/${workspaceId}/skills${suffix}`);\n }\n\n /** Get a single workspace skill, including SKILL.md contents. */\n async getWorkspaceSkill(workspaceId: string, skillName: string): Promise<WorkspaceSkillResponse> {\n return this.request<WorkspaceSkillResponse>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/skills/${encodeURIComponent(skillName)}`,\n );\n }\n\n /** Create a workspace skill from full SKILL.md markdown. */\n async createWorkspaceSkill(\n workspaceId: string,\n skillName: string,\n markdown: string,\n ): Promise<WorkspaceSkillWriteResponse> {\n return this.request<WorkspaceSkillWriteResponse>(\n \"POST\",\n `/v1/workspaces/${workspaceId}/skills/${encodeURIComponent(skillName)}`,\n { markdown },\n );\n }\n\n /** Update a workspace skill by replacing its SKILL.md markdown. */\n async updateWorkspaceSkill(\n workspaceId: string,\n skillName: string,\n markdown: string,\n ): Promise<WorkspaceSkillWriteResponse> {\n return this.request<WorkspaceSkillWriteResponse>(\n \"PUT\",\n `/v1/workspaces/${workspaceId}/skills/${encodeURIComponent(skillName)}`,\n { markdown },\n );\n }\n\n /** Delete a workspace skill. */\n async deleteWorkspaceSkill(workspaceId: string, skillName: string): Promise<WorkspaceSkillDeleteResponse> {\n return this.request<WorkspaceSkillDeleteResponse>(\n \"DELETE\",\n `/v1/workspaces/${workspaceId}/skills/${encodeURIComponent(skillName)}`,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Project skills\n // ---------------------------------------------------------------------------\n\n /** List project skills, including whether each skill is enabled. */\n async listProjectSkills(projectId: string): Promise<ListProjectSkillsResponse> {\n return this.request<ListProjectSkillsResponse>(\"GET\", `/v1/projects/${projectId}/skills`);\n }\n\n /** Enable or disable a project skill without removing it from the project repo. */\n async setProjectSkillEnabled(projectId: string, skillName: string, enabled: boolean): Promise<ProjectSkillResponse> {\n return this.request<ProjectSkillResponse>(\n \"PUT\",\n `/v1/projects/${projectId}/skills/${encodeURIComponent(skillName)}/enabled`,\n { enabled },\n );\n }\n\n /** Get project knowledge (custom instructions for the AI agent). */\n async getProjectKnowledge(projectId: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.GET(\"/v1/projects/{project_id}/knowledge\", {\n params: { path: { project_id: projectId } },\n });\n return data!;\n }\n\n /** Set project knowledge. Max 10,000 characters. */\n async setProjectKnowledge(projectId: string, content: string): Promise<KnowledgeResponse> {\n return this.request<KnowledgeResponse>(\"PUT\", `/v1/projects/${projectId}/knowledge`, { content });\n }\n\n // ---------------------------------------------------------------------------\n // Git operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get the structured diff for a message or commit.\n * Pass `messageId` to get the diff for a specific AI message,\n * or `sha` for a specific commit.\n */\n async getDiff(\n projectId: string,\n params: { messageId?: string; sha?: string; baseSha?: string },\n ): Promise<GitDiffResponse> {\n const qs = new URLSearchParams();\n if (params.messageId) qs.set(\"message_id\", params.messageId);\n if (params.sha) qs.set(\"sha\", params.sha);\n if (params.baseSha) qs.set(\"base_sha\", params.baseSha);\n return this.request<GitDiffResponse>(\"GET\", `/v1/projects/${projectId}/git/diff?${qs.toString()}`);\n }\n\n /** List all files in a project at a specific git ref. */\n async listFiles(projectId: string, ref: string): Promise<GitFilesResponse> {\n const qs = new URLSearchParams({ ref });\n return this.request<GitFilesResponse>(\"GET\", `/v1/projects/${projectId}/git/files?${qs.toString()}`);\n }\n\n /** Read the raw content of a single file at a specific git ref. Returns text. */\n async readFile(projectId: string, path: string, ref: string): Promise<string> {\n const qs = new URLSearchParams({ path, ref });\n return this.requestText(\"GET\", `/v1/projects/${projectId}/git/file?${qs.toString()}`);\n }\n\n // ---------------------------------------------------------------------------\n // Edits\n // ---------------------------------------------------------------------------\n\n /** List the edit history of a project. */\n async listEdits(projectId: string, params?: { limit?: number; before?: string }): Promise<EditsResponse> {\n const qs = new URLSearchParams();\n if (params?.limit !== undefined) qs.set(\"limit\", String(params.limit));\n if (params?.before) qs.set(\"before\", params.before);\n const suffix = qs.toString() ? `?${qs.toString()}` : \"\";\n return this.request<EditsResponse>(\"GET\", `/v1/projects/${projectId}/edits${suffix}`);\n }\n\n // ---------------------------------------------------------------------------\n // File upload\n // ---------------------------------------------------------------------------\n\n /** Get a presigned URL for uploading a file. Returns the upload URL and file ID. */\n async getFileUploadUrl(params: { file_name: string; content_type?: string }): Promise<FileUploadUrlResponse> {\n return this.request<FileUploadUrlResponse>(\"POST\", \"/v1/files/upload-url\", params);\n }\n\n // ---------------------------------------------------------------------------\n // Visibility\n // ---------------------------------------------------------------------------\n\n /** Set a project's visibility (draft, private, or public). */\n async setProjectVisibility(projectId: string, visibility: string): Promise<{ visibility: string }> {\n return this.request<{ visibility: string }>(\"PUT\", `/v1/projects/${projectId}/visibility`, { visibility });\n }\n\n /** Set a folder's visibility (personal or workspace). */\n async setFolderVisibility(\n workspaceId: string,\n folderId: string,\n visibility: string,\n ): Promise<{ visibility: string }> {\n return this.request<{ visibility: string }>(\"PUT\", `/v1/workspaces/${workspaceId}/folders/${folderId}/visibility`, {\n visibility,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Library & template projects\n // ---------------------------------------------------------------------------\n\n /** List available design system library projects in a workspace. */\n async listLibraryProjects(workspaceId: string): Promise<{ libraries: LibraryProjectResponse[] }> {\n return this.request<{ libraries: LibraryProjectResponse[] }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/available-library-projects`,\n );\n }\n\n /** List available template projects in a workspace. */\n async listTemplateProjects(workspaceId: string): Promise<{ templates: TemplateProjectResponse[] }> {\n return this.request<{ templates: TemplateProjectResponse[] }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/available-template-projects`,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Connectors (MCP servers)\n // ---------------------------------------------------------------------------\n\n /** List all connectors in a workspace. */\n async listConnectors(workspaceId: string): Promise<{ connectors: ConnectorResponse[] }> {\n return this.request<{ connectors: ConnectorResponse[] }>(\"GET\", `/v1/workspaces/${workspaceId}/connectors`);\n }\n\n /** Add a connector to a workspace. The server URL is tested before saving. */\n async addConnector(workspaceId: string, body: AddConnectorBody): Promise<ConnectorResponse> {\n return this.request<ConnectorResponse>(\"POST\", `/v1/workspaces/${workspaceId}/connectors`, body);\n }\n\n /** Remove a connector from a workspace. */\n async removeConnector(workspaceId: string, connectorId: string): Promise<{ success: boolean }> {\n return this.request<{ success: boolean }>(\"DELETE\", `/v1/workspaces/${workspaceId}/connectors/${connectorId}`);\n }\n\n /** Browse available connector templates. */\n async listAvailableConnectors(workspaceId: string): Promise<{ catalog: AvailableConnectorEntry[] }> {\n return this.request<{ catalog: AvailableConnectorEntry[] }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/available-connectors`,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Connectors\n // ---------------------------------------------------------------------------\n\n /** List standard (OAuth-based) connectors in a workspace. */\n async listStandardConnectors(workspaceId: string): Promise<{ connectors: StandardConnectorItem[] }> {\n return this.request<{ connectors: StandardConnectorItem[] }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/connectors/standard`,\n );\n }\n\n /** List seamless (zero-config) connectors in a workspace. */\n async listSeamlessConnectors(workspaceId: string): Promise<{ connectors: SeamlessConnectorItem[] }> {\n return this.request<{ connectors: SeamlessConnectorItem[] }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/connectors/seamless`,\n );\n }\n\n /** List MCP connectors in a workspace. */\n async listMCPConnectors(workspaceId: string): Promise<{ connectors: MCPConnectorItem[]; custom_enabled: boolean }> {\n return this.request<{ connectors: MCPConnectorItem[]; custom_enabled: boolean }>(\n \"GET\",\n `/v1/workspaces/${workspaceId}/connectors/mcp`,\n );\n }\n\n /** List authenticated connections (accounts) in a workspace. */\n async listConnections(\n workspaceId: string,\n params?: { connector_id?: string },\n ): Promise<{ connections: ConnectionItem[] }> {\n const qs = new URLSearchParams();\n if (params?.connector_id) qs.set(\"connector_id\", params.connector_id);\n const suffix = qs.toString() ? `?${qs.toString()}` : \"\";\n return this.request<{ connections: ConnectionItem[] }>(\"GET\", `/v1/workspaces/${workspaceId}/connections${suffix}`);\n }\n\n // ---------------------------------------------------------------------------\n // Analytics\n // ---------------------------------------------------------------------------\n\n /** Get historical analytics for a published project. */\n async getProjectAnalytics(\n projectId: string,\n params: { startDate: string; endDate: string; granularity?: string },\n ): Promise<ProjectAnalyticsResponse> {\n const qs = new URLSearchParams({\n startDate: params.startDate,\n endDate: params.endDate,\n });\n if (params.granularity) qs.set(\"granularity\", params.granularity);\n return this.request<ProjectAnalyticsResponse>(\"GET\", `/v1/projects/${projectId}/analytics?${qs.toString()}`);\n }\n\n /** Get real-time visitor trend for a published project. */\n async getProjectAnalyticsTrend(projectId: string): Promise<ProjectAnalyticsTrendResponse> {\n return this.request<ProjectAnalyticsTrendResponse>(\"GET\", `/v1/projects/${projectId}/analytics/trend`);\n }\n\n /**\n * Publish a project.\n *\n * This triggers a deployment which makes the project publicly accessible.\n * The deployment runs asynchronously - use waitForProjectPublished() to wait for completion.\n *\n * @param projectId - The project ID to publish\n * @param options.name - Optional custom slug for the published URL\n * @returns Deployment info including deployment ID\n */\n async publish(projectId: string, options?: { name?: string }): Promise<DeploymentResponse> {\n return this.request<DeploymentResponse>(\"POST\", `/v1/projects/${projectId}/deployments`, {\n name: options?.name,\n });\n }\n\n /**\n * Remix (fork) an existing project, optionally at a specific message point in time.\n *\n * When `messageId` is provided, the remix captures the project state as it was\n * just before that message was processed (default). Set `remixMode: \"including\"`\n * to include the message and its AI response in the remix.\n * Without `messageId`, the full current state is remixed.\n *\n * @param sourceProjectId - The project to remix from\n * @param options.workspaceId - Target workspace for the new project\n * @param options.messageId - Optional message ID to snapshot at\n * @param options.remixMode - \"before\" (default): state before the message; \"including\": state after the message and its AI response\n * @param options.includeHistory - Whether to preserve chat history (default: false)\n * @param options.includeCustomKnowledge - Whether to copy custom instructions (default: false)\n * @param options.initialMessage - Optional initial message to send after remix\n * @returns The remix job ID for polling progress\n */\n async remixProject(sourceProjectId: string, options: RemixProjectOptions): Promise<string> {\n const body: RemixInitBody = {\n workspace_id: options.workspaceId,\n include_history: options.includeHistory,\n include_custom_knowledge: options.includeCustomKnowledge,\n project_name: options.projectName,\n skip_initial_remix_message: options.skipInitialRemixMessage,\n skip_integrations: options.skipIntegrations,\n };\n\n if (options.messageId) {\n body.message_id = options.messageId;\n body.remix_mode = options.remixMode ?? \"before\";\n }\n\n if (options.initialMessage) {\n body.initial_message = {\n id: crypto.randomUUID(),\n message: options.initialMessage,\n chat_only: false,\n headless: true,\n };\n }\n\n const response = await this.request<RemixInitResponse>(\"POST\", `/v1/projects/${sourceProjectId}/remix/init`, body);\n return response.job_id;\n }\n\n /**\n * Wait for a remix operation to complete.\n *\n * Polls the remix progress endpoint until the job reaches \"completed\" or \"error\" status.\n *\n * @param sourceProjectId - The source project ID (used for the progress endpoint)\n * @param jobId - The job ID returned by `remixProject()`\n * @param options.pollInterval - Time between polls in ms (default: 2000)\n * @param options.timeout - Maximum time to wait in ms (default: 300000 = 5 minutes)\n * @param options.onProgress - Optional callback for status/step updates\n * @returns The new project ID\n * @throws Error if the remix fails or timeout is reached\n */\n async waitForRemix(sourceProjectId: string, jobId: string, options?: RemixWaitOptions): Promise<RemixResult> {\n const pollInterval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300000;\n const startTime = Date.now();\n\n while (true) {\n const progress = await this.request<RemixProgressResponse>(\n \"GET\",\n `/v1/projects/${sourceProjectId}/remix/progress?job_id=${encodeURIComponent(jobId)}`,\n );\n\n options?.onProgress?.(progress.status, progress.step);\n\n if (progress.status === \"completed\" && progress.result) {\n return { projectId: progress.result.project_id };\n }\n\n if (progress.status === \"error\") {\n throw new Error(progress.error_message ?? \"Remix failed\");\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for remix of project ${sourceProjectId}`);\n }\n\n await sleep(pollInterval);\n }\n }\n\n /**\n * Wait for a project to reach \"completed\" status.\n *\n * Projects start in \"in_progress\" status while being created/built.\n * This method polls until the status becomes \"completed\" or \"failed\".\n * A successful completion means the project's preview is ready to view.\n *\n * @param projectId - The project ID to wait for\n * @param options.pollInterval - Time between polls in ms (default: 2000)\n * @param options.timeout - Maximum time to wait in ms (default: 300000 = 5 minutes)\n * @param options.onProgress - Optional callback for status updates\n * @returns The completed project\n * @throws Error if project fails or timeout is reached\n */\n async waitForProjectReady(projectId: string, options?: WaitOptions): Promise<ProjectResponse> {\n const pollInterval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300000;\n const startTime = Date.now();\n\n while (true) {\n const project = await this.getProject(projectId);\n options?.onProgress?.(project);\n\n if (project.status === \"completed\") {\n return project;\n }\n\n if (project.status === \"failed\") {\n throw new Error(`Project ${projectId} failed to build`);\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for project ${projectId} to be ready`);\n }\n\n await sleep(pollInterval);\n }\n }\n\n /**\n * Wait for the AI response to a chat message.\n *\n * Connects to the project's message stream (SSE) and accumulates the\n * response content until the message is complete. Returns the full\n * response text along with the project's preview URL.\n *\n * Use this after `chat()` or after `createProject()` with `initialMessage`.\n *\n * @param projectId - The project ID to listen for\n * @param options.timeout - Maximum time to wait in ms (default: 300000 = 5 minutes)\n * @returns The AI response content and preview URL\n * @throws Error if the stream fails or timeout is reached\n */\n async waitForResponse(projectId: string, options?: ChatResponseOptions): Promise<ChatResponse> {\n const timeout = options?.timeout ?? 300000;\n const url = `${this.baseUrl}/v1/projects/${projectId}/messages/stream`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n headers: {\n ...this.authHeaders,\n ...this.extraHeaders,\n },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new ApiError(response.status, `Failed to connect to message stream: HTTP ${response.status}`);\n }\n\n if (!response.body) {\n throw new Error(\"Response body is not readable\");\n }\n\n const result = await this.consumeSSEStream(response.body);\n return {\n content: result.content,\n messageId: result.messageId,\n previewUrl: this.getPreviewUrl(projectId),\n };\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new Error(`Timeout waiting for response on project ${projectId}`);\n }\n throw err;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private isFileInput(file: File | FileInput): file is FileInput {\n return \"data\" in file;\n }\n\n private async uploadFile(file: File | FileInput): Promise<UnscopedFile> {\n const fileName = this.isFileInput(file) ? file.name : file.name;\n const mimeType = this.isFileInput(file) ? file.type : file.type;\n const body = this.isFileInput(file) ? file.data : file;\n\n const { url, file_id: objectPath } = await this.request<{ url: string; file_id: string }>(\n \"POST\",\n \"/v1/files/upload-url\",\n {\n file_name: fileName,\n content_type: mimeType,\n },\n );\n\n const uploadResponse = await fetch(url, {\n method: \"PUT\",\n body,\n headers: { \"Content-Type\": mimeType },\n });\n if (!uploadResponse.ok) {\n throw new Error(`File upload failed for \"${fileName}\": HTTP ${uploadResponse.status}`);\n }\n\n return { file_id: objectPath, type: \"user_upload\", file_name: fileName, mime_type: mimeType };\n }\n\n private async uploadFiles(files: (File | FileInput)[]): Promise<UnscopedFile[]> {\n return Promise.all(files.map((file) => this.uploadFile(file)));\n }\n\n private async consumeSSEStream(body: ReadableStream<Uint8Array>): Promise<{ content: string; messageId: string }> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let content = \"\";\n let messageId = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n if (!part.trim()) continue;\n\n const lines = part.split(\"\\n\");\n let eventType = \"\";\n let eventData = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event: \")) {\n eventType = line.slice(7);\n } else if (line.startsWith(\"data: \")) {\n eventData = line.slice(6);\n }\n }\n\n if (eventType === \"message\" && eventData) {\n try {\n const data = JSON.parse(eventData);\n if (typeof data.content === \"string\") {\n content += data.content;\n }\n if (typeof data.message_id === \"string\" && data.message_id) {\n messageId = data.message_id;\n }\n if (data.is_final) {\n return { content, messageId };\n }\n } catch {\n // Skip non-JSON data lines\n }\n }\n\n if (eventType === \"error\") {\n let detail = \"Stream error from server\";\n try {\n const data = JSON.parse(eventData);\n if (data.message) detail = data.message;\n } catch {\n // use default message\n }\n throw new Error(detail);\n }\n }\n }\n } finally {\n void reader.cancel();\n }\n\n return { content, messageId };\n }\n\n /**\n * Wait for a project to be published (deployed).\n *\n * This method polls until the project has `is_published: true` and a `url`.\n *\n * @param projectId - The project ID to wait for\n * @param options.pollInterval - Time between polls in ms (default: 3000)\n * @param options.timeout - Maximum time to wait in ms (default: 600000 = 10 minutes)\n * @param options.onProgress - Optional callback for status updates\n * @returns The published project with URL\n * @throws Error if timeout is reached\n */\n async waitForProjectPublished(projectId: string, options?: WaitOptions): Promise<ProjectResponse> {\n const pollInterval = options?.pollInterval ?? 3000;\n const timeout = options?.timeout ?? 600000;\n const startTime = Date.now();\n\n while (true) {\n const project = await this.getProject(projectId);\n options?.onProgress?.(project);\n\n if (project.is_published && project.url) {\n return project;\n }\n\n if (project.status === \"failed\") {\n throw new Error(`Project ${projectId} failed to build`);\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for project ${projectId} to be published`);\n }\n\n await sleep(pollInterval);\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// Type definitions for the Lovable SDK\n// These are self-contained and don't require external dependencies\n\nexport type ProjectVisibility = \"draft\" | \"private\" | \"public\";\nexport type MemberRole = \"admin\" | \"collaborator\" | \"invited\" | \"member\" | \"none\" | \"owner\" | \"viewer\";\nexport type ProjectStatus = \"completed\" | \"in_progress\" | \"failed\";\n\nexport interface MeWorkspace {\n id: string;\n name: string;\n role: string;\n}\n\nexport interface MeResponse {\n id: string;\n email: string;\n name: string;\n workspaces: MeWorkspace[];\n}\n\nexport interface WorkspaceMembership {\n email: string;\n invited_at?: string;\n joined_at?: string;\n monthly_credit_limit: number | null;\n project_access?: Record<string, { access_level?: string }>;\n role: MemberRole;\n user_id: string;\n workspace_id: string;\n}\n\nexport interface WorkspaceWithMembership {\n id: string;\n name: string;\n description?: string;\n image_url?: string;\n owner_id?: string;\n is_personal?: boolean;\n plan?: string;\n plan_type?: string;\n num_projects: number;\n num_seats?: number;\n membership: WorkspaceMembership;\n created_at: string;\n updated_at: string;\n deleted_at?: string;\n credits_granted: number;\n credits_used: number;\n daily_credits_limit: number;\n daily_credits_used: number;\n billing_period_credits_limit: number;\n billing_period_credits_used: number;\n billing_period_start_date?: string;\n billing_period_end_date?: string;\n rollover_credits_limit: number;\n rollover_credits_used: number;\n topup_credits_limit: number;\n topup_credits_used: number;\n total_credits_used: number;\n subscription_status?:\n | \"active\"\n | \"canceled\"\n | \"incomplete_expired\"\n | \"incomplete\"\n | \"past_due\"\n | \"paused\"\n | \"trialing\"\n | \"unpaid\";\n referral_code?: string;\n short_referral_code?: string;\n referral_count: number;\n followers_count: number;\n default_project_visibility?: ProjectVisibility;\n default_project_publish_visibility?: \"private\" | \"public\";\n mcp_enabled?: boolean;\n}\n\nexport interface WorkspaceMembershipResponse {\n user_id: string;\n username: string;\n display_name?: string;\n email?: string;\n role: MemberRole;\n invited_at?: string;\n joined_at?: string;\n monthly_credit_limit?: number;\n total_credits_used?: number;\n total_credits_used_in_billing_period?: number;\n project_access?: Record<string, { access_level?: string }>;\n}\n\n/**\n * Project response from the API.\n *\n * The v1 endpoints (getProject, createProject) return a lean subset:\n * id, workspace_id, name, display_name, description, status, visibility,\n * is_published, url. Other fields are available from list endpoints.\n */\nexport interface ProjectResponse {\n id: string;\n name?: string;\n display_name?: string;\n description?: string;\n tech_stack?: string;\n status?: string;\n visibility?: ProjectVisibility;\n publish_visibility?: \"private\" | \"public\";\n is_published?: boolean;\n /** Present in create project response when initial_message was provided */\n message_id?: string;\n is_starred?: boolean;\n is_template?: boolean;\n is_github?: boolean;\n is_supabase_enabled?: boolean;\n url?: string;\n /**\n * Preview URL with a short-lived signed token (`?__lovable_token=…`) that\n * authenticates an iframe load without an in-iframe Lovable login. Use this\n * to embed the running app inside a partner UI. Token TTL is 1 hour.\n */\n embed_url?: string;\n og_image_url?: string;\n latest_screenshot_url?: string;\n user_id?: string;\n user_display_name?: string;\n user_photo_url?: string;\n created_at?: string;\n created_by?: string;\n updated_at?: string;\n deleted_at?: string;\n last_edited_at?: string;\n last_viewed_at?: string;\n published_at?: string;\n workspace_id?: string;\n folder_id?: string;\n category?: string;\n edit_count?: number;\n gen_count?: number;\n user_message_count?: number;\n remix_count?: number;\n remixed_from_project_id?: string;\n template_project_id?: string;\n credit_total?: number;\n custom_instructions?: string;\n main_branch?: string;\n latest_commit_sha?: string;\n github_repo_name?: string;\n github_repo_id?: number;\n deployment_target?: string;\n active_deployment_job_id?: string;\n environments_enabled?: boolean;\n hide_badge?: boolean | null;\n featured?: boolean;\n featured_at?: string;\n feature_rank?: number;\n feature_source?: string;\n}\n\nexport interface UnscopedFile {\n file_id: string;\n type: \"user_upload\";\n file_name?: string;\n mime_type?: string;\n}\n\nexport interface FileInput {\n name: string;\n data: Blob | ArrayBuffer | Uint8Array;\n type: string;\n}\n\n/**\n * Configuration to use a custom OpenAI-compatible model as the main agent.\n */\nexport interface CustomModelConfig {\n /** Base URL of the OpenAI-compatible API (e.g. \"https://my-vllm.example.com/v1\") */\n endpoint: string;\n /** API key for the custom endpoint */\n apiKey: string;\n /** Model identifier sent in the request (e.g. \"my-org/my-model-id\") */\n modelName: string;\n}\n\nexport interface ChatRequest {\n id: string;\n message: string;\n chat_only: boolean;\n headless: boolean;\n ai_message_id?: string;\n intent?: string;\n model?: string;\n temperature?: number;\n current_page?: string;\n view?: string;\n view_description?: string;\n prev_session_id?: string;\n is_creation?: boolean;\n files?: UnscopedFile[];\n custom_model_endpoint?: string;\n custom_model_api_key?: string;\n custom_model_name?: string;\n custom_model_disable_race?: boolean;\n}\n\nexport interface CreateProjectBody {\n description: string;\n tech_stack?: string;\n visibility?: ProjectVisibility;\n template_project_id?: string;\n initial_message?: string;\n files?: UnscopedFile[];\n selected_libraries?: { project_id: string }[];\n category?: string;\n project_type?: string;\n prompt_name?: string;\n selected_theme?: string;\n env_vars?: Record<string, string>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AddUserToWorkspaceInputBody {\n email: string;\n role?: MemberRole;\n}\n\nexport interface GetWorkspacesResponse {\n workspaces: WorkspaceWithMembership[] | null;\n}\n\nexport interface GetWorkspaceProjectsResponse {\n projects: ProjectResponse[] | null;\n}\n\nexport interface CreateProjectOptions {\n description: string;\n techStack?: string;\n visibility?: ProjectVisibility;\n templateProjectId?: string;\n initialMessage?: string;\n /** Files to upload and attach to the initial message. The SDK handles uploading. */\n files?: (File | FileInput)[];\n /** Pre-uploaded file references to attach to the initial message. Skips upload. */\n uploadedFiles?: UnscopedFile[];\n /** Design system library projects to connect to the new project. */\n selectedLibraries?: { project_id: string }[];\n}\n\nexport interface InviteCollaboratorOptions {\n email: string;\n role?: MemberRole;\n}\n\n/**\n * Controls prompt cache continuation behavior for a message.\n *\n * - `\"force\"` — skip cache TTL and token/criteria checks (force continuation)\n * - `\"fresh_build\"` — force a full prompt rebuild from scratch\n * - `\"allow_expired_cache\"` — skip cache TTL check but respect token/criteria limits\n *\n * Omit for default behavior (5-min TTL, token and criteria checks apply).\n */\nexport type ContinuationOverride = \"force\" | \"fresh_build\" | \"allow_expired_cache\";\n\nexport interface ChatMessageOptions {\n message: string;\n /** Files to upload and attach. The SDK handles uploading them first. */\n files?: (File | FileInput)[];\n /** Pre-uploaded file references (already uploaded via getFileUploadUrl). Skips upload. */\n uploadedFiles?: UnscopedFile[];\n /** Enable plan mode: the agent discusses and plans without editing code. */\n planMode?: boolean;\n customModel?: CustomModelConfig;\n /**\n * When true, the server may skip staggered inference racing for that request if your\n * custom model endpoint supports it; otherwise the request fails with a validation error.\n * API key authentication only. Sent as `custom_model_disable_race` in the JSON body.\n */\n customModelDisableRace?: boolean;\n /**\n * Override continuation behavior for this message.\n * Controls whether the agent reuses the prompt cache or rebuilds from scratch.\n */\n continuation?: ContinuationOverride;\n}\n\nexport interface LovableClientOptions {\n /** API key for authentication (mutually exclusive with bearerToken) */\n apiKey?: string;\n /** Bearer token for OAuth authentication (mutually exclusive with apiKey) */\n bearerToken?: string;\n baseUrl?: string;\n /** Additional headers to include on every request */\n headers?: Record<string, string>;\n /**\n * Identifier for the originating client, sent as the `X-Client-Source` header.\n * Used by the API to tag audit logs and observability with the message origin.\n * Defaults to `\"sdk\"`. The Go API allowlist accepts `\"mcp\"`, `\"sdk\"`, `\"cli\"`.\n */\n clientSource?: string;\n}\n\nexport interface LovableError extends Error {\n status: number;\n type?: string;\n detail?: string;\n}\n\nexport interface WaitOptions {\n pollInterval?: number;\n timeout?: number;\n onProgress?: (project: ProjectResponse) => void;\n}\n\nexport interface DeploymentResponse {\n status: string;\n deployment_id?: string;\n url?: string;\n}\n\nexport interface ChatResponse {\n content: string;\n previewUrl: string;\n messageId: string;\n}\n\nexport interface ChatResponseOptions {\n timeout?: number;\n}\n\n// --- Remix types ---\n\nexport type RemixJobStatus = \"unknown\" | \"preparing\" | \"running\" | \"completed\" | \"error\";\n\nexport type RemixJobStep =\n | \"starting\"\n | \"creating_new_project\"\n | \"restoring_supabase\"\n | \"copying_history\"\n | \"preparing_repository\"\n | \"remixing_integration\"\n | \"pushing_repository\"\n | \"finalizing\"\n | \"completed\";\n\nexport interface RemixJobStepInfo {\n step: RemixJobStep;\n integration_name?: string;\n status?: string;\n}\n\nexport type RemixMode = \"before\" | \"including\";\n\nexport interface RemixProjectOptions {\n workspaceId: string;\n messageId?: string;\n remixMode?: RemixMode;\n includeHistory?: boolean;\n includeCustomKnowledge?: boolean;\n initialMessage?: string;\n projectName?: string;\n skipInitialRemixMessage?: boolean;\n skipIntegrations?: boolean;\n}\n\nexport interface RemixInitBody {\n workspace_id: string;\n message_id?: string;\n remix_mode?: RemixMode;\n include_history?: boolean;\n include_custom_knowledge?: boolean;\n initial_message?: ChatRequest;\n project_name?: string;\n skip_initial_remix_message?: boolean;\n skip_integrations?: boolean;\n}\n\nexport interface RemixInitResponse {\n job_id: string;\n}\n\nexport interface RemixProgressResult {\n project_id: string;\n}\n\nexport interface RemixProgressResponse {\n status: RemixJobStatus;\n step?: RemixJobStepInfo;\n error_message?: string;\n result?: RemixProgressResult;\n}\n\nexport interface RemixResult {\n projectId: string;\n}\n\nexport interface RemixWaitOptions {\n pollInterval?: number;\n timeout?: number;\n onProgress?: (status: RemixJobStatus, step?: RemixJobStepInfo) => void;\n}\n\n// --- Database types ---\n\nexport interface DatabaseStatus {\n enabled: boolean;\n stack?: string;\n}\n\nexport interface EnableDatabaseResult {\n enabled: boolean;\n stack: string;\n}\n\nexport interface DatabaseQueryResult {\n rows: Record<string, unknown>[] | null;\n}\n\n// --- API Error ---\n\nexport class ApiError extends Error {\n readonly status: number;\n readonly type?: string;\n readonly detail?: string;\n readonly props?: Record<string, unknown>;\n\n constructor(status: number, message: string, type?: string, detail?: string, props?: Record<string, unknown>) {\n super(message);\n this.status = status;\n this.type = type;\n this.detail = detail;\n this.props = props;\n }\n}\n\n// --- Send message response ---\n\nexport interface SendMessageResponse {\n message_id: string;\n status: string;\n}\n\n// --- Get message response ---\n\nexport interface GetMessageResponse {\n message_id: string;\n role: string;\n content: string;\n status: string;\n created_at: string;\n edit_id?: string;\n commit_sha?: string;\n summary?: string;\n cost_credits?: number;\n response?: {\n message_id: string;\n status: string;\n content: string;\n edit_id?: string;\n commit_sha?: string;\n summary?: string;\n cost_credits?: number;\n };\n queue_position?: number;\n queue_paused?: boolean;\n queue_pause_reason?: string;\n}\n\n// --- List messages response ---\n\nexport interface MessageSummary {\n message_id: string;\n role: string;\n content: string;\n status: string;\n created_at: string;\n edit_id?: string;\n}\n\nexport interface ListMessagesResponse {\n messages: MessageSummary[];\n has_more: boolean;\n}\n\nexport interface MessageCompletionResult {\n status: \"completed\" | \"timeout\" | \"error\";\n message_id: string;\n content: string;\n edit_id?: string;\n commit_sha?: string;\n summary?: string;\n cost_credits?: number;\n error?: string;\n}\n\nexport interface MessageCompletionOptions {\n /** Time between polls in ms (default: 3000) */\n pollInterval?: number;\n /** Maximum time to wait in ms (default: 600000 = 10 minutes) */\n timeout?: number;\n}\n\n// --- Knowledge ---\n\nexport interface KnowledgeResponse {\n content: string;\n}\n\n// --- Workspace skills ---\n\nexport interface WorkspaceSkillFile {\n name: string;\n contents?: string;\n binary: boolean;\n sizeExceeded: boolean;\n sizeBytes: number;\n}\n\nexport interface WorkspaceSkill {\n name: string;\n description: string;\n metadata?: Record<string, unknown>;\n markdown?: string;\n files: WorkspaceSkillFile[];\n}\n\nexport interface ListWorkspaceSkillsResponse {\n skills: WorkspaceSkill[];\n}\n\nexport interface WorkspaceSkillResponse {\n skill: WorkspaceSkill;\n}\n\nexport interface WorkspaceSkillWriteResponse {\n skill: WorkspaceSkill;\n commit_sha: string;\n}\n\nexport interface WorkspaceSkillDeleteResponse {\n commit_sha: string;\n}\n\n// --- Project skills ---\n\nexport interface ProjectSkill {\n name: string;\n description: string;\n metadata?: Record<string, unknown>;\n enabled: boolean;\n}\n\nexport interface ListProjectSkillsResponse {\n skills: ProjectSkill[];\n}\n\nexport interface ProjectSkillResponse {\n skill: Pick<ProjectSkill, \"name\" | \"enabled\">;\n}\n\n// --- File upload ---\n\nexport interface FileUploadUrlResponse {\n url: string;\n file_id: string;\n}\n\n// --- Git types ---\n\nexport interface DiffLine {\n type: string;\n content: string;\n}\n\nexport interface DiffHunk {\n oldStart: number;\n oldCount: number;\n newStart: number;\n newCount: number;\n lines: DiffLine[];\n}\n\nexport interface DiffEntry {\n action: string;\n file_path: string;\n original_file_path?: string;\n file_type?: string;\n is_image: boolean;\n is_incomplete?: boolean;\n hunks?: DiffHunk[];\n}\n\nexport interface GitDiffResponse {\n diffs: DiffEntry[];\n error?: string;\n}\n\nexport interface GitFileEntry {\n path: string;\n size: number;\n binary: boolean;\n}\n\nexport interface GitFilesResponse {\n files: GitFileEntry[];\n ref: string;\n}\n\n// --- Edits ---\n\nexport interface EditSummary {\n id: string;\n type: string;\n commit_sha?: string;\n commit_message?: string;\n status: string;\n created_at: string;\n}\n\nexport interface EditsResponse {\n edits: EditSummary[];\n has_more: boolean;\n}\n\n// --- List projects (expanded) ---\n\nexport interface ListProjectItem extends ProjectResponse {\n user_id?: string;\n is_template?: boolean;\n is_starred?: boolean;\n created_at?: string;\n updated_at?: string;\n last_edited_at?: string;\n last_viewed_at?: string;\n edit_count?: number;\n remix_count?: number;\n}\n\nexport interface ListProjectsResponse {\n projects: ListProjectItem[];\n total: number;\n has_more: boolean;\n}\n\nexport interface ListProjectsOptions {\n query?: string;\n visibility?: string;\n publish_status?: string;\n folder_id?: string;\n user_id?: string;\n sort_by?: string;\n sort_order?: string;\n viewed_by_me?: boolean;\n limit?: number;\n offset?: number;\n cursor?: string;\n}\n\n// --- Library & template projects ---\n\nexport interface LibraryProjectResponse {\n id: string;\n name: string | null;\n description: string;\n updated_at: string;\n}\n\nexport interface TemplateProjectResponse {\n id: string;\n name: string | null;\n description: string;\n updated_at: string;\n}\n\n// --- MCP servers ---\n\nexport interface ConnectorResponse {\n id: string;\n name: string;\n url?: string;\n auth_type: string;\n connector_id?: string;\n is_connected: boolean;\n}\n\nexport interface AvailableConnectorEntry {\n id: string;\n display_name: string;\n summary: string;\n category: string;\n requires_custom_url?: boolean;\n documentation_url?: string;\n}\n\nexport interface AddConnectorBody {\n name: string;\n url: string;\n auth_type: \"none\" | \"bearer_token\";\n connector_id?: string;\n token?: string;\n}\n\n// --- Connectors ---\n\nexport interface StandardConnectorItem {\n id: string;\n display_name: string;\n short_description: string;\n categories: string[];\n is_enabled_for_workspace: boolean;\n auth_type: string;\n logo_id?: string;\n documentation_url?: string;\n connection_scope?: string;\n}\n\nexport interface SeamlessConnectorItem {\n id: string;\n display_name: string;\n short_description: string;\n categories: string[];\n is_enabled_for_workspace: boolean;\n logo_id?: string;\n documentation_url?: string;\n}\n\nexport interface MCPConnectorItem {\n id: string;\n display_name: string;\n summary: string;\n status: string;\n is_enabled_for_workspace: boolean;\n is_connected: boolean;\n connector_id?: string;\n documentation_url?: string;\n}\n\nexport interface ConnectionItem {\n id: string;\n connector_id: string;\n display_name: string;\n is_managed: boolean;\n status: string;\n created_at: string;\n updated_at: string;\n}\n\n// --- Analytics ---\n\nexport interface TimeSeriesDataPoint {\n date: string;\n value: number;\n}\n\nexport interface TimeSeriesData {\n total: number;\n label: string;\n data: TimeSeriesDataPoint[];\n}\n\nexport interface ListDataPoint {\n label: string;\n value: number;\n}\n\nexport interface ListData {\n label: string;\n data: ListDataPoint[];\n}\n\nexport interface ProjectAnalyticsResponse {\n timeSeries: {\n visitors: TimeSeriesData;\n pageviews: TimeSeriesData;\n pageviewsPerVisit: TimeSeriesData;\n sessionDuration: TimeSeriesData;\n bounceRate: TimeSeriesData;\n };\n lists: {\n page: ListData;\n source: ListData;\n device: ListData;\n country: ListData;\n };\n}\n\nexport interface TrendDataPoint {\n time: string;\n visits: number;\n}\n\nexport interface ProjectAnalyticsTrendResponse {\n data: TrendDataPoint[];\n currentVisitors: number;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/retryFetch.ts","../src/types.ts"],"sourcesContent":["import type { Client, Middleware } from \"openapi-fetch\";\n\nimport createClient from \"openapi-fetch\";\n\nimport type { components, paths } from \"./generated/paths.js\";\n\ntype Schemas = components[\"schemas\"];\ntype CreateProjectPostBody = paths[\"/v1/projects\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\n\n// POST /v1/database/query is served but sits outside the public OpenAPI\n// boundary, so the generated paths omit it; this mirrors the openapi-typescript\n// operation shape for queryDatabase.\ntype DatabaseQueryCompatPaths = {\n \"/v1/database/query\": {\n parameters: { query?: never; header?: never; path?: never; cookie?: never };\n get?: never;\n put?: never;\n post: {\n parameters: { query?: never; header?: never; path?: never; cookie?: never };\n requestBody: {\n content: { \"application/json\": { project_id: string; sql: string } };\n };\n responses: {\n 200: {\n headers: { [name: string]: unknown };\n content: { \"application/json\": DatabaseQueryResult };\n };\n default: {\n headers: { [name: string]: unknown };\n content: { \"application/problem+json\": Record<string, unknown> };\n };\n };\n };\n delete?: never;\n options?: never;\n head?: never;\n patch?: never;\n trace?: never;\n };\n};\nimport type {\n LovableClientOptions,\n CreateProjectOptions,\n ChatMessageOptions,\n CreateVariantOptions,\n WaitOptions,\n ProjectResponse,\n CreateProjectResponse,\n CreateProjectBody,\n UpdateProjectOptions,\n EmbedURLResponse,\n ProjectPatchVisibility,\n DeploymentResponse,\n UnscopedFile,\n FileInput,\n RemixProjectOptions,\n RemixCreateProjectBody,\n RemixJobStatus,\n RemixResult,\n RemixWaitOptions,\n MeResponse,\n MeWorkspace,\n GetWorkspacesResponse,\n WorkspaceWithMembership,\n DatabaseStatus,\n EnableDatabaseResult,\n DatabaseQueryResult,\n SendMessageResponse,\n GetMessageResponse,\n ListMessagesResponse,\n ListMessagesOptions,\n ChatResponse,\n ChatResponseOptions,\n CreateVariantResponse,\n MessageCompletionResult,\n MessageCompletionOptions,\n GetMessageOptions,\n KnowledgeResponse,\n FileUploadUrlResponse,\n GitDiffResponse,\n GitFilesResponse,\n EditsResponse,\n ListProjectsResponse,\n ListProjectsOptions,\n ListConnectorsOptions,\n ListCursorPaginationOptions,\n ListHybridPaginationOptions,\n ListOffsetPaginationOptions,\n CursorPaginationOptions,\n MoveProjectsToFolderResponse,\n ConnectorResponse,\n AddConnectorBody,\n ListConnectorsResponse,\n ListAvailableConnectorsResponse,\n ListStandardConnectorsResponse,\n ListSeamlessConnectorsResponse,\n ListMCPConnectorsResponse,\n ListConnectionsResponse,\n ProjectAnalyticsResponse,\n ProjectAnalyticsTrendResponse,\n ListLibraryProjectsResponse,\n ListTemplateProjectsResponse,\n ListWorkspaceSkillsResponse,\n WorkspaceSkillResponse,\n WorkspaceSkillWriteResponse,\n WorkspaceSkillDeleteResponse,\n ListProjectSkillsResponse,\n ProjectSkillResponse,\n RateLimitInfo,\n} from \"./types.js\";\n\nimport { makeRetryFetch } from \"./retryFetch.js\";\nimport { ApiError } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.lovable.dev\";\nconst PUBLIC_API_CURSOR_VERSION = 1;\n\nfunction normalizeBaseUrl(url: string | undefined): string {\n if (!url) return DEFAULT_BASE_URL;\n\n const normalized = url.replace(/\\/$/, \"\");\n\n if (!normalized.startsWith(\"http://\") && !normalized.startsWith(\"https://\")) {\n throw new Error(`baseUrl must include a protocol (http:// or https://). Got: \"${url}\"`);\n }\n\n return normalized;\n}\n\nfunction encodePublicCursor(id: string): string {\n const raw = JSON.stringify({ v: PUBLIC_API_CURSOR_VERSION, id });\n const bytes = new TextEncoder().encode(raw);\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction normalizeWorkspaceList<T>(body: { data?: T[] | null; workspaces?: T[] | null }): T[] {\n return body.data ?? body.workspaces ?? [];\n}\n\nfunction cursorHasMore(body: { pagination?: { has_more?: boolean } | null; has_more?: boolean }): boolean {\n return body.pagination?.has_more ?? body.has_more ?? false;\n}\n\nfunction requireCreateProjectId<T extends { id?: string }>(project: T): T & { id: string } {\n if (!project.id) throw new Error(\"Create project response missing project ID\");\n return project as T & { id: string };\n}\n\n/**\n * openapi-fetch middleware that converts non-2xx Response objects into the\n * SDK's ApiError, preserving the existing error contract (status/type/detail/\n * props) used by every other method in this client.\n */\nconst errorMiddleware: Middleware = {\n async onResponse({ response }) {\n if (response.ok) return;\n let errorBody:\n | {\n type?: string;\n title?: string;\n message?: string;\n detail?: string;\n details?: string;\n props?: Record<string, unknown>;\n }\n | undefined;\n try {\n errorBody = (await response.clone().json()) as typeof errorBody;\n } catch {\n // Ignore JSON parse errors\n }\n const message = buildErrorMessage(errorBody, response.status, response.statusText);\n const type = errorBody?.type ?? errorBody?.title;\n const detail = errorBody?.detail ?? errorBody?.details;\n throw new ApiError(response.status, message, type, detail, errorBody?.props, parseRateLimitInfo(response.headers));\n },\n};\n\nfunction parseRateLimitInfo(headers: Headers): RateLimitInfo | undefined {\n const limit = parsePositiveInt(headers.get(\"x-ratelimit-limit\"));\n const remaining = parsePositiveInt(headers.get(\"x-ratelimit-remaining\"));\n const retryAfterMs = parseRetryAfterMs(headers.get(\"retry-after\"));\n if (limit == null && remaining == null && retryAfterMs == null) return undefined;\n return { limit, remaining, retryAfterMs };\n}\n\nfunction parsePositiveInt(raw: string | null): number | undefined {\n if (raw == null) return undefined;\n const n = Number(raw);\n return Number.isFinite(n) && n >= 0 ? n : undefined;\n}\n\nfunction parseRetryAfterMs(raw: string | null): number | undefined {\n if (!raw) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const dateMs = Date.parse(raw);\n if (!Number.isNaN(dateMs)) {\n const delta = dateMs - Date.now();\n return delta > 0 ? delta : 0;\n }\n return undefined;\n}\n\n// HTTP/2 leaves response.statusText empty, and some Go API endpoints return\n// `{message: \"\"}` / `{title: \"\"}` bodies on errors. `??` would preserve the\n// empty string and produce an ApiError with no usable message; consumers\n// downstream (MCP, logs, UI) then render an unlabeled failure.\nfunction buildErrorMessage(\n body: { message?: string; title?: string } | undefined,\n status: number,\n statusText: string,\n): string {\n return body?.message || body?.title || (statusText ? `HTTP ${status}: ${statusText}` : `HTTP ${status}`);\n}\n\nexport class LovableClient {\n private readonly authHeaders: Record<string, string>;\n private readonly baseUrl: string;\n private readonly extraHeaders: Record<string, string>;\n private readonly clientSource: string;\n private readonly typedClient: Client<paths>;\n\n constructor(options: LovableClientOptions) {\n const hasApiKey = !!options.apiKey;\n const hasBearerToken = !!options.bearerToken;\n\n if (!hasApiKey && !hasBearerToken) {\n throw new Error(\"Either apiKey or bearerToken is required\");\n }\n if (hasApiKey && hasBearerToken) {\n throw new Error(\"Provide either apiKey or bearerToken, not both\");\n }\n\n this.authHeaders = hasApiKey\n ? { \"Lovable-API-Key\": options.apiKey! }\n : { Authorization: `Bearer ${options.bearerToken}` };\n\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n this.extraHeaders = options.headers ?? {};\n this.clientSource = options.clientSource ?? \"sdk\";\n\n this.typedClient = createClient<paths>({\n baseUrl: this.baseUrl,\n headers: {\n \"X-Client-Source\": this.clientSource,\n ...this.authHeaders,\n ...this.extraHeaders,\n Accept: \"application/json\",\n },\n fetch: makeRetryFetch(),\n });\n this.typedClient.use(errorMiddleware);\n }\n\n /**\n * Type-safe access to any documented API route, driven by the auto-generated\n * OpenAPI schema. Path / query params and request bodies are checked at compile\n * time; calling an unknown path is a type error.\n *\n * Non-2xx responses throw `ApiError`; on success, `data` is set on the result.\n */\n get typed(): Client<paths> {\n return this.typedClient;\n }\n\n /**\n * Get the current authenticated user and their workspaces.\n * Useful for validating an API key and discovering workspace IDs.\n */\n async me(): Promise<MeResponse> {\n const { data } = await this.typed.GET(\"/v1/me\");\n return {\n ...data!,\n workspaces: normalizeWorkspaceList<MeWorkspace>(\n data! as { data?: MeWorkspace[] | null; workspaces?: MeWorkspace[] | null },\n ),\n };\n }\n\n /**\n * List workspaces the authenticated user has access to.\n */\n async listWorkspaces(options: ListHybridPaginationOptions = {}): Promise<GetWorkspacesResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces\", {\n params: { query: options },\n });\n return { ...data!, workspaces: normalizeWorkspaceList<WorkspaceWithMembership>(data!) };\n }\n\n /**\n * Get a specific workspace by ID\n */\n async getWorkspace(workspaceId: string) {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}\", {\n params: { path: { workspace_id: workspaceId } },\n });\n return data!.workspace;\n }\n\n /**\n * List projects in a workspace.\n * Supports full-text search, filtering by visibility/publish status/folder/creator,\n * and cursor pagination.\n */\n async listProjects(workspaceId: string, options?: ListProjectsOptions): Promise<ListProjectsResponse> {\n const { data } = await this.typed.GET(\"/v1/projects\", {\n params: {\n query: {\n workspace_id: workspaceId,\n q: options?.query,\n visibility: options?.visibility,\n publish_status: options?.publish_status,\n folder_id: options?.folder_id,\n folder_ids: options?.folder_ids,\n user_id: options?.user_id,\n type: options?.type,\n include_risk: options?.include_risk,\n search_fields: options?.search_fields,\n viewed_by_me: options?.viewed_by_me,\n cursor: options?.cursor,\n limit: options?.limit,\n },\n },\n });\n const projects =\n (data as unknown as { projects?: ListProjectsResponse[\"projects\"] }).projects ?? data!.data ?? null;\n const total = (data as unknown as { total?: number }).total;\n return {\n ...data!,\n projects,\n ...(total === undefined ? {} : { total }),\n has_more: data!.pagination?.has_more ?? (data as unknown as { has_more?: boolean }).has_more,\n };\n }\n\n /**\n * Create a new project in a workspace\n */\n async createProject(workspaceId: string, options: CreateProjectOptions): Promise<CreateProjectResponse> {\n let fileRefs: UnscopedFile[] | undefined;\n let ephemeralFileRefs: UnscopedFile[] | undefined;\n if (options.uploadedFiles?.length) {\n ({ fileRefs, ephemeralFileRefs } = this.partitionUploadedFiles(options.uploadedFiles));\n } else if (options.files?.length) {\n ephemeralFileRefs = await this.uploadEphemeralFiles(options.files);\n }\n\n const body: CreateProjectBody = {\n description: options.description,\n template_project_id: options.templateProjectId,\n };\n if (options.projectName) {\n body.display_name = options.projectName;\n }\n if (options.visibility) {\n body.visibility = options.visibility;\n }\n if (options.techStack) {\n body.tech_stack = options.techStack;\n }\n if (options.sandboxTemplate) {\n body.sandbox_template = options.sandboxTemplate;\n }\n if (options.selectedLibraries?.length) {\n body.selected_libraries = options.selectedLibraries;\n }\n if (options.initialMessage) {\n body.initial_message = options.initialMessage;\n }\n if (fileRefs?.length) {\n body.files = fileRefs;\n }\n if (options.fileUrls?.length) {\n body.file_urls = options.fileUrls;\n }\n if (ephemeralFileRefs?.length) {\n body.ephemeral_files = ephemeralFileRefs;\n }\n\n const { data } = await this.typed.POST(\"/v1/projects\", {\n body: { ...body, workspace_id: workspaceId },\n });\n return requireCreateProjectId(data!);\n }\n\n /**\n * Send a chat message to a project.\n *\n * The API accepts the message and processes it in the background.\n * Returns the message ID and status. Use `waitForMessageCompletion()`\n * to poll for the AI response.\n */\n async chat(projectId: string, options: ChatMessageOptions): Promise<SendMessageResponse> {\n let fileRefs: UnscopedFile[] | undefined;\n let ephemeralFileRefs: UnscopedFile[] | undefined;\n if (options.uploadedFiles?.length) {\n ({ fileRefs, ephemeralFileRefs } = this.partitionUploadedFiles(options.uploadedFiles));\n } else if (options.files?.length) {\n fileRefs = await this.uploadProjectFiles(projectId, options.files);\n }\n\n const body: Omit<Schemas[\"PublicV1SendMessageInputBody\"], \"project_id\"> = {\n message: options.message,\n };\n if (options.variantId) {\n body.variant_id = options.variantId;\n }\n if (fileRefs) {\n body.files = fileRefs;\n }\n if (ephemeralFileRefs) {\n body.ephemeral_files = ephemeralFileRefs;\n }\n if (options.planMode) {\n body.plan_mode = true;\n }\n if (options.continuation) {\n body.continuation = options.continuation;\n }\n\n const { data } = await this.typed.POST(\"/v1/messages\", {\n body: { ...body, project_id: projectId },\n });\n return data!;\n }\n\n /**\n * Create an independent variant from the project's current main branch, or from a full baseSha when provided.\n */\n async createVariant(projectId: string, options: CreateVariantOptions = {}): Promise<CreateVariantResponse> {\n const { data } = await this.typed.POST(\"/v1/projects/{project_id}/variants\", {\n params: { path: { project_id: projectId } },\n body: { label: options.label, base_sha: options.baseSha },\n });\n return data!;\n }\n\n /**\n * Get project details by ID\n */\n async getProject(projectId: string): Promise<ProjectResponse> {\n const { data } = await this.typed.GET(\"/v1/projects/{project_id}\", {\n params: { path: { project_id: projectId } },\n });\n return data!;\n }\n\n /**\n * Create an anonymous, one-hour static preview URL for one exact HTTPS parent origin.\n */\n async createEmbedUrl(projectId: string, parentOrigin: string): Promise<EmbedURLResponse> {\n const { data } = await this.typed.POST(\"/v1/projects/{project_id}/embed-url\", {\n params: { path: { project_id: projectId } },\n body: { parent_origin: parentOrigin },\n });\n return data!;\n }\n\n /**\n * Update supported project fields.\n */\n async updateProject(projectId: string, options: UpdateProjectOptions): Promise<ProjectResponse> {\n const { data } = await this.typed.PATCH(\"/v1/projects/{project_id}\", {\n params: { path: { project_id: projectId } },\n body: options,\n });\n return data!;\n }\n\n /**\n * Soft-delete a project. Repeated deletes are treated as successful.\n */\n async deleteProject(projectId: string): Promise<void> {\n await this.typed.DELETE(\"/v1/projects/{project_id}\", {\n params: { path: { project_id: projectId } },\n });\n }\n\n /**\n * Get the preview URL for a project.\n *\n * The preview URL is available once the project reaches \"completed\" status.\n * This URL allows viewing the project in development mode.\n *\n * @param projectId - The project ID\n * @returns The preview URL\n */\n getPreviewUrl(projectId: string): string {\n return `https://id-preview--${projectId}.lovable.app`;\n }\n\n /**\n * Get the published URL for a project (if published).\n *\n * Returns the public URL if the project has been published, or null if not.\n *\n * @param projectId - The project ID\n * @returns The published URL or null if not published\n */\n async getPublishedUrl(projectId: string): Promise<string | null> {\n const project = await this.getProject(projectId);\n return project.is_published && project.url ? project.url : null;\n }\n\n /**\n * Get the cloud database status for a project.\n *\n * @param projectId - The project ID\n * @returns Whether the database is enabled and which stack is used\n */\n async getDatabaseStatus(projectId: string): Promise<DatabaseStatus> {\n const { data } = await this.typed.GET(\"/v1/database\", {\n params: { query: { project_id: projectId } },\n });\n return data!;\n }\n\n /**\n * Enable (provision) a cloud database for a project.\n *\n * This triggers database provisioning which takes 30-60 seconds.\n * The call blocks until provisioning completes.\n *\n * @param projectId - The project ID\n * @returns The database status after enablement\n */\n async enableDatabase(projectId: string): Promise<EnableDatabaseResult> {\n const { data } = await this.typed.POST(\"/v1/database/enable\", {\n body: { project_id: projectId },\n });\n return data!;\n }\n\n /**\n * Execute a SQL query against the project's cloud database.\n *\n * Supports SELECT, INSERT, UPDATE, DELETE, and DDL statements.\n * The database must be enabled first (see enableDatabase).\n *\n * @param projectId - The project ID\n * @param sql - SQL query to execute\n * @returns Query result rows as JSON objects\n */\n async queryDatabase(projectId: string, sql: string): Promise<DatabaseQueryResult> {\n // The route sits outside the public OpenAPI boundary, so the generated\n // paths lack it; DatabaseQueryCompatPaths stands in for the generated shape.\n const compat = this.typedClient as unknown as Client<DatabaseQueryCompatPaths>;\n const { data } = await compat.POST(\"/v1/database/query\", {\n body: { project_id: projectId, sql },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Messages\n // ---------------------------------------------------------------------------\n\n /**\n * Get a message by ID. Returns the message content, status, and (for user messages)\n * the AI response if available.\n *\n * Pass `waitSeconds` to long-poll: the server holds the request until the\n * message reaches a terminal state (completed / stopped / error / awaiting_input) or the\n * duration elapses. This replaces client-side polling for `waitForMessageCompletion`.\n */\n async getMessage(projectId: string, messageId: string, options?: GetMessageOptions): Promise<GetMessageResponse> {\n const waitSeconds = options?.waitSeconds;\n const query = {\n wait: waitSeconds && waitSeconds > 0 ? `${Math.floor(waitSeconds)}s` : undefined,\n thread_id: options?.threadId,\n };\n const { data } = await this.typed.GET(\"/v1/messages/{message_id}\", {\n params: { path: { message_id: messageId }, query: { ...query, project_id: projectId } },\n });\n return data!;\n }\n\n /**\n * List recent messages in a project, newest first. Use `cursor` from the\n * previous page's `pagination.next_cursor` to paginate through history.\n */\n async listMessages(projectId: string, params?: ListMessagesOptions): Promise<ListMessagesResponse> {\n const cursor = params?.cursor ?? (params?.before ? encodePublicCursor(params.before) : undefined);\n const { data } = await this.typed.GET(\"/v1/messages\", {\n params: {\n query: { project_id: projectId, limit: params?.limit, cursor },\n },\n });\n return {\n ...data!,\n messages: data!.data,\n has_more: cursorHasMore(data!),\n };\n }\n\n /**\n * Wait for the AI response to reach a terminal status (completed, stopped, error, awaiting_input)\n * or for `timeout` to elapse.\n *\n * Primary path is SSE against `/v1/messages/{message_id}/stream`: one\n * held connection that pushes a snapshot on every relevant change and closes\n * on terminal. If SSE isn't reachable (proxy strips text/event-stream, server\n * returns 404 / 415 / 501) we fall back to the long-poll JSON endpoint on the\n * same URL. Both paths share the same `MessageCompletionResult` shape.\n */\n async waitForMessageCompletion(\n projectId: string,\n messageId: string,\n options?: MessageCompletionOptions,\n ): Promise<MessageCompletionResult> {\n const timeout = options?.timeout ?? 600_000;\n const deadline = Date.now() + timeout;\n\n const sse = await this.waitForMessageCompletionViaSSE(projectId, messageId, deadline, options?.threadId);\n if (sse.kind === \"result\") {\n return sse.result;\n }\n if (Date.now() >= deadline) {\n return timeoutResult(messageId, timeout);\n }\n return this.waitForMessageCompletionViaLongPoll(projectId, messageId, deadline, timeout, options);\n }\n\n /**\n * @deprecated Use `chat()` or `createProject()`'s returned `message_id`,\n * then call `waitForMessageCompletion(projectId, messageId)`.\n *\n * Throws when the turn pauses for human input (`awaiting_input`) — the\n * legacy `ChatResponse` shape cannot carry resume metadata. HITL-capable\n * flows need `waitForMessageCompletion` plus `respondToTool`.\n */\n async waitForResponse(projectId: string, options?: ChatResponseOptions): Promise<ChatResponse> {\n const messages = await this.listMessages(projectId, { limit: 10 });\n const latest = messages.messages?.find((message) => message.role === \"user\");\n\n if (!latest?.message_id) {\n throw new Error(`No messages found for project ${projectId}`);\n }\n\n const completionOptions = options?.timeout === undefined ? undefined : { timeout: options.timeout };\n const result = await this.waitForMessageCompletion(projectId, latest.message_id, completionOptions);\n // Preserve the pre-deprecation contract: throw on failure. waitForMessageCompletion\n // returns (never throws) on timeout/error, so without this a timed-out or errored run\n // looks like a successful empty response to try/catch callers.\n if (result.status !== \"completed\" && result.status !== \"stopped\") {\n throw new Error(result.error ?? `Message ${latest.message_id} did not complete (status: ${result.status})`);\n }\n return {\n content: result.content,\n messageId: result.message_id,\n previewUrl: this.getPreviewUrl(projectId),\n };\n }\n\n private async waitForMessageCompletionViaSSE(\n projectId: string,\n messageId: string,\n deadline: number,\n threadId?: string,\n ): Promise<{ kind: \"result\"; result: MessageCompletionResult } | { kind: \"fallback\" } | { kind: \"timeout\" }> {\n const remaining = deadline - Date.now();\n if (remaining <= 0) return { kind: \"timeout\" };\n\n const url = new URL(`${this.baseUrl}/v1/messages/${encodeURIComponent(messageId)}/stream`);\n url.searchParams.set(\"project_id\", projectId);\n if (threadId) {\n url.searchParams.set(\"thread_id\", threadId);\n }\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), remaining);\n\n let response: Response;\n try {\n response = await fetch(url, {\n headers: {\n ...this.authHeaders,\n ...this.extraHeaders,\n \"X-Client-Source\": this.clientSource,\n Accept: \"text/event-stream\",\n },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timeoutId);\n if (isAbortError(err)) return { kind: \"timeout\" };\n return { kind: \"fallback\" };\n }\n\n if (!response.ok) {\n clearTimeout(timeoutId);\n if (response.status === 404 || response.status === 415 || response.status === 501) {\n await cancelResponseBody(response);\n return { kind: \"fallback\" };\n }\n if (response.status >= 500) {\n await cancelResponseBody(response);\n return { kind: \"fallback\" };\n }\n const detail = await safeReadText(response);\n throw new ApiError(response.status, detail || `HTTP ${response.status}`);\n }\n\n if (!response.body) {\n clearTimeout(timeoutId);\n return { kind: \"fallback\" };\n }\n\n try {\n for await (const frame of parseSSEFrames(response.body)) {\n if (!frame.data) continue;\n let snapshot: GetMessageResponse;\n try {\n snapshot = JSON.parse(frame.data) as GetMessageResponse;\n } catch {\n continue;\n }\n\n const queuedResult = queuedExitResult(snapshot, messageId);\n if (queuedResult) return { kind: \"result\", result: queuedResult };\n\n const terminal = terminalResultFromMessage(snapshot, messageId);\n if (terminal) {\n return { kind: \"result\", result: terminal };\n }\n }\n return { kind: \"fallback\" };\n } catch (err) {\n if (isAbortError(err)) return { kind: \"timeout\" };\n return { kind: \"fallback\" };\n } finally {\n clearTimeout(timeoutId);\n controller.abort();\n }\n }\n\n private async waitForMessageCompletionViaLongPoll(\n projectId: string,\n messageId: string,\n deadline: number,\n totalTimeoutMs: number,\n options?: MessageCompletionOptions,\n ): Promise<MessageCompletionResult> {\n const waitSeconds = Math.max(1, Math.min(55, options?.waitSeconds ?? 30));\n const transientBackoffMs = 1000;\n let notFoundSince: number | null = null;\n const notFoundGraceMs = 15_000;\n\n while (Date.now() < deadline) {\n const remainingMs = deadline - Date.now();\n const perCallSeconds = Math.min(waitSeconds, Math.floor(remainingMs / 1000));\n const waitOptions = perCallSeconds > 0 ? { waitSeconds: perCallSeconds } : undefined;\n\n const callStartedAt = Date.now();\n try {\n const msg = await this.getMessage(projectId, messageId, { ...waitOptions, threadId: options?.threadId });\n notFoundSince = null;\n\n const queuedResult = queuedExitResult(msg, messageId);\n if (queuedResult) return queuedResult;\n\n const terminal = terminalResultFromMessage(msg, messageId);\n if (terminal) return terminal;\n\n // Server returned a non-terminal snapshot far faster than the wait\n // window it was given. That happens when the streamer is nil or its\n // subscription fails server-side, or for queued messages that have no\n // stream events yet. Backoff so we don't tight-loop until the deadline.\n if (Date.now() - callStartedAt < transientBackoffMs) {\n await sleep(Math.min(transientBackoffMs, Math.max(0, deadline - Date.now())));\n }\n } catch (err) {\n if (err instanceof ApiError) {\n if (err.status === 404) {\n if (notFoundSince === null) {\n notFoundSince = Date.now();\n }\n if (Date.now() - notFoundSince < notFoundGraceMs) {\n await sleep(Math.min(transientBackoffMs, Math.max(0, deadline - Date.now())));\n continue;\n }\n return {\n status: \"error\",\n message_id: messageId,\n content: \"\",\n error: \"Message not found. It may have been deleted from the queue.\",\n };\n }\n if (err.status < 500) {\n throw err;\n }\n }\n await sleep(Math.min(transientBackoffMs, Math.max(0, deadline - Date.now())));\n }\n }\n\n return timeoutResult(messageId, totalTimeoutMs);\n }\n\n // ---------------------------------------------------------------------------\n // Knowledge\n // ---------------------------------------------------------------------------\n\n /** Get workspace knowledge (custom instructions for the AI agent). */\n async getWorkspaceKnowledge(workspaceId: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/knowledge\", {\n params: { path: { workspace_id: workspaceId } },\n });\n return data!;\n }\n\n /** Set workspace knowledge. Max 10,000 characters. */\n async setWorkspaceKnowledge(workspaceId: string, content: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.PUT(\"/v1/workspaces/{workspace_id}/knowledge\", {\n params: { path: { workspace_id: workspaceId } },\n body: { content },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Workspace skills\n // ---------------------------------------------------------------------------\n\n /** List workspace skills. */\n async listWorkspaceSkills(\n workspaceId: string,\n options: { includeMarkdown?: boolean } & ListOffsetPaginationOptions = {},\n ): Promise<ListWorkspaceSkillsResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/skills\", {\n params: {\n path: { workspace_id: workspaceId },\n query: { include_markdown: options.includeMarkdown, limit: options.limit, offset: options.offset },\n },\n });\n return { ...data!, skills: data!.skills ?? [] };\n }\n\n /** Get a single workspace skill, including SKILL.md contents. */\n async getWorkspaceSkill(workspaceId: string, skillName: string): Promise<WorkspaceSkillResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/skills/{skill_name}\", {\n params: { path: { workspace_id: workspaceId, skill_name: skillName } },\n });\n return data!;\n }\n\n /** Create a workspace skill from full SKILL.md markdown. */\n async createWorkspaceSkill(\n workspaceId: string,\n skillName: string,\n markdown: string,\n ): Promise<WorkspaceSkillWriteResponse> {\n const { data } = await this.typed.POST(\"/v1/workspaces/{workspace_id}/skills/{skill_name}\", {\n params: { path: { workspace_id: workspaceId, skill_name: skillName } },\n body: { markdown },\n });\n return data!;\n }\n\n /** Update a workspace skill by replacing its SKILL.md markdown. */\n async updateWorkspaceSkill(\n workspaceId: string,\n skillName: string,\n markdown: string,\n ): Promise<WorkspaceSkillWriteResponse> {\n const { data } = await this.typed.PUT(\"/v1/workspaces/{workspace_id}/skills/{skill_name}\", {\n params: { path: { workspace_id: workspaceId, skill_name: skillName } },\n body: { markdown },\n });\n return data!;\n }\n\n /** Delete a workspace skill. */\n async deleteWorkspaceSkill(workspaceId: string, skillName: string): Promise<WorkspaceSkillDeleteResponse> {\n const { data } = await this.typed.DELETE(\"/v1/workspaces/{workspace_id}/skills/{skill_name}\", {\n params: { path: { workspace_id: workspaceId, skill_name: skillName } },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Project skills\n // ---------------------------------------------------------------------------\n\n /** List project skills, including whether each skill is enabled. */\n async listProjectSkills(\n projectId: string,\n options: ListCursorPaginationOptions = {},\n ): Promise<ListProjectSkillsResponse> {\n const { data } = await this.typed.GET(\"/v1/skills\", {\n params: { query: { project_id: projectId, limit: options.limit, cursor: options.cursor } },\n });\n const skills = (data as unknown as { skills?: ListProjectSkillsResponse[\"skills\"] }).skills ?? data!.data ?? [];\n return { ...data!, skills };\n }\n\n /** Enable or disable a project skill without removing it from the project repo. */\n async setProjectSkillEnabled(projectId: string, skillName: string, enabled: boolean): Promise<ProjectSkillResponse> {\n const { data } = await this.typed.PATCH(\"/v1/skills/{skill_name}\", {\n params: { path: { skill_name: skillName } },\n body: { project_id: projectId, enabled },\n });\n return data!;\n }\n\n /** Get project knowledge (custom instructions for the AI agent). */\n async getProjectKnowledge(projectId: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.GET(\"/v1/knowledge\", {\n params: { query: { project_id: projectId } },\n });\n return data!;\n }\n\n /** Set project knowledge. Max 10,000 characters. */\n async setProjectKnowledge(projectId: string, content: string): Promise<KnowledgeResponse> {\n const { data } = await this.typed.PUT(\"/v1/knowledge\", {\n body: { project_id: projectId, content },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Git operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get the structured diff for a message or commit.\n * Pass `messageId` to get the diff for a specific AI message,\n * or `sha` for a specific commit.\n */\n async getDiff(\n projectId: string,\n params: { messageId?: string; sha?: string; baseSha?: string },\n ): Promise<GitDiffResponse> {\n const { data } = await this.typed.GET(\"/v1/git/diff\", {\n params: {\n query: { project_id: projectId, message_id: params.messageId, sha: params.sha, base_sha: params.baseSha },\n },\n });\n return data!;\n }\n\n /** List files in a project. Omitting ref uses the API default. */\n async listFiles(projectId: string, ref?: string, options?: CursorPaginationOptions): Promise<GitFilesResponse>;\n async listFiles(projectId: string, options?: CursorPaginationOptions): Promise<GitFilesResponse>;\n async listFiles(\n projectId: string,\n refOrOptions?: string | CursorPaginationOptions,\n options: CursorPaginationOptions = {},\n ): Promise<GitFilesResponse> {\n const ref = typeof refOrOptions === \"string\" ? refOrOptions : undefined;\n const pagination = typeof refOrOptions === \"string\" ? options : (refOrOptions ?? options);\n const { data } = await this.typed.GET(\"/v1/git/files\", {\n params: { query: { project_id: projectId, ref, limit: pagination.limit, cursor: pagination.cursor } },\n });\n const files = data!.data ?? [];\n return { ...data!, data: files, files };\n }\n\n /** Read the raw content of a single file. Omitting ref uses the API default. */\n async readFile(projectId: string, path: string, ref?: string): Promise<string> {\n // The Go OpenAPI annotation for this route declares 200 as `content?: never`\n // even though the handler returns the raw file text. `parseAs: \"text\"` makes\n // openapi-fetch read the body as text at runtime; the cast covers the spec\n // gap. Drop the cast once the Go annotation declares text/plain content.\n const { data } = await this.typed.GET(\"/v1/git/files/{path}\", {\n params: { path: { path }, query: { project_id: projectId, ref } },\n parseAs: \"text\",\n });\n return data as unknown as string;\n }\n\n // ---------------------------------------------------------------------------\n // Edits\n // ---------------------------------------------------------------------------\n\n /** List the edit history of a project. */\n async listEdits(projectId: string, params?: { limit?: number; before?: string }): Promise<EditsResponse> {\n const { data } = await this.typed.GET(\"/v1/edits\", {\n params: {\n query: { project_id: projectId, limit: params?.limit, before: params?.before },\n },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // File upload\n // ---------------------------------------------------------------------------\n\n /** Get an ephemeral presigned URL for uploading a file before a project exists. */\n async getFileUploadUrl(params: { file_name: string; content_type?: string }): Promise<FileUploadUrlResponse> {\n return this.getEphemeralFileUploadUrl({ content_type: params.content_type });\n }\n\n /** Get a project-scoped presigned URL for uploading a file. Returns the upload URL, file ID, and required PUT headers. */\n async getProjectFileUploadUrl(projectId: string, params: { content_type?: string }): Promise<FileUploadUrlResponse> {\n const { data } = await this.typed.POST(\"/v1/project-files/upload-url\", {\n body: { project_id: projectId, ...params },\n });\n return data!;\n }\n\n /** Get an ephemeral presigned URL for uploading a file before a project exists. */\n async getEphemeralFileUploadUrl(params: { content_type?: string }): Promise<FileUploadUrlResponse> {\n const { data } = await this.typed.POST(\"/v1/files/ephemeral-upload-url\", { body: params });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Visibility\n // ---------------------------------------------------------------------------\n\n /** Set a project's visibility (draft, private, workspace_view, or public). */\n async setProjectVisibility(projectId: string, visibility: ProjectPatchVisibility): Promise<ProjectResponse> {\n return this.updateProject(projectId, { visibility });\n }\n\n /** Set a folder's visibility (personal or workspace). */\n async setFolderVisibility(workspaceId: string, folderId: string, visibility: \"personal\" | \"workspace\") {\n const { data } = await this.typed.PUT(\"/v1/workspaces/{workspace_id}/folders/{folder_id}/visibility\", {\n params: { path: { workspace_id: workspaceId, folder_id: folderId } },\n body: { visibility },\n });\n return data!;\n }\n\n /** Move projects into a folder, removing existing folder memberships first. */\n async moveProjectsToFolder(\n workspaceId: string,\n folderId: string,\n projectIds: string[],\n ): Promise<MoveProjectsToFolderResponse> {\n const { data } = await this.typed.POST(\"/v1/workspaces/{workspace_id}/folders/{folder_id}/projects/move\", {\n params: { path: { workspace_id: workspaceId, folder_id: folderId } },\n body: { project_ids: projectIds },\n });\n return data!;\n }\n\n // ---------------------------------------------------------------------------\n // Library & template projects\n // ---------------------------------------------------------------------------\n\n /** List available design system library projects in a workspace. */\n async listLibraryProjects(\n workspaceId: string,\n options: ListOffsetPaginationOptions = {},\n ): Promise<ListLibraryProjectsResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/available-library-projects\", {\n params: { path: { workspace_id: workspaceId }, query: options },\n });\n return { ...data!, libraries: data!.libraries ?? [] };\n }\n\n /** List available template projects in a workspace. */\n async listTemplateProjects(\n workspaceId: string,\n options: ListOffsetPaginationOptions = {},\n ): Promise<ListTemplateProjectsResponse> {\n const { data } = await this.typed.GET(\"/v1/workspaces/{workspace_id}/available-template-projects\", {\n params: { path: { workspace_id: workspaceId }, query: options },\n });\n return { ...data!, templates: data!.templates ?? [] };\n }\n\n // ---------------------------------------------------------------------------\n // Connectors (MCP servers)\n // ---------------------------------------------------------------------------\n\n /** List all connectors in a workspace. */\n async listConnectors(workspaceId: string, options: ListConnectorsOptions = {}): Promise<ListConnectorsResponse> {\n const { data } = await this.typed.GET(\"/v1/connectors\", {\n params: {\n query: {\n workspace_id: workspaceId,\n type: options.type,\n status: options.status,\n limit: options.limit,\n cursor: options.cursor,\n },\n },\n });\n const connectors =\n (data as unknown as { connectors?: ListConnectorsResponse[\"connectors\"] }).connectors ?? data!.data ?? [];\n return { ...data!, data: connectors, connectors, has_more: cursorHasMore(data!) };\n }\n\n /** Add a connector to a workspace. The server URL is tested before saving. */\n async addConnector(workspaceId: string, body: AddConnectorBody): Promise<ConnectorResponse> {\n const { data } = await this.typed.POST(\"/v1/connectors\", {\n body: { ...body, workspace_id: workspaceId },\n });\n return data!;\n }\n\n /** Remove a connector from a workspace. */\n async removeConnector(workspaceId: string, connectorId: string) {\n const { data } = await this.typed.DELETE(\"/v1/connectors/{connector_id}\", {\n params: { path: { connector_id: connectorId }, query: { workspace_id: workspaceId } },\n });\n return data!;\n }\n\n /** Browse available connector templates. */\n async listAvailableConnectors(\n workspaceId: string,\n options: ListCursorPaginationOptions = {},\n ): Promise<ListAvailableConnectorsResponse> {\n const { data } = await this.typed.GET(\"/v1/available-connectors\", {\n params: { query: { workspace_id: workspaceId, limit: options.limit, cursor: options.cursor } },\n });\n const catalog =\n (data as unknown as { catalog?: ListAvailableConnectorsResponse[\"catalog\"] }).catalog ?? data!.data ?? [];\n return { ...data!, data: catalog, catalog, has_more: cursorHasMore(data!) };\n }\n\n // ---------------------------------------------------------------------------\n // Connectors\n // ---------------------------------------------------------------------------\n\n /** List standard (OAuth-based) connectors in a workspace. */\n async listStandardConnectors(\n workspaceId: string,\n options: ListCursorPaginationOptions = {},\n ): Promise<ListStandardConnectorsResponse> {\n const { data } = await this.typed.GET(\"/v1/connectors\", {\n params: { query: { workspace_id: workspaceId, type: \"standard\", limit: options.limit, cursor: options.cursor } },\n });\n const connectors =\n (data as unknown as { connectors?: ListStandardConnectorsResponse[\"connectors\"] }).connectors ?? data!.data ?? [];\n return { ...data!, data: connectors, connectors, has_more: cursorHasMore(data!) };\n }\n\n /** List seamless (zero-config) connectors in a workspace. */\n async listSeamlessConnectors(\n workspaceId: string,\n options: ListCursorPaginationOptions = {},\n ): Promise<ListSeamlessConnectorsResponse> {\n const { data } = await this.typed.GET(\"/v1/connectors\", {\n params: { query: { workspace_id: workspaceId, type: \"seamless\", limit: options.limit, cursor: options.cursor } },\n });\n const connectors =\n (data as unknown as { connectors?: ListSeamlessConnectorsResponse[\"connectors\"] }).connectors ?? data!.data ?? [];\n return { ...data!, data: connectors, connectors, has_more: cursorHasMore(data!) };\n }\n\n /** List MCP connectors in a workspace. */\n async listMCPConnectors(\n workspaceId: string,\n options: ListCursorPaginationOptions = {},\n ): Promise<ListMCPConnectorsResponse> {\n const { data } = await this.typed.GET(\"/v1/connectors\", {\n params: { query: { workspace_id: workspaceId, type: \"mcp\", limit: options.limit, cursor: options.cursor } },\n });\n const connectors =\n (data as unknown as { connectors?: ListMCPConnectorsResponse[\"connectors\"] }).connectors ?? data!.data ?? [];\n return { ...data!, data: connectors, connectors, has_more: cursorHasMore(data!) };\n }\n\n /** List authenticated connections (accounts) in a workspace. */\n async listConnections(\n workspaceId: string,\n params: { connector_id?: string; limit?: number; cursor?: string } = {},\n ): Promise<ListConnectionsResponse> {\n const { data } = await this.typed.GET(\"/v1/connections\", {\n params: {\n query: {\n workspace_id: workspaceId,\n connector_id: params.connector_id,\n limit: params.limit,\n cursor: params.cursor,\n },\n },\n });\n const connections = data!.data ?? [];\n return { ...data!, data: connections, connections, has_more: cursorHasMore(data!) };\n }\n\n // ---------------------------------------------------------------------------\n // Analytics\n // ---------------------------------------------------------------------------\n\n /** Get historical analytics for a published project. */\n async getProjectAnalytics(\n projectId: string,\n params: { startDate: string; endDate: string; granularity?: string },\n ): Promise<ProjectAnalyticsResponse> {\n const { data } = await this.typed.GET(\"/v1/analytics\", {\n params: {\n query: {\n project_id: projectId,\n startDate: params.startDate,\n endDate: params.endDate,\n granularity: params.granularity,\n },\n },\n });\n return data!;\n }\n\n /** Get real-time visitor trend for a published project. */\n async getProjectAnalyticsTrend(projectId: string): Promise<ProjectAnalyticsTrendResponse> {\n const { data } = await this.typed.GET(\"/v1/analytics/trend\", {\n params: { query: { project_id: projectId } },\n });\n return data!;\n }\n\n /**\n * Publish a project.\n *\n * This triggers a deployment which makes the project publicly accessible.\n * The deployment runs asynchronously - use waitForProjectPublished() to wait for completion.\n *\n * @param projectId - The project ID to publish\n * @param options.name - Optional custom slug for the published URL\n * @returns Deployment info including deployment ID\n */\n async publish(projectId: string, options?: { name?: string }): Promise<DeploymentResponse> {\n const { data } = await this.typed.POST(\"/v1/deployments\", {\n body: { project_id: projectId, name: options?.name },\n });\n return data!;\n }\n\n /**\n * Remix (fork) an existing project, optionally at a specific message point in time.\n *\n * When `messageId` is provided, the remix captures the project state after\n * that message and its AI response by default. Set `remixMode: \"before\"` to\n * start before the message was processed.\n * Without `messageId`, the full current state is remixed.\n *\n * @param sourceProjectId - The project to remix from\n * @param options.workspaceId - Target workspace for the new project\n * @param options.messageId - Optional message ID to snapshot at\n * @param options.remixMode - \"including\" (server default): state after the message and its AI response; \"before\": state before the message\n * @param options.includeHistory - Whether to preserve chat history (default: false)\n * @param options.includeCustomKnowledge - Whether to copy custom instructions (default: false)\n * @param options.initialMessage - Optional initial message to send after remix\n * @param options.description - Optional custom description for the new project\n * @returns The remix job ID for polling progress\n */\n async remixProject(sourceProjectId: string, options: RemixProjectOptions): Promise<string> {\n const body: RemixCreateProjectBody = {\n workspace_id: options.workspaceId,\n source_project_id: sourceProjectId,\n include_history: options.includeHistory,\n include_custom_knowledge: options.includeCustomKnowledge,\n description: options.description,\n display_name: options.projectName,\n skip_initial_remix_message: options.skipInitialRemixMessage,\n skip_integrations: options.skipIntegrations,\n };\n\n if (options.messageId) {\n body.message_id = options.messageId;\n if (options.remixMode) {\n body.remix_mode = options.remixMode;\n }\n }\n\n if (options.initialMessage) {\n body.initial_message = options.initialMessage;\n }\n\n const { data } = await this.typed.POST(\"/v1/projects\", {\n body: body as CreateProjectPostBody,\n });\n const remix = data;\n if (!remix?.job_id) {\n throw new Error(\"Failed to get job ID from remix create\");\n }\n return remix.job_id;\n }\n\n /**\n * Wait for a remix operation to complete.\n *\n * Polls the remix progress endpoint until the job reaches \"completed\" or \"error\" status.\n *\n * @param sourceProjectId - The source project ID (used for the progress endpoint)\n * @param jobId - The job ID returned by `remixProject()`\n * @param options.pollInterval - Time between polls in ms (default: 2000)\n * @param options.timeout - Maximum time to wait in ms (default: 300000 = 5 minutes)\n * @param options.onProgress - Optional callback for status/step updates\n * @returns The new project ID\n * @throws Error if the remix fails or timeout is reached\n */\n async waitForRemix(sourceProjectId: string, jobId: string, options?: RemixWaitOptions): Promise<RemixResult> {\n const pollInterval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300000;\n const startTime = Date.now();\n\n while (true) {\n const { data } = await this.typed.GET(\"/v1/projects/{project_id}/remix/progress\", {\n params: {\n path: { project_id: sourceProjectId },\n query: { job_id: jobId },\n },\n });\n const progress = data!;\n const status = progress.status as RemixJobStatus;\n options?.onProgress?.(status, progress.step);\n\n if (status === \"completed\" && progress.result) {\n return { projectId: progress.result.project_id };\n }\n\n if (status === \"error\") {\n throw new Error(progress.error_message ?? \"Remix failed\");\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for remix of project ${sourceProjectId}`);\n }\n\n await sleep(pollInterval);\n }\n }\n\n /**\n * Wait for a project to reach \"completed\" status.\n *\n * Projects start in \"in_progress\" status while being created/built.\n * This method polls until the status becomes \"completed\" or \"failed\".\n * A successful completion means the project's preview is ready to view.\n *\n * @param projectId - The project ID to wait for\n * @param options.pollInterval - Time between polls in ms (default: 2000)\n * @param options.timeout - Maximum time to wait in ms (default: 300000 = 5 minutes)\n * @param options.onProgress - Optional callback for status updates\n * @returns The completed project\n * @throws Error if project fails or timeout is reached\n */\n async waitForProjectReady(projectId: string, options?: WaitOptions): Promise<ProjectResponse> {\n const pollInterval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300000;\n const startTime = Date.now();\n\n while (true) {\n const project = await this.getProject(projectId);\n options?.onProgress?.(project);\n\n if (project.status === \"completed\") {\n return project;\n }\n\n if (project.status === \"failed\") {\n throw new Error(`Project ${projectId} failed to build`);\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for project ${projectId} to be ready`);\n }\n\n await sleep(pollInterval);\n }\n }\n\n private isFileInput(file: File | FileInput): file is FileInput {\n return \"data\" in file;\n }\n\n private async uploadFile(\n file: File | FileInput,\n getUploadUrl: (fileName: string, mimeType: string) => Promise<FileUploadUrlResponse>,\n ): Promise<UnscopedFile> {\n const fileName = this.isFileInput(file) ? file.name : file.name;\n const mimeType = this.isFileInput(file) ? file.type : file.type;\n const body = this.isFileInput(file) ? file.data : file;\n\n const uploadUrl = await getUploadUrl(fileName, mimeType);\n const { url, file_id: objectPath, headers } = uploadUrl;\n\n const uploadResponse = await fetch(url, {\n method: \"PUT\",\n body,\n headers: { \"Content-Type\": mimeType, ...headers },\n });\n if (!uploadResponse.ok) {\n throw new Error(`File upload failed for \"${fileName}\": HTTP ${uploadResponse.status}`);\n }\n\n return { file_id: objectPath, type: \"user_upload\", file_name: fileName, mime_type: mimeType };\n }\n\n private async uploadProjectFiles(projectId: string, files: (File | FileInput)[]): Promise<UnscopedFile[]> {\n return Promise.all(\n files.map((file) =>\n this.uploadFile(file, (_fileName, mimeType) =>\n this.getProjectFileUploadUrl(projectId, { content_type: mimeType }),\n ),\n ),\n );\n }\n\n private async uploadEphemeralFiles(files: (File | FileInput)[]): Promise<UnscopedFile[]> {\n return Promise.all(\n files.map((file) =>\n this.uploadFile(file, (_fileName, mimeType) => this.getEphemeralFileUploadUrl({ content_type: mimeType })),\n ),\n );\n }\n\n private partitionUploadedFiles(files: UnscopedFile[]): {\n fileRefs: UnscopedFile[] | undefined;\n ephemeralFileRefs: UnscopedFile[] | undefined;\n } {\n const fileRefs: UnscopedFile[] = [];\n const ephemeralFileRefs: UnscopedFile[] = [];\n for (const file of files) {\n if (file.file_id.startsWith(\"ephemeral/\")) {\n ephemeralFileRefs.push(file);\n } else {\n fileRefs.push(file);\n }\n }\n return {\n fileRefs: fileRefs.length > 0 ? fileRefs : undefined,\n ephemeralFileRefs: ephemeralFileRefs.length > 0 ? ephemeralFileRefs : undefined,\n };\n }\n /**\n * Wait for a project to be published (deployed).\n *\n * This method polls until the project has `is_published: true` and a `url`.\n *\n * @param projectId - The project ID to wait for\n * @param options.pollInterval - Time between polls in ms (default: 3000)\n * @param options.timeout - Maximum time to wait in ms (default: 600000 = 10 minutes)\n * @param options.onProgress - Optional callback for status updates\n * @returns The published project with URL\n * @throws Error if timeout is reached\n */\n async waitForProjectPublished(projectId: string, options?: WaitOptions): Promise<ProjectResponse> {\n const pollInterval = options?.pollInterval ?? 3000;\n const timeout = options?.timeout ?? 600000;\n const startTime = Date.now();\n\n while (true) {\n const project = await this.getProject(projectId);\n options?.onProgress?.(project);\n\n if (project.is_published && project.url) {\n return project;\n }\n\n if (project.status === \"failed\") {\n throw new Error(`Project ${projectId} failed to build`);\n }\n\n if (Date.now() - startTime > timeout) {\n throw new Error(`Timeout waiting for project ${projectId} to be published`);\n }\n\n await sleep(pollInterval);\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isAbortError(err: unknown): boolean {\n return typeof err === \"object\" && err !== null && \"name\" in err && err.name === \"AbortError\";\n}\n\nasync function safeReadText(response: Response): Promise<string> {\n try {\n return await response.text();\n } catch {\n return \"\";\n }\n}\n\nasync function cancelResponseBody(response: Response): Promise<void> {\n try {\n await response.body?.cancel();\n } catch {}\n}\n\nasync function* parseSSEFrames(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<{ event: string; data: string }, void, void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let sep = buffer.indexOf(\"\\n\\n\");\n while (sep !== -1) {\n const raw = buffer.slice(0, sep);\n buffer = buffer.slice(sep + 2);\n sep = buffer.indexOf(\"\\n\\n\");\n\n let event = \"message\";\n const dataLines: string[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) continue;\n if (line.startsWith(\"event:\")) {\n event = line.slice(6).trimStart();\n } else if (line.startsWith(\"data:\")) {\n dataLines.push(line.slice(5).trimStart());\n }\n }\n if (dataLines.length === 0) continue;\n yield { event, data: dataLines.join(\"\\n\") };\n }\n }\n } finally {\n try {\n reader.releaseLock();\n } catch {\n // ignore\n }\n try {\n await body.cancel();\n } catch {\n // ignore\n }\n }\n}\n\nfunction terminalResultFromMessage(msg: GetMessageResponse, fallbackMessageId: string): MessageCompletionResult | null {\n const ai = msg.response;\n if (ai && isTerminalAIStatus(ai.status)) {\n return {\n status: messageCompletionStatus(ai.status),\n message_id: ai.message_id || fallbackMessageId,\n content: ai.content,\n edit_id: ai.edit_id,\n commit_sha: ai.commit_sha,\n summary: ai.summary,\n cost_credits: ai.cost_credits,\n awaiting_input: ai.awaiting_input,\n ...(ai.status === \"error\" ? { error: \"Agent reported an error.\" } : {}),\n };\n }\n if (msg.role === \"assistant\" && isTerminalAIStatus(msg.status)) {\n return {\n status: messageCompletionStatus(msg.status),\n message_id: msg.message_id || fallbackMessageId,\n content: msg.content,\n edit_id: msg.edit_id,\n commit_sha: msg.commit_sha,\n summary: msg.summary,\n cost_credits: msg.cost_credits,\n awaiting_input: msg.awaiting_input,\n ...(msg.status === \"error\" ? { error: \"Agent reported an error.\" } : {}),\n };\n }\n return null;\n}\n\nfunction messageCompletionStatus(status: string): MessageCompletionResult[\"status\"] {\n return status === \"completed\" || status === \"stopped\" || status === \"awaiting_input\" ? status : \"error\";\n}\n\nfunction isTerminalAIStatus(status: string | undefined): boolean {\n return status === \"completed\" || status === \"stopped\" || status === \"error\" || status === \"awaiting_input\";\n}\n\nfunction queuedExitResult(msg: GetMessageResponse, fallbackMessageId: string): MessageCompletionResult | null {\n if (msg.status !== \"queued\") return null;\n if (!msg.queue_paused) return null;\n if (msg.queue_pause_reason === \"hitl_tool\") return null;\n return {\n status: \"error\",\n message_id: fallbackMessageId,\n content: \"\",\n error:\n `Message is queued (position ${msg.queue_position ?? \"unknown\"}) but the queue is paused` +\n (msg.queue_pause_reason ? ` (reason: ${msg.queue_pause_reason})` : \"\") +\n `. Unpause the queue in the Lovable editor, or use wait=false to return immediately.`,\n };\n}\n\nfunction timeoutResult(messageId: string, timeoutMs: number): MessageCompletionResult {\n return {\n status: \"timeout\",\n message_id: messageId,\n content: \"\",\n error: `Agent did not finish within ${Math.max(0, Math.round(timeoutMs / 1000))}s`,\n };\n}\n","const RETRY_DELAYS_MS = [100, 300, 500] as const;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nfunction parseRetryAfterMs(headers: Headers): number | undefined {\n const raw = headers.get(\"retry-after\");\n if (!raw) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const dateMs = Date.parse(raw);\n if (!Number.isNaN(dateMs)) {\n const delta = dateMs - Date.now();\n return delta > 0 ? delta : 0;\n }\n return undefined;\n}\n\nexport type RetryFetch = (input: Request) => Promise<Response>;\n\n/**\n * Wraps a fetch implementation with retry on HTTP 429. Up to three retries\n * at 100ms / 300ms / 500ms; if the server sends `Retry-After` and it's\n * larger than the planned delay, we honor the server value. The Request is\n * cloned before each attempt so its body remains replayable.\n *\n * Matches openapi-fetch's `fetch` option signature: a single `Request` in,\n * `Promise<Response>` out.\n */\nexport function makeRetryFetch(baseFetch: RetryFetch = (input) => globalThis.fetch(input)): RetryFetch {\n return async (input) => {\n // Request.clone() and the fetch parameter resolve to different Request type\n // definitions when @types/node (undici) and @types/bun are both in scope;\n // the cloned object is structurally the same Request, so assert the param type.\n const clone = (): Parameters<RetryFetch>[0] => input.clone() as Parameters<RetryFetch>[0];\n let response = await baseFetch(clone());\n for (const planned of RETRY_DELAYS_MS) {\n if (response.status !== 429) break;\n const serverDelay = parseRetryAfterMs(response.headers);\n await sleep(Math.max(planned, serverDelay ?? 0));\n response = await baseFetch(clone());\n }\n return response;\n };\n}\n","// Type definitions for the Lovable SDK.\n//\n// Response and request body types come straight from the generated OpenAPI\n// types (`./generated/paths.ts`, produced by `openapi-typescript` from the\n// trimmed v1 spec). The same trimmed spec also drives `./generated/zod/`\n// (consumed by `@lovable.dev/sdk/schemas` for runtime validation), so the\n// type aliases here are guaranteed to match the schemas the MCP server\n// uses — there is no hand-maintained parallel shape to drift.\n//\n// Types that don't have a 1:1 OpenAPI counterpart (request options, SDK\n// wrappers like `MessageCompletionResult` that re-shape responses, helper\n// interfaces like `FileInput`) stay hand-written below.\n\nimport type { components, paths } from \"./generated/paths.js\";\n\ntype Schemas = components[\"schemas\"];\n\ntype ListProjectsQuery = NonNullable<paths[\"/v1/projects\"][\"get\"][\"parameters\"][\"query\"]>;\ntype ListConnectorsQuery = NonNullable<paths[\"/v1/connectors\"][\"get\"][\"parameters\"][\"query\"]>;\n\n// =============================================================================\n// API types — derived from the OpenAPI spec\n// =============================================================================\n\n// --- Users & workspaces ---\n\nexport type MeWorkspace = Schemas[\"GetMeWorkspace\"];\nexport type MeResponse = Schemas[\"GetMeOutputBody\"];\nexport type WorkspaceMembership = Schemas[\"WorkspaceMembership\"];\nexport type WorkspaceWithMembership = Schemas[\"WorkspaceWithMembership\"];\nexport type GetWorkspacesResponse = Schemas[\"V1ListWorkspacesBody\"];\n\n// Role enum lives on WorkspaceMembership in the spec; reuse it so SDK callers\n// always pick from the same set the server returns.\nexport type MemberRole = WorkspaceMembership[\"role\"];\n\n// --- Projects ---\n\n// Lean shape returned by GET /v1/projects/{id} and POST /v1/projects.\nexport type ProjectResponse = Schemas[\"V1ProjectResponse\"];\nexport type CreateProjectResponse = Schemas[\"PublicV1CreateProjectResponse\"] & { id: string };\nexport type CreateProjectBody = Omit<Schemas[\"PublicV1ProjectCreateInputBody\"], \"workspace_id\">;\nexport type UpdateProjectOptions = Schemas[\"PublicV1PatchProjectBody\"];\nexport type EmbedURLResponse = Schemas[\"V1CreateEmbedURLOutputBody\"];\n\n// Wider listing shape returned by the search endpoint.\nexport type ListProjectItem = Schemas[\"SearchProjectItem\"];\nexport type ListProjectsResponse = Schemas[\"CursorListResponseSearchProjectItem\"] & {\n projects: ListProjectItem[] | null;\n total?: number;\n has_more?: boolean;\n};\nexport type GetWorkspaceProjectsResponse = ListProjectsResponse;\nexport type MoveProjectsToFolderResponse = Schemas[\"AddProjectsToFolderResult\"];\n\n// Visibility enum is narrowest on SearchProjectItem (\"public\" | \"private\" | \"draft\");\n// V1ProjectResponse types visibility as plain string. Use the narrower one.\nexport type ProjectVisibility = NonNullable<ListProjectItem[\"visibility\"]>;\nexport type ProjectPatchVisibility = NonNullable<UpdateProjectOptions[\"visibility\"]>;\n\n// --- Messages ---\n\nexport type SendMessageResponse = Schemas[\"V1SendMessageOutputBody\"];\nexport type GetMessageResponse = Schemas[\"V1MessageResponse\"];\nexport type MessageSummary = Schemas[\"V1MessageListItem\"];\ntype AwaitingInputSummary = Partial<Schemas[\"V1AwaitingInputSummary\"]>;\nexport type ListMessagesResponse = Schemas[\"CursorListResponseV1MessageListItem\"] & {\n messages: MessageSummary[] | null;\n has_more: boolean;\n};\nexport interface ListMessagesOptions {\n limit?: number;\n cursor?: string;\n /** @deprecated Use `cursor` from `pagination.next_cursor`; kept for source compatibility. */\n before?: string;\n}\n\nexport interface ChatResponse {\n content: string;\n previewUrl: string;\n messageId: string;\n}\n\nexport interface ChatResponseOptions {\n timeout?: number;\n}\n\nexport type CreateVariantResponse = Schemas[\"V1CreateVariantOutputBody\"];\n\n// --- Deployment ---\n\nexport type DeploymentResponse = Schemas[\"V1DeployProjectOutputBody\"];\n\n// --- Database ---\n\nexport type DatabaseStatus = Schemas[\"V1GetDatabaseStatusOutputBody\"];\nexport type EnableDatabaseResult = Schemas[\"V1EnableDatabaseOutputBody\"];\n// POST /v1/database/query is served but sits outside the public OpenAPI\n// boundary, so no generated type exists; hand-maintained for queryDatabase\n// and the MCP query_database tool.\nexport type DatabaseQueryResult = {\n rows: Record<string, unknown>[] | null;\n};\n\n// --- Knowledge ---\n\nexport type KnowledgeResponse = Schemas[\"V1KnowledgeResponse\"];\n\n// --- Skills ---\n\nexport type WorkspaceSkillFile = Schemas[\"ProjectFileInfo\"];\nexport type WorkspaceSkill = Schemas[\"V1WorkspaceSkillDTO\"];\nexport type ListWorkspaceSkillsResponse = Schemas[\"V1ListWorkspaceSkillsOutputBody\"];\nexport type WorkspaceSkillResponse = Schemas[\"V1GetWorkspaceSkillOutputBody\"];\nexport type WorkspaceSkillWriteResponse = Schemas[\"V1WriteWorkspaceSkillOutputBody\"];\nexport type WorkspaceSkillDeleteResponse = Schemas[\"V1DeleteWorkspaceSkillOutputBody\"];\n\nexport type ProjectSkill = Schemas[\"V1ProjectSkillDTO\"];\nexport type ListProjectSkillsResponse = Schemas[\"CursorListResponseV1ProjectSkillDTO\"] & {\n skills: ProjectSkill[];\n};\nexport type ProjectSkillResponse = Schemas[\"V1SetProjectSkillEnabledOutputBody\"];\n\n// --- File upload ---\n\nexport type FileUploadUrlResponse = Schemas[\"V1FileUploadURLOutputBody\"];\nexport type UnscopedFile = Schemas[\"V1UnscopedFile\"];\n\n// --- Git / diffs / files / edits ---\n\nexport type DiffLine = Schemas[\"DiffLine\"];\nexport type DiffHunk = Schemas[\"DiffHunk\"];\nexport type DiffEntry = Schemas[\"V1DiffEntry\"];\nexport type GitDiffResponse = Schemas[\"V1DiffResponse\"];\nexport type GitFileEntry = Schemas[\"GitFileEntryLite\"];\nexport type GitFilesResponse = Schemas[\"PublicV1GitFilesResponse\"] & { files: GitFileEntry[] };\nexport type EditSummary = Schemas[\"V1EditSummary\"];\nexport type EditsResponse = Schemas[\"V1GetEditsOutputBody\"];\n\n// --- Libraries & templates ---\n\nexport type LibraryProjectResponse = Record<string, unknown>;\nexport type TemplateProjectResponse = Record<string, unknown>;\nexport type ListLibraryProjectsResponse = {\n libraries: LibraryProjectResponse[];\n total?: number;\n has_more?: boolean;\n};\nexport type ListTemplateProjectsResponse = {\n templates: TemplateProjectResponse[];\n total?: number;\n has_more?: boolean;\n};\n\n// --- Connectors ---\n\nexport type ConnectorResponse = Schemas[\"V1ConnectorResponse\"];\nexport type AvailableConnectorEntry = Schemas[\"V1AvailableConnectorEntry\"];\nexport type AddConnectorBody = Omit<Schemas[\"PublicV1AddConnectorBody\"], \"workspace_id\">;\nexport type ConnectorItem = Schemas[\"PublicV1ConnectorItem\"];\nexport type StandardConnectorItem = ConnectorItem;\nexport type SeamlessConnectorItem = ConnectorItem;\nexport type MCPConnectorItem = ConnectorItem;\nexport type ConnectionItem = Schemas[\"V1ConnectionItem\"];\nexport type ListConnectorsResponse = Omit<Schemas[\"CursorListResponsePublicV1ConnectorItem\"], \"data\"> & {\n data: ConnectorItem[];\n connectors: ConnectorItem[];\n has_more: boolean;\n};\nexport type ListAvailableConnectorsResponse = Omit<Schemas[\"CursorListResponseV1AvailableConnectorEntry\"], \"data\"> & {\n data: AvailableConnectorEntry[];\n catalog: AvailableConnectorEntry[];\n has_more: boolean;\n};\nexport type ListStandardConnectorsResponse = Omit<ListConnectorsResponse, \"connectors\"> & {\n connectors: StandardConnectorItem[];\n};\nexport type ListSeamlessConnectorsResponse = Omit<ListConnectorsResponse, \"connectors\"> & {\n connectors: SeamlessConnectorItem[];\n};\nexport type ListMCPConnectorsResponse = Omit<ListConnectorsResponse, \"connectors\"> &\n Partial<Omit<Schemas[\"V1ListMCPConnectorsResponse\"], \"connectors\">> & {\n data: MCPConnectorItem[];\n connectors: MCPConnectorItem[];\n };\nexport type ListConnectionsResponse = Omit<Schemas[\"CursorListResponseV1ConnectionItem\"], \"data\"> & {\n data: ConnectionItem[];\n connections: ConnectionItem[];\n has_more: boolean;\n};\n\n// --- Analytics ---\n\nexport type TimeSeriesDataPoint = Schemas[\"TimeSeriesDataPoint\"];\nexport type TimeSeriesData = Schemas[\"TimeSeriesData\"];\nexport type ListDataPoint = Schemas[\"ListDataPoint\"];\nexport type ListData = Schemas[\"ListData\"];\nexport type ProjectAnalyticsResponse = Schemas[\"ProjectAnalyticsResponse\"];\nexport type TrendDataPoint = Schemas[\"TrendDataPoint\"];\nexport type ProjectAnalyticsTrendResponse = Schemas[\"ProjectTrendResponse\"];\n\n// --- Remix ---\n\nexport type RemixJobStepInfo = Schemas[\"RemixJobStepInfo\"];\nexport type RemixInitResponse = { job_id: string };\nexport type RemixProgressResult = Schemas[\"V1RemixProgressResult\"];\nexport type RemixProgressResponse = {\n status: string;\n step?: RemixJobStepInfo;\n result?: RemixProgressResult;\n error_message?: string;\n error_code?: string;\n};\n\n// The V1 spec types `status` as plain string. The Go handler returns one of\n// these five values — keep the narrow union here as an SDK-side aid for\n// callers that switch on it. If the spec ever exposes this as an enum,\n// replace with `Schemas[\"V1RemixProgressOutputBody\"][\"status\"]`.\nexport type RemixJobStatus = \"unknown\" | \"preparing\" | \"running\" | \"completed\" | \"error\";\nexport type RemixJobStep =\n | \"starting\"\n | \"creating_new_project\"\n | \"restoring_supabase\"\n | \"copying_history\"\n | \"preparing_repository\"\n | \"remixing_integration\"\n | \"pushing_repository\"\n | \"finalizing\"\n | \"completed\";\n\n// V1 status field on V1ProjectResponse is plain string; the Go handler returns\n// one of these three. Same rationale as RemixJobStatus.\nexport type ProjectStatus = \"completed\" | \"in_progress\" | \"failed\";\n\n// =============================================================================\n// SDK helpers — no OpenAPI counterpart\n// =============================================================================\n\nexport interface ChatRequest {\n id: string;\n message: string;\n chat_only: boolean;\n headless: boolean;\n ai_message_id?: string;\n intent?: string;\n model?: string;\n temperature?: number;\n current_page?: string;\n view?: string;\n view_description?: string;\n prev_session_id?: string;\n is_creation?: boolean;\n files?: UnscopedFile[];\n}\n\n/** @deprecated `remixProject()` now uses POST /v1/projects with `source_project_id`. */\nexport interface RemixInitBody extends Omit<Schemas[\"V1RemixInitInputBody\"], \"initial_message\"> {\n initial_message?: ChatRequest;\n message_id?: string;\n remix_mode?: RemixMode;\n skip_integrations?: boolean;\n}\n\nexport type RemixCreateProjectBody = Schemas[\"PublicV1ProjectRemixInputBody\"];\n\nexport interface FileInput {\n name: string;\n data: Blob | ArrayBuffer | Uint8Array;\n type: string;\n}\n\nexport interface CreateProjectOptions {\n description: string;\n projectName?: string;\n techStack?: string;\n /** Sandbox runtime template. Requires a workspace with access to the requested template. */\n sandboxTemplate?: string;\n visibility?: ProjectVisibility;\n templateProjectId?: string;\n initialMessage?: string;\n /** Files to upload and attach to the initial message. The SDK handles uploading. */\n files?: (File | FileInput)[];\n /** Pre-uploaded file references to attach to the initial message. Skips upload. */\n uploadedFiles?: UnscopedFile[];\n /** Public image or HTML file URLs to fetch server-side and attach to the initial message. */\n fileUrls?: string[];\n /** Design system library projects to connect to the new project. */\n selectedLibraries?: { project_id: string }[];\n}\n\n/**\n * Controls prompt cache continuation behavior for a message.\n *\n * - `\"force\"` — skip cache TTL and token/criteria checks (force continuation)\n * - `\"fresh_build\"` — force a full prompt rebuild from scratch\n * - `\"allow_expired_cache\"` — skip cache TTL check but respect token/criteria limits\n *\n * Omit for default behavior (5-min TTL, token and criteria checks apply).\n */\nexport type ContinuationOverride = \"force\" | \"fresh_build\" | \"allow_expired_cache\";\n\nexport interface ChatMessageOptions {\n message: string;\n /** Send the message to this project variant instead of the main agent. */\n variantId?: string;\n /** Files to upload and attach. The SDK handles uploading them first. */\n files?: (File | FileInput)[];\n /** Pre-uploaded file references. Skips upload. */\n uploadedFiles?: UnscopedFile[];\n /** Enable plan mode: the agent discusses and plans without editing code. */\n planMode?: boolean;\n /**\n * Override continuation behavior for this message.\n * Controls whether the agent reuses the prompt cache or rebuilds from scratch.\n */\n continuation?: ContinuationOverride;\n}\n\nexport interface CreateVariantOptions {\n /** Display name. The API assigns the next Draft number when omitted. */\n label?: string;\n /** Full 40-character commit SHA to base the variant branch on. Defaults to the project main branch. */\n baseSha?: string;\n}\n\nexport interface LovableClientOptions {\n /** API key for authentication (mutually exclusive with bearerToken) */\n apiKey?: string;\n /** Bearer token for OAuth authentication (mutually exclusive with apiKey) */\n bearerToken?: string;\n baseUrl?: string;\n /** Additional headers to include on every request */\n headers?: Record<string, string>;\n /**\n * Identifier for the originating client, sent as the `X-Client-Source` header.\n * Used by the API to tag audit logs and observability with the message origin.\n * Defaults to `\"sdk\"`. The Go API allowlist accepts `\"mcp\"`, `\"sdk\"`, `\"cli\"`.\n */\n clientSource?: string;\n}\n\nexport interface LovableError extends Error {\n status: number;\n type?: string;\n detail?: string;\n}\n\nexport interface WaitOptions {\n pollInterval?: number;\n timeout?: number;\n onProgress?: (project: ProjectResponse) => void;\n}\n\nexport interface ListCursorPaginationOptions {\n limit?: number;\n cursor?: string;\n}\n\nexport interface ListOffsetPaginationOptions {\n limit?: number;\n offset?: number;\n}\n\nexport interface ListHybridPaginationOptions {\n limit?: number;\n cursor?: string;\n offset?: number;\n}\n\nexport type ListConnectorsOptions = Omit<ListConnectorsQuery, \"workspace_id\">;\n\n/** @deprecated Use the cursor, offset, or hybrid pagination option type that matches the route. */\nexport type ListPaginationOptions = ListHybridPaginationOptions;\n\nexport type CursorPaginationOptions = ListCursorPaginationOptions;\n\nexport type RemixMode = \"before\" | \"including\";\n\nexport interface RemixProjectOptions {\n workspaceId: string;\n messageId?: string;\n remixMode?: RemixMode;\n includeHistory?: boolean;\n includeCustomKnowledge?: boolean;\n initialMessage?: string;\n description?: string;\n projectName?: string;\n skipInitialRemixMessage?: boolean;\n skipIntegrations?: boolean;\n}\n\n// camelCase wrapper — not a direct alias of V1RemixProgressResult.\nexport interface RemixResult {\n projectId: string;\n}\n\nexport interface RemixWaitOptions {\n pollInterval?: number;\n timeout?: number;\n onProgress?: (status: RemixJobStatus, step?: RemixJobStepInfo) => void;\n}\n\nexport interface MessageCompletionResult {\n status: \"completed\" | \"stopped\" | \"awaiting_input\" | \"timeout\" | \"error\";\n message_id: string;\n content: string;\n awaiting_input?: AwaitingInputSummary;\n edit_id?: string;\n commit_sha?: string;\n summary?: string;\n cost_credits?: number;\n error?: string;\n}\n\nexport interface MessageCompletionOptions {\n /** Trajectory thread returned by chat(). Enables thread-aware completion. */\n threadId?: string;\n /**\n * Maximum seconds the server holds each long-poll request before returning\n * a non-terminal snapshot. Clamped server-side to [0, 55]. Defaults to 30.\n */\n waitSeconds?: number;\n /** Maximum total time to wait in ms (default: 600000 = 10 minutes) */\n timeout?: number;\n /**\n * @deprecated Long-poll replaces client-side polling; this is ignored.\n * Kept for source-compat with callers that still pass it.\n */\n pollInterval?: number;\n}\n\nexport interface GetMessageOptions {\n /** Trajectory thread returned by chat(). Enables thread-aware status reads. */\n threadId?: string;\n /**\n * Long-poll: ask the server to hold the request until the message reaches a\n * terminal state or this many seconds elapse. Clamped server-side to [0, 55].\n */\n waitSeconds?: number;\n}\n\nexport interface ListProjectsOptions {\n /** Full-text search; mapped to `q` on the wire. */\n query?: string;\n visibility?: ListProjectsQuery[\"visibility\"];\n publish_status?: ListProjectsQuery[\"publish_status\"];\n folder_id?: ListProjectsQuery[\"folder_id\"];\n folder_ids?: ListProjectsQuery[\"folder_ids\"];\n user_id?: ListProjectsQuery[\"user_id\"];\n type?: ListProjectsQuery[\"type\"];\n include_risk?: ListProjectsQuery[\"include_risk\"];\n search_fields?: ListProjectsQuery[\"search_fields\"];\n viewed_by_me?: ListProjectsQuery[\"viewed_by_me\"];\n cursor?: ListProjectsQuery[\"cursor\"];\n limit?: ListProjectsQuery[\"limit\"];\n}\n\n// =============================================================================\n// Runtime exports\n// =============================================================================\n\nexport interface RateLimitInfo {\n /** X-RateLimit-Limit: the request budget for the current window. */\n limit?: number;\n /** X-RateLimit-Remaining: requests left in the current window. */\n remaining?: number;\n /** Retry-After in milliseconds (parsed from the Retry-After header). */\n retryAfterMs?: number;\n}\n\nexport class ApiError extends Error {\n readonly status: number;\n readonly type?: string;\n readonly detail?: string;\n readonly props?: Record<string, unknown>;\n readonly rateLimit?: RateLimitInfo;\n\n constructor(\n status: number,\n message: string,\n type?: string,\n detail?: string,\n props?: Record<string, unknown>,\n rateLimit?: RateLimitInfo,\n ) {\n super(message);\n this.status = status;\n this.type = type;\n this.detail = detail;\n this.props = props;\n this.rateLimit = rateLimit;\n }\n}\n"],"mappings":";AAEA,OAAO,kBAAkB;;;ACFzB,IAAM,kBAAkB,CAAC,KAAK,KAAK,GAAG;AAEtC,IAAM,QAAQ,CAAC,OAA8B,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAE7F,SAAS,kBAAkB,SAAsC;AAC/D,QAAM,MAAM,QAAQ,IAAI,aAAa;AACrC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,UAAU,OAAO,GAAG;AAC1B,MAAI,OAAO,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO,UAAU;AAC/D,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,MAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,UAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC7B;AACA,SAAO;AACT;AAaO,SAAS,eAAe,YAAwB,CAAC,UAAU,WAAW,MAAM,KAAK,GAAe;AACrG,SAAO,OAAO,UAAU;AAItB,UAAM,QAAQ,MAAiC,MAAM,MAAM;AAC3D,QAAI,WAAW,MAAM,UAAU,MAAM,CAAC;AACtC,eAAW,WAAW,iBAAiB;AACrC,UAAI,SAAS,WAAW,IAAK;AAC7B,YAAM,cAAc,kBAAkB,SAAS,OAAO;AACtD,YAAM,MAAM,KAAK,IAAI,SAAS,eAAe,CAAC,CAAC;AAC/C,iBAAW,MAAM,UAAU,MAAM,CAAC;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AACF;;;AC2aO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,QACA,SACA,MACA,QACA,OACA,WACA;AACA,UAAM,OAAO;AACb,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,YAAY;AAAA,EACnB;AACF;;;AF1XA,IAAM,mBAAmB;AACzB,IAAM,4BAA4B;AAElC,SAAS,iBAAiB,KAAiC;AACzD,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,aAAa,IAAI,QAAQ,OAAO,EAAE;AAExC,MAAI,CAAC,WAAW,WAAW,SAAS,KAAK,CAAC,WAAW,WAAW,UAAU,GAAG;AAC3E,UAAM,IAAI,MAAM,gEAAgE,GAAG,GAAG;AAAA,EACxF;AAEA,SAAO;AACT;AAEA,SAAS,mBAAmB,IAAoB;AAC9C,QAAM,MAAM,KAAK,UAAU,EAAE,GAAG,2BAA2B,GAAG,CAAC;AAC/D,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,GAAG;AAC1C,MAAI,SAAS;AACb,aAAW,QAAQ,OAAO;AACxB,cAAU,OAAO,aAAa,IAAI;AAAA,EACpC;AACA,SAAO,KAAK,MAAM,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAC/E;AAEA,SAAS,uBAA0B,MAA2D;AAC5F,SAAO,KAAK,QAAQ,KAAK,cAAc,CAAC;AAC1C;AAEA,SAAS,cAAc,MAAmF;AACxG,SAAO,KAAK,YAAY,YAAY,KAAK,YAAY;AACvD;AAEA,SAAS,uBAAkD,SAAgC;AACzF,MAAI,CAAC,QAAQ,GAAI,OAAM,IAAI,MAAM,4CAA4C;AAC7E,SAAO;AACT;AAOA,IAAM,kBAA8B;AAAA,EAClC,MAAM,WAAW,EAAE,SAAS,GAAG;AAC7B,QAAI,SAAS,GAAI;AACjB,QAAI;AAUJ,QAAI;AACF,kBAAa,MAAM,SAAS,MAAM,EAAE,KAAK;AAAA,IAC3C,QAAQ;AAAA,IAER;AACA,UAAM,UAAU,kBAAkB,WAAW,SAAS,QAAQ,SAAS,UAAU;AACjF,UAAM,OAAO,WAAW,QAAQ,WAAW;AAC3C,UAAM,SAAS,WAAW,UAAU,WAAW;AAC/C,UAAM,IAAI,SAAS,SAAS,QAAQ,SAAS,MAAM,QAAQ,WAAW,OAAO,mBAAmB,SAAS,OAAO,CAAC;AAAA,EACnH;AACF;AAEA,SAAS,mBAAmB,SAA6C;AACvE,QAAM,QAAQ,iBAAiB,QAAQ,IAAI,mBAAmB,CAAC;AAC/D,QAAM,YAAY,iBAAiB,QAAQ,IAAI,uBAAuB,CAAC;AACvE,QAAM,eAAeA,mBAAkB,QAAQ,IAAI,aAAa,CAAC;AACjE,MAAI,SAAS,QAAQ,aAAa,QAAQ,gBAAgB,KAAM,QAAO;AACvE,SAAO,EAAE,OAAO,WAAW,aAAa;AAC1C;AAEA,SAAS,iBAAiB,KAAwC;AAChE,MAAI,OAAO,KAAM,QAAO;AACxB,QAAM,IAAI,OAAO,GAAG;AACpB,SAAO,OAAO,SAAS,CAAC,KAAK,KAAK,IAAI,IAAI;AAC5C;AAEA,SAASA,mBAAkB,KAAwC;AACjE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,UAAU,OAAO,GAAG;AAC1B,MAAI,OAAO,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO,UAAU;AAC/D,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,MAAI,CAAC,OAAO,MAAM,MAAM,GAAG;AACzB,UAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC7B;AACA,SAAO;AACT;AAMA,SAAS,kBACP,MACA,QACA,YACQ;AACR,SAAO,MAAM,WAAW,MAAM,UAAU,aAAa,QAAQ,MAAM,KAAK,UAAU,KAAK,QAAQ,MAAM;AACvG;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA+B;AACzC,UAAM,YAAY,CAAC,CAAC,QAAQ;AAC5B,UAAM,iBAAiB,CAAC,CAAC,QAAQ;AAEjC,QAAI,CAAC,aAAa,CAAC,gBAAgB;AACjC,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,QAAI,aAAa,gBAAgB;AAC/B,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AAEA,SAAK,cAAc,YACf,EAAE,mBAAmB,QAAQ,OAAQ,IACrC,EAAE,eAAe,UAAU,QAAQ,WAAW,GAAG;AAErD,SAAK,UAAU,iBAAiB,QAAQ,OAAO;AAC/C,SAAK,eAAe,QAAQ,WAAW,CAAC;AACxC,SAAK,eAAe,QAAQ,gBAAgB;AAE5C,SAAK,cAAc,aAAoB;AAAA,MACrC,SAAS,KAAK;AAAA,MACd,SAAS;AAAA,QACP,mBAAmB,KAAK;AAAA,QACxB,GAAG,KAAK;AAAA,QACR,GAAG,KAAK;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA,OAAO,eAAe;AAAA,IACxB,CAAC;AACD,SAAK,YAAY,IAAI,eAAe;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,QAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAA0B;AAC9B,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,QAAQ;AAC9C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,YAAY;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,UAAuC,CAAC,GAAmC;AAC9F,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACtD,QAAQ,EAAE,OAAO,QAAQ;AAAA,IAC3B,CAAC;AACD,WAAO,EAAE,GAAG,MAAO,YAAY,uBAAgD,IAAK,EAAE;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,aAAqB;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,iCAAiC;AAAA,MACrE,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,EAAE;AAAA,IAChD,CAAC;AACD,WAAO,KAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,aAAqB,SAA8D;AACpG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gBAAgB;AAAA,MACpD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,cAAc;AAAA,UACd,GAAG,SAAS;AAAA,UACZ,YAAY,SAAS;AAAA,UACrB,gBAAgB,SAAS;AAAA,UACzB,WAAW,SAAS;AAAA,UACpB,YAAY,SAAS;AAAA,UACrB,SAAS,SAAS;AAAA,UAClB,MAAM,SAAS;AAAA,UACf,cAAc,SAAS;AAAA,UACvB,eAAe,SAAS;AAAA,UACxB,cAAc,SAAS;AAAA,UACvB,QAAQ,SAAS;AAAA,UACjB,OAAO,SAAS;AAAA,QAClB;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,WACH,KAAoE,YAAY,KAAM,QAAQ;AACjG,UAAM,QAAS,KAAuC;AACtD,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,GAAI,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;AAAA,MACvC,UAAU,KAAM,YAAY,YAAa,KAA2C;AAAA,IACtF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,aAAqB,SAA+D;AACtG,QAAI;AACJ,QAAI;AACJ,QAAI,QAAQ,eAAe,QAAQ;AACjC,OAAC,EAAE,UAAU,kBAAkB,IAAI,KAAK,uBAAuB,QAAQ,aAAa;AAAA,IACtF,WAAW,QAAQ,OAAO,QAAQ;AAChC,0BAAoB,MAAM,KAAK,qBAAqB,QAAQ,KAAK;AAAA,IACnE;AAEA,UAAM,OAA0B;AAAA,MAC9B,aAAa,QAAQ;AAAA,MACrB,qBAAqB,QAAQ;AAAA,IAC/B;AACA,QAAI,QAAQ,aAAa;AACvB,WAAK,eAAe,QAAQ;AAAA,IAC9B;AACA,QAAI,QAAQ,YAAY;AACtB,WAAK,aAAa,QAAQ;AAAA,IAC5B;AACA,QAAI,QAAQ,WAAW;AACrB,WAAK,aAAa,QAAQ;AAAA,IAC5B;AACA,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,mBAAmB,QAAQ;AAAA,IAClC;AACA,QAAI,QAAQ,mBAAmB,QAAQ;AACrC,WAAK,qBAAqB,QAAQ;AAAA,IACpC;AACA,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,kBAAkB,QAAQ;AAAA,IACjC;AACA,QAAI,UAAU,QAAQ;AACpB,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,QAAQ,UAAU,QAAQ;AAC5B,WAAK,YAAY,QAAQ;AAAA,IAC3B;AACA,QAAI,mBAAmB,QAAQ;AAC7B,WAAK,kBAAkB;AAAA,IACzB;AAEA,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,gBAAgB;AAAA,MACrD,MAAM,EAAE,GAAG,MAAM,cAAc,YAAY;AAAA,IAC7C,CAAC;AACD,WAAO,uBAAuB,IAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAK,WAAmB,SAA2D;AACvF,QAAI;AACJ,QAAI;AACJ,QAAI,QAAQ,eAAe,QAAQ;AACjC,OAAC,EAAE,UAAU,kBAAkB,IAAI,KAAK,uBAAuB,QAAQ,aAAa;AAAA,IACtF,WAAW,QAAQ,OAAO,QAAQ;AAChC,iBAAW,MAAM,KAAK,mBAAmB,WAAW,QAAQ,KAAK;AAAA,IACnE;AAEA,UAAM,OAAoE;AAAA,MACxE,SAAS,QAAQ;AAAA,IACnB;AACA,QAAI,QAAQ,WAAW;AACrB,WAAK,aAAa,QAAQ;AAAA,IAC5B;AACA,QAAI,UAAU;AACZ,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,mBAAmB;AACrB,WAAK,kBAAkB;AAAA,IACzB;AACA,QAAI,QAAQ,UAAU;AACpB,WAAK,YAAY;AAAA,IACnB;AACA,QAAI,QAAQ,cAAc;AACxB,WAAK,eAAe,QAAQ;AAAA,IAC9B;AAEA,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,gBAAgB;AAAA,MACrD,MAAM,EAAE,GAAG,MAAM,YAAY,UAAU;AAAA,IACzC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,WAAmB,UAAgC,CAAC,GAAmC;AACzG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,sCAAsC;AAAA,MAC3E,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,MAC1C,MAAM,EAAE,OAAO,QAAQ,OAAO,UAAU,QAAQ,QAAQ;AAAA,IAC1D,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,WAA6C;AAC5D,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,6BAA6B;AAAA,MACjE,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,IAC5C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,WAAmB,cAAiD;AACvF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,uCAAuC;AAAA,MAC5E,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,MAC1C,MAAM,EAAE,eAAe,aAAa;AAAA,IACtC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,WAAmB,SAAyD;AAC9F,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,MAAM,6BAA6B;AAAA,MACnE,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,MAC1C,MAAM;AAAA,IACR,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,WAAkC;AACpD,UAAM,KAAK,MAAM,OAAO,6BAA6B;AAAA,MACnD,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,IAC5C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cAAc,WAA2B;AACvC,WAAO,uBAAuB,SAAS;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgB,WAA2C;AAC/D,UAAM,UAAU,MAAM,KAAK,WAAW,SAAS;AAC/C,WAAO,QAAQ,gBAAgB,QAAQ,MAAM,QAAQ,MAAM;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,WAA4C;AAClE,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gBAAgB;AAAA,MACpD,QAAQ,EAAE,OAAO,EAAE,YAAY,UAAU,EAAE;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,eAAe,WAAkD;AACrE,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,uBAAuB;AAAA,MAC5D,MAAM,EAAE,YAAY,UAAU;AAAA,IAChC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,cAAc,WAAmB,KAA2C;AAGhF,UAAM,SAAS,KAAK;AACpB,UAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,sBAAsB;AAAA,MACvD,MAAM,EAAE,YAAY,WAAW,IAAI;AAAA,IACrC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WAAW,WAAmB,WAAmB,SAA0D;AAC/G,UAAM,cAAc,SAAS;AAC7B,UAAM,QAAQ;AAAA,MACZ,MAAM,eAAe,cAAc,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC,MAAM;AAAA,MACvE,WAAW,SAAS;AAAA,IACtB;AACA,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,6BAA6B;AAAA,MACjE,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,GAAG,OAAO,EAAE,GAAG,OAAO,YAAY,UAAU,EAAE;AAAA,IACxF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,WAAmB,QAA6D;AACjG,UAAM,SAAS,QAAQ,WAAW,QAAQ,SAAS,mBAAmB,OAAO,MAAM,IAAI;AACvF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gBAAgB;AAAA,MACpD,QAAQ;AAAA,QACN,OAAO,EAAE,YAAY,WAAW,OAAO,QAAQ,OAAO,OAAO;AAAA,MAC/D;AAAA,IACF,CAAC;AACD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,KAAM;AAAA,MAChB,UAAU,cAAc,IAAK;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,yBACJ,WACA,WACA,SACkC;AAClC,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,UAAM,MAAM,MAAM,KAAK,+BAA+B,WAAW,WAAW,UAAU,SAAS,QAAQ;AACvG,QAAI,IAAI,SAAS,UAAU;AACzB,aAAO,IAAI;AAAA,IACb;AACA,QAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,aAAO,cAAc,WAAW,OAAO;AAAA,IACzC;AACA,WAAO,KAAK,oCAAoC,WAAW,WAAW,UAAU,SAAS,OAAO;AAAA,EAClG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgB,WAAmB,SAAsD;AAC7F,UAAM,WAAW,MAAM,KAAK,aAAa,WAAW,EAAE,OAAO,GAAG,CAAC;AACjE,UAAM,SAAS,SAAS,UAAU,KAAK,CAAC,YAAY,QAAQ,SAAS,MAAM;AAE3E,QAAI,CAAC,QAAQ,YAAY;AACvB,YAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,IAC9D;AAEA,UAAM,oBAAoB,SAAS,YAAY,SAAY,SAAY,EAAE,SAAS,QAAQ,QAAQ;AAClG,UAAM,SAAS,MAAM,KAAK,yBAAyB,WAAW,OAAO,YAAY,iBAAiB;AAIlG,QAAI,OAAO,WAAW,eAAe,OAAO,WAAW,WAAW;AAChE,YAAM,IAAI,MAAM,OAAO,SAAS,WAAW,OAAO,UAAU,8BAA8B,OAAO,MAAM,GAAG;AAAA,IAC5G;AACA,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,WAAW,OAAO;AAAA,MAClB,YAAY,KAAK,cAAc,SAAS;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAc,+BACZ,WACA,WACA,UACA,UAC2G;AAC3G,UAAM,YAAY,WAAW,KAAK,IAAI;AACtC,QAAI,aAAa,EAAG,QAAO,EAAE,MAAM,UAAU;AAE7C,UAAM,MAAM,IAAI,IAAI,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,SAAS,CAAC,SAAS;AACzF,QAAI,aAAa,IAAI,cAAc,SAAS;AAC5C,QAAI,UAAU;AACZ,UAAI,aAAa,IAAI,aAAa,QAAQ;AAAA,IAC5C;AACA,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAEhE,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK;AAAA,QAC1B,SAAS;AAAA,UACP,GAAG,KAAK;AAAA,UACR,GAAG,KAAK;AAAA,UACR,mBAAmB,KAAK;AAAA,UACxB,QAAQ;AAAA,QACV;AAAA,QACA,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,mBAAa,SAAS;AACtB,UAAI,aAAa,GAAG,EAAG,QAAO,EAAE,MAAM,UAAU;AAChD,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,mBAAa,SAAS;AACtB,UAAI,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACjF,cAAM,mBAAmB,QAAQ;AACjC,eAAO,EAAE,MAAM,WAAW;AAAA,MAC5B;AACA,UAAI,SAAS,UAAU,KAAK;AAC1B,cAAM,mBAAmB,QAAQ;AACjC,eAAO,EAAE,MAAM,WAAW;AAAA,MAC5B;AACA,YAAM,SAAS,MAAM,aAAa,QAAQ;AAC1C,YAAM,IAAI,SAAS,SAAS,QAAQ,UAAU,QAAQ,SAAS,MAAM,EAAE;AAAA,IACzE;AAEA,QAAI,CAAC,SAAS,MAAM;AAClB,mBAAa,SAAS;AACtB,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAEA,QAAI;AACF,uBAAiB,SAAS,eAAe,SAAS,IAAI,GAAG;AACvD,YAAI,CAAC,MAAM,KAAM;AACjB,YAAI;AACJ,YAAI;AACF,qBAAW,KAAK,MAAM,MAAM,IAAI;AAAA,QAClC,QAAQ;AACN;AAAA,QACF;AAEA,cAAM,eAAe,iBAAiB,UAAU,SAAS;AACzD,YAAI,aAAc,QAAO,EAAE,MAAM,UAAU,QAAQ,aAAa;AAEhE,cAAM,WAAW,0BAA0B,UAAU,SAAS;AAC9D,YAAI,UAAU;AACZ,iBAAO,EAAE,MAAM,UAAU,QAAQ,SAAS;AAAA,QAC5C;AAAA,MACF;AACA,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B,SAAS,KAAK;AACZ,UAAI,aAAa,GAAG,EAAG,QAAO,EAAE,MAAM,UAAU;AAChD,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B,UAAE;AACA,mBAAa,SAAS;AACtB,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAc,oCACZ,WACA,WACA,UACA,gBACA,SACkC;AAClC,UAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,eAAe,EAAE,CAAC;AACxE,UAAM,qBAAqB;AAC3B,QAAI,gBAA+B;AACnC,UAAM,kBAAkB;AAExB,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,cAAc,WAAW,KAAK,IAAI;AACxC,YAAM,iBAAiB,KAAK,IAAI,aAAa,KAAK,MAAM,cAAc,GAAI,CAAC;AAC3E,YAAM,cAAc,iBAAiB,IAAI,EAAE,aAAa,eAAe,IAAI;AAE3E,YAAM,gBAAgB,KAAK,IAAI;AAC/B,UAAI;AACF,cAAM,MAAM,MAAM,KAAK,WAAW,WAAW,WAAW,EAAE,GAAG,aAAa,UAAU,SAAS,SAAS,CAAC;AACvG,wBAAgB;AAEhB,cAAM,eAAe,iBAAiB,KAAK,SAAS;AACpD,YAAI,aAAc,QAAO;AAEzB,cAAM,WAAW,0BAA0B,KAAK,SAAS;AACzD,YAAI,SAAU,QAAO;AAMrB,YAAI,KAAK,IAAI,IAAI,gBAAgB,oBAAoB;AACnD,gBAAMC,OAAM,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;AAAA,QAC9E;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,eAAe,UAAU;AAC3B,cAAI,IAAI,WAAW,KAAK;AACtB,gBAAI,kBAAkB,MAAM;AAC1B,8BAAgB,KAAK,IAAI;AAAA,YAC3B;AACA,gBAAI,KAAK,IAAI,IAAI,gBAAgB,iBAAiB;AAChD,oBAAMA,OAAM,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;AAC5E;AAAA,YACF;AACA,mBAAO;AAAA,cACL,QAAQ;AAAA,cACR,YAAY;AAAA,cACZ,SAAS;AAAA,cACT,OAAO;AAAA,YACT;AAAA,UACF;AACA,cAAI,IAAI,SAAS,KAAK;AACpB,kBAAM;AAAA,UACR;AAAA,QACF;AACA,cAAMA,OAAM,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC;AAAA,MAC9E;AAAA,IACF;AAEA,WAAO,cAAc,WAAW,cAAc;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,sBAAsB,aAAiD;AAC3E,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,2CAA2C;AAAA,MAC/E,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,EAAE;AAAA,IAChD,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,sBAAsB,aAAqB,SAA6C;AAC5F,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,2CAA2C;AAAA,MAC/E,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,EAAE;AAAA,MAC9C,MAAM,EAAE,QAAQ;AAAA,IAClB,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBACJ,aACA,UAAuE,CAAC,GAClC;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,wCAAwC;AAAA,MAC5E,QAAQ;AAAA,QACN,MAAM,EAAE,cAAc,YAAY;AAAA,QAClC,OAAO,EAAE,kBAAkB,QAAQ,iBAAiB,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,MACnG;AAAA,IACF,CAAC;AACD,WAAO,EAAE,GAAG,MAAO,QAAQ,KAAM,UAAU,CAAC,EAAE;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,kBAAkB,aAAqB,WAAoD;AAC/F,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,qDAAqD;AAAA,MACzF,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,YAAY,UAAU,EAAE;AAAA,IACvE,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,qBACJ,aACA,WACA,UACsC;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,qDAAqD;AAAA,MAC1F,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,YAAY,UAAU,EAAE;AAAA,MACrE,MAAM,EAAE,SAAS;AAAA,IACnB,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,qBACJ,aACA,WACA,UACsC;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,qDAAqD;AAAA,MACzF,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,YAAY,UAAU,EAAE;AAAA,MACrE,MAAM,EAAE,SAAS;AAAA,IACnB,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,qBAAqB,aAAqB,WAA0D;AACxG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,OAAO,qDAAqD;AAAA,MAC5F,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,YAAY,UAAU,EAAE;AAAA,IACvE,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBACJ,WACA,UAAuC,CAAC,GACJ;AACpC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,cAAc;AAAA,MAClD,QAAQ,EAAE,OAAO,EAAE,YAAY,WAAW,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAAA,IAC3F,CAAC;AACD,UAAM,SAAU,KAAqE,UAAU,KAAM,QAAQ,CAAC;AAC9G,WAAO,EAAE,GAAG,MAAO,OAAO;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,uBAAuB,WAAmB,WAAmB,SAAiD;AAClH,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,MAAM,2BAA2B;AAAA,MACjE,QAAQ,EAAE,MAAM,EAAE,YAAY,UAAU,EAAE;AAAA,MAC1C,MAAM,EAAE,YAAY,WAAW,QAAQ;AAAA,IACzC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,oBAAoB,WAA+C;AACvE,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,iBAAiB;AAAA,MACrD,QAAQ,EAAE,OAAO,EAAE,YAAY,UAAU,EAAE;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,oBAAoB,WAAmB,SAA6C;AACxF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,iBAAiB;AAAA,MACrD,MAAM,EAAE,YAAY,WAAW,QAAQ;AAAA,IACzC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,QACJ,WACA,QAC0B;AAC1B,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gBAAgB;AAAA,MACpD,QAAQ;AAAA,QACN,OAAO,EAAE,YAAY,WAAW,YAAY,OAAO,WAAW,KAAK,OAAO,KAAK,UAAU,OAAO,QAAQ;AAAA,MAC1G;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAKA,MAAM,UACJ,WACA,cACA,UAAmC,CAAC,GACT;AAC3B,UAAM,MAAM,OAAO,iBAAiB,WAAW,eAAe;AAC9D,UAAM,aAAa,OAAO,iBAAiB,WAAW,UAAW,gBAAgB;AACjF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,iBAAiB;AAAA,MACrD,QAAQ,EAAE,OAAO,EAAE,YAAY,WAAW,KAAK,OAAO,WAAW,OAAO,QAAQ,WAAW,OAAO,EAAE;AAAA,IACtG,CAAC;AACD,UAAM,QAAQ,KAAM,QAAQ,CAAC;AAC7B,WAAO,EAAE,GAAG,MAAO,MAAM,OAAO,MAAM;AAAA,EACxC;AAAA;AAAA,EAGA,MAAM,SAAS,WAAmB,MAAc,KAA+B;AAK7E,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,wBAAwB;AAAA,MAC5D,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,EAAE,YAAY,WAAW,IAAI,EAAE;AAAA,MAChE,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,WAAmB,QAAsE;AACvG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,aAAa;AAAA,MACjD,QAAQ;AAAA,QACN,OAAO,EAAE,YAAY,WAAW,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,MAC/E;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAiB,QAAsF;AAC3G,WAAO,KAAK,0BAA0B,EAAE,cAAc,OAAO,aAAa,CAAC;AAAA,EAC7E;AAAA;AAAA,EAGA,MAAM,wBAAwB,WAAmB,QAAmE;AAClH,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,gCAAgC;AAAA,MACrE,MAAM,EAAE,YAAY,WAAW,GAAG,OAAO;AAAA,IAC3C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,0BAA0B,QAAmE;AACjG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,kCAAkC,EAAE,MAAM,OAAO,CAAC;AACzF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAAqB,WAAmB,YAA8D;AAC1G,WAAO,KAAK,cAAc,WAAW,EAAE,WAAW,CAAC;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,oBAAoB,aAAqB,UAAkB,YAAsC;AACrG,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,gEAAgE;AAAA,MACpG,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,WAAW,SAAS,EAAE;AAAA,MACnE,MAAM,EAAE,WAAW;AAAA,IACrB,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,qBACJ,aACA,UACA,YACuC;AACvC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,mEAAmE;AAAA,MACxG,QAAQ,EAAE,MAAM,EAAE,cAAc,aAAa,WAAW,SAAS,EAAE;AAAA,MACnE,MAAM,EAAE,aAAa,WAAW;AAAA,IAClC,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBACJ,aACA,UAAuC,CAAC,GACF;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,4DAA4D;AAAA,MAChG,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,GAAG,OAAO,QAAQ;AAAA,IAChE,CAAC;AACD,WAAO,EAAE,GAAG,MAAO,WAAW,KAAM,aAAa,CAAC,EAAE;AAAA,EACtD;AAAA;AAAA,EAGA,MAAM,qBACJ,aACA,UAAuC,CAAC,GACD;AACvC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,6DAA6D;AAAA,MACjG,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,GAAG,OAAO,QAAQ;AAAA,IAChE,CAAC;AACD,WAAO,EAAE,GAAG,MAAO,WAAW,KAAM,aAAa,CAAC,EAAE;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,eAAe,aAAqB,UAAiC,CAAC,GAAoC;AAC9G,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACtD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,cAAc;AAAA,UACd,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,UAChB,OAAO,QAAQ;AAAA,UACf,QAAQ,QAAQ;AAAA,QAClB;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,aACH,KAA0E,cAAc,KAAM,QAAQ,CAAC;AAC1G,WAAO,EAAE,GAAG,MAAO,MAAM,YAAY,YAAY,UAAU,cAAc,IAAK,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAM,aAAa,aAAqB,MAAoD;AAC1F,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,kBAAkB;AAAA,MACvD,MAAM,EAAE,GAAG,MAAM,cAAc,YAAY;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,gBAAgB,aAAqB,aAAqB;AAC9D,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,OAAO,iCAAiC;AAAA,MACxE,QAAQ,EAAE,MAAM,EAAE,cAAc,YAAY,GAAG,OAAO,EAAE,cAAc,YAAY,EAAE;AAAA,IACtF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,wBACJ,aACA,UAAuC,CAAC,GACE;AAC1C,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,4BAA4B;AAAA,MAChE,QAAQ,EAAE,OAAO,EAAE,cAAc,aAAa,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAAA,IAC/F,CAAC;AACD,UAAM,UACH,KAA6E,WAAW,KAAM,QAAQ,CAAC;AAC1G,WAAO,EAAE,GAAG,MAAO,MAAM,SAAS,SAAS,UAAU,cAAc,IAAK,EAAE;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,uBACJ,aACA,UAAuC,CAAC,GACC;AACzC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACtD,QAAQ,EAAE,OAAO,EAAE,cAAc,aAAa,MAAM,YAAY,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAAA,IACjH,CAAC;AACD,UAAM,aACH,KAAkF,cAAc,KAAM,QAAQ,CAAC;AAClH,WAAO,EAAE,GAAG,MAAO,MAAM,YAAY,YAAY,UAAU,cAAc,IAAK,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAM,uBACJ,aACA,UAAuC,CAAC,GACC;AACzC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACtD,QAAQ,EAAE,OAAO,EAAE,cAAc,aAAa,MAAM,YAAY,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAAA,IACjH,CAAC;AACD,UAAM,aACH,KAAkF,cAAc,KAAM,QAAQ,CAAC;AAClH,WAAO,EAAE,GAAG,MAAO,MAAM,YAAY,YAAY,UAAU,cAAc,IAAK,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAM,kBACJ,aACA,UAAuC,CAAC,GACJ;AACpC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,kBAAkB;AAAA,MACtD,QAAQ,EAAE,OAAO,EAAE,cAAc,aAAa,MAAM,OAAO,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE;AAAA,IAC5G,CAAC;AACD,UAAM,aACH,KAA6E,cAAc,KAAM,QAAQ,CAAC;AAC7G,WAAO,EAAE,GAAG,MAAO,MAAM,YAAY,YAAY,UAAU,cAAc,IAAK,EAAE;AAAA,EAClF;AAAA;AAAA,EAGA,MAAM,gBACJ,aACA,SAAqE,CAAC,GACpC;AAClC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,mBAAmB;AAAA,MACvD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,cAAc;AAAA,UACd,cAAc,OAAO;AAAA,UACrB,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,cAAc,KAAM,QAAQ,CAAC;AACnC,WAAO,EAAE,GAAG,MAAO,MAAM,aAAa,aAAa,UAAU,cAAc,IAAK,EAAE;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBACJ,WACA,QACmC;AACnC,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,iBAAiB;AAAA,MACrD,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,WAAW,OAAO;AAAA,UAClB,SAAS,OAAO;AAAA,UAChB,aAAa,OAAO;AAAA,QACtB;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,yBAAyB,WAA2D;AACxF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,uBAAuB;AAAA,MAC3D,QAAQ,EAAE,OAAO,EAAE,YAAY,UAAU,EAAE;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAAQ,WAAmB,SAA0D;AACzF,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,mBAAmB;AAAA,MACxD,MAAM,EAAE,YAAY,WAAW,MAAM,SAAS,KAAK;AAAA,IACrD,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,aAAa,iBAAyB,SAA+C;AACzF,UAAM,OAA+B;AAAA,MACnC,cAAc,QAAQ;AAAA,MACtB,mBAAmB;AAAA,MACnB,iBAAiB,QAAQ;AAAA,MACzB,0BAA0B,QAAQ;AAAA,MAClC,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,4BAA4B,QAAQ;AAAA,MACpC,mBAAmB,QAAQ;AAAA,IAC7B;AAEA,QAAI,QAAQ,WAAW;AACrB,WAAK,aAAa,QAAQ;AAC1B,UAAI,QAAQ,WAAW;AACrB,aAAK,aAAa,QAAQ;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,kBAAkB,QAAQ;AAAA,IACjC;AAEA,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,gBAAgB;AAAA,MACrD;AAAA,IACF,CAAC;AACD,UAAM,QAAQ;AACd,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AACA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,aAAa,iBAAyB,OAAe,SAAkD;AAC3G,UAAM,eAAe,SAAS,gBAAgB;AAC9C,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,YAAY,KAAK,IAAI;AAE3B,WAAO,MAAM;AACX,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,4CAA4C;AAAA,QAChF,QAAQ;AAAA,UACN,MAAM,EAAE,YAAY,gBAAgB;AAAA,UACpC,OAAO,EAAE,QAAQ,MAAM;AAAA,QACzB;AAAA,MACF,CAAC;AACD,YAAM,WAAW;AACjB,YAAM,SAAS,SAAS;AACxB,eAAS,aAAa,QAAQ,SAAS,IAAI;AAE3C,UAAI,WAAW,eAAe,SAAS,QAAQ;AAC7C,eAAO,EAAE,WAAW,SAAS,OAAO,WAAW;AAAA,MACjD;AAEA,UAAI,WAAW,SAAS;AACtB,cAAM,IAAI,MAAM,SAAS,iBAAiB,cAAc;AAAA,MAC1D;AAEA,UAAI,KAAK,IAAI,IAAI,YAAY,SAAS;AACpC,cAAM,IAAI,MAAM,wCAAwC,eAAe,EAAE;AAAA,MAC3E;AAEA,YAAMA,OAAM,YAAY;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,oBAAoB,WAAmB,SAAiD;AAC5F,UAAM,eAAe,SAAS,gBAAgB;AAC9C,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,YAAY,KAAK,IAAI;AAE3B,WAAO,MAAM;AACX,YAAM,UAAU,MAAM,KAAK,WAAW,SAAS;AAC/C,eAAS,aAAa,OAAO;AAE7B,UAAI,QAAQ,WAAW,aAAa;AAClC,eAAO;AAAA,MACT;AAEA,UAAI,QAAQ,WAAW,UAAU;AAC/B,cAAM,IAAI,MAAM,WAAW,SAAS,kBAAkB;AAAA,MACxD;AAEA,UAAI,KAAK,IAAI,IAAI,YAAY,SAAS;AACpC,cAAM,IAAI,MAAM,+BAA+B,SAAS,cAAc;AAAA,MACxE;AAEA,YAAMA,OAAM,YAAY;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,YAAY,MAA2C;AAC7D,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAc,WACZ,MACA,cACuB;AACvB,UAAM,WAAW,KAAK,YAAY,IAAI,IAAI,KAAK,OAAO,KAAK;AAC3D,UAAM,WAAW,KAAK,YAAY,IAAI,IAAI,KAAK,OAAO,KAAK;AAC3D,UAAM,OAAO,KAAK,YAAY,IAAI,IAAI,KAAK,OAAO;AAElD,UAAM,YAAY,MAAM,aAAa,UAAU,QAAQ;AACvD,UAAM,EAAE,KAAK,SAAS,YAAY,QAAQ,IAAI;AAE9C,UAAM,iBAAiB,MAAM,MAAM,KAAK;AAAA,MACtC,QAAQ;AAAA,MACR;AAAA,MACA,SAAS,EAAE,gBAAgB,UAAU,GAAG,QAAQ;AAAA,IAClD,CAAC;AACD,QAAI,CAAC,eAAe,IAAI;AACtB,YAAM,IAAI,MAAM,2BAA2B,QAAQ,WAAW,eAAe,MAAM,EAAE;AAAA,IACvF;AAEA,WAAO,EAAE,SAAS,YAAY,MAAM,eAAe,WAAW,UAAU,WAAW,SAAS;AAAA,EAC9F;AAAA,EAEA,MAAc,mBAAmB,WAAmB,OAAsD;AACxG,WAAO,QAAQ;AAAA,MACb,MAAM;AAAA,QAAI,CAAC,SACT,KAAK;AAAA,UAAW;AAAA,UAAM,CAAC,WAAW,aAChC,KAAK,wBAAwB,WAAW,EAAE,cAAc,SAAS,CAAC;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,qBAAqB,OAAsD;AACvF,WAAO,QAAQ;AAAA,MACb,MAAM;AAAA,QAAI,CAAC,SACT,KAAK,WAAW,MAAM,CAAC,WAAW,aAAa,KAAK,0BAA0B,EAAE,cAAc,SAAS,CAAC,CAAC;AAAA,MAC3G;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,uBAAuB,OAG7B;AACA,UAAM,WAA2B,CAAC;AAClC,UAAM,oBAAoC,CAAC;AAC3C,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,QAAQ,WAAW,YAAY,GAAG;AACzC,0BAAkB,KAAK,IAAI;AAAA,MAC7B,OAAO;AACL,iBAAS,KAAK,IAAI;AAAA,MACpB;AAAA,IACF;AACA,WAAO;AAAA,MACL,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,MAC3C,mBAAmB,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,IACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,wBAAwB,WAAmB,SAAiD;AAChG,UAAM,eAAe,SAAS,gBAAgB;AAC9C,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,YAAY,KAAK,IAAI;AAE3B,WAAO,MAAM;AACX,YAAM,UAAU,MAAM,KAAK,WAAW,SAAS;AAC/C,eAAS,aAAa,OAAO;AAE7B,UAAI,QAAQ,gBAAgB,QAAQ,KAAK;AACvC,eAAO;AAAA,MACT;AAEA,UAAI,QAAQ,WAAW,UAAU;AAC/B,cAAM,IAAI,MAAM,WAAW,SAAS,kBAAkB;AAAA,MACxD;AAEA,UAAI,KAAK,IAAI,IAAI,YAAY,SAAS;AACpC,cAAM,IAAI,MAAM,+BAA+B,SAAS,kBAAkB;AAAA,MAC5E;AAEA,YAAMA,OAAM,YAAY;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAASA,OAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,SAAS,aAAa,KAAuB;AAC3C,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,UAAU,OAAO,IAAI,SAAS;AAClF;AAEA,eAAe,aAAa,UAAqC;AAC/D,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,mBAAmB,UAAmC;AACnE,MAAI;AACF,UAAM,SAAS,MAAM,OAAO;AAAA,EAC9B,QAAQ;AAAA,EAAC;AACX;AAEA,gBAAgB,eACd,MAC6D;AAC7D,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AAEb,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,UAAI,MAAM,OAAO,QAAQ,MAAM;AAC/B,aAAO,QAAQ,IAAI;AACjB,cAAM,MAAM,OAAO,MAAM,GAAG,GAAG;AAC/B,iBAAS,OAAO,MAAM,MAAM,CAAC;AAC7B,cAAM,OAAO,QAAQ,MAAM;AAE3B,YAAI,QAAQ;AACZ,cAAM,YAAsB,CAAC;AAC7B,mBAAW,QAAQ,IAAI,MAAM,IAAI,GAAG;AAClC,cAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AACnC,cAAI,KAAK,WAAW,QAAQ,GAAG;AAC7B,oBAAQ,KAAK,MAAM,CAAC,EAAE,UAAU;AAAA,UAClC,WAAW,KAAK,WAAW,OAAO,GAAG;AACnC,sBAAU,KAAK,KAAK,MAAM,CAAC,EAAE,UAAU,CAAC;AAAA,UAC1C;AAAA,QACF;AACA,YAAI,UAAU,WAAW,EAAG;AAC5B,cAAM,EAAE,OAAO,MAAM,UAAU,KAAK,IAAI,EAAE;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI;AACF,aAAO,YAAY;AAAA,IACrB,QAAQ;AAAA,IAER;AACA,QAAI;AACF,YAAM,KAAK,OAAO;AAAA,IACpB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,SAAS,0BAA0B,KAAyB,mBAA2D;AACrH,QAAM,KAAK,IAAI;AACf,MAAI,MAAM,mBAAmB,GAAG,MAAM,GAAG;AACvC,WAAO;AAAA,MACL,QAAQ,wBAAwB,GAAG,MAAM;AAAA,MACzC,YAAY,GAAG,cAAc;AAAA,MAC7B,SAAS,GAAG;AAAA,MACZ,SAAS,GAAG;AAAA,MACZ,YAAY,GAAG;AAAA,MACf,SAAS,GAAG;AAAA,MACZ,cAAc,GAAG;AAAA,MACjB,gBAAgB,GAAG;AAAA,MACnB,GAAI,GAAG,WAAW,UAAU,EAAE,OAAO,2BAA2B,IAAI,CAAC;AAAA,IACvE;AAAA,EACF;AACA,MAAI,IAAI,SAAS,eAAe,mBAAmB,IAAI,MAAM,GAAG;AAC9D,WAAO;AAAA,MACL,QAAQ,wBAAwB,IAAI,MAAM;AAAA,MAC1C,YAAY,IAAI,cAAc;AAAA,MAC9B,SAAS,IAAI;AAAA,MACb,SAAS,IAAI;AAAA,MACb,YAAY,IAAI;AAAA,MAChB,SAAS,IAAI;AAAA,MACb,cAAc,IAAI;AAAA,MAClB,gBAAgB,IAAI;AAAA,MACpB,GAAI,IAAI,WAAW,UAAU,EAAE,OAAO,2BAA2B,IAAI,CAAC;AAAA,IACxE;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB,QAAmD;AAClF,SAAO,WAAW,eAAe,WAAW,aAAa,WAAW,mBAAmB,SAAS;AAClG;AAEA,SAAS,mBAAmB,QAAqC;AAC/D,SAAO,WAAW,eAAe,WAAW,aAAa,WAAW,WAAW,WAAW;AAC5F;AAEA,SAAS,iBAAiB,KAAyB,mBAA2D;AAC5G,MAAI,IAAI,WAAW,SAAU,QAAO;AACpC,MAAI,CAAC,IAAI,aAAc,QAAO;AAC9B,MAAI,IAAI,uBAAuB,YAAa,QAAO;AACnD,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,OACE,+BAA+B,IAAI,kBAAkB,SAAS,+BAC7D,IAAI,qBAAqB,aAAa,IAAI,kBAAkB,MAAM,MACnE;AAAA,EACJ;AACF;AAEA,SAAS,cAAc,WAAmB,WAA4C;AACpF,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,OAAO,+BAA+B,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,GAAI,CAAC,CAAC;AAAA,EACjF;AACF;","names":["parseRetryAfterMs","sleep"]}
|