@agentshouse/mdruntime 0.1.0-cd3486bd400ed → 0.1.0-cd37f80239af0
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 +21 -9
- package/dist/adapter.d.ts +149 -46
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/attempt.d.ts.map +1 -1
- package/dist/attempt.js +14 -1
- package/dist/binary.d.ts +18 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +8 -0
- package/dist/bootstrap.d.ts +27 -11
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +184 -84
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -14
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -62
- package/dist/change.d.ts +41 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +34 -0
- package/dist/client.d.ts +31 -13
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +103 -7
- package/dist/collection.d.ts +10 -7
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +38 -79
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +786 -0
- package/dist/connection.d.ts +50 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3786 -931
- package/dist/conversation.d.ts +37 -16
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +700 -257
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/durability.d.ts +4 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +20 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +151 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/fulltext.d.ts +27 -0
- package/dist/fulltext.d.ts.map +1 -0
- package/dist/fulltext.js +370 -0
- package/dist/host.d.ts +13 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +130 -17
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +17 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +123 -0
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +218 -0
- package/dist/memory.d.ts +17 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +231 -91
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +90 -0
- package/dist/model.d.ts +9 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +8 -2
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +20 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +113 -12
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/outcome.d.ts +52 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +46 -0
- package/dist/overlay.d.ts +15 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +129 -177
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +68 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +48 -7
- package/dist/reach.d.ts +18 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +224 -55
- package/dist/react.d.ts +9 -6
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/readiness.d.ts +52 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +27 -0
- package/dist/recovery.d.ts +26 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +224 -0
- package/dist/refresh.d.ts +17 -14
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +136 -56
- package/dist/replica.d.ts +58 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +307 -159
- package/dist/room-draft.d.ts +51 -4
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +210 -18
- package/dist/rows.d.ts +37 -35
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +173 -102
- package/dist/save.d.ts +70 -3
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +805 -147
- package/dist/search.d.ts +39 -28
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +37 -105
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +15 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +421 -0
- package/dist/status.d.ts +5 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +107 -80
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +325 -461
- package/dist/stored.d.ts +130 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +560 -0
- package/dist/tables.d.ts +325 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +578 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/turn.d.ts +9 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +75 -0
- package/dist/validation.d.ts +29 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +101 -0
- package/dist/windows.d.ts +22 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +89 -0
- package/dist/wire.d.ts +165 -30
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +56 -29
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +156 -0
- package/package.json +26 -15
- package/AGENTS.md +0 -290
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
- package/dist/chat/acts.d.ts +0 -34
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/messages.d.ts +0 -21
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -151
- package/dist/chat/overlay.d.ts +0 -31
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -97
- package/dist/chat/parts.d.ts +0 -57
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -119
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -57
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -637
- package/dist/chat/questions.d.ts +0 -31
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/questions.js +0 -111
- package/dist/chat/read.d.ts +0 -5
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/read.js +0 -13
- package/dist/chat.d.ts +0 -7
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -2
- package/dist/read-side.d.ts +0 -18
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -433
package/dist/query.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { pointerFacts, } from '@agentshouse/mdmodel';
|
|
2
2
|
import { referenceField } from './model.js';
|
|
3
3
|
import { normalize } from './paths.js';
|
|
4
|
+
import { decodedCursor } from './windows.js';
|
|
4
5
|
export class QueryError extends Error {
|
|
5
6
|
code;
|
|
6
7
|
retryable = false;
|
|
@@ -11,9 +12,18 @@ export class QueryError extends Error {
|
|
|
11
12
|
}
|
|
12
13
|
const RANGE = ['$gt', '$gte', '$lt', '$lte'];
|
|
13
14
|
const SINGLE = ['$eq', '$ne', '$in', '$nin', '$all', '$size', '$exists'];
|
|
14
|
-
const FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'hop', 'backlinks'];
|
|
15
|
+
const FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'folder', 'paths', 'hop', 'backlinks'];
|
|
15
16
|
const RELATED = ['types', 'where', 'pathPrefix', 'field'];
|
|
16
|
-
const PARTS = [
|
|
17
|
+
const PARTS = [
|
|
18
|
+
'fields',
|
|
19
|
+
'sections',
|
|
20
|
+
'preamble',
|
|
21
|
+
'markdown',
|
|
22
|
+
'backlinks',
|
|
23
|
+
'change',
|
|
24
|
+
'fileId',
|
|
25
|
+
'revision',
|
|
26
|
+
];
|
|
17
27
|
const ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];
|
|
18
28
|
const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
19
29
|
const STRAY_ESCAPE = /~(?![01])/u;
|
|
@@ -60,6 +70,13 @@ function names(input, at) {
|
|
|
60
70
|
invalid(at, 'expects a list of names');
|
|
61
71
|
return [...new Set(listed)].sort();
|
|
62
72
|
}
|
|
73
|
+
function pathsOf(input) {
|
|
74
|
+
const listed = list(input, 'paths');
|
|
75
|
+
if (listed.some((item) => typeof item !== 'string' || item === '' || normalize(item) !== item)) {
|
|
76
|
+
invalid('paths', 'expects a list of Paths');
|
|
77
|
+
}
|
|
78
|
+
return [...new Set(listed)].sort();
|
|
79
|
+
}
|
|
63
80
|
function directory(input, at) {
|
|
64
81
|
if (typeof input !== 'string' || normalize(input) !== input) {
|
|
65
82
|
invalid(at, 'expects a normalized directory');
|
|
@@ -279,15 +296,16 @@ function backlinksOf(facts, rooms, input) {
|
|
|
279
296
|
return { types, where, pathPrefix, field };
|
|
280
297
|
}
|
|
281
298
|
function keyPlan(typed, input, at, path) {
|
|
282
|
-
if (input === 'room' || input === 'type' || (path && input === 'path'))
|
|
299
|
+
if (input === 'room' || input === 'type' || input === 'folder' || (path && input === 'path')) {
|
|
283
300
|
return { of: input };
|
|
301
|
+
}
|
|
284
302
|
if (plain(input) && Object.hasOwn(input, 'field') && Object.keys(input).length === 1) {
|
|
285
303
|
if (specs(typed, input.field, place(at, 'field')).some(several)) {
|
|
286
304
|
invalid(place(at, 'field'), 'a path that can hold several values');
|
|
287
305
|
}
|
|
288
306
|
return { of: 'field', field: input.field };
|
|
289
307
|
}
|
|
290
|
-
return invalid(at, path ? 'expects room, path, type or a field' : 'expects room, type or a field');
|
|
308
|
+
return invalid(at, path ? 'expects room, path, type, folder or a field' : 'expects room, type, folder or a field');
|
|
291
309
|
}
|
|
292
310
|
function direction(input, at) {
|
|
293
311
|
if (input === undefined)
|
|
@@ -349,7 +367,7 @@ function parts(typed, input, at, fields) {
|
|
|
349
367
|
});
|
|
350
368
|
return named;
|
|
351
369
|
}
|
|
352
|
-
function flag(input, at) {
|
|
370
|
+
export function flag(input, at) {
|
|
353
371
|
if (input === undefined)
|
|
354
372
|
return false;
|
|
355
373
|
if (input !== true)
|
|
@@ -377,6 +395,8 @@ function documentShape(typed, input) {
|
|
|
377
395
|
markdown: true,
|
|
378
396
|
backlinks: true,
|
|
379
397
|
change: true,
|
|
398
|
+
fileId: true,
|
|
399
|
+
revision: true,
|
|
380
400
|
orderBy,
|
|
381
401
|
};
|
|
382
402
|
}
|
|
@@ -391,6 +411,8 @@ function documentShape(typed, input) {
|
|
|
391
411
|
markdown: flag(select.markdown, 'select.markdown'),
|
|
392
412
|
backlinks: flag(select.backlinks, 'select.backlinks'),
|
|
393
413
|
change: flag(select.change, 'select.change'),
|
|
414
|
+
fileId: flag(select.fileId, 'select.fileId'),
|
|
415
|
+
revision: flag(select.revision, 'select.revision'),
|
|
394
416
|
orderBy,
|
|
395
417
|
};
|
|
396
418
|
}
|
|
@@ -421,20 +443,36 @@ export function planOf(input, facts, reach = null) {
|
|
|
421
443
|
invalid('select', 'a grouped query selects nothing');
|
|
422
444
|
if (!grouped && input.select === undefined)
|
|
423
445
|
invalid('select', 'a Document query must select');
|
|
424
|
-
known(input, [...FILTER, 'orderBy', 'limit', grouped ? 'groupBy' : 'select'], '');
|
|
446
|
+
known(input, [...FILTER, 'orderBy', 'limit', 'after', 'total', grouped ? 'groupBy' : 'select'], '');
|
|
425
447
|
const limit = limitOf(input.limit);
|
|
426
448
|
const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');
|
|
427
449
|
const { typed, ...root } = scope(facts, rooms, input, '');
|
|
450
|
+
const shape = grouped ? groupShape(typed, input) : documentShape(typed, input);
|
|
428
451
|
return {
|
|
452
|
+
key: queryKey(input),
|
|
429
453
|
rooms,
|
|
430
454
|
reach,
|
|
455
|
+
locked: [],
|
|
431
456
|
root,
|
|
457
|
+
folder: input.folder === undefined ? null : directory(input.folder, 'folder'),
|
|
458
|
+
paths: input.paths === undefined ? null : pathsOf(input.paths),
|
|
432
459
|
hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),
|
|
433
460
|
backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),
|
|
434
|
-
shape
|
|
461
|
+
shape,
|
|
435
462
|
limit,
|
|
463
|
+
after: continuationOf(input.after, shape.orderBy.length + 1),
|
|
464
|
+
total: flag(input.total, 'total'),
|
|
436
465
|
};
|
|
437
466
|
}
|
|
467
|
+
function continuationOf(input, arity) {
|
|
468
|
+
if (input === undefined)
|
|
469
|
+
return null;
|
|
470
|
+
const values = typeof input === 'string' ? decodedCursor(input) : null;
|
|
471
|
+
if (values === null || (values.length !== 0 && values.length !== arity)) {
|
|
472
|
+
invalid('after', 'expects the next an earlier result of this query returned');
|
|
473
|
+
}
|
|
474
|
+
return { text: input, values: values.length === 0 ? null : values };
|
|
475
|
+
}
|
|
438
476
|
export function limitOf(input) {
|
|
439
477
|
if (input === undefined)
|
|
440
478
|
return null;
|
|
@@ -449,6 +487,9 @@ export function filterOf(input, facts, reach = null) {
|
|
|
449
487
|
known(input, FILTER, '');
|
|
450
488
|
return planOf({ ...input, select: {} }, facts, reach);
|
|
451
489
|
}
|
|
490
|
+
export function queryKey(query) {
|
|
491
|
+
return canonical(query);
|
|
492
|
+
}
|
|
452
493
|
function canonical(value) {
|
|
453
494
|
if (Array.isArray(value))
|
|
454
495
|
return `[${value.map(canonical).join(',')}]`;
|
package/dist/reach.d.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import type { MdRuntime, RuntimeTopic } from './connection.js';
|
|
1
|
+
import type { AppRoom, MdRuntime, ReadinessPort, RuntimeTopic } from './connection.js';
|
|
2
2
|
import type { Plan, PlanReach, QueryResult } from './query.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { Readiness } from './readiness.js';
|
|
4
|
+
import { type SearchResult } from './search.js';
|
|
4
5
|
export type ReachedDocument = {
|
|
5
6
|
readonly room: string;
|
|
6
7
|
readonly path: string;
|
|
7
8
|
};
|
|
9
|
+
export type ReachedArea = {
|
|
10
|
+
readonly room: string;
|
|
11
|
+
readonly path: string;
|
|
12
|
+
readonly open: readonly string[];
|
|
13
|
+
};
|
|
8
14
|
export type PortReach = {
|
|
9
15
|
readonly rooms: readonly string[];
|
|
10
16
|
readonly documents: readonly ReachedDocument[];
|
|
17
|
+
readonly areas?: readonly ReachedArea[];
|
|
11
18
|
readonly conversations: boolean;
|
|
12
19
|
};
|
|
13
20
|
export type Deliver = (message: unknown) => void;
|
|
@@ -18,12 +25,19 @@ export type RuntimeView = {
|
|
|
18
25
|
};
|
|
19
26
|
export type NarrowedView = RuntimeView & {
|
|
20
27
|
narrow(reach: PortReach | null): void;
|
|
28
|
+
facts(port: ReadinessPort): void;
|
|
21
29
|
};
|
|
22
30
|
export type Reachable = RuntimeView & {
|
|
23
31
|
plan(input: unknown, reach: PortReach | null): Plan;
|
|
24
32
|
query(plan: Plan): Promise<QueryResult>;
|
|
25
33
|
watchPlan(plan: Plan, deliver: (message: unknown) => void): () => void;
|
|
26
|
-
search(input: unknown, reach: PortReach | null): Promise<SearchResult>;
|
|
34
|
+
search(input: unknown, reach: PortReach | null, locked: readonly string[]): Promise<SearchResult>;
|
|
35
|
+
watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
|
|
36
|
+
locked(room: string): boolean;
|
|
37
|
+
lockedRooms(): readonly string[];
|
|
38
|
+
watchLocks(notify: () => void): () => void;
|
|
39
|
+
located(room: string, path: string, destination: string): ReachedDocument | null;
|
|
40
|
+
room(locator: string): AppRoom | undefined;
|
|
27
41
|
};
|
|
28
42
|
export declare function holds(reach: PortReach | null, room: string): boolean;
|
|
29
43
|
export declare function governs(reach: PortReach | null, room: {
|
|
@@ -36,5 +50,5 @@ export declare function governs(reach: PortReach | null, room: {
|
|
|
36
50
|
readonly selection: boolean;
|
|
37
51
|
};
|
|
38
52
|
export declare function planReach(reach: PortReach | null): PlanReach | null;
|
|
39
|
-
export declare function narrowed(runtime: Reachable, given: PortReach | null): NarrowedView;
|
|
53
|
+
export declare function narrowed(runtime: Reachable, given: PortReach | null, told: ReadinessPort): NarrowedView;
|
|
40
54
|
//# sourceMappingURL=reach.d.ts.map
|
package/dist/reach.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}
|
package/dist/reach.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { unheldView } from './conversation.js';
|
|
2
2
|
import { modelTypes, NO_MODEL } from './model.js';
|
|
3
|
-
import {
|
|
3
|
+
import { changeOf, digestApplied, digestOf, observing, } from './observation.js';
|
|
4
4
|
import { runtimeError } from './failure.js';
|
|
5
|
-
import { failure, undeclared } from './outcome.js';
|
|
5
|
+
import { failure, lockedRoom, ROOM_LOCKED, undeclared, UNREADABLE, } from './outcome.js';
|
|
6
6
|
import { beneath } from './paths.js';
|
|
7
|
-
import { reconciled } from './read-side.js';
|
|
8
7
|
import { moveTarget, readParts, staleWrite, } from './room-draft.js';
|
|
9
8
|
import { documentKey } from './rows.js';
|
|
9
|
+
import { undeclaredSearch } from './search.js';
|
|
10
10
|
const UNHELD_TYPES = { collection: modelTypes(NO_MODEL), typedSelection: null };
|
|
11
11
|
function unconversed(name) {
|
|
12
12
|
return () => Promise.resolve(undeclared(name));
|
|
@@ -14,18 +14,26 @@ function unconversed(name) {
|
|
|
14
14
|
const NO_CONVERSATION = {
|
|
15
15
|
list: () => Promise.resolve([]),
|
|
16
16
|
read: (conversation) => Promise.resolve(unheldView(conversation)),
|
|
17
|
-
create: unconversed('
|
|
18
|
-
send: unconversed('
|
|
19
|
-
answer: unconversed('
|
|
20
|
-
interrupt: unconversed('
|
|
21
|
-
kill: unconversed('
|
|
22
|
-
|
|
23
|
-
delete: unconversed('conversation.delete'),
|
|
17
|
+
create: unconversed('conversations/create'),
|
|
18
|
+
send: unconversed('conversations/send'),
|
|
19
|
+
answer: unconversed('conversations/interaction/answer'),
|
|
20
|
+
interrupt: unconversed('conversations/interrupt'),
|
|
21
|
+
kill: unconversed('conversations/kill'),
|
|
22
|
+
delete: unconversed('conversations/delete'),
|
|
24
23
|
};
|
|
25
24
|
const NO_CHAT_DRAFT = {
|
|
26
25
|
write: () => Promise.resolve(),
|
|
26
|
+
prepend: () => Promise.resolve(),
|
|
27
27
|
discard: () => Promise.resolve(),
|
|
28
28
|
};
|
|
29
|
+
function areasOf(reach) {
|
|
30
|
+
return reach.areas ?? [];
|
|
31
|
+
}
|
|
32
|
+
function fenced(reach, room, path) {
|
|
33
|
+
return areasOf(reach).some((area) => area.room === room &&
|
|
34
|
+
beneath(area.path, path) &&
|
|
35
|
+
!area.open.some((open) => beneath(open, path)));
|
|
36
|
+
}
|
|
29
37
|
export function holds(reach, room) {
|
|
30
38
|
return (reach === null ||
|
|
31
39
|
reach.rooms.includes(room) ||
|
|
@@ -46,8 +54,9 @@ export function governs(reach, room) {
|
|
|
46
54
|
}
|
|
47
55
|
function covers(reach, room, path) {
|
|
48
56
|
return (reach === null ||
|
|
49
|
-
reach
|
|
50
|
-
|
|
57
|
+
(!fenced(reach, room, path) &&
|
|
58
|
+
(reach.rooms.includes(room) ||
|
|
59
|
+
reach.documents.some((document) => document.room === room && document.path === path))));
|
|
51
60
|
}
|
|
52
61
|
function conversing(reach) {
|
|
53
62
|
return reach === null || reach.conversations;
|
|
@@ -60,6 +69,9 @@ export function planReach(reach) {
|
|
|
60
69
|
documents: [
|
|
61
70
|
...new Set(reach.documents.map(({ room, path }) => documentKey(room, path))),
|
|
62
71
|
].sort(),
|
|
72
|
+
areas: areasOf(reach)
|
|
73
|
+
.map(({ room, path, open }) => ({ room, path, open: [...new Set(open)].sort() }))
|
|
74
|
+
.sort((left, right) => documentKey(left.room, left.path) < documentKey(right.room, right.path) ? -1 : 1),
|
|
63
75
|
};
|
|
64
76
|
}
|
|
65
77
|
function roomsWithin(reach, rooms) {
|
|
@@ -75,7 +87,7 @@ function typesWithin(reach, room, types) {
|
|
|
75
87
|
};
|
|
76
88
|
}
|
|
77
89
|
function moves(reach, room, move) {
|
|
78
|
-
return move === undefined || covers(reach, room, moveTarget(move));
|
|
90
|
+
return move === undefined || covers(reach, move.room ?? room, moveTarget(move));
|
|
79
91
|
}
|
|
80
92
|
function draftWithin(reach, draft) {
|
|
81
93
|
return covers(reach, draft.room, draft.path) && moves(reach, draft.room, draft.parts.move);
|
|
@@ -109,75 +121,127 @@ function statusWithin(reach, status) {
|
|
|
109
121
|
return {
|
|
110
122
|
...status,
|
|
111
123
|
attentionRequired: status.attentionRequired.filter((entry) => covers(reach, entry.room, entry.path)),
|
|
124
|
+
unsent: status.unsent.filter((change) => covers(reach, change.room, change.path)),
|
|
112
125
|
};
|
|
113
126
|
}
|
|
114
127
|
function queueWithin(reach, room, entries) {
|
|
115
|
-
return entries
|
|
116
|
-
(
|
|
128
|
+
return entries
|
|
129
|
+
.filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
|
|
130
|
+
(change.kind !== 'move' || covers(reach, room, change.to))))
|
|
131
|
+
.map((entry) => {
|
|
132
|
+
const { between, ...batch } = entry.batch;
|
|
133
|
+
if (between === undefined)
|
|
134
|
+
return entry;
|
|
135
|
+
return wholly(reach, between.source.room) && wholly(reach, between.destination.room)
|
|
136
|
+
? entry
|
|
137
|
+
: { ...entry, batch };
|
|
138
|
+
});
|
|
117
139
|
}
|
|
118
140
|
function unreached(room) {
|
|
119
|
-
return runtimeError('room
|
|
141
|
+
return runtimeError('unknown-room', `Unknown Room ${room}`);
|
|
142
|
+
}
|
|
143
|
+
function lockedError(room) {
|
|
144
|
+
return runtimeError(ROOM_LOCKED, `${room} is locked until House confirms its access`, true);
|
|
145
|
+
}
|
|
146
|
+
function deviceUnreached() {
|
|
147
|
+
return runtimeError('device-unreached', 'Only the panel cleans up this device');
|
|
120
148
|
}
|
|
121
|
-
|
|
149
|
+
const ATTACH_REQUIRED = 'attach-required';
|
|
150
|
+
function attachRequired() {
|
|
151
|
+
return runtimeError(ATTACH_REQUIRED, 'App code takes a file in with binaryFile.attach');
|
|
152
|
+
}
|
|
153
|
+
function carriesFile(parts) {
|
|
154
|
+
return parts !== null && typeof parts === 'object' && Object.hasOwn(parts, 'file');
|
|
155
|
+
}
|
|
156
|
+
export function narrowed(runtime, given, told) {
|
|
122
157
|
const { md, watch } = runtime;
|
|
123
158
|
let reach = given;
|
|
159
|
+
let port = told;
|
|
124
160
|
const open = new Set();
|
|
125
|
-
function following(begin) {
|
|
161
|
+
function following(begin, locking = false) {
|
|
126
162
|
let stop = begin();
|
|
127
163
|
const restart = () => {
|
|
128
164
|
stop();
|
|
129
165
|
stop = begin();
|
|
130
166
|
};
|
|
131
167
|
open.add(restart);
|
|
168
|
+
const unwatch = locking ? runtime.watchLocks(restart) : () => { };
|
|
132
169
|
return () => {
|
|
133
170
|
open.delete(restart);
|
|
171
|
+
unwatch();
|
|
134
172
|
stop();
|
|
135
173
|
};
|
|
136
174
|
}
|
|
175
|
+
const unlocking = (rooms) => {
|
|
176
|
+
const locked = (rooms ?? []).filter((room) => runtime.locked(room));
|
|
177
|
+
return locked.length === 0
|
|
178
|
+
? null
|
|
179
|
+
: { pending: locked.map((room) => ({ room, awaits: 'unlock' })) };
|
|
180
|
+
};
|
|
181
|
+
const unlocked = (entries) => entries.filter((entry) => !runtime.locked(entry.room));
|
|
182
|
+
const intoLocked = (held) => held.some((move) => move?.room !== undefined && runtime.locked(move.room));
|
|
137
183
|
const within = (topic, input, deliver) => {
|
|
138
184
|
if (topic === 'rooms') {
|
|
139
185
|
return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms))));
|
|
140
186
|
}
|
|
187
|
+
if (topic === 'readiness') {
|
|
188
|
+
return following(() => runtime.watchReadiness(port, reach, deliver));
|
|
189
|
+
}
|
|
141
190
|
if (topic === 'sync-status') {
|
|
142
|
-
return following(() => watch(topic, input, (status) =>
|
|
191
|
+
return following(() => watch(topic, input, (status) => {
|
|
192
|
+
const within = statusWithin(reach, status);
|
|
193
|
+
deliver({ ...within, attentionRequired: unlocked(within.attentionRequired) });
|
|
194
|
+
}), true);
|
|
143
195
|
}
|
|
144
196
|
if (topic === 'room-drafts') {
|
|
145
|
-
return following(() => watch(topic, input, (drafts) => deliver(draftsWithin(reach, drafts))));
|
|
197
|
+
return following(() => watch(topic, input, (drafts) => deliver(unlocked(draftsWithin(reach, drafts)))), true);
|
|
146
198
|
}
|
|
147
199
|
if (topic === 'queue') {
|
|
148
200
|
const room = input[0];
|
|
149
201
|
return following(() => {
|
|
150
|
-
if (!holds(reach, room)) {
|
|
202
|
+
if (!holds(reach, room) || runtime.locked(room)) {
|
|
151
203
|
deliver([]);
|
|
152
204
|
return () => { };
|
|
153
205
|
}
|
|
154
206
|
return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)));
|
|
155
|
-
});
|
|
207
|
+
}, true);
|
|
156
208
|
}
|
|
157
209
|
if (topic === 'query') {
|
|
158
210
|
const plan = runtime.plan(input[0], reach);
|
|
159
211
|
let held = null;
|
|
160
212
|
return following(() => {
|
|
213
|
+
const locked = unlocking(plan.rooms);
|
|
214
|
+
if (locked !== null) {
|
|
215
|
+
const answer = { result: locked, keys: [] };
|
|
216
|
+
if (held === null || changeOf(held, answer) !== null)
|
|
217
|
+
deliver(answer);
|
|
218
|
+
held = digestOf(answer);
|
|
219
|
+
return () => { };
|
|
220
|
+
}
|
|
161
221
|
let first = true;
|
|
162
|
-
|
|
222
|
+
let open = true;
|
|
223
|
+
const heard = (message) => {
|
|
163
224
|
if (!first) {
|
|
164
|
-
held =
|
|
225
|
+
held = digestApplied(held, message);
|
|
165
226
|
deliver(message);
|
|
166
227
|
return;
|
|
167
228
|
}
|
|
168
229
|
first = false;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
deliver(next.change);
|
|
230
|
+
const change = held === null ? message : changeOf(held, message);
|
|
231
|
+
held = digestOf(message);
|
|
232
|
+
if (change !== null)
|
|
233
|
+
deliver(change);
|
|
234
|
+
};
|
|
235
|
+
const current = { ...plan, reach: planReach(reach), locked: runtime.lockedRooms() };
|
|
236
|
+
const stop = runtime.watchPlan(current, (message) => {
|
|
237
|
+
if (open)
|
|
238
|
+
heard(message);
|
|
179
239
|
});
|
|
180
|
-
|
|
240
|
+
return () => {
|
|
241
|
+
open = false;
|
|
242
|
+
stop();
|
|
243
|
+
};
|
|
244
|
+
}, true);
|
|
181
245
|
}
|
|
182
246
|
if (topic === 'conversation') {
|
|
183
247
|
return following(() => {
|
|
@@ -197,49 +261,149 @@ export function narrowed(runtime, given) {
|
|
|
197
261
|
}
|
|
198
262
|
return watch(topic, input, deliver);
|
|
199
263
|
};
|
|
264
|
+
const files = new Map();
|
|
265
|
+
let handed = 0;
|
|
266
|
+
async function hand(reading) {
|
|
267
|
+
const answer = await reading;
|
|
268
|
+
if (answer.kind !== 'binary')
|
|
269
|
+
return answer;
|
|
270
|
+
handed += 1;
|
|
271
|
+
const file = String(handed);
|
|
272
|
+
files.set(file, answer.file);
|
|
273
|
+
return { ...answer, file };
|
|
274
|
+
}
|
|
200
275
|
const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
|
|
201
276
|
const chatDraft = () => (conversing(reach) ? md.chatDraft : NO_CHAT_DRAFT);
|
|
202
277
|
const view = {
|
|
203
278
|
...md,
|
|
204
|
-
rooms: () => roomsWithin(reach,
|
|
205
|
-
query: ((input) =>
|
|
206
|
-
|
|
279
|
+
rooms: () => md.rooms().then((rooms) => roomsWithin(reach, rooms)),
|
|
280
|
+
query: ((input) => {
|
|
281
|
+
const plan = runtime.plan(input, reach);
|
|
282
|
+
return Promise.resolve(unlocking(plan.rooms) ?? runtime.query({ ...plan, locked: runtime.lockedRooms() }));
|
|
283
|
+
}),
|
|
284
|
+
search: (input) => port.search === 'required'
|
|
285
|
+
? runtime.search(input, reach, runtime.lockedRooms())
|
|
286
|
+
: Promise.resolve(undeclaredSearch()),
|
|
207
287
|
types(room) {
|
|
288
|
+
if (holds(reach, room) && runtime.locked(room))
|
|
289
|
+
throw lockedError(room);
|
|
208
290
|
if (wholly(reach, room))
|
|
209
291
|
return md.types(room);
|
|
210
292
|
if (!holds(reach, room))
|
|
211
293
|
return structuredClone(UNHELD_TYPES);
|
|
212
|
-
|
|
213
|
-
return typesWithin(reach, listed, md.types(room));
|
|
294
|
+
return typesWithin(reach, runtime.room(room), md.types(room));
|
|
214
295
|
},
|
|
215
296
|
async save(room, roomDrafts, writtenBy) {
|
|
216
297
|
if (!holds(reach, room))
|
|
217
298
|
throw unreached(room);
|
|
218
|
-
|
|
219
|
-
|
|
299
|
+
if (runtime.locked(room))
|
|
300
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
301
|
+
const held = (await Promise.all(roomDrafts.map(({ path }) => md.roomDraft.read(room, path)))).map((draft) => draft?.parts.move);
|
|
302
|
+
const outside = roomDrafts.find(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]));
|
|
220
303
|
if (outside !== undefined) {
|
|
221
304
|
return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
|
|
222
305
|
}
|
|
306
|
+
if (intoLocked(held))
|
|
307
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
223
308
|
return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
|
|
224
309
|
},
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
310
|
+
async saveParts(room, parts, writtenBy) {
|
|
311
|
+
if (!holds(reach, room))
|
|
312
|
+
throw unreached(room);
|
|
313
|
+
const filed = reach === null ? undefined : parts.find(({ parts: one }) => carriesFile(one));
|
|
314
|
+
if (filed !== undefined) {
|
|
315
|
+
return { outcome: 'refused', code: ATTACH_REQUIRED, retryable: false, file: filed.path };
|
|
316
|
+
}
|
|
317
|
+
if (runtime.locked(room))
|
|
318
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
319
|
+
const held = parts.map(({ parts: one }) => readParts(one).move);
|
|
320
|
+
if (parts.some(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]))) {
|
|
321
|
+
throw unreached(room);
|
|
322
|
+
}
|
|
323
|
+
if (intoLocked(held))
|
|
324
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
325
|
+
return savedWithin(reach, room, await md.saveParts(room, parts, writtenBy));
|
|
326
|
+
},
|
|
327
|
+
resolve(room, path, destination) {
|
|
328
|
+
const at = runtime.located(room, path, destination);
|
|
329
|
+
return at !== null && !covers(reach, at.room, at.path)
|
|
330
|
+
? Promise.resolve(UNREADABLE)
|
|
331
|
+
: md.resolve(room, path, destination);
|
|
332
|
+
},
|
|
333
|
+
history: (room, path, query) => !covers(reach, room, path)
|
|
334
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
335
|
+
: runtime.locked(room)
|
|
336
|
+
? Promise.resolve(lockedRoom(room))
|
|
337
|
+
: md.history(room, path, query),
|
|
338
|
+
binaryFile: {
|
|
339
|
+
read: (room, path, revision) => !covers(reach, room, path)
|
|
340
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
341
|
+
: runtime.locked(room)
|
|
342
|
+
? Promise.resolve(lockedRoom(room))
|
|
343
|
+
: hand(md.binaryFile.read(room, path, revision)),
|
|
344
|
+
link: (room, path, revision) => !covers(reach, room, path)
|
|
345
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
346
|
+
: runtime.locked(room)
|
|
347
|
+
? Promise.resolve(lockedRoom(room))
|
|
348
|
+
: md.binaryFile.link(room, path, revision),
|
|
349
|
+
show: (room, path, revision) => !covers(reach, room, path)
|
|
350
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
351
|
+
: runtime.locked(room)
|
|
352
|
+
? Promise.resolve(lockedRoom(room))
|
|
353
|
+
: hand(md.binaryFile.show(room, path, revision)),
|
|
354
|
+
attach: (room, file) => !wholly(reach, room)
|
|
355
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
356
|
+
: runtime.locked(room)
|
|
357
|
+
? Promise.resolve(lockedRoom(room))
|
|
358
|
+
: md.binaryFile.attach(room, file),
|
|
359
|
+
async part(file, part) {
|
|
360
|
+
const key = files.get(file);
|
|
361
|
+
if (key === undefined)
|
|
362
|
+
return null;
|
|
363
|
+
const bytes = await md.binaryFile.part(key, part);
|
|
364
|
+
if (bytes === null)
|
|
365
|
+
files.delete(file);
|
|
366
|
+
return bytes;
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
reached: async (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
|
|
370
|
+
!runtime.locked(room) &&
|
|
371
|
+
(await md.reached(room, roomVersion, path)),
|
|
230
372
|
log: () => (reach === null ? md.log() : ''),
|
|
373
|
+
cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
|
|
231
374
|
roomDraft: {
|
|
232
|
-
list: () => md.roomDraft.list().then((drafts) => draftsWithin(reach, drafts)),
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
375
|
+
list: () => md.roomDraft.list().then((drafts) => unlocked(draftsWithin(reach, drafts))),
|
|
376
|
+
async read(room, path) {
|
|
377
|
+
if (!covers(reach, room, path))
|
|
378
|
+
return null;
|
|
379
|
+
if (runtime.locked(room))
|
|
380
|
+
throw lockedError(room);
|
|
381
|
+
return shownDraft(reach, await md.roomDraft.read(room, path));
|
|
382
|
+
},
|
|
383
|
+
write(room, path, revision, parts, next) {
|
|
384
|
+
try {
|
|
385
|
+
if (reach !== null && carriesFile(parts))
|
|
386
|
+
throw attachRequired();
|
|
387
|
+
const move = readParts(parts).move;
|
|
388
|
+
if (!covers(reach, room, path) || !moves(reach, room, move))
|
|
389
|
+
throw unreached(room);
|
|
390
|
+
if (runtime.locked(room))
|
|
391
|
+
throw lockedError(room);
|
|
392
|
+
if (intoLocked([move]))
|
|
393
|
+
throw lockedError(move.room);
|
|
237
394
|
}
|
|
238
|
-
|
|
395
|
+
catch (error) {
|
|
396
|
+
return Promise.reject(error);
|
|
397
|
+
}
|
|
398
|
+
return md.roomDraft
|
|
399
|
+
.write(room, path, revision, parts, next)
|
|
400
|
+
.then((written) => writeWithin(reach, written));
|
|
239
401
|
},
|
|
240
402
|
async discard(room, path, revision) {
|
|
241
403
|
if (!covers(reach, room, path))
|
|
242
404
|
return staleWrite(null);
|
|
405
|
+
if (runtime.locked(room))
|
|
406
|
+
throw lockedError(room);
|
|
243
407
|
return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
|
|
244
408
|
},
|
|
245
409
|
},
|
|
@@ -247,15 +411,15 @@ export function narrowed(runtime, given) {
|
|
|
247
411
|
list: () => conversation().list(),
|
|
248
412
|
read: (id, options) => conversation().read(id, options),
|
|
249
413
|
create: (input) => conversation().create(input),
|
|
250
|
-
send: (id) => conversation().send(id),
|
|
414
|
+
send: (id, operation, draft) => conversation().send(id, operation, draft),
|
|
251
415
|
answer: (id, answer) => conversation().answer(id, answer),
|
|
252
416
|
interrupt: (id) => conversation().interrupt(id),
|
|
253
417
|
kill: (id) => conversation().kill(id),
|
|
254
|
-
cancel: (id, turn) => conversation().cancel(id, turn),
|
|
255
418
|
delete: (id) => conversation().delete(id),
|
|
256
419
|
},
|
|
257
420
|
chatDraft: {
|
|
258
421
|
write: (id, draft, revision) => chatDraft().write(id, draft, revision),
|
|
422
|
+
prepend: (id, draft) => chatDraft().prepend(id, draft),
|
|
259
423
|
discard: (id) => chatDraft().discard(id),
|
|
260
424
|
},
|
|
261
425
|
observe: observing(within),
|
|
@@ -268,5 +432,10 @@ export function narrowed(runtime, given) {
|
|
|
268
432
|
for (const restart of [...open])
|
|
269
433
|
restart();
|
|
270
434
|
},
|
|
435
|
+
facts(next) {
|
|
436
|
+
port = next;
|
|
437
|
+
for (const restart of [...open])
|
|
438
|
+
restart();
|
|
439
|
+
},
|
|
271
440
|
};
|
|
272
441
|
}
|