@agentshouse/mdruntime 0.1.0-c8ca66ac9e99d → 0.1.0-c8eac46931574
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 +152 -53
- 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/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 +184 -81
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -14
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -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 +28 -16
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +98 -12
- package/dist/collection.d.ts +10 -7
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +38 -79
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +789 -0
- package/dist/connection.d.ts +44 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3840 -967
- package/dist/conversation.d.ts +39 -17
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +704 -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 +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 +152 -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 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +127 -17
- package/dist/identity.d.ts +1 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +3 -0
- package/dist/index.d.ts +17 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/job.d.ts +8 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +13 -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 +16 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +214 -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 +9 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +8 -2
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +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/phrase.d.ts +3 -0
- package/dist/phrase.d.ts.map +1 -0
- package/dist/phrase.js +8 -0
- package/dist/query.d.ts +70 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +67 -7
- package/dist/reach.d.ts +19 -6
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +227 -80
- package/dist/react.d.ts +9 -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 +155 -51
- package/dist/replica.d.ts +55 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +300 -154
- package/dist/room-draft.d.ts +36 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +161 -74
- package/dist/rows.d.ts +38 -37
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +178 -104
- 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 +111 -78
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +342 -478
- package/dist/stored.d.ts +162 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +549 -0
- package/dist/tables.d.ts +353 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +585 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/turn.d.ts +9 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +75 -0
- package/dist/validation.d.ts +29 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +101 -0
- package/dist/windows.d.ts +22 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +89 -0
- package/dist/wire.d.ts +165 -32
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +56 -31
- package/package.json +22 -19
- package/AGENTS.md +0 -299
- 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/context.js +0 -10
- 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 -26
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -62
- package/dist/chat/markdown.d.ts +0 -20
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -188
- 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/memory.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
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:
|
|
8
|
+
outcome: 604_800,
|
|
5
9
|
refreshHorizon: 1,
|
|
6
10
|
};
|
|
7
11
|
function declaredRetention(value) {
|
|
@@ -15,12 +19,7 @@ function declaredRetention(value) {
|
|
|
15
19
|
}
|
|
16
20
|
const MODEL_ABSENT = { kind: 'model-unavailable', reason: 'not-readable' };
|
|
17
21
|
function modelsOf(room) {
|
|
18
|
-
return {
|
|
19
|
-
collection: room.model ?? MODEL_ABSENT,
|
|
20
|
-
...(room.typedSelection === undefined
|
|
21
|
-
? {}
|
|
22
|
-
: { selection: room.selectionModel ?? MODEL_ABSENT }),
|
|
23
|
-
};
|
|
22
|
+
return { collection: room.model ?? MODEL_ABSENT };
|
|
24
23
|
}
|
|
25
24
|
function changedModels(room, from) {
|
|
26
25
|
const now = modelsOf(room);
|
|
@@ -53,12 +52,16 @@ export function createMemoryAdapter(options = {}) {
|
|
|
53
52
|
const listeners = new Set();
|
|
54
53
|
const modeObservers = new Set();
|
|
55
54
|
const scripted = new Map();
|
|
56
|
-
const
|
|
57
|
-
const sealed = new Set();
|
|
55
|
+
const sentTurns = new Map();
|
|
58
56
|
const historyPageSize = options.historyPageSize;
|
|
59
|
-
|
|
57
|
+
const attached = new Map();
|
|
58
|
+
const linked = new WeakMap();
|
|
59
|
+
const carried = new Map();
|
|
60
60
|
let expiring = [];
|
|
61
|
+
let openings = 0;
|
|
62
|
+
const declaredRooms = new Set();
|
|
61
63
|
let replicated = [];
|
|
64
|
+
let heldCursor = null;
|
|
62
65
|
let issued = 0;
|
|
63
66
|
function scriptConversations(entries) {
|
|
64
67
|
scripted.clear();
|
|
@@ -86,6 +89,19 @@ export function createMemoryAdapter(options = {}) {
|
|
|
86
89
|
const wanted = ordinals.get(`${locator}\u0000${target}`);
|
|
87
90
|
return held !== undefined && wanted !== undefined && held >= wanted;
|
|
88
91
|
}
|
|
92
|
+
function heldBlob(room, path) {
|
|
93
|
+
return attached.get(`${room.locator}\u0000${path}`) ?? room.blobs?.[path];
|
|
94
|
+
}
|
|
95
|
+
function freePath(room, name) {
|
|
96
|
+
const dot = name.lastIndexOf('.');
|
|
97
|
+
const stem = dot > 0 ? name.slice(0, dot) : name;
|
|
98
|
+
const extension = dot > 0 ? name.slice(dot) : '';
|
|
99
|
+
for (let count = 1;; count += 1) {
|
|
100
|
+
const path = `${ATTACHMENTS}/${count === 1 ? stem : `${stem}-${count}`}${extension}`;
|
|
101
|
+
if (heldBlob(room, path) === undefined && room.documents?.[path] === undefined)
|
|
102
|
+
return path;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
89
105
|
function retain(entries) {
|
|
90
106
|
for (const room of entries) {
|
|
91
107
|
note(room.locator, room);
|
|
@@ -121,22 +137,37 @@ export function createMemoryAdapter(options = {}) {
|
|
|
121
137
|
...(opening ? { models: modelsOf(room) } : {}),
|
|
122
138
|
documents: named(room.documents ?? {}, taken),
|
|
123
139
|
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
140
|
+
...(room.fileIds === undefined
|
|
141
|
+
? {}
|
|
142
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
124
143
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
125
144
|
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
145
|
+
...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
|
|
126
146
|
...(next < paths.length ? { pageToken: taken.at(-1) } : {}),
|
|
127
147
|
};
|
|
128
148
|
}
|
|
129
|
-
function
|
|
149
|
+
function foldersMoved(room, from) {
|
|
150
|
+
const now = new Set(room.folders ?? []);
|
|
151
|
+
const before = new Set(from.folders ?? []);
|
|
152
|
+
const folders = [...now].filter((folder) => !before.has(folder)).sort();
|
|
153
|
+
const folderRemovals = [...before].filter((folder) => !now.has(folder)).sort();
|
|
154
|
+
return {
|
|
155
|
+
...(folders.length === 0 ? {} : { folders }),
|
|
156
|
+
...(folderRemovals.length === 0 ? {} : { folderRemovals }),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function advancement(room, from, at, whole = false) {
|
|
130
160
|
const current = room.documents ?? {};
|
|
131
161
|
const previous = from.documents ?? {};
|
|
132
162
|
const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
|
|
133
163
|
const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
|
|
134
164
|
const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
|
|
165
|
+
room.fileIds?.[path] !== from.fileIds?.[path] ||
|
|
135
166
|
!sameChange(room.changes?.[path], from.changes?.[path]);
|
|
136
167
|
const changed = Object.keys(current)
|
|
137
168
|
.filter((path) => current[path] !== previous[path] || headMoved(path))
|
|
138
169
|
.sort();
|
|
139
|
-
const size = pageSize ?? changed.length;
|
|
170
|
+
const size = whole ? changed.length : (pageSize ?? changed.length);
|
|
140
171
|
const taken = changed.slice(at, at + size);
|
|
141
172
|
const next = at + taken.length;
|
|
142
173
|
const opening = at === 0;
|
|
@@ -153,8 +184,12 @@ export function createMemoryAdapter(options = {}) {
|
|
|
153
184
|
...(models === undefined ? {} : { models }),
|
|
154
185
|
documents: named(current, taken),
|
|
155
186
|
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
187
|
+
...(room.fileIds === undefined
|
|
188
|
+
? {}
|
|
189
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
156
190
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
157
191
|
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
192
|
+
...(opening ? foldersMoved(room, from) : {}),
|
|
158
193
|
removals: opening
|
|
159
194
|
? [
|
|
160
195
|
...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
|
|
@@ -164,6 +199,26 @@ export function createMemoryAdapter(options = {}) {
|
|
|
164
199
|
...(pageToken === undefined ? {} : { pageToken }),
|
|
165
200
|
};
|
|
166
201
|
}
|
|
202
|
+
function carry(locator) {
|
|
203
|
+
const at = carried.get(locator);
|
|
204
|
+
const current = rooms.find((entry) => entry.locator === locator);
|
|
205
|
+
if (at === undefined || current === undefined || current.roomVersion === at)
|
|
206
|
+
return;
|
|
207
|
+
const from = served.get(locator)?.get(at);
|
|
208
|
+
carried.set(locator, current.roomVersion);
|
|
209
|
+
if (from === undefined)
|
|
210
|
+
return;
|
|
211
|
+
const page = advancement(current, from, 0, true);
|
|
212
|
+
for (const observer of observers) {
|
|
213
|
+
observer({
|
|
214
|
+
kind: 'room-change',
|
|
215
|
+
locator,
|
|
216
|
+
from: at,
|
|
217
|
+
roomVersion: current.roomVersion,
|
|
218
|
+
read: async () => page,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
167
222
|
function pageOf(conversation, after) {
|
|
168
223
|
const messages = conversation.messages ?? [];
|
|
169
224
|
const first = typeof after === 'string' ? messages.findIndex((message) => message.position > after) : 0;
|
|
@@ -178,16 +233,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
178
233
|
: {}),
|
|
179
234
|
};
|
|
180
235
|
}
|
|
181
|
-
function historiesOf(
|
|
182
|
-
const asked = input?.conversations;
|
|
183
|
-
if (!Array.isArray(asked))
|
|
184
|
-
return { kind: 'rejected', code: 'invalid_request', fields: {}, retryable: false };
|
|
236
|
+
function historiesOf(request) {
|
|
185
237
|
const histories = [];
|
|
186
|
-
for (const entry of
|
|
187
|
-
const conversation =
|
|
238
|
+
for (const entry of request.conversations) {
|
|
239
|
+
const conversation = scripted.get(entry.conversation);
|
|
188
240
|
if (conversation === undefined)
|
|
189
241
|
continue;
|
|
190
|
-
const outcome = conversation.outcomes?.
|
|
242
|
+
const outcome = conversation.outcomes?.history;
|
|
191
243
|
if (outcome !== undefined)
|
|
192
244
|
return outcome;
|
|
193
245
|
histories.push(pageOf(conversation, entry.after));
|
|
@@ -198,15 +250,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
198
250
|
function conversationAction(request) {
|
|
199
251
|
const name = request.name;
|
|
200
252
|
const input = (request.input ?? {});
|
|
201
|
-
if (name === '
|
|
202
|
-
return historiesOf(request.input);
|
|
203
|
-
if (name === 'conversation.create') {
|
|
253
|
+
if (name === 'conversations/create') {
|
|
204
254
|
issued += 1;
|
|
205
255
|
const conversation = `conversation-${issued}`;
|
|
206
256
|
scripted.set(conversation, { conversation });
|
|
207
|
-
return { kind: 'action', result: { conversation } };
|
|
257
|
+
return { kind: 'action', result: { conversation_id: conversation } };
|
|
208
258
|
}
|
|
209
|
-
const named = typeof input.
|
|
259
|
+
const named = typeof input.conversation_id === 'string' ? input.conversation_id : '';
|
|
210
260
|
const conversation = scripted.get(named);
|
|
211
261
|
if (conversation === undefined) {
|
|
212
262
|
return {
|
|
@@ -219,28 +269,28 @@ export function createMemoryAdapter(options = {}) {
|
|
|
219
269
|
const outcome = conversation.outcomes?.[name];
|
|
220
270
|
if (outcome !== undefined)
|
|
221
271
|
return outcome;
|
|
222
|
-
if (name === '
|
|
272
|
+
if (name === 'conversations/send') {
|
|
273
|
+
const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
|
|
274
|
+
const answered = operation === null ? undefined : sentTurns.get(operation);
|
|
275
|
+
if (answered !== undefined)
|
|
276
|
+
return { kind: 'action', result: { message_id: answered } };
|
|
223
277
|
issued += 1;
|
|
224
278
|
const turn = `turn-${issued}`;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (name === 'conversation.cancel') {
|
|
229
|
-
const turn = typeof input.turn === 'string' ? input.turn : '';
|
|
230
|
-
if (sealed.has(turn) || !unsealed.has(turn)) {
|
|
231
|
-
return { kind: 'rejected', code: 'turn-sealed', fields: { turn }, retryable: false };
|
|
232
|
-
}
|
|
233
|
-
unsealed.delete(turn);
|
|
234
|
-
return { kind: 'action', result: { turn, cancelled: true } };
|
|
279
|
+
if (operation !== null)
|
|
280
|
+
sentTurns.set(operation, turn);
|
|
281
|
+
return { kind: 'action', result: { message_id: turn } };
|
|
235
282
|
}
|
|
236
|
-
if (name === '
|
|
283
|
+
if (name === 'conversations/delete')
|
|
237
284
|
scripted.delete(named);
|
|
238
|
-
return { kind: 'action', result: {
|
|
285
|
+
return { kind: 'action', result: { conversation_id: named } };
|
|
239
286
|
}
|
|
240
287
|
function announceList() {
|
|
241
|
-
const entries = [...scripted.values()].flatMap(({ conversation, listed }) => listed === undefined
|
|
242
|
-
|
|
243
|
-
|
|
288
|
+
const entries = [...scripted.values()].flatMap(({ conversation, listed, messages = [] }) => listed === undefined
|
|
289
|
+
? []
|
|
290
|
+
: [{ conversation, ...listed, newest: messages.at(-1)?.position ?? null }]);
|
|
291
|
+
for (const listener of listeners) {
|
|
292
|
+
listener({ kind: 'list', entries, whole: true, more: false, cursor: null });
|
|
293
|
+
}
|
|
244
294
|
}
|
|
245
295
|
function discovery() {
|
|
246
296
|
return {
|
|
@@ -252,7 +302,41 @@ export function createMemoryAdapter(options = {}) {
|
|
|
252
302
|
...(options.member === undefined ? {} : { member: options.member }),
|
|
253
303
|
};
|
|
254
304
|
}
|
|
305
|
+
function discovered() {
|
|
306
|
+
return resolveScript(scripts.discover, discovery, undefined).then((answer) => {
|
|
307
|
+
if (answer.kind === 'discovery')
|
|
308
|
+
for (const room of answer.rooms)
|
|
309
|
+
note(room.locator, room);
|
|
310
|
+
return answer;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function opened(notify) {
|
|
314
|
+
const opening = ++openings;
|
|
315
|
+
notify({ kind: 'opened' });
|
|
316
|
+
void discovered()
|
|
317
|
+
.catch(() => ({ kind: 'transport-uncertainty' }))
|
|
318
|
+
.then((answer) => {
|
|
319
|
+
if (opening !== openings)
|
|
320
|
+
return;
|
|
321
|
+
if (answer.kind !== 'discovery') {
|
|
322
|
+
openings += 1;
|
|
323
|
+
carried.clear();
|
|
324
|
+
const revoked = answer.kind === 'revoked-authorization';
|
|
325
|
+
notify({ kind: 'closed', revoked, lost: !revoked, authorityChanged: false });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
declaredRooms.clear();
|
|
329
|
+
for (const room of answer.rooms)
|
|
330
|
+
declaredRooms.add(room.locator);
|
|
331
|
+
notify({ kind: 'discovered', discovery: answer });
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
function emitAll(event) {
|
|
335
|
+
for (const observer of observers)
|
|
336
|
+
observer(event);
|
|
337
|
+
}
|
|
255
338
|
return {
|
|
339
|
+
...(options.roomTypes === undefined ? {} : { roomTypes: options.roomTypes }),
|
|
256
340
|
setRooms(next) {
|
|
257
341
|
rooms = [...next];
|
|
258
342
|
retain(rooms);
|
|
@@ -261,26 +345,37 @@ export function createMemoryAdapter(options = {}) {
|
|
|
261
345
|
scriptConversations(next);
|
|
262
346
|
},
|
|
263
347
|
open() {
|
|
348
|
+
carried.clear();
|
|
264
349
|
announceList();
|
|
265
|
-
|
|
266
|
-
observer({ kind: 'opened' });
|
|
350
|
+
opened(emitAll);
|
|
267
351
|
},
|
|
268
|
-
close(revoked = false) {
|
|
269
|
-
|
|
270
|
-
|
|
352
|
+
close({ revoked = false, lost = !revoked, authorityChanged = false } = {}) {
|
|
353
|
+
openings += 1;
|
|
354
|
+
carried.clear();
|
|
355
|
+
emitAll({ kind: 'closed', revoked, lost, authorityChanged });
|
|
271
356
|
},
|
|
272
357
|
expire(locators) {
|
|
273
358
|
expiring = [...locators];
|
|
274
359
|
},
|
|
275
|
-
notifyRoomVersion({ locator
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
});
|
|
278
377
|
},
|
|
279
378
|
notifyConversation(event) {
|
|
280
|
-
if (event.kind === 'accepted-message') {
|
|
281
|
-
sealed.add(event.message.turn);
|
|
282
|
-
unsealed.delete(event.message.turn);
|
|
283
|
-
}
|
|
284
379
|
for (const listener of listeners)
|
|
285
380
|
listener(event);
|
|
286
381
|
},
|
|
@@ -289,21 +384,31 @@ export function createMemoryAdapter(options = {}) {
|
|
|
289
384
|
observer(mode);
|
|
290
385
|
},
|
|
291
386
|
heldRooms() {
|
|
292
|
-
return
|
|
387
|
+
return [...carried.keys()].sort();
|
|
293
388
|
},
|
|
294
389
|
replicatedConversations() {
|
|
295
390
|
return replicated;
|
|
296
391
|
},
|
|
392
|
+
heldConversationCursor() {
|
|
393
|
+
return heldCursor;
|
|
394
|
+
},
|
|
297
395
|
conversations: {
|
|
298
396
|
replicate(next) {
|
|
299
397
|
replicated = [...next];
|
|
300
398
|
},
|
|
399
|
+
hold(cursor) {
|
|
400
|
+
heldCursor = cursor;
|
|
401
|
+
},
|
|
301
402
|
observe(notify) {
|
|
302
403
|
listeners.add(notify);
|
|
303
404
|
return () => {
|
|
304
405
|
listeners.delete(notify);
|
|
305
406
|
};
|
|
306
407
|
},
|
|
408
|
+
history: (request) => Promise.resolve(historiesOf(request)),
|
|
409
|
+
...(options.agents === undefined
|
|
410
|
+
? {}
|
|
411
|
+
: { agents: () => Promise.resolve(structuredClone(options.agents)) }),
|
|
307
412
|
},
|
|
308
413
|
serviceMode: {
|
|
309
414
|
observe(notify) {
|
|
@@ -315,29 +420,29 @@ export function createMemoryAdapter(options = {}) {
|
|
|
315
420
|
},
|
|
316
421
|
roomStream: {
|
|
317
422
|
hold(asked) {
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
expiring = [];
|
|
321
|
-
const moved = asked.flatMap((room) => {
|
|
423
|
+
const named = asked.map((room) => room.locator);
|
|
424
|
+
const unknown = asked.flatMap((room) => {
|
|
322
425
|
const current = rooms.find((entry) => entry.locator === room.locator);
|
|
323
426
|
return current === undefined ||
|
|
324
|
-
|
|
325
|
-
|
|
427
|
+
current.roomVersion === room.roomVersion ||
|
|
428
|
+
served.get(room.locator)?.has(room.roomVersion) === true
|
|
326
429
|
? []
|
|
327
|
-
: [
|
|
430
|
+
: [room.locator];
|
|
328
431
|
});
|
|
432
|
+
const expired = [
|
|
433
|
+
...new Set([...expiring.filter((locator) => named.includes(locator)), ...unknown]),
|
|
434
|
+
];
|
|
435
|
+
expiring = expiring.filter((locator) => !named.includes(locator));
|
|
329
436
|
queueMicrotask(() => {
|
|
330
|
-
for (const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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
|
+
}
|
|
334
444
|
}
|
|
335
|
-
|
|
336
|
-
},
|
|
337
|
-
reopen() {
|
|
338
|
-
queueMicrotask(() => {
|
|
339
|
-
for (const observer of observers)
|
|
340
|
-
observer({ kind: 'closed', revoked: false });
|
|
445
|
+
emitAll({ kind: 'caught-up', expired });
|
|
341
446
|
});
|
|
342
447
|
},
|
|
343
448
|
observe(notify) {
|
|
@@ -346,11 +451,14 @@ export function createMemoryAdapter(options = {}) {
|
|
|
346
451
|
if (!observers.has(notify))
|
|
347
452
|
return;
|
|
348
453
|
if (options.unopened === true) {
|
|
349
|
-
notify({ kind: 'closed', revoked: false });
|
|
454
|
+
notify({ kind: 'closed', revoked: false, lost: true, authorityChanged: false });
|
|
350
455
|
return;
|
|
351
456
|
}
|
|
352
457
|
announceList();
|
|
353
|
-
|
|
458
|
+
opened((event) => {
|
|
459
|
+
if (observers.has(notify))
|
|
460
|
+
notify(event);
|
|
461
|
+
});
|
|
354
462
|
});
|
|
355
463
|
return () => {
|
|
356
464
|
observers.delete(notify);
|
|
@@ -367,12 +475,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
367
475
|
return resolveScript(scripts.authorize, () => ({}), undefined);
|
|
368
476
|
},
|
|
369
477
|
async discover(_authorization) {
|
|
370
|
-
return
|
|
371
|
-
if (answer.kind === 'discovery')
|
|
372
|
-
for (const room of answer.rooms)
|
|
373
|
-
note(room.locator, room);
|
|
374
|
-
return answer;
|
|
375
|
-
});
|
|
478
|
+
return discovered();
|
|
376
479
|
},
|
|
377
480
|
reached,
|
|
378
481
|
follows(locator, roomVersion, next) {
|
|
@@ -429,7 +532,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
429
532
|
retryable: false,
|
|
430
533
|
affected: {},
|
|
431
534
|
};
|
|
432
|
-
}, request).then((answer) =>
|
|
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
|
+
});
|
|
433
542
|
},
|
|
434
543
|
async history(_authorization, request) {
|
|
435
544
|
return resolveScript(scripts.history, () => {
|
|
@@ -445,31 +554,42 @@ export function createMemoryAdapter(options = {}) {
|
|
|
445
554
|
},
|
|
446
555
|
async binary(_authorization, request) {
|
|
447
556
|
return resolveScript(scripts.binary, () => {
|
|
448
|
-
if (request.kind === 'reference') {
|
|
449
|
-
return { kind: 'rejected', code: 'unscripted-binary', fields: {}, retryable: false };
|
|
450
|
-
}
|
|
451
557
|
const room = rooms.find((entry) => entry.locator === request.locator);
|
|
452
558
|
if (room === undefined)
|
|
453
559
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
454
|
-
const blob = room
|
|
560
|
+
const blob = heldBlob(room, request.path);
|
|
455
561
|
return blob === undefined
|
|
456
562
|
? { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false }
|
|
457
|
-
: { kind: 'binary', blob };
|
|
563
|
+
: { kind: 'binary', body: blob.stream(), mediaType: blob.type };
|
|
458
564
|
}, request);
|
|
459
565
|
},
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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);
|
|
469
589
|
},
|
|
470
590
|
async action(_authorization, request) {
|
|
471
591
|
return resolveScript(scripts.action, () => {
|
|
472
|
-
if (request.name.startsWith('
|
|
592
|
+
if (request.name.startsWith('conversations/'))
|
|
473
593
|
return conversationAction(request);
|
|
474
594
|
return { kind: 'rejected', code: 'unscripted-action', fields: {}, retryable: false };
|
|
475
595
|
}, request).then((answer) => {
|
|
@@ -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":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,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"}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { HOLDS_PHRASE } from './phrase.js';
|
|
2
|
+
export const MESSAGE_TABLES = [
|
|
3
|
+
'CREATE TABLE conversation_reads (conversation TEXT PRIMARY KEY, read TEXT, partial INTEGER NOT NULL) WITHOUT ROWID',
|
|
4
|
+
'CREATE TABLE conversation_messages (id INTEGER PRIMARY KEY, conversation TEXT NOT NULL, identity TEXT NOT NULL, turn TEXT NOT NULL, position TEXT NOT NULL, message TEXT NOT NULL, text TEXT NOT NULL)',
|
|
5
|
+
'CREATE UNIQUE INDEX conversation_messages_identity ON conversation_messages (conversation, identity)',
|
|
6
|
+
'CREATE INDEX conversation_messages_position ON conversation_messages (conversation, position, identity)',
|
|
7
|
+
'CREATE INDEX conversation_messages_turn ON conversation_messages (conversation, turn)',
|
|
8
|
+
];
|
|
9
|
+
function text(value) {
|
|
10
|
+
return typeof value === 'string' ? value : String(value);
|
|
11
|
+
}
|
|
12
|
+
export function heldConversations(connection) {
|
|
13
|
+
const held = new Map();
|
|
14
|
+
for (const row of connection.rows('SELECT conversation, read, partial FROM conversation_reads')) {
|
|
15
|
+
held.set(text(row.conversation), {
|
|
16
|
+
conversation: text(row.conversation),
|
|
17
|
+
read: row.read === null ? null : text(row.read),
|
|
18
|
+
partial: Number(row.partial) === 1,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
for (const row of connection.rows('SELECT DISTINCT conversation FROM conversation_messages WHERE conversation NOT IN (SELECT conversation FROM conversation_reads)')) {
|
|
22
|
+
held.set(text(row.conversation), {
|
|
23
|
+
conversation: text(row.conversation),
|
|
24
|
+
read: undefined,
|
|
25
|
+
partial: true,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return [...held.values()];
|
|
29
|
+
}
|
|
30
|
+
export function keptMessages(connection, { conversation, messages, read }) {
|
|
31
|
+
for (const message of messages) {
|
|
32
|
+
const [held] = connection.rows('SELECT id FROM conversation_messages WHERE conversation = ? AND identity = ?', [conversation, message.identity]);
|
|
33
|
+
const record = [
|
|
34
|
+
message.turn,
|
|
35
|
+
message.position,
|
|
36
|
+
JSON.stringify(message.message ?? null),
|
|
37
|
+
message.text,
|
|
38
|
+
];
|
|
39
|
+
if (held === undefined) {
|
|
40
|
+
connection.run('INSERT INTO conversation_messages (conversation, identity, turn, position, message, text) VALUES (?, ?, ?, ?, ?, ?)', [conversation, message.identity, ...record]);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
connection.run('UPDATE conversation_messages SET turn = ?, position = ?, message = ?, text = ? WHERE id = ?', [...record, held.id]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (read !== undefined) {
|
|
47
|
+
connection.run('INSERT OR REPLACE INTO conversation_reads (conversation, read, partial) VALUES (?, ?, ?)', [conversation, read.at, read.partial ? 1 : 0]);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function accepted(row) {
|
|
52
|
+
return {
|
|
53
|
+
identity: text(row.identity),
|
|
54
|
+
turn: text(row.turn),
|
|
55
|
+
position: text(row.position),
|
|
56
|
+
text: text(row.text),
|
|
57
|
+
message: JSON.parse(text(row.message)),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function holding(phrase) {
|
|
61
|
+
return phrase === null
|
|
62
|
+
? { sql: '', bind: [] }
|
|
63
|
+
: { sql: ` AND ${HOLDS_PHRASE}(text, ?)`, bind: [phrase.toLowerCase()] };
|
|
64
|
+
}
|
|
65
|
+
export function messageWindow(connection, conversation, limit, before, phrase) {
|
|
66
|
+
const held = holding(phrase);
|
|
67
|
+
const rows = connection.rows(`SELECT identity, turn, position, message, text FROM conversation_messages WHERE conversation = ?${held.sql}${before === null ? '' : ' AND (position < ? OR (position = ? AND identity < ?))'} ORDER BY position DESC, identity DESC LIMIT ?`, before === null
|
|
68
|
+
? [conversation, ...held.bind, limit + 1]
|
|
69
|
+
: [conversation, ...held.bind, before[0], before[0], before[1], limit + 1]);
|
|
70
|
+
return { messages: rows.slice(0, limit).map(accepted).reverse(), more: rows.length > limit };
|
|
71
|
+
}
|
|
72
|
+
export function messageCount(connection, conversation, phrase) {
|
|
73
|
+
const held = holding(phrase);
|
|
74
|
+
const [counted] = connection.rows(`SELECT count(*) AS held FROM conversation_messages WHERE conversation = ?${held.sql}`, [conversation, ...held.bind]);
|
|
75
|
+
return Number(counted?.held ?? 0);
|
|
76
|
+
}
|
|
77
|
+
export function turnArrived(connection, conversation, turn) {
|
|
78
|
+
return (connection.rows('SELECT 1 FROM conversation_messages WHERE conversation = ? AND turn = ? LIMIT 1', [conversation, turn]).length > 0);
|
|
79
|
+
}
|
|
80
|
+
export function droppedMessages(connection, conversations) {
|
|
81
|
+
for (const conversation of conversations) {
|
|
82
|
+
connection.run('DELETE FROM conversation_messages WHERE conversation = ?', [conversation]);
|
|
83
|
+
connection.run('DELETE FROM conversation_reads WHERE conversation = ?', [conversation]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function forgottenMessages(connection) {
|
|
87
|
+
connection.run('DELETE FROM conversation_messages');
|
|
88
|
+
connection.run('DELETE FROM conversation_reads');
|
|
89
|
+
}
|
package/dist/model.d.ts
CHANGED
|
@@ -28,13 +28,19 @@ export type ModelState = {
|
|
|
28
28
|
verifiedWith: ModelIdentity;
|
|
29
29
|
types: VerifiedModel['types'];
|
|
30
30
|
};
|
|
31
|
-
export type
|
|
31
|
+
export type StoredModel = Extract<ModelState, {
|
|
32
32
|
status: 'unavailable';
|
|
33
|
+
}> | Omit<Extract<ModelState, {
|
|
34
|
+
status: 'current' | 'cached';
|
|
35
|
+
}>, 'types'>;
|
|
36
|
+
export type TypesResult = {
|
|
37
|
+
status: Open<'unavailable'>;
|
|
33
38
|
reason: ModelUnavailableReason;
|
|
39
|
+
types: null;
|
|
34
40
|
schema?: string | null;
|
|
35
41
|
revision?: string | null;
|
|
36
42
|
} | {
|
|
37
|
-
status: 'current' | 'cached'
|
|
43
|
+
status: Open<'current' | 'cached'>;
|
|
38
44
|
identity: string;
|
|
39
45
|
version: string;
|
|
40
46
|
verifiedWith: ModelIdentity;
|
|
@@ -50,6 +56,7 @@ export type ValidationReceipt = {
|
|
|
50
56
|
export declare const NO_MODEL: ModelState;
|
|
51
57
|
export declare function definitionOf(state: ModelState, type: string | undefined): Definition | undefined;
|
|
52
58
|
export declare function modelTypes(state: ModelState): TypesResult;
|
|
59
|
+
export declare function storedModel(state: ModelState): StoredModel;
|
|
53
60
|
export declare function cached(state: ModelState): ModelState;
|
|
54
61
|
export declare function sameModel(left: ModelIdentity, right: ModelIdentity): boolean;
|
|
55
62
|
export declare function referenceField(facts: ValueFacts | undefined): boolean;
|