@lovable.dev/sdk 0.1.9 → 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/src/index.ts ADDED
@@ -0,0 +1,93 @@
1
+ export { LovableClient } from "./client.js";
2
+ export { ApiError } from "./types.js";
3
+ export type { RateLimitInfo } from "./types.js";
4
+ export type {
5
+ LovableClientOptions,
6
+ LovableError,
7
+ CreateProjectOptions,
8
+ ChatMessageOptions,
9
+ CreateVariantOptions,
10
+ ContinuationOverride,
11
+ WaitOptions,
12
+ WorkspaceWithMembership,
13
+ WorkspaceMembership,
14
+ ProjectResponse,
15
+ EmbedURLResponse,
16
+ CreateProjectResponse,
17
+ CreateProjectBody,
18
+ ChatRequest,
19
+ ProjectVisibility,
20
+ ProjectStatus,
21
+ MemberRole,
22
+ DeploymentResponse,
23
+ ChatResponse,
24
+ ChatResponseOptions,
25
+ UnscopedFile,
26
+ FileInput,
27
+ RemixProjectOptions,
28
+ RemixResult,
29
+ RemixWaitOptions,
30
+ RemixJobStatus,
31
+ RemixJobStep,
32
+ RemixJobStepInfo,
33
+ RemixMode,
34
+ MeResponse,
35
+ MeWorkspace,
36
+ DatabaseStatus,
37
+ EnableDatabaseResult,
38
+ DatabaseQueryResult,
39
+ GetWorkspacesResponse,
40
+ // New types for MCP parity
41
+ SendMessageResponse,
42
+ GetMessageResponse,
43
+ MessageSummary,
44
+ ListMessagesResponse,
45
+ ListMessagesOptions,
46
+ CreateVariantResponse,
47
+ MessageCompletionResult,
48
+ MessageCompletionOptions,
49
+ KnowledgeResponse,
50
+ FileUploadUrlResponse,
51
+ DiffLine,
52
+ DiffHunk,
53
+ DiffEntry,
54
+ GitDiffResponse,
55
+ GitFileEntry,
56
+ GitFilesResponse,
57
+ EditSummary,
58
+ EditsResponse,
59
+ ListProjectItem,
60
+ ListProjectsResponse,
61
+ ListProjectsOptions,
62
+ ListConnectorsOptions,
63
+ ListCursorPaginationOptions,
64
+ ListHybridPaginationOptions,
65
+ ListPaginationOptions,
66
+ ListOffsetPaginationOptions,
67
+ CursorPaginationOptions,
68
+ LibraryProjectResponse,
69
+ TemplateProjectResponse,
70
+ ListLibraryProjectsResponse,
71
+ ListTemplateProjectsResponse,
72
+ ConnectorResponse,
73
+ AvailableConnectorEntry,
74
+ AddConnectorBody,
75
+ ConnectorItem,
76
+ StandardConnectorItem,
77
+ SeamlessConnectorItem,
78
+ MCPConnectorItem,
79
+ ConnectionItem,
80
+ ListConnectorsResponse,
81
+ ListAvailableConnectorsResponse,
82
+ ListStandardConnectorsResponse,
83
+ ListSeamlessConnectorsResponse,
84
+ ListMCPConnectorsResponse,
85
+ ListConnectionsResponse,
86
+ TimeSeriesDataPoint,
87
+ TimeSeriesData,
88
+ ListDataPoint,
89
+ ListData,
90
+ ProjectAnalyticsResponse,
91
+ TrendDataPoint,
92
+ ProjectAnalyticsTrendResponse,
93
+ } from "./types.js";
@@ -0,0 +1,44 @@
1
+ const RETRY_DELAYS_MS = [100, 300, 500] as const;
2
+
3
+ const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
4
+
5
+ function parseRetryAfterMs(headers: Headers): number | undefined {
6
+ const raw = headers.get("retry-after");
7
+ if (!raw) return undefined;
8
+ const seconds = Number(raw);
9
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;
10
+ const dateMs = Date.parse(raw);
11
+ if (!Number.isNaN(dateMs)) {
12
+ const delta = dateMs - Date.now();
13
+ return delta > 0 ? delta : 0;
14
+ }
15
+ return undefined;
16
+ }
17
+
18
+ export type RetryFetch = (input: Request) => Promise<Response>;
19
+
20
+ /**
21
+ * Wraps a fetch implementation with retry on HTTP 429. Up to three retries
22
+ * at 100ms / 300ms / 500ms; if the server sends `Retry-After` and it's
23
+ * larger than the planned delay, we honor the server value. The Request is
24
+ * cloned before each attempt so its body remains replayable.
25
+ *
26
+ * Matches openapi-fetch's `fetch` option signature: a single `Request` in,
27
+ * `Promise<Response>` out.
28
+ */
29
+ export function makeRetryFetch(baseFetch: RetryFetch = (input) => globalThis.fetch(input)): RetryFetch {
30
+ return async (input) => {
31
+ // Request.clone() and the fetch parameter resolve to different Request type
32
+ // definitions when @types/node (undici) and @types/bun are both in scope;
33
+ // the cloned object is structurally the same Request, so assert the param type.
34
+ const clone = (): Parameters<RetryFetch>[0] => input.clone() as Parameters<RetryFetch>[0];
35
+ let response = await baseFetch(clone());
36
+ for (const planned of RETRY_DELAYS_MS) {
37
+ if (response.status !== 429) break;
38
+ const serverDelay = parseRetryAfterMs(response.headers);
39
+ await sleep(Math.max(planned, serverDelay ?? 0));
40
+ response = await baseFetch(clone());
41
+ }
42
+ return response;
43
+ };
44
+ }
package/src/schemas.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Zod schemas for the Lovable public API, generated by `@hey-api/openapi-ts`
3
+ * from the Go OpenAPI spec operations marked as public API.
4
+ *
5
+ * Consumers import schemas to validate API responses or to advertise them as
6
+ * MCP tool output schemas. The published SDK keeps the typed openapi-fetch
7
+ * client unchanged; this module is the runtime-validation entry point.
8
+ */
9
+ export * from "./generated/zod/zod.gen.js";
10
+
11
+ import { z } from "zod";
12
+
13
+ // POST /v1/database/query is served but sits outside the public OpenAPI
14
+ // boundary, so its schemas are not generated; hand-maintained for the MCP
15
+ // query_database tool's output validation.
16
+ export const V1DatabaseQueryOutputBodySchema = z.object({
17
+ rows: z.array(z.record(z.string(), z.unknown())).nullable(),
18
+ });
19
+
20
+ export const V1DatabaseQueryOutputBodyWritableSchema = z.object({
21
+ rows: z.array(z.record(z.string(), z.unknown())).nullable(),
22
+ });
package/src/types.ts ADDED
@@ -0,0 +1,493 @@
1
+ // Type definitions for the Lovable SDK.
2
+ //
3
+ // Response and request body types come straight from the generated OpenAPI
4
+ // types (`./generated/paths.ts`, produced by `openapi-typescript` from the
5
+ // trimmed v1 spec). The same trimmed spec also drives `./generated/zod/`
6
+ // (consumed by `@lovable.dev/sdk/schemas` for runtime validation), so the
7
+ // type aliases here are guaranteed to match the schemas the MCP server
8
+ // uses — there is no hand-maintained parallel shape to drift.
9
+ //
10
+ // Types that don't have a 1:1 OpenAPI counterpart (request options, SDK
11
+ // wrappers like `MessageCompletionResult` that re-shape responses, helper
12
+ // interfaces like `FileInput`) stay hand-written below.
13
+
14
+ import type { components, paths } from "./generated/paths.js";
15
+
16
+ type Schemas = components["schemas"];
17
+
18
+ type ListProjectsQuery = NonNullable<paths["/v1/projects"]["get"]["parameters"]["query"]>;
19
+ type ListConnectorsQuery = NonNullable<paths["/v1/connectors"]["get"]["parameters"]["query"]>;
20
+
21
+ // =============================================================================
22
+ // API types — derived from the OpenAPI spec
23
+ // =============================================================================
24
+
25
+ // --- Users & workspaces ---
26
+
27
+ export type MeWorkspace = Schemas["GetMeWorkspace"];
28
+ export type MeResponse = Schemas["GetMeOutputBody"];
29
+ export type WorkspaceMembership = Schemas["WorkspaceMembership"];
30
+ export type WorkspaceWithMembership = Schemas["WorkspaceWithMembership"];
31
+ export type GetWorkspacesResponse = Schemas["V1ListWorkspacesBody"];
32
+
33
+ // Role enum lives on WorkspaceMembership in the spec; reuse it so SDK callers
34
+ // always pick from the same set the server returns.
35
+ export type MemberRole = WorkspaceMembership["role"];
36
+
37
+ // --- Projects ---
38
+
39
+ // Lean shape returned by GET /v1/projects/{id} and POST /v1/projects.
40
+ export type ProjectResponse = Schemas["V1ProjectResponse"];
41
+ export type CreateProjectResponse = Schemas["PublicV1CreateProjectResponse"] & { id: string };
42
+ export type CreateProjectBody = Omit<Schemas["PublicV1ProjectCreateInputBody"], "workspace_id">;
43
+ export type UpdateProjectOptions = Schemas["PublicV1PatchProjectBody"];
44
+ export type EmbedURLResponse = Schemas["V1CreateEmbedURLOutputBody"];
45
+
46
+ // Wider listing shape returned by the search endpoint.
47
+ export type ListProjectItem = Schemas["SearchProjectItem"];
48
+ export type ListProjectsResponse = Schemas["CursorListResponseSearchProjectItem"] & {
49
+ projects: ListProjectItem[] | null;
50
+ total?: number;
51
+ has_more?: boolean;
52
+ };
53
+ export type GetWorkspaceProjectsResponse = ListProjectsResponse;
54
+ export type MoveProjectsToFolderResponse = Schemas["AddProjectsToFolderResult"];
55
+
56
+ // Visibility enum is narrowest on SearchProjectItem ("public" | "private" | "draft");
57
+ // V1ProjectResponse types visibility as plain string. Use the narrower one.
58
+ export type ProjectVisibility = NonNullable<ListProjectItem["visibility"]>;
59
+ export type ProjectPatchVisibility = NonNullable<UpdateProjectOptions["visibility"]>;
60
+
61
+ // --- Messages ---
62
+
63
+ export type SendMessageResponse = Schemas["V1SendMessageOutputBody"];
64
+ export type GetMessageResponse = Schemas["V1MessageResponse"];
65
+ export type MessageSummary = Schemas["V1MessageListItem"];
66
+ type AwaitingInputSummary = Partial<Schemas["V1AwaitingInputSummary"]>;
67
+ export type ListMessagesResponse = Schemas["CursorListResponseV1MessageListItem"] & {
68
+ messages: MessageSummary[] | null;
69
+ has_more: boolean;
70
+ };
71
+ export interface ListMessagesOptions {
72
+ limit?: number;
73
+ cursor?: string;
74
+ /** @deprecated Use `cursor` from `pagination.next_cursor`; kept for source compatibility. */
75
+ before?: string;
76
+ }
77
+
78
+ export interface ChatResponse {
79
+ content: string;
80
+ previewUrl: string;
81
+ messageId: string;
82
+ }
83
+
84
+ export interface ChatResponseOptions {
85
+ timeout?: number;
86
+ }
87
+
88
+ export type CreateVariantResponse = Schemas["V1CreateVariantOutputBody"];
89
+
90
+ // --- Deployment ---
91
+
92
+ export type DeploymentResponse = Schemas["V1DeployProjectOutputBody"];
93
+
94
+ // --- Database ---
95
+
96
+ export type DatabaseStatus = Schemas["V1GetDatabaseStatusOutputBody"];
97
+ export type EnableDatabaseResult = Schemas["V1EnableDatabaseOutputBody"];
98
+ // POST /v1/database/query is served but sits outside the public OpenAPI
99
+ // boundary, so no generated type exists; hand-maintained for queryDatabase
100
+ // and the MCP query_database tool.
101
+ export type DatabaseQueryResult = {
102
+ rows: Record<string, unknown>[] | null;
103
+ };
104
+
105
+ // --- Knowledge ---
106
+
107
+ export type KnowledgeResponse = Schemas["V1KnowledgeResponse"];
108
+
109
+ // --- Skills ---
110
+
111
+ export type WorkspaceSkillFile = Schemas["ProjectFileInfo"];
112
+ export type WorkspaceSkill = Schemas["V1WorkspaceSkillDTO"];
113
+ export type ListWorkspaceSkillsResponse = Schemas["V1ListWorkspaceSkillsOutputBody"];
114
+ export type WorkspaceSkillResponse = Schemas["V1GetWorkspaceSkillOutputBody"];
115
+ export type WorkspaceSkillWriteResponse = Schemas["V1WriteWorkspaceSkillOutputBody"];
116
+ export type WorkspaceSkillDeleteResponse = Schemas["V1DeleteWorkspaceSkillOutputBody"];
117
+
118
+ export type ProjectSkill = Schemas["V1ProjectSkillDTO"];
119
+ export type ListProjectSkillsResponse = Schemas["CursorListResponseV1ProjectSkillDTO"] & {
120
+ skills: ProjectSkill[];
121
+ };
122
+ export type ProjectSkillResponse = Schemas["V1SetProjectSkillEnabledOutputBody"];
123
+
124
+ // --- File upload ---
125
+
126
+ export type FileUploadUrlResponse = Schemas["V1FileUploadURLOutputBody"];
127
+ export type UnscopedFile = Schemas["V1UnscopedFile"];
128
+
129
+ // --- Git / diffs / files / edits ---
130
+
131
+ export type DiffLine = Schemas["DiffLine"];
132
+ export type DiffHunk = Schemas["DiffHunk"];
133
+ export type DiffEntry = Schemas["V1DiffEntry"];
134
+ export type GitDiffResponse = Schemas["V1DiffResponse"];
135
+ export type GitFileEntry = Schemas["GitFileEntryLite"];
136
+ export type GitFilesResponse = Schemas["PublicV1GitFilesResponse"] & { files: GitFileEntry[] };
137
+ export type EditSummary = Schemas["V1EditSummary"];
138
+ export type EditsResponse = Schemas["V1GetEditsOutputBody"];
139
+
140
+ // --- Libraries & templates ---
141
+
142
+ export type LibraryProjectResponse = Record<string, unknown>;
143
+ export type TemplateProjectResponse = Record<string, unknown>;
144
+ export type ListLibraryProjectsResponse = {
145
+ libraries: LibraryProjectResponse[];
146
+ total?: number;
147
+ has_more?: boolean;
148
+ };
149
+ export type ListTemplateProjectsResponse = {
150
+ templates: TemplateProjectResponse[];
151
+ total?: number;
152
+ has_more?: boolean;
153
+ };
154
+
155
+ // --- Connectors ---
156
+
157
+ export type ConnectorResponse = Schemas["V1ConnectorResponse"];
158
+ export type AvailableConnectorEntry = Schemas["V1AvailableConnectorEntry"];
159
+ export type AddConnectorBody = Omit<Schemas["PublicV1AddConnectorBody"], "workspace_id">;
160
+ export type ConnectorItem = Schemas["PublicV1ConnectorItem"];
161
+ export type StandardConnectorItem = ConnectorItem;
162
+ export type SeamlessConnectorItem = ConnectorItem;
163
+ export type MCPConnectorItem = ConnectorItem;
164
+ export type ConnectionItem = Schemas["V1ConnectionItem"];
165
+ export type ListConnectorsResponse = Omit<Schemas["CursorListResponsePublicV1ConnectorItem"], "data"> & {
166
+ data: ConnectorItem[];
167
+ connectors: ConnectorItem[];
168
+ has_more: boolean;
169
+ };
170
+ export type ListAvailableConnectorsResponse = Omit<Schemas["CursorListResponseV1AvailableConnectorEntry"], "data"> & {
171
+ data: AvailableConnectorEntry[];
172
+ catalog: AvailableConnectorEntry[];
173
+ has_more: boolean;
174
+ };
175
+ export type ListStandardConnectorsResponse = Omit<ListConnectorsResponse, "connectors"> & {
176
+ connectors: StandardConnectorItem[];
177
+ };
178
+ export type ListSeamlessConnectorsResponse = Omit<ListConnectorsResponse, "connectors"> & {
179
+ connectors: SeamlessConnectorItem[];
180
+ };
181
+ export type ListMCPConnectorsResponse = Omit<ListConnectorsResponse, "connectors"> &
182
+ Partial<Omit<Schemas["V1ListMCPConnectorsResponse"], "connectors">> & {
183
+ data: MCPConnectorItem[];
184
+ connectors: MCPConnectorItem[];
185
+ };
186
+ export type ListConnectionsResponse = Omit<Schemas["CursorListResponseV1ConnectionItem"], "data"> & {
187
+ data: ConnectionItem[];
188
+ connections: ConnectionItem[];
189
+ has_more: boolean;
190
+ };
191
+
192
+ // --- Analytics ---
193
+
194
+ export type TimeSeriesDataPoint = Schemas["TimeSeriesDataPoint"];
195
+ export type TimeSeriesData = Schemas["TimeSeriesData"];
196
+ export type ListDataPoint = Schemas["ListDataPoint"];
197
+ export type ListData = Schemas["ListData"];
198
+ export type ProjectAnalyticsResponse = Schemas["ProjectAnalyticsResponse"];
199
+ export type TrendDataPoint = Schemas["TrendDataPoint"];
200
+ export type ProjectAnalyticsTrendResponse = Schemas["ProjectTrendResponse"];
201
+
202
+ // --- Remix ---
203
+
204
+ export type RemixJobStepInfo = Schemas["RemixJobStepInfo"];
205
+ export type RemixInitResponse = { job_id: string };
206
+ export type RemixProgressResult = Schemas["V1RemixProgressResult"];
207
+ export type RemixProgressResponse = {
208
+ status: string;
209
+ step?: RemixJobStepInfo;
210
+ result?: RemixProgressResult;
211
+ error_message?: string;
212
+ error_code?: string;
213
+ };
214
+
215
+ // The V1 spec types `status` as plain string. The Go handler returns one of
216
+ // these five values — keep the narrow union here as an SDK-side aid for
217
+ // callers that switch on it. If the spec ever exposes this as an enum,
218
+ // replace with `Schemas["V1RemixProgressOutputBody"]["status"]`.
219
+ export type RemixJobStatus = "unknown" | "preparing" | "running" | "completed" | "error";
220
+ export type RemixJobStep =
221
+ | "starting"
222
+ | "creating_new_project"
223
+ | "restoring_supabase"
224
+ | "copying_history"
225
+ | "preparing_repository"
226
+ | "remixing_integration"
227
+ | "pushing_repository"
228
+ | "finalizing"
229
+ | "completed";
230
+
231
+ // V1 status field on V1ProjectResponse is plain string; the Go handler returns
232
+ // one of these three. Same rationale as RemixJobStatus.
233
+ export type ProjectStatus = "completed" | "in_progress" | "failed";
234
+
235
+ // =============================================================================
236
+ // SDK helpers — no OpenAPI counterpart
237
+ // =============================================================================
238
+
239
+ export interface ChatRequest {
240
+ id: string;
241
+ message: string;
242
+ chat_only: boolean;
243
+ headless: boolean;
244
+ ai_message_id?: string;
245
+ intent?: string;
246
+ model?: string;
247
+ temperature?: number;
248
+ current_page?: string;
249
+ view?: string;
250
+ view_description?: string;
251
+ prev_session_id?: string;
252
+ is_creation?: boolean;
253
+ files?: UnscopedFile[];
254
+ }
255
+
256
+ /** @deprecated `remixProject()` now uses POST /v1/projects with `source_project_id`. */
257
+ export interface RemixInitBody extends Omit<Schemas["V1RemixInitInputBody"], "initial_message"> {
258
+ initial_message?: ChatRequest;
259
+ message_id?: string;
260
+ remix_mode?: RemixMode;
261
+ skip_integrations?: boolean;
262
+ }
263
+
264
+ export type RemixCreateProjectBody = Schemas["PublicV1ProjectRemixInputBody"];
265
+
266
+ export interface FileInput {
267
+ name: string;
268
+ data: Blob | ArrayBuffer | Uint8Array;
269
+ type: string;
270
+ }
271
+
272
+ export interface CreateProjectOptions {
273
+ description: string;
274
+ projectName?: string;
275
+ techStack?: string;
276
+ /** Sandbox runtime template. Requires a workspace with access to the requested template. */
277
+ sandboxTemplate?: string;
278
+ visibility?: ProjectVisibility;
279
+ templateProjectId?: string;
280
+ initialMessage?: string;
281
+ /** Files to upload and attach to the initial message. The SDK handles uploading. */
282
+ files?: (File | FileInput)[];
283
+ /** Pre-uploaded file references to attach to the initial message. Skips upload. */
284
+ uploadedFiles?: UnscopedFile[];
285
+ /** Public image or HTML file URLs to fetch server-side and attach to the initial message. */
286
+ fileUrls?: string[];
287
+ /** Design system library projects to connect to the new project. */
288
+ selectedLibraries?: { project_id: string }[];
289
+ }
290
+
291
+ /**
292
+ * Controls prompt cache continuation behavior for a message.
293
+ *
294
+ * - `"force"` — skip cache TTL and token/criteria checks (force continuation)
295
+ * - `"fresh_build"` — force a full prompt rebuild from scratch
296
+ * - `"allow_expired_cache"` — skip cache TTL check but respect token/criteria limits
297
+ *
298
+ * Omit for default behavior (5-min TTL, token and criteria checks apply).
299
+ */
300
+ export type ContinuationOverride = "force" | "fresh_build" | "allow_expired_cache";
301
+
302
+ export interface ChatMessageOptions {
303
+ message: string;
304
+ /** Send the message to this project variant instead of the main agent. */
305
+ variantId?: string;
306
+ /** Files to upload and attach. The SDK handles uploading them first. */
307
+ files?: (File | FileInput)[];
308
+ /** Pre-uploaded file references. Skips upload. */
309
+ uploadedFiles?: UnscopedFile[];
310
+ /** Enable plan mode: the agent discusses and plans without editing code. */
311
+ planMode?: boolean;
312
+ /**
313
+ * Override continuation behavior for this message.
314
+ * Controls whether the agent reuses the prompt cache or rebuilds from scratch.
315
+ */
316
+ continuation?: ContinuationOverride;
317
+ }
318
+
319
+ export interface CreateVariantOptions {
320
+ /** Display name. The API assigns the next Draft number when omitted. */
321
+ label?: string;
322
+ /** Full 40-character commit SHA to base the variant branch on. Defaults to the project main branch. */
323
+ baseSha?: string;
324
+ }
325
+
326
+ export interface LovableClientOptions {
327
+ /** API key for authentication (mutually exclusive with bearerToken) */
328
+ apiKey?: string;
329
+ /** Bearer token for OAuth authentication (mutually exclusive with apiKey) */
330
+ bearerToken?: string;
331
+ baseUrl?: string;
332
+ /** Additional headers to include on every request */
333
+ headers?: Record<string, string>;
334
+ /**
335
+ * Identifier for the originating client, sent as the `X-Client-Source` header.
336
+ * Used by the API to tag audit logs and observability with the message origin.
337
+ * Defaults to `"sdk"`. The Go API allowlist accepts `"mcp"`, `"sdk"`, `"cli"`.
338
+ */
339
+ clientSource?: string;
340
+ }
341
+
342
+ export interface LovableError extends Error {
343
+ status: number;
344
+ type?: string;
345
+ detail?: string;
346
+ }
347
+
348
+ export interface WaitOptions {
349
+ pollInterval?: number;
350
+ timeout?: number;
351
+ onProgress?: (project: ProjectResponse) => void;
352
+ }
353
+
354
+ export interface ListCursorPaginationOptions {
355
+ limit?: number;
356
+ cursor?: string;
357
+ }
358
+
359
+ export interface ListOffsetPaginationOptions {
360
+ limit?: number;
361
+ offset?: number;
362
+ }
363
+
364
+ export interface ListHybridPaginationOptions {
365
+ limit?: number;
366
+ cursor?: string;
367
+ offset?: number;
368
+ }
369
+
370
+ export type ListConnectorsOptions = Omit<ListConnectorsQuery, "workspace_id">;
371
+
372
+ /** @deprecated Use the cursor, offset, or hybrid pagination option type that matches the route. */
373
+ export type ListPaginationOptions = ListHybridPaginationOptions;
374
+
375
+ export type CursorPaginationOptions = ListCursorPaginationOptions;
376
+
377
+ export type RemixMode = "before" | "including";
378
+
379
+ export interface RemixProjectOptions {
380
+ workspaceId: string;
381
+ messageId?: string;
382
+ remixMode?: RemixMode;
383
+ includeHistory?: boolean;
384
+ includeCustomKnowledge?: boolean;
385
+ initialMessage?: string;
386
+ description?: string;
387
+ projectName?: string;
388
+ skipInitialRemixMessage?: boolean;
389
+ skipIntegrations?: boolean;
390
+ }
391
+
392
+ // camelCase wrapper — not a direct alias of V1RemixProgressResult.
393
+ export interface RemixResult {
394
+ projectId: string;
395
+ }
396
+
397
+ export interface RemixWaitOptions {
398
+ pollInterval?: number;
399
+ timeout?: number;
400
+ onProgress?: (status: RemixJobStatus, step?: RemixJobStepInfo) => void;
401
+ }
402
+
403
+ export interface MessageCompletionResult {
404
+ status: "completed" | "stopped" | "awaiting_input" | "timeout" | "error";
405
+ message_id: string;
406
+ content: string;
407
+ awaiting_input?: AwaitingInputSummary;
408
+ edit_id?: string;
409
+ commit_sha?: string;
410
+ summary?: string;
411
+ cost_credits?: number;
412
+ error?: string;
413
+ }
414
+
415
+ export interface MessageCompletionOptions {
416
+ /** Trajectory thread returned by chat(). Enables thread-aware completion. */
417
+ threadId?: string;
418
+ /**
419
+ * Maximum seconds the server holds each long-poll request before returning
420
+ * a non-terminal snapshot. Clamped server-side to [0, 55]. Defaults to 30.
421
+ */
422
+ waitSeconds?: number;
423
+ /** Maximum total time to wait in ms (default: 600000 = 10 minutes) */
424
+ timeout?: number;
425
+ /**
426
+ * @deprecated Long-poll replaces client-side polling; this is ignored.
427
+ * Kept for source-compat with callers that still pass it.
428
+ */
429
+ pollInterval?: number;
430
+ }
431
+
432
+ export interface GetMessageOptions {
433
+ /** Trajectory thread returned by chat(). Enables thread-aware status reads. */
434
+ threadId?: string;
435
+ /**
436
+ * Long-poll: ask the server to hold the request until the message reaches a
437
+ * terminal state or this many seconds elapse. Clamped server-side to [0, 55].
438
+ */
439
+ waitSeconds?: number;
440
+ }
441
+
442
+ export interface ListProjectsOptions {
443
+ /** Full-text search; mapped to `q` on the wire. */
444
+ query?: string;
445
+ visibility?: ListProjectsQuery["visibility"];
446
+ publish_status?: ListProjectsQuery["publish_status"];
447
+ folder_id?: ListProjectsQuery["folder_id"];
448
+ folder_ids?: ListProjectsQuery["folder_ids"];
449
+ user_id?: ListProjectsQuery["user_id"];
450
+ type?: ListProjectsQuery["type"];
451
+ include_risk?: ListProjectsQuery["include_risk"];
452
+ search_fields?: ListProjectsQuery["search_fields"];
453
+ viewed_by_me?: ListProjectsQuery["viewed_by_me"];
454
+ cursor?: ListProjectsQuery["cursor"];
455
+ limit?: ListProjectsQuery["limit"];
456
+ }
457
+
458
+ // =============================================================================
459
+ // Runtime exports
460
+ // =============================================================================
461
+
462
+ export interface RateLimitInfo {
463
+ /** X-RateLimit-Limit: the request budget for the current window. */
464
+ limit?: number;
465
+ /** X-RateLimit-Remaining: requests left in the current window. */
466
+ remaining?: number;
467
+ /** Retry-After in milliseconds (parsed from the Retry-After header). */
468
+ retryAfterMs?: number;
469
+ }
470
+
471
+ export class ApiError extends Error {
472
+ readonly status: number;
473
+ readonly type?: string;
474
+ readonly detail?: string;
475
+ readonly props?: Record<string, unknown>;
476
+ readonly rateLimit?: RateLimitInfo;
477
+
478
+ constructor(
479
+ status: number,
480
+ message: string,
481
+ type?: string,
482
+ detail?: string,
483
+ props?: Record<string, unknown>,
484
+ rateLimit?: RateLimitInfo,
485
+ ) {
486
+ super(message);
487
+ this.status = status;
488
+ this.type = type;
489
+ this.detail = detail;
490
+ this.props = props;
491
+ this.rateLimit = rateLimit;
492
+ }
493
+ }