@agentshouse/mdruntime 0.1.0-c389df724fd2f → 0.1.0-c38dcfe165d81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -11
- package/dist/adapter.d.ts +175 -54
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/attempt.d.ts +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 +202 -48
- 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 -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 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +123 -22
- package/dist/collection.d.ts +13 -14
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +52 -56
- 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 +59 -20
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3810 -905
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- package/dist/conversation.d.ts +50 -20
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +714 -242
- 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 +159 -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/host.d.ts +11 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +128 -25
- package/dist/identity.d.ts +3 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +13 -1
- package/dist/index.d.ts +23 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -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 +19 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +251 -98
- 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 +13 -6
- 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/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 +42 -181
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -461
- package/dist/reach.d.ts +18 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +234 -69
- package/dist/react.d.ts +14 -8
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +8 -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 +20 -7
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +148 -59
- package/dist/replica.d.ts +59 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +320 -157
- package/dist/room-draft.d.ts +59 -11
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +276 -80
- package/dist/rows.d.ts +23 -35
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +61 -117
- 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 +15 -54
- 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 +7 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -9
- package/dist/store.d.ts +107 -62
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +318 -354
- package/dist/stored.d.ts +129 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +495 -0
- package/dist/tables.d.ts +326 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +574 -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 +169 -33
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +68 -31
- package/package.json +26 -15
- package/AGENTS.md +0 -253
- 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/memory.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { sameChange } from './overlay.js';
|
|
2
|
+
const ATTACHMENTS = 'attachments';
|
|
3
|
+
function lastName(path) {
|
|
4
|
+
return path.slice(path.lastIndexOf('/') + 1);
|
|
5
|
+
}
|
|
2
6
|
const FIXTURE_RETENTION = {
|
|
3
7
|
history: { kind: 'duration', seconds: 1 },
|
|
4
|
-
outcome: 1,
|
|
5
8
|
refreshHorizon: 1,
|
|
6
9
|
};
|
|
7
10
|
function declaredRetention(value) {
|
|
@@ -15,12 +18,7 @@ function declaredRetention(value) {
|
|
|
15
18
|
}
|
|
16
19
|
const MODEL_ABSENT = { kind: 'model-unavailable', reason: 'not-readable' };
|
|
17
20
|
function modelsOf(room) {
|
|
18
|
-
return {
|
|
19
|
-
collection: room.model ?? MODEL_ABSENT,
|
|
20
|
-
...(room.typedSelection === undefined
|
|
21
|
-
? {}
|
|
22
|
-
: { selection: room.selectionModel ?? MODEL_ABSENT }),
|
|
23
|
-
};
|
|
21
|
+
return { collection: room.model ?? MODEL_ABSENT };
|
|
24
22
|
}
|
|
25
23
|
function changedModels(room, from) {
|
|
26
24
|
const now = modelsOf(room);
|
|
@@ -53,12 +51,16 @@ export function createMemoryAdapter(options = {}) {
|
|
|
53
51
|
const listeners = new Set();
|
|
54
52
|
const modeObservers = new Set();
|
|
55
53
|
const scripted = new Map();
|
|
56
|
-
const
|
|
57
|
-
const sealed = new Set();
|
|
54
|
+
const sentTurns = new Map();
|
|
58
55
|
const historyPageSize = options.historyPageSize;
|
|
59
|
-
|
|
56
|
+
const attached = new Map();
|
|
57
|
+
const linked = new WeakMap();
|
|
58
|
+
const carried = new Map();
|
|
60
59
|
let expiring = [];
|
|
60
|
+
let openings = 0;
|
|
61
|
+
const declaredRooms = new Set();
|
|
61
62
|
let replicated = [];
|
|
63
|
+
let heldCursor = null;
|
|
62
64
|
let issued = 0;
|
|
63
65
|
function scriptConversations(entries) {
|
|
64
66
|
scripted.clear();
|
|
@@ -86,6 +88,19 @@ export function createMemoryAdapter(options = {}) {
|
|
|
86
88
|
const wanted = ordinals.get(`${locator}\u0000${target}`);
|
|
87
89
|
return held !== undefined && wanted !== undefined && held >= wanted;
|
|
88
90
|
}
|
|
91
|
+
function heldBlob(room, path) {
|
|
92
|
+
return attached.get(`${room.locator}\u0000${path}`) ?? room.blobs?.[path];
|
|
93
|
+
}
|
|
94
|
+
function freePath(room, name) {
|
|
95
|
+
const dot = name.lastIndexOf('.');
|
|
96
|
+
const stem = dot > 0 ? name.slice(0, dot) : name;
|
|
97
|
+
const extension = dot > 0 ? name.slice(dot) : '';
|
|
98
|
+
for (let count = 1;; count += 1) {
|
|
99
|
+
const path = `${ATTACHMENTS}/${count === 1 ? stem : `${stem}-${count}`}${extension}`;
|
|
100
|
+
if (heldBlob(room, path) === undefined && room.documents?.[path] === undefined)
|
|
101
|
+
return path;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
89
104
|
function retain(entries) {
|
|
90
105
|
for (const room of entries) {
|
|
91
106
|
note(room.locator, room);
|
|
@@ -107,35 +122,51 @@ export function createMemoryAdapter(options = {}) {
|
|
|
107
122
|
providerOwnedPaths: room.providerOwnedPaths,
|
|
108
123
|
};
|
|
109
124
|
}
|
|
110
|
-
function page(room,
|
|
125
|
+
function page(room, after) {
|
|
111
126
|
const paths = Object.keys(room.documents ?? {}).sort();
|
|
127
|
+
const opening = after === undefined;
|
|
128
|
+
const from = opening ? 0 : paths.filter((path) => path <= after).length;
|
|
112
129
|
const size = pageSize ?? paths.length;
|
|
113
130
|
const taken = paths.slice(from, from + size);
|
|
114
131
|
const next = from + taken.length;
|
|
115
|
-
const targets =
|
|
132
|
+
const targets = opening ? Object.keys(room.binaryFiles ?? {}) : [];
|
|
116
133
|
return {
|
|
117
134
|
kind: 'bootstrap',
|
|
118
135
|
roomVersion: room.roomVersion,
|
|
119
|
-
...(
|
|
136
|
+
...(opening ? { models: modelsOf(room) } : {}),
|
|
120
137
|
documents: named(room.documents ?? {}, taken),
|
|
121
|
-
revisions: named(room.revisions ?? {}, taken),
|
|
138
|
+
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
139
|
+
...(room.fileIds === undefined
|
|
140
|
+
? {}
|
|
141
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
122
142
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
123
|
-
|
|
124
|
-
...(
|
|
125
|
-
...(next < paths.length ? { pageToken:
|
|
143
|
+
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
144
|
+
...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
|
|
145
|
+
...(next < paths.length ? { pageToken: taken.at(-1) } : {}),
|
|
126
146
|
};
|
|
127
147
|
}
|
|
128
|
-
function
|
|
148
|
+
function foldersMoved(room, from) {
|
|
149
|
+
const now = new Set(room.folders ?? []);
|
|
150
|
+
const before = new Set(from.folders ?? []);
|
|
151
|
+
const folders = [...now].filter((folder) => !before.has(folder)).sort();
|
|
152
|
+
const folderRemovals = [...before].filter((folder) => !now.has(folder)).sort();
|
|
153
|
+
return {
|
|
154
|
+
...(folders.length === 0 ? {} : { folders }),
|
|
155
|
+
...(folderRemovals.length === 0 ? {} : { folderRemovals }),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function advancement(room, from, at, whole = false) {
|
|
129
159
|
const current = room.documents ?? {};
|
|
130
160
|
const previous = from.documents ?? {};
|
|
131
|
-
const currentTargets = new Set(room.
|
|
132
|
-
const previousTargets = new Set(from.
|
|
161
|
+
const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
|
|
162
|
+
const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
|
|
133
163
|
const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
|
|
164
|
+
room.fileIds?.[path] !== from.fileIds?.[path] ||
|
|
134
165
|
!sameChange(room.changes?.[path], from.changes?.[path]);
|
|
135
166
|
const changed = Object.keys(current)
|
|
136
167
|
.filter((path) => current[path] !== previous[path] || headMoved(path))
|
|
137
168
|
.sort();
|
|
138
|
-
const size = pageSize ?? changed.length;
|
|
169
|
+
const size = whole ? changed.length : (pageSize ?? changed.length);
|
|
139
170
|
const taken = changed.slice(at, at + size);
|
|
140
171
|
const next = at + taken.length;
|
|
141
172
|
const opening = at === 0;
|
|
@@ -145,27 +176,48 @@ export function createMemoryAdapter(options = {}) {
|
|
|
145
176
|
const targets = opening
|
|
146
177
|
? [...currentTargets].filter((target) => !previousTargets.has(target) || headMoved(target))
|
|
147
178
|
: [];
|
|
148
|
-
const attachments = room.attachments ?? [];
|
|
149
|
-
const declared = opening && JSON.stringify(attachments) !== JSON.stringify(from.attachments ?? []);
|
|
150
179
|
const models = opening ? changedModels(room, from) : undefined;
|
|
151
180
|
return {
|
|
152
181
|
kind: 'net-advancement',
|
|
153
182
|
roomVersion: room.roomVersion,
|
|
154
183
|
...(models === undefined ? {} : { models }),
|
|
155
184
|
documents: named(current, taken),
|
|
156
|
-
revisions: named(room.revisions ?? {}, taken),
|
|
185
|
+
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
186
|
+
...(room.fileIds === undefined
|
|
187
|
+
? {}
|
|
188
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
157
189
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
158
|
-
|
|
190
|
+
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
191
|
+
...(opening ? foldersMoved(room, from) : {}),
|
|
159
192
|
removals: opening
|
|
160
193
|
? [
|
|
161
194
|
...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
|
|
162
195
|
...[...previousTargets].filter((target) => !currentTargets.has(target) && !(target in current)),
|
|
163
196
|
].sort()
|
|
164
197
|
: [],
|
|
165
|
-
...(declared ? { attachments } : {}),
|
|
166
198
|
...(pageToken === undefined ? {} : { pageToken }),
|
|
167
199
|
};
|
|
168
200
|
}
|
|
201
|
+
function carry(locator) {
|
|
202
|
+
const at = carried.get(locator);
|
|
203
|
+
const current = rooms.find((entry) => entry.locator === locator);
|
|
204
|
+
if (at === undefined || current === undefined || current.roomVersion === at)
|
|
205
|
+
return;
|
|
206
|
+
const from = served.get(locator)?.get(at);
|
|
207
|
+
carried.set(locator, current.roomVersion);
|
|
208
|
+
if (from === undefined)
|
|
209
|
+
return;
|
|
210
|
+
const page = advancement(current, from, 0, true);
|
|
211
|
+
for (const observer of observers) {
|
|
212
|
+
observer({
|
|
213
|
+
kind: 'room-change',
|
|
214
|
+
locator,
|
|
215
|
+
from: at,
|
|
216
|
+
roomVersion: current.roomVersion,
|
|
217
|
+
read: async () => page,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
169
221
|
function pageOf(conversation, after) {
|
|
170
222
|
const messages = conversation.messages ?? [];
|
|
171
223
|
const first = typeof after === 'string' ? messages.findIndex((message) => message.position > after) : 0;
|
|
@@ -180,16 +232,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
180
232
|
: {}),
|
|
181
233
|
};
|
|
182
234
|
}
|
|
183
|
-
function historiesOf(
|
|
184
|
-
const asked = input?.conversations;
|
|
185
|
-
if (!Array.isArray(asked))
|
|
186
|
-
return { kind: 'rejected', code: 'invalid_request', fields: {} };
|
|
235
|
+
function historiesOf(request) {
|
|
187
236
|
const histories = [];
|
|
188
|
-
for (const entry of
|
|
189
|
-
const conversation =
|
|
237
|
+
for (const entry of request.conversations) {
|
|
238
|
+
const conversation = scripted.get(entry.conversation);
|
|
190
239
|
if (conversation === undefined)
|
|
191
240
|
continue;
|
|
192
|
-
const outcome = conversation.outcomes?.
|
|
241
|
+
const outcome = conversation.outcomes?.history;
|
|
193
242
|
if (outcome !== undefined)
|
|
194
243
|
return outcome;
|
|
195
244
|
histories.push(pageOf(conversation, entry.after));
|
|
@@ -200,44 +249,47 @@ export function createMemoryAdapter(options = {}) {
|
|
|
200
249
|
function conversationAction(request) {
|
|
201
250
|
const name = request.name;
|
|
202
251
|
const input = (request.input ?? {});
|
|
203
|
-
if (name === '
|
|
204
|
-
return historiesOf(request.input);
|
|
205
|
-
if (name === 'conversation.create') {
|
|
252
|
+
if (name === 'conversations/create') {
|
|
206
253
|
issued += 1;
|
|
207
254
|
const conversation = `conversation-${issued}`;
|
|
208
255
|
scripted.set(conversation, { conversation });
|
|
209
|
-
return { kind: 'action', result: { conversation } };
|
|
256
|
+
return { kind: 'action', result: { conversation_id: conversation } };
|
|
210
257
|
}
|
|
211
|
-
const named = typeof input.
|
|
258
|
+
const named = typeof input.conversation_id === 'string' ? input.conversation_id : '';
|
|
212
259
|
const conversation = scripted.get(named);
|
|
213
260
|
if (conversation === undefined) {
|
|
214
|
-
return {
|
|
261
|
+
return {
|
|
262
|
+
kind: 'rejected',
|
|
263
|
+
code: 'unknown-conversation',
|
|
264
|
+
fields: { conversation: named },
|
|
265
|
+
retryable: false,
|
|
266
|
+
};
|
|
215
267
|
}
|
|
216
268
|
const outcome = conversation.outcomes?.[name];
|
|
217
269
|
if (outcome !== undefined)
|
|
218
270
|
return outcome;
|
|
219
|
-
if (name === '
|
|
271
|
+
if (name === 'conversations/send') {
|
|
272
|
+
const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
|
|
273
|
+
const answered = operation === null ? undefined : sentTurns.get(operation);
|
|
274
|
+
if (answered !== undefined)
|
|
275
|
+
return { kind: 'action', result: { message_id: answered } };
|
|
220
276
|
issued += 1;
|
|
221
277
|
const turn = `turn-${issued}`;
|
|
222
|
-
|
|
223
|
-
|
|
278
|
+
if (operation !== null)
|
|
279
|
+
sentTurns.set(operation, turn);
|
|
280
|
+
return { kind: 'action', result: { message_id: turn } };
|
|
224
281
|
}
|
|
225
|
-
if (name === '
|
|
226
|
-
const turn = typeof input.turn === 'string' ? input.turn : '';
|
|
227
|
-
if (sealed.has(turn) || !unsealed.has(turn)) {
|
|
228
|
-
return { kind: 'rejected', code: 'turn-sealed', fields: { turn } };
|
|
229
|
-
}
|
|
230
|
-
unsealed.delete(turn);
|
|
231
|
-
return { kind: 'action', result: { turn, cancelled: true } };
|
|
232
|
-
}
|
|
233
|
-
if (name === 'conversation.delete')
|
|
282
|
+
if (name === 'conversations/delete')
|
|
234
283
|
scripted.delete(named);
|
|
235
|
-
return { kind: 'action', result: {
|
|
284
|
+
return { kind: 'action', result: { conversation_id: named } };
|
|
236
285
|
}
|
|
237
286
|
function announceList() {
|
|
238
|
-
const entries = [...scripted.values()].flatMap(({ conversation, listed }) => listed === undefined
|
|
239
|
-
|
|
240
|
-
|
|
287
|
+
const entries = [...scripted.values()].flatMap(({ conversation, listed, messages = [] }) => listed === undefined
|
|
288
|
+
? []
|
|
289
|
+
: [{ conversation, ...listed, newest: messages.at(-1)?.position ?? null }]);
|
|
290
|
+
for (const listener of listeners) {
|
|
291
|
+
listener({ kind: 'list', entries, whole: true, more: false, cursor: null });
|
|
292
|
+
}
|
|
241
293
|
}
|
|
242
294
|
function discovery() {
|
|
243
295
|
return {
|
|
@@ -249,7 +301,42 @@ export function createMemoryAdapter(options = {}) {
|
|
|
249
301
|
...(options.member === undefined ? {} : { member: options.member }),
|
|
250
302
|
};
|
|
251
303
|
}
|
|
304
|
+
function discovered() {
|
|
305
|
+
return resolveScript(scripts.discover, discovery, undefined).then((answer) => {
|
|
306
|
+
if (answer.kind === 'discovery')
|
|
307
|
+
for (const room of answer.rooms)
|
|
308
|
+
note(room.locator, room);
|
|
309
|
+
return answer;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
function opened(notify) {
|
|
313
|
+
const opening = ++openings;
|
|
314
|
+
notify({ kind: 'opened' });
|
|
315
|
+
void discovered()
|
|
316
|
+
.catch(() => ({ kind: 'transport-uncertainty' }))
|
|
317
|
+
.then((answer) => {
|
|
318
|
+
if (opening !== openings)
|
|
319
|
+
return;
|
|
320
|
+
if (answer.kind !== 'discovery') {
|
|
321
|
+
openings += 1;
|
|
322
|
+
carried.clear();
|
|
323
|
+
const revoked = answer.kind === 'revoked-authorization';
|
|
324
|
+
notify({ kind: 'closed', revoked, lost: !revoked, authorityChanged: false });
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
declaredRooms.clear();
|
|
328
|
+
for (const room of answer.rooms)
|
|
329
|
+
declaredRooms.add(room.locator);
|
|
330
|
+
notify({ kind: 'discovered', discovery: answer });
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
function emitAll(event) {
|
|
334
|
+
for (const observer of observers)
|
|
335
|
+
observer(event);
|
|
336
|
+
}
|
|
252
337
|
return {
|
|
338
|
+
...(options.roomTypes === undefined ? {} : { roomTypes: options.roomTypes }),
|
|
339
|
+
...(options.typedPaths === undefined ? {} : { typedPaths: options.typedPaths }),
|
|
253
340
|
setRooms(next) {
|
|
254
341
|
rooms = [...next];
|
|
255
342
|
retain(rooms);
|
|
@@ -258,26 +345,37 @@ export function createMemoryAdapter(options = {}) {
|
|
|
258
345
|
scriptConversations(next);
|
|
259
346
|
},
|
|
260
347
|
open() {
|
|
348
|
+
carried.clear();
|
|
261
349
|
announceList();
|
|
262
|
-
|
|
263
|
-
observer({ kind: 'opened' });
|
|
350
|
+
opened(emitAll);
|
|
264
351
|
},
|
|
265
|
-
close(revoked = false) {
|
|
266
|
-
|
|
267
|
-
|
|
352
|
+
close({ revoked = false, lost = !revoked, authorityChanged = false } = {}) {
|
|
353
|
+
openings += 1;
|
|
354
|
+
carried.clear();
|
|
355
|
+
emitAll({ kind: 'closed', revoked, lost, authorityChanged });
|
|
268
356
|
},
|
|
269
357
|
expire(locators) {
|
|
270
358
|
expiring = [...locators];
|
|
271
359
|
},
|
|
272
|
-
notifyRoomVersion({ locator
|
|
273
|
-
|
|
274
|
-
|
|
360
|
+
notifyRoomVersion({ locator }) {
|
|
361
|
+
carry(locator);
|
|
362
|
+
},
|
|
363
|
+
notifyAuthorityChanged(locators) {
|
|
364
|
+
const named = new Set(locators ?? [...declaredRooms, ...rooms.map((room) => room.locator)]);
|
|
365
|
+
const listed = rooms.filter((room) => named.has(room.locator));
|
|
366
|
+
const left = [...named].filter((locator) => !listed.some((room) => room.locator === locator));
|
|
367
|
+
for (const room of listed)
|
|
368
|
+
declaredRooms.add(room.locator);
|
|
369
|
+
for (const locator of left)
|
|
370
|
+
declaredRooms.delete(locator);
|
|
371
|
+
emitAll({
|
|
372
|
+
kind: 'authority-changed',
|
|
373
|
+
rooms: listed.map(declared),
|
|
374
|
+
left,
|
|
375
|
+
...(options.member === undefined ? {} : { member: options.member }),
|
|
376
|
+
});
|
|
275
377
|
},
|
|
276
378
|
notifyConversation(event) {
|
|
277
|
-
if (event.kind === 'accepted-message') {
|
|
278
|
-
sealed.add(event.message.turn);
|
|
279
|
-
unsealed.delete(event.message.turn);
|
|
280
|
-
}
|
|
281
379
|
for (const listener of listeners)
|
|
282
380
|
listener(event);
|
|
283
381
|
},
|
|
@@ -286,21 +384,31 @@ export function createMemoryAdapter(options = {}) {
|
|
|
286
384
|
observer(mode);
|
|
287
385
|
},
|
|
288
386
|
heldRooms() {
|
|
289
|
-
return
|
|
387
|
+
return [...carried.keys()].sort();
|
|
290
388
|
},
|
|
291
389
|
replicatedConversations() {
|
|
292
390
|
return replicated;
|
|
293
391
|
},
|
|
392
|
+
heldConversationCursor() {
|
|
393
|
+
return heldCursor;
|
|
394
|
+
},
|
|
294
395
|
conversations: {
|
|
295
396
|
replicate(next) {
|
|
296
397
|
replicated = [...next];
|
|
297
398
|
},
|
|
399
|
+
hold(cursor) {
|
|
400
|
+
heldCursor = cursor;
|
|
401
|
+
},
|
|
298
402
|
observe(notify) {
|
|
299
403
|
listeners.add(notify);
|
|
300
404
|
return () => {
|
|
301
405
|
listeners.delete(notify);
|
|
302
406
|
};
|
|
303
407
|
},
|
|
408
|
+
history: (request) => Promise.resolve(historiesOf(request)),
|
|
409
|
+
...(options.agents === undefined
|
|
410
|
+
? {}
|
|
411
|
+
: { agents: () => Promise.resolve(structuredClone(options.agents)) }),
|
|
304
412
|
},
|
|
305
413
|
serviceMode: {
|
|
306
414
|
observe(notify) {
|
|
@@ -312,29 +420,29 @@ export function createMemoryAdapter(options = {}) {
|
|
|
312
420
|
},
|
|
313
421
|
roomStream: {
|
|
314
422
|
hold(asked) {
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
expiring = [];
|
|
318
|
-
const moved = asked.flatMap((room) => {
|
|
423
|
+
const named = asked.map((room) => room.locator);
|
|
424
|
+
const unknown = asked.flatMap((room) => {
|
|
319
425
|
const current = rooms.find((entry) => entry.locator === room.locator);
|
|
320
426
|
return current === undefined ||
|
|
321
|
-
|
|
322
|
-
|
|
427
|
+
current.roomVersion === room.roomVersion ||
|
|
428
|
+
served.get(room.locator)?.has(room.roomVersion) === true
|
|
323
429
|
? []
|
|
324
|
-
: [
|
|
430
|
+
: [room.locator];
|
|
325
431
|
});
|
|
432
|
+
const expired = [
|
|
433
|
+
...new Set([...expiring.filter((locator) => named.includes(locator)), ...unknown]),
|
|
434
|
+
];
|
|
435
|
+
expiring = expiring.filter((locator) => !named.includes(locator));
|
|
326
436
|
queueMicrotask(() => {
|
|
327
|
-
for (const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
437
|
+
for (const room of asked) {
|
|
438
|
+
if (expired.includes(room.locator))
|
|
439
|
+
carried.delete(room.locator);
|
|
440
|
+
else {
|
|
441
|
+
carried.set(room.locator, room.roomVersion);
|
|
442
|
+
carry(room.locator);
|
|
443
|
+
}
|
|
331
444
|
}
|
|
332
|
-
|
|
333
|
-
},
|
|
334
|
-
reopen() {
|
|
335
|
-
queueMicrotask(() => {
|
|
336
|
-
for (const observer of observers)
|
|
337
|
-
observer({ kind: 'closed', revoked: false });
|
|
445
|
+
emitAll({ kind: 'caught-up', expired });
|
|
338
446
|
});
|
|
339
447
|
},
|
|
340
448
|
observe(notify) {
|
|
@@ -343,11 +451,14 @@ export function createMemoryAdapter(options = {}) {
|
|
|
343
451
|
if (!observers.has(notify))
|
|
344
452
|
return;
|
|
345
453
|
if (options.unopened === true) {
|
|
346
|
-
notify({ kind: 'closed', revoked: false });
|
|
454
|
+
notify({ kind: 'closed', revoked: false, lost: true, authorityChanged: false });
|
|
347
455
|
return;
|
|
348
456
|
}
|
|
349
457
|
announceList();
|
|
350
|
-
|
|
458
|
+
opened((event) => {
|
|
459
|
+
if (observers.has(notify))
|
|
460
|
+
notify(event);
|
|
461
|
+
});
|
|
351
462
|
});
|
|
352
463
|
return () => {
|
|
353
464
|
observers.delete(notify);
|
|
@@ -364,12 +475,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
364
475
|
return resolveScript(scripts.authorize, () => ({}), undefined);
|
|
365
476
|
},
|
|
366
477
|
async discover(_authorization) {
|
|
367
|
-
return
|
|
368
|
-
if (answer.kind === 'discovery')
|
|
369
|
-
for (const room of answer.rooms)
|
|
370
|
-
note(room.locator, room);
|
|
371
|
-
return answer;
|
|
372
|
-
});
|
|
478
|
+
return discovered();
|
|
373
479
|
},
|
|
374
480
|
reached,
|
|
375
481
|
follows(locator, roomVersion, next) {
|
|
@@ -386,7 +492,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
386
492
|
if (room === undefined) {
|
|
387
493
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
388
494
|
}
|
|
389
|
-
return page(room, request.pageToken
|
|
495
|
+
return page(room, request.pageToken);
|
|
390
496
|
}, request).then((answer) => note(request.locator, answer));
|
|
391
497
|
},
|
|
392
498
|
async refresh(_authorization, request) {
|
|
@@ -419,8 +525,20 @@ export function createMemoryAdapter(options = {}) {
|
|
|
419
525
|
if (room === undefined) {
|
|
420
526
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
421
527
|
}
|
|
422
|
-
return {
|
|
423
|
-
|
|
528
|
+
return {
|
|
529
|
+
kind: 'rejected',
|
|
530
|
+
code: 'unscripted-mutation',
|
|
531
|
+
fields: {},
|
|
532
|
+
retryable: false,
|
|
533
|
+
affected: {},
|
|
534
|
+
};
|
|
535
|
+
}, request).then((answer) => {
|
|
536
|
+
const destination = request.changeBatch.between?.destination.room;
|
|
537
|
+
if (answer.kind === 'accepted' && answer.destination !== undefined && destination) {
|
|
538
|
+
note(destination, answer.destination);
|
|
539
|
+
}
|
|
540
|
+
return note(request.locator, answer);
|
|
541
|
+
});
|
|
424
542
|
},
|
|
425
543
|
async history(_authorization, request) {
|
|
426
544
|
return resolveScript(scripts.history, () => {
|
|
@@ -434,11 +552,46 @@ export function createMemoryAdapter(options = {}) {
|
|
|
434
552
|
};
|
|
435
553
|
}, request);
|
|
436
554
|
},
|
|
555
|
+
async binary(_authorization, request) {
|
|
556
|
+
return resolveScript(scripts.binary, () => {
|
|
557
|
+
const room = rooms.find((entry) => entry.locator === request.locator);
|
|
558
|
+
if (room === undefined)
|
|
559
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
560
|
+
const blob = heldBlob(room, request.path);
|
|
561
|
+
return blob === undefined
|
|
562
|
+
? { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false }
|
|
563
|
+
: { kind: 'binary', body: blob.stream(), mediaType: blob.type };
|
|
564
|
+
}, request);
|
|
565
|
+
},
|
|
566
|
+
async link(_authorization, request) {
|
|
567
|
+
return resolveScript(scripts.link, () => {
|
|
568
|
+
const room = rooms.find((entry) => entry.locator === request.locator);
|
|
569
|
+
if (room === undefined)
|
|
570
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
571
|
+
const blob = heldBlob(room, request.path);
|
|
572
|
+
if (blob === undefined) {
|
|
573
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
574
|
+
}
|
|
575
|
+
const url = linked.get(blob) ?? URL.createObjectURL(blob);
|
|
576
|
+
linked.set(blob, url);
|
|
577
|
+
return { kind: 'link', url, name: lastName(request.path), mediaType: blob.type };
|
|
578
|
+
}, request);
|
|
579
|
+
},
|
|
580
|
+
async attach(_authorization, request) {
|
|
581
|
+
return resolveScript(scripts.attach, () => {
|
|
582
|
+
const room = rooms.find((entry) => entry.locator === request.locator);
|
|
583
|
+
if (room === undefined)
|
|
584
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
585
|
+
const path = freePath(room, request.name);
|
|
586
|
+
attached.set(`${room.locator}\u0000${path}`, request.blob);
|
|
587
|
+
return { kind: 'attached', path, revision: `attached-${attached.size}` };
|
|
588
|
+
}, request);
|
|
589
|
+
},
|
|
437
590
|
async action(_authorization, request) {
|
|
438
591
|
return resolveScript(scripts.action, () => {
|
|
439
|
-
if (request.name.startsWith('
|
|
592
|
+
if (request.name.startsWith('conversations/'))
|
|
440
593
|
return conversationAction(request);
|
|
441
|
-
return { kind: 'rejected', code: 'unscripted-action', fields: {} };
|
|
594
|
+
return { kind: 'rejected', code: 'unscripted-action', fields: {}, retryable: false };
|
|
442
595
|
}, request).then((answer) => {
|
|
443
596
|
if (answer.kind === 'action' && answer.at !== undefined)
|
|
444
597
|
note(answer.at.locator, answer.at);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AcceptedMessage } from './adapter.js';
|
|
2
|
+
import type { Connection } from './tables.js';
|
|
3
|
+
export declare const MESSAGE_TABLES: readonly string[];
|
|
4
|
+
export type HeldConversation = {
|
|
5
|
+
readonly conversation: string;
|
|
6
|
+
readonly read: string | null | undefined;
|
|
7
|
+
readonly partial: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type MessageWindow = {
|
|
10
|
+
readonly messages: AcceptedMessage[];
|
|
11
|
+
readonly more: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type ConversationWrite = {
|
|
14
|
+
readonly conversation: string;
|
|
15
|
+
readonly messages: readonly AcceptedMessage[];
|
|
16
|
+
readonly read?: {
|
|
17
|
+
readonly at: string | null;
|
|
18
|
+
readonly partial: boolean;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare function heldConversations(connection: Connection): HeldConversation[];
|
|
22
|
+
export declare function keptMessages(connection: Connection, { conversation, messages, read }: ConversationWrite): null;
|
|
23
|
+
export declare function messageWindow(connection: Connection, conversation: string, limit: number, before: readonly [string, string] | null, phrase: string | null): MessageWindow;
|
|
24
|
+
export declare function messageCount(connection: Connection, conversation: string, phrase: string | null): number;
|
|
25
|
+
export declare function turnArrived(connection: Connection, conversation: string, turn: string): boolean;
|
|
26
|
+
export declare function droppedMessages(connection: Connection, conversations: readonly string[]): void;
|
|
27
|
+
export declare function forgottenMessages(connection: Connection): void;
|
|
28
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAM3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3E,CAAC;AAMF,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAmB5E;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAClD,IAAI,CA+BN;AAkBD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,EACxC,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,aAAa,CAWf;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAOR;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/F;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAK9F;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAG9D"}
|