@lovable.dev/sdk 0.0.5 → 0.0.6

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 CHANGED
@@ -259,10 +259,10 @@ Options:
259
259
  - `workspaceId` (required): Target workspace for the new project
260
260
  - `messageId` (optional): Message ID to snapshot at — by default the remix reflects the project state just before this message
261
261
  - `remixMode` (optional): `"before"` (default) captures state before the message; `"including"` captures state after the message and its AI response
262
- - `includeHistory` (optional): Whether to preserve chat history
263
- - `includeCustomKnowledge` (optional): Whether to copy custom instructions/knowledge
262
+ - `includeHistory` (optional, default: `false`): Whether to preserve chat history
263
+ - `includeCustomKnowledge` (optional, default: `false`): Whether to copy custom instructions/knowledge
264
264
  - `initialMessage` (optional): Initial chat message to send after remix completes
265
- - `integrationParameters` (optional): Integration-specific parameter values
265
+ - `skipInitialRemixMessage` (optional, default: `false`): When true, suppresses the default "I've successfully remixed this project" message
266
266
 
267
267
  ##### `waitForRemix(sourceProjectId: string, jobId: string, options?): Promise<RemixResult>`
268
268
 
package/dist/index.d.ts CHANGED
@@ -272,7 +272,7 @@ interface RemixProjectOptions {
272
272
  includeHistory?: boolean;
273
273
  includeCustomKnowledge?: boolean;
274
274
  initialMessage?: string;
275
- integrationParameters?: Record<string, Record<string, string>>;
275
+ skipInitialRemixMessage?: boolean;
276
276
  }
