@makemind/sdk 0.1.0 → 0.2.1

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.js CHANGED
@@ -101,6 +101,8 @@ var ErrorCodes = {
101
101
  NOT_FOUND: "NOT_FOUND",
102
102
  ALREADY_EXISTS: "ALREADY_EXISTS",
103
103
  VALIDATION_ERROR: "VALIDATION_ERROR",
104
+ /** No refresh credential on this client; the session is intact but cannot be refreshed here. */
105
+ AUTH_REFRESH_UNAVAILABLE: "AUTH_REFRESH_UNAVAILABLE",
104
106
  // Tenant errors
105
107
  TENANT_NOT_FOUND: "TENANT_NOT_FOUND",
106
108
  TENANT_SUSPENDED: "TENANT_SUSPENDED",
@@ -265,30 +267,17 @@ var MAKEMINDAuth = class {
265
267
  async signInWithEmailAndPassword(email, password) {
266
268
  return this.signInWithEmail(email, password);
267
269
  }
268
- async signUp(email, password, options) {
269
- try {
270
- const response = await this.apiClient.post("/auth/signup", {
271
- email,
272
- password,
273
- displayName: options?.displayName,
274
- phoneNumber: options?.phoneNumber,
275
- applicationId: this.applicationId
276
- }, { skipAuth: true });
277
- this._currentUser = response.user;
278
- this.refreshToken = response.refreshToken ?? null;
279
- this._memberships = response.memberships || [];
280
- this.setAuthToken(response.token);
281
- this.persistSession(response.user, response.token, response.refreshToken, response.memberships);
282
- this.onAuthStateChange(response.user);
283
- this.notifyAuthStateCallbacks(response.user);
284
- return response.user;
285
- } catch (error) {
286
- if (error instanceof MAKEMINDError) {
287
- throw error;
288
- }
289
- throw new MAKEMINDError("AUTH_ERROR", "Failed to sign up");
290
- }
291
- }
270
+ /*
271
+ * `signUp` stood here. The platform registers nobody from this surface
272
+ * (2026-09-17): `/auth/signup` was removed and answers 404, so the method
273
+ * could only ever fail. A published client that offers an operation the
274
+ * server does not have is a lie the caller finds at runtime; it is removed
275
+ * rather than left to throw.
276
+ *
277
+ * Where accounts come from now: a platform account exists once its person
278
+ * signs in at the tenant portal; a tenant's own end users register in that
279
+ * tenant's pool (`endusers-selfRegisterEndUser`).
280
+ */
292
281
  async signOut() {
293
282
  try {
294
283
  await this.apiClient.post("/auth/signout", {});
@@ -303,12 +292,12 @@ var MAKEMINDAuth = class {
303
292
  this.notifyAuthStateCallbacks(null);
304
293
  }
305
294
  }
306
- async sendPasswordResetEmail(email) {
307
- await this.apiClient.post("/auth/password/reset", {
308
- email,
309
- applicationId: this.applicationId
310
- }, { skipAuth: true });
311
- }
295
+ /*
296
+ * `sendPasswordResetEmail` stood here, with `confirmPasswordReset` and
297
+ * `verifyEmail` below. All three routes were removed with the sign-up they
298
+ * belonged to: the reset ended at an email this platform could not send,
299
+ * while the API answered that a link had been sent.
300
+ */
312
301
  onAuthStateChanged(callback) {
313
302
  this.authStateCallbacks.add(callback);
314
303
  callback(this._currentUser);
@@ -344,7 +333,13 @@ var MAKEMINDAuth = class {
344
333
  } else if (this._currentUser) {
345
334
  this.persistSession(this._currentUser, response.token, response.refreshToken, response.memberships);
346
335
  }
347
- } catch {
336
+ } catch (error) {
337
+ if (error instanceof MAKEMINDError && error.code === ErrorCodes.VALIDATION_ERROR) {
338
+ throw new MAKEMINDError(
339
+ ErrorCodes.AUTH_REFRESH_UNAVAILABLE,
340
+ "This client holds no refresh credential; sign in again to pick up new claims"
341
+ );
342
+ }
348
343
  await this.signOut();
349
344
  throw new MAKEMINDError("UNAUTHENTICATED", "Session expired");
350
345
  }
@@ -426,25 +421,6 @@ var MAKEMINDAuth = class {
426
421
  }
427
422
  await this.apiClient.dispatch("resendVerificationEmail");
428
423
  }
429
- /**
430
- * Verify email with code
431
- */
432
- async verifyEmail(code) {
433
- await this.apiClient.post("/auth/verify-email", {
434
- code,
435
- applicationId: this.applicationId
436
- }, { skipAuth: true });
437
- }
438
- /**
439
- * Confirm password reset with code
440
- */
441
- async confirmPasswordReset(code, newPassword) {
442
- await this.apiClient.post("/auth/confirm-reset", {
443
- code,
444
- newPassword,
445
- applicationId: this.applicationId
446
- }, { skipAuth: true });
447
- }
448
424
  /**
449
425
  * OAuth redirect-based sign-in is NOT supported by this backend.
450
426
  * The backend has no /oauth/initiate or /oauth/callback routes.
@@ -601,31 +577,49 @@ var MAKEMINDData = class {
601
577
  metadata: { hasMore: res.hasMore ?? false, lastDocId: res.nextCursor }
602
578
  };
603
579
  }
580
+ /*
581
+ * Every method on this service addresses the document platform — the store
582
+ * `query`, the batch methods, `aggregate` and `search` already read. The
583
+ * single-document methods used to go through the REST data door, which
584
+ * keeps a separate tree with a fixed set of collection names: a document
585
+ * created there was invisible to `query` and refused by `batchDelete`, and
586
+ * a collection of the tenant's own naming was refused at the door. One
587
+ * object, one store.
588
+ */
604
589
  async get(options) {
605
590
  try {
606
- const response = await this.apiClient.get(
607
- `/data/${options.collection}/${options.documentId}`
608
- );
609
- return response;
591
+ const doc = await this.apiClient.dispatch("dataGetDocument", {
592
+ id: options.documentId
593
+ });
594
+ return { id: doc.id ?? options.documentId, data: doc.data };
610
595
  } catch (error) {
611
- if (error instanceof MAKEMINDError && error.code === "NOT_FOUND") {
596
+ if (error instanceof MAKEMINDError && (error.code === "NOT_FOUND" || error.code === "DATA_NOT_FOUND")) {
612
597
  return null;
613
598
  }
614
599
  throw error;
615
600
  }
616
601
  }
617
602
  async create(options) {
618
- const response = await this.apiClient.post(`/data/${options.collection}`, {
619
- ...options.data,
620
- documentId: options.documentId
621
- });
622
- return response;
603
+ const created = await this.apiClient.dispatch(
604
+ "dataCreateDocument",
605
+ {
606
+ collection: options.collection,
607
+ data: options.data,
608
+ id: options.documentId
609
+ }
610
+ );
611
+ return { id: created.id, data: options.data };
623
612
  }
624
613
  async update(options) {
625
- await this.apiClient.patch(`/data/${options.collection}/${options.documentId}`, options.data);
614
+ await this.apiClient.dispatch("dataUpdateDocument", {
615
+ id: options.documentId,
616
+ data: options.data
617
+ });
626
618
  }
627
619
  async delete(options) {
628
- await this.apiClient.delete(`/data/${options.collection}/${options.documentId}`);
620
+ await this.apiClient.dispatch("dataDeleteDocument", {
621
+ id: options.documentId
622
+ });
629
623
  }
630
624
  onSnapshot(options, callback) {
631
625
  const subscriptionId = `doc:${options.collection}:${options.documentId}`;
@@ -743,11 +737,33 @@ var MAKEMINDData = class {
743
737
  ...documentId ? { id: documentId } : {},
744
738
  data
745
739
  }));
740
+ const results = await this.batchWrite(operations);
741
+ return results.map((r) => ({ id: r.id, data: {} }));
742
+ }
743
+ /**
744
+ * Send a batch and refuse to report a partial one as whole.
745
+ *
746
+ * The backend answers per item: an item it would not perform comes back
747
+ * `status: 'denied'` with the reason (`DATA_ALREADY_EXISTS` for a create over
748
+ * an id that exists, `DATA_WRITE_ONCE_VIOLATION`, `AUTH_ACCESS_DENIED`) while
749
+ * the others commit. Reading only the ids told the caller every item was
750
+ * written. A denied item now raises `BATCH_PARTIALLY_DENIED`, and the error
751
+ * carries every item's result so the caller can see which ones did commit.
752
+ */
753
+ async batchWrite(operations) {
746
754
  const response = await this.apiClient.dispatch(
747
755
  "dataBatchWrite",
748
756
  { operations }
749
757
  );
750
- return response.results.map((r) => ({ id: r.id, data: {} }));
758
+ const denied = response.results.filter((r) => r.status === "denied");
759
+ if (denied.length > 0) {
760
+ throw new MAKEMINDError(
761
+ "BATCH_PARTIALLY_DENIED",
762
+ `${denied.length} of ${response.results.length} batch operations were refused: ` + denied.map((r) => `${r.id} (${r.error ?? "denied"})`).join(", "),
763
+ { results: response.results, denied }
764
+ );
765
+ }
766
+ return response.results;
751
767
  }
752
768
  async batchUpdate(collection, updates) {
753
769
  const operations = updates.map(({ documentId, data }) => ({
@@ -755,14 +771,14 @@ var MAKEMINDData = class {
755
771
  id: documentId,
756
772
  data
757
773
  }));
758
- await this.apiClient.dispatch("dataBatchWrite", { operations });
774
+ await this.batchWrite(operations);
759
775
  }
760
776
  async batchDelete(collection, documentIds) {
761
777
  const operations = documentIds.map((id) => ({
762
778
  type: "delete",
763
779
  id
764
780
  }));
765
- await this.apiClient.dispatch("dataBatchWrite", { operations });
781
+ await this.batchWrite(operations);
766
782
  }
767
783
  // Export/Import operations
768
784
  //
@@ -2835,12 +2851,12 @@ var MAKEMINDAI = class {
2835
2851
  }
2836
2852
  /**
2837
2853
  * Document analysis (summary, field extraction, or QA).
2838
- * No dedicated onCall exists in the ai domain; implemented via ai-aiChat
2839
- * with a structured system prompt that targets the requested analysis type.
2840
- * The document content must be fetched by the caller and passed as text —
2841
- * the backend has no URL-fetch / OCR pipeline for onCall yet.
2854
+ * The document itself is sent — a PDF as a `document` part, which the
2855
+ * platform hands only to a model that reads PDFs (core-ai 18 §5.2). `document`
2856
+ * is an https address the platform reads, or a `data:application/pdf;base64,…`
2857
+ * URI.
2842
2858
  */
2843
- async analyzeDocument(documentUrl, analysisType, options) {
2859
+ async analyzeDocument(document2, analysisType, options) {
2844
2860
  const systemPromptMap = {
2845
2861
  summary: "You are a document summarization assistant. Summarize the provided document concisely.",
2846
2862
  extract: `You are a document extraction assistant. Extract the following fields from the document as JSON: ${(options?.extractFields ?? []).join(", ")}.`,
@@ -2848,9 +2864,10 @@ var MAKEMINDAI = class {
2848
2864
  };
2849
2865
  const response = await this.apiClient.dispatch("ai-aiChat", {
2850
2866
  tenantId: this.getTenantId(),
2867
+ ...options?.model ? { model: options.model } : {},
2851
2868
  messages: [
2852
2869
  { role: "system", content: systemPromptMap[analysisType] },
2853
- { role: "user", content: `Document URL: ${documentUrl}` }
2870
+ { role: "user", content: [{ type: "document", document: { url: document2 } }] }
2854
2871
  ]
2855
2872
  });
2856
2873
  let result = response.content;
@@ -2866,6 +2883,20 @@ var MAKEMINDAI = class {
2866
2883
  usage: { totalTokens: response.usage.totalTokens }
2867
2884
  };
2868
2885
  }
2886
+ /**
2887
+ * A document's text as written, page by page and line by line, from an OCR
2888
+ * engine — each line with its confidence and its box on the page (core-ai 18
2889
+ * §5.3). One call reads at most 30 pages; read the next window while `more`.
2890
+ * `document` is an https address or a data URI (PDF, PNG, JPEG, TIFF).
2891
+ */
2892
+ async ocr(document2, options) {
2893
+ return this.apiClient.dispatch("ai-aiOcr", {
2894
+ tenantId: this.getTenantId(),
2895
+ document: { url: document2, ...options?.mediaType ? { mediaType: options.mediaType } : {} },
2896
+ ...options?.pages ? { pages: options.pages } : {},
2897
+ ...options?.model ? { model: options.model } : {}
2898
+ });
2899
+ }
2869
2900
  // Text generation
2870
2901
  async generate(prompt, options) {
2871
2902
  const response = await this.chat(
@@ -3081,8 +3112,12 @@ var MAKEMINDApps = class {
3081
3112
  // ============================================
3082
3113
  // Publishing & Versioning
3083
3114
  // ============================================
3084
- async publish(appId, changelog) {
3085
- const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog });
3115
+ /**
3116
+ * Cut a version and publish it — to everyone, or with `rolloutPercent`
3117
+ * (1–99) to that share of visitors beside the published version.
3118
+ */
3119
+ async publish(appId, changelog, options = {}) {
3120
+ const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog, ...options });
3086
3121
  return response;
3087
3122
  }
3088
3123
  async unpublish(appId) {
@@ -3281,16 +3316,20 @@ var MAKEMINDApps = class {
3281
3316
  // ============================================
3282
3317
  // AI Features
3283
3318
  // ============================================
3319
+ /** A widget subtree in DSL from a description (app builder DDD 08 §9). */
3284
3320
  async generateUI(prompt, context, appId) {
3285
3321
  const response = await this.apiClient.post(
3286
3322
  "/apps/ai/generate-ui",
3287
3323
  { prompt, context, appId }
3288
3324
  );
3289
- return { components: response.components };
3325
+ return { content: response.content };
3290
3326
  }
3291
- async suggestActions(appId, componentType, context) {
3292
- const response = await this.apiClient.post(`/apps/${appId}/ai/suggest-actions`, { componentType, context });
3293
- return { actions: response.suggestions };
3327
+ /** DSL actions a widget could run, from the tools the app's origin offers. */
3328
+ async suggestActions(appId, widgetType) {
3329
+ return this.apiClient.post(
3330
+ `/apps/${appId}/ai/suggest-actions`,
3331
+ { widgetType }
3332
+ );
3294
3333
  }
3295
3334
  // ============================================
3296
3335
  // Collaboration
package/dist/index.mjs CHANGED
@@ -45,6 +45,8 @@ var ErrorCodes = {
45
45
  NOT_FOUND: "NOT_FOUND",
46
46
  ALREADY_EXISTS: "ALREADY_EXISTS",
47
47
  VALIDATION_ERROR: "VALIDATION_ERROR",
48
+ /** No refresh credential on this client; the session is intact but cannot be refreshed here. */
49
+ AUTH_REFRESH_UNAVAILABLE: "AUTH_REFRESH_UNAVAILABLE",
48
50
  // Tenant errors
49
51
  TENANT_NOT_FOUND: "TENANT_NOT_FOUND",
50
52
  TENANT_SUSPENDED: "TENANT_SUSPENDED",
@@ -209,30 +211,17 @@ var MAKEMINDAuth = class {
209
211
  async signInWithEmailAndPassword(email, password) {
210
212
  return this.signInWithEmail(email, password);
211
213
  }
212
- async signUp(email, password, options) {
213
- try {
214
- const response = await this.apiClient.post("/auth/signup", {
215
- email,
216
- password,
217
- displayName: options?.displayName,
218
- phoneNumber: options?.phoneNumber,
219
- applicationId: this.applicationId
220
- }, { skipAuth: true });
221
- this._currentUser = response.user;
222
- this.refreshToken = response.refreshToken ?? null;
223
- this._memberships = response.memberships || [];
224
- this.setAuthToken(response.token);
225
- this.persistSession(response.user, response.token, response.refreshToken, response.memberships);
226
- this.onAuthStateChange(response.user);
227
- this.notifyAuthStateCallbacks(response.user);
228
- return response.user;
229
- } catch (error) {
230
- if (error instanceof MAKEMINDError) {
231
- throw error;
232
- }
233
- throw new MAKEMINDError("AUTH_ERROR", "Failed to sign up");
234
- }
235
- }
214
+ /*
215
+ * `signUp` stood here. The platform registers nobody from this surface
216
+ * (2026-09-17): `/auth/signup` was removed and answers 404, so the method
217
+ * could only ever fail. A published client that offers an operation the
218
+ * server does not have is a lie the caller finds at runtime; it is removed
219
+ * rather than left to throw.
220
+ *
221
+ * Where accounts come from now: a platform account exists once its person
222
+ * signs in at the tenant portal; a tenant's own end users register in that
223
+ * tenant's pool (`endusers-selfRegisterEndUser`).
224
+ */
236
225
  async signOut() {
237
226
  try {
238
227
  await this.apiClient.post("/auth/signout", {});
@@ -247,12 +236,12 @@ var MAKEMINDAuth = class {
247
236
  this.notifyAuthStateCallbacks(null);
248
237
  }
249
238
  }
250
- async sendPasswordResetEmail(email) {
251
- await this.apiClient.post("/auth/password/reset", {
252
- email,
253
- applicationId: this.applicationId
254
- }, { skipAuth: true });
255
- }
239
+ /*
240
+ * `sendPasswordResetEmail` stood here, with `confirmPasswordReset` and
241
+ * `verifyEmail` below. All three routes were removed with the sign-up they
242
+ * belonged to: the reset ended at an email this platform could not send,
243
+ * while the API answered that a link had been sent.
244
+ */
256
245
  onAuthStateChanged(callback) {
257
246
  this.authStateCallbacks.add(callback);
258
247
  callback(this._currentUser);
@@ -288,7 +277,13 @@ var MAKEMINDAuth = class {
288
277
  } else if (this._currentUser) {
289
278
  this.persistSession(this._currentUser, response.token, response.refreshToken, response.memberships);
290
279
  }
291
- } catch {
280
+ } catch (error) {
281
+ if (error instanceof MAKEMINDError && error.code === ErrorCodes.VALIDATION_ERROR) {
282
+ throw new MAKEMINDError(
283
+ ErrorCodes.AUTH_REFRESH_UNAVAILABLE,
284
+ "This client holds no refresh credential; sign in again to pick up new claims"
285
+ );
286
+ }
292
287
  await this.signOut();
293
288
  throw new MAKEMINDError("UNAUTHENTICATED", "Session expired");
294
289
  }
@@ -370,25 +365,6 @@ var MAKEMINDAuth = class {
370
365
  }
371
366
  await this.apiClient.dispatch("resendVerificationEmail");
372
367
  }
373
- /**
374
- * Verify email with code
375
- */
376
- async verifyEmail(code) {
377
- await this.apiClient.post("/auth/verify-email", {
378
- code,
379
- applicationId: this.applicationId
380
- }, { skipAuth: true });
381
- }
382
- /**
383
- * Confirm password reset with code
384
- */
385
- async confirmPasswordReset(code, newPassword) {
386
- await this.apiClient.post("/auth/confirm-reset", {
387
- code,
388
- newPassword,
389
- applicationId: this.applicationId
390
- }, { skipAuth: true });
391
- }
392
368
  /**
393
369
  * OAuth redirect-based sign-in is NOT supported by this backend.
394
370
  * The backend has no /oauth/initiate or /oauth/callback routes.
@@ -545,31 +521,49 @@ var MAKEMINDData = class {
545
521
  metadata: { hasMore: res.hasMore ?? false, lastDocId: res.nextCursor }
546
522
  };
547
523
  }
524
+ /*
525
+ * Every method on this service addresses the document platform — the store
526
+ * `query`, the batch methods, `aggregate` and `search` already read. The
527
+ * single-document methods used to go through the REST data door, which
528
+ * keeps a separate tree with a fixed set of collection names: a document
529
+ * created there was invisible to `query` and refused by `batchDelete`, and
530
+ * a collection of the tenant's own naming was refused at the door. One
531
+ * object, one store.
532
+ */
548
533
  async get(options) {
549
534
  try {
550
- const response = await this.apiClient.get(
551
- `/data/${options.collection}/${options.documentId}`
552
- );
553
- return response;
535
+ const doc = await this.apiClient.dispatch("dataGetDocument", {
536
+ id: options.documentId
537
+ });
538
+ return { id: doc.id ?? options.documentId, data: doc.data };
554
539
  } catch (error) {
555
- if (error instanceof MAKEMINDError && error.code === "NOT_FOUND") {
540
+ if (error instanceof MAKEMINDError && (error.code === "NOT_FOUND" || error.code === "DATA_NOT_FOUND")) {
556
541
  return null;
557
542
  }
558
543
  throw error;
559
544
  }
560
545
  }
561
546
  async create(options) {
562
- const response = await this.apiClient.post(`/data/${options.collection}`, {
563
- ...options.data,
564
- documentId: options.documentId
565
- });
566
- return response;
547
+ const created = await this.apiClient.dispatch(
548
+ "dataCreateDocument",
549
+ {
550
+ collection: options.collection,
551
+ data: options.data,
552
+ id: options.documentId
553
+ }
554
+ );
555
+ return { id: created.id, data: options.data };
567
556
  }
568
557
  async update(options) {
569
- await this.apiClient.patch(`/data/${options.collection}/${options.documentId}`, options.data);
558
+ await this.apiClient.dispatch("dataUpdateDocument", {
559
+ id: options.documentId,
560
+ data: options.data
561
+ });
570
562
  }
571
563
  async delete(options) {
572
- await this.apiClient.delete(`/data/${options.collection}/${options.documentId}`);
564
+ await this.apiClient.dispatch("dataDeleteDocument", {
565
+ id: options.documentId
566
+ });
573
567
  }
574
568
  onSnapshot(options, callback) {
575
569
  const subscriptionId = `doc:${options.collection}:${options.documentId}`;
@@ -687,11 +681,33 @@ var MAKEMINDData = class {
687
681
  ...documentId ? { id: documentId } : {},
688
682
  data
689
683
  }));
684
+ const results = await this.batchWrite(operations);
685
+ return results.map((r) => ({ id: r.id, data: {} }));
686
+ }
687
+ /**
688
+ * Send a batch and refuse to report a partial one as whole.
689
+ *
690
+ * The backend answers per item: an item it would not perform comes back
691
+ * `status: 'denied'` with the reason (`DATA_ALREADY_EXISTS` for a create over
692
+ * an id that exists, `DATA_WRITE_ONCE_VIOLATION`, `AUTH_ACCESS_DENIED`) while
693
+ * the others commit. Reading only the ids told the caller every item was
694
+ * written. A denied item now raises `BATCH_PARTIALLY_DENIED`, and the error
695
+ * carries every item's result so the caller can see which ones did commit.
696
+ */
697
+ async batchWrite(operations) {
690
698
  const response = await this.apiClient.dispatch(
691
699
  "dataBatchWrite",
692
700
  { operations }
693
701
  );
694
- return response.results.map((r) => ({ id: r.id, data: {} }));
702
+ const denied = response.results.filter((r) => r.status === "denied");
703
+ if (denied.length > 0) {
704
+ throw new MAKEMINDError(
705
+ "BATCH_PARTIALLY_DENIED",
706
+ `${denied.length} of ${response.results.length} batch operations were refused: ` + denied.map((r) => `${r.id} (${r.error ?? "denied"})`).join(", "),
707
+ { results: response.results, denied }
708
+ );
709
+ }
710
+ return response.results;
695
711
  }
696
712
  async batchUpdate(collection, updates) {
697
713
  const operations = updates.map(({ documentId, data }) => ({
@@ -699,14 +715,14 @@ var MAKEMINDData = class {
699
715
  id: documentId,
700
716
  data
701
717
  }));
702
- await this.apiClient.dispatch("dataBatchWrite", { operations });
718
+ await this.batchWrite(operations);
703
719
  }
704
720
  async batchDelete(collection, documentIds) {
705
721
  const operations = documentIds.map((id) => ({
706
722
  type: "delete",
707
723
  id
708
724
  }));
709
- await this.apiClient.dispatch("dataBatchWrite", { operations });
725
+ await this.batchWrite(operations);
710
726
  }
711
727
  // Export/Import operations
712
728
  //
@@ -2779,12 +2795,12 @@ var MAKEMINDAI = class {
2779
2795
  }
2780
2796
  /**
2781
2797
  * Document analysis (summary, field extraction, or QA).
2782
- * No dedicated onCall exists in the ai domain; implemented via ai-aiChat
2783
- * with a structured system prompt that targets the requested analysis type.
2784
- * The document content must be fetched by the caller and passed as text —
2785
- * the backend has no URL-fetch / OCR pipeline for onCall yet.
2798
+ * The document itself is sent — a PDF as a `document` part, which the
2799
+ * platform hands only to a model that reads PDFs (core-ai 18 §5.2). `document`
2800
+ * is an https address the platform reads, or a `data:application/pdf;base64,…`
2801
+ * URI.
2786
2802
  */
2787
- async analyzeDocument(documentUrl, analysisType, options) {
2803
+ async analyzeDocument(document2, analysisType, options) {
2788
2804
  const systemPromptMap = {
2789
2805
  summary: "You are a document summarization assistant. Summarize the provided document concisely.",
2790
2806
  extract: `You are a document extraction assistant. Extract the following fields from the document as JSON: ${(options?.extractFields ?? []).join(", ")}.`,
@@ -2792,9 +2808,10 @@ var MAKEMINDAI = class {
2792
2808
  };
2793
2809
  const response = await this.apiClient.dispatch("ai-aiChat", {
2794
2810
  tenantId: this.getTenantId(),
2811
+ ...options?.model ? { model: options.model } : {},
2795
2812
  messages: [
2796
2813
  { role: "system", content: systemPromptMap[analysisType] },
2797
- { role: "user", content: `Document URL: ${documentUrl}` }
2814
+ { role: "user", content: [{ type: "document", document: { url: document2 } }] }
2798
2815
  ]
2799
2816
  });
2800
2817
  let result = response.content;
@@ -2810,6 +2827,20 @@ var MAKEMINDAI = class {
2810
2827
  usage: { totalTokens: response.usage.totalTokens }
2811
2828
  };
2812
2829
  }
2830
+ /**
2831
+ * A document's text as written, page by page and line by line, from an OCR
2832
+ * engine — each line with its confidence and its box on the page (core-ai 18
2833
+ * §5.3). One call reads at most 30 pages; read the next window while `more`.
2834
+ * `document` is an https address or a data URI (PDF, PNG, JPEG, TIFF).
2835
+ */
2836
+ async ocr(document2, options) {
2837
+ return this.apiClient.dispatch("ai-aiOcr", {
2838
+ tenantId: this.getTenantId(),
2839
+ document: { url: document2, ...options?.mediaType ? { mediaType: options.mediaType } : {} },
2840
+ ...options?.pages ? { pages: options.pages } : {},
2841
+ ...options?.model ? { model: options.model } : {}
2842
+ });
2843
+ }
2813
2844
  // Text generation
2814
2845
  async generate(prompt, options) {
2815
2846
  const response = await this.chat(
@@ -3025,8 +3056,12 @@ var MAKEMINDApps = class {
3025
3056
  // ============================================
3026
3057
  // Publishing & Versioning
3027
3058
  // ============================================
3028
- async publish(appId, changelog) {
3029
- const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog });
3059
+ /**
3060
+ * Cut a version and publish it — to everyone, or with `rolloutPercent`
3061
+ * (1–99) to that share of visitors beside the published version.
3062
+ */
3063
+ async publish(appId, changelog, options = {}) {
3064
+ const response = await this.apiClient.post(`/apps/${appId}/publish`, { changelog, ...options });
3030
3065
  return response;
3031
3066
  }
3032
3067
  async unpublish(appId) {
@@ -3225,16 +3260,20 @@ var MAKEMINDApps = class {
3225
3260
  // ============================================
3226
3261
  // AI Features
3227
3262
  // ============================================
3263
+ /** A widget subtree in DSL from a description (app builder DDD 08 §9). */
3228
3264
  async generateUI(prompt, context, appId) {
3229
3265
  const response = await this.apiClient.post(
3230
3266
  "/apps/ai/generate-ui",
3231
3267
  { prompt, context, appId }
3232
3268
  );
3233
- return { components: response.components };
3269
+ return { content: response.content };
3234
3270
  }
3235
- async suggestActions(appId, componentType, context) {
3236
- const response = await this.apiClient.post(`/apps/${appId}/ai/suggest-actions`, { componentType, context });
3237
- return { actions: response.suggestions };
3271
+ /** DSL actions a widget could run, from the tools the app's origin offers. */
3272
+ async suggestActions(appId, widgetType) {
3273
+ return this.apiClient.post(
3274
+ `/apps/${appId}/ai/suggest-actions`,
3275
+ { widgetType }
3276
+ );
3238
3277
  }
3239
3278
  // ============================================
3240
3279
  // Collaboration
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makemind/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "MAKEMIND Platform SDK for Web Applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -34,15 +34,17 @@
34
34
  "firebase": "^10.14.1"
35
35
  },
36
36
  "devDependencies": {
37
+ "@makemind/app-builder-ui": "file:../app-builder-ui",
37
38
  "@types/jsdom": "^30.0.0",
38
39
  "@types/node": "^20.10.0",
40
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
41
+ "@typescript-eslint/parser": "^7.18.0",
39
42
  "eslint": "^8.55.0",
40
43
  "firebase": "^10.7.0",
41
44
  "jsdom": "^30.0.1",
42
45
  "tsup": "^8.0.1",
43
46
  "typescript": "^5.3.0",
44
- "vitest": "^1.0.0",
45
- "@makemind/app-builder-ui": "file:../app-builder-ui"
47
+ "vitest": "^1.0.0"
46
48
  },
47
49
  "keywords": [
48
50
  "makemind",