mindoodb-app-sdk 0.0.73 → 0.0.74

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.
Files changed (3) hide show
  1. package/README.md +52 -8
  2. package/dist/index.js +10 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -266,7 +266,7 @@ Haven uses the app's registration label as the headline and ignores any title fr
266
266
 
267
267
  An app can offer its own operations to AI agents. Haven registers them with the browser's agent interface ([WebMCP](https://webmachinelearning.github.io/webmcp/)) next to Haven's own tools, so an agent in the browser — or a local agent connected through a WebMCP bridge — can call "create a mind map", "list open tasks" or "attach this file" instead of clicking through the UI.
268
268
 
269
- The app declares tools; `execute` runs inside the app. Haven validates the declarations, prefixes the names with the app's tool prefix (`vega_maps_list` for `"agentToolPrefix": "vega"` in `haven-app.json`; without it Haven derives one from the app id or label), checks permission, asks the user before consequential calls, and forwards each call over the bridge. The tools disappear when the app closes.
269
+ The app declares tools; `execute` runs inside the app. Haven validates the declarations, prefixes the names with the app's tool prefix (`todo_list` for `"agentToolPrefix": "todo"` in `haven-app.json`; without it Haven derives one from the app id or label), checks permission, asks the user before consequential calls, and forwards each call over the bridge. The tools disappear when the app closes.
270
270
 
271
271
  Agents only see an app's tools while the user has **Agent tools** switched on in Haven (Settings → General) **and** has allowed this app (**Offer tools to AI agents** in the app's settings). Neither can be set by `haven-app.json`. `registerTools()` works either way; `enabled` in its answer says whether agents can call the tools right now.
272
272
 
@@ -420,7 +420,7 @@ Agents only see an app's tools while it runs. To pick the right app first, they
420
420
  - **`summary`**: neutral, 1-3 sentences, at most 400 characters per locale; `en` is required.
421
421
  - **`capabilities`**: 1-8 entries; `tools` names the tools as in `registerTools` (no prefix, no `haven_*`). Together they should cover every tool.
422
422
  - **`examples`**, **`limits`**: up to 8 strings per locale.
423
- - **`guide`**: Markdown how-to per locale, a path relative to `haven-app.json` (at most 8 KB): typical steps, where ids come from, pitfalls. Parameter tables belong in the tools (or `ops_guide`), not here.
423
+ - **`guide`**: Markdown how-to per locale, a path relative to `haven-app.json` (at most 8 KB): typical steps, where ids come from, pitfalls. Parameter tables belong in the tools (or `ops_guide`), not here. Haven fetches it cross-origin, so serve it with `Access-Control-Allow-Origin: *` like `haven-app.json` (Cloudflare: an `/agent/*` rule in `public/_headers`).
424
424
 
425
425
  Keep the profile honest with a unit test: `checkAgentManifest` from `mindoodb-app-sdk/testing` compares it with the registered tools and fails when a capability or the guide names a tool that does not exist (`assertAgentManifest` throws instead):
426
426
 
