mindoodb-app-sdk 0.0.53 → 0.0.55

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
@@ -22,26 +22,17 @@ A **MindooDB App** is any web application that uses this SDK to communicate with
22
22
 
23
23
  ## Architecture
24
24
 
25
- ```
26
- ┌─────────────────────────────────────────────────────────┐
27
- │ Haven (browser tab) │
28
- │ │
29
- │ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐ │
30
- │ │ Haven UI │──▶│ Bridge Host │──▶│ MindooDB │ │
31
- │ │ (theme, │ │ (RPC + │ │ (encrypted │ │
32
- │ │ viewport) │ │ streams) │ │ databases) │ │
33
- │ └──────────────┘ └──────┬──────┘ └─────────────┘ │
34
- │ │ │
35
- │ postMessage + MessagePort │
36
- │ │ │
37
- │ ┌─────────────────────────┼─────────────────────────┐ │
38
- │ │ Your App (sandboxed iframe / window) │ │
39
- │ │ │ │ │
40
- │ │ ┌──────────▼──────────┐ │ │
41
- │ │ │ mindoodb-app-sdk │ │ │
42
- │ │ └─────────────────────┘ │ │
43
- │ └───────────────────────────────────────────────────┘ │
44
- └─────────────────────────────────────────────────────────┘
25
+ ```mermaid
26
+ flowchart TB
27
+ subgraph haven["Haven (browser tab)"]
28
+ direction TB
29
+ ui["Haven UI<br/>(theme, viewport)"] --> bridge["Bridge Host<br/>(RPC + streams)"]
30
+ bridge --> db["MindooDB<br/>(encrypted databases)"]
31
+ subgraph app["Your App (sandboxed iframe / window)"]
32
+ sdk["mindoodb-app-sdk"]
33
+ end
34
+ bridge -- "postMessage + MessagePort" --> sdk
35
+ end
45
36
  ```
46
37
 
47
38
  The bridge carries RPC calls (documents, views, database info), binary attachment streams, and push events (theme changes, viewport resizes) over a single `MessagePort`.
@@ -258,6 +249,77 @@ Show a notice when the app does not have host focus, or when a long task finishe
258
249
 
259
250
  Haven uses the app's registration label as the headline and ignores any title from the app. Pass the same `id` to update that notice in place. Omit `id` to add another notice. An id only matches notices from this launch. Omit `durationMs` and the notice stays until the user dismisses it or clicks it. A duration is clamped to about 1–8 seconds, which fits a short progress step such as "10%". Clicking the notice brings that launch back. The close button only dismisses it.
260
251
 
252
+ ### Agent tools (WebMCP)
253
+
254
+ 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.
255
+
256
+ The app declares tools; `execute` runs inside the app. Haven validates the declarations, prefixes the names with the app's key (`vega_maps_list` for an app id `mindoodb-app-vega`), checks permission, asks the user before consequential calls, and forwards each call over the bridge. The tools disappear when the app closes.
257
+
258
+ 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.
259
+
260
+ ```ts
261
+ import { createViewLanguage, MindooDBAppAgentToolError } from "mindoodb-app-sdk";
262
+
263
+ const v = createViewLanguage<{ title: string; status: string; due: string }>();
264
+
265
+ if (session.agent) {
266
+ await session.agent.registerTools([
267
+ {
268
+ name: "tasks_search",
269
+ description:
270
+ "Finds tasks by part of the title. Returns taskId, title, status and due date. " +
271
+ "Use the taskId with todo_tasks_complete.",
272
+ inputSchema: {
273
+ type: "object",
274
+ required: ["query"],
275
+ properties: { query: { type: "string", description: "Part of the title." } },
276
+ },
277
+ annotations: { readOnlyHint: true, untrustedContentHint: true },
278
+ async execute(input) {
279
+ const result = await database.documents.query({
280
+ filter: v.contains(v.lower(v.field("title")), v.string(String(input.query).toLowerCase())),
281
+ fields: ["title", "status", "due"],
282
+ limit: 20,
283
+ });
284
+ return { tasks: result.rows.map((row) => ({ taskId: row.docId, ...row.fields })) };
285
+ },
286
+ },
287
+ {
288
+ name: "tasks_complete",
289
+ description: "Marks a task as done. taskId comes from todo_tasks_search; never pass a title.",
290
+ inputSchema: {
291
+ type: "object",
292
+ required: ["taskId"],
293
+ properties: { taskId: { type: "string" } },
294
+ },
295
+ async execute(input) {
296
+ const taskId = String(input.taskId ?? "");
297
+ const task = await database.documents.get(taskId).catch(() => null);
298
+ if (!task) {
299
+ throw new MindooDBAppAgentToolError("NOT_FOUND", `No task "${taskId}".`, "call todo_tasks_search");
300
+ }
301
+ await database.documents.update(taskId, { set: { status: "done" } });
302
+ return { taskId, status: "done" };
303
+ },
304
+ },
305
+ ]);
306
+
307
+ // What the user has open, for "this task" / "the selected one". Small and semantic.
308
+ await session.agent.setContext({ view: "list", selectedTaskId: null });
309
+ }
310
+ ```
311
+
312
+ - **`registerTools(tools)`** replaces the app's whole tool set; call it again when the set changes (e.g. after a document opens). At most 30 tools; names are lower case, digits and `_`, starting with a letter.
313
+ - **`description`** is written for a model: what the tool does, when to use it, where ids come from, what it returns. **`inputSchema`** is a JSON Schema object; use `enum` for fixed choices.
314
+ - **`annotations`**: `readOnlyHint` for reads; `consequentialHint` for anything the user should confirm (sending, sharing, deleting) — Haven shows its own confirmation dialog and a refusal reaches the agent as `NOT_ALLOWED`; `untrustedContentHint` when the result contains text other people wrote.
315
+ - **Errors**: throw `MindooDBAppAgentToolError(code, message, requiredAction?)` with `NOT_FOUND`, `INVALID_INPUT`, `INVALID_STATE`, `STATE_CHANGED`, `NOT_ALLOWED` or `FAILED`; `requiredAction` tells the agent what to do next ("call todo_tasks_search"). Any other exception becomes `FAILED`. Haven passes the agent one JSON error.
316
+ - **Results** must be JSON. Return what changed (ids, new values), not just `ok`.
317
+ - **`setContext(context)`** shows the app's state to agents in `haven_get_context` under the focused app.
318
+ - **Files** never travel through the agent. `agent.provideFile(blob, { name, mimeType })` hands Haven a file the app produced and returns a `fileRef` (valid ten minutes) for the agent to pass to `haven_files_export`, which saves it into the user's exchange folder. `agent.takeFile(fileRef)` returns a `File` the agent imported for this app with `haven_files_import`.
319
+ - A call that runs longer than two minutes fails with `FAILED`; files are limited to 50 MB.
320
+
321
+ `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").
322
+
261
323
  ### Host-owned drag
262
324
 
263
325
  When two apps run as visible workspace chicklets, native HTML5 drag dies at the iframe boundary. The SDK therefore hands the gesture to Haven: the source starts it, Haven draws a PNG ghost above every frame, and the target hit-tests the drop.
@@ -297,6 +359,7 @@ Each database mapped to your app carries a set of **capabilities** that Haven co
297
359
  | `history` | Access document revision history and historical snapshots |
298
360
  | `attachments` | List, upload, download, remove, and preview file attachments |
299
361
  | `views` | Create app-defined virtual views for this database |
362
+ | `directory` | List the tenant's users (`directory.listUsers()`), resolve signing keys |
300
363
  | `sealedchannel` | Open an encrypted channel to a tenant-joined service |
301
364
 
