@agentshouse/mdruntime 0.1.0-c97456d63baba → 0.1.0-c99ee6ff87175
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 +145 -70
- 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 +26 -10
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +180 -99
- 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 -16
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -88
- 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 +17 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +95 -11
- package/dist/collection.d.ts +10 -21
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +39 -291
- 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 +28 -15
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3294 -1360
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/{chat/context.js → context.js} +1 -4
- package/dist/conversation.d.ts +30 -14
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +462 -203
- 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 +2 -5
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +4 -1
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +19 -23
- 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 +6 -8
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +93 -23
- 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 +18 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- 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 +16 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +208 -102
- 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 +6 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -10
- 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 +17 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +100 -5
- 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 +45 -7
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +39 -0
- package/dist/overlay.d.ts +3 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +95 -156
- 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 +42 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +67 -7
- package/dist/reach.d.ts +16 -8
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +219 -90
- package/dist/react.d.ts +4 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/readiness.d.ts +14 -17
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +2 -8
- package/dist/recovery.d.ts +3 -2
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +34 -7
- package/dist/refresh.d.ts +17 -14
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +155 -52
- package/dist/replica.d.ts +55 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +300 -182
- package/dist/room-draft.d.ts +35 -4
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +161 -74
- package/dist/rows.d.ts +39 -29
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +178 -94
- package/dist/save.d.ts +53 -14
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +529 -185
- package/dist/search.d.ts +15 -77
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +10 -184
- 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 +7 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +119 -66
- package/dist/status.d.ts +4 -3
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +99 -97
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +336 -660
- 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 +5 -3
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +51 -21
- 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 +34 -5
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +10 -2
- package/package.json +18 -19
- package/AGENTS.md +0 -299
- package/dist/acquisition.d.ts +0 -14
- package/dist/acquisition.d.ts.map +0 -1
- package/dist/acquisition.js +0 -24
- package/dist/chat/acts.d.ts +0 -33
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/context.d.ts +0 -3
- package/dist/chat/context.d.ts.map +0 -1
- package/dist/chat/input.d.ts +0 -9
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -99
- package/dist/chat/kit.d.ts +0 -61
- 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 -27
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -63
- 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 -22
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -155
- 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 -629
- 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 -34
- 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 -25
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -639
package/dist/memory.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
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
8
|
outcome: 604_800,
|
|
@@ -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,14 +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 unsealed = new Map();
|
|
57
|
-
const sealed = new Set();
|
|
58
55
|
const sentTurns = new Map();
|
|
59
56
|
const historyPageSize = options.historyPageSize;
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
const attached = new Map();
|
|
58
|
+
const linked = new WeakMap();
|
|
59
|
+
const carried = new Map();
|
|
62
60
|
let expiring = [];
|
|
61
|
+
let openings = 0;
|
|
62
|
+
const declaredRooms = new Set();
|
|
63
63
|
let replicated = [];
|
|
64
|
+
let heldCursor = null;
|
|
64
65
|
let issued = 0;
|
|
65
66
|
function scriptConversations(entries) {
|
|
66
67
|
scripted.clear();
|
|
@@ -88,6 +89,19 @@ export function createMemoryAdapter(options = {}) {
|
|
|
88
89
|
const wanted = ordinals.get(`${locator}\u0000${target}`);
|
|
89
90
|
return held !== undefined && wanted !== undefined && held >= wanted;
|
|
90
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
|
+
}
|
|
91
105
|
function retain(entries) {
|
|
92
106
|
for (const room of entries) {
|
|
93
107
|
note(room.locator, room);
|
|
@@ -123,22 +137,37 @@ export function createMemoryAdapter(options = {}) {
|
|
|
123
137
|
...(opening ? { models: modelsOf(room) } : {}),
|
|
124
138
|
documents: named(room.documents ?? {}, taken),
|
|
125
139
|
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
140
|
+
...(room.fileIds === undefined
|
|
141
|
+
? {}
|
|
142
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
126
143
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
127
144
|
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
145
|
+
...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
|
|
128
146
|
...(next < paths.length ? { pageToken: taken.at(-1) } : {}),
|
|
129
147
|
};
|
|
130
148
|
}
|
|
131
|
-
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) {
|
|
132
160
|
const current = room.documents ?? {};
|
|
133
161
|
const previous = from.documents ?? {};
|
|
134
162
|
const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
|
|
135
163
|
const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
|
|
136
164
|
const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
|
|
165
|
+
room.fileIds?.[path] !== from.fileIds?.[path] ||
|
|
137
166
|
!sameChange(room.changes?.[path], from.changes?.[path]);
|
|
138
167
|
const changed = Object.keys(current)
|
|
139
168
|
.filter((path) => current[path] !== previous[path] || headMoved(path))
|
|
140
169
|
.sort();
|
|
141
|
-
const size = pageSize ?? changed.length;
|
|
170
|
+
const size = whole ? changed.length : (pageSize ?? changed.length);
|
|
142
171
|
const taken = changed.slice(at, at + size);
|
|
143
172
|
const next = at + taken.length;
|
|
144
173
|
const opening = at === 0;
|
|
@@ -155,8 +184,12 @@ export function createMemoryAdapter(options = {}) {
|
|
|
155
184
|
...(models === undefined ? {} : { models }),
|
|
156
185
|
documents: named(current, taken),
|
|
157
186
|
revisions: named(room.revisions ?? {}, [...taken, ...targets]),
|
|
187
|
+
...(room.fileIds === undefined
|
|
188
|
+
? {}
|
|
189
|
+
: { fileIds: named(room.fileIds, [...taken, ...targets]) }),
|
|
158
190
|
changes: named(room.changes ?? {}, [...taken, ...targets]),
|
|
159
191
|
binaryFiles: named(room.binaryFiles ?? {}, targets),
|
|
192
|
+
...(opening ? foldersMoved(room, from) : {}),
|
|
160
193
|
removals: opening
|
|
161
194
|
? [
|
|
162
195
|
...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
|
|
@@ -166,6 +199,26 @@ export function createMemoryAdapter(options = {}) {
|
|
|
166
199
|
...(pageToken === undefined ? {} : { pageToken }),
|
|
167
200
|
};
|
|
168
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
|
+
}
|
|
169
222
|
function pageOf(conversation, after) {
|
|
170
223
|
const messages = conversation.messages ?? [];
|
|
171
224
|
const first = typeof after === 'string' ? messages.findIndex((message) => message.position > after) : 0;
|
|
@@ -180,16 +233,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
180
233
|
: {}),
|
|
181
234
|
};
|
|
182
235
|
}
|
|
183
|
-
function historiesOf(
|
|
184
|
-
const asked = input?.conversations;
|
|
185
|
-
if (!Array.isArray(asked))
|
|
186
|
-
return { kind: 'rejected', code: 'invalid_request', fields: {}, retryable: false };
|
|
236
|
+
function historiesOf(request) {
|
|
187
237
|
const histories = [];
|
|
188
|
-
for (const entry of
|
|
189
|
-
const conversation =
|
|
238
|
+
for (const entry of request.conversations) {
|
|
239
|
+
const conversation = scripted.get(entry.conversation);
|
|
190
240
|
if (conversation === undefined)
|
|
191
241
|
continue;
|
|
192
|
-
const outcome = conversation.outcomes?.
|
|
242
|
+
const outcome = conversation.outcomes?.history;
|
|
193
243
|
if (outcome !== undefined)
|
|
194
244
|
return outcome;
|
|
195
245
|
histories.push(pageOf(conversation, entry.after));
|
|
@@ -200,15 +250,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
200
250
|
function conversationAction(request) {
|
|
201
251
|
const name = request.name;
|
|
202
252
|
const input = (request.input ?? {});
|
|
203
|
-
if (name === '
|
|
204
|
-
return historiesOf(request.input);
|
|
205
|
-
if (name === 'conversation.create') {
|
|
253
|
+
if (name === 'conversations/create') {
|
|
206
254
|
issued += 1;
|
|
207
255
|
const conversation = `conversation-${issued}`;
|
|
208
256
|
scripted.set(conversation, { conversation });
|
|
209
|
-
return { kind: 'action', result: { conversation } };
|
|
257
|
+
return { kind: 'action', result: { conversation_id: conversation } };
|
|
210
258
|
}
|
|
211
|
-
const named = typeof input.
|
|
259
|
+
const named = typeof input.conversation_id === 'string' ? input.conversation_id : '';
|
|
212
260
|
const conversation = scripted.get(named);
|
|
213
261
|
if (conversation === undefined) {
|
|
214
262
|
return {
|
|
@@ -221,34 +269,28 @@ export function createMemoryAdapter(options = {}) {
|
|
|
221
269
|
const outcome = conversation.outcomes?.[name];
|
|
222
270
|
if (outcome !== undefined)
|
|
223
271
|
return outcome;
|
|
224
|
-
if (name === '
|
|
272
|
+
if (name === 'conversations/send') {
|
|
225
273
|
const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
|
|
226
274
|
const answered = operation === null ? undefined : sentTurns.get(operation);
|
|
227
275
|
if (answered !== undefined)
|
|
228
|
-
return { kind: 'action', result: {
|
|
276
|
+
return { kind: 'action', result: { message_id: answered } };
|
|
229
277
|
issued += 1;
|
|
230
278
|
const turn = `turn-${issued}`;
|
|
231
|
-
unsealed.set(turn, named);
|
|
232
279
|
if (operation !== null)
|
|
233
280
|
sentTurns.set(operation, turn);
|
|
234
|
-
return { kind: 'action', result: { turn } };
|
|
281
|
+
return { kind: 'action', result: { message_id: turn } };
|
|
235
282
|
}
|
|
236
|
-
if (name === '
|
|
237
|
-
const turn = typeof input.turn === 'string' ? input.turn : '';
|
|
238
|
-
if (sealed.has(turn) || !unsealed.has(turn)) {
|
|
239
|
-
return { kind: 'rejected', code: 'turn-sealed', fields: { turn }, retryable: false };
|
|
240
|
-
}
|
|
241
|
-
unsealed.delete(turn);
|
|
242
|
-
return { kind: 'action', result: { turn, cancelled: true } };
|
|
243
|
-
}
|
|
244
|
-
if (name === 'conversation.delete')
|
|
283
|
+
if (name === 'conversations/delete')
|
|
245
284
|
scripted.delete(named);
|
|
246
|
-
return { kind: 'action', result: {
|
|
285
|
+
return { kind: 'action', result: { conversation_id: named } };
|
|
247
286
|
}
|
|
248
287
|
function announceList() {
|
|
249
|
-
const entries = [...scripted.values()].flatMap(({ conversation, listed }) => listed === undefined
|
|
250
|
-
|
|
251
|
-
|
|
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
|
+
}
|
|
252
294
|
}
|
|
253
295
|
function discovery() {
|
|
254
296
|
return {
|
|
@@ -260,8 +302,41 @@ export function createMemoryAdapter(options = {}) {
|
|
|
260
302
|
...(options.member === undefined ? {} : { member: options.member }),
|
|
261
303
|
};
|
|
262
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
|
+
}
|
|
263
338
|
return {
|
|
264
|
-
...(options.
|
|
339
|
+
...(options.roomTypes === undefined ? {} : { roomTypes: options.roomTypes }),
|
|
265
340
|
setRooms(next) {
|
|
266
341
|
rooms = [...next];
|
|
267
342
|
retain(rooms);
|
|
@@ -270,26 +345,37 @@ export function createMemoryAdapter(options = {}) {
|
|
|
270
345
|
scriptConversations(next);
|
|
271
346
|
},
|
|
272
347
|
open() {
|
|
348
|
+
carried.clear();
|
|
273
349
|
announceList();
|
|
274
|
-
|
|
275
|
-
observer({ kind: 'opened' });
|
|
350
|
+
opened(emitAll);
|
|
276
351
|
},
|
|
277
|
-
close(revoked = false) {
|
|
278
|
-
|
|
279
|
-
|
|
352
|
+
close({ revoked = false, lost = !revoked, authorityChanged = false } = {}) {
|
|
353
|
+
openings += 1;
|
|
354
|
+
carried.clear();
|
|
355
|
+
emitAll({ kind: 'closed', revoked, lost, authorityChanged });
|
|
280
356
|
},
|
|
281
357
|
expire(locators) {
|
|
282
358
|
expiring = [...locators];
|
|
283
359
|
},
|
|
284
|
-
notifyRoomVersion({ locator
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
});
|
|
287
377
|
},
|
|
288
378
|
notifyConversation(event) {
|
|
289
|
-
if (event.kind === 'accepted-message') {
|
|
290
|
-
sealed.add(event.message.turn);
|
|
291
|
-
unsealed.delete(event.message.turn);
|
|
292
|
-
}
|
|
293
379
|
for (const listener of listeners)
|
|
294
380
|
listener(event);
|
|
295
381
|
},
|
|
@@ -298,24 +384,31 @@ export function createMemoryAdapter(options = {}) {
|
|
|
298
384
|
observer(mode);
|
|
299
385
|
},
|
|
300
386
|
heldRooms() {
|
|
301
|
-
return
|
|
302
|
-
},
|
|
303
|
-
heldDemand() {
|
|
304
|
-
return heldDemand;
|
|
387
|
+
return [...carried.keys()].sort();
|
|
305
388
|
},
|
|
306
389
|
replicatedConversations() {
|
|
307
390
|
return replicated;
|
|
308
391
|
},
|
|
392
|
+
heldConversationCursor() {
|
|
393
|
+
return heldCursor;
|
|
394
|
+
},
|
|
309
395
|
conversations: {
|
|
310
396
|
replicate(next) {
|
|
311
397
|
replicated = [...next];
|
|
312
398
|
},
|
|
399
|
+
hold(cursor) {
|
|
400
|
+
heldCursor = cursor;
|
|
401
|
+
},
|
|
313
402
|
observe(notify) {
|
|
314
403
|
listeners.add(notify);
|
|
315
404
|
return () => {
|
|
316
405
|
listeners.delete(notify);
|
|
317
406
|
};
|
|
318
407
|
},
|
|
408
|
+
history: (request) => Promise.resolve(historiesOf(request)),
|
|
409
|
+
...(options.agents === undefined
|
|
410
|
+
? {}
|
|
411
|
+
: { agents: () => Promise.resolve(structuredClone(options.agents)) }),
|
|
319
412
|
},
|
|
320
413
|
serviceMode: {
|
|
321
414
|
observe(notify) {
|
|
@@ -326,45 +419,46 @@ export function createMemoryAdapter(options = {}) {
|
|
|
326
419
|
},
|
|
327
420
|
},
|
|
328
421
|
roomStream: {
|
|
329
|
-
hold(asked
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const expired = expiring.filter((locator) => held.includes(locator));
|
|
333
|
-
expiring = [];
|
|
334
|
-
const moved = asked.flatMap((room) => {
|
|
422
|
+
hold(asked) {
|
|
423
|
+
const named = asked.map((room) => room.locator);
|
|
424
|
+
const unknown = asked.flatMap((room) => {
|
|
335
425
|
const current = rooms.find((entry) => entry.locator === room.locator);
|
|
336
426
|
return current === undefined ||
|
|
337
|
-
|
|
338
|
-
|
|
427
|
+
current.roomVersion === room.roomVersion ||
|
|
428
|
+
served.get(room.locator)?.has(room.roomVersion) === true
|
|
339
429
|
? []
|
|
340
|
-
: [
|
|
430
|
+
: [room.locator];
|
|
341
431
|
});
|
|
432
|
+
const expired = [
|
|
433
|
+
...new Set([...expiring.filter((locator) => named.includes(locator)), ...unknown]),
|
|
434
|
+
];
|
|
435
|
+
expiring = expiring.filter((locator) => !named.includes(locator));
|
|
342
436
|
queueMicrotask(() => {
|
|
343
|
-
for (const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
+
}
|
|
347
444
|
}
|
|
445
|
+
emitAll({ kind: 'caught-up', expired });
|
|
348
446
|
});
|
|
349
447
|
},
|
|
350
|
-
reopen() {
|
|
351
|
-
queueMicrotask(() => {
|
|
352
|
-
for (const observer of observers)
|
|
353
|
-
observer({ kind: 'closed', revoked: false });
|
|
354
|
-
});
|
|
355
|
-
},
|
|
356
|
-
published() { },
|
|
357
448
|
observe(notify) {
|
|
358
449
|
observers.add(notify);
|
|
359
450
|
queueMicrotask(() => {
|
|
360
451
|
if (!observers.has(notify))
|
|
361
452
|
return;
|
|
362
453
|
if (options.unopened === true) {
|
|
363
|
-
notify({ kind: 'closed', revoked: false });
|
|
454
|
+
notify({ kind: 'closed', revoked: false, lost: true, authorityChanged: false });
|
|
364
455
|
return;
|
|
365
456
|
}
|
|
366
457
|
announceList();
|
|
367
|
-
|
|
458
|
+
opened((event) => {
|
|
459
|
+
if (observers.has(notify))
|
|
460
|
+
notify(event);
|
|
461
|
+
});
|
|
368
462
|
});
|
|
369
463
|
return () => {
|
|
370
464
|
observers.delete(notify);
|
|
@@ -381,12 +475,7 @@ export function createMemoryAdapter(options = {}) {
|
|
|
381
475
|
return resolveScript(scripts.authorize, () => ({}), undefined);
|
|
382
476
|
},
|
|
383
477
|
async discover(_authorization) {
|
|
384
|
-
return
|
|
385
|
-
if (answer.kind === 'discovery')
|
|
386
|
-
for (const room of answer.rooms)
|
|
387
|
-
note(room.locator, room);
|
|
388
|
-
return answer;
|
|
389
|
-
});
|
|
478
|
+
return discovered();
|
|
390
479
|
},
|
|
391
480
|
reached,
|
|
392
481
|
follows(locator, roomVersion, next) {
|
|
@@ -443,7 +532,13 @@ export function createMemoryAdapter(options = {}) {
|
|
|
443
532
|
retryable: false,
|
|
444
533
|
affected: {},
|
|
445
534
|
};
|
|
446
|
-
}, 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
|
+
});
|
|
447
542
|
},
|
|
448
543
|
async history(_authorization, request) {
|
|
449
544
|
return resolveScript(scripts.history, () => {
|
|
@@ -459,31 +554,42 @@ export function createMemoryAdapter(options = {}) {
|
|
|
459
554
|
},
|
|
460
555
|
async binary(_authorization, request) {
|
|
461
556
|
return resolveScript(scripts.binary, () => {
|
|
462
|
-
if (request.kind === 'reference') {
|
|
463
|
-
return { kind: 'rejected', code: 'unscripted-binary', fields: {}, retryable: false };
|
|
464
|
-
}
|
|
465
557
|
const room = rooms.find((entry) => entry.locator === request.locator);
|
|
466
558
|
if (room === undefined)
|
|
467
559
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
468
|
-
const blob = room
|
|
560
|
+
const blob = heldBlob(room, request.path);
|
|
469
561
|
return blob === undefined
|
|
470
562
|
? { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false }
|
|
471
|
-
: { kind: 'binary', blob };
|
|
563
|
+
: { kind: 'binary', body: blob.stream(), mediaType: blob.type };
|
|
472
564
|
}, request);
|
|
473
565
|
},
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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);
|
|
483
589
|
},
|
|
484
590
|
async action(_authorization, request) {
|
|
485
591
|
return resolveScript(scripts.action, () => {
|
|
486
|
-
if (request.name.startsWith('
|
|
592
|
+
if (request.name.startsWith('conversations/'))
|
|
487
593
|
return conversationAction(request);
|
|
488
594
|
return { kind: 'rejected', code: 'unscripted-action', fields: {}, retryable: false };
|
|
489
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,6 +28,11 @@ export type ModelState = {
|
|
|
28
28
|
verifiedWith: ModelIdentity;
|
|
29
29
|
types: VerifiedModel['types'];
|
|
30
30
|
};
|
|
31
|
+
export type StoredModel = Extract<ModelState, {
|
|
32
|
+
status: 'unavailable';
|
|
33
|
+
}> | Omit<Extract<ModelState, {
|
|
34
|
+
status: 'current' | 'cached';
|
|
35
|
+
}>, 'types'>;
|
|
31
36
|
export type TypesResult = {
|
|
32
37
|
status: Open<'unavailable'>;
|
|
33
38
|
reason: ModelUnavailableReason;
|
|
@@ -51,8 +56,8 @@ export type ValidationReceipt = {
|
|
|
51
56
|
export declare const NO_MODEL: ModelState;
|
|
52
57
|
export declare function definitionOf(state: ModelState, type: string | undefined): Definition | undefined;
|
|
53
58
|
export declare function modelTypes(state: ModelState): TypesResult;
|
|
59
|
+
export declare function storedModel(state: ModelState): StoredModel;
|
|
54
60
|
export declare function cached(state: ModelState): ModelState;
|
|
55
61
|
export declare function sameModel(left: ModelIdentity, right: ModelIdentity): boolean;
|
|
56
|
-
export declare function sameTyping(left: ModelState, right: ModelState): boolean;
|
|
57
62
|
export declare function referenceField(facts: ValueFacts | undefined): boolean;
|
|
58
63
|
//# sourceMappingURL=model.d.ts.map
|