@mindstudio-ai/agent 0.1.88 → 0.1.90

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/dist/index.d.ts CHANGED
@@ -1,3 +1,159 @@
1
+ /**
2
+ * Access level of a file store. `private` (the default) → reads are signed /
3
+ * session-authorized; `public` → world-readable, CDN-served on the app's own
4
+ * domain (and resizable via image query params).
5
+ */
6
+ type FileAccess = 'public' | 'private';
7
+ /** Options for {@link Store.put}. */
8
+ interface PutOptions {
9
+ /**
10
+ * Object key within the store (nested paths allowed, e.g. `reports/q1.pdf`).
11
+ * Omit to auto-generate a UUID key (with `filename`'s extension, if given).
12
+ */
13
+ key?: string;
14
+ /** MIME type stored on the object and returned on read. */
15
+ contentType?: string;
16
+ /** Original filename — used only to derive an extension when `key` is omitted. */
17
+ filename?: string;
18
+ /**
19
+ * When true (and no explicit `key`), derive the key from a content hash
20
+ * (`<sha256>.<ext>`) instead of a random UUID — immutable + idempotent, so
21
+ * re-uploading identical bytes yields the same key/URL. Ideal for public
22
+ * assets baked into source.
23
+ */
24
+ contentAddressed?: boolean;
25
+ }
26
+ /** Options for {@link Store.list}. */
27
+ interface ListOptions {
28
+ /** Restrict to keys under this prefix (relative to the store). */
29
+ prefix?: string;
30
+ /** Pagination cursor from a previous page. */
31
+ cursor?: string;
32
+ /** Max objects per page. */
33
+ limit?: number;
34
+ }
35
+ /** A stored object plus a ready-to-use URL. */
36
+ interface StoredFile {
37
+ store: string;
38
+ key: string;
39
+ access: FileAccess;
40
+ size?: number;
41
+ contentType?: string;
42
+ updatedAt?: string;
43
+ /**
44
+ * Stable, on-domain URL for the app's own frontend — drop straight into
45
+ * `<img src>`, `fetch`, or `<a download>`. Relative (resolves against the
46
+ * app's origin); a same-origin logged-in request authorizes automatically
47
+ * via the app session, so there's nothing to await.
48
+ */
49
+ url: string;
50
+ /**
51
+ * Mint an ABSOLUTE, signed share URL that works with **no** active session —
52
+ * email it, or embed it on another site. Expires (default 24h). Private
53
+ * stores only.
54
+ */
55
+ shareUrl(options?: {
56
+ expiresIn?: number;
57
+ }): Promise<string>;
58
+ }
59
+ /**
60
+ * A token for a client-direct upload, from {@link Store.createUploadToken}.
61
+ * Return it from a backend method and pass it straight to the frontend's
62
+ * `platform.upload(token, file)` — the browser then POSTs the file directly to
63
+ * storage (no bytes through the platform).
64
+ */
65
+ interface UploadToken {
66
+ /** The object key the upload will land at (within the store). */
67
+ key: string;
68
+ /** The stable on-domain URL the file will be readable at once uploaded. */
69
+ url: string;
70
+ /** @internal The scoped presigned POST the frontend submits to. */
71
+ upload: {
72
+ url: string;
73
+ fields: Record<string, string>;
74
+ };
75
+ }
76
+ /** @internal Per-store upload policy carried from `defineStore`. */
77
+ interface StorePolicy {
78
+ maxSize?: number;
79
+ contentTypes?: string[];
80
+ }
81
+ /** @internal Transport: `POST /_internal/v2/files/<op>` with the hook token. */
82
+ type FilesTransport = (op: string, body: unknown) => Promise<any>;
83
+ /**
84
+ * A typed handle to one named file store. Lazy — nothing executes until a
85
+ * method is awaited, so it's safe to `defineStore()` at module scope and import
86
+ * the handle into route handlers (same ergonomics as `db.defineTable`).
87
+ */
88
+ declare class Store {
89
+ private readonly _store;
90
+ private readonly _access;
91
+ private readonly _call;
92
+ private readonly _policy;
93
+ constructor(_store: string, _access: FileAccess, _call: FilesTransport, _policy?: StorePolicy);
94
+ /** The store's name. */
95
+ get name(): string;
96
+ /** The store's access level. */
97
+ get access(): FileAccess;
98
+ /** Store bytes. Returns a {@link StoredFile} with a ready-to-use `url`. */
99
+ put(content: Buffer | Uint8Array | string, options?: PutOptions): Promise<StoredFile>;
100
+ /** Read an object's bytes (backend / trusted context). */
101
+ get(key: string): Promise<Buffer>;
102
+ /** Metadata without downloading. Rejects if the object doesn't exist. */
103
+ head(key: string): Promise<StoredFile>;
104
+ /** Whether an object exists. */
105
+ exists(key: string): Promise<boolean>;
106
+ /** List objects in the store (optionally under `prefix`), one page at a time. */
107
+ list(options?: ListOptions): Promise<{
108
+ files: StoredFile[];
109
+ cursor?: string;
110
+ }>;
111
+ /** Delete an object. No-op if it doesn't exist. */
112
+ delete(key: string): Promise<void>;
113
+ /**
114
+ * Mint an ABSOLUTE, signed share URL for a key — works with **no** active
115
+ * session (email it, or embed it on another site). Expires (default 24h).
116
+ * Private stores only.
117
+ *
118
+ * The same link is available as `file.shareUrl()` on a {@link StoredFile};
119
+ * this convenience skips the `head()` when you already hold just the key.
120
+ */
121
+ shareUrl(key: string, options?: {
122
+ expiresIn?: number;
123
+ }): Promise<string>;
124
+ /**
125
+ * Mint an {@link UploadToken} for a **client-direct** upload — the browser
126
+ * POSTs the file straight to storage, so the bytes never pass through the
127
+ * platform. Return the token from a backend method and hand it to the
128
+ * frontend's `platform.upload(token, file)`. Works for private + public stores.
129
+ *
130
+ * Enforced at upload time by the presigned POST: a max size (this call's
131
+ * `maxSize`, else the store's, else the platform default) and — when
132
+ * `contentType` is set — an exact content-type match. When the store declares
133
+ * `contentTypes`, `contentType` must be one of them.
134
+ *
135
+ * Note: a presigned POST can pin exactly ONE content-type per token, so the
136
+ * *allowlist* is declared on `defineStore({ contentTypes })` and each token
137
+ * pins one type from it. This is by design, not a per-token limitation.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * // backend method
142
+ * export async function getUploadSlot(input: { contentType: string }) {
143
+ * return Uploads.createUploadToken({ contentType: input.contentType, maxSize: 50 * 1024 * 1024 });
144
+ * }
145
+ * ```
146
+ */
147
+ createUploadToken(options?: {
148
+ key?: string;
149
+ contentType?: string;
150
+ filename?: string;
151
+ maxSize?: number;
152
+ expiresIn?: number;
153
+ }): Promise<UploadToken>;
154
+ private _toFile;
155
+ }
156
+
1
157
  /** Configuration options for creating a {@link MindStudioAgent}. */
