mindoodb-app-sdk 0.0.63 → 0.0.65
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/TESTING.md +38 -1
- package/dist/testing/index.d.ts +169 -4
- package/dist/testing/index.js +1169 -153
- package/package.json +1 -1
package/TESTING.md
CHANGED
|
@@ -108,6 +108,24 @@ Each database entry can provide:
|
|
|
108
108
|
- `methods.attachments`
|
|
109
109
|
- `fulltextSetup` — the initial config returned by `db.getFulltextSetup()`; `db.setFulltextSetup()` overwrites it for the lifetime of the handle. Use this to test your app's full-text bootstrap logic. Note the mock evaluates `text` query clauses regardless of this config.
|
|
110
110
|
- `summarySetup` — the initial config returned by `db.getSummarySetup()`; `db.setSummarySetup()` overwrites it for the lifetime of the handle. The mock's `query()` reads seeded documents directly and ignores this config; use it to test your app's summary bootstrap logic.
|
|
111
|
+
- `automerge: true` — back every document with a real Automerge document, as Haven does (off by default: plain JSON with `mock-head-N` heads). `create`/`update` then return real Automerge heads, `update` applies `set`/`unset`, `json` (with `Automerge.changeAt(json.baseHeads)` when given) and `text` patches as Automerge changes with Haven's rules (missing parents and lists are created, `unset` is idempotent, `counterIncrement` needs a counter, an empty `json` patch is rejected), and `get`/`list`/`query` return the plain projection (atomic strings as strings, counters as numbers, timestamps as ISO strings). `richText` snapshots replace the value at their path and `richTextSteps` are spliced into the text without marks. Seeds are built with a fixed actor, so two mocks from the same seed have identical heads. `mockDatabasesFromDefinition(definition, seed, { automerge: true })` and the test host URL setting `automerge=1` turn it on, too.
|
|
112
|
+
|
|
113
|
+
#### Concurrent edits from another device
|
|
114
|
+
|
|
115
|
+
`applyRemoteUpdate(databaseId, docId, input, { actor? })` on the controller (`createMockMindooDBAppSession`, `createFakeBridgeHost`, the browser test host and `window.__havenTestHost`) writes `input` as another device and syncs it in; live queries update as after any write. With `automerge: true` the device holds the history up to `input.json.baseHeads` (plus its own earlier changes) and writes as its own Automerge actor, so its edit truly merges with an app save at the same heads:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const doc = await database.documents.get("sheet-1"); // heads H
|
|
119
|
+
await mock.applyRemoteUpdate("main", "sheet-1", { // device B, at H
|
|
120
|
+
json: { baseHeads: doc!.heads, listInsert: [{ path: ["rows"], index: 1, values: ["remote"] }] },
|
|
121
|
+
});
|
|
122
|
+
const saved = await database.documents.update("sheet-1", { // the app, also at H
|
|
123
|
+
json: { baseHeads: doc!.heads, listInsert: [{ path: ["rows"], index: 1, values: ["local"] }] },
|
|
124
|
+
});
|
|
125
|
+
// saved.data.rows keeps both entries; saved.heads has two heads
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The relative order of concurrent inserts at the same index follows Automerge's op ids, as in Haven. Without `automerge`, `applyRemoteUpdate` is a plain update.
|
|
111
129
|
|
|
112
130
|
### Evaluating VirtualViews
|
|
113
131
|
|
|
@@ -344,6 +362,7 @@ The page shows the app next to a control panel:
|
|
|
344
362
|
- **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
363
|
- **Directory**: fills the tenant directory with 0 to 500 generated users (`CN=Test User 001/O=Test`, …) for recipient pickers and paging.
|
|
346
364
|
- **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.
|
|
365
|
+
- **Agent tools**: the tools the app declared with `session.agent.registerTools()` (with the prefix agents see, `read-only` and `asks first` tags, description and input schema), a form to call one with a JSON input as an agent would, and the result as the agent gets it (images in the result are shown). Tools marked `consequentialHint` go through a confirm, like Haven's consent dialog. A checkbox switches agent access off. **Agent files** imports files for the app (each gets a `fileRef` for `takeFile`) and lists the files the app handed over with `provideFile` for download. **Agent context** shows what the app last passed to `setContext`.
|
|
347
366
|
- 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
367
|
|
|
349
368
|
`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:
|
|
@@ -363,7 +382,7 @@ mountHavenTestHost({
|
|
|
363
382
|
});
|
|
364
383
|
```
|
|
365
384
|
|
|
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`:
|
|
385
|
+
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; `automerge=1` backs all databases with Automerge documents; URL settings win over the options). The same controls are scriptable as `window.__havenTestHost`:
|
|
367
386
|
|
|
368
387
|
```ts
|
|
369
388
|
await page.goto("/__haven-test/?enforce=1");
|
|
@@ -375,8 +394,26 @@ await page.evaluate(() => window.__havenTestHost!.setLocale("de-DE"));
|
|
|
375
394
|
await page.evaluate(() => window.__havenTestHost!.setNextScan({ fileName: "receipt.pdf", mimeType: "application/pdf", size: 1024 }));
|
|
376
395
|
await app.getByRole("button", { name: "Scan" }).click();
|
|
377
396
|
expect(await page.evaluate(() => window.__havenTestHost!.log.scans)).toHaveLength(1);
|
|
397
|
+
|
|
398
|
+
// with ?automerge=1: another device edits the document the app has open
|
|
399
|
+
await page.evaluate(() => window.__havenTestHost!.applyRemoteUpdate("main", "sheet-1", { set: { title: "Renamed elsewhere" } }));
|
|
378
400
|
```
|
|
379
401
|
|
|
402
|
+
Agent tools are scriptable through `window.__havenTestHost.agent`, the same controller the Vitest helpers expose as `createFakeBridgeHost().agent`:
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
const agent = () => window.__havenTestHost!.agent;
|
|
406
|
+
const fileRef = await page.evaluate(() =>
|
|
407
|
+
agent().importFile({ name: "logo.png", mimeType: "image/png", data: new Uint8Array([137, 80, 78, 71]) }),
|
|
408
|
+
);
|
|
409
|
+
const added = await page.evaluate((ref) => agent().call("image_add", { fileRef: ref }), fileRef);
|
|
410
|
+
expect(added).toMatchObject({ ok: true });
|
|
411
|
+
const exported = await page.evaluate(() => agent().call("deck_export", { format: "pptx" }));
|
|
412
|
+
const file = await page.evaluate((ref) => agent().getFile(ref)?.name, (exported as any).result.files[0].fileRef);
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
`call()` takes the tool's own name or the prefixed one and never throws: failures come back as `{ ok: false, error: { code, message, requiredAction } }`, the codes an agent sees. The mock follows Haven: tool declarations are validated (name, at most 64 tools, 2000-character descriptions, an object `inputSchema`), the prefix is the definition's `agentToolPrefix` (pass it as the `agentToolPrefix` option) or derived from the app id, an app can only `takeFile()` what was imported for it, and file refs expire after ten minutes. `setConsent("allow" | "deny" | fn)` answers the consent step in scripts, `setEnabled(false)` switches access off, and `calls()` lists every call with its outcome.
|
|
416
|
+
|
|
380
417
|
`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
418
|
|
|
382
419
|
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.
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ay as MindooDBAppComponentInfo, bq as MindooDBAppEmbedRect, aU as MindooDBAppCreateViewNavigatorInput, de as MindooDBAppViewNavigator, ad as MindooDBAppBridgeRpcRequest, bC as MindooDBAppHostTheme, av as MindooDBAppCapability, j as MindooDBAppDefinition, J as MindooDBAppAttachmentApi, e as MindooDBAppBridge, cQ as MindooDBAppSession, cg as MindooDBAppProposeAppInput, dm as MindooDBAppViewport, d8 as MindooDBAppUiPreferences, cm as MindooDBAppQueryResult, dl as MindooDBAppViewUpdateStats, a9 as MindooDBAppBridgePortMessage, aV as MindooDBAppDatabaseInfo, bl as MindooDBAppEmbedCloseReason, a4 as MindooDBAppBridgeErrorPayload, bX as MindooDBAppLaunchContext, b2 as MindooDBAppDocumentApi, dg as MindooDBAppViewNavigatorOpenOptions, bD as MindooDBAppIdentityApi, d4 as MindooDBAppTimestampApi, b0 as MindooDBAppDirectoryApi,
|
|
1
|
+
import { ay as MindooDBAppComponentInfo, bq as MindooDBAppEmbedRect, I as MindooDBAppAgentToolDescriptor, f as MindooDBAppAgentToolErrorCode, V as MindooDBAppBridgeAgentResultMessage, U as MindooDBAppBridgeAgentInvokeMessage, aU as MindooDBAppCreateViewNavigatorInput, de as MindooDBAppViewNavigator, ad as MindooDBAppBridgeRpcRequest, bC as MindooDBAppHostTheme, av as MindooDBAppCapability, d9 as MindooDBAppUpdateDocumentInput, l as MindooDBAppDocument, j as MindooDBAppDefinition, J as MindooDBAppAttachmentApi, e as MindooDBAppBridge, cQ as MindooDBAppSession, cg as MindooDBAppProposeAppInput, dm as MindooDBAppViewport, d8 as MindooDBAppUiPreferences, cm as MindooDBAppQueryResult, dl as MindooDBAppViewUpdateStats, a9 as MindooDBAppBridgePortMessage, aV as MindooDBAppDatabaseInfo, bl as MindooDBAppEmbedCloseReason, a4 as MindooDBAppBridgeErrorPayload, bX as MindooDBAppLaunchContext, b2 as MindooDBAppDocumentApi, dg as MindooDBAppViewNavigatorOpenOptions, bD as MindooDBAppIdentityApi, d4 as MindooDBAppTimestampApi, b0 as MindooDBAppDirectoryApi, bz as MindooDBAppFulltextSetup, by as MindooDBAppExtractionSetup, cY as MindooDBAppSummarySetup, ch as MindooDBAppProposeAppResult, bN as MindooDBAppIncomingSource, c as MindooDBAppDragStartResult, bj as MindooDBAppDragProfile, bM as MindooDBAppIncomingResult } from '../types-BeRUxGKN.js';
|
|
2
2
|
import * as mindoodb from 'mindoodb';
|
|
3
3
|
import 'mindoodb-view-language';
|
|
4
4
|
|
|
@@ -21,6 +21,118 @@ interface MockEmbeddingFinish {
|
|
|
21
21
|
message?: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Haven's side of agent tools, for tests: what `session.agent` talks to.
|
|
26
|
+
*
|
|
27
|
+
* It accepts the app's tool declarations and context with Haven's validation, keeps
|
|
28
|
+
* the files the app hands over (`provideFile`), lets a test hand the app files the way
|
|
29
|
+
* Haven imports them from the exchange folder (`takeFile`), and calls the app's tools
|
|
30
|
+
* over the bridge port like Haven's broker, including the consent step for tools
|
|
31
|
+
* marked `consequentialHint`.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** A file in the mock exchange: handed over by the app, or imported for it by the test. */
|
|
35
|
+
interface MockAgentFile {
|
|
36
|
+
fileRef: string;
|
|
37
|
+
name: string;
|
|
38
|
+
mimeType: string;
|
|
39
|
+
data: Uint8Array;
|
|
40
|
+
/** `app`: the app produced it (`provideFile`); `host`: imported for the app (`takeFile`). */
|
|
41
|
+
source: "app" | "host";
|
|
42
|
+
createdAt: number;
|
|
43
|
+
expiresAt: number;
|
|
44
|
+
}
|
|
45
|
+
/** How Haven's consent dialog answers a call to a consequential tool. */
|
|
46
|
+
type MockAgentConsent = "allow" | "deny" | ((call: {
|
|
47
|
+
tool: string;
|
|
48
|
+
input: Record<string, unknown>;
|
|
49
|
+
}) => boolean | Promise<boolean>);
|
|
50
|
+
type MockAgentCallResult = {
|
|
51
|
+
ok: true;
|
|
52
|
+
result: unknown;
|
|
53
|
+
durationMs: number;
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
error: {
|
|
57
|
+
code: MindooDBAppAgentToolErrorCode | "LOCKED" | string;
|
|
58
|
+
message: string;
|
|
59
|
+
requiredAction?: string;
|
|
60
|
+
};
|
|
61
|
+
durationMs: number;
|
|
62
|
+
};
|
|
63
|
+
/** One tool call as the log records it. */
|
|
64
|
+
interface MockAgentCall {
|
|
65
|
+
callId: string;
|
|
66
|
+
tool: string;
|
|
67
|
+
input: Record<string, unknown>;
|
|
68
|
+
startedAt: number;
|
|
69
|
+
outcome?: MockAgentCallResult;
|
|
70
|
+
}
|
|
71
|
+
interface MockAgentHostOptions {
|
|
72
|
+
/**
|
|
73
|
+
* The prefix agents see in front of the app's tool names (`agentToolPrefix` in
|
|
74
|
+
* `haven-app.json`). Without one it is derived from the app id, as Haven does.
|
|
75
|
+
*/
|
|
76
|
+
agentToolPrefix?: string;
|
|
77
|
+
/** Whether the user has agent access on (`registerTools` answers `enabled`). Default true. */
|
|
78
|
+
agentToolsEnabled?: boolean;
|
|
79
|
+
/** Answer of the consent dialog for consequential tools. Default `"allow"`. */
|
|
80
|
+
agentConsent?: MockAgentConsent;
|
|
81
|
+
/** How long a call waits for the app. Default 120 s, Haven's limit. */
|
|
82
|
+
agentInvokeTimeoutMs?: number;
|
|
83
|
+
}
|
|
84
|
+
interface MockAgentHostController {
|
|
85
|
+
/** The app's tools as it declared them (without prefix). */
|
|
86
|
+
tools(): MindooDBAppAgentToolDescriptor[];
|
|
87
|
+
/** The names agents see: `<prefix>_<name>`. */
|
|
88
|
+
exposedNames(): string[];
|
|
89
|
+
readonly prefix: string;
|
|
90
|
+
/** What the app last passed to `setContext`. */
|
|
91
|
+
context(): Record<string, unknown> | null;
|
|
92
|
+
isEnabled(): boolean;
|
|
93
|
+
setEnabled(enabled: boolean): void;
|
|
94
|
+
setConsent(consent: MockAgentConsent): void;
|
|
95
|
+
/**
|
|
96
|
+
* Calls one of the app's tools as an agent would, by its own name or the prefixed
|
|
97
|
+
* one. Never throws: failures come back as `{ ok: false, error }` with the code the
|
|
98
|
+
* agent would see.
|
|
99
|
+
*/
|
|
100
|
+
call(tool: string, input?: Record<string, unknown>): Promise<MockAgentCallResult>;
|
|
101
|
+
/** Every call so far, oldest first. */
|
|
102
|
+
calls(): ReadonlyArray<MockAgentCall>;
|
|
103
|
+
/** Puts a file in the exchange for the app, as Haven's `haven_files_import`; returns its fileRef. */
|
|
104
|
+
importFile(file: {
|
|
105
|
+
name: string;
|
|
106
|
+
mimeType?: string;
|
|
107
|
+
data: Uint8Array | ArrayBuffer | Blob | string;
|
|
108
|
+
}): Promise<string>;
|
|
109
|
+
/** A file the app handed over (`provideFile`), or `null` when unknown or expired. */
|
|
110
|
+
getFile(fileRef: string): MockAgentFile | null;
|
|
111
|
+
/** Files in the exchange (both directions), newest first. */
|
|
112
|
+
files(): MockAgentFile[];
|
|
113
|
+
}
|
|
114
|
+
/** Haven's derivation when the app declares no prefix (`agentAppKey`). */
|
|
115
|
+
declare function mockAgentToolPrefix(appId: string, declared?: string): string;
|
|
116
|
+
/** Haven's checks on declared tools (`validateAgentToolDescriptors`). */
|
|
117
|
+
declare function validateMockAgentTools(raw: unknown): MindooDBAppAgentToolDescriptor[];
|
|
118
|
+
interface MockAgentHost {
|
|
119
|
+
controller: MockAgentHostController;
|
|
120
|
+
/** Answers `agent.*` requests; `undefined` for any other method. */
|
|
121
|
+
dispatch(method: string, params: unknown): Promise<{
|
|
122
|
+
result: unknown;
|
|
123
|
+
} | undefined>;
|
|
124
|
+
/** The app's `agent-result` message. */
|
|
125
|
+
handleResult(message: MindooDBAppBridgeAgentResultMessage): void;
|
|
126
|
+
/** Fails pending calls (the app closed or reloaded). */
|
|
127
|
+
reset(reason?: string): void;
|
|
128
|
+
}
|
|
129
|
+
declare function createMockAgentHost(options: MockAgentHostOptions & {
|
|
130
|
+
appId: () => string;
|
|
131
|
+
/** Posts to the app's port; `false` when no app is connected. */
|
|
132
|
+
post(message: MindooDBAppBridgeAgentInvokeMessage): boolean;
|
|
133
|
+
onChange?(): void;
|
|
134
|
+
}): MockAgentHost;
|
|
135
|
+
|
|
24
136
|
type EvaluatingViewDocument = {
|
|
25
137
|
origin: string;
|
|
26
138
|
docId: string;
|
|
@@ -105,6 +217,12 @@ interface CreateBrowserTestHostOptions extends CreateFakeBridgeHostOptions {
|
|
|
105
217
|
interface BrowserTestHost {
|
|
106
218
|
host: FakeBridgeHostController;
|
|
107
219
|
log: BrowserTestHostLog;
|
|
220
|
+
/**
|
|
221
|
+
* Haven's agent-tool side (same as `host.agent`): the app's declared tools and
|
|
222
|
+
* context, `call(tool, input)` as an agent would, `importFile()` to hand the app a
|
|
223
|
+
* file for `takeFile`, and `getFile()` for what it handed over with `provideFile`.
|
|
224
|
+
*/
|
|
225
|
+
agent: MockAgentHostController;
|
|
108
226
|
/**
|
|
109
227
|
* Decides the outcome of the app's next `attachments.scan()`: a file to "scan", or
|
|
110
228
|
* `null` to act as if the user cancelled. Later scans follow {@link setScanMode}.
|
|
@@ -126,6 +244,14 @@ interface BrowserTestHost {
|
|
|
126
244
|
setEnforceCapabilities(enforce: boolean): void;
|
|
127
245
|
/** Replaces the usernames of the tenant directory (`directory.listUsers()`). */
|
|
128
246
|
setDirectoryUsers(users: readonly string[]): void;
|
|
247
|
+
/**
|
|
248
|
+
* Another device edits a document and the change syncs in: the app's live queries
|
|
249
|
+
* update. With Automerge-backed databases (`automerge=1` / `automerge: true`) the
|
|
250
|
+
* edit is made at `input.json.baseHeads` by another actor and merged, so it is
|
|
251
|
+
* concurrent to app saves at the same heads. See
|
|
252
|
+
* `MockMindooDBAppSessionController.applyRemoteUpdate`.
|
|
253
|
+
*/
|
|
254
|
+
applyRemoteUpdate(databaseId: string, docId: string, input: MindooDBAppUpdateDocumentInput, options?: MockRemoteUpdateOptions): Promise<MindooDBAppDocument>;
|
|
129
255
|
/** Reloads the app frame. The mock data survives; the app's in-memory state does not. */
|
|
130
256
|
reloadApp(): void;
|
|
131
257
|
dispose(): void;
|
|
@@ -153,6 +279,8 @@ interface MockDatabasesFromDefinitionOptions {
|
|
|
153
279
|
* `"none"`: the mock's stateless default.
|
|
154
280
|
*/
|
|
155
281
|
attachments?: "memory" | "none";
|
|
282
|
+
/** Back documents with real Automerge documents (`MockMindooDBAppDatabaseDefinition.automerge`). */
|
|
283
|
+
automerge?: boolean;
|
|
156
284
|
}
|
|
157
285
|
/**
|
|
158
286
|
* Mock databases for every database a `haven-app.json` declares, granted as requested
|
|
@@ -166,10 +294,13 @@ declare function mockDatabasesFromDefinition(definition: Pick<MindooDBAppDefinit
|
|
|
166
294
|
* - `enforce=1` turns the capability checks on
|
|
167
295
|
* - `users=<count>` fills the directory with generated users
|
|
168
296
|
* - `locale=<tag>`, `theme=dark|light`
|
|
297
|
+
* - `automerge=1` backs every database with real Automerge documents (concurrent
|
|
298
|
+
* `baseHeads` merges, real heads); `automerge=0` turns it off
|
|
169
299
|
*/
|
|
170
300
|
interface TestHostUrlSettings {
|
|
171
301
|
overrides: Record<string, MockDatabaseOverride>;
|
|
172
302
|
enforceCapabilities?: boolean;
|
|
303
|
+
automerge?: boolean;
|
|
173
304
|
directoryUserCount?: number;
|
|
174
305
|
locale?: string;
|
|
175
306
|
theme?: "dark" | "light";
|
|
@@ -187,7 +318,7 @@ interface MountHavenTestHostOptions extends Omit<CreateBrowserTestHostOptions, "
|
|
|
187
318
|
label: string;
|
|
188
319
|
}>;
|
|
189
320
|
/**
|
|
190
|
-
* Read `db=`, `enforce=`, `users=`, `locale=` and `
|
|
321
|
+
* Read `db=`, `enforce=`, `users=`, `locale=`, `theme=` and `automerge=` from the page URL (see
|
|
191
322
|
* {@link readTestHostUrlSettings}) and keep the URL in sync with the panel. Default
|
|
192
323
|
* true. URL settings win over the options passed here.
|
|
193
324
|
*/
|
|
@@ -295,6 +426,22 @@ interface MockMindooDBAppDatabaseDefinition {
|
|
|
295
426
|
* results the same way they would in Haven.
|
|
296
427
|
*/
|
|
297
428
|
summarySetup?: MindooDBAppSummarySetup | null;
|
|
429
|
+
/**
|
|
430
|
+
* Back every document with a real Automerge document, like Haven: `update`
|
|
431
|
+
* applies `set`/`unset`, `json` (at `json.baseHeads`) and `text` patches as
|
|
432
|
+
* Automerge changes, heads are real Automerge heads, and `applyRemoteUpdate`
|
|
433
|
+
* on the controller writes as another device so concurrent edits truly
|
|
434
|
+
* merge. Off by default (plain JSON with `mock-head-N` heads).
|
|
435
|
+
*/
|
|
436
|
+
automerge?: boolean;
|
|
437
|
+
}
|
|
438
|
+
/** Options of `applyRemoteUpdate`. */
|
|
439
|
+
interface MockRemoteUpdateOptions {
|
|
440
|
+
/**
|
|
441
|
+
* Automerge actor id (hex) of the simulated device. Defaults to one fixed
|
|
442
|
+
* "remote" actor; pass different ids to simulate several devices.
|
|
443
|
+
*/
|
|
444
|
+
actor?: string;
|
|
298
445
|
}
|
|
299
446
|
/**
|
|
300
447
|
* Stands in for the host-owned sealed channel.
|
|
@@ -379,6 +526,15 @@ interface MockMindooDBAppSessionController {
|
|
|
379
526
|
setEnforceCapabilities(enforce: boolean): void;
|
|
380
527
|
/** Replaces the directory's usernames (see `directoryUsers`). */
|
|
381
528
|
setDirectoryUsers(users: readonly string[]): void;
|
|
529
|
+
/**
|
|
530
|
+
* Writes `input` to a document as another device would, then syncs it in:
|
|
531
|
+
* live queries update like after any write. With `automerge: true` on the
|
|
532
|
+
* database the edit is made by a different Automerge actor on the history
|
|
533
|
+
* up to `input.json.baseHeads` (the current state when omitted) and merged,
|
|
534
|
+
* so it is truly concurrent to app writes at the same heads. Without it, it
|
|
535
|
+
* is a plain update. Bypasses capability checks (it is not the app writing).
|
|
536
|
+
*/
|
|
537
|
+
applyRemoteUpdate(databaseId: string, docId: string, input: MindooDBAppUpdateDocumentInput, options?: MockRemoteUpdateOptions): Promise<MindooDBAppDocument>;
|
|
382
538
|
emitThemeChange(theme: MindooDBAppHostTheme): void;
|
|
383
539
|
emitViewportChange(viewport: MindooDBAppViewport): void;
|
|
384
540
|
emitUiPreferencesChange(uiPreferences: MindooDBAppUiPreferences): void;
|
|
@@ -451,8 +607,10 @@ type FakeBridgeRpcResponse = {
|
|
|
451
607
|
error: MindooDBAppBridgeErrorPayload;
|
|
452
608
|
durationMs: number;
|
|
453
609
|
};
|
|
454
|
-
interface CreateFakeBridgeHostOptions extends CreateMockMindooDBAppSessionOptions {
|
|
610
|
+
interface CreateFakeBridgeHostOptions extends CreateMockMindooDBAppSessionOptions, MockAgentHostOptions {
|
|
455
611
|
windowMode?: "parent" | "opener";
|
|
612
|
+
/** Called when the app's agent tools, context or exchange files change, and after each tool call. */
|
|
613
|
+
onAgentChange?: () => void;
|
|
456
614
|
requestHandlers?: Record<string, FakeBridgeRequestHandler>;
|
|
457
615
|
/** Called for every RPC request the app sends, before it is answered. */
|
|
458
616
|
onRequest?: (request: MindooDBAppBridgeRpcRequest) => void;
|
|
@@ -502,6 +660,8 @@ interface FakeBridgeHostController {
|
|
|
502
660
|
/** See {@link CreateMockMindooDBAppSessionOptions.directoryUsers}. */
|
|
503
661
|
setDirectoryUsers(users: readonly string[]): void;
|
|
504
662
|
getDirectoryUsers(): string[];
|
|
663
|
+
/** See {@link MockMindooDBAppSessionController.applyRemoteUpdate}. */
|
|
664
|
+
applyRemoteUpdate(databaseId: string, docId: string, input: MindooDBAppUpdateDocumentInput, options?: MockRemoteUpdateOptions): Promise<MindooDBAppDocument>;
|
|
505
665
|
/** Embeds the app has open (`session.embeds.open`). */
|
|
506
666
|
listEmbeds(): MockEmbedState[];
|
|
507
667
|
/** Closes an embed and pushes the `embed-event` to the app. */
|
|
@@ -519,7 +679,12 @@ interface FakeBridgeHostController {
|
|
|
519
679
|
* over the port and resolves or rejects with the app's answer.
|
|
520
680
|
*/
|
|
521
681
|
requestEmbeddingSave(): Promise<void>;
|
|
682
|
+
/**
|
|
683
|
+
* Haven's agent-tool side: the tools and context the app declared, files in the
|
|
684
|
+
* exchange, and `call()` to run a tool as an agent would.
|
|
685
|
+
*/
|
|
686
|
+
readonly agent: MockAgentHostController;
|
|
522
687
|
}
|
|
523
688
|
declare function createFakeBridgeHost(options?: CreateFakeBridgeHostOptions): FakeBridgeHostController;
|
|
524
689
|
|
|
525
|
-
export { ALL_CAPABILITIES, type BrowserTestHost, type BrowserTestHostLog, type BrowserTestHostScan, type BrowserTestHostScanMode, type CreateBrowserTestHostOptions, type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type EvaluatingViewDocument, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type FakeBridgeRpcResponse, type MockDatabaseOverride, type MockDatabasesFromDefinitionOptions, type MockEmbedState, type MockEmbeddingFinish, MockForbiddenError, type MockIncomingContentInput, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, type MockSealedChannelOptions, type MockSeedDocument, type MountHavenTestHostOptions, TEST_HOST_LOCALES, type TestHostUrlSettings, capabilitiesForDefinitionPermissions, createBrowserTestHost, createEvaluatingViewNavigator, createFakeBridgeHost, createMemoryAttachments, createMockMindooDBAppBridge, createMockMindooDBAppSession, generateDirectoryUsers, loadMindoodbForTesting, mockDatabasesFromDefinition, mountHavenTestHost, previewJson, readTestHostUrlSettings };
|
|
690
|
+
export { ALL_CAPABILITIES, type BrowserTestHost, type BrowserTestHostLog, type BrowserTestHostScan, type BrowserTestHostScanMode, type CreateBrowserTestHostOptions, type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type EvaluatingViewDocument, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type FakeBridgeRpcResponse, type MockAgentCall, type MockAgentCallResult, type MockAgentConsent, type MockAgentFile, type MockAgentHost, type MockAgentHostController, type MockAgentHostOptions, type MockDatabaseOverride, type MockDatabasesFromDefinitionOptions, type MockEmbedState, type MockEmbeddingFinish, MockForbiddenError, type MockIncomingContentInput, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, type MockRemoteUpdateOptions, type MockSealedChannelOptions, type MockSeedDocument, type MountHavenTestHostOptions, TEST_HOST_LOCALES, type TestHostUrlSettings, capabilitiesForDefinitionPermissions, createBrowserTestHost, createEvaluatingViewNavigator, createFakeBridgeHost, createMemoryAttachments, createMockAgentHost, createMockMindooDBAppBridge, createMockMindooDBAppSession, generateDirectoryUsers, loadMindoodbForTesting, mockAgentToolPrefix, mockDatabasesFromDefinition, mountHavenTestHost, previewJson, readTestHostUrlSettings, validateMockAgentTools };
|