@agentshouse/mdruntime 0.1.0-cc7bd7a53214e → 0.1.0-ccbb89b0ca151
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 +24 -11
- package/dist/adapter.d.ts +187 -48
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +1 -9
- package/dist/attached-model.d.ts +15 -0
- package/dist/attached-model.d.ts.map +1 -0
- package/dist/attached-model.js +64 -0
- package/dist/attempt.d.ts +16 -0
- package/dist/attempt.d.ts.map +1 -0
- package/dist/attempt.js +70 -0
- 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 +44 -7
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +223 -45
- 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 -56
- package/dist/change.d.ts +45 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +34 -0
- package/dist/client.d.ts +37 -15
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +159 -29
- package/dist/collection.d.ts +9 -13
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +46 -56
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +765 -0
- package/dist/connection.d.ts +64 -25
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3926 -961
- package/dist/conversation.d.ts +54 -16
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +730 -243
- 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 +5 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +19 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +151 -0
- package/dist/expectation.d.ts +21 -0
- package/dist/expectation.d.ts.map +1 -0
- package/dist/expectation.js +70 -0
- package/dist/failure.d.ts +13 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +19 -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 +368 -0
- package/dist/host.d.ts +15 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +136 -31
- package/dist/identity.d.ts +4 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +16 -1
- package/dist/index.d.ts +19 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +124 -0
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +195 -0
- package/dist/memory.d.ts +22 -8
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +207 -47
- 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 +17 -14
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +16 -4
- 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 +19 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +113 -12
- package/dist/open.d.ts +2 -0
- package/dist/open.d.ts.map +1 -0
- package/dist/open.js +1 -0
- 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 +73 -3
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +79 -1
- package/dist/overlay.d.ts +15 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +136 -180
- package/dist/paths.d.ts +0 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +0 -16
- package/dist/query.d.ts +71 -5
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +122 -40
- package/dist/reach.d.ts +17 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +251 -81
- package/dist/react.d.ts +43 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +54 -0
- package/dist/readiness.d.ts +64 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -0
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +100 -0
- package/dist/recovery.d.ts +25 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +198 -0
- package/dist/refresh.d.ts +19 -7
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +125 -53
- package/dist/replica.d.ts +59 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +321 -156
- package/dist/room-draft.d.ts +41 -9
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +186 -37
- package/dist/rows.d.ts +39 -34
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +195 -81
- package/dist/save.d.ts +72 -6
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +889 -178
- package/dist/search.d.ts +41 -29
- 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 +16 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +431 -0
- package/dist/status.d.ts +6 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -8
- package/dist/store.d.ts +119 -58
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +362 -344
- package/dist/stored.d.ts +152 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +607 -0
- package/dist/tables.d.ts +352 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +624 -0
- 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 +30 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +162 -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 +174 -45
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +70 -46
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +150 -0
- package/package.json +33 -10
- package/AGENTS.md +0 -215
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
- package/dist/read-side.d.ts +0 -18
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -377
package/dist/reach.js
CHANGED
|
@@ -1,34 +1,46 @@
|
|
|
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
|
+
import { runtimeError } from './failure.js';
|
|
5
|
+
import { failure, lockedRoom, ROOM_LOCKED, undeclared, UNREADABLE, } from './outcome.js';
|
|
4
6
|
import { beneath } from './paths.js';
|
|
5
|
-
import {
|
|
6
|
-
import { moveTarget, readParts } from './room-draft.js';
|
|
7
|
+
import { moveTarget, readParts, staleWrite, } from './room-draft.js';
|
|
7
8
|
import { documentKey } from './rows.js';
|
|
9
|
+
import { undeclaredSearch } from './search.js';
|
|
8
10
|
const UNHELD_TYPES = { collection: modelTypes(NO_MODEL), typedSelection: null };
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return Promise.resolve(UNDECLARED);
|
|
11
|
+
function unconversed(name) {
|
|
12
|
+
return () => Promise.resolve(undeclared(name));
|
|
12
13
|
}
|
|
13
14
|
const NO_CONVERSATION = {
|
|
14
15
|
list: () => Promise.resolve([]),
|
|
15
16
|
read: (conversation) => Promise.resolve(unheldView(conversation)),
|
|
16
|
-
create:
|
|
17
|
-
send:
|
|
18
|
-
answer:
|
|
19
|
-
interrupt:
|
|
20
|
-
kill:
|
|
21
|
-
cancel:
|
|
22
|
-
delete:
|
|
17
|
+
create: unconversed('conversation.create'),
|
|
18
|
+
send: unconversed('conversation.send'),
|
|
19
|
+
answer: unconversed('conversation.answer'),
|
|
20
|
+
interrupt: unconversed('conversation.interrupt'),
|
|
21
|
+
kill: unconversed('conversation.kill'),
|
|
22
|
+
cancel: unconversed('conversation.cancel'),
|
|
23
|
+
delete: unconversed('conversation.delete'),
|
|
23
24
|
};
|
|
24
25
|
const NO_CHAT_DRAFT = {
|
|
25
26
|
write: () => Promise.resolve(),
|
|
27
|
+
prepend: () => Promise.resolve(),
|
|
26
28
|
discard: () => Promise.resolve(),
|
|
27
29
|
};
|
|
30
|
+
function areasOf(reach) {
|
|
31
|
+
return reach.areas ?? [];
|
|
32
|
+
}
|
|
33
|
+
function typedAreas(reach, room) {
|
|
34
|
+
return areasOf(reach).filter((area) => area.room === room && area.types.length > 0);
|
|
35
|
+
}
|
|
36
|
+
function fenced(reach, room, path) {
|
|
37
|
+
return areasOf(reach).some((area) => area.room === room && beneath(area.path, path));
|
|
38
|
+
}
|
|
28
39
|
export function holds(reach, room) {
|
|
29
40
|
return (reach === null ||
|
|
30
41
|
reach.rooms.includes(room) ||
|
|
31
|
-
reach.documents.some((document) => document.room === room)
|
|
42
|
+
reach.documents.some((document) => document.room === room) ||
|
|
43
|
+
typedAreas(reach, room).length > 0);
|
|
32
44
|
}
|
|
33
45
|
function wholly(reach, room) {
|
|
34
46
|
return reach === null || reach.rooms.includes(room);
|
|
@@ -38,15 +50,19 @@ export function governs(reach, room) {
|
|
|
38
50
|
return { collection: true, selection: room.typedSelection !== null };
|
|
39
51
|
}
|
|
40
52
|
const selected = (path) => room.typedSelection?.roots.some((root) => beneath(root, path)) ?? false;
|
|
41
|
-
const paths =
|
|
42
|
-
.
|
|
43
|
-
|
|
53
|
+
const paths = [
|
|
54
|
+
...reach.documents
|
|
55
|
+
.filter((document) => document.room === room.locator)
|
|
56
|
+
.map(({ path }) => path),
|
|
57
|
+
...typedAreas(reach, room.locator).map(({ path }) => path),
|
|
58
|
+
];
|
|
44
59
|
return { collection: paths.some((path) => !selected(path)), selection: paths.some(selected) };
|
|
45
60
|
}
|
|
46
61
|
function covers(reach, room, path) {
|
|
47
62
|
return (reach === null ||
|
|
48
|
-
reach
|
|
49
|
-
|
|
63
|
+
(!fenced(reach, room, path) &&
|
|
64
|
+
(reach.rooms.includes(room) ||
|
|
65
|
+
reach.documents.some((document) => document.room === room && document.path === path))));
|
|
50
66
|
}
|
|
51
67
|
function conversing(reach) {
|
|
52
68
|
return reach === null || reach.conversations;
|
|
@@ -59,26 +75,13 @@ export function planReach(reach) {
|
|
|
59
75
|
documents: [
|
|
60
76
|
...new Set(reach.documents.map(({ room, path }) => documentKey(room, path))),
|
|
61
77
|
].sort(),
|
|
78
|
+
areas: areasOf(reach)
|
|
79
|
+
.map(({ room, path, types }) => ({ room, path, types: [...new Set(types)].sort() }))
|
|
80
|
+
.sort((left, right) => documentKey(left.room, left.path) < documentKey(right.room, right.path) ? -1 : 1),
|
|
62
81
|
};
|
|
63
82
|
}
|
|
64
83
|
function roomsWithin(reach, rooms) {
|
|
65
|
-
|
|
66
|
-
return rooms;
|
|
67
|
-
return rooms
|
|
68
|
-
.filter((room) => holds(reach, room.locator))
|
|
69
|
-
.map((room) => {
|
|
70
|
-
if (wholly(reach, room.locator))
|
|
71
|
-
return room;
|
|
72
|
-
const governed = governs(reach, room);
|
|
73
|
-
return {
|
|
74
|
-
...room,
|
|
75
|
-
attachedModel: governed.collection ? room.attachedModel : null,
|
|
76
|
-
model: governed.collection ? room.model : modelTypes(NO_MODEL),
|
|
77
|
-
typedSelection: governed.selection ? room.typedSelection : null,
|
|
78
|
-
roomVersion: null,
|
|
79
|
-
attachments: [],
|
|
80
|
-
};
|
|
81
|
-
});
|
|
84
|
+
return rooms.filter((room) => wholly(reach, room.locator));
|
|
82
85
|
}
|
|
83
86
|
function typesWithin(reach, room, types) {
|
|
84
87
|
if (room === undefined)
|
|
@@ -90,7 +93,7 @@ function typesWithin(reach, room, types) {
|
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
95
|
function moves(reach, room, move) {
|
|
93
|
-
return move === undefined || covers(reach, room, moveTarget(move));
|
|
96
|
+
return move === undefined || covers(reach, move.room ?? room, moveTarget(move));
|
|
94
97
|
}
|
|
95
98
|
function draftWithin(reach, draft) {
|
|
96
99
|
return covers(reach, draft.room, draft.path) && moves(reach, draft.room, draft.parts.move);
|
|
@@ -104,7 +107,7 @@ function shownDraft(reach, draft) {
|
|
|
104
107
|
function writeWithin(reach, write) {
|
|
105
108
|
return write.outcome === 'written'
|
|
106
109
|
? { outcome: 'written', roomDraft: shownDraft(reach, write.roomDraft) }
|
|
107
|
-
:
|
|
110
|
+
: staleWrite(shownDraft(reach, write.current));
|
|
108
111
|
}
|
|
109
112
|
function savedWithin(reach, room, result) {
|
|
110
113
|
if (reach === null || result.outcome === 'saved')
|
|
@@ -123,76 +126,127 @@ function savedWithin(reach, room, result) {
|
|
|
123
126
|
function statusWithin(reach, status) {
|
|
124
127
|
return {
|
|
125
128
|
...status,
|
|
126
|
-
attentionRequired: status.attentionRequired.filter((entry) => covers(reach, entry.room, entry.path)),
|
|
129
|
+
attentionRequired: status.attentionRequired.filter((entry) => 'refusal' in entry ? wholly(reach, entry.room) : covers(reach, entry.room, entry.path)),
|
|
127
130
|
};
|
|
128
131
|
}
|
|
129
132
|
function queueWithin(reach, room, entries) {
|
|
130
|
-
return entries
|
|
131
|
-
(
|
|
133
|
+
return entries
|
|
134
|
+
.filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
|
|
135
|
+
(change.kind !== 'move' || covers(reach, room, change.to))))
|
|
136
|
+
.map((entry) => {
|
|
137
|
+
const { between, ...batch } = entry.batch;
|
|
138
|
+
if (between === undefined)
|
|
139
|
+
return entry;
|
|
140
|
+
return wholly(reach, between.source.room) && wholly(reach, between.destination.room)
|
|
141
|
+
? entry
|
|
142
|
+
: { ...entry, batch };
|
|
143
|
+
});
|
|
132
144
|
}
|
|
133
145
|
function unreached(room) {
|
|
134
|
-
return
|
|
146
|
+
return runtimeError('room-not-held', `No Local Replica for ${room}`);
|
|
147
|
+
}
|
|
148
|
+
function lockedError(room) {
|
|
149
|
+
return runtimeError(ROOM_LOCKED, `${room} is locked until House confirms its access`, true);
|
|
150
|
+
}
|
|
151
|
+
function deviceUnreached() {
|
|
152
|
+
return runtimeError('device-unreached', 'Only the panel cleans up this device');
|
|
153
|
+
}
|
|
154
|
+
const ATTACH_REQUIRED = 'attach-required';
|
|
155
|
+
function attachRequired() {
|
|
156
|
+
return runtimeError(ATTACH_REQUIRED, 'App code takes a file in with binaryFile.attach');
|
|
157
|
+
}
|
|
158
|
+
function carriesFile(parts) {
|
|
159
|
+
return parts !== null && typeof parts === 'object' && Object.hasOwn(parts, 'file');
|
|
135
160
|
}
|
|
136
|
-
export function narrowed(runtime, given) {
|
|
161
|
+
export function narrowed(runtime, given, told) {
|
|
137
162
|
const { md, watch } = runtime;
|
|
138
163
|
let reach = given;
|
|
164
|
+
let port = told;
|
|
139
165
|
const open = new Set();
|
|
140
|
-
function following(begin) {
|
|
166
|
+
function following(begin, locking = false) {
|
|
141
167
|
let stop = begin();
|
|
142
168
|
const restart = () => {
|
|
143
169
|
stop();
|
|
144
170
|
stop = begin();
|
|
145
171
|
};
|
|
146
172
|
open.add(restart);
|
|
173
|
+
const unwatch = locking ? runtime.watchLocks(restart) : () => { };
|
|
147
174
|
return () => {
|
|
148
175
|
open.delete(restart);
|
|
176
|
+
unwatch();
|
|
149
177
|
stop();
|
|
150
178
|
};
|
|
151
179
|
}
|
|
180
|
+
const unlocking = (rooms) => {
|
|
181
|
+
const locked = (rooms ?? []).filter((room) => runtime.locked(room));
|
|
182
|
+
return locked.length === 0
|
|
183
|
+
? null
|
|
184
|
+
: { pending: locked.map((room) => ({ room, awaits: 'unlock' })) };
|
|
185
|
+
};
|
|
186
|
+
const unlocked = (entries) => entries.filter((entry) => !runtime.locked(entry.room));
|
|
187
|
+
const intoLocked = (held) => held.some((move) => move?.room !== undefined && runtime.locked(move.room));
|
|
152
188
|
const within = (topic, input, deliver) => {
|
|
153
189
|
if (topic === 'rooms') {
|
|
154
190
|
return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms))));
|
|
155
191
|
}
|
|
192
|
+
if (topic === 'readiness') {
|
|
193
|
+
return following(() => runtime.watchReadiness(port, reach, deliver));
|
|
194
|
+
}
|
|
156
195
|
if (topic === 'sync-status') {
|
|
157
|
-
return following(() => watch(topic, input, (status) =>
|
|
196
|
+
return following(() => watch(topic, input, (status) => {
|
|
197
|
+
const within = statusWithin(reach, status);
|
|
198
|
+
deliver({ ...within, attentionRequired: unlocked(within.attentionRequired) });
|
|
199
|
+
}), true);
|
|
158
200
|
}
|
|
159
201
|
if (topic === 'room-drafts') {
|
|
160
|
-
return following(() => watch(topic, input, (drafts) => deliver(draftsWithin(reach, drafts))));
|
|
202
|
+
return following(() => watch(topic, input, (drafts) => deliver(unlocked(draftsWithin(reach, drafts)))), true);
|
|
161
203
|
}
|
|
162
204
|
if (topic === 'queue') {
|
|
163
205
|
const room = input[0];
|
|
164
206
|
return following(() => {
|
|
165
|
-
if (!holds(reach, room)) {
|
|
207
|
+
if (!holds(reach, room) || runtime.locked(room)) {
|
|
166
208
|
deliver([]);
|
|
167
209
|
return () => { };
|
|
168
210
|
}
|
|
169
211
|
return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)));
|
|
170
|
-
});
|
|
212
|
+
}, true);
|
|
171
213
|
}
|
|
172
214
|
if (topic === 'query') {
|
|
173
215
|
const plan = runtime.plan(input[0], reach);
|
|
174
216
|
let held = null;
|
|
175
217
|
return following(() => {
|
|
218
|
+
const locked = unlocking(plan.rooms);
|
|
219
|
+
if (locked !== null) {
|
|
220
|
+
const answer = { result: locked, keys: [] };
|
|
221
|
+
if (held === null || changeOf(held, answer) !== null)
|
|
222
|
+
deliver(answer);
|
|
223
|
+
held = digestOf(answer);
|
|
224
|
+
return () => { };
|
|
225
|
+
}
|
|
176
226
|
let first = true;
|
|
177
|
-
|
|
227
|
+
let open = true;
|
|
228
|
+
const heard = (message) => {
|
|
178
229
|
if (!first) {
|
|
179
|
-
held =
|
|
230
|
+
held = digestApplied(held, message);
|
|
180
231
|
deliver(message);
|
|
181
232
|
return;
|
|
182
233
|
}
|
|
183
234
|
first = false;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
deliver(next.change);
|
|
235
|
+
const change = held === null ? message : changeOf(held, message);
|
|
236
|
+
held = digestOf(message);
|
|
237
|
+
if (change !== null)
|
|
238
|
+
deliver(change);
|
|
239
|
+
};
|
|
240
|
+
const current = { ...plan, reach: planReach(reach), locked: runtime.lockedRooms() };
|
|
241
|
+
const stop = runtime.watchPlan(current, (message) => {
|
|
242
|
+
if (open)
|
|
243
|
+
heard(message);
|
|
194
244
|
});
|
|
195
|
-
|
|
245
|
+
return () => {
|
|
246
|
+
open = false;
|
|
247
|
+
stop();
|
|
248
|
+
};
|
|
249
|
+
}, true);
|
|
196
250
|
}
|
|
197
251
|
if (topic === 'conversation') {
|
|
198
252
|
return following(() => {
|
|
@@ -202,16 +256,42 @@ export function narrowed(runtime, given) {
|
|
|
202
256
|
return () => { };
|
|
203
257
|
});
|
|
204
258
|
}
|
|
259
|
+
if (topic === 'conversations' || topic === 'agents') {
|
|
260
|
+
return following(() => {
|
|
261
|
+
if (conversing(reach))
|
|
262
|
+
return watch(topic, input, deliver);
|
|
263
|
+
deliver([]);
|
|
264
|
+
return () => { };
|
|
265
|
+
});
|
|
266
|
+
}
|
|
205
267
|
return watch(topic, input, deliver);
|
|
206
268
|
};
|
|
269
|
+
const files = new Map();
|
|
270
|
+
let handed = 0;
|
|
271
|
+
async function hand(reading) {
|
|
272
|
+
const answer = await reading;
|
|
273
|
+
if (answer.kind !== 'binary')
|
|
274
|
+
return answer;
|
|
275
|
+
handed += 1;
|
|
276
|
+
const file = String(handed);
|
|
277
|
+
files.set(file, answer.file);
|
|
278
|
+
return { ...answer, file };
|
|
279
|
+
}
|
|
207
280
|
const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
|
|
208
281
|
const chatDraft = () => (conversing(reach) ? md.chatDraft : NO_CHAT_DRAFT);
|
|
209
282
|
const view = {
|
|
210
283
|
...md,
|
|
211
284
|
rooms: () => roomsWithin(reach, md.rooms()),
|
|
212
|
-
query: ((input) =>
|
|
213
|
-
|
|
285
|
+
query: ((input) => {
|
|
286
|
+
const plan = runtime.plan(input, reach);
|
|
287
|
+
return Promise.resolve(unlocking(plan.rooms) ?? runtime.query({ ...plan, locked: runtime.lockedRooms() }));
|
|
288
|
+
}),
|
|
289
|
+
search: (input) => port.search === 'required'
|
|
290
|
+
? runtime.search(input, reach, runtime.lockedRooms())
|
|
291
|
+
: Promise.resolve(undeclaredSearch()),
|
|
214
292
|
types(room) {
|
|
293
|
+
if (holds(reach, room) && runtime.locked(room))
|
|
294
|
+
throw lockedError(room);
|
|
215
295
|
if (wholly(reach, room))
|
|
216
296
|
return md.types(room);
|
|
217
297
|
if (!holds(reach, room))
|
|
@@ -222,30 +302,114 @@ export function narrowed(runtime, given) {
|
|
|
222
302
|
async save(room, roomDrafts, writtenBy) {
|
|
223
303
|
if (!holds(reach, room))
|
|
224
304
|
throw unreached(room);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
305
|
+
if (runtime.locked(room))
|
|
306
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
307
|
+
const held = (await Promise.all(roomDrafts.map(({ path }) => md.roomDraft.read(room, path)))).map((draft) => draft?.parts.move);
|
|
308
|
+
const outside = roomDrafts.find(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]));
|
|
309
|
+
if (outside !== undefined) {
|
|
310
|
+
return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
|
|
311
|
+
}
|
|
312
|
+
if (intoLocked(held))
|
|
313
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
229
314
|
return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
|
|
230
315
|
},
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
316
|
+
async saveParts(room, parts, writtenBy) {
|
|
317
|
+
if (!holds(reach, room))
|
|
318
|
+
throw unreached(room);
|
|
319
|
+
const filed = reach === null ? undefined : parts.find(({ parts: one }) => carriesFile(one));
|
|
320
|
+
if (filed !== undefined) {
|
|
321
|
+
return { outcome: 'refused', code: ATTACH_REQUIRED, retryable: false, file: filed.path };
|
|
322
|
+
}
|
|
323
|
+
if (runtime.locked(room))
|
|
324
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
325
|
+
const held = parts.map(({ parts: one }) => readParts(one).move);
|
|
326
|
+
if (parts.some(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]))) {
|
|
327
|
+
throw unreached(room);
|
|
328
|
+
}
|
|
329
|
+
if (intoLocked(held))
|
|
330
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
331
|
+
return savedWithin(reach, room, await md.saveParts(room, parts, writtenBy));
|
|
332
|
+
},
|
|
333
|
+
resolve(room, path, destination) {
|
|
334
|
+
const at = runtime.located(room, path, destination);
|
|
335
|
+
return at !== null && !covers(reach, at.room, at.path)
|
|
336
|
+
? Promise.resolve(UNREADABLE)
|
|
337
|
+
: md.resolve(room, path, destination);
|
|
338
|
+
},
|
|
339
|
+
history: (room, path, query) => !covers(reach, room, path)
|
|
340
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
341
|
+
: runtime.locked(room)
|
|
342
|
+
? Promise.resolve(lockedRoom(room))
|
|
343
|
+
: md.history(room, path, query),
|
|
344
|
+
binaryFile: {
|
|
345
|
+
read: (room, path, revision) => !covers(reach, room, path)
|
|
346
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
347
|
+
: runtime.locked(room)
|
|
348
|
+
? Promise.resolve(lockedRoom(room))
|
|
349
|
+
: hand(md.binaryFile.read(room, path, revision)),
|
|
350
|
+
link: (room, path, revision) => !covers(reach, room, path)
|
|
351
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
352
|
+
: runtime.locked(room)
|
|
353
|
+
? Promise.resolve(lockedRoom(room))
|
|
354
|
+
: md.binaryFile.link(room, path, revision),
|
|
355
|
+
show: (room, path, revision) => !covers(reach, room, path)
|
|
356
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
357
|
+
: runtime.locked(room)
|
|
358
|
+
? Promise.resolve(lockedRoom(room))
|
|
359
|
+
: hand(md.binaryFile.show(room, path, revision)),
|
|
360
|
+
attach: (room, file) => !wholly(reach, room)
|
|
361
|
+
? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
|
|
362
|
+
: runtime.locked(room)
|
|
363
|
+
? Promise.resolve(lockedRoom(room))
|
|
364
|
+
: md.binaryFile.attach(room, file),
|
|
365
|
+
async part(file, part) {
|
|
366
|
+
const key = files.get(file);
|
|
367
|
+
if (key === undefined)
|
|
368
|
+
return null;
|
|
369
|
+
const bytes = await md.binaryFile.part(key, part);
|
|
370
|
+
if (bytes === null)
|
|
371
|
+
files.delete(file);
|
|
372
|
+
return bytes;
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
reached: async (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
|
|
376
|
+
!runtime.locked(room) &&
|
|
377
|
+
(await md.reached(room, roomVersion, path)),
|
|
236
378
|
log: () => (reach === null ? md.log() : ''),
|
|
379
|
+
cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
|
|
237
380
|
roomDraft: {
|
|
238
|
-
list: () => md.roomDraft.list().then((drafts) => draftsWithin(reach, drafts)),
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
381
|
+
list: () => md.roomDraft.list().then((drafts) => unlocked(draftsWithin(reach, drafts))),
|
|
382
|
+
async read(room, path) {
|
|
383
|
+
if (!covers(reach, room, path))
|
|
384
|
+
return null;
|
|
385
|
+
if (runtime.locked(room))
|
|
386
|
+
throw lockedError(room);
|
|
387
|
+
return shownDraft(reach, await md.roomDraft.read(room, path));
|
|
388
|
+
},
|
|
389
|
+
write(room, path, revision, parts, next) {
|
|
390
|
+
try {
|
|
391
|
+
if (reach !== null && carriesFile(parts))
|
|
392
|
+
throw attachRequired();
|
|
393
|
+
const move = readParts(parts).move;
|
|
394
|
+
if (!covers(reach, room, path) || !moves(reach, room, move))
|
|
395
|
+
throw unreached(room);
|
|
396
|
+
if (runtime.locked(room))
|
|
397
|
+
throw lockedError(room);
|
|
398
|
+
if (intoLocked([move]))
|
|
399
|
+
throw lockedError(move.room);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
return Promise.reject(error);
|
|
243
403
|
}
|
|
244
|
-
return
|
|
404
|
+
return md.roomDraft
|
|
405
|
+
.write(room, path, revision, parts, next)
|
|
406
|
+
.then((written) => writeWithin(reach, written));
|
|
245
407
|
},
|
|
246
408
|
async discard(room, path, revision) {
|
|
247
409
|
if (!covers(reach, room, path))
|
|
248
|
-
return
|
|
410
|
+
return staleWrite(null);
|
|
411
|
+
if (runtime.locked(room))
|
|
412
|
+
throw lockedError(room);
|
|
249
413
|
return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
|
|
250
414
|
},
|
|
251
415
|
},
|
|
@@ -253,7 +417,7 @@ export function narrowed(runtime, given) {
|
|
|
253
417
|
list: () => conversation().list(),
|
|
254
418
|
read: (id, options) => conversation().read(id, options),
|
|
255
419
|
create: (input) => conversation().create(input),
|
|
256
|
-
send: (id) => conversation().send(id),
|
|
420
|
+
send: (id, operation, draft) => conversation().send(id, operation, draft),
|
|
257
421
|
answer: (id, answer) => conversation().answer(id, answer),
|
|
258
422
|
interrupt: (id) => conversation().interrupt(id),
|
|
259
423
|
kill: (id) => conversation().kill(id),
|
|
@@ -261,7 +425,8 @@ export function narrowed(runtime, given) {
|
|
|
261
425
|
delete: (id) => conversation().delete(id),
|
|
262
426
|
},
|
|
263
427
|
chatDraft: {
|
|
264
|
-
write: (id, draft) => chatDraft().write(id, draft),
|
|
428
|
+
write: (id, draft, revision) => chatDraft().write(id, draft, revision),
|
|
429
|
+
prepend: (id, draft) => chatDraft().prepend(id, draft),
|
|
265
430
|
discard: (id) => chatDraft().discard(id),
|
|
266
431
|
},
|
|
267
432
|
observe: observing(within),
|
|
@@ -274,5 +439,10 @@ export function narrowed(runtime, given) {
|
|
|
274
439
|
for (const restart of [...open])
|
|
275
440
|
restart();
|
|
276
441
|
},
|
|
442
|
+
facts(next) {
|
|
443
|
+
port = next;
|
|
444
|
+
for (const restart of [...open])
|
|
445
|
+
restart();
|
|
446
|
+
},
|
|
277
447
|
};
|
|
278
448
|
}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { MdRuntimeClient } from './client.js';
|
|
2
|
+
import type { AppRoom, ConnectionRefusal, SavedRoomDraft, SaveResult } from './connection.js';
|
|
3
|
+
import type { Member, ServiceMode } from './adapter.js';
|
|
4
|
+
import type { ConversationAgent, ConversationEntry, ConversationOptions, ConversationView } from './conversation.js';
|
|
5
|
+
import { type RuntimeError } from './failure.js';
|
|
6
|
+
import type { QueueEntry } from './outcome.js';
|
|
7
|
+
import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult, PendingResult } from './query.js';
|
|
8
|
+
import type { Readiness } from './readiness.js';
|
|
9
|
+
import type { RoomDraft, RoomDraftParts } from './room-draft.js';
|
|
10
|
+
import type { SyncStatus } from './status.js';
|
|
11
|
+
type Client = MdRuntimeClient | null;
|
|
12
|
+
export type Observed<T> = {
|
|
13
|
+
readonly state: 'loading';
|
|
14
|
+
} | {
|
|
15
|
+
readonly state: 'ready';
|
|
16
|
+
readonly value: T;
|
|
17
|
+
};
|
|
18
|
+
export declare function useObserve(client: Client, topic: 'deployment-facts'): Observed<unknown>;
|
|
19
|
+
export declare function useObserve(client: Client, topic: 'rooms'): Observed<readonly AppRoom[]>;
|
|
20
|
+
export declare function useObserve(client: Client, topic: 'readiness'): Observed<Readiness>;
|
|
21
|
+
export declare function useObserve(client: Client, topic: 'connection-refusal'): Observed<ConnectionRefusal | null>;
|
|
22
|
+
export declare function useObserve(client: Client, topic: 'storage-loss'): Observed<string | null>;
|
|
23
|
+
export declare function useObserve(client: Client, topic: 'sync-status'): Observed<SyncStatus>;
|
|
24
|
+
export declare function useObserve(client: Client, topic: 'service-mode'): Observed<ServiceMode>;
|
|
25
|
+
export declare function useObserve(client: Client, topic: 'member'): Observed<Member | null>;
|
|
26
|
+
export declare function useObserve(client: Client, topic: 'query', query: DocumentQuery): Observed<DocumentResult | PendingResult>;
|
|
27
|
+
export declare function useObserve(client: Client, topic: 'query', query: GroupQuery): Observed<GroupResult | PendingResult>;
|
|
28
|
+
export declare function useObserve(client: Client, topic: 'queue', locator: string): Observed<readonly QueueEntry[]>;
|
|
29
|
+
export declare function useObserve(client: Client, topic: 'room-drafts'): Observed<readonly RoomDraft[]>;
|
|
30
|
+
export declare function useObserve(client: Client, topic: 'presentation'): Observed<unknown>;
|
|
31
|
+
export declare function useObserve(client: Client, topic: 'conversation', conversation: string, options: ConversationOptions): Observed<ConversationView>;
|
|
32
|
+
export declare function useObserve(client: Client, topic: 'conversations'): Observed<readonly ConversationEntry[]>;
|
|
33
|
+
export declare function useObserve(client: Client, topic: 'agents'): Observed<readonly ConversationAgent[]>;
|
|
34
|
+
export type Saving = {
|
|
35
|
+
readonly busy: boolean;
|
|
36
|
+
readonly outcome: SaveResult | null;
|
|
37
|
+
readonly failure: RuntimeError | null;
|
|
38
|
+
save(room: string, parts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
|
|
39
|
+
saveWritten(room: string, roomDrafts: readonly SavedRoomDraft[]): Promise<SaveResult>;
|
|
40
|
+
};
|
|
41
|
+
export declare function useSave(client: MdRuntimeClient): Saving;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
import { failed } from './failure.js';
|
|
3
|
+
const LOADING = { state: 'loading' };
|
|
4
|
+
export function useObserve(client, topic, ...input) {
|
|
5
|
+
const key = JSON.stringify([topic, ...input]);
|
|
6
|
+
const [held, setHeld] = useState(null);
|
|
7
|
+
const opened = useRef(input);
|
|
8
|
+
opened.current = input;
|
|
9
|
+
useLayoutEffect(() => {
|
|
10
|
+
if (client === null)
|
|
11
|
+
return;
|
|
12
|
+
let live = true;
|
|
13
|
+
let observation = null;
|
|
14
|
+
const observe = client.observe;
|
|
15
|
+
void observe(topic, ...opened.current).then((open) => {
|
|
16
|
+
if (!live) {
|
|
17
|
+
open.close();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
observation = open;
|
|
21
|
+
const take = (value) => {
|
|
22
|
+
if (live)
|
|
23
|
+
setHeld({ client, key, observed: { state: 'ready', value } });
|
|
24
|
+
};
|
|
25
|
+
take(open.current());
|
|
26
|
+
open.subscribe(take);
|
|
27
|
+
});
|
|
28
|
+
return () => {
|
|
29
|
+
live = false;
|
|
30
|
+
observation?.close();
|
|
31
|
+
};
|
|
32
|
+
}, [client, key]);
|
|
33
|
+
return held !== null && held.client === client && held.key === key ? held.observed : LOADING;
|
|
34
|
+
}
|
|
35
|
+
const IDLE = { busy: false, outcome: null, failure: null };
|
|
36
|
+
export function useSave(client) {
|
|
37
|
+
const [state, setState] = useState(IDLE);
|
|
38
|
+
const settled = useCallback(async (saving) => {
|
|
39
|
+
setState({ busy: true, outcome: null, failure: null });
|
|
40
|
+
try {
|
|
41
|
+
const outcome = await saving();
|
|
42
|
+
setState({ busy: false, outcome, failure: null });
|
|
43
|
+
return outcome;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const failure = failed(error);
|
|
47
|
+
setState({ busy: false, outcome: null, failure });
|
|
48
|
+
throw failure;
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
const save = useCallback((room, parts) => settled(() => client.saveParts(room, [...parts].map(([path, one]) => ({ path, parts: one })))), [client, settled]);
|
|
52
|
+
const saveWritten = useCallback((room, roomDrafts) => settled(() => client.save(room, roomDrafts)), [client, settled]);
|
|
53
|
+
return { ...state, save, saveWritten };
|
|
54
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Open } from './open.js';
|
|
2
|
+
export type CodeAvailability = Open<'stored' | 'absent'>;
|
|
3
|
+
export type RoomPreparation = Open<'complete' | 'acquiring' | 'preparing' | 'refused' | 'unadmitted'>;
|
|
4
|
+
export type RoomCoverage = {
|
|
5
|
+
readonly room: string;
|
|
6
|
+
readonly state: RoomPreparation;
|
|
7
|
+
};
|
|
8
|
+
export type ConversationCoverage = Open<'complete' | 'acquiring' | 'undeclared'>;
|
|
9
|
+
export type SearchObligation = Open<'required' | 'unused'>;
|
|
10
|
+
export type TargetCoverage = {
|
|
11
|
+
readonly complete: boolean;
|
|
12
|
+
readonly listed: boolean;
|
|
13
|
+
readonly rooms: readonly RoomCoverage[];
|
|
14
|
+
readonly conversations: ConversationCoverage;
|
|
15
|
+
readonly search: SearchObligation;
|
|
16
|
+
};
|
|
17
|
+
export type Persistence = Open<'granted' | 'denied' | 'unavailable'>;
|
|
18
|
+
export type Durability = Open<'persistent' | 'best-effort'>;
|
|
19
|
+
export type ConnectionAvailability = Open<'connected' | 'connecting' | 'unreachable'>;
|
|
20
|
+
export type HouseOutcome = Open<'open' | 'write-halted' | 'refused'>;
|
|
21
|
+
export type Space = Open<'full'>;
|
|
22
|
+
export type RefusedRoom = {
|
|
23
|
+
readonly room: string;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly file: string;
|
|
26
|
+
readonly rule: string;
|
|
27
|
+
readonly location: string | null;
|
|
28
|
+
};
|
|
29
|
+
export type InstallationStep = Open<'listing' | 'downloading' | 'writing' | 'replaying'>;
|
|
30
|
+
export type InstallationPause = Open<'hidden'>;
|
|
31
|
+
export type InstallationAmount = {
|
|
32
|
+
readonly done: number;
|
|
33
|
+
readonly total: number;
|
|
34
|
+
};
|
|
35
|
+
export type Installation = {
|
|
36
|
+
readonly step: InstallationStep | null;
|
|
37
|
+
readonly paused: InstallationPause | null;
|
|
38
|
+
readonly rooms: InstallationAmount;
|
|
39
|
+
readonly parts: InstallationAmount;
|
|
40
|
+
readonly bytes: InstallationAmount;
|
|
41
|
+
readonly received: InstallationAmount;
|
|
42
|
+
};
|
|
43
|
+
export type ReadinessStatus = Open<'preparing' | 'paused' | 'refused' | 'ready' | 'lost'>;
|
|
44
|
+
export type Readiness = {
|
|
45
|
+
readonly status: ReadinessStatus;
|
|
46
|
+
readonly ready: boolean;
|
|
47
|
+
readonly usable: boolean;
|
|
48
|
+
readonly code: CodeAvailability;
|
|
49
|
+
readonly coverage: TargetCoverage;
|
|
50
|
+
readonly durability: Durability;
|
|
51
|
+
readonly persistence: Persistence;
|
|
52
|
+
readonly connection: ConnectionAvailability;
|
|
53
|
+
readonly house: HouseOutcome;
|
|
54
|
+
readonly space: Space | null;
|
|
55
|
+
readonly installation: Installation;
|
|
56
|
+
readonly refused: readonly RefusedRoom[];
|
|
57
|
+
readonly lost: boolean;
|
|
58
|
+
};
|
|
59
|
+
export type ReadinessFacts = Omit<Readiness, 'status' | 'ready' | 'usable' | 'durability' | 'coverage'> & {
|
|
60
|
+
readonly coverage: Omit<TargetCoverage, 'complete'>;
|
|
61
|
+
readonly established: boolean;
|
|
62
|
+
};
|
|
63
|
+
export declare function readinessOf(facts: ReadinessFacts): Readiness;
|
|
64
|
+
//# sourceMappingURL=readiness.d.ts.map
|