@@ -436,7 +436,27 @@ const warnings = assertAgentManifest({
436
436
  expect(warnings).toEqual([]); // every tool belongs to a capability
437
437
  ```
438
438
 
439
- `session.agent` is absent on hosts without agent tools, so check for it. Test tools by calling `execute` directly in unit tests; the reference implementation is `src/features/agent/` in [mindoodb-app-vega](https://github.com/klehmann/mindoodb-app-vega). How to design tools that agents use well is in the [best practices guide](https://github.com/klehmann/MindooDB/blob/main/docs/best-practices.md) (section "Offer operations to AI agents").
439
+ `session.agent` is absent on hosts without agent tools, so check for it. `registerTools()` answers `{ enabled, exposedNames }`: show from `enabled` whether agents can call the tools right now (and that **Offer tools to AI agents** switches them on), and use `exposedNames` when you display the names agents see. There is no event when the user changes the setting later; register again (e.g. when the app regains focus) to refresh it.
440
+
441
+ #### A recommended tool set for a data app
442
+
443
+ What the open-source SDK example app and TodoManager offer, from small to large:
444
+
445
+ - `get_context`: the open database, read-only or not, the signed-in user, today's date, what is selected. Agents call it first.
446
+ - `list` / `search`: exact criteria through `documents.query` filters on the summary buffer, topics through a full-text `text` clause, bounded output with `truncated`. Check `db.getFulltextSetup()` first: Haven rejects `text` with `fulltext-not-enabled` when the database has no index, while the mock answers anyway.
447
+ - `get`, `create`, `update`, `delete` over a small public model, never storage field names; `delete` with `consequentialHint`. Batch with lists so one call is one step.
448
+ - `undo` (and `history`/`redo` in larger apps): every write call is one undo step marked as made by an agent; undo refuses with `STATE_CHANGED` when the document changed since, so agents never overwrite user work.
449
+ - `users_search` when the app stores people: look names up in the tenant directory (`directory` permission) and store the directory id.
450
+
451
+ Small reference: `src/features/agent/` and `src/app/useAgentSection.ts` in [mindoodb-app-example](https://github.com/klehmann/mindoodb-app-example) (eight tools, undo, profile test). Full-size: `src/features/agent/` in [mindoodb-app-todomanager](https://github.com/klehmann/mindoodb-app-todomanager) (search, undo/redo/history, directory lookup, agent profile). Both are open source; copy from them.
452
+
453
+ #### Testing agent tools
454
+
455
+ - **Unit**: call `execute` directly with a database from `createMockMindooDBAppSession`.
456
+ - **End to end**: `createFakeBridgeHost({ agentToolPrefix, agentToolsEnabled, agentConsent })` connects the real bridge; `host.agent.tools()`, `host.agent.context()` and `host.agent.call(name, input)` act as the agent, and `call` answers `{ ok, result }` or `{ ok: false, error }`; `agentConsent: "deny"` plays a user who declines a `consequentialHint` call (`NOT_ALLOWED`).
457
+ - **In the browser**: the `/__haven-test/` page (`mountHavenTestHost`) lists the tools with a call button. Pass `agentToolPrefix: definition.agentToolPrefix`; without it the page derives the prefix from the app id, so the names differ from Haven's.
458
+
459
+ How to design tools that agents use well is in the [best practices guide](https://github.com/klehmann/MindooDB/blob/main/docs/best-practices.md) (section "Offer operations to AI agents").
440
460
 
441
461
  ### Host-owned drag
442
462
 
@@ -740,6 +760,30 @@ answers like a current Haven, so the SDK frames that URL in the container. Both
740
760
  controllers simulate unsaved changes: `setEmbedDirty`, `failNextEmbedSave`, and for an
741
761
  app under test that is a component, `getEmbeddingDirty` and `requestEmbeddingSave`.
742
762
 
763
+ **Host checklist.** What a host needs beyond the calls above (the "Embedded editors" tab of
764
+ [mindoodb-app-example](https://github.com/klehmann/mindoodb-app-example) is a small
765
+ complete host, `src/app/useEmbedsSection.ts`):
766
+
767
+ - `embeds.open` rejects with an `Error` whose `name` says why: `declined` (the user said
768
+ no), `component-not-found` (the app is not installed or no longer offers it),
769
+ `forbidden`, `database-not-found`, `document-not-found`, `invalid-request`,
770
+ `unsupported` (a Haven without components). Explain these to the user.
771
+ - `requestAccess` never asks again for what the user put off; Haven asks for it when the
772
+ document is opened. So say "Haven asks when you open one" instead of offering "ask again".
773
+ - `createFields` may contain nested values; copy it with a JSON round trip, not
774
+ `structuredClone`, when the component sits in Vue reactive state.
775
+ - Keep fields of your own on the root top-level and prefixed (`exampleEditor`), so
776
+ queries find them without `setSummarySetup`; nested fields (`crm.folders`) need a summary
777
+ setup first.
778
+ - Copy the component's `children` link onto the root (or remember it) so you can still
779
+ delete a document with all its children after the providing app was uninstalled.
780
+ - Keep the container mounted while the editor should live: removing the element (a tab
781
+ rendered with `v-if`) closes the editor. Hide it with `v-show` and
782
+ `embed.setVisible(false)` instead.
783
+ - With `placement === "overlay"` the SDK follows the container on resize and scroll, not
784
+ when content above it changes height; keep banners and confirm bars out of the space
785
+ above an open editor.
786
+
743
787
  A host with agent tools marks the component in the front tab with `embed.setActive()`
744
788
  and reads `embed.agentTools`; see *Agent tools of embedded components*.
745
789
 
@@ -1065,7 +1109,7 @@ An id in `dependencyIds` may name a revision the timeline does not list, because
1065
1109
 
1066
1110
  ### Granular JSON edits
1067
1111
 
1068
- When you need to edit nested objects or lists inside a document — not just top-level fields — describe the change as a **granular JSON patch** rather than rewriting the whole document. This is the model behind structured collaborative editing in apps like [`mindoodb-app-teamgrid`](https://github.com/klehmann/mindoodb-app-teamgrid), where two users can insert different rows into the same worksheet on different devices and the merge keeps both sides cleanly.
1112
+ When you need to edit nested objects or lists inside a document — not just top-level fields — describe the change as a **granular JSON patch** rather than rewriting the whole document. This is the model behind structured collaborative editing in apps like TeamGrid, where two users can insert different rows into the same worksheet on different devices and the merge keeps both sides cleanly.
1069
1113
 
1070
1114
  A JSON patch is a bag of four operation kinds applied at specific JSON paths inside `document.data`, all carried with the document version (`baseHeads`) the app was looking at when it composed them:
1071
1115
 
@@ -1366,11 +1410,11 @@ Buffer API at a glance:
1366
1410
 
1367
1411
  #### End-to-end sample
1368
1412
 
1369
- The [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit) sample wires `MindooDBTextBuffer` to a Milkdown markdown editor with Save / Refresh / preview pane, and is the recommended starting point for building your own collaborative text app.
1413
+ TeamEdit wires `MindooDBTextBuffer` to a Milkdown markdown editor with Save / Refresh / preview pane; its code is not public, so build on the snippets above.
1370
1414
 
1371
1415
  ### Collaborative rich-text editing
1372
1416
 
1373
- For structured documents that need formatting — headings, bold/italic runs, lists, tables, fonts, colors — use the **rich-text patch API**. This is the surface behind the Word/.docx mode in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit), where two users can edit the same document at the same time and Haven merges both formatting and structure on its side via Automerge's rich-text CRDT.
1417
+ For structured documents that need formatting — headings, bold/italic runs, lists, tables, fonts, colors — use the **rich-text patch API**. This is the surface behind TeamEdit's Word/.docx mode, where two users can edit the same document at the same time and Haven merges both formatting and structure on its side via Automerge's rich-text CRDT.
1374
1418
 
1375
1419
  Rich-text fields are stored internally as Automerge rich-text, but apps never see Automerge directly. The bridge speaks JSON and represents a rich-text field as an ordered list of **spans** — text runs with marks for inline formatting, plus block markers for paragraphs, headings, lists, and tables:
1376
1420
 
@@ -1480,7 +1524,7 @@ Like the text buffer, the rich-text handle always sends the original `baseHeads`
1480
1524
 
1481
1525
  #### End-to-end sample
1482
1526
 
1483
- The Word/.docx mode in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit) is the **only supported in-repo use case** for the Automerge binary sync API below — it needs a local replica and binary flush because `set`/`unset` and the JSON patch APIs are not sufficient for that editor. For span-only rich-text apps, use `createMindooDBRichTextHandle` instead.
1527
+ TeamEdit's Word/.docx mode is the **only supported in-repo use case** for the Automerge binary sync API below — it needs a local replica and binary flush because `set`/`unset` and the JSON patch APIs are not sufficient for that editor. For span-only rich-text apps, use `createMindooDBRichTextHandle` instead.
1484
1528
 
1485
1529
  ### Automerge binary sync (advanced)
1486
1530
 
@@ -1589,7 +1633,7 @@ Requires the `update` capability (same as other write operations). For historica
1589
1633
 
1590
1634
  #### Reference implementation (not a template)
1591
1635
 
1592
- TeamEdit's Word/.docx mode is why these RPCs exist — see `wordAutomergeHandle.ts` in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit). Treat it as a reference for an unsupported edge case, not as a pattern to copy into new apps.
1636
+ TeamEdit's Word/.docx mode is why these RPCs exist. Treat them as an unsupported edge case, not as a pattern for new apps.
1593
1637
 
1594
1638
  ### Queries & Live Queries
1595
1639
 
package/dist/index.js CHANGED
@@ -1,3 +1,13 @@
1
+ import {
2
+ MINDOODB_APP_BUNDLE_ARCHIVE_FILE_NAME,
3
+ MINDOODB_APP_BUNDLE_MANIFEST_FILE_NAME,
4
+ MINDOODB_APP_BUNDLE_MANIFEST_FORMAT,
5
+ MINDOODB_APP_BUNDLE_MANIFEST_VERSION,
6
+ buildMindooDBAppBundleContentHashInput,
7
+ isMindooDBAppBundleHash,
8
+ normalizeMindooDBAppBundlePath,
9
+ validateMindooDBAppBundleManifest
10
+ } from "./chunk-LT4FK6LU.js";
1
11
  import {
2
12
  DEFAULT_DRAG_LONG_PRESS_MS,
3
13
  DEFAULT_DRAG_POINTER_THRESHOLD_PX,
@@ -88,16 +98,6 @@ import {
88
98
  validateMindooDBAppComponents,
89
99
  validateMindooDBAppDefinition
90
100
  } from "./chunk-FKTNDDWB.js";
91
- import {
92
- MINDOODB_APP_BUNDLE_ARCHIVE_FILE_NAME,
93
- MINDOODB_APP_BUNDLE_MANIFEST_FILE_NAME,
94
- MINDOODB_APP_BUNDLE_MANIFEST_FORMAT,
95
- MINDOODB_APP_BUNDLE_MANIFEST_VERSION,
96
- buildMindooDBAppBundleContentHashInput,
97
- isMindooDBAppBundleHash,
98
- normalizeMindooDBAppBundlePath,
99
- validateMindooDBAppBundleManifest
100
- } from "./chunk-LT4FK6LU.js";
101
101
 
102
102
  // src/types.ts
103
103
  var MINDOODB_APP_WELL_KNOWN_DRAG_TYPES = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindoodb-app-sdk",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "engines": {
5
5
  "node": ">=22.13.0"
6
6
  },