2
158
  interface AgentOptions {
3
159
  /**
@@ -83,6 +239,33 @@ interface StepExecutionOptions {
83
239
  * selection and token info.
84
240
  */
85
241
  onLog?: (event: StepLogEvent) => void;
242
+ /**
243
+ * Send any asset this step generates to one of the app's own file stores
244
+ * instead of the shared public MindStudio CDN.
245
+ *
246
+ * **Optional — the default is fine for most cases.** Omit it and generated
247
+ * assets keep going to the public CDN, exactly as before. Reach for it when
248
+ * the asset is user-specific, should be private, or belongs alongside the
249
+ * app's other files (where it shows up in the app's Files dashboard).
250
+ *
251
+ * The store's `access` comes from its `defineStore()`, so a private store
252
+ * yields a private asset — the returned URL is an on-domain
253
+ * `/_/files/private/...` link that only an authorized session can load,
254
+ * rather than a permanent public one.
255
+ *
256
+ * v2 apps only.
257
+ *
258
+ * @example
259
+ * ```ts
260
+ * const Photos = files.defineStore('product-photos', { access: 'public' });
261
+ *
262
+ * const { imageUrl } = await agent.generateImage(
263
+ * { prompt: 'a red sneaker on concrete' },
264
+ * { store: Photos },
265
+ * );
266
+ * ```
267
+ */
268
+ store?: Store;
86
269
  }
87
270
  /** Execution metadata returned alongside every step result. */