302
365
  ```ts
@@ -312,6 +375,21 @@ if (!db.capabilities.includes("delete")) {
312
375
 
313
376
  When the database is readable, `documents.list()` can also expose deleted document IDs by setting `status: "all"` or `status: "deleted"`. This is useful for app-side indexes and sync checkpoints.
314
377
 
378
+ ### Directory users
379
+
380
+ With the `directory` capability, `db.directory.listUsers()` returns the tenant's active usernames, e.g. for a recipient picker. For large directories ask for pages instead, with an optional case-insensitive search:
381
+
382
+ ```ts
383
+ let cursor: string | null = null;
384
+ do {
385
+ const page = await db.directory.listUsers({ query: "ann", cursor, limit: 50 });
386
+ addOptions(page.users);
387
+ cursor = page.nextCursor;
388
+ } while (cursor);
389
+ ```
390
+
391
+ Hosts that do not page yet answer with the full list; the SDK then filters and pages it on the client, so the paged form works with every Haven version.
392
+
315
393
  ### Sealed channels
316
394
 
317
395
  Some services join the user's tenant as a member of their own and then talk to your app over HTTP — the MindooMail bridge is the first. A sealed channel is how you reach one without your app ever touching key material.
@@ -757,23 +835,11 @@ Two layers are available:
757
835
 
758
836
  The end-to-end flow is the same in both cases:
759
837
 
760
- ```
761
- ┌────────────────────────────────────────────────────┐
762
- edit ───► │ App buffer (local string + pending splices) │ ──► flush
763
- └─────────────────────────┬──────────────────────────┘
764
- │ documents.update({
765
- │ text: [{ path, baseHeads, edits }]
766
- │ })
767
- ▼
768
- ┌────────────────────────────────────────────────────┐
769
- │ Haven applies edits at `baseHeads` and merges with │
770
- │ concurrent changes via Automerge │
771
- └─────────────────────────┬──────────────────────────┘
772
- │ canonical merged document
773
- ▼
774
- ┌────────────────────────────────────────────────────┐
775
- │ App reconciles its editor with the canonical text │
776
- └────────────────────────────────────────────────────┘
838
+ ```mermaid
839
+ flowchart TB
840
+ edit(["edit"]) --> buffer["App buffer<br/>(local string + pending splices)"]
841
+ buffer -- "flush: documents.update({ text: [{ path, baseHeads, edits }] })" --> merge["Haven applies edits at baseHeads<br/>and merges with concurrent changes via Automerge"]
842
+ merge -- "canonical merged document" --> reconcile["App reconciles its editor<br/>with the canonical text"]
777
843
  ```
778
844
 
779
845
  #### Text patch shape
@@ -1003,24 +1069,14 @@ If you must use binary sync, Haven decrypts the canonical document, merges incom
1003
1069
 
1004
1070
  Typical flow:
1005
1071
 
1006
- ```
1007
- ┌────────────────────────────────────────────────────┐
1008
- open ──► │ getAutomergeSnapshot → load local replica │
1009
- └─────────────────────────┬──────────────────────────┘
1010
- │
1011
- edit ──► │ Local Automerge doc (or span edits applied locally) │
1012
- └─────────────────────────┬──────────────────────────┘
1013
- │ getChangesSince(baseHeads)
1014
- ▼
1015
- ┌────────────────────────────────────────────────────┐
1016
- save ──► │ applyAutomergeChanges({ baseHeads, replicaHeads, │
1017
- │ changes }) │
1018
- └─────────────────────────┬──────────────────────────┘
1019
- │ Haven merges + persists
1020
- ▼
1021
- ┌────────────────────────────────────────────────────┐
1022
- │ Apply result.changesSince locally (or skip if empty) │
1023
- └────────────────────────────────────────────────────┘
1072
+ ```mermaid
1073
+ flowchart TB
1074
+ open(["open"]) --> snapshot["getAutomergeSnapshot<br/>→ load local replica"]
1075
+ snapshot --> local["Local Automerge doc<br/>(or span edits applied locally)"]
1076
+ editStep(["edit"]) --> local
1077
+ local -- "getChangesSince(baseHeads)" --> apply["applyAutomergeChanges({<br/>baseHeads, replicaHeads, changes })"]
1078
+ saveStep(["save"]) --> apply
1079
+ apply -- "Haven merges + persists" --> result["Apply result.changesSince locally<br/>(or skip if empty)"]
1024
1080
  ```
1025
1081
 
1026
1082
  Bridge RPCs: `documents.automerge.getSnapshot` and `documents.automerge.applyChanges`.
@@ -1702,6 +1758,7 @@ What the page shows comes from the optional `listing` in `haven-app.json`. Haven
1702
1758
  "listing": {
1703
1759
  "summary": { "en": "Plan trips together.", "de": "Reisen gemeinsam planen." },
1704
1760
  "description": { "en": "First paragraph.\n\nSecond paragraph." },
1761
+ "descriptionMarkdown": { "en": "**Plan** together.\n\n- Shared board\n- [Website](https://trips.example.com)" },
1705
1762
  "icon": "icon.svg",
1706
1763
  "screenshots": [{ "file": "screenshots/board.webp", "caption": { "en": "The trip board" } }],
1707
1764
  "publisher": { "name": "Mindoo GmbH", "url": "https://mindoo.de" }
@@ -1711,6 +1768,10 @@ What the page shows comes from the optional `listing` in `haven-app.json`. Haven
1711
1768
 
1712
1769
  Texts are a string or a per-locale map with an `en` fallback. Image paths are relative to the app origin or absolute `https:` URLs. The listing is display-only and grants nothing.
1713
1770
 
1771
+ Opening the app URL directly also puts share tags into `index.html` (`twitter:card` = `summary`, plus the Open Graph tags other apps read), with the app icon as the image. A production build takes the absolute URL from `publicUrl` in `haven-app.json`. `vite dev` uses the dev server's own origin instead, so `http://127.0.0.1:<port>/` previews against itself. Crawlers do not run the landing page's JavaScript, which is why the tags are in the HTML file.
1772
+
1773
+ `description` is plain text. `descriptionMarkdown` is the same text with formatting, in a small Markdown subset: paragraphs, headings, bullet and numbered lists, `**bold**`, `_italic_`, `` `code` ``, `[text](https://…)`, `[text](mailto:…)` and bare `https://…` links. Links to any other scheme render as plain text. Readers that know `descriptionMarkdown` show it instead of `description`; older Haven versions ignore it, so set both if they matter. `listingMarkdownToPlainText()` derives the plain version. A publisher `url` (`https:` only) turns the publisher name into a link.
1774
+
1714
1775
  For automated and manual tests use a separate test URL that frames the app with a mock host instead — see "Browser test host" in [`TESTING.md`](./TESTING.md). End users never see that page, and they never see mock data.
1715
1776
 
1716
1777
  ### Haven-hosted bundles
@@ -1818,6 +1879,10 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
1818
1879
  | `hasHostFocus()` | `Promise<boolean>` |
1819
1880
  | `onHostFocusChange(listener)` | `() => void` (unsubscribe) |
1820
1881
  | `notify(input)` | `Promise<{ id: string }>` |
1882
+ | `agent?.registerTools(tools)` | `Promise<MindooDBAppAgentRegistration>` |
1883
+ | `agent?.setContext(context)` | `Promise<void>` |
1884
+ | `agent?.provideFile(data, options)` | `Promise<{ fileRef: string; size: number }>` |
1885
+ | `agent?.takeFile(fileRef)` | `Promise<File>` |
1821
1886
  | `drag.setProfile(profile)` | `Promise<void>` |
1822
1887
  | `drag.start(input)` | `Promise<MindooDBAppDragStartResult>` |
1823
1888
  | `drag.cancel()` | `Promise<void>` |
package/TESTING.md CHANGED
@@ -337,16 +337,50 @@ mountHavenTestHost({
337
337
  });
