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 +120 -55
- package/TESTING.md +36 -2
- package/dist/{chunk-6NTVTL6G.js → chunk-S73KTYZF.js} +139 -6
- package/dist/index.d.ts +80 -3
- package/dist/index.js +276 -8
- package/dist/testing/index.d.ts +170 -10
- package/dist/testing/index.js +731 -62
- package/dist/{types-CsKw_niD.d.ts → types-Dl70Tlfj.d.ts} +144 -2
- package/dist/vite/index.d.ts +18 -5
- package/dist/vite/index.js +156 -2
- package/package.json +1 -1
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
763
|
-
|
|
764
|
-
|
|
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
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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:
|
|
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
|
-
|
|
1497
|
-
|
|
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
|
-
|
|
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
|
|
2
|
-
export {
|
|
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 };
|