@agentshouse/mdruntime 0.1.0-c6e4c19c13638 → 0.1.0-c6f02ec9468d4
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 +23 -10
- package/dist/adapter.d.ts +156 -43
- 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 +53 -6
- 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 +33 -5
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +201 -48
- 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 -16
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +156 -20
- package/dist/collection.d.ts +12 -14
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +52 -56
- 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 +61 -20
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3877 -885
- package/dist/conversation.d.ts +48 -19
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +723 -240
- 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/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 +370 -0
- package/dist/host.d.ts +13 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +134 -24
- 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 +20 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -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 +18 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +252 -92
- 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 +19 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -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/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 +72 -5
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +81 -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 +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +70 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +53 -38
- package/dist/reach.d.ts +18 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +235 -64
- package/dist/react.d.ts +32 -19
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +13 -21
- 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 +20 -7
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +148 -59
- package/dist/replica.d.ts +58 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +320 -157
- package/dist/room-draft.d.ts +57 -10
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +222 -39
- package/dist/rows.d.ts +39 -35
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +176 -99
- package/dist/save.d.ts +73 -4
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +825 -150
- 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 +15 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +421 -0
- package/dist/status.d.ts +7 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -9
- package/dist/store.d.ts +110 -59
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +324 -344
- 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 +170 -33
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +69 -31
- 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 -241
- 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 -433
package/dist/reach.js
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
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
|
-
|
|
22
|
-
delete: undeclared,
|
|
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'),
|
|
23
23
|
};
|
|
24
24
|
const NO_CHAT_DRAFT = {
|
|
25
25
|
write: () => Promise.resolve(),
|
|
26
|
+
prepend: () => Promise.resolve(),
|
|
26
27
|
discard: () => Promise.resolve(),
|
|
27
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
|
+
}
|
|
28
37
|
export function holds(reach, room) {
|
|
29
38
|
return (reach === null ||
|
|
30
39
|
reach.rooms.includes(room) ||
|
|
@@ -45,8 +54,9 @@ export function governs(reach, room) {
|
|
|
45
54
|
}
|
|
46
55
|
function covers(reach, room, path) {
|
|
47
56
|
return (reach === null ||
|
|
48
|
-
reach
|
|
49
|
-
|
|
57
|
+
(!fenced(reach, room, path) &&
|
|
58
|
+
(reach.rooms.includes(room) ||
|
|
59
|
+
reach.documents.some((document) => document.room === room && document.path === path))));
|
|
50
60
|
}
|
|
51
61
|
function conversing(reach) {
|
|
52
62
|
return reach === null || reach.conversations;
|
|
@@ -59,6 +69,9 @@ export function planReach(reach) {
|
|
|
59
69
|
documents: [
|
|
60
70
|
...new Set(reach.documents.map(({ room, path }) => documentKey(room, path))),
|
|
61
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),
|
|
62
75
|
};
|
|
63
76
|
}
|
|
64
77
|
function roomsWithin(reach, rooms) {
|
|
@@ -74,7 +87,7 @@ function typesWithin(reach, room, types) {
|
|
|
74
87
|
};
|
|
75
88
|
}
|
|
76
89
|
function moves(reach, room, move) {
|
|
77
|
-
return move === undefined || covers(reach, room, moveTarget(move));
|
|
90
|
+
return move === undefined || covers(reach, move.room ?? room, moveTarget(move));
|
|
78
91
|
}
|
|
79
92
|
function draftWithin(reach, draft) {
|
|
80
93
|
return covers(reach, draft.room, draft.path) && moves(reach, draft.room, draft.parts.move);
|
|
@@ -88,7 +101,7 @@ function shownDraft(reach, draft) {
|
|
|
88
101
|
function writeWithin(reach, write) {
|
|
89
102
|
return write.outcome === 'written'
|
|
90
103
|
? { outcome: 'written', roomDraft: shownDraft(reach, write.roomDraft) }
|
|
91
|
-
:
|
|
104
|
+
: staleWrite(shownDraft(reach, write.current));
|
|
92
105
|
}
|
|
93
106
|
function savedWithin(reach, room, result) {
|
|
94
107
|
if (reach === null || result.outcome === 'saved')
|
|
@@ -108,75 +121,127 @@ function statusWithin(reach, status) {
|
|
|
108
121
|
return {
|
|
109
122
|
...status,
|
|
110
123
|
attentionRequired: status.attentionRequired.filter((entry) => covers(reach, entry.room, entry.path)),
|
|
124
|
+
unsent: status.unsent.filter((change) => covers(reach, change.room, change.path)),
|
|
111
125
|
};
|
|
112
126
|
}
|
|
113
127
|
function queueWithin(reach, room, entries) {
|
|
114
|
-
return entries
|
|
115
|
-
(
|
|
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
|
+
});
|
|
116
139
|
}
|
|
117
140
|
function unreached(room) {
|
|
118
|
-
return
|
|
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);
|
|
119
145
|
}
|
|
120
|
-
|
|
146
|
+
function deviceUnreached() {
|
|
147
|
+
return runtimeError('device-unreached', 'Only the panel cleans up this device');
|
|
148
|
+
}
|
|
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) {
|
|
121
157
|
const { md, watch } = runtime;
|
|
122
158
|
let reach = given;
|
|
159
|
+
let port = told;
|
|
123
160
|
const open = new Set();
|
|
124
|
-
function following(begin) {
|
|
161
|
+
function following(begin, locking = false) {
|
|
125
162
|
let stop = begin();
|
|
126
163
|
const restart = () => {
|
|
127
164
|
stop();
|
|
128
165
|
stop = begin();
|
|
129
166
|
};
|
|
130
167
|
open.add(restart);
|
|
168
|
+
const unwatch = locking ? runtime.watchLocks(restart) : () => { };
|
|
131
169
|
return () => {
|
|
132
170
|
open.delete(restart);
|
|
171
|
+
unwatch();
|
|
133
172
|
stop();
|
|
134
173
|
};
|
|
135
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));
|
|
136
183
|
const within = (topic, input, deliver) => {
|
|
137
184
|
if (topic === 'rooms') {
|
|
138
185
|
return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms))));
|
|
139
186
|
}
|
|
187
|
+
if (topic === 'readiness') {
|
|
188
|
+
return following(() => runtime.watchReadiness(port, reach, deliver));
|
|
189
|
+
}
|
|
140
190
|
if (topic === 'sync-status') {
|
|
141
|
-
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);
|
|
142
195
|
}
|
|
143
196
|
if (topic === 'room-drafts') {
|
|
144
|
-
return following(() => watch(topic, input, (drafts) => deliver(draftsWithin(reach, drafts))));
|
|
197
|
+
return following(() => watch(topic, input, (drafts) => deliver(unlocked(draftsWithin(reach, drafts)))), true);
|
|
145
198
|
}
|
|
146
199
|
if (topic === 'queue') {
|
|
147
200
|
const room = input[0];
|
|
148
201
|
return following(() => {
|
|
149
|
-
if (!holds(reach, room)) {
|
|
202
|
+
if (!holds(reach, room) || runtime.locked(room)) {
|
|
150
203
|
deliver([]);
|
|
151
204
|
return () => { };
|
|
152
205
|
}
|
|
153
206
|
return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)));
|
|
154
|
-
});
|
|
207
|
+
}, true);
|
|
155
208
|
}
|
|
156
209
|
if (topic === 'query') {
|
|
157
210
|
const plan = runtime.plan(input[0], reach);
|
|
158
211
|
let held = null;
|
|
159
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
|
+
}
|
|
160
221
|
let first = true;
|
|
161
|
-
|
|
222
|
+
let open = true;
|
|
223
|
+
const heard = (message) => {
|
|
162
224
|
if (!first) {
|
|
163
|
-
held =
|
|
225
|
+
held = digestApplied(held, message);
|
|
164
226
|
deliver(message);
|
|
165
227
|
return;
|
|
166
228
|
}
|
|
167
229
|
first = false;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
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);
|
|
178
239
|
});
|
|
179
|
-
|
|
240
|
+
return () => {
|
|
241
|
+
open = false;
|
|
242
|
+
stop();
|
|
243
|
+
};
|
|
244
|
+
}, true);
|
|
180
245
|
}
|
|
181
246
|
if (topic === 'conversation') {
|
|
182
247
|
return following(() => {
|
|
@@ -186,7 +251,7 @@ export function narrowed(runtime, given) {
|
|
|
186
251
|
return () => { };
|
|
187
252
|
});
|
|
188
253
|
}
|
|
189
|
-
if (topic === 'conversations') {
|
|
254
|
+
if (topic === 'conversations' || topic === 'agents') {
|
|
190
255
|
return following(() => {
|
|
191
256
|
if (conversing(reach))
|
|
192
257
|
return watch(topic, input, deliver);
|
|
@@ -196,48 +261,149 @@ export function narrowed(runtime, given) {
|
|
|
196
261
|
}
|
|
197
262
|
return watch(topic, input, deliver);
|
|
198
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
|
+
}
|
|
199
275
|
const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
|
|
200
276
|
const chatDraft = () => (conversing(reach) ? md.chatDraft : NO_CHAT_DRAFT);
|
|
201
277
|
const view = {
|
|
202
278
|
...md,
|
|
203
|
-
rooms: () => roomsWithin(reach,
|
|
204
|
-
query: ((input) =>
|
|
205
|
-
|
|
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()),
|
|
206
287
|
types(room) {
|
|
288
|
+
if (holds(reach, room) && runtime.locked(room))
|
|
289
|
+
throw lockedError(room);
|
|
207
290
|
if (wholly(reach, room))
|
|
208
291
|
return md.types(room);
|
|
209
292
|
if (!holds(reach, room))
|
|
210
293
|
return structuredClone(UNHELD_TYPES);
|
|
211
|
-
|
|
212
|
-
return typesWithin(reach, listed, md.types(room));
|
|
294
|
+
return typesWithin(reach, runtime.room(room), md.types(room));
|
|
213
295
|
},
|
|
214
296
|
async save(room, roomDrafts, writtenBy) {
|
|
215
297
|
if (!holds(reach, room))
|
|
216
298
|
throw unreached(room);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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]));
|
|
303
|
+
if (outside !== undefined) {
|
|
304
|
+
return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
|
|
305
|
+
}
|
|
306
|
+
if (intoLocked(held))
|
|
307
|
+
return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
|
|
221
308
|
return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
|
|
222
309
|
},
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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)),
|
|
228
372
|
log: () => (reach === null ? md.log() : ''),
|
|
373
|
+
cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
|
|
229
374
|
roomDraft: {
|
|
230
|
-
list: () => md.roomDraft.list().then((drafts) => draftsWithin(reach, drafts)),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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);
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
return Promise.reject(error);
|
|
235
397
|
}
|
|
236
|
-
return
|
|
398
|
+
return md.roomDraft
|
|
399
|
+
.write(room, path, revision, parts, next)
|
|
400
|
+
.then((written) => writeWithin(reach, written));
|
|
237
401
|
},
|
|
238
402
|
async discard(room, path, revision) {
|
|
239
403
|
if (!covers(reach, room, path))
|
|
240
|
-
return
|
|
404
|
+
return staleWrite(null);
|
|
405
|
+
if (runtime.locked(room))
|
|
406
|
+
throw lockedError(room);
|
|
241
407
|
return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
|
|
242
408
|
},
|
|
243
409
|
},
|
|
@@ -245,15 +411,15 @@ export function narrowed(runtime, given) {
|
|
|
245
411
|
list: () => conversation().list(),
|
|
246
412
|
read: (id, options) => conversation().read(id, options),
|
|
247
413
|
create: (input) => conversation().create(input),
|
|
248
|
-
send: (id) => conversation().send(id),
|
|
414
|
+
send: (id, operation, draft) => conversation().send(id, operation, draft),
|
|
249
415
|
answer: (id, answer) => conversation().answer(id, answer),
|
|
250
416
|
interrupt: (id) => conversation().interrupt(id),
|
|
251
417
|
kill: (id) => conversation().kill(id),
|
|
252
|
-
cancel: (id, turn) => conversation().cancel(id, turn),
|
|
253
418
|
delete: (id) => conversation().delete(id),
|
|
254
419
|
},
|
|
255
420
|
chatDraft: {
|
|
256
|
-
write: (id, draft) => chatDraft().write(id, draft),
|
|
421
|
+
write: (id, draft, revision) => chatDraft().write(id, draft, revision),
|
|
422
|
+
prepend: (id, draft) => chatDraft().prepend(id, draft),
|
|
257
423
|
discard: (id) => chatDraft().discard(id),
|
|
258
424
|
},
|
|
259
425
|
observe: observing(within),
|
|
@@ -266,5 +432,10 @@ export function narrowed(runtime, given) {
|
|
|
266
432
|
for (const restart of [...open])
|
|
267
433
|
restart();
|
|
268
434
|
},
|
|
435
|
+
facts(next) {
|
|
436
|
+
port = next;
|
|
437
|
+
for (const restart of [...open])
|
|
438
|
+
restart();
|
|
439
|
+
},
|
|
269
440
|
};
|
|
270
441
|
}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
import type { MdRuntimeClient } from './client.js';
|
|
2
|
-
import type { AppRoom, ConnectionRefusal, SaveResult } from './connection.js';
|
|
3
|
-
import type { ServiceMode } from './adapter.js';
|
|
4
|
-
import type { ConversationEntry, ConversationOptions, ConversationView } from './conversation.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';
|
|
5
6
|
import type { QueueEntry } from './outcome.js';
|
|
6
|
-
import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult } from './query.js';
|
|
7
|
+
import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult, PendingResult } from './query.js';
|
|
8
|
+
import type { Readiness } from './readiness.js';
|
|
7
9
|
import type { RoomDraft, RoomDraftParts } from './room-draft.js';
|
|
8
10
|
import type { SyncStatus } from './status.js';
|
|
9
11
|
type Client = MdRuntimeClient | null;
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export declare function useObserve(client: Client, topic: '
|
|
17
|
-
export declare function useObserve(client: Client, topic: '
|
|
18
|
-
export declare function useObserve(client: Client, topic: '
|
|
19
|
-
export declare function useObserve(client: Client, topic: '
|
|
20
|
-
export declare function useObserve(client: Client, topic: '
|
|
21
|
-
export declare function useObserve(client: Client, topic: '
|
|
22
|
-
export declare function useObserve(client: Client, topic: '
|
|
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: 'authority-changes'): Observed<number>;
|
|
27
|
+
export declare function useObserve(client: Client, topic: 'query', query: DocumentQuery): Observed<DocumentResult | PendingResult>;
|
|
28
|
+
export declare function useObserve(client: Client, topic: 'query', query: GroupQuery): Observed<GroupResult | PendingResult>;
|
|
29
|
+
export declare function useObserve(client: Client, topic: 'queue', locator: string): Observed<readonly QueueEntry[]>;
|
|
30
|
+
export declare function useObserve(client: Client, topic: 'room-drafts'): Observed<readonly RoomDraft[]>;
|
|
31
|
+
export declare function useObserve(client: Client, topic: 'presentation'): Observed<unknown>;
|
|
32
|
+
export declare function useObserve(client: Client, topic: 'conversation', conversation: string, options: ConversationOptions): Observed<ConversationView>;
|
|
33
|
+
export declare function useObserve(client: Client, topic: 'conversations'): Observed<readonly ConversationEntry[]>;
|
|
34
|
+
export declare function useObserve(client: Client, topic: 'agents'): Observed<readonly ConversationAgent[]>;
|
|
23
35
|
export type Saving = {
|
|
24
36
|
readonly busy: boolean;
|
|
25
37
|
readonly outcome: SaveResult | null;
|
|
26
|
-
readonly failure:
|
|
27
|
-
save(room: string,
|
|
38
|
+
readonly failure: RuntimeError | null;
|
|
39
|
+
save(room: string, parts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
|
|
40
|
+
saveWritten(room: string, roomDrafts: readonly SavedRoomDraft[]): Promise<SaveResult>;
|
|
28
41
|
};
|
|
29
42
|
export declare function useSave(client: MdRuntimeClient): Saving;
|
|
30
43
|
export {};
|
package/dist/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
|
package/dist/react.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { useCallback,
|
|
1
|
+
import { useCallback, useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
import { failed } from './failure.js';
|
|
3
|
+
const LOADING = { state: 'loading' };
|
|
2
4
|
export function useObserve(client, topic, ...input) {
|
|
3
5
|
const key = JSON.stringify([topic, ...input]);
|
|
4
6
|
const [held, setHeld] = useState(null);
|
|
5
7
|
const opened = useRef(input);
|
|
6
8
|
opened.current = input;
|
|
7
|
-
|
|
9
|
+
useLayoutEffect(() => {
|
|
8
10
|
if (client === null)
|
|
9
11
|
return;
|
|
10
12
|
let live = true;
|
|
@@ -18,7 +20,7 @@ export function useObserve(client, topic, ...input) {
|
|
|
18
20
|
observation = open;
|
|
19
21
|
const take = (value) => {
|
|
20
22
|
if (live)
|
|
21
|
-
setHeld({ client, key, value });
|
|
23
|
+
setHeld({ client, key, observed: { state: 'ready', value } });
|
|
22
24
|
};
|
|
23
25
|
take(open.current());
|
|
24
26
|
open.subscribe(take);
|
|
@@ -28,35 +30,25 @@ export function useObserve(client, topic, ...input) {
|
|
|
28
30
|
observation?.close();
|
|
29
31
|
};
|
|
30
32
|
}, [client, key]);
|
|
31
|
-
return held !== null && held.client === client && held.key === key ? held.
|
|
33
|
+
return held !== null && held.client === client && held.key === key ? held.observed : LOADING;
|
|
32
34
|
}
|
|
33
35
|
const IDLE = { busy: false, outcome: null, failure: null };
|
|
34
|
-
async function written(client, room, roomDrafts) {
|
|
35
|
-
const kept = [];
|
|
36
|
-
for (const [path, parts] of roomDrafts) {
|
|
37
|
-
const prior = await client.roomDraft.read(room, path);
|
|
38
|
-
const write = await client.roomDraft.write(room, path, prior?.revision ?? null, parts);
|
|
39
|
-
if (write.outcome !== 'written' || write.roomDraft === null) {
|
|
40
|
-
throw new Error(`the Room Draft at ${path} was not written`);
|
|
41
|
-
}
|
|
42
|
-
kept.push({ path, revision: write.roomDraft.revision });
|
|
43
|
-
}
|
|
44
|
-
return client.save(room, kept);
|
|
45
|
-
}
|
|
46
36
|
export function useSave(client) {
|
|
47
37
|
const [state, setState] = useState(IDLE);
|
|
48
|
-
const
|
|
38
|
+
const settled = useCallback(async (saving) => {
|
|
49
39
|
setState({ busy: true, outcome: null, failure: null });
|
|
50
40
|
try {
|
|
51
|
-
const outcome = await
|
|
41
|
+
const outcome = await saving();
|
|
52
42
|
setState({ busy: false, outcome, failure: null });
|
|
53
43
|
return outcome;
|
|
54
44
|
}
|
|
55
45
|
catch (error) {
|
|
56
|
-
const failure =
|
|
46
|
+
const failure = failed(error);
|
|
57
47
|
setState({ busy: false, outcome: null, failure });
|
|
58
48
|
throw failure;
|
|
59
49
|
}
|
|
60
|
-
}, [
|
|
61
|
-
|
|
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 };
|
|
62
54
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Open } from './open.js';
|
|
2
|
+
export type CodeAvailability = Open<'stored' | 'absent'>;
|
|
3
|
+
export type RoomPreparation = Open<'complete' | 'acquiring' | 'preparing' | '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 InstallationStep = Open<'downloading' | 'writing' | 'replaying'>;
|
|
23
|
+
export type InstallationAmount = {
|
|
24
|
+
readonly done: number;
|
|
25
|
+
readonly total: number;
|
|
26
|
+
};
|
|
27
|
+
export type Installation = {
|
|
28
|
+
readonly step: InstallationStep | null;
|
|
29
|
+
readonly rooms: InstallationAmount;
|
|
30
|
+
readonly bytes: InstallationAmount;
|
|
31
|
+
};
|
|
32
|
+
export type ReadinessStatus = Open<'preparing' | 'paused' | 'ready' | 'lost'>;
|
|
33
|
+
export type Readiness = {
|
|
34
|
+
readonly status: ReadinessStatus;
|
|
35
|
+
readonly ready: boolean;
|
|
36
|
+
readonly usable: boolean;
|
|
37
|
+
readonly code: CodeAvailability;
|
|
38
|
+
readonly coverage: TargetCoverage;
|
|
39
|
+
readonly durability: Durability;
|
|
40
|
+
readonly persistence: Persistence;
|
|
41
|
+
readonly connection: ConnectionAvailability;
|
|
42
|
+
readonly house: HouseOutcome;
|
|
43
|
+
readonly space: Space | null;
|
|
44
|
+
readonly installation: Installation;
|
|
45
|
+
readonly lost: boolean;
|
|
46
|
+
};
|
|
47
|
+
export type ReadinessFacts = Omit<Readiness, 'status' | 'ready' | 'usable' | 'durability' | 'coverage'> & {
|
|
48
|
+
readonly coverage: Omit<TargetCoverage, 'complete'>;
|
|
49
|
+
readonly established: boolean;
|
|
50
|
+
};
|
|
51
|
+
export declare function readinessOf(facts: ReadinessFacts): Readiness;
|
|
52
|
+
//# sourceMappingURL=readiness.d.ts.map
|