338
338
  ```
339
339
 
340
- The page shows the app next to a control panel: theme and host-focus toggles, a file picker that decides what the app's next `attachments.scan()` returns (none means the user cancelled), and a live log of notifications, attachment previews, scans and every RPC request. The same controls are scriptable as `window.__havenTestHost`:
340
+ The page shows the app next to a control panel:
341
+
342
+ - **Host**: theme and host-focus toggles, reload the app frame.
343
+ - **Language**: switches the launch context's locale live (`onLocaleChange`), so you see the app re-render in every language without a reload.
344
+ - **Databases**: one checkbox per capability for every mapped database, plus **Enforce capabilities**. Changing a capability relaunches the app, as Haven does after a permission change. With enforcement on, the mock rejects every call the database was not granted with a `forbidden` error (and `documents.canCreate()` and friends answer `allowed: false`), so you can check the app's hints for missing rights.
345
+ - **Directory**: fills the tenant directory with 0 to 500 generated users (`CN=Test User 001/O=Test`, …) for recipient pickers and paging.
346
+ - **Scanner**: what `attachments.scan()` returns — cancel, a generated sample page, or a file you choose. The file is written to the document's attachments like Haven's scanner does, so the app can read it back.
347
+ - A live log of notifications, attachment previews, scans and every RPC request. Click a request for its parameters, its result or error, and how long it took; binary values show as size plus a hex preview.
348
+
349
+ `mockDatabasesFromDefinition` gives every database an in-memory attachment store (`attachments: "none"` restores the stateless default) and takes overrides for testing other mappings than the definition requests:
350
+
351
+ ```ts
352
+ mountHavenTestHost({
353
+ appUrl: "/",
354
+ databases: mockDatabasesFromDefinition(definition, seed, {
355
+ overrides: {
356
+ main: { capabilities: ["read"] }, // read-only mapping
357
+ archive: { mapped: false }, // the user did not map this one
358
+ },
359
+ }),
360
+ enforceCapabilities: true,
361
+ directoryUsers: generateDirectoryUsers(120),
362
+ scanMode: "sample",
363
+ });
364
+ ```
365
+
366
+ The panel keeps its settings in the page URL, so a scenario can be linked or opened by Playwright directly: `/__haven-test/?db=main:read,attachments&db=archive:none&enforce=1&users=120&locale=de-DE&theme=dark` (`db=<id>:none` unmaps a database; URL settings win over the options). The same controls are scriptable as `window.__havenTestHost`:
341
367
 
342
368
  ```ts
343
- await page.goto("/__haven-test/");
369
+ await page.goto("/__haven-test/?enforce=1");
344
370
  const app = page.frameLocator('[data-testid="haven-test-app-frame"]');
371
+ await page.evaluate(() => window.__havenTestHost!.setCapabilities("main", ["read"])); // relaunches the app
372
+ await expect(app.getByText("You can only view")).toBeVisible();
373
+
374
+ await page.evaluate(() => window.__havenTestHost!.setLocale("de-DE"));
345
375
  await page.evaluate(() => window.__havenTestHost!.setNextScan({ fileName: "receipt.pdf", mimeType: "application/pdf", size: 1024 }));
346
376
  await app.getByRole("button", { name: "Scan" }).click();
347
377
  expect(await page.evaluate(() => window.__havenTestHost!.log.scans)).toHaveLength(1);
