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