88
271
  interface StepExecutionMeta {
@@ -232,7 +415,7 @@ interface MindStudioModel {
232
415
  id?: string;
233
416
  /** Display name of the model. */
234
417
  name?: string;
235
- /** One of: `llm_chat`, `image_generation`, `video_generation`, `video_analysis`, `text_to_speech`, `vision`, `transcription`. */
418
+ /** See `ModelType` for the full set. */
236
419
  type?: ModelType;
237
420
  maxTemperature?: number;
238
421
  maxResponseSize?: number;
@@ -244,13 +427,20 @@ interface MindStudioModelSummary {
244
427
  id?: string;
245
428
  /** Display name of the model. */
246
429
  name?: string;
247
- /** One of: `llm_chat`, `image_generation`, `video_generation`, `video_analysis`, `text_to_speech`, `vision`, `transcription`. */
430
+ /** See `ModelType` for the full set. */
248
431
  type?: ModelType;
249
432
  /** Comma-separated tags for the model. */
250
433
  tags?: string;
251
434
  }
252
- /** Supported model type categories for filtering. */
253
- type ModelType = 'llm_chat' | 'image_generation' | 'video_generation' | 'video_analysis' | 'text_to_speech' | 'vision' | 'transcription';
435
+ /**
436
+ * Supported model type categories for filtering.
437
+ *
438
+ * `embedding`, `reranking` and `document_extraction` have no SDK step — the
439
+ * data-source pipeline chooses those platform-side and reports the result on
440
+ * `pipeline.embeddingModelId`. They are listed so the catalog can be queried
441
+ * and described, not so they can be passed to a generate call.
442
+ */
443
+ type ModelType = 'llm_chat' | 'image_generation' | '3d_generation' | 'video_generation' | 'video_analysis' | 'text_to_speech' | 'music_generation' | 'lipsync' | 'vision' | 'transcription' | 'embedding' | 'reranking' | 'document_extraction';
254
444
  /** Role assignment for a user within an app. */
255
445
  interface AppRoleAssignment {
256
446
  userId: string;
@@ -478,6 +668,12 @@ interface ExecuteStepBatchOptions {
478
668
  threadId?: string;
479
669
  /** Progress callback, called on each poll while the batch is running. */
480
670
  onProgress?: (completedSteps: number, totalSteps: number) => void;
671
+ /**
672
+ * Send assets generated by any step in this batch to one of the app's own
673
+ * file stores instead of the shared public MindStudio CDN. Optional; applies
674
+ * to every step in the batch. See {@link StepExecutionOptions.store}.
675
+ */
676
+ store?: Store;
481
677
  }
482
678
  /** Result of {@link MindStudioAgent.executeStepBatch}. */
483
679
  interface ExecuteStepBatchResult {
@@ -1292,160 +1488,6 @@ interface Db {
1292
1488
  batch(...queries: PromiseLike<unknown>[]): Promise<unknown[]>;
1293
1489
  }
1294
1490
 
1295
- /**
1296
- * Access level of a file store. `private` (the default) → reads are signed /
1297
- * session-authorized; `public` → world-readable, CDN-served on the app's own
1298
- * domain (and resizable via image query params).
1299
- */
1300
- type FileAccess = 'public' | 'private';
1301
- /** Options for {@link Store.put}. */
1302
- interface PutOptions {
1303
- /**
1304
- * Object key within the store (nested paths allowed, e.g. `reports/q1.pdf`).
1305
- * Omit to auto-generate a UUID key (with `filename`'s extension, if given).
1306
- */
1307
- key?: string;
1308
- /** MIME type stored on the object and returned on read. */
1309
- contentType?: string;
1310
- /** Original filename — used only to derive an extension when `key` is omitted. */
1311
- filename?: string;
1312
- /**
1313
- * When true (and no explicit `key`), derive the key from a content hash
1314
- * (`<sha256>.<ext>`) instead of a random UUID — immutable + idempotent, so
1315
- * re-uploading identical bytes yields the same key/URL. Ideal for public
1316
- * assets baked into source.
1317
- */
1318
- contentAddressed?: boolean;
1319
- }
1320
- /** Options for {@link Store.list}. */
1321
- interface ListOptions {
1322
- /** Restrict to keys under this prefix (relative to the store). */
1323
- prefix?: string;
1324
- /** Pagination cursor from a previous page. */
1325
- cursor?: string;
1326
- /** Max objects per page. */
1327
- limit?: number;
1328
- }
1329
- /** A stored object plus a ready-to-use URL. */
1330
- interface StoredFile {
1331
- store: string;
1332
- key: string;
1333
- access: FileAccess;
1334
- size?: number;
1335
- contentType?: string;
1336
- updatedAt?: string;
1337
- /**
1338
- * Stable, on-domain URL for the app's own frontend — drop straight into
1339
- * `<img src>`, `fetch`, or `<a download>`. Relative (resolves against the
1340
- * app's origin); a same-origin logged-in request authorizes automatically
1341
- * via the app session, so there's nothing to await.
1342
- */
1343
- url: string;
1344
- /**
1345
- * Mint an ABSOLUTE, signed share URL that works with **no** active session —
1346
- * email it, or embed it on another site. Expires (default 24h). Private
1347
- * stores only.
1348
- */
1349
- shareUrl(options?: {
1350
- expiresIn?: number;
1351
- }): Promise<string>;
1352
- }
1353
- /**
1354
- * A token for a client-direct upload, from {@link Store.createUploadToken}.
1355
- * Return it from a backend method and pass it straight to the frontend's
1356
- * `platform.upload(token, file)` — the browser then POSTs the file directly to
1357
- * storage (no bytes through the platform).
1358
- */
1359
- interface UploadToken {
1360
- /** The object key the upload will land at (within the store). */
1361
- key: string;
1362
- /** The stable on-domain URL the file will be readable at once uploaded. */
1363
- url: string;
1364
- /** @internal The scoped presigned POST the frontend submits to. */
1365
- upload: {
1366
- url: string;
1367
- fields: Record<string, string>;
1368
- };
1369
- }
1370
- /** @internal Per-store upload policy carried from `defineStore`. */
1371
- interface StorePolicy {
1372
- maxSize?: number;
1373
- contentTypes?: string[];
1374
- }
1375
- /** @internal Transport: `POST /_internal/v2/files/<op>` with the hook token. */
1376
- type FilesTransport = (op: string, body: unknown) => Promise<any>;
1377
- /**
1378
- * A typed handle to one named file store. Lazy — nothing executes until a
1379
- * method is awaited, so it's safe to `defineStore()` at module scope and import
1380
- * the handle into route handlers (same ergonomics as `db.defineTable`).
1381
- */
1382
- declare class Store {
1383
- private readonly _store;
1384
- private readonly _access;
1385
- private readonly _call;
1386
- private readonly _policy;
1387
- constructor(_store: string, _access: FileAccess, _call: FilesTransport, _policy?: StorePolicy);
1388
- /** The store's access level. */
1389
- get access(): FileAccess;
1390
- /** Store bytes. Returns a {@link StoredFile} with a ready-to-use `url`. */
1391
- put(content: Buffer | Uint8Array | string, options?: PutOptions): Promise<StoredFile>;
1392
- /** Read an object's bytes (backend / trusted context). */
1393
- get(key: string): Promise<Buffer>;
1394
- /** Metadata without downloading. Rejects if the object doesn't exist. */
1395
- head(key: string): Promise<StoredFile>;
1396
- /** Whether an object exists. */
1397
- exists(key: string): Promise<boolean>;
1398
- /** List objects in the store (optionally under `prefix`), one page at a time. */
1399
- list(options?: ListOptions): Promise<{
1400
- files: StoredFile[];
1401
- cursor?: string;
1402
- }>;
1403
- /** Delete an object. No-op if it doesn't exist. */
1404
- delete(key: string): Promise<void>;
1405
- /**
1406
- * Mint an ABSOLUTE, signed share URL for a key — works with **no** active
1407
- * session (email it, or embed it on another site). Expires (default 24h).
1408
- * Private stores only.
1409
- *
1410
- * The same link is available as `file.shareUrl()` on a {@link StoredFile};
1411
- * this convenience skips the `head()` when you already hold just the key.
1412
- */
1413
- shareUrl(key: string, options?: {
1414
- expiresIn?: number;
1415
- }): Promise<string>;
1416
- /**
1417
- * Mint an {@link UploadToken} for a **client-direct** upload — the browser
1418
- * POSTs the file straight to storage, so the bytes never pass through the
1419
- * platform. Return the token from a backend method and hand it to the
1420
- * frontend's `platform.upload(token, file)`. Works for private + public stores.
1421
- *
1422
- * Enforced at upload time by the presigned POST: a max size (this call's
1423
- * `maxSize`, else the store's, else the platform default) and — when
1424
- * `contentType` is set — an exact content-type match. When the store declares
1425
- * `contentTypes`, `contentType` must be one of them.
1426
- *
1427
- * Note: a presigned POST can pin exactly ONE content-type per token, so the
1428
- * *allowlist* is declared on `defineStore({ contentTypes })` and each token
1429
- * pins one type from it. This is by design, not a per-token limitation.
1430
- *
1431
- * @example
1432
- * ```ts
1433
- * // backend method
1434
- * export async function getUploadSlot(input: { contentType: string }) {
1435
- * return Uploads.createUploadToken({ contentType: input.contentType, maxSize: 50 * 1024 * 1024 });
1436
- * }
1437
- * ```
1438
- */
1439
- createUploadToken(options?: {
1440
- key?: string;
1441
- contentType?: string;
1442
- filename?: string;
1443
- maxSize?: number;
1444
- expiresIn?: number;
1445
- }): Promise<UploadToken>;
1446
- private _toFile;
1447
- }
1448
-
1449
1491
  /**
1450
1492
  * The `files` namespace — typed, private-by-default file storage for MindStudio
1451
1493
  * apps. Think of a store as a CDN-backed bucket the app talks to, not app-defined
@@ -3169,6 +3211,8 @@ interface ExtractAudioFromVideoStepOutput {
3169
3211
  interface ExtractTextStepInput {
3170
3212
  /** URL or array of URLs to extract text from. Accepts a single URL, comma-separated list, or JSON array */
3171
3213
  url: string | string[];
3214
+ /** Optional extraction model id (a `document_extraction` model, e.g. `mistral-ocr-latest`, `llamaparse`, `google-document-ai`). Defaults to the platform default when omitted. */
3215
+ model?: string;
3172
3216
  }
3173
3217
  interface ExtractTextStepOutput {
3174
3218
  /** Extracted text content. A single string for one URL, or an array for multiple URLs */
@@ -3710,7 +3754,11 @@ interface GenerateImageStepInput {
3710
3754
  generateVariants?: boolean;
3711
3755
  /** Number of variants to generate (max 10) */
3712
3756
  numVariants?: number;
3713
- /** Whether to add a MindStudio watermark to the generated image */
3757
+ /**
3758
+ * Whether to add a MindStudio watermark to the generated image.
3759
+ *
3760
+ * The watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there.
3761
+ */
3714
3762
  addWatermark?: boolean;
3715
3763
  }
3716
3764
  interface GenerateImageStepOutput {
@@ -3720,7 +3768,11 @@ interface GenerateImageStepOutput {
3720
3768
  interface GenerateLipsyncStepInput {
3721
3769
  /** When true, the asset is created but hidden from the user's gallery (tagged as intermediate) */
3722
3770
  intermediateAsset?: boolean;
3723
- /** Whether to add a MindStudio watermark to the generated video */
3771
+ /**
3772
+ * Whether to add a MindStudio watermark to the generated video.
3773
+ *
3774
+ * The watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there.
3775
+ */
3724
3776
  addWatermark?: boolean;
3725
3777
  /** Optional model configuration override. Uses the workflow's default lipsync model if not specified */
3726
3778
  lipsyncModelOverride?: {
@@ -3855,7 +3907,11 @@ interface GenerateVideoStepInput {
3855
3907
  generateVariants?: boolean;
3856
3908
  /** Number of variants to generate (max 10) */
3857
3909
  numVariants?: number;
3858
- /** Whether to add a MindStudio watermark to the generated video */
3910
+ /**
3911
+ * Whether to add a MindStudio watermark to the generated video.
3912
+ *
3913
+ * The watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there.
3914
+ */
3859
3915
  addWatermark?: boolean;
3860
3916
  }
3861
3917
  interface GenerateVideoStepOutput {
@@ -7215,6 +7271,7 @@ interface StepMethods {
7215
7271
  * - Handles both text-layer PDFs and image-based/scanned PDFs (e.g. Figma/Canva exports, scanned documents). Image-based PDFs are processed with OCR automatically — there is no need to convert PDF pages to images first.
7216
7272
  * - Accepts a single URL, a comma-separated list of URLs, or a JSON array of URLs.
7217
7273
  * - Files are rehosted on the MindStudio CDN before extraction.
7274
+ * - Optionally set `model` to a specific document-extraction model (`mistral-ocr-latest`, `llamaparse`, `google-document-ai`); omit to use the platform default.
7218
7275
  * - Maximum file size is 50MB per URL.
7219
7276
  *
7220
7277
  * @example
package/dist/index.js CHANGED
@@ -107,8 +107,16 @@ var WS_OPEN_TIMEOUT_MS = 5e3;
107
107
  var WS_OPEN = 1;
108
108
  var WS_MAX_FRAME_CHARS = 9e5;
109
109
  var DbWsTransportError = class extends Error {
110
+ constructor(message, sent = false) {
111
+ super(message);
112
+ this.sent = sent;
113
+ }
110
114
  name = "DbWsTransportError";
111
115
  };
116
+ function isReadOnlySql(sql) {
117
+ const head = sql.trimStart().slice(0, 8).toUpperCase();
118
+ return head.startsWith("SELECT") || head.startsWith("PRAGMA") || head.startsWith("EXPLAIN");
119
+ }
112
120
  var socket = null;
113
121
  var opening = null;
114
122
  var idCounter = 0;
@@ -136,7 +144,7 @@ function getOrOpen(url) {
136
144
  opening = null;
137
145
  for (const [, p] of pending) {
138
146
  clearTimeout(p.timer);
139
- p.reject(err);
147
+ p.reject(new DbWsTransportError(err.message, true));
140
148
  }
141
149
  pending.clear();
142
150
  reject(err);
@@ -206,7 +214,7 @@ async function executeDbBatchOverWs(url, token, databaseId, queries) {
206
214
  return await new Promise((resolve, reject) => {
207
215
  const timer = setTimeout(() => {
208
216
  pending.delete(id);
209
- reject(new DbWsTransportError("ws execute timed out"));
217
+ reject(new DbWsTransportError("ws execute timed out", true));
210
218
  }, WS_REQUEST_TIMEOUT_MS);
211
219
  pending.set(id, { resolve, reject, timer });
212
220
  try {
@@ -215,7 +223,10 @@ async function executeDbBatchOverWs(url, token, databaseId, queries) {
215
223
  clearTimeout(timer);
216
224
  pending.delete(id);
217
225
  reject(
218
- new DbWsTransportError(`ws send failed: ${err?.message || "unknown"}`)
226
+ new DbWsTransportError(
227
+ `ws send failed: ${err?.message || "unknown"}`,
228
+ false
229
+ )
219
230
  );
220
231
  }
221
232
  });
@@ -1945,6 +1956,10 @@ var Store = class {
1945
1956
  this._call = _call;
1946
1957
  this._policy = _policy;
1947
1958
  }
1959
+ /** The store's name. */
1960
+ get name() {
1961
+ return this._store;
1962
+ }
1948
1963
  /** The store's access level. */
1949
1964
  get access() {
1950
1965
  return this._access;
@@ -2505,8 +2520,8 @@ var stepMetadata = {
2505
2520
  "extractText": {
2506
2521
  stepType: "extractText",
2507
2522
  description: "Download a file from a URL and extract its text content. Supports PDFs (including scanned/image-based PDFs via OCR), plain text files, and other document formats.",
2508
- usageNotes: "- Best suited for PDFs and raw text/document files. For web pages, use the scrapeUrl step instead.\n- Handles both text-layer PDFs and image-based/scanned PDFs (e.g. Figma/Canva exports, scanned documents). Image-based PDFs are processed with OCR automatically \u2014 there is no need to convert PDF pages to images first.\n- Accepts a single URL, a comma-separated list of URLs, or a JSON array of URLs.\n- Files are rehosted on the MindStudio CDN before extraction.\n- Maximum file size is 50MB per URL.",
2509
- inputSchema: { "type": "object", "properties": { "url": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["url"] },
2523
+ usageNotes: "- Best suited for PDFs and raw text/document files. For web pages, use the scrapeUrl step instead.\n- Handles both text-layer PDFs and image-based/scanned PDFs (e.g. Figma/Canva exports, scanned documents). Image-based PDFs are processed with OCR automatically \u2014 there is no need to convert PDF pages to images first.\n- Accepts a single URL, a comma-separated list of URLs, or a JSON array of URLs.\n- Files are rehosted on the MindStudio CDN before extraction.\n- Optionally set `model` to a specific document-extraction model (`mistral-ocr-latest`, `llamaparse`, `google-document-ai`); omit to use the platform default.\n- Maximum file size is 50MB per URL.",
2524
+ inputSchema: { "type": "object", "properties": { "url": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] }, "model": { "type": "string", "description": "Optional extraction model id (a `document_extraction` model, e.g. `mistral-ocr-latest`, `llamaparse`, `google-document-ai`). Defaults to the platform default when omitted." } }, "required": ["url"] },
2510
2525
  outputSchema: { "type": "object", "properties": { "text": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["text"] }
2511
2526
  },
2512
2527
  "fetchDataSourceDocument": {
@@ -2590,14 +2605,14 @@ var stepMetadata = {
2590
2605
  stepType: "generateImage",
2591
2606
  description: "Generate an image from a text prompt using an AI model.",
2592
2607
  usageNotes: "- Prompts should be descriptive but concise (roughly 3\u20136 sentences).\n- Images are automatically hosted on a CDN.\n- In foreground mode, the image is displayed to the user. In background mode, the URL is saved to a variable.\n- When generateVariants is true with numVariants > 1, multiple images are generated in parallel.\n- In direct execution, foreground mode behaves as background, and userSelect variant behavior behaves as saveAll.",
2593
- inputSchema: { "type": "object", "properties": { "prompt": { "type": "string", "description": "Text prompt describing the image to generate" }, "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "imageModelOverride": { "type": "object", "properties": { "model": { "type": "string", "description": "Image generation model identifier" }, "config": { "type": "object", "properties": {}, "required": [], "description": "Additional model-specific configuration" } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default image model if not specified" }, "generateVariants": { "type": "boolean", "description": "Whether to generate multiple image variants in parallel" }, "numVariants": { "type": "number", "description": "Number of variants to generate (max 10)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated image" } }, "required": ["prompt"] },
2608
+ inputSchema: { "type": "object", "properties": { "prompt": { "type": "string", "description": "Text prompt describing the image to generate" }, "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "imageModelOverride": { "type": "object", "properties": { "model": { "type": "string", "description": "Image generation model identifier" }, "config": { "type": "object", "properties": {}, "required": [], "description": "Additional model-specific configuration" } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default image model if not specified" }, "generateVariants": { "type": "boolean", "description": "Whether to generate multiple image variants in parallel" }, "numVariants": { "type": "number", "description": "Number of variants to generate (max 10)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated image.\n\nThe watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there." } }, "required": ["prompt"] },
2594
2609
  outputSchema: { "type": "object", "properties": { "imageUrl": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["imageUrl"] }
2595
2610
  },
2596
2611
  "generateLipsync": {
2597
2612
  stepType: "generateLipsync",
2598
2613
  description: "Generate a lip sync video from provided audio and image.",
2599
2614
  usageNotes: "- In foreground mode, the video is displayed to the user. In background mode, the URL is saved to a variable.",
2600
- inputSchema: { "type": "object", "properties": { "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated video" }, "lipsyncModelOverride": { "type": "object", "properties": { "model": { "type": "string" }, "config": { "type": "object", "properties": {}, "required": [] } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default lipsync model if not specified" } } },
2615
+ inputSchema: { "type": "object", "properties": { "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated video.\n\nThe watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there." }, "lipsyncModelOverride": { "type": "object", "properties": { "model": { "type": "string" }, "config": { "type": "object", "properties": {}, "required": [] } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default lipsync model if not specified" } } },
2601
2616
  outputSchema: { "description": "This step does not produce output data." }
2602
2617
  },
2603
2618
  "generateMusic": {
@@ -2643,7 +2658,7 @@ var stepMetadata = {
2643
2658
  stepType: "generateVideo",
2644
2659
  description: "Generate a video from a text prompt using an AI model.",
2645
2660
  usageNotes: "- Prompts should be descriptive but concise (roughly 3\u20136 sentences).\n- Videos are automatically hosted on a CDN.\n- In foreground mode, the video is displayed to the user. In background mode, the URL is saved to a variable.\n- When generateVariants is true with numVariants > 1, multiple videos are generated in parallel.\n- In direct execution, foreground mode behaves as background, and userSelect variant behavior behaves as saveAll.",
2646
- inputSchema: { "type": "object", "properties": { "prompt": { "type": "string", "description": "Text prompt describing the video to generate" }, "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "videoModelOverride": { "type": "object", "properties": { "model": { "type": "string", "description": "Video generation model identifier" }, "config": { "type": "object", "properties": {}, "required": [], "description": "Additional model-specific configuration" } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default video model if not specified" }, "generateVariants": { "type": "boolean", "description": "Whether to generate multiple video variants in parallel" }, "numVariants": { "type": "number", "description": "Number of variants to generate (max 10)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated video" } }, "required": ["prompt"] },
2661
+ inputSchema: { "type": "object", "properties": { "prompt": { "type": "string", "description": "Text prompt describing the video to generate" }, "intermediateAsset": { "type": "boolean", "description": "When true, the asset is created but hidden from the user's gallery (tagged as intermediate)" }, "videoModelOverride": { "type": "object", "properties": { "model": { "type": "string", "description": "Video generation model identifier" }, "config": { "type": "object", "properties": {}, "required": [], "description": "Additional model-specific configuration" } }, "required": ["model"], "description": "Optional model configuration override. Uses the workflow's default video model if not specified" }, "generateVariants": { "type": "boolean", "description": "Whether to generate multiple video variants in parallel" }, "numVariants": { "type": "number", "description": "Number of variants to generate (max 10)" }, "addWatermark": { "type": "boolean", "description": "Whether to add a MindStudio watermark to the generated video.\n\nThe watermark is a product mark on assets generated in the MindStudio UI. A step run directly via the SDK or API is producing the app's own asset, so it is never watermarked and this flag has no effect there." } }, "required": ["prompt"] },
2647
2662
  outputSchema: { "type": "object", "properties": { "videoUrl": { "anyOf": [{ "type": "string" }, { "type": "array", "items": { "type": "string" } }] } }, "required": ["videoUrl"] }
2648
2663
  },
2649
2664
  "getGmailAttachments": {
@@ -4349,7 +4364,10 @@ var MindStudioAgent = class {
4349
4364
  ...options?.appId != null && { appId: options.appId },
4350
4365
  ...threadId != null && { threadId },
4351
4366
  ...this._currentStreamId != null && { streamId: this._currentStreamId },
4352
- ...this._requestSource != null && { requestSource: this._requestSource }
4367
+ ...this._requestSource != null && {
4368
+ requestSource: this._requestSource
4369
+ },
4370
+ ...assetStoreBody(options?.store)
4353
4371
  });
4354
4372
  const remaining = headers.get("x-ratelimit-remaining");
4355
4373
  const returnedThreadId = asyncData.threadId ?? "";
@@ -4433,7 +4451,10 @@ var MindStudioAgent = class {
4433
4451
  ...options.appId != null && { appId: options.appId },
4434
4452
  ...threadId != null && { threadId },
4435
4453
  ...this._currentStreamId != null && { streamId: this._currentStreamId },
4436
- ...this._requestSource != null && { requestSource: this._requestSource }
4454
+ ...this._requestSource != null && {
4455
+ requestSource: this._requestSource
4456
+ },
4457
+ ...assetStoreBody(options.store)
4437
4458
  };
4438
4459
  await this._httpConfig.rateLimiter.acquire();
4439
4460
  let res;
@@ -4620,7 +4641,10 @@ var MindStudioAgent = class {
4620
4641
  })),
4621
4642
  ...options?.appId != null && { appId: options.appId },
4622
4643
  ...threadId != null && { threadId },
4623
- ...this._requestSource != null && { requestSource: this._requestSource }
4644
+ ...this._requestSource != null && {
4645
+ requestSource: this._requestSource
4646
+ },
4647
+ ...assetStoreBody(options?.store)
4624
4648
  });
4625
4649
  const pollUrl = `${this._currentHttpConfig.baseUrl}/developer/v2/steps/execute-batch-async/poll/${asyncData.batchToken}`;
4626
4650
  let pollDelay = 300;
@@ -5235,6 +5259,13 @@ var MindStudioAgent = class {
5235
5259
  if (!(err instanceof DbWsTransportError)) {
5236
5260
  throw err;
5237
5261
  }
5262
+ if (err.sent && queries.some((q) => !isReadOnlySql(q.sql))) {
5263
+ throw new MindStudioError(
5264
+ "[db] Connection was interrupted after this query was sent; because it contains a write, it was not automatically retried (the write may or may not have been applied). Verify the current state before re-running it.",
5265
+ "db_transport_interrupted",
5266
+ 503
5267
+ );
5268
+ }
5238
5269
  console.warn(
5239
5270
  `[mindstudio] db: WebSocket transport unavailable (${err.message}); using HTTP for this query.`
5240
5271
  );
@@ -5625,7 +5656,10 @@ var MindStudioAgent = class {
5625
5656
  content.byteOffset,
5626
5657
  content.byteOffset + content.byteLength
5627
5658
  );
5628
- const fileBlob = new Blob([buf], options.type ? { type: options.type } : void 0);
5659
+ const fileBlob = new Blob(
5660
+ [buf],
5661
+ options.type ? { type: options.type } : void 0
5662
+ );
5629
5663
  form.append("file", fileBlob, filename);
5630
5664
  const res = await fetch(data.url, { method: "POST", body: form });
5631
5665
  if (!res.ok) {
@@ -5651,6 +5685,9 @@ function sleep3(ms) {
5651
5685
  return new Promise((resolve) => setTimeout(resolve, ms));
5652
5686
  }
5653
5687
  applyStepMethods(MindStudioAgent);
5688
+ function assetStoreBody(store) {
5689
+ return store ? { assetStore: { store: store.name, access: store.access } } : {};
5690
+ }
5654
5691
  function resolveStepType2(name) {
5655
5692
  const meta = stepMetadata[name];
5656
5693
  return meta ? meta.stepType : name;