348
378
  ```
349
379
 
380
+ `setNextScan()` decides only the next scan (pass `bytes` to attach real content); `setScanMode()` decides the ones after it. `setDirectoryUsers()` and `setEnforceCapabilities()` apply to the next call.
381
+
382
+ The Level 1 and 2 helpers take the same options: `createMockMindooDBAppSession({ enforceCapabilities: true, directoryUsers: generateDirectoryUsers(120) })`, with `setCapabilities()`, `setEnforceCapabilities()` and `setDirectoryUsers()` on the controller, and `createMemoryAttachments()` for a database's `methods.attachments`. `createFakeBridgeHost({ onResponse })` reports every answer with its duration.
383
+
350
384
  Lower-level pieces, if you build your own page: `createBrowserTestHost({ frame, appUrl, ...mockOptions })` wires one iframe to a fake host, and `host.acceptConnection(message, ports)` answers a handshake you received yourself.
351
385
 
352
386
  Keep the test page out of production builds. The starter template builds it only for `vite dev` and when `HAVEN_TEST_HOST=1` is set (for preview deployments), so the app's public URL keeps showing its landing page.
@@ -431,6 +431,123 @@ function bindDragSource(element, options, start, follow) {
431
431
  };
432
432
  }
433
433
 
434
+ // src/client/agentTools.ts
435
+ var TOOL_NAME_PATTERN = /^[a-z][a-z0-9_]{0,47}$/;
436
+ var MindooDBAppAgentToolError = class extends Error {
437
+ code;
438
+ requiredAction;
439
+ constructor(code, message, requiredAction) {
440
+ super(message);
441
+ this.name = "MindooDBAppAgentToolError";
442
+ this.code = code;
443
+ this.requiredAction = requiredAction;
444
+ }
445
+ };
446
+ function toJson(value) {
447
+ return value === void 0 ? null : JSON.parse(JSON.stringify(value));
448
+ }
449
+ var MindooDBAppAgentApiImpl = class {
450
+ constructor(rpc) {
451
+ this.rpc = rpc;
452
+ this.stopListening = rpc.addMessageListener((message) => {
453
+ if (message.kind === "agent-invoke") {
454
+ void this.invoke(message.callId, message.tool, message.input);
455
+ }
456
+ });
457
+ }
458
+ rpc;
459
+ tools = /* @__PURE__ */ new Map();
460
+ stopListening;
461
+ async registerTools(tools) {
462
+ const next = /* @__PURE__ */ new Map();
463
+ for (const tool of tools) {
464
+ if (!TOOL_NAME_PATTERN.test(tool.name)) {
465
+ throw new Error(`Invalid agent tool name "${tool.name}": use lower case, digits and underscores.`);
466
+ }
467
+ if (next.has(tool.name)) {
468
+ throw new Error(`Agent tool "${tool.name}" is registered twice.`);
469
+ }
470
+ next.set(tool.name, tool);
471
+ }
472
+ this.tools = next;
473
+ return await this.rpc.call("agent.registerTools", {
474
+ tools: tools.map((tool) => ({
475
+ name: tool.name,
476
+ description: tool.description,
477
+ inputSchema: toJson(tool.inputSchema),
478
+ ...tool.annotations ? { annotations: { ...tool.annotations } } : {}
479
+ }))
480
+ });
481
+ }
482
+ async provideFile(data, options) {
483
+ const buffer = data instanceof Blob ? await data.arrayBuffer() : data instanceof Uint8Array ? data.slice().buffer : data;
484
+ return await this.rpc.call("agent.provideFile", {
485
+ name: options.name,
486
+ mimeType: options.mimeType ?? (data instanceof Blob ? data.type : void 0),
487
+ data: buffer
488
+ });
489
+ }
490
+ async takeFile(fileRef) {
491
+ const result = await this.rpc.call("agent.takeFile", {
492
+ fileRef
493
+ });
494
+ return new File([result.data], result.name, { type: result.mimeType });
495
+ }
496
+ async setContext(context) {
497
+ await this.rpc.call("agent.setContext", { context: context === null ? null : toJson(context) });
498
+ }
499
+ dispose() {
500
+ this.stopListening();
501
+ this.tools.clear();
502
+ }
503
+ async invoke(callId, name, input) {
504
+ let reply;
505
+ const tool = this.tools.get(name);
506
+ try {
507
+ if (!tool) {
508
+ throw new MindooDBAppAgentToolError("NOT_FOUND", `The app has no tool "${name}" (any more).`);
509
+ }
510
+ const result = await tool.execute(input ?? {});
511
+ reply = { protocol: "mindoodb-app-bridge", kind: "agent-result", callId, ok: true, result: toJson(result) };
512
+ } catch (error) {
513
+ reply = {
514
+ protocol: "mindoodb-app-bridge",
515
+ kind: "agent-result",
516
+ callId,
517
+ ok: false,
518
+ error: error instanceof MindooDBAppAgentToolError ? {
519
+ code: error.code,
520
+ message: error.message,
521
+ ...error.requiredAction ? { requiredAction: error.requiredAction } : {}
522
+ } : { code: "FAILED", message: error instanceof Error && error.message ? error.message : String(error) }
523
+ };
524
+ }
525
+ try {
526
+ this.rpc.postMessage(reply);
527
+ } catch (error) {
528
+ console.warn("[mindoodb-app-sdk] Could not return an agent tool result.", error);
529
+ }
530
+ }
531
+ };
532
+
533
+ // src/directoryPaging.ts
534
+ var LIST_USERS_DEFAULT_LIMIT = 50;
535
+ var LIST_USERS_MAX_LIMIT = 500;
536
+ function pageUsers(users, options) {
537
+ const needle = options.query?.trim().toLocaleLowerCase();
538
+ const filtered = needle ? users.filter((user) => user.toLocaleLowerCase().includes(needle)) : [...users];
539
+ const limit = Math.min(
540
+ Math.max(1, Math.floor(options.limit ?? LIST_USERS_DEFAULT_LIMIT)),
541
+ LIST_USERS_MAX_LIMIT
542
+ );
543
+ const offset = Math.max(0, Number.parseInt(options.cursor ?? "0", 10) || 0);
544
+ const end = offset + limit;
545
+ return {
546
+ users: filtered.slice(offset, end),
547
+ nextCursor: end < filtered.length ? String(end) : null
548
+ };
549
+ }
550
+
434
551
  // src/hostShortcuts.ts
435
552
  var DEFAULT_HAVEN_HOST_SHORTCUTS = [
436
553
  { action: "open-workspace", code: "Enter", shiftKey: true, metaOrCtrl: true },
@@ -1491,18 +1608,29 @@ var MindooDBAppDatabaseImpl = class {
1491
1608
  databaseId: this.databaseId,
1492
1609
  publicKeys
1493
1610
  }),
1494
- listUsers: async () => {
1611
+ listUsers: (async (options) => {
1612
+ let result;
1495
1613
  try {
1496
- return await this.rpc.call("directory.listUsers", {
1497
- databaseId: this.databaseId
1498
- });
1614
+ result = await this.rpc.call(
1615
+ "directory.listUsers",
1616
+ options ? {
1617
+ databaseId: this.databaseId,
1618
+ query: options.query,
1619
+ cursor: options.cursor ?? void 0,
1620
+ limit: options.limit
1621
+ } : { databaseId: this.databaseId }
1622
+ );
1499
1623
  } catch (error) {
1500
1624
  if (!isMethodNotFoundError(error)) {
1501
1625
  throw error;
1502
1626
  }
1503
- return [];
1627
+ result = [];
1504
1628
  }
1505
- }
1629
+ if (!options) {
1630
+ return Array.isArray(result) ? result : result.users;
1631
+ }
1632
+ return Array.isArray(result) ? pageUsers(result, options) : result;
1633
+ })
1506
1634
  };
1507
1635
  this.attachments = {
1508
1636
  list: async (docId, options) => await this.rpc.call("attachments.list", {
@@ -1785,6 +1913,7 @@ var MindooDBAppSessionImpl = class {
1785
1913
  }
1786
1914
  };
1787
1915
  this.drag = new MindooDBAppDragApiImpl(this.rpc);
1916
+ this.agent = new MindooDBAppAgentApiImpl(this.rpc);
1788
1917
  this.storage = {
1789
1918
  snapshot: async (options) => await this.rpc.call("appStorage.snapshot", {
1790
1919
  prefixes: options?.prefixes
@@ -1847,6 +1976,7 @@ var MindooDBAppSessionImpl = class {
1847
1976
  menus;
1848
1977
  drag;
1849
1978
  storage;
1979
+ agent;
1850
1980
  beforeCloseListeners = /* @__PURE__ */ new Set();
1851
1981
  hostShortcuts = DEFAULT_HAVEN_HOST_SHORTCUTS;
1852
1982
  stopHostShortcuts;
@@ -2019,6 +2149,7 @@ var MindooDBAppSessionImpl = class {
2019
2149
  this.stopHostShortcuts();
2020
2150
  this.stopHostFocus();
2021
2151
  this.drag.dispose();
2152
+ this.agent.dispose();
2022
2153
  try {
2023
2154
  await this.rpc.call("session.disconnect", {});
2024
2155
  } finally {
@@ -2087,6 +2218,8 @@ export {
2087
2218
  normalizeDragStartInput,
2088
2219
  snapshotElementToPng,
2089
2220
  bindDragSource,
2221
+ MindooDBAppAgentToolError,
2222
+ pageUsers,
2090
2223
  DEFAULT_HAVEN_HOST_SHORTCUTS,
2091
2224
  matchHostShortcut,
2092
2225
  isHostShortcutAction,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppDragBindSourceOptions, b as MindooDBAppDragStartInput, c as MindooDBAppDragStartResult, d as MindooDBAppDragPreview, e as MindooDBAppBridge, f as MindooDBAppHostShortcutBinding, g as MindooDBAppHostShortcutAction, h as MindooDBAppHostingMode, i as MindooDBAppDefinition, j as MindooDBAppDatabase, k as MindooDBAppDocument, l as MindooDBAppRichTextSpan, m as MindooDBAppRichTextSnapshot, n as MindooDBAppCreateDocumentInput } from './types-CsKw_niD.js';
2
- export { o as MINDOODB_APP_DEFINITION_FILE_NAME, p as MINDOODB_APP_DEFINITION_FORMAT, q as MINDOODB_APP_DEFINITION_PERMISSIONS, r as MINDOODB_APP_DEFINITION_REGISTRATION_PERMISSIONS, s as MINDOODB_APP_DEFINITION_VERSION, t as MINDOODB_APP_LISTING_DESCRIPTION_MAX, u as MINDOODB_APP_LISTING_MAX_SCREENSHOTS, v as MINDOODB_APP_LISTING_SUMMARY_MAX, w as MINDOODB_APP_SEAL_SIGNING_DOMAIN, x as MINDOODB_APP_WELL_KNOWN_DRAG_TYPES, y as MindooDBAppAccessDecision, z as MindooDBAppAccessTier, A as MindooDBAppAttachmentApi, B as MindooDBAppAttachmentChunk, C as MindooDBAppAttachmentInfo, D as MindooDBAppAttachmentPreviewOptions, E as MindooDBAppAttachmentPreviewSession, F as MindooDBAppAutomergeChangesPatch, G as MindooDBAppAutomergeChangesSince, H as MindooDBAppAutomergeGetOptions, I as MindooDBAppAutomergePatchResult, J as MindooDBAppAutomergeSnapshot, K as MindooDBAppBridgeBeforeCloseAck, L as MindooDBAppBridgeBeforeCloseMessage, N as MindooDBAppBridgeConnectMessage, O as MindooDBAppBridgeConnectOptions, P as MindooDBAppBridgeConnectedMessage, Q as MindooDBAppBridgeDragDropMessage, R as MindooDBAppBridgeDragLeaveMessage, S as MindooDBAppBridgeDragOverMessage, T as MindooDBAppBridgeErrorPayload, U as MindooDBAppBridgeHandshakeErrorMessage, V as MindooDBAppBridgeHostFocusChangedMessage, W as MindooDBAppBridgeLocaleChangedMessage, X as MindooDBAppBridgePortMessage, Y as MindooDBAppBridgeQueryResultMessage, Z as MindooDBAppBridgeRpcError, _ as MindooDBAppBridgeRpcMessage, $ as MindooDBAppBridgeRpcRequest, a0 as MindooDBAppBridgeRpcSuccess, a1 as MindooDBAppBridgeShortcutInvokedMessage, a2 as MindooDBAppBridgeShortcutsChangedMessage, a3 as MindooDBAppBridgeStreamAbortRequest, a4 as MindooDBAppBridgeStreamAck, a5 as MindooDBAppBridgeStreamCloseRequest, a6 as MindooDBAppBridgeStreamError, a7 as MindooDBAppBridgeStreamMessage, a8 as MindooDBAppBridgeStreamOpenResult, a9 as MindooDBAppBridgeStreamReadRequest, aa as MindooDBAppBridgeStreamWriteRequest, ab as MindooDBAppBridgeThemeChangedMessage, ac as MindooDBAppBridgeUiPreferencesChangedMessage, ad as MindooDBAppBridgeViewChangedMessage, ae as MindooDBAppBridgeViewportChangedMessage, af as MindooDBAppBridgeWorkspaceFocusRequestedMessage, ag as MindooDBAppCapability, ah as MindooDBAppConfiguredViewCategorizationStyle, ai as MindooDBAppConfiguredViewColumn, aj as MindooDBAppConfiguredViewColumnRole, ak as MindooDBAppConfiguredViewExpressionMode, al as MindooDBAppConfiguredViewFieldExpression, am as MindooDBAppConfiguredViewFilterDefinition, an as MindooDBAppConfiguredViewFilterMode, ao as MindooDBAppConfiguredViewFilterRule, ap as MindooDBAppConfiguredViewFormulaExpression, aq as MindooDBAppConfiguredViewFormulaFilterDefinition, ar as MindooDBAppConfiguredViewPreviewMode, as as MindooDBAppConfiguredViewRuleFilterDefinition, at as MindooDBAppConfiguredViewRuleMatchMode, au as MindooDBAppConfiguredViewRuleOperator, av as MindooDBAppConfiguredViewValueExpression, aw as MindooDBAppCreateKeyInfo, ax as MindooDBAppCreateViewInput, ay as MindooDBAppCreateViewNavigatorInput, az as MindooDBAppDatabaseInfo, aA as MindooDBAppDefinitionDatabase, aB as MindooDBAppDefinitionListing, aC as MindooDBAppDefinitionPermission, aD as MindooDBAppDefinitionRegistrationPermission, aE as MindooDBAppDefinitionScreenshot, aF as MindooDBAppDefinitionValidation, aG as MindooDBAppDirectoryApi, aH as MindooDBAppDirectoryEntry, aI as MindooDBAppDocumentApi, aJ as MindooDBAppDocumentHeadCursorResult, aK as MindooDBAppDocumentHistoryEntry, aL as MindooDBAppDocumentListQuery, aM as MindooDBAppDocumentListResult, aN as MindooDBAppDocumentQuery, aO as MindooDBAppDocumentRevisionId, aP as MindooDBAppDocumentScanPreset, aQ as MindooDBAppDocumentSummary, aR as MindooDBAppDragApi, aS as MindooDBAppDragCancelReason, aT as MindooDBAppDragDropEvent, aU as MindooDBAppDragEffect, aV as MindooDBAppDragHoverResult, aW as MindooDBAppDragOffer, aX as MindooDBAppDragOverEvent, aY as MindooDBAppDragPointer, aZ as MindooDBAppDragProfile, a_ as MindooDBAppEntryAttachmentRef, a$ as MindooDBAppEntryProvenance, b0 as MindooDBAppExtractDocumentTextInput, b1 as MindooDBAppExtractDocumentTextResult, b2 as MindooDBAppExtractTextFormat, b3 as MindooDBAppExtractionSetup, b4 as MindooDBAppFulltextSetup, b5 as MindooDBAppHistoricalDocument, b6 as MindooDBAppHistoryQuery, b7 as MindooDBAppHostTheme, b8 as MindooDBAppIdentityApi, b9 as MindooDBAppInaccessibleDocument, ba as MindooDBAppInaccessibleDocumentListQuery, bb as MindooDBAppInaccessibleDocumentListResult, bc as MindooDBAppJsonCounterIncrementPatch, bd as MindooDBAppJsonListDeletePatch, be as MindooDBAppJsonListInsertPatch, bf as MindooDBAppJsonPatch, bg as MindooDBAppJsonSetPatch, bh as MindooDBAppJsonTextMarkPatch, bi as MindooDBAppJsonTextSplicePatch, bj as MindooDBAppJsonTextUnmarkPatch, bk as MindooDBAppJsonUnsetPatch, bl as MindooDBAppLaunchContext, bm as MindooDBAppLiveQuerySubscription, bn as MindooDBAppLocalizedText, bo as MindooDBAppMenuAnchor, bp as MindooDBAppMenuApi, bq as MindooDBAppMenuCommandItem, br as MindooDBAppMenuDismissReason, bs as MindooDBAppMenuDismissedResult, bt as MindooDBAppMenuItem, bu as MindooDBAppMenuKind, bv as MindooDBAppMenuPlacement, bw as MindooDBAppMenuPointAnchor, bx as MindooDBAppMenuRect, by as MindooDBAppMenuRectAnchor, bz as MindooDBAppMenuSelectionResult, bA as MindooDBAppMenuSeparatorItem, bB as MindooDBAppNotificationSeverity, bC as MindooDBAppNotifyInput, bD as MindooDBAppNotifyResult, bE as MindooDBAppProposeAppInput, bF as MindooDBAppProposeAppResult, bG as MindooDBAppQueryCoverage, bH as MindooDBAppQueryInclude, bI as MindooDBAppQueryIncludeCardinality, bJ as MindooDBAppQueryIncludeSlots, bK as MindooDBAppQueryResult, bL as MindooDBAppQueryRow, bM as MindooDBAppQuerySortKey, bN as MindooDBAppQueryTextClause, bO as MindooDBAppReadableAttachmentStream, bP as MindooDBAppRecipientOptions, bQ as MindooDBAppResolvedViewDefinition, bR as MindooDBAppResolvedViewSource, bS as MindooDBAppRevisionPhase, bT as MindooDBAppRevisionVerification, bU as MindooDBAppRichTextBlockSpan, bV as MindooDBAppRichTextGetOptions, bW as MindooDBAppRichTextImmutableString, bX as MindooDBAppRichTextMarkRange, bY as MindooDBAppRichTextMaterializeValue, bZ as MindooDBAppRichTextPatch, b_ as MindooDBAppRichTextScalar, b$ as MindooDBAppRichTextSpliceStep, c0 as MindooDBAppRichTextStep, c1 as MindooDBAppRichTextStepPatch, c2 as MindooDBAppRichTextTextSpan, c3 as MindooDBAppRuntime, c4 as MindooDBAppScanAttachmentOptions, c5 as MindooDBAppScanAttachmentResult, c6 as MindooDBAppScopedDocId, c7 as MindooDBAppScopedDocumentSummary, c8 as MindooDBAppSealIntent, c9 as MindooDBAppSealedChannelOpenInput, ca as MindooDBAppSealedChannelOpenResult, cb as MindooDBAppSealedChannelRequestInput, cc as MindooDBAppSession, cd as MindooDBAppShowMenuInput, ce as MindooDBAppShowMenuResult, cf as MindooDBAppSignPreview, cg as MindooDBAppSignPreviewScope, ch as MindooDBAppSignStatementInput, ci as MindooDBAppSignStatementResult, cj as MindooDBAppStorageApi, ck as MindooDBAppSummarySetup, cl as MindooDBAppTextCursorOptions, cm as MindooDBAppTextCursorPosition, cn as MindooDBAppTextCursorPositionsResult, co as MindooDBAppTextCursorsResult, cp as MindooDBAppTextEdit, cq as MindooDBAppTextPatch, cr as MindooDBAppThemeMode, cs as MindooDBAppTimestampApi, ct as MindooDBAppTimestampInput, cu as MindooDBAppTimestampProvider, cv as MindooDBAppTimestampResult, cw as MindooDBAppUiPreferences, cx as MindooDBAppUpdateDocumentInput, cy as MindooDBAppViewCursorDocumentListResult, cz as MindooDBAppViewCursorResult, cA as MindooDBAppViewEntry, cB as MindooDBAppViewEntryKind, cC as MindooDBAppViewNavigator, cD as MindooDBAppViewNavigatorExpansionState, cE as MindooDBAppViewNavigatorOpenOptions, cF as MindooDBAppViewNavigatorPageOptions, cG as MindooDBAppViewNavigatorPageResult, cH as MindooDBAppViewNavigatorRangeQuery, cI as MindooDBAppViewNavigatorSelectionState, cJ as MindooDBAppViewUpdateStats, cK as MindooDBAppViewport, cL as MindooDBAppWellKnownDragType, cM as MindooDBAppWritableAttachmentStream, cN as resolveMindooDBAppDefinitionUrl, cO as resolveMindooDBAppListingAssetUrl, cP as resolveMindooDBAppLocalizedText, cQ as validateMindooDBAppDefinition } from './types-CsKw_niD.js';
1
+ import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppDragBindSourceOptions, b as MindooDBAppDragStartInput, c as MindooDBAppDragStartResult, d as MindooDBAppDragPreview, e as MindooDBAppBridge, f as MindooDBAppAgentToolErrorCode, g as MindooDBAppHostShortcutBinding, h as MindooDBAppHostShortcutAction, i as MindooDBAppHostingMode, j as MindooDBAppDefinition, k as MindooDBAppDatabase, l as MindooDBAppDocument, m as MindooDBAppRichTextSpan, n as MindooDBAppRichTextSnapshot, o as MindooDBAppCreateDocumentInput } from './types-Dl70Tlfj.js';
2
+ export { p as MINDOODB_APP_DEFINITION_FILE_NAME, q as MINDOODB_APP_DEFINITION_FORMAT, r as MINDOODB_APP_DEFINITION_PERMISSIONS, s as MINDOODB_APP_DEFINITION_REGISTRATION_PERMISSIONS, t as MINDOODB_APP_DEFINITION_VERSION, u as MINDOODB_APP_LISTING_DESCRIPTION_MAX, v as MINDOODB_APP_LISTING_MAX_SCREENSHOTS, w as MINDOODB_APP_LISTING_SUMMARY_MAX, x as MINDOODB_APP_SEAL_SIGNING_DOMAIN, y as MINDOODB_APP_WELL_KNOWN_DRAG_TYPES, z as MindooDBAppAccessDecision, A as MindooDBAppAccessTier, B as MindooDBAppAgentApi, C as MindooDBAppAgentRegistration, D as MindooDBAppAgentTool, E as MindooDBAppAgentToolAnnotations, F as MindooDBAppAgentToolDescriptor, G as MindooDBAppAttachmentApi, H as MindooDBAppAttachmentChunk, I as MindooDBAppAttachmentInfo, J as MindooDBAppAttachmentPreviewOptions, K as MindooDBAppAttachmentPreviewSession, L as MindooDBAppAutomergeChangesPatch, N as MindooDBAppAutomergeChangesSince, O as MindooDBAppAutomergeGetOptions, P as MindooDBAppAutomergePatchResult, Q as MindooDBAppAutomergeSnapshot, R as MindooDBAppBridgeAgentInvokeMessage, S as MindooDBAppBridgeAgentResultMessage, T as MindooDBAppBridgeBeforeCloseAck, U as MindooDBAppBridgeBeforeCloseMessage, V as MindooDBAppBridgeConnectMessage, W as MindooDBAppBridgeConnectOptions, X as MindooDBAppBridgeConnectedMessage, Y as MindooDBAppBridgeDragDropMessage, Z as MindooDBAppBridgeDragLeaveMessage, _ as MindooDBAppBridgeDragOverMessage, $ as MindooDBAppBridgeErrorPayload, a0 as MindooDBAppBridgeHandshakeErrorMessage, a1 as MindooDBAppBridgeHostFocusChangedMessage, a2 as MindooDBAppBridgeLocaleChangedMessage, a3 as MindooDBAppBridgePortMessage, a4 as MindooDBAppBridgeQueryResultMessage, a5 as MindooDBAppBridgeRpcError, a6 as MindooDBAppBridgeRpcMessage, a7 as MindooDBAppBridgeRpcRequest, a8 as MindooDBAppBridgeRpcSuccess, a9 as MindooDBAppBridgeShortcutInvokedMessage, aa as MindooDBAppBridgeShortcutsChangedMessage, ab as MindooDBAppBridgeStreamAbortRequest, ac as MindooDBAppBridgeStreamAck, ad as MindooDBAppBridgeStreamCloseRequest, ae as MindooDBAppBridgeStreamError, af as MindooDBAppBridgeStreamMessage, ag as MindooDBAppBridgeStreamOpenResult, ah as MindooDBAppBridgeStreamReadRequest, ai as MindooDBAppBridgeStreamWriteRequest, aj as MindooDBAppBridgeThemeChangedMessage, ak as MindooDBAppBridgeUiPreferencesChangedMessage, al as MindooDBAppBridgeViewChangedMessage, am as MindooDBAppBridgeViewportChangedMessage, an as MindooDBAppBridgeWorkspaceFocusRequestedMessage, ao as MindooDBAppCapability, ap as MindooDBAppConfiguredViewCategorizationStyle, aq as MindooDBAppConfiguredViewColumn, ar as MindooDBAppConfiguredViewColumnRole, as as MindooDBAppConfiguredViewExpressionMode, at as MindooDBAppConfiguredViewFieldExpression, au as MindooDBAppConfiguredViewFilterDefinition, av as MindooDBAppConfiguredViewFilterMode, aw as MindooDBAppConfiguredViewFilterRule, ax as MindooDBAppConfiguredViewFormulaExpression, ay as MindooDBAppConfiguredViewFormulaFilterDefinition, az as MindooDBAppConfiguredViewPreviewMode, aA as MindooDBAppConfiguredViewRuleFilterDefinition, aB as MindooDBAppConfiguredViewRuleMatchMode, aC as MindooDBAppConfiguredViewRuleOperator, aD as MindooDBAppConfiguredViewValueExpression, aE as MindooDBAppCreateKeyInfo, aF as MindooDBAppCreateViewInput, aG as MindooDBAppCreateViewNavigatorInput, aH as MindooDBAppDatabaseInfo, aI as MindooDBAppDefinitionDatabase, aJ as MindooDBAppDefinitionListing, aK as MindooDBAppDefinitionPermission, aL as MindooDBAppDefinitionRegistrationPermission, aM as MindooDBAppDefinitionScreenshot, aN as MindooDBAppDefinitionValidation, aO as MindooDBAppDirectoryApi, aP as MindooDBAppDirectoryEntry, aQ as MindooDBAppDocumentApi, aR as MindooDBAppDocumentHeadCursorResult, aS as MindooDBAppDocumentHistoryEntry, aT as MindooDBAppDocumentListQuery, aU as MindooDBAppDocumentListResult, aV as MindooDBAppDocumentQuery, aW as MindooDBAppDocumentRevisionId, aX as MindooDBAppDocumentScanPreset, aY as MindooDBAppDocumentSummary, aZ as MindooDBAppDragApi, a_ as MindooDBAppDragCancelReason, a$ as MindooDBAppDragDropEvent, b0 as MindooDBAppDragEffect, b1 as MindooDBAppDragHoverResult, b2 as MindooDBAppDragOffer, b3 as MindooDBAppDragOverEvent, b4 as MindooDBAppDragPointer, b5 as MindooDBAppDragProfile, b6 as MindooDBAppEntryAttachmentRef, b7 as MindooDBAppEntryProvenance, b8 as MindooDBAppExtractDocumentTextInput, b9 as MindooDBAppExtractDocumentTextResult, ba as MindooDBAppExtractTextFormat, bb as MindooDBAppExtractionSetup, bc as MindooDBAppFulltextSetup, bd as MindooDBAppHistoricalDocument, be as MindooDBAppHistoryQuery, bf as MindooDBAppHostTheme, bg as MindooDBAppIdentityApi, bh as MindooDBAppInaccessibleDocument, bi as MindooDBAppInaccessibleDocumentListQuery, bj as MindooDBAppInaccessibleDocumentListResult, bk as MindooDBAppJsonCounterIncrementPatch, bl as MindooDBAppJsonListDeletePatch, bm as MindooDBAppJsonListInsertPatch, bn as MindooDBAppJsonPatch, bo as MindooDBAppJsonSetPatch, bp as MindooDBAppJsonTextMarkPatch, bq as MindooDBAppJsonTextSplicePatch, br as MindooDBAppJsonTextUnmarkPatch, bs as MindooDBAppJsonUnsetPatch, bt as MindooDBAppLaunchContext, bu as MindooDBAppListUsersOptions, bv as MindooDBAppListUsersPage, bw as MindooDBAppLiveQuerySubscription, bx as MindooDBAppLocalizedText, by as MindooDBAppMenuAnchor, bz as MindooDBAppMenuApi, bA as MindooDBAppMenuCommandItem, bB as MindooDBAppMenuDismissReason, bC as MindooDBAppMenuDismissedResult, bD as MindooDBAppMenuItem, bE as MindooDBAppMenuKind, bF as MindooDBAppMenuPlacement, bG as MindooDBAppMenuPointAnchor, bH as MindooDBAppMenuRect, bI as MindooDBAppMenuRectAnchor, bJ as MindooDBAppMenuSelectionResult, bK as MindooDBAppMenuSeparatorItem, bL as MindooDBAppNotificationSeverity, bM as MindooDBAppNotifyInput, bN as MindooDBAppNotifyResult, bO as MindooDBAppProposeAppInput, bP as MindooDBAppProposeAppResult, bQ as MindooDBAppQueryCoverage, bR as MindooDBAppQueryInclude, bS as MindooDBAppQueryIncludeCardinality, bT as MindooDBAppQueryIncludeSlots, bU as MindooDBAppQueryResult, bV as MindooDBAppQueryRow, bW as MindooDBAppQuerySortKey, bX as MindooDBAppQueryTextClause, bY as MindooDBAppReadableAttachmentStream, bZ as MindooDBAppRecipientOptions, b_ as MindooDBAppResolvedViewDefinition, b$ as MindooDBAppResolvedViewSource, c0 as MindooDBAppRevisionPhase, c1 as MindooDBAppRevisionVerification, c2 as MindooDBAppRichTextBlockSpan, c3 as MindooDBAppRichTextGetOptions, c4 as MindooDBAppRichTextImmutableString, c5 as MindooDBAppRichTextMarkRange, c6 as MindooDBAppRichTextMaterializeValue, c7 as MindooDBAppRichTextPatch, c8 as MindooDBAppRichTextScalar, c9 as MindooDBAppRichTextSpliceStep, ca as MindooDBAppRichTextStep, cb as MindooDBAppRichTextStepPatch, cc as MindooDBAppRichTextTextSpan, cd as MindooDBAppRuntime, ce as MindooDBAppScanAttachmentOptions, cf as MindooDBAppScanAttachmentResult, cg as MindooDBAppScopedDocId, ch as MindooDBAppScopedDocumentSummary, ci as MindooDBAppSealIntent, cj as MindooDBAppSealedChannelOpenInput, ck as MindooDBAppSealedChannelOpenResult, cl as MindooDBAppSealedChannelRequestInput, cm as MindooDBAppSession, cn as MindooDBAppShowMenuInput, co as MindooDBAppShowMenuResult, cp as MindooDBAppSignPreview, cq as MindooDBAppSignPreviewScope, cr as MindooDBAppSignStatementInput, cs as MindooDBAppSignStatementResult, ct as MindooDBAppStorageApi, cu as MindooDBAppSummarySetup, cv as MindooDBAppTextCursorOptions, cw as MindooDBAppTextCursorPosition, cx as MindooDBAppTextCursorPositionsResult, cy as MindooDBAppTextCursorsResult, cz as MindooDBAppTextEdit, cA as MindooDBAppTextPatch, cB as MindooDBAppThemeMode, cC as MindooDBAppTimestampApi, cD as MindooDBAppTimestampInput, cE as MindooDBAppTimestampProvider, cF as MindooDBAppTimestampResult, cG as MindooDBAppUiPreferences, cH as MindooDBAppUpdateDocumentInput, cI as MindooDBAppViewCursorDocumentListResult, cJ as MindooDBAppViewCursorResult, cK as MindooDBAppViewEntry, cL as MindooDBAppViewEntryKind, cM as MindooDBAppViewNavigator, cN as MindooDBAppViewNavigatorExpansionState, cO as MindooDBAppViewNavigatorOpenOptions, cP as MindooDBAppViewNavigatorPageOptions, cQ as MindooDBAppViewNavigatorPageResult, cR as MindooDBAppViewNavigatorRangeQuery, cS as MindooDBAppViewNavigatorSelectionState, cT as MindooDBAppViewUpdateStats, cU as MindooDBAppViewport, cV as MindooDBAppWellKnownDragType, cW as MindooDBAppWritableAttachmentStream, cX as resolveMindooDBAppDefinitionUrl, cY as resolveMindooDBAppListingAssetUrl, cZ as resolveMindooDBAppLocalizedText, c_ as validateMindooDBAppDefinition } from './types-Dl70Tlfj.js';
3
3
  export { M as MINDOODB_APP_BUNDLE_ARCHIVE_FILE_NAME, a as MINDOODB_APP_BUNDLE_MANIFEST_FILE_NAME, b as MINDOODB_APP_BUNDLE_MANIFEST_FORMAT, c as MINDOODB_APP_BUNDLE_MANIFEST_VERSION, d as MindooDBAppBundleArchive, e as MindooDBAppBundleFileEntry, f as MindooDBAppBundleHash, g as MindooDBAppBundleManifest, h as MindooDBAppBundleManifestValidation, i as buildMindooDBAppBundleContentHashInput, j as isMindooDBAppBundleHash, n as normalizeMindooDBAppBundlePath, v as validateMindooDBAppBundleManifest } from './appBundleManifest-B0xfpaXG.js';
4
4
  import { MindooDBAppBooleanExpression } from 'mindoodb-view-language';
5
5
  export { MindooDBAppBooleanExpression, MindooDBAppExpression, MindooDBAppFilterDefinition, MindooDBAppViewCategoryChildrenPageRequest, MindooDBAppViewColumn, MindooDBAppViewColumnRole, MindooDBAppViewDefinition, MindooDBAppViewExpansionState, MindooDBAppViewExpressionBase, MindooDBAppViewExpressionDatePart, MindooDBAppViewExpressionOperation, MindooDBAppViewFieldExpression, MindooDBAppViewIfExpression, MindooDBAppViewLetExpression, MindooDBAppViewLiteralExpression, MindooDBAppViewLookupByPath, MindooDBAppViewOperationExpression, MindooDBAppViewOriginExpression, MindooDBAppViewPageRequest, MindooDBAppViewPageResult, MindooDBAppViewRow, MindooDBAppViewSortDirection, MindooDBAppViewTotalMode, MindooDBAppViewValueExpressionRef, MindooDBAppViewVariableExpression, createViewLanguage } from 'mindoodb-view-language';
@@ -166,6 +166,25 @@ declare function releaseMindooDBAppBridgeSessions(launchId?: string): void;
166
166
  */
167
167
  declare function createMindooDBAppBridge(): MindooDBAppBridge;
168
168
 
169
+ /**
170
+ * App side of agent tools: keeps the implementations, tells Haven what exists,
171
+ * and answers Haven's `agent-invoke` messages.
172
+ *
173
+ * Only descriptors cross the bridge. `execute` stays in the app and runs when
174
+ * Haven forwards an agent's call; the outcome goes back as one `agent-result`
175
+ * message per call. A tool that throws {@link MindooDBAppAgentToolError}
176
+ * reports its code; any other exception becomes `FAILED`.
177
+ *
178
+ * @module agentTools
179
+ */
180
+
181
+ /** Throw from `execute` to give the agent a code and, ideally, what to do next. */
182
+ declare class MindooDBAppAgentToolError extends Error {
183
+ readonly code: MindooDBAppAgentToolErrorCode;
184
+ readonly requiredAction?: string;
185
+ constructor(code: MindooDBAppAgentToolErrorCode, message: string, requiredAction?: string);
186
+ }
187
+
169
188
  /**
170
189
  * Haven's default host chords. Both sides of the bridge use this table so a
171
190
  * key that Haven handles on its own pages is the same key an iframe reports.
@@ -295,6 +314,64 @@ declare function buildHavenAppInstallUrl(appUrl: string, havenUrl?: string): str
295
314
  */
296
315
  declare function renderHavenAppLandingPage(options?: RenderHavenAppLandingPageOptions): Promise<HavenAppLandingPage>;
297
316
 
317
+ /**
318
+ * The Markdown subset a publisher may use in `listing.descriptionMarkdown`.
319
+ *
320
+ * The text comes from a file on the publisher's server and is shown before anyone has
321
+ * agreed to install the app, so it is parsed into a small tree here and rendered with
322
+ * `createElement`/`textContent` (or Vue render functions) — never as HTML. What the
323
+ * subset knows:
324
+ *
325
+ * - paragraphs (blank lines), headings (`#`), bullet (`-`, `*`, `+`) and numbered lists
326
+ * - `**bold**`, `__bold__`, `*italic*`, `_italic_`, `` `code` ``, `\` escapes
327
+ * - `[text](https://…)`, `[text](mailto:…)` and bare `https://…` links
328
+ *
329
+ * Anything else stays literal text. Links are limited to `https:` and `mailto:` by
330
+ * {@link sanitizeListingHref}; a link with any other target renders as its text only.
331
+ *
332
+ * DOM-free on purpose, so Haven, the landing page and build scripts can share it.
333
+ */
334
+ type ListingInline = {
335
+ type: "text";
336
+ text: string;
337
+ } | {
338
+ type: "code";
339
+ text: string;
340
+ } | {
341
+ type: "strong";
342
+ children: ListingInline[];
343
+ } | {
344
+ type: "em";
345
+ children: ListingInline[];
346
+ } | {
347
+ type: "link";
348
+ href: string;
349
+ children: ListingInline[];
350
+ };
351
+ type ListingBlock = {
352
+ type: "paragraph";
353
+ children: ListingInline[];
354
+ } | {
355
+ type: "heading";
356
+ children: ListingInline[];
357
+ } | {
358
+ type: "list";
359
+ ordered: boolean;
360
+ items: ListingInline[][];
361
+ };
362
+ /**
363
+ * `https:` and `mailto:` only. Embedded tab/LF/CR are stripped first, as browsers do,
364
+ * so `java\nscript:` cannot slip past the scheme check.
365
+ */
366
+ declare function sanitizeListingHref(raw: string): string | null;
367
+ /** Parses a description into blocks. Unknown syntax stays text; nothing is dropped. */
368
+ declare function parseListingMarkdown(markdown: string): ListingBlock[];
369
+ /**
370
+ * The same text for readers that only show plain paragraphs (`listing.description`):
371
+ * one paragraph per block and per list item, links as "text (url)".
372
+ */
373
+ declare function listingMarkdownToPlainText(markdown: string): string;
374
+
298
375
  interface InstallHavenStorageShimOptions {
299
376
  /**
300
377
  * Key prefixes whose values are written through to the host and restored on the next
@@ -501,4 +578,4 @@ declare function inheritDocumentEncryption(parent: Pick<MindooDBAppDocument, "de
501
578
  */
502
579
  declare function watchWordChunks(database: MindooDBAppDatabase, parentId: string, listener: (docIds: string[]) => void): Promise<() => Promise<void>>;
503
580
 
504
- export { type CreateMindooDBRichTextHandleOptions, type CreateMindooDBTextBufferOptions, DEFAULT_DRAG_LONG_PRESS_MS, DEFAULT_DRAG_POINTER_THRESHOLD_PX, DEFAULT_HAVEN_HOST_SHORTCUTS, DEFAULT_HAVEN_URL, type HavenAppLandingPage, type HavenStorageShimHandle, type InstallHavenStorageShimOptions, MINDOODB_APP_HOSTING_QUERY_PARAM, MINDOODB_APP_LAUNCH_ID_QUERY_PARAM, MINDOODB_APP_MAX_DRAG_PAYLOAD_BYTES, MINDOODB_APP_MAX_DRAG_PREVIEW_BYTES, MINDOODB_APP_MAX_DRAG_PREVIEW_EDGE, MINDOODB_APP_MAX_DRAG_TYPES, MINDOODB_APP_VALUE_TAG, MINIMAL_DRAG_PREVIEW_PNG, type MindooDBAppAtomicValue, MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, type MindooDBAppCounterValue, MindooDBAppCreateDocumentInput, MindooDBAppDatabase, MindooDBAppDefinition, MindooDBAppDocument, MindooDBAppDragBindSourceOptions, MindooDBAppDragInputError, MindooDBAppDragPreview, MindooDBAppDragStartInput, MindooDBAppDragStartResult, MindooDBAppHostShortcutAction, MindooDBAppHostShortcutBinding, MindooDBAppHostingMode, MindooDBAppRichTextSnapshot, MindooDBAppRichTextSpan, type MindooDBAppTimestampValue, type MindooDBAppTypedValue, MindooDBAppValue, MindooDBRichTextHandle, type MindooDBRichTextHandleChangeListener, type MindooDBRichTextHandleFlushResult, MindooDBTextBuffer, type MindooDBTextBufferFlushResult, type RenderHavenAppLandingPageOptions, abbreviateCanonicalName, applyHostedDocumentOverscrollContain, bindDragSource, buildHavenAppInstallUrl, canPreviewAttachment, createMindooDBAppBridge, createMindooDBRichTextHandle, createMindooDBTextBuffer, expandAbbreviatedName, inheritDocumentEncryption, installHavenStorageShim, installHostShortcutCapture, isHostShortcutAction, isHostedBundleRuntime, isLaunchedByHaven, isMindooDBAppDragType, matchHostShortcut, normalizeDragAccepts, normalizeDragPointerInput, normalizeDragStartInput, queryDocuments, readMindooDBAppHostingMode, readMindooDBAppLaunchId, releaseMindooDBAppBridgeSessions, renderHavenAppLandingPage, resolveCurrentHavenAppUrl, sanitizeHostShortcutBindings, snapshotElementToPng, watchWordChunks };
581
+ export { type CreateMindooDBRichTextHandleOptions, type CreateMindooDBTextBufferOptions, DEFAULT_DRAG_LONG_PRESS_MS, DEFAULT_DRAG_POINTER_THRESHOLD_PX, DEFAULT_HAVEN_HOST_SHORTCUTS, DEFAULT_HAVEN_URL, type HavenAppLandingPage, type HavenStorageShimHandle, type InstallHavenStorageShimOptions, type ListingBlock, type ListingInline, MINDOODB_APP_HOSTING_QUERY_PARAM, MINDOODB_APP_LAUNCH_ID_QUERY_PARAM, MINDOODB_APP_MAX_DRAG_PAYLOAD_BYTES, MINDOODB_APP_MAX_DRAG_PREVIEW_BYTES, MINDOODB_APP_MAX_DRAG_PREVIEW_EDGE, MINDOODB_APP_MAX_DRAG_TYPES, MINDOODB_APP_VALUE_TAG, MINIMAL_DRAG_PREVIEW_PNG, MindooDBAppAgentToolError, MindooDBAppAgentToolErrorCode, type MindooDBAppAtomicValue, MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, type MindooDBAppCounterValue, MindooDBAppCreateDocumentInput, MindooDBAppDatabase, MindooDBAppDefinition, MindooDBAppDocument, MindooDBAppDragBindSourceOptions, MindooDBAppDragInputError, MindooDBAppDragPreview, MindooDBAppDragStartInput, MindooDBAppDragStartResult, MindooDBAppHostShortcutAction, MindooDBAppHostShortcutBinding, MindooDBAppHostingMode, MindooDBAppRichTextSnapshot, MindooDBAppRichTextSpan, type MindooDBAppTimestampValue, type MindooDBAppTypedValue, MindooDBAppValue, MindooDBRichTextHandle, type MindooDBRichTextHandleChangeListener, type MindooDBRichTextHandleFlushResult, MindooDBTextBuffer, type MindooDBTextBufferFlushResult, type RenderHavenAppLandingPageOptions, abbreviateCanonicalName, applyHostedDocumentOverscrollContain, bindDragSource, buildHavenAppInstallUrl, canPreviewAttachment, createMindooDBAppBridge, createMindooDBRichTextHandle, createMindooDBTextBuffer, expandAbbreviatedName, inheritDocumentEncryption, installHavenStorageShim, installHostShortcutCapture, isHostShortcutAction, isHostedBundleRuntime, isLaunchedByHaven, isMindooDBAppDragType, listingMarkdownToPlainText, matchHostShortcut, normalizeDragAccepts, normalizeDragPointerInput, normalizeDragStartInput, parseListingMarkdown, queryDocuments, readMindooDBAppHostingMode, readMindooDBAppLaunchId, releaseMindooDBAppBridgeSessions, renderHavenAppLandingPage, resolveCurrentHavenAppUrl, sanitizeHostShortcutBindings, sanitizeListingHref, snapshotElementToPng, watchWordChunks };