@agentshouse/mdruntime 0.1.0-cba6f2439bb25 → 0.1.0-cbbae1fff01c6
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 +10 -10
- package/dist/acceptance.d.ts +3 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +308 -0
- package/dist/actions.d.ts +20 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +251 -0
- package/dist/adapter.d.ts +95 -103
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +3 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +21 -56
- package/dist/bootstrap.d.ts +12 -11
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +213 -89
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/change-set.d.ts +4 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +6 -0
- package/dist/change.d.ts +1 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +4 -2
- package/dist/chat-types.d.ts +5 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +13 -0
- package/dist/client.d.ts +24 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -5
- package/dist/collection.d.ts +23 -7
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +13 -19
- package/dist/compile.d.ts +6 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +272 -332
- package/dist/connection.d.ts +5 -143
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +105 -5253
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- package/dist/conversation-live.d.ts +135 -0
- package/dist/conversation-live.d.ts.map +1 -0
- package/dist/conversation-live.js +247 -0
- package/dist/conversation-row.d.ts +33 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +53 -0
- package/dist/conversation.d.ts +41 -47
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +874 -911
- package/dist/declaration.d.ts +10 -0
- package/dist/declaration.d.ts.map +1 -0
- package/dist/declaration.js +24 -0
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +148 -0
- package/dist/durability.d.ts +15 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +2 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +17 -7
- package/dist/expectation.d.ts +4 -2
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +33 -11
- package/dist/failure.d.ts +1 -0
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +3 -0
- package/dist/figures.d.ts +49 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +197 -0
- package/dist/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +20 -8
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +44 -34
- package/dist/identity.d.ts +0 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -3
- package/dist/index.d.ts +28 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/install.d.ts +54 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +538 -0
- package/dist/job.d.ts +5 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +7 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +272 -0
- package/dist/listing.d.ts +48 -0
- package/dist/listing.d.ts.map +1 -0
- package/dist/listing.js +139 -0
- package/dist/live.d.ts +5 -4
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +64 -23
- package/dist/locks.d.ts +7 -0
- package/dist/locks.d.ts.map +1 -0
- package/dist/locks.js +33 -0
- package/dist/log.d.ts +1 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/lost.d.ts +5 -0
- package/dist/lost.d.ts.map +1 -0
- package/dist/lost.js +50 -0
- package/dist/media.d.ts +2 -2
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +22 -12
- package/dist/memory.d.ts +14 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +177 -85
- package/dist/messages.d.ts +24 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +89 -31
- package/dist/model.d.ts +2 -11
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -23
- package/dist/models.d.ts +10 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +156 -0
- package/dist/observation.d.ts +2 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +14 -14
- package/dist/opened.d.ts +1 -1
- package/dist/opened.d.ts.map +1 -1
- package/dist/opened.js +5 -5
- package/dist/opening.d.ts +4 -0
- package/dist/opening.d.ts.map +1 -0
- package/dist/opening.js +59 -0
- package/dist/outcome.d.ts +4 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +3 -0
- package/dist/overlay.d.ts +3 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +43 -21
- package/dist/parts.d.ts +11 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +21 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +22 -0
- package/dist/preparation.d.ts +20 -0
- package/dist/preparation.d.ts.map +1 -0
- package/dist/preparation.js +233 -0
- package/dist/presence.d.ts +52 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +220 -0
- package/dist/queries.d.ts +16 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +270 -0
- package/dist/query.d.ts +14 -210
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- package/dist/questions.d.ts +34 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +122 -0
- package/dist/queue.d.ts +40 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +455 -0
- package/dist/reach.d.ts +15 -13
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +187 -140
- package/dist/react.d.ts +14 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +10 -1
- package/dist/read.d.ts +7 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +17 -0
- package/dist/readiness.d.ts +2 -16
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +4 -10
- package/dist/reads.d.ts +36 -10
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +160 -77
- package/dist/recovery.d.ts +1 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +35 -1
- package/dist/refresh.d.ts +7 -5
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +35 -7
- package/dist/refusal.d.ts +5 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +57 -0
- package/dist/replica.d.ts +11 -17
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +64 -34
- package/dist/room-draft.d.ts +7 -8
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +100 -103
- package/dist/room-drafts.d.ts +24 -0
- package/dist/room-drafts.d.ts.map +1 -0
- package/dist/room-drafts.js +217 -0
- package/dist/rows.d.ts +14 -21
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +49 -186
- package/dist/runtime.d.ts +34 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/save.d.ts +41 -86
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +239 -116
- package/dist/saves.d.ts +32 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +413 -0
- package/dist/search.d.ts +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- package/dist/seed.d.ts +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -1
- package/dist/shared.d.ts +1 -7
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +13 -105
- package/dist/shown.d.ts +32 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +290 -0
- package/dist/socket/admission.d.ts +7 -0
- package/dist/socket/admission.d.ts.map +1 -0
- package/dist/socket/admission.js +39 -0
- package/dist/socket/answers.d.ts +6 -0
- package/dist/socket/answers.d.ts.map +1 -0
- package/dist/socket/answers.js +20 -0
- package/dist/socket/lanes.d.ts +20 -0
- package/dist/socket/lanes.d.ts.map +1 -0
- package/dist/socket/lanes.js +77 -0
- package/dist/socket/reads.d.ts +10 -0
- package/dist/socket/reads.d.ts.map +1 -0
- package/dist/socket/reads.js +31 -0
- package/dist/socket/session.d.ts +38 -0
- package/dist/socket/session.d.ts.map +1 -0
- package/dist/socket/session.js +23 -0
- package/dist/socket.d.ts +67 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +170 -0
- package/dist/source.d.ts +61 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +82 -0
- package/dist/status.d.ts +0 -6
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -6
- package/dist/store/installs.d.ts +30 -0
- package/dist/store/installs.d.ts.map +1 -0
- package/dist/store/installs.js +34 -0
- package/dist/store/readiness.d.ts +10 -0
- package/dist/store/readiness.d.ts.map +1 -0
- package/dist/store/readiness.js +52 -0
- package/dist/store/records.d.ts +210 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +428 -0
- package/dist/store/room-held.d.ts +8 -0
- package/dist/store/room-held.d.ts.map +1 -0
- package/dist/store/room-held.js +17 -0
- package/dist/store/space.d.ts +11 -0
- package/dist/store/space.d.ts.map +1 -0
- package/dist/store/space.js +41 -0
- package/dist/store/watchers.d.ts +17 -0
- package/dist/store/watchers.d.ts.map +1 -0
- package/dist/store/watchers.js +56 -0
- package/dist/store/writes.d.ts +24 -0
- package/dist/store/writes.d.ts.map +1 -0
- package/dist/store/writes.js +125 -0
- package/dist/store.d.ts +110 -157
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +162 -394
- package/dist/stored.d.ts +59 -38
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +287 -206
- package/dist/surface.d.ts +88 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +223 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +521 -0
- package/dist/tables.d.ts +116 -56
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +214 -98
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +129 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/validation.d.ts +3 -4
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +42 -100
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +21 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +10 -4
- package/package.json +3 -2
- package/dist/fence.d.ts +0 -6
- package/dist/fence.d.ts.map +0 -1
- package/dist/fence.js +0 -10
- package/dist/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -370
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -156
package/dist/presence.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const UNANSWERED = {
|
|
2
|
+
stale: false,
|
|
3
|
+
repairable: null,
|
|
4
|
+
repairing: false,
|
|
5
|
+
reloadDue: false,
|
|
6
|
+
refusal: null,
|
|
7
|
+
unreading: false,
|
|
8
|
+
unreadable: false,
|
|
9
|
+
unheldModel: null,
|
|
10
|
+
confirmed: false,
|
|
11
|
+
};
|
|
12
|
+
// A Room the Provider answers not ready is asked again after these waits, the last repeating, so a chunk build that catches up within seconds installs at once and a long one is asked every 15 seconds.
|
|
13
|
+
const NOT_READY_MS = [1_000, 2_000, 3_000, 5_000, 8_000, 11_000, 15_000];
|
|
14
|
+
// A Room that locks offline stays readable this long after the connection drops, so a laptop waking or changing network keeps working while a disconnected device locks soon after.
|
|
15
|
+
const LOCK_GRACE_MS = 120_000;
|
|
16
|
+
export function createPresence() {
|
|
17
|
+
const listed = new Map();
|
|
18
|
+
const answered = new Map();
|
|
19
|
+
const marks = new Map();
|
|
20
|
+
const lastLost = new Map();
|
|
21
|
+
const unready = new Map();
|
|
22
|
+
let lossCount = 0;
|
|
23
|
+
let lockGrace = null;
|
|
24
|
+
function answer(locator) {
|
|
25
|
+
return answered.get(locator) ?? UNANSWERED;
|
|
26
|
+
}
|
|
27
|
+
function change(locator, next) {
|
|
28
|
+
answered.set(locator, { ...answer(locator), ...next });
|
|
29
|
+
}
|
|
30
|
+
function heard(locator, next) {
|
|
31
|
+
if (!marks.has(locator))
|
|
32
|
+
change(locator, next);
|
|
33
|
+
}
|
|
34
|
+
function readied(locator) {
|
|
35
|
+
const held = unready.get(locator);
|
|
36
|
+
if (held === undefined)
|
|
37
|
+
return;
|
|
38
|
+
if (held.timer !== null)
|
|
39
|
+
clearTimeout(held.timer);
|
|
40
|
+
unready.delete(locator);
|
|
41
|
+
}
|
|
42
|
+
function stopAsking(locator) {
|
|
43
|
+
for (const held of locator === undefined ? [...unready.keys()] : [locator])
|
|
44
|
+
readied(held);
|
|
45
|
+
}
|
|
46
|
+
function connectionLive() {
|
|
47
|
+
if (lockGrace !== null)
|
|
48
|
+
clearTimeout(lockGrace);
|
|
49
|
+
lockGrace = null;
|
|
50
|
+
}
|
|
51
|
+
function readable(locator) {
|
|
52
|
+
const { unreadable, unreading } = answer(locator);
|
|
53
|
+
if (!unreadable || marks.has(locator))
|
|
54
|
+
return false;
|
|
55
|
+
change(locator, {
|
|
56
|
+
unreadable: false,
|
|
57
|
+
...(unreading ? { refusal: null, unreading: false } : {}),
|
|
58
|
+
});
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
function locks(locator, mode) {
|
|
62
|
+
return mode === 'locked' && !answer(locator).confirmed && !marks.has(locator);
|
|
63
|
+
}
|
|
64
|
+
function liftable(locator, discovery) {
|
|
65
|
+
const mark = marks.get(locator);
|
|
66
|
+
return mark === undefined || mark.during < discovery;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
list(found, { whole, live }) {
|
|
70
|
+
const kept = found.filter(({ locator }) => !marks.has(locator));
|
|
71
|
+
if (whole)
|
|
72
|
+
listed.clear();
|
|
73
|
+
for (const room of kept) {
|
|
74
|
+
listed.set(room.locator, room);
|
|
75
|
+
change(room.locator, {
|
|
76
|
+
refusal: null,
|
|
77
|
+
unreading: false,
|
|
78
|
+
...(live && room.replica.admission === 'admitted' ? { confirmed: true } : {}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return kept;
|
|
82
|
+
},
|
|
83
|
+
room: (locator) => listed.get(locator),
|
|
84
|
+
rooms: () => [...listed.values()],
|
|
85
|
+
available(locator, selection) {
|
|
86
|
+
if (marks.has(locator))
|
|
87
|
+
return false;
|
|
88
|
+
const room = listed.get(locator);
|
|
89
|
+
if (room === undefined)
|
|
90
|
+
return true;
|
|
91
|
+
return ((selection === undefined || selection === room.replica.selection) &&
|
|
92
|
+
room.replica.admission === 'admitted' &&
|
|
93
|
+
!answer(locator).unreadable);
|
|
94
|
+
},
|
|
95
|
+
refusal: (locator) => answer(locator).refusal,
|
|
96
|
+
unheldModel: (locator) => answer(locator).unheldModel,
|
|
97
|
+
refused(locator, refusal) {
|
|
98
|
+
if (refusal === null) {
|
|
99
|
+
heard(locator, { unreadable: true });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const unreading = refusal.scope !== 'operation' && refusal.scope !== 'model';
|
|
103
|
+
heard(locator, {
|
|
104
|
+
refusal: { code: refusal.code, fields: refusal.fields, retryable: refusal.retryable },
|
|
105
|
+
unreading,
|
|
106
|
+
...(unreading ? { unreadable: true } : {}),
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
readable,
|
|
110
|
+
modelled(locator, model) {
|
|
111
|
+
heard(locator, { unheldModel: model });
|
|
112
|
+
},
|
|
113
|
+
installed(locator, bootstrapped) {
|
|
114
|
+
if (marks.has(locator))
|
|
115
|
+
return;
|
|
116
|
+
if (bootstrapped) {
|
|
117
|
+
readied(locator);
|
|
118
|
+
change(locator, { unheldModel: null });
|
|
119
|
+
}
|
|
120
|
+
change(locator, { stale: false });
|
|
121
|
+
readable(locator);
|
|
122
|
+
},
|
|
123
|
+
async locked(locator, stored) {
|
|
124
|
+
if (marks.has(locator) || answer(locator).confirmed)
|
|
125
|
+
return false;
|
|
126
|
+
return locks(locator, (await stored()) ?? listed.get(locator)?.replica.offline);
|
|
127
|
+
},
|
|
128
|
+
lockedAmong(stored) {
|
|
129
|
+
const modes = new Map([...listed].map(([locator, room]) => [locator, room.replica.offline]));
|
|
130
|
+
for (const [locator, mode] of stored)
|
|
131
|
+
modes.set(locator, mode);
|
|
132
|
+
return [...modes]
|
|
133
|
+
.filter(([locator, mode]) => locks(locator, mode))
|
|
134
|
+
.map(([locator]) => locator)
|
|
135
|
+
.sort();
|
|
136
|
+
},
|
|
137
|
+
connectionLost(lapsed) {
|
|
138
|
+
if (lockGrace !== null)
|
|
139
|
+
return;
|
|
140
|
+
lockGrace = setTimeout(() => {
|
|
141
|
+
lockGrace = null;
|
|
142
|
+
lapsed();
|
|
143
|
+
}, LOCK_GRACE_MS);
|
|
144
|
+
},
|
|
145
|
+
connectionLive,
|
|
146
|
+
lapse() {
|
|
147
|
+
for (const [locator, held] of answered) {
|
|
148
|
+
if (held.confirmed)
|
|
149
|
+
answered.set(locator, { ...held, confirmed: false });
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
stood(locator, stale, repairable) {
|
|
153
|
+
heard(locator, { stale, ...(repairable === undefined ? {} : { repairable }) });
|
|
154
|
+
},
|
|
155
|
+
repairing(locator, running) {
|
|
156
|
+
change(locator, { repairing: running });
|
|
157
|
+
},
|
|
158
|
+
reload(locator, due) {
|
|
159
|
+
change(locator, { reloadDue: due });
|
|
160
|
+
},
|
|
161
|
+
standing(locator) {
|
|
162
|
+
const { stale, repairable, repairing, reloadDue } = answer(locator);
|
|
163
|
+
return { stale, repairable, repairing, reloadDue };
|
|
164
|
+
},
|
|
165
|
+
settled: () => ![...answered].some(([locator, { stale }]) => stale && !marks.has(locator)),
|
|
166
|
+
repairsOwed: () => [...answered]
|
|
167
|
+
.filter(([locator, { stale, repairable }]) => stale && repairable !== null && !marks.has(locator))
|
|
168
|
+
.map(([locator]) => locator),
|
|
169
|
+
askAgain(locator, ask) {
|
|
170
|
+
const held = unready.get(locator) ?? { tries: 0, timer: null };
|
|
171
|
+
unready.set(locator, held);
|
|
172
|
+
if (held.timer !== null)
|
|
173
|
+
return;
|
|
174
|
+
const wait = NOT_READY_MS[Math.min(held.tries, NOT_READY_MS.length - 1)];
|
|
175
|
+
held.tries += 1;
|
|
176
|
+
held.timer = setTimeout(() => {
|
|
177
|
+
held.timer = null;
|
|
178
|
+
ask();
|
|
179
|
+
}, wait);
|
|
180
|
+
},
|
|
181
|
+
stopAsking,
|
|
182
|
+
lose(locator, during) {
|
|
183
|
+
if (marks.has(locator))
|
|
184
|
+
return false;
|
|
185
|
+
marks.set(locator, { during, written: false });
|
|
186
|
+
lastLost.set(locator, ++lossCount);
|
|
187
|
+
listed.delete(locator);
|
|
188
|
+
readied(locator);
|
|
189
|
+
const { repairing, reloadDue } = answer(locator);
|
|
190
|
+
answered.set(locator, { ...UNANSWERED, repairing, reloadDue });
|
|
191
|
+
return true;
|
|
192
|
+
},
|
|
193
|
+
writing(locator) {
|
|
194
|
+
const mark = marks.get(locator);
|
|
195
|
+
if (mark === undefined || mark.written)
|
|
196
|
+
return false;
|
|
197
|
+
marks.set(locator, { ...mark, written: true });
|
|
198
|
+
return true;
|
|
199
|
+
},
|
|
200
|
+
unwritten(locator) {
|
|
201
|
+
const mark = marks.get(locator);
|
|
202
|
+
if (mark !== undefined)
|
|
203
|
+
marks.set(locator, { ...mark, written: false });
|
|
204
|
+
},
|
|
205
|
+
lost: (locator) => marks.has(locator),
|
|
206
|
+
losses: () => lossCount,
|
|
207
|
+
lostSince: (locator, losses) => marks.has(locator) || (lastLost.get(locator) ?? 0) > losses,
|
|
208
|
+
liftable,
|
|
209
|
+
lift(locator, discovery, unfenced) {
|
|
210
|
+
const mark = marks.get(locator);
|
|
211
|
+
if (mark !== undefined && liftable(locator, discovery) && (unfenced || !mark.written)) {
|
|
212
|
+
marks.delete(locator);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
close() {
|
|
216
|
+
stopAsking();
|
|
217
|
+
connectionLive();
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type FiguresCover } from './figures.js';
|
|
2
|
+
import type { Cover, Ran } from './live.js';
|
|
3
|
+
import { type Plan, type QueryResult } from './query.js';
|
|
4
|
+
import { type Deliver, type Fail, type PortReach } from './reach.js';
|
|
5
|
+
import type { Runtime } from './runtime.js';
|
|
6
|
+
import { type SearchResult } from './search.js';
|
|
7
|
+
import type { QueryRoom } from './store.js';
|
|
8
|
+
export declare function figuresCover(runtime: Runtime): Promise<FiguresCover>;
|
|
9
|
+
export declare function answeredPlan(runtime: Runtime, plan: Plan, cover: () => Promise<Cover>): Promise<Ran>;
|
|
10
|
+
export declare function rowsQuery(runtime: Runtime, plan: Plan): Promise<QueryResult>;
|
|
11
|
+
export declare function planned(runtime: Runtime, input: unknown, reach: PortReach | null): Promise<Plan>;
|
|
12
|
+
export declare function roomTallies(runtime: Runtime, rooms: readonly QueryRoom[], since: string): Promise<readonly import("./tallies.js").RoomTally[]>;
|
|
13
|
+
export declare function watchPlan(runtime: Runtime, plan: Plan, deliver: Deliver, fail: Fail): () => void;
|
|
14
|
+
export declare function watchPlanned(runtime: Runtime, planning: Promise<Plan>, deliver: Deliver, fail: Fail): () => void;
|
|
15
|
+
export declare function searched(runtime: Runtime, input: unknown, reach: PortReach | null): Promise<SearchResult>;
|
|
16
|
+
//# sourceMappingURL=queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAK5C,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAa,SAAS,EAAgB,MAAM,YAAY,CAAC;AAqFrE,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAa1E;AA2ED,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAC1B,OAAO,CAAC,GAAG,CAAC,CAQd;AAQD,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAWlF;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,wDAO7F;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,IAAI,CAchG;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,EACvB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,GACT,MAAM,IAAI,CAeZ;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,YAAY,CAAC,CAqDvB"}
|
package/dist/queries.js
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { identityOf } from '@agentshouse/mdmodel';
|
|
2
|
+
import { ROOM_TOTALS } from './figures.js';
|
|
3
|
+
import { roomInFlight } from './install.js';
|
|
4
|
+
import { roomFacts } from './listing.js';
|
|
5
|
+
import { lockedRooms } from './locks.js';
|
|
6
|
+
import { OFFLINE, UNCERTAIN, failure } from './outcome.js';
|
|
7
|
+
import { connectionNow, prepare, roomsOfReach } from './preparation.js';
|
|
8
|
+
import { planWithin, } from './query.js';
|
|
9
|
+
import { planReach } from './reach.js';
|
|
10
|
+
import { refuse } from './refusal.js';
|
|
11
|
+
import { documentKey } from './rows.js';
|
|
12
|
+
import { searchPlanOf } from './search.js';
|
|
13
|
+
import { seedApplies, seededResult, watchSeeded } from './seed.js';
|
|
14
|
+
import { capped, MAXIMUM_WINDOW } from './windows.js';
|
|
15
|
+
const QUERY_BYTES = 1 << 20;
|
|
16
|
+
function everyRoom({ presence }, held) {
|
|
17
|
+
return [
|
|
18
|
+
...new Set([
|
|
19
|
+
...presence.rooms().map(({ locator }) => locator),
|
|
20
|
+
...held.rooms.keys(),
|
|
21
|
+
...held.queues.keys(),
|
|
22
|
+
]),
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
function reachedRooms(runtime, plan, held) {
|
|
26
|
+
const reached = plan.reach === null ? null : roomsOfReach(plan.reach);
|
|
27
|
+
const named = plan.rooms ?? (reached === null ? everyRoom(runtime, held) : [...reached]);
|
|
28
|
+
return [...new Set(named)]
|
|
29
|
+
.filter((locator) => (reached === null || reached.has(locator)) && !plan.locked.includes(locator))
|
|
30
|
+
.sort();
|
|
31
|
+
}
|
|
32
|
+
function awaited({ socket, presence }, locator) {
|
|
33
|
+
return (!socket.session.now().roomsListed || presence.room(locator)?.replica.admission === 'admitted');
|
|
34
|
+
}
|
|
35
|
+
function coveredRooms(runtime, locators, whole, held) {
|
|
36
|
+
const { store, socket } = runtime;
|
|
37
|
+
if (locators.length === 0 && whole && !socket.session.now().roomsListed)
|
|
38
|
+
return { pending: [] };
|
|
39
|
+
const pending = [];
|
|
40
|
+
const coverage = [];
|
|
41
|
+
const overlay = [];
|
|
42
|
+
const read = [];
|
|
43
|
+
for (const locator of locators) {
|
|
44
|
+
const replica = held.rooms.get(locator);
|
|
45
|
+
if (replica === undefined) {
|
|
46
|
+
if (awaited(runtime, locator))
|
|
47
|
+
pending.push({ room: locator, awaits: 'acquisition' });
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!replica.indexed) {
|
|
51
|
+
pending.push({ room: locator, awaits: 'preparation' });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
coverage.push({
|
|
55
|
+
room: locator,
|
|
56
|
+
generation: replica.transfer,
|
|
57
|
+
current: !roomInFlight(store, locator),
|
|
58
|
+
});
|
|
59
|
+
read.push({ locator, key: replica.key });
|
|
60
|
+
for (const id of held.queues.get(locator) ?? [])
|
|
61
|
+
overlay.push(id);
|
|
62
|
+
}
|
|
63
|
+
if (pending.length > 0)
|
|
64
|
+
return { pending };
|
|
65
|
+
return { coverage: { rooms: coverage, overlay }, rooms: read };
|
|
66
|
+
}
|
|
67
|
+
function covered(runtime, plan, held) {
|
|
68
|
+
return coveredRooms(runtime, reachedRooms(runtime, plan, held), plan.rooms === null && plan.reach === null, held);
|
|
69
|
+
}
|
|
70
|
+
function awaitPreparation(runtime, cover) {
|
|
71
|
+
if (!('pending' in cover))
|
|
72
|
+
return;
|
|
73
|
+
const waiting = cover.pending.filter(({ awaits }) => awaits === 'preparation');
|
|
74
|
+
if (waiting.length > 0) {
|
|
75
|
+
prepare(runtime, waiting.map(({ room }) => room));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function figuresCover(runtime) {
|
|
79
|
+
const held = await runtime.store.covering();
|
|
80
|
+
const locked = await lockedRooms(runtime);
|
|
81
|
+
const cover = coveredRooms(runtime, everyRoom(runtime, held)
|
|
82
|
+
.filter((locator) => !locked.includes(locator))
|
|
83
|
+
.sort(), true, held);
|
|
84
|
+
awaitPreparation(runtime, cover);
|
|
85
|
+
return 'pending' in cover ? cover : { rooms: cover.rooms };
|
|
86
|
+
}
|
|
87
|
+
function sameCover(left, right) {
|
|
88
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
89
|
+
}
|
|
90
|
+
async function windowRows(local, plan, rooms, unchanged) {
|
|
91
|
+
const first = await local.query(plan, rooms, QUERY_BYTES);
|
|
92
|
+
if (first.more === undefined || !('documents' in first)) {
|
|
93
|
+
const { more: _more, ...rows } = first;
|
|
94
|
+
return rows;
|
|
95
|
+
}
|
|
96
|
+
const documents = [...first.documents];
|
|
97
|
+
for (let more = first.more; more !== undefined;) {
|
|
98
|
+
if (!unchanged())
|
|
99
|
+
return null;
|
|
100
|
+
const page = await local.query({
|
|
101
|
+
...plan,
|
|
102
|
+
after: { text: more, values: JSON.parse(more) },
|
|
103
|
+
limit: plan.limit === null ? null : plan.limit - documents.length,
|
|
104
|
+
total: false,
|
|
105
|
+
}, rooms, QUERY_BYTES);
|
|
106
|
+
if (!('documents' in page))
|
|
107
|
+
return null;
|
|
108
|
+
documents.push(...page.documents);
|
|
109
|
+
more = page.more;
|
|
110
|
+
if (more === undefined) {
|
|
111
|
+
return {
|
|
112
|
+
documents,
|
|
113
|
+
...(page.next === undefined ? {} : { next: page.next }),
|
|
114
|
+
...(first.total === undefined ? {} : { total: first.total }),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
async function coveredRows({ store }, plan, cover) {
|
|
121
|
+
for (;;) {
|
|
122
|
+
const before = await cover();
|
|
123
|
+
if ('pending' in before)
|
|
124
|
+
return { pending: before };
|
|
125
|
+
const local = await store.open();
|
|
126
|
+
const keys = before.rooms.map(({ key }) => key);
|
|
127
|
+
const changes = local.changes(keys);
|
|
128
|
+
const current = () => local.changes(keys) === changes;
|
|
129
|
+
const rows = await windowRows(local, plan, before.rooms, current);
|
|
130
|
+
const after = await cover();
|
|
131
|
+
if (rows !== null && sameCover(before, after))
|
|
132
|
+
return { rows, cover: before, current };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function keyedOf(rows, coverage) {
|
|
136
|
+
if ('groups' in rows) {
|
|
137
|
+
return {
|
|
138
|
+
result: { ...rows, coverage },
|
|
139
|
+
keys: rows.groups.map((group) => JSON.stringify(group.key)),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
result: { ...rows, coverage },
|
|
144
|
+
keys: rows.documents.map((document) => documentKey(document.room, document.path)),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export async function answeredPlan(runtime, plan, cover) {
|
|
148
|
+
const answered = await coveredRows(runtime, plan, cover);
|
|
149
|
+
if ('pending' in answered) {
|
|
150
|
+
const pending = answered.pending;
|
|
151
|
+
return { result: pending, keys: [], current: () => true };
|
|
152
|
+
}
|
|
153
|
+
const held = answered.cover;
|
|
154
|
+
return { ...keyedOf(answered.rows, held.coverage), current: answered.current };
|
|
155
|
+
}
|
|
156
|
+
async function coverNow(runtime, plan) {
|
|
157
|
+
const cover = covered(runtime, plan, await runtime.store.covering());
|
|
158
|
+
awaitPreparation(runtime, cover);
|
|
159
|
+
return cover;
|
|
160
|
+
}
|
|
161
|
+
export async function rowsQuery(runtime, plan) {
|
|
162
|
+
const held = await runtime.store.covering();
|
|
163
|
+
const before = covered(runtime, plan, held);
|
|
164
|
+
awaitPreparation(runtime, before);
|
|
165
|
+
const seeded = seedApplies(runtime, plan, held);
|
|
166
|
+
if (seeded !== null)
|
|
167
|
+
return seededResult(seeded).result;
|
|
168
|
+
if ('pending' in before)
|
|
169
|
+
return before;
|
|
170
|
+
const answered = await coveredRows(runtime, plan, () => coverNow(runtime, plan));
|
|
171
|
+
if ('pending' in answered)
|
|
172
|
+
return answered.pending;
|
|
173
|
+
const shownCover = answered.cover;
|
|
174
|
+
return { ...answered.rows, coverage: shownCover.coverage };
|
|
175
|
+
}
|
|
176
|
+
export async function planned(runtime, input, reach) {
|
|
177
|
+
const plan = planWithin(input, await roomFacts(runtime, reach), planReach(reach));
|
|
178
|
+
const named = plan.paths !== null &&
|
|
179
|
+
plan.rooms !== null &&
|
|
180
|
+
plan.paths.length * plan.rooms.length <= MAXIMUM_WINDOW;
|
|
181
|
+
return plan.limit === null && named ? plan : { ...plan, limit: capped(plan.limit) };
|
|
182
|
+
}
|
|
183
|
+
export async function roomTallies(runtime, rooms, since) {
|
|
184
|
+
return runtime.store.ask({
|
|
185
|
+
kind: 'replica.tallies',
|
|
186
|
+
totals: { ...(await planned(runtime, ROOM_TOTALS, null)), limit: null },
|
|
187
|
+
rooms,
|
|
188
|
+
since,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
export function watchPlan(runtime, plan, deliver, fail) {
|
|
192
|
+
return watchSeeded(runtime, plan, deliver, (behind, answered) => runtime.liveQueries.watch(plan, identityOf(plan), (held) => {
|
|
193
|
+
const cover = covered(runtime, plan, held);
|
|
194
|
+
awaitPreparation(runtime, cover);
|
|
195
|
+
return behind(cover, held);
|
|
196
|
+
}, answered, fail));
|
|
197
|
+
}
|
|
198
|
+
export function watchPlanned(runtime, planning, deliver, fail) {
|
|
199
|
+
let stop = null;
|
|
200
|
+
let stopped = false;
|
|
201
|
+
planning.then((plan) => {
|
|
202
|
+
if (!stopped)
|
|
203
|
+
stop = watchPlan(runtime, plan, deliver, fail);
|
|
204
|
+
}, (error) => {
|
|
205
|
+
if (!stopped)
|
|
206
|
+
fail(error);
|
|
207
|
+
});
|
|
208
|
+
return () => {
|
|
209
|
+
stopped = true;
|
|
210
|
+
stop?.();
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export async function searched(runtime, input, reach) {
|
|
214
|
+
const { store, socket, journal } = runtime;
|
|
215
|
+
const { session } = socket;
|
|
216
|
+
const asked = searchPlanOf(input);
|
|
217
|
+
await socket.ready;
|
|
218
|
+
const search = socket.search();
|
|
219
|
+
if (search === undefined) {
|
|
220
|
+
return {
|
|
221
|
+
kind: 'undeclared',
|
|
222
|
+
code: 'action-undeclared',
|
|
223
|
+
fields: { name: 'search' },
|
|
224
|
+
retryable: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
if (socket.closed() ||
|
|
228
|
+
session.now().refusal !== null ||
|
|
229
|
+
(await connectionNow(runtime)) !== 'connected')
|
|
230
|
+
return OFFLINE;
|
|
231
|
+
const reached = reach === null ? null : new Set(reach.rooms);
|
|
232
|
+
const named = asked.rooms === null
|
|
233
|
+
? reached === null
|
|
234
|
+
? null
|
|
235
|
+
: [...reached]
|
|
236
|
+
: asked.rooms.filter((room) => reached === null || reached.has(room));
|
|
237
|
+
const held = named === null ? null : await store.rooms(named);
|
|
238
|
+
const rooms = named === null ? null : named.filter((room) => held.has(room)).sort();
|
|
239
|
+
if (rooms !== null && rooms.length === 0)
|
|
240
|
+
return { kind: 'found', documents: [] };
|
|
241
|
+
try {
|
|
242
|
+
await socket.authorize();
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return UNCERTAIN;
|
|
246
|
+
}
|
|
247
|
+
const { closed, authorization, refusal } = session.now();
|
|
248
|
+
if (closed || authorization === undefined || refusal !== null)
|
|
249
|
+
return UNCERTAIN;
|
|
250
|
+
journal.record('transfer search');
|
|
251
|
+
try {
|
|
252
|
+
const result = await search(authorization, { text: asked.text, rooms });
|
|
253
|
+
if (result.kind === 'revoked-authorization')
|
|
254
|
+
await refuse(runtime, 'revoked-authorization');
|
|
255
|
+
journal.record(`outcome search ${result.kind}`);
|
|
256
|
+
if (result.kind === 'rejected')
|
|
257
|
+
return result;
|
|
258
|
+
if (result.kind !== 'found')
|
|
259
|
+
return failure(result);
|
|
260
|
+
const kept = rooms === null ? null : new Set(rooms);
|
|
261
|
+
return {
|
|
262
|
+
kind: 'found',
|
|
263
|
+
documents: result.documents.filter((hit) => kept === null || kept.has(hit.room)),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
journal.record('outcome search transport-uncertainty');
|
|
268
|
+
return UNCERTAIN;
|
|
269
|
+
}
|
|
270
|
+
}
|