mindoodb-app-sdk 0.0.71 → 0.0.72

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
@@ -525,9 +525,12 @@ only database. The launch context then carries `embed` (`docId`, `databaseId`,
525
525
  `intent`, `hostAppLabel`): open that document, hide "New"/"Open", and finish with
526
526
 
527
527
  ```ts
528
- await session.embedding.complete({ title }); // or session.embedding.cancel()
528
+ await session.embedding.complete({ subject, summary, stats: { words } }); // or session.embedding.cancel()
529
529
  ```
530
530
 
531
+ `complete` takes plain JSON; `MindooDBAppEmbeddingResult` (`subject`, optional
532
+ `summary`, `thumbnail` as a small data URL, `stats`) is the shape hosts expect.
533
+
531
534
  Haven writes every change back to the host's database as it happens and only lets the
532
535
  component create documents that are children of the root.
533
536
 
@@ -628,6 +631,72 @@ never does is closed without asking; `embed.onDirtyChange` lets the host mark it
628
631
  dot in its tab). `embed.save()` rejects with `unsupported` when the component has no save
629
632
  handler.
630
633
 
634
+ **Checking before saving.** A component can tell hosts more about itself in
635
+ `supports`, and hosts filter on it:
636
+
637
+ ```json
638
+ "supports": ["inspect:mindoo.inspect.document@1", "validate", "issues", "reveal"]
639
+ ```
640
+
641
+ ```ts
642
+ const [letterEditor] = await session.components.list({ requires: ["inspect:mindoo.inspect.document@1", "validate"] });
643
+ ```
644
+
645
+ - `inspect:<contract>`: the component describes its document in a shared shape:
646
+ `mindoo.inspect.document@1` (Word/Markdown: subject, outline with anchors, open
647
+ placeholders and MERGEFIELDs, open comments and tracked changes, word count, text on
648
+ request), `mindoo.inspect.spreadsheet@1` (sheets, named ranges, requested cells,
649
+ formula errors with address), `mindoo.inspect.slides@1` (slide count, titles, empty
650
+ placeholders). Anchors: `{ kind: "heading", id }`, `{ kind: "cell", ref: "Sheet1!B3" }`,
651
+ `{ kind: "slide", index }`.
652
+ - `validate`: it asks before it saves, so the host can stop a save.
653
+ - `issues` / `reveal`: it shows a host's findings and scrolls to an anchor.
654
+
655
+ Changing `supports` does not ask users again; it grants no access.
656
+
657
+ ```ts
658
+ // host
659
+ const letter = await embed.inspect<MindooDBAppDocumentInspection>(); // { outline, placeholders, … }
660
+ const rules = defineDocumentRules<MindooDBAppDocumentInspection>({
661
+ contract: MINDOODB_INSPECT_DOCUMENT,
662
+ rules: [mindooDBAppInspectRules.noOpenPlaceholders(), mindooDBAppInspectRules.noOpenTrackedChanges("warning")],
663
+ });
664
+ rules.attach(embed); // = embed.onBeforeSave(rules.beforeSave, { inspect: rules.request })
665
+ embed.onAfterSave(() => refreshTree());
666
+ await embed.showIssues(rules.checkRoot(doc.data)); // the root summary, see below
667
+ await embed.reveal({ kind: "heading", id: "h-3" });
668
+ await embed.callTool("text_insert", { text: "…" }); // any of its document agent tools
669
+
670
+ // component
671
+ session.embedding.provideInspection((request) => describeDocument(request));
672
+ session.embedding.onShowIssues((issues) => showIssuesPanel(issues));
673
+ session.embedding.onReveal((anchor) => scrollTo(anchor));
674
+ await session.embedding.save(async ({ inspection }) => {
675
+ await db.documents.update({ docId, set: { ...changes, ...(inspection ? { inspection } : {}) } });
676
+ }); // throws MindooDBAppEmbedValidationError (with .issues) when the host's check stopped it
677
+ ```
678
+
679
+ Haven never holds writes back: the component asks first (`embedding.validate`, which
680
+ `embedding.save` calls), Haven fetches the inspection the host asked for, passes it with
681
+ the root document to the host's `onBeforeSave` and answers the component: an `error`
682
+ stops the save, a `warning` asks the user whether to save anyway, and when the host does
683
+ not answer within about 5 s the component saves (`timedOut`). This covers saves the
684
+ user, the host (`embed.save()`) and agents start; an agent tool saves with
685
+ `save(flush, { interactive: false })`, where warnings do not stop it, and reports the
686
+ error's issues as its tool error. Standalone, `validate` answers `ok` at once.
687
+
688
+ `save` also hands `flush` a small summary of the inspection (at most 8 KiB, lists and
689
+ text shortened, counts exact) as an atomic value for the root's `inspection` field, so
690
+ hosts can check documents they do not have open: `rules.checkRoot(root)`, or
691
+ `readMindooDBAppInspectionSummary(root)`. Write it in standalone saves too.
692
+
693
+ In tests, the mock plays the components with `embedInspection`, `embedTools` and
694
+ `confirmSaveWarnings`, and records `getEmbedRequests(embedId)`; `validateEmbed(embedId)`
695
+ runs the host's check as if the component was about to save. For an app under test that
696
+ is a component, `embeddingValidation` plays the host, and `requestEmbeddingInspection`,
697
+ `requestEmbeddingShowIssues`, `requestEmbeddingReveal`, `getEmbeddingValidations` and
698
+ `getEmbeddingSaveCount` drive and observe it.
699
+
631
700
  Havens that predate this lay the component over the container instead, above the host's
632
701
  frame (`embed.placement === "overlay"`). The host then cannot draw on top of it: hide it
633
702
  with `embed.setVisible(false)` while a menu or dialog of the host should be visible.