277
277
  interface RemixResult {
278
278
  projectId: string;
@@ -377,7 +377,6 @@ declare class LovableClient {
377
377
  * @param options.includeHistory - Whether to preserve chat history (default: false)
378
378
  * @param options.includeCustomKnowledge - Whether to copy custom instructions (default: false)
379
379
  * @param options.initialMessage - Optional initial message to send after remix
380
- * @param options.integrationParameters - Integration-specific parameters
381
380
  * @returns The remix job ID for polling progress
382
381
  */
383
382
  remixProject(sourceProjectId: string, options: RemixProjectOptions): Promise<string>;
package/dist/index.js CHANGED
@@ -208,7 +208,6 @@ var LovableClient = class {
208
208
  * @param options.includeHistory - Whether to preserve chat history (default: false)
209
209
  * @param options.includeCustomKnowledge - Whether to copy custom instructions (default: false)
210
210
  * @param options.initialMessage - Optional initial message to send after remix
211
- * @param options.integrationParameters - Integration-specific parameters
212
211
  * @returns The remix job ID for polling progress
213
212
  */
214
213
  async remixProject(sourceProjectId, options) {
@@ -216,7 +215,7 @@ var LovableClient = class {
216
215
  workspace_id: options.workspaceId,
217
216
  include_history: options.includeHistory,
218
217
  include_custom_knowledge: options.includeCustomKnowledge,
219
- integration_parameters: options.integrationParameters
218
+ skip_initial_remix_message: options.skipInitialRemixMessage
220
219
  };
221
220
  if (options.messageId) {
222
221
  body.message_id = options.messageId;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type {\n LovableClientOptions,\n LovableError,\n CreateProjectOptions,\n InviteCollaboratorOptions,\n ChatMessageOptions,\n WaitOptions,\n WorkspaceWithMembership,\n ProjectResponse,\n WorkspaceMembershipResponse,\n CreateProjectBody,\n ChatRequest,\n AddUserToWorkspaceInputBody,\n GetWorkspacesResponse,\n GetWorkspaceProjectsResponse,\n DeploymentResponse,\n ChatResponse,\n ChatResponseOptions,\n UnscopedFile,\n FileInput,\n RemixProjectOptions,\n RemixInitBody,\n RemixInitResponse,\n RemixProgressResponse,\n RemixResult,\n RemixWaitOptions,\n MessageTracesResponse,\n GetMessageTracesOptions,\n TraceQuery,\n BatchTracesResult,\n} 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 let normalized = url.replace(/\\/$/, \"\");\n\n // Add http:// for localhost URLs without protocol\n if (!normalized.startsWith(\"http://\") && !normalized.startsWith(\"https://\")) {\n const isLocalhost = normalized.startsWith(\"localhost\") || normalized.startsWith(\"127.0.0.1\");\n normalized = isLocalhost ? `http://${normalized}` : `https://${normalized}`;\n }\n\n return normalized;\n}\n\nexport class LovableClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(options: LovableClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"API key is required\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n \"Lovable-API-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n let errorBody: { title?: string; detail?: string } | undefined;\n try {\n errorBody = (await response.json()) as { title?: string; detail?: string };\n } catch {\n // Ignore JSON parse errors\n }\n\n const error = new Error(errorBody?.title ?? `HTTP ${response.status}: ${response.statusText}`) as LovableError;\n error.status = response.status;\n error.type = errorBody?.title;\n error.detail = errorBody?.detail;\n throw error;\n }\n\n if (response.status === 204 || response.status === 202) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\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\", \"/user/workspaces\");\n return response.workspaces ?? [];\n }\n\n /**\n * Get a specific workspace by ID\n */\n async getWorkspace(workspaceId: string): Promise<WorkspaceWithMembership> {\n return this.request<WorkspaceWithMembership>(\"GET\", `/user/workspaces/${workspaceId}`);\n }\n\n /**\n * List projects in a workspace\n */\n async listProjects(\n workspaceId: string,\n options?: { limit?: number; visibility?: \"all\" | \"personal\" | \"public\" | \"workspace\" },\n ): Promise<ProjectResponse[]> {\n const params = new URLSearchParams();\n if (options?.limit) params.set(\"limit\", options.limit.toString());\n if (options?.visibility) params.set(\"visibility\", options.visibility);\n\n const query = params.toString();\n const path = `/workspaces/${workspaceId}/projects${query ? `?${query}` : \"\"}`;\n\n const response = await this.request<GetWorkspaceProjectsResponse>(\"GET\", path);\n return response.projects ?? [];\n }\n\n /**\n * Create a new project in a workspace\n */\n async createProject(workspaceId: string, options: CreateProjectOptions): Promise<ProjectResponse> {\n const body: CreateProjectBody = {\n description: options.description,\n tech_stack: options.techStack ?? \"\",\n visibility: options.visibility ?? \"private\",\n template_project_id: options.templateProjectId,\n };\n\n let uploadedFiles: UnscopedFile[] | undefined;\n if (options.files?.length) {\n uploadedFiles = await this.uploadFiles(options.files);\n }\n\n if (options.initialMessage || uploadedFiles) {\n body.initial_message = {\n id: crypto.randomUUID(),\n message: options.initialMessage ?? options.description,\n chat_only: false,\n headless: true,\n files: uploadedFiles,\n };\n }\n\n return this.request<ProjectResponse>(\"POST\", `/workspaces/${workspaceId}/projects`, body);\n }\n\n /**\n * Send a chat message to a project\n *\n * Note: This sends a message to the project's AI agent. The response is\n * asynchronous - the API accepts the message and processes it in the background.\n */\n async chat(projectId: string, options: ChatMessageOptions): Promise<void> {\n let uploadedFiles: UnscopedFile[] | undefined;\n if (options.files?.length) {\n uploadedFiles = await this.uploadFiles(options.files);\n }\n\n const body: ChatRequest = {\n id: crypto.randomUUID(),\n message: options.message,\n chat_only: options.chatOnly ?? false,\n headless: true,\n files: uploadedFiles,\n ...(options.customModel && {\n custom_model_endpoint: options.customModel.endpoint,\n custom_model_api_key: options.customModel.apiKey,\n custom_model_name: options.customModel.modelName,\n }),\n };\n\n await this.request<void>(\"POST\", `/projects/${projectId}/chat`, 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\", `/projects/${projectId}/details`);\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 * 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\", `/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 * @param options.integrationParameters - Integration-specific parameters\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 integration_parameters: options.integrationParameters,\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\", `/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 `/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}/projects/${projectId}/latest-message`;\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 \"Lovable-API-Key\": this.apiKey,\n },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const error = new Error(`Failed to connect to message stream: HTTP ${response.status}`) as LovableError;\n error.status = response.status;\n throw error;\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 /**\n * Fetch Braintrust traces for a specific chat message.\n *\n * Returns the trace spans associated with the AI response message.\n * The messageId is available from the ChatResponse returned by waitForResponse().\n *\n * Use the `purposes` option to filter which span types are returned.\n * When a purpose has multiple spans (e.g. main_agent across turns),\n * only the last span is returned — it contains the full accumulated context.\n *\n * @param projectId - The project ID\n * @param messageId - The AI message ID (from ChatResponse.messageId)\n * @param options.purposes - Filter spans by purpose (e.g. [\"main_agent\", \"knowledge_rag\"])\n * @returns The trace data including filtered spans\n */\n async getMessageTraces(\n projectId: string,\n messageId: string,\n options?: GetMessageTracesOptions,\n ): Promise<MessageTracesResponse> {\n const params = new URLSearchParams();\n if (options?.purposes?.length) {\n params.set(\"purposes\", options.purposes.join(\",\"));\n }\n const query = params.toString();\n const path = `/projects/${projectId}/messages/${messageId}/traces${query ? `?${query}` : \"\"}`;\n return this.request<MessageTracesResponse>(\"GET\", path);\n }\n\n /**\n * Fetch traces for multiple messages across projects in parallel.\n *\n * Fires concurrent requests (up to `concurrency` at a time) and collects\n * results. Failed requests are captured in `errors` instead of throwing.\n *\n * @param queries - Array of { projectId, messageId } to fetch\n * @param options.purposes - Filter spans by purpose (applied to all queries)\n * @param options.concurrency - Max parallel requests (default: 5)\n * @returns Object with `traces` map (keyed by messageId) and `errors` map\n */\n async getMessageTracesBatch(\n queries: TraceQuery[],\n options?: GetMessageTracesOptions & { concurrency?: number },\n ): Promise<BatchTracesResult> {\n const concurrency = options?.concurrency ?? 5;\n const traces = new Map<string, MessageTracesResponse>();\n const errors = new Map<string, Error>();\n const purposeOpts = options?.purposes ? { purposes: options.purposes } : undefined;\n\n const pending = [...queries];\n const executing = new Set<Promise<void>>();\n\n for (const query of pending) {\n const task = this.getMessageTraces(query.projectId, query.messageId, purposeOpts)\n .then((result) => {\n traces.set(query.messageId, result);\n })\n .catch((err) => {\n errors.set(query.messageId, err instanceof Error ? err : new Error(String(err)));\n })\n .finally(() => {\n executing.delete(task);\n });\n\n executing.add(task);\n\n if (executing.size >= concurrency) {\n await Promise.race(executing);\n }\n }\n\n await Promise.all(executing);\n\n return { traces, errors };\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 fileId = crypto.randomUUID();\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 } = await this.request<{ url: string }>(\"POST\", \"/files/generate-upload-url\", {\n file_name: fileId,\n content_type: mimeType,\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: fileId, 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"],"mappings":";AAgCA,IAAM,mBAAmB;AAEzB,SAAS,iBAAiB,KAAiC;AACzD,MAAI,CAAC;AAAK,WAAO;AAEjB,MAAI,aAAa,IAAI,QAAQ,OAAO,EAAE;AAGtC,MAAI,CAAC,WAAW,WAAW,SAAS,KAAK,CAAC,WAAW,WAAW,UAAU,GAAG;AAC3E,UAAM,cAAc,WAAW,WAAW,WAAW,KAAK,WAAW,WAAW,WAAW;AAC3F,iBAAa,cAAc,UAAU,UAAU,KAAK,WAAW,UAAU;AAAA,EAC3E;AAEA,SAAO;AACT;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EACA;AAAA,EAEjB,YAAY,SAA+B;AACzC,QAAI,CAAC,QAAQ,QAAQ;AACnB,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AACA,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,iBAAiB,QAAQ,OAAO;AAAA,EACjD;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,MAA4B;AACjF,UAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI;AAElC,UAAM,UAAkC;AAAA,MACtC,mBAAmB,KAAK;AAAA,MACxB,gBAAgB;AAAA,IAClB;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IACtC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI;AACJ,UAAI;AACF,oBAAa,MAAM,SAAS,KAAK;AAAA,MACnC,QAAQ;AAAA,MAER;AAEA,YAAM,QAAQ,IAAI,MAAM,WAAW,SAAS,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAC7F,YAAM,SAAS,SAAS;AACxB,YAAM,OAAO,WAAW;AACxB,YAAM,SAAS,WAAW;AAC1B,YAAM;AAAA,IACR;AAEA,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,aAAO;AAAA,IACT;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAqD;AACzD,UAAM,WAAW,MAAM,KAAK,QAA+B,OAAO,kBAAkB;AACpF,WAAO,SAAS,cAAc,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,aAAuD;AACxE,WAAO,KAAK,QAAiC,OAAO,oBAAoB,WAAW,EAAE;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,aACA,SAC4B;AAC5B,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS;AAAO,aAAO,IAAI,SAAS,QAAQ,MAAM,SAAS,CAAC;AAChE,QAAI,SAAS;AAAY,aAAO,IAAI,cAAc,QAAQ,UAAU;AAEpE,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,eAAe,WAAW,YAAY,QAAQ,IAAI,KAAK,KAAK,EAAE;AAE3E,UAAM,WAAW,MAAM,KAAK,QAAsC,OAAO,IAAI;AAC7E,WAAO,SAAS,YAAY,CAAC;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,aAAqB,SAAyD;AAChG,UAAM,OAA0B;AAAA,MAC9B,aAAa,QAAQ;AAAA,MACrB,YAAY,QAAQ,aAAa;AAAA,MACjC,YAAY,QAAQ,cAAc;AAAA,MAClC,qBAAqB,QAAQ;AAAA,IAC/B;AAEA,QAAI;AACJ,QAAI,QAAQ,OAAO,QAAQ;AACzB,sBAAgB,MAAM,KAAK,YAAY,QAAQ,KAAK;AAAA,IACtD;AAEA,QAAI,QAAQ,kBAAkB,eAAe;AAC3C,WAAK,kBAAkB;AAAA,QACrB,IAAI,OAAO,WAAW;AAAA,QACtB,SAAS,QAAQ,kBAAkB,QAAQ;AAAA,QAC3C,WAAW;AAAA,QACX,UAAU;AAAA,QACV,OAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,KAAK,QAAyB,QAAQ,eAAe,WAAW,aAAa,IAAI;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK,WAAmB,SAA4C;AACxE,QAAI;AACJ,QAAI,QAAQ,OAAO,QAAQ;AACzB,sBAAgB,MAAM,KAAK,YAAY,QAAQ,KAAK;AAAA,IACtD;AAEA,UAAM,OAAoB;AAAA,MACxB,IAAI,OAAO,WAAW;AAAA,MACtB,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ,YAAY;AAAA,MAC/B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,GAAI,QAAQ,eAAe;AAAA,QACzB,uBAAuB,QAAQ,YAAY;AAAA,QAC3C,sBAAsB,QAAQ,YAAY;AAAA,QAC1C,mBAAmB,QAAQ,YAAY;AAAA,MACzC;AAAA,IACF;AAEA,UAAM,KAAK,QAAc,QAAQ,aAAa,SAAS,SAAS,IAAI;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACJ,aACA,SACsC;AACtC,UAAM,OAAoC;AAAA,MACxC,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ,QAAQ;AAAA,IACxB;AAEA,WAAO,KAAK,QAAqC,QAAQ,eAAe,WAAW,gBAAgB,IAAI;AAAA,EACzG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAqB,aAA6D;AACtF,UAAM,WAAW,MAAM,KAAK,QAEzB,OAAO,eAAe,WAAW,cAAc;AAClD,WAAO,SAAS,eAAe,CAAC;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,aAAqB,QAA+B;AAC9E,UAAM,KAAK,QAAc,UAAU,eAAe,WAAW,gBAAgB,MAAM,EAAE;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,WAA6C;AAC5D,WAAO,KAAK,QAAyB,OAAO,aAAa,SAAS,UAAU;AAAA,EAC9E;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;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QAAQ,WAAmB,SAA0D;AACzF,WAAO,KAAK,QAA4B,QAAQ,aAAa,SAAS,gBAAgB;AAAA,MACpF,MAAM,SAAS;AAAA,IACjB,CAAC;AAAA,EACH;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,OAAsB;AAAA,MAC1B,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,MACzB,0BAA0B,QAAQ;AAAA,MAClC,wBAAwB,QAAQ;AAAA,IAClC;AAEA,QAAI,QAAQ,WAAW;AACrB,WAAK,aAAa,QAAQ;AAC1B,WAAK,aAAa,QAAQ,aAAa;AAAA,IACzC;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,kBAAkB;AAAA,QACrB,IAAI,OAAO,WAAW;AAAA,QACtB,SAAS,QAAQ;AAAA,QACjB,WAAW;AAAA,QACX,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,QAA2B,QAAQ,aAAa,eAAe,eAAe,IAAI;AAC9G,WAAO,SAAS;AAAA,EAClB;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,WAAW,MAAM,KAAK;AAAA,QAC1B;AAAA,QACA,aAAa,eAAe,0BAA0B,mBAAmB,KAAK,CAAC;AAAA,MACjF;AAEA,eAAS,aAAa,SAAS,QAAQ,SAAS,IAAI;AAEpD,UAAI,SAAS,WAAW,eAAe,SAAS,QAAQ;AACtD,eAAO,EAAE,WAAW,SAAS,OAAO,WAAW;AAAA,MACjD;AAEA,UAAI,SAAS,WAAW,SAAS;AAC/B,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,YAAM,MAAM,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,YAAM,MAAM,YAAY;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,gBAAgB,WAAmB,SAAsD;AAC7F,UAAM,UAAU,SAAS,WAAW;AACpC,UAAM,MAAM,GAAG,KAAK,OAAO,aAAa,SAAS;AAEjD,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO;AAE9D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAChC,SAAS;AAAA,UACP,mBAAmB,KAAK;AAAA,QAC1B;AAAA,QACA,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,QAAQ,IAAI,MAAM,6CAA6C,SAAS,MAAM,EAAE;AACtF,cAAM,SAAS,SAAS;AACxB,cAAM;AAAA,MACR;AAEA,UAAI,CAAC,SAAS,MAAM;AAClB,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,YAAM,SAAS,MAAM,KAAK,iBAAiB,SAAS,IAAI;AACxD,aAAO;AAAA,QACL,SAAS,OAAO;AAAA,QAChB,WAAW,OAAO;AAAA,QAClB,YAAY,KAAK,cAAc,SAAS;AAAA,MAC1C;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,gBAAgB,IAAI,SAAS,cAAc;AAC5D,cAAM,IAAI,MAAM,2CAA2C,SAAS,EAAE;AAAA,MACxE;AACA,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,iBACJ,WACA,WACA,SACgC;AAChC,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS,UAAU,QAAQ;AAC7B,aAAO,IAAI,YAAY,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,IACnD;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,aAAa,SAAS,aAAa,SAAS,UAAU,QAAQ,IAAI,KAAK,KAAK,EAAE;AAC3F,WAAO,KAAK,QAA+B,OAAO,IAAI;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,sBACJ,SACA,SAC4B;AAC5B,UAAM,cAAc,SAAS,eAAe;AAC5C,UAAM,SAAS,oBAAI,IAAmC;AACtD,UAAM,SAAS,oBAAI,IAAmB;AACtC,UAAM,cAAc,SAAS,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI;AAEzE,UAAM,UAAU,CAAC,GAAG,OAAO;AAC3B,UAAM,YAAY,oBAAI,IAAmB;AAEzC,eAAW,SAAS,SAAS;AAC3B,YAAM,OAAO,KAAK,iBAAiB,MAAM,WAAW,MAAM,WAAW,WAAW,EAC7E,KAAK,CAAC,WAAW;AAChB,eAAO,IAAI,MAAM,WAAW,MAAM;AAAA,MACpC,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,eAAO,IAAI,MAAM,WAAW,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,MACjF,CAAC,EACA,QAAQ,MAAM;AACb,kBAAU,OAAO,IAAI;AAAA,MACvB,CAAC;AAEH,gBAAU,IAAI,IAAI;AAElB,UAAI,UAAU,QAAQ,aAAa;AACjC,cAAM,QAAQ,KAAK,SAAS;AAAA,MAC9B;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,SAAS;AAE3B,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAAA,EAEQ,YAAY,MAA2C;AAC7D,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAc,WAAW,MAA+C;AACtE,UAAM,SAAS,OAAO,WAAW;AACjC,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,EAAE,IAAI,IAAI,MAAM,KAAK,QAAyB,QAAQ,8BAA8B;AAAA,MACxF,WAAW;AAAA,MACX,cAAc;AAAA,IAChB,CAAC;AAED,UAAM,iBAAiB,MAAM,MAAM,KAAK;AAAA,MACtC,QAAQ;AAAA,MACR;AAAA,MACA,SAAS,EAAE,gBAAgB,SAAS;AAAA,IACtC,CAAC;AACD,QAAI,CAAC,eAAe,IAAI;AACtB,YAAM,IAAI,MAAM,2BAA2B,QAAQ,WAAW,eAAe,MAAM,EAAE;AAAA,IACvF;AAEA,WAAO,EAAE,SAAS,QAAQ,MAAM,eAAe,WAAW,UAAU,WAAW,SAAS;AAAA,EAC1F;AAAA,EAEA,MAAc,YAAY,OAAsD;AAC9E,WAAO,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAc,iBAAiB,MAAmF;AAChH,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,UAAU,IAAI,YAAY;AAChC,QAAI,SAAS;AACb,QAAI,UAAU;AACd,QAAI,YAAY;AAEhB,QAAI;AACF,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI;AAAM;AAEV,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGhD,cAAM,QAAQ,OAAO,MAAM,MAAM;AACjC,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACxB,cAAI,CAAC,KAAK,KAAK;AAAG;AAElB,gBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,cAAI,YAAY;AAChB,cAAI,YAAY;AAEhB,qBAAW,QAAQ,OAAO;AACxB,gBAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,0BAAY,KAAK,MAAM,CAAC;AAAA,YAC1B,WAAW,KAAK,WAAW,QAAQ,GAAG;AACpC,0BAAY,KAAK,MAAM,CAAC;AAAA,YAC1B;AAAA,UACF;AAEA,cAAI,cAAc,aAAa,WAAW;AACxC,gBAAI;AACF,oBAAM,OAAO,KAAK,MAAM,SAAS;AACjC,kBAAI,OAAO,KAAK,YAAY,UAAU;AACpC,2BAAW,KAAK;AAAA,cAClB;AACA,kBAAI,OAAO,KAAK,eAAe,YAAY,KAAK,YAAY;AAC1D,4BAAY,KAAK;AAAA,cACnB;AACA,kBAAI,KAAK,UAAU;AACjB,uBAAO,EAAE,SAAS,UAAU;AAAA,cAC9B;AAAA,YACF,QAAQ;AAAA,YAER;AAAA,UACF;AAEA,cAAI,cAAc,SAAS;AACzB,gBAAI,SAAS;AACb,gBAAI;AACF,oBAAM,OAAO,KAAK,MAAM,SAAS;AACjC,kBAAI,KAAK;AAAS,yBAAS,KAAK;AAAA,YAClC,QAAQ;AAAA,YAER;AACA,kBAAM,IAAI,MAAM,MAAM;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF,UAAE;AACA,WAAK,OAAO,OAAO;AAAA,IACrB;AAEA,WAAO,EAAE,SAAS,UAAU;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,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,YAAM,MAAM,YAAY;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type {\n LovableClientOptions,\n LovableError,\n CreateProjectOptions,\n InviteCollaboratorOptions,\n ChatMessageOptions,\n WaitOptions,\n WorkspaceWithMembership,\n ProjectResponse,\n WorkspaceMembershipResponse,\n CreateProjectBody,\n ChatRequest,\n AddUserToWorkspaceInputBody,\n GetWorkspacesResponse,\n GetWorkspaceProjectsResponse,\n DeploymentResponse,\n ChatResponse,\n ChatResponseOptions,\n UnscopedFile,\n FileInput,\n RemixProjectOptions,\n RemixInitBody,\n RemixInitResponse,\n RemixProgressResponse,\n RemixResult,\n RemixWaitOptions,\n MessageTracesResponse,\n GetMessageTracesOptions,\n TraceQuery,\n BatchTracesResult,\n} 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 let normalized = url.replace(/\\/$/, \"\");\n\n // Add http:// for localhost URLs without protocol\n if (!normalized.startsWith(\"http://\") && !normalized.startsWith(\"https://\")) {\n const isLocalhost = normalized.startsWith(\"localhost\") || normalized.startsWith(\"127.0.0.1\");\n normalized = isLocalhost ? `http://${normalized}` : `https://${normalized}`;\n }\n\n return normalized;\n}\n\nexport class LovableClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(options: LovableClientOptions) {\n if (!options.apiKey) {\n throw new Error(\"API key is required\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = normalizeBaseUrl(options.baseUrl);\n }\n\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n \"Lovable-API-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n let errorBody: { title?: string; detail?: string } | undefined;\n try {\n errorBody = (await response.json()) as { title?: string; detail?: string };\n } catch {\n // Ignore JSON parse errors\n }\n\n const error = new Error(errorBody?.title ?? `HTTP ${response.status}: ${response.statusText}`) as LovableError;\n error.status = response.status;\n error.type = errorBody?.title;\n error.detail = errorBody?.detail;\n throw error;\n }\n\n if (response.status === 204 || response.status === 202) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\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\", \"/user/workspaces\");\n return response.workspaces ?? [];\n }\n\n /**\n * Get a specific workspace by ID\n */\n async getWorkspace(workspaceId: string): Promise<WorkspaceWithMembership> {\n return this.request<WorkspaceWithMembership>(\"GET\", `/user/workspaces/${workspaceId}`);\n }\n\n /**\n * List projects in a workspace\n */\n async listProjects(\n workspaceId: string,\n options?: { limit?: number; visibility?: \"all\" | \"personal\" | \"public\" | \"workspace\" },\n ): Promise<ProjectResponse[]> {\n const params = new URLSearchParams();\n if (options?.limit) params.set(\"limit\", options.limit.toString());\n if (options?.visibility) params.set(\"visibility\", options.visibility);\n\n const query = params.toString();\n const path = `/workspaces/${workspaceId}/projects${query ? `?${query}` : \"\"}`;\n\n const response = await this.request<GetWorkspaceProjectsResponse>(\"GET\", path);\n return response.projects ?? [];\n }\n\n /**\n * Create a new project in a workspace\n */\n async createProject(workspaceId: string, options: CreateProjectOptions): Promise<ProjectResponse> {\n const body: CreateProjectBody = {\n description: options.description,\n tech_stack: options.techStack ?? \"\",\n visibility: options.visibility ?? \"private\",\n template_project_id: options.templateProjectId,\n };\n\n let uploadedFiles: UnscopedFile[] | undefined;\n if (options.files?.length) {\n uploadedFiles = await this.uploadFiles(options.files);\n }\n\n if (options.initialMessage || uploadedFiles) {\n body.initial_message = {\n id: crypto.randomUUID(),\n message: options.initialMessage ?? options.description,\n chat_only: false,\n headless: true,\n files: uploadedFiles,\n };\n }\n\n return this.request<ProjectResponse>(\"POST\", `/workspaces/${workspaceId}/projects`, body);\n }\n\n /**\n * Send a chat message to a project\n *\n * Note: This sends a message to the project's AI agent. The response is\n * asynchronous - the API accepts the message and processes it in the background.\n */\n async chat(projectId: string, options: ChatMessageOptions): Promise<void> {\n let uploadedFiles: UnscopedFile[] | undefined;\n if (options.files?.length) {\n uploadedFiles = await this.uploadFiles(options.files);\n }\n\n const body: ChatRequest = {\n id: crypto.randomUUID(),\n message: options.message,\n chat_only: options.chatOnly ?? false,\n headless: true,\n files: uploadedFiles,\n ...(options.customModel && {\n custom_model_endpoint: options.customModel.endpoint,\n custom_model_api_key: options.customModel.apiKey,\n custom_model_name: options.customModel.modelName,\n }),\n };\n\n await this.request<void>(\"POST\", `/projects/${projectId}/chat`, 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\", `/projects/${projectId}/details`);\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 * 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\", `/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 skip_initial_remix_message: options.skipInitialRemixMessage,\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\", `/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 `/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}/projects/${projectId}/latest-message`;\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 \"Lovable-API-Key\": this.apiKey,\n },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const error = new Error(`Failed to connect to message stream: HTTP ${response.status}`) as LovableError;\n error.status = response.status;\n throw error;\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 /**\n * Fetch Braintrust traces for a specific chat message.\n *\n * Returns the trace spans associated with the AI response message.\n * The messageId is available from the ChatResponse returned by waitForResponse().\n *\n * Use the `purposes` option to filter which span types are returned.\n * When a purpose has multiple spans (e.g. main_agent across turns),\n * only the last span is returned — it contains the full accumulated context.\n *\n * @param projectId - The project ID\n * @param messageId - The AI message ID (from ChatResponse.messageId)\n * @param options.purposes - Filter spans by purpose (e.g. [\"main_agent\", \"knowledge_rag\"])\n * @returns The trace data including filtered spans\n */\n async getMessageTraces(\n projectId: string,\n messageId: string,\n options?: GetMessageTracesOptions,\n ): Promise<MessageTracesResponse> {\n const params = new URLSearchParams();\n if (options?.purposes?.length) {\n params.set(\"purposes\", options.purposes.join(\",\"));\n }\n const query = params.toString();\n const path = `/projects/${projectId}/messages/${messageId}/traces${query ? `?${query}` : \"\"}`;\n return this.request<MessageTracesResponse>(\"GET\", path);\n }\n\n /**\n * Fetch traces for multiple messages across projects in parallel.\n *\n * Fires concurrent requests (up to `concurrency` at a time) and collects\n * results. Failed requests are captured in `errors` instead of throwing.\n *\n * @param queries - Array of { projectId, messageId } to fetch\n * @param options.purposes - Filter spans by purpose (applied to all queries)\n * @param options.concurrency - Max parallel requests (default: 5)\n * @returns Object with `traces` map (keyed by messageId) and `errors` map\n */\n async getMessageTracesBatch(\n queries: TraceQuery[],\n options?: GetMessageTracesOptions & { concurrency?: number },\n ): Promise<BatchTracesResult> {\n const concurrency = options?.concurrency ?? 5;\n const traces = new Map<string, MessageTracesResponse>();\n const errors = new Map<string, Error>();\n const purposeOpts = options?.purposes ? { purposes: options.purposes } : undefined;\n\n const pending = [...queries];\n const executing = new Set<Promise<void>>();\n\n for (const query of pending) {\n const task = this.getMessageTraces(query.projectId, query.messageId, purposeOpts)\n .then((result) => {\n traces.set(query.messageId, result);\n })\n .catch((err) => {\n errors.set(query.messageId, err instanceof Error ? err : new Error(String(err)));\n })\n .finally(() => {\n executing.delete(task);\n });\n\n executing.add(task);\n\n if (executing.size >= concurrency) {\n await Promise.race(executing);\n }\n }\n\n await Promise.all(executing);\n\n return { traces, errors };\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 fileId = crypto.randomUUID();\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 } = await this.request<{ url: string }>(\"POST\", \"/files/generate-upload-url\", {\n file_name: fileId,\n content_type: mimeType,\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: fileId, 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"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/sdk",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "TypeScript SDK for the Lovable API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "scripts": {
34
34
  "build": "tsup",
35
- "typecheck": "tsc --noEmit",
35
+ "typecheck": "tsgo --noEmit",
36
36
  "test": "vitest",
37
37
  "publish:npm": "pnpm publish --access public"
38
38
  }