@agentshouse/mdruntime 0.1.0-ca6edc1abd618 → 0.1.0-ca8707258fdde
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 +2 -2
- package/dist/acceptance.d.ts +26 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +384 -0
- package/dist/adapter.d.ts +102 -70
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +3 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +29 -47
- package/dist/bootstrap.d.ts +16 -14
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +272 -129
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/change.d.ts +1 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/chat-types.d.ts +3 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +2 -0
- package/dist/client.d.ts +20 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +55 -6
- package/dist/collection.d.ts +7 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +23 -17
- package/dist/compile.d.ts +6 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +278 -282
- package/dist/connection.d.ts +22 -44
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1600 -3577
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- package/dist/conversation-row.d.ts +33 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +47 -0
- package/dist/conversation.d.ts +27 -18
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +484 -258
- package/dist/durability.d.ts +6 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +3 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +18 -8
- package/dist/figures.d.ts +48 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +197 -0
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/host.d.ts +3 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +29 -32
- 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 +20 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/install.d.ts +86 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +537 -0
- package/dist/job.d.ts +33 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +54 -0
- package/dist/live.d.ts +5 -4
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +62 -20
- package/dist/log.d.ts +1 -0
- package/dist/log.d.ts.map +1 -1
- 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 +12 -5
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +216 -85
- package/dist/messages.d.ts +27 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +97 -19
- package/dist/model.d.ts +8 -10
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +5 -17
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +8 -3
- package/dist/outcome.d.ts +14 -5
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +19 -2
- package/dist/overlay.d.ts +1 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +11 -0
- package/dist/parts.d.ts +59 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +118 -0
- 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 +18 -207
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- package/dist/questions.d.ts +32 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +118 -0
- package/dist/reach.d.ts +18 -11
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +206 -126
- package/dist/react.d.ts +5 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/read.d.ts +7 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +17 -0
- package/dist/readiness.d.ts +3 -17
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +4 -10
- package/dist/reads.d.ts +34 -10
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +114 -86
- package/dist/recovery.d.ts +1 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +35 -1
- package/dist/refresh.d.ts +7 -5
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +33 -5
- package/dist/replica.d.ts +10 -11
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +52 -20
- package/dist/room-draft.d.ts +21 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +98 -51
- package/dist/room-drafts.d.ts +29 -0
- package/dist/room-drafts.d.ts.map +1 -0
- package/dist/room-drafts.js +216 -0
- package/dist/rows.d.ts +18 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +45 -153
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +22 -13
- package/dist/saves.d.ts +96 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +999 -0
- package/dist/search.d.ts +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- package/dist/seed.d.ts +16 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +66 -0
- package/dist/shared.d.ts +0 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +0 -10
- package/dist/socket/admission.d.ts +7 -0
- package/dist/socket/admission.d.ts.map +1 -0
- package/dist/socket/admission.js +39 -0
- package/dist/socket/answers.d.ts +6 -0
- package/dist/socket/answers.d.ts.map +1 -0
- package/dist/socket/answers.js +20 -0
- package/dist/socket/reads.d.ts +10 -0
- package/dist/socket/reads.d.ts.map +1 -0
- package/dist/socket/reads.js +31 -0
- package/dist/socket.d.ts +43 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +96 -0
- package/dist/source.d.ts +61 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +81 -0
- package/dist/status.d.ts +4 -5
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -7
- package/dist/store/fences.d.ts +16 -0
- package/dist/store/fences.d.ts.map +1 -0
- package/dist/store/fences.js +26 -0
- package/dist/store/installs.d.ts +30 -0
- package/dist/store/installs.d.ts.map +1 -0
- package/dist/store/installs.js +34 -0
- package/dist/store/records.d.ts +212 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +408 -0
- package/dist/store/room-held.d.ts +8 -0
- package/dist/store/room-held.d.ts.map +1 -0
- package/dist/store/room-held.js +17 -0
- package/dist/store/watchers.d.ts +15 -0
- package/dist/store/watchers.d.ts.map +1 -0
- package/dist/store/watchers.js +36 -0
- package/dist/store/writes.d.ts +24 -0
- package/dist/store/writes.d.ts.map +1 -0
- package/dist/store/writes.js +125 -0
- package/dist/store.d.ts +76 -158
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +117 -403
- package/dist/stored.d.ts +66 -55
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +343 -273
- package/dist/tables.d.ts +118 -65
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +199 -99
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +129 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/validation.d.ts +3 -4
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +42 -100
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +23 -8
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +8 -2
- package/package.json +2 -2
- package/dist/fence.d.ts +0 -6
- package/dist/fence.d.ts.map +0 -1
- package/dist/fence.js +0 -10
- package/dist/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -368
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -150
package/dist/tables.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import { sql } from '@agentshouse/mdmodel';
|
|
1
2
|
import { answerQuery } from './compile.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { conversationRows, droppedMessages, forgottenMessages, heldConversations, jobMarkers, keptMessages, messageCount, messageWindow, MESSAGE_TABLES, turnArrived, } from './messages.js';
|
|
4
|
+
import { keptRead, READ_TABLES, readsOfOtherBuildsForgotten, storedRead, } from './reads.js';
|
|
5
|
+
import { conversationTallies, roomTallies, } from './tallies.js';
|
|
6
|
+
import { abandon, release, commit, covering, demoted, ended, entries, erase, facts, fenceRooms, folders, heldLocators, heldRoom, heldRooms, offlineMode, opened, overlaid, presentation, rederive, referrers, refreshing, REPLICA_TABLES, resume, stage, typed, stagedLocators, typedWithin, unrefresh, } from './stored.js';
|
|
5
7
|
const STATEMENTS_HELD = 256;
|
|
6
8
|
export function sqliteConnection(engine, database) {
|
|
7
9
|
const decoder = new TextDecoder();
|
|
8
10
|
const held = new Map();
|
|
11
|
+
database.createFunction(sql.HOLDS_PHRASE, sql.holdsPhrase, {
|
|
12
|
+
arity: 2,
|
|
13
|
+
deterministic: true,
|
|
14
|
+
});
|
|
9
15
|
function prepared(sql) {
|
|
10
16
|
if (sql.includes(';'))
|
|
11
17
|
return null;
|
|
@@ -72,7 +78,7 @@ const TABLES = [
|
|
|
72
78
|
['authored_queues', 'locator TEXT PRIMARY KEY, ids TEXT NOT NULL'],
|
|
73
79
|
[
|
|
74
80
|
'authored_pending',
|
|
75
|
-
'locator TEXT NOT NULL, id TEXT NOT NULL, batch TEXT NOT NULL, state TEXT NOT NULL, files TEXT NOT NULL, PRIMARY KEY (locator, id)',
|
|
81
|
+
'locator TEXT NOT NULL, id TEXT NOT NULL, batch TEXT NOT NULL, state TEXT NOT NULL, files TEXT NOT NULL, paths TEXT NOT NULL, moving INTEGER NOT NULL, PRIMARY KEY (locator, id)',
|
|
76
82
|
],
|
|
77
83
|
[
|
|
78
84
|
'authored_room_drafts',
|
|
@@ -89,38 +95,51 @@ export const RUNTIME_TABLES = [
|
|
|
89
95
|
'CREATE INDEX opened_files_name ON opened_files (locator, path, revision)',
|
|
90
96
|
...REPLICA_TABLES,
|
|
91
97
|
...MESSAGE_TABLES,
|
|
92
|
-
...
|
|
98
|
+
...READ_TABLES,
|
|
93
99
|
];
|
|
94
100
|
const OWNERS = ['authored_pending', 'authored_room_drafts', 'authored_calls'];
|
|
95
101
|
const AUTHORED_KEYS = OWNERS.map((table) => `SELECT value FROM ${table}, json_each(${table}.files)`).join(' UNION ');
|
|
96
102
|
const UNOWNED_PARTS = `DELETE FROM file_parts WHERE key NOT IN (${AUTHORED_KEYS} UNION SELECT key FROM opened_files)`;
|
|
97
103
|
const READS = new Set([
|
|
98
|
-
'authored.
|
|
104
|
+
'authored.status',
|
|
105
|
+
'authored.moving',
|
|
106
|
+
'authored.pending',
|
|
107
|
+
'authored.batch',
|
|
108
|
+
'authored.order',
|
|
109
|
+
'authored.queued',
|
|
99
110
|
'authored.roomDrafts',
|
|
111
|
+
'authored.chatDraft.read',
|
|
100
112
|
'authored.chatDrafts',
|
|
101
113
|
'authored.calls',
|
|
102
114
|
'authored.fences',
|
|
115
|
+
'authored.unsent',
|
|
103
116
|
'authored.fact',
|
|
104
117
|
'authored.file',
|
|
105
118
|
'replica.open',
|
|
119
|
+
'replica.rooms',
|
|
120
|
+
'replica.room',
|
|
121
|
+
'replica.covering',
|
|
122
|
+
'replica.offline',
|
|
123
|
+
'replica.held',
|
|
124
|
+
'replica.facts',
|
|
125
|
+
'replica.presentation',
|
|
106
126
|
'replica.query',
|
|
127
|
+
'replica.tallies',
|
|
107
128
|
'replica.entries',
|
|
108
129
|
'replica.typed',
|
|
109
130
|
'replica.referrers',
|
|
110
|
-
'replica.
|
|
111
|
-
'replica.files',
|
|
131
|
+
'replica.folders',
|
|
112
132
|
'replica.typedWithin',
|
|
113
|
-
'replica.counts',
|
|
114
|
-
'replica.search',
|
|
115
|
-
'replica.received',
|
|
116
|
-
'replica.receivedParts',
|
|
117
|
-
'replica.transferPart',
|
|
118
133
|
'opened.find',
|
|
119
134
|
'file.part',
|
|
120
135
|
'conversation.held',
|
|
121
136
|
'conversation.window',
|
|
122
137
|
'conversation.count',
|
|
123
138
|
'conversation.turn',
|
|
139
|
+
'conversation.rows',
|
|
140
|
+
'conversation.jobs',
|
|
141
|
+
'conversation.tallies',
|
|
142
|
+
'read.stored',
|
|
124
143
|
]);
|
|
125
144
|
const KINDS = new Set([
|
|
126
145
|
...READS,
|
|
@@ -132,19 +151,19 @@ const KINDS = new Set([
|
|
|
132
151
|
'authored.claim',
|
|
133
152
|
'authored.end',
|
|
134
153
|
'replica.stage',
|
|
135
|
-
'replica.
|
|
154
|
+
'replica.resume',
|
|
136
155
|
'replica.refresh',
|
|
137
156
|
'replica.unrefresh',
|
|
138
157
|
'replica.commit',
|
|
139
158
|
'replica.fence',
|
|
140
159
|
'replica.erase',
|
|
141
160
|
'replica.abandon',
|
|
161
|
+
'replica.unfence',
|
|
142
162
|
'replica.release',
|
|
143
163
|
'replica.rederive',
|
|
164
|
+
'replica.demote',
|
|
144
165
|
'replica.fact',
|
|
145
166
|
'replica.present',
|
|
146
|
-
'replica.receive',
|
|
147
|
-
'replica.unreceive',
|
|
148
167
|
'opened.begin',
|
|
149
168
|
'opened.part',
|
|
150
169
|
'opened.keep',
|
|
@@ -153,6 +172,8 @@ const KINDS = new Set([
|
|
|
153
172
|
'conversation.keep',
|
|
154
173
|
'conversation.drop',
|
|
155
174
|
'space.probe',
|
|
175
|
+
'read.keep',
|
|
176
|
+
'read.builds',
|
|
156
177
|
]);
|
|
157
178
|
export function isRuntime(request) {
|
|
158
179
|
return KINDS.has(request.kind);
|
|
@@ -225,29 +246,71 @@ function unowned(connection) {
|
|
|
225
246
|
connection.run(UNOWNED_PARTS);
|
|
226
247
|
}
|
|
227
248
|
function queued(connection) {
|
|
249
|
+
return connection.rows('SELECT locator, ids FROM authored_queues').map((row) => ({
|
|
250
|
+
locator: text(row.locator),
|
|
251
|
+
ids: JSON.parse(text(row.ids)),
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
function heldWork(connection, locator) {
|
|
255
|
+
const room = heldRoom(connection, locator);
|
|
256
|
+
const pending = new Map(connection
|
|
257
|
+
.rows('SELECT id, batch, state FROM authored_pending WHERE locator = ?', [locator])
|
|
258
|
+
.map((row) => [
|
|
259
|
+
text(row.id),
|
|
260
|
+
{ id: text(row.id), batch: text(row.batch), state: text(row.state) },
|
|
261
|
+
]));
|
|
228
262
|
return {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
263
|
+
room: room === null ? null : { ...room, overlaid: overlaid(connection, room.key) },
|
|
264
|
+
queue: heldOrder(connection, locator).map((id) => {
|
|
265
|
+
const held = pending.get(id);
|
|
266
|
+
if (held === undefined)
|
|
267
|
+
throw new Error(`Missing Pending Change ${locator}/${id}`);
|
|
268
|
+
return held;
|
|
269
|
+
}),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function status(connection) {
|
|
273
|
+
const [completed] = connection.rows("SELECT value FROM replica_facts WHERE name = 'lastCompleted'");
|
|
274
|
+
return {
|
|
275
|
+
queued: texts(connection.rows('SELECT locator FROM authored_queues'), 'locator'),
|
|
276
|
+
lastCompleted: completed === undefined ? null : text(completed.value),
|
|
277
|
+
changes: connection
|
|
278
|
+
.rows('SELECT p.locator, c.value AS path FROM authored_pending p, json_each(p.paths) c')
|
|
279
|
+
.map((row) => ({ locator: text(row.locator), path: text(row.path) })),
|
|
280
|
+
resets: connection
|
|
281
|
+
.rows(`SELECT locator, json_extract(state, '$.submission.reset') AS reset FROM authored_pending
|
|
282
|
+
WHERE json_extract(state, '$.submission.state') = 'reset'`)
|
|
283
|
+
.map((row) => ({ locator: text(row.locator), reset: text(row.reset) })),
|
|
284
|
+
returned: texts(connection.rows(`SELECT record FROM authored_room_drafts WHERE json_type(record, '$.returned') = 'object'`), 'record'),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function pendingOf(connection, locator, id) {
|
|
288
|
+
const [held] = connection.rows('SELECT state FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
289
|
+
return {
|
|
290
|
+
state: held === undefined ? null : text(held.state),
|
|
291
|
+
room: connection.rows('SELECT 1 FROM replica_rooms WHERE locator = ?', [locator]).length > 0,
|
|
241
292
|
};
|
|
242
293
|
}
|
|
294
|
+
function roomDraftRecords(connection, locator, paths) {
|
|
295
|
+
if (locator === null) {
|
|
296
|
+
return texts(connection.rows('SELECT record FROM authored_room_drafts'), 'record');
|
|
297
|
+
}
|
|
298
|
+
if (paths === null) {
|
|
299
|
+
return texts(connection.rows('SELECT record FROM authored_room_drafts WHERE locator = ?', [locator]), 'record');
|
|
300
|
+
}
|
|
301
|
+
return texts(connection.rows('SELECT record FROM authored_room_drafts WHERE locator = ? AND path IN (SELECT value FROM json_each(?))', [locator, JSON.stringify(paths)]), 'record');
|
|
302
|
+
}
|
|
303
|
+
function chatDraftRecord(connection, conversation) {
|
|
304
|
+
const [held] = connection.rows('SELECT record FROM authored_chat_drafts WHERE conversation = ?', [
|
|
305
|
+
conversation,
|
|
306
|
+
]);
|
|
307
|
+
return held === undefined ? null : text(held.record);
|
|
308
|
+
}
|
|
243
309
|
function heldOrder(connection, locator) {
|
|
244
310
|
const [held] = connection.rows('SELECT ids FROM authored_queues WHERE locator = ?', [locator]);
|
|
245
311
|
return held === undefined ? [] : JSON.parse(text(held.ids));
|
|
246
312
|
}
|
|
247
|
-
function keptRows(connection, { locator, order, added, founded, roomDrafts, consumedRoomDrafts
|
|
248
|
-
for (const { id, amendment } of amendments ?? []) {
|
|
249
|
-
amended(connection, { kind: 'authored.amend', locator, id, amendment });
|
|
250
|
-
}
|
|
313
|
+
function keptRows(connection, { locator, order, added, founded, roomDrafts, consumedRoomDrafts }) {
|
|
251
314
|
for (const path of consumedRoomDrafts ?? []) {
|
|
252
315
|
connection.run('DELETE FROM authored_room_drafts WHERE locator = ? AND path = ?', [
|
|
253
316
|
locator,
|
|
@@ -274,19 +337,26 @@ function keptRows(connection, { locator, order, added, founded, roomDrafts, cons
|
|
|
274
337
|
connection.run('DELETE FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
275
338
|
}
|
|
276
339
|
}
|
|
277
|
-
for (const { id, batch, state, files } of added ?? []) {
|
|
340
|
+
for (const { id, batch, state, files, paths, moving } of added ?? []) {
|
|
278
341
|
if (before.has(id) || !after.has(id))
|
|
279
342
|
continue;
|
|
280
|
-
connection.run('INSERT OR REPLACE INTO authored_pending (locator, id, batch, state, files) VALUES (?, ?, ?, ?, ?)', [locator, id, batch, state, owned(files)]);
|
|
343
|
+
connection.run('INSERT OR REPLACE INTO authored_pending (locator, id, batch, state, files, paths, moving) VALUES (?, ?, ?, ?, ?, ?, ?)', [locator, id, batch, state, owned(files), JSON.stringify(paths), moving ? 1 : 0]);
|
|
281
344
|
}
|
|
282
|
-
for (const { id, batch, files } of founded ?? []) {
|
|
345
|
+
for (const { id, batch, files, paths, moving } of founded ?? []) {
|
|
283
346
|
const [held] = connection.rows('SELECT files FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
284
347
|
if (held === undefined || !before.has(id))
|
|
285
348
|
continue;
|
|
286
|
-
connection.run('UPDATE authored_pending SET batch = ?, files = ? WHERE locator = ? AND id = ?', [
|
|
349
|
+
connection.run('UPDATE authored_pending SET batch = ?, files = ?, paths = ?, moving = ? WHERE locator = ? AND id = ?', [
|
|
350
|
+
batch,
|
|
351
|
+
owned([...JSON.parse(text(held.files)), ...files]),
|
|
352
|
+
JSON.stringify(paths),
|
|
353
|
+
moving ? 1 : 0,
|
|
354
|
+
locator,
|
|
355
|
+
id,
|
|
356
|
+
]);
|
|
287
357
|
}
|
|
288
358
|
}
|
|
289
|
-
async function kept(connection, { writes, files, whole
|
|
359
|
+
async function kept(connection, { writes, files, whole }) {
|
|
290
360
|
const refused = writes.find(({ locator }) => fenced(connection, locator));
|
|
291
361
|
if (refused !== undefined && whole)
|
|
292
362
|
return refused.locator;
|
|
@@ -295,8 +365,6 @@ async function kept(connection, { writes, files, whole, discards }) {
|
|
|
295
365
|
if (!fenced(connection, write.locator))
|
|
296
366
|
keptRows(connection, write);
|
|
297
367
|
}
|
|
298
|
-
for (const locator of discards ?? [])
|
|
299
|
-
roomWork(connection, locator);
|
|
300
368
|
unowned(connection);
|
|
301
369
|
return refused?.locator ?? null;
|
|
302
370
|
}
|
|
@@ -366,11 +434,15 @@ function fence(connection, locators) {
|
|
|
366
434
|
return fenceRooms(connection, locators);
|
|
367
435
|
}
|
|
368
436
|
function erased(connection, { locator, limit }) {
|
|
369
|
-
|
|
370
|
-
|
|
437
|
+
return erase(connection, locator, limit);
|
|
438
|
+
}
|
|
439
|
+
function unfenced(connection, locators) {
|
|
440
|
+
const erased = locators.filter((locator) => connection.rows('SELECT 1 FROM replica_erasing WHERE locator = ? LIMIT 1', [locator])
|
|
441
|
+
.length === 0);
|
|
442
|
+
for (const locator of erased) {
|
|
371
443
|
connection.run('DELETE FROM authored_fences WHERE locator = ?', [locator]);
|
|
372
444
|
}
|
|
373
|
-
return
|
|
445
|
+
return erased;
|
|
374
446
|
}
|
|
375
447
|
function claim(connection, holder) {
|
|
376
448
|
const held = fact(connection, 'holder');
|
|
@@ -449,6 +521,16 @@ function keptOpened(connection, { key, sha256, byteLength, parts }) {
|
|
|
449
521
|
unowned(connection);
|
|
450
522
|
return true;
|
|
451
523
|
}
|
|
524
|
+
const UNSENT = [
|
|
525
|
+
['pending-change', 'authored_pending'],
|
|
526
|
+
['call', 'authored_calls'],
|
|
527
|
+
['room-draft', 'authored_room_drafts'],
|
|
528
|
+
['chat-draft', 'authored_chat_drafts'],
|
|
529
|
+
];
|
|
530
|
+
function unsent(connection) {
|
|
531
|
+
const [held] = connection.rows(`SELECT ${UNSENT.map(([kind, table]) => `(SELECT count(*) FROM ${table}) AS "${kind}"`).join(', ')}`);
|
|
532
|
+
return UNSENT.map(([kind]) => ({ kind, count: count(held?.[kind]) })).filter((work) => work.count > 0);
|
|
533
|
+
}
|
|
452
534
|
function cleaned(connection) {
|
|
453
535
|
connection.run('DELETE FROM opened_files');
|
|
454
536
|
const [freed] = connection.rows(`SELECT coalesce(sum(length(bytes)), 0) AS bytes FROM file_parts WHERE key NOT IN (${AUTHORED_KEYS})`);
|
|
@@ -458,47 +540,51 @@ function cleaned(connection) {
|
|
|
458
540
|
async function committed(connection, { authored, rooms }) {
|
|
459
541
|
const refused = authored === undefined ? null : await kept(connection, authored);
|
|
460
542
|
if (refused !== null && authored?.whole === true) {
|
|
461
|
-
return { fenced: refused,
|
|
543
|
+
return { fenced: refused, changed: {}, indexed: {} };
|
|
462
544
|
}
|
|
463
545
|
return {
|
|
464
546
|
fenced: refused,
|
|
465
547
|
...commit(connection, rooms.filter(({ locator }) => !fenced(connection, locator))),
|
|
466
548
|
};
|
|
467
549
|
}
|
|
468
|
-
function receivedParts(connection, key, count) {
|
|
469
|
-
return connection
|
|
470
|
-
.rows('SELECT value FROM replica_received_parts WHERE key = ? AND part < ? ORDER BY part', [
|
|
471
|
-
key,
|
|
472
|
-
count,
|
|
473
|
-
])
|
|
474
|
-
.map((row) => JSON.parse(text(row.value)));
|
|
475
|
-
}
|
|
476
|
-
function receive(connection, { key, head, part }) {
|
|
477
|
-
connection.run('INSERT OR REPLACE INTO replica_received (key, head) VALUES (?, ?)', [key, head]);
|
|
478
|
-
if (part !== undefined) {
|
|
479
|
-
connection.run('INSERT OR REPLACE INTO replica_received_parts (key, part, value) VALUES (?, ?, ?)', [key, part.index, part.value]);
|
|
480
|
-
}
|
|
481
|
-
return null;
|
|
482
|
-
}
|
|
483
|
-
function unreceive(connection, keys) {
|
|
484
|
-
for (const key of keys) {
|
|
485
|
-
connection.run('DELETE FROM replica_received WHERE key = ?', [key]);
|
|
486
|
-
connection.run('DELETE FROM replica_received_parts WHERE key = ?', [key]);
|
|
487
|
-
}
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
550
|
export function answerRuntime(connection, request, spool) {
|
|
491
551
|
switch (request.kind) {
|
|
492
|
-
case 'authored.
|
|
493
|
-
return
|
|
552
|
+
case 'authored.status':
|
|
553
|
+
return status(connection);
|
|
554
|
+
case 'authored.moving':
|
|
555
|
+
return {
|
|
556
|
+
queues: queued(connection),
|
|
557
|
+
pending: connection
|
|
558
|
+
.rows('SELECT locator, id, batch, state FROM authored_pending WHERE moving = 1 ORDER BY locator')
|
|
559
|
+
.map((row) => ({
|
|
560
|
+
locator: text(row.locator),
|
|
561
|
+
id: text(row.id),
|
|
562
|
+
batch: text(row.batch),
|
|
563
|
+
state: text(row.state),
|
|
564
|
+
})),
|
|
565
|
+
};
|
|
566
|
+
case 'authored.pending':
|
|
567
|
+
return pendingOf(connection, request.locator, request.id);
|
|
568
|
+
case 'authored.batch': {
|
|
569
|
+
const [held] = connection.rows('SELECT batch FROM authored_pending WHERE locator = ? AND id = ?', [request.locator, request.id]);
|
|
570
|
+
return held === undefined ? null : text(held.batch);
|
|
571
|
+
}
|
|
572
|
+
case 'authored.order':
|
|
573
|
+
return heldOrder(connection, request.locator);
|
|
574
|
+
case 'authored.queued':
|
|
575
|
+
return texts(connection.rows('SELECT locator FROM authored_queues'), 'locator');
|
|
494
576
|
case 'authored.roomDrafts':
|
|
495
|
-
return
|
|
577
|
+
return roomDraftRecords(connection, request.locator, request.paths);
|
|
578
|
+
case 'authored.chatDraft.read':
|
|
579
|
+
return chatDraftRecord(connection, request.conversation);
|
|
496
580
|
case 'authored.chatDrafts':
|
|
497
581
|
return texts(connection.rows('SELECT record FROM authored_chat_drafts'), 'record');
|
|
498
582
|
case 'authored.calls':
|
|
499
583
|
return texts(connection.rows('SELECT record FROM authored_calls'), 'record');
|
|
500
584
|
case 'authored.fences':
|
|
501
585
|
return texts(connection.rows('SELECT locator FROM authored_fences'), 'locator');
|
|
586
|
+
case 'authored.unsent':
|
|
587
|
+
return unsent(connection);
|
|
502
588
|
case 'authored.fact':
|
|
503
589
|
return fact(connection, request.name);
|
|
504
590
|
case 'authored.file':
|
|
@@ -519,39 +605,43 @@ export function answerRuntime(connection, request, spool) {
|
|
|
519
605
|
return end(connection, request.holder);
|
|
520
606
|
case 'replica.open':
|
|
521
607
|
return opened(connection);
|
|
608
|
+
case 'replica.rooms':
|
|
609
|
+
return heldRooms(connection, request.locators);
|
|
610
|
+
case 'replica.room':
|
|
611
|
+
return heldWork(connection, request.locator);
|
|
612
|
+
case 'replica.covering':
|
|
613
|
+
return {
|
|
614
|
+
rooms: covering(connection),
|
|
615
|
+
queues: queued(connection),
|
|
616
|
+
};
|
|
617
|
+
case 'replica.offline':
|
|
618
|
+
return offlineMode(connection, request.locator);
|
|
619
|
+
case 'replica.held':
|
|
620
|
+
return { held: heldLocators(connection), staged: stagedLocators(connection) };
|
|
621
|
+
case 'replica.demote':
|
|
622
|
+
return demoted(connection);
|
|
623
|
+
case 'replica.facts':
|
|
624
|
+
return facts(connection);
|
|
625
|
+
case 'replica.presentation':
|
|
626
|
+
return presentation(connection, request.app);
|
|
522
627
|
case 'replica.query':
|
|
523
628
|
return answerQuery(connection, request.plan, request.rooms, request.budget);
|
|
629
|
+
case 'replica.tallies':
|
|
630
|
+
return roomTallies(connection, request.totals, request.rooms, request.since);
|
|
524
631
|
case 'replica.entries':
|
|
525
632
|
return entries(connection, request.key, request.view, request.paths);
|
|
526
633
|
case 'replica.typed':
|
|
527
634
|
return typed(connection, request.key, request.view, request.paths);
|
|
528
635
|
case 'replica.referrers':
|
|
529
|
-
return referrers(connection, request.key, request.view, request.targets
|
|
530
|
-
case 'replica.
|
|
531
|
-
return
|
|
532
|
-
case 'replica.files':
|
|
533
|
-
return files(connection, request.key, request.view, request.after, request.limit);
|
|
636
|
+
return referrers(connection, request.key, request.view, request.targets);
|
|
637
|
+
case 'replica.folders':
|
|
638
|
+
return folders(connection, request.key, request.view, request.paths);
|
|
534
639
|
case 'replica.typedWithin':
|
|
535
640
|
return typedWithin(connection, request.key, request.view, request.roots, request.within);
|
|
536
|
-
case 'replica.counts':
|
|
537
|
-
return counts(connection, request.rooms);
|
|
538
|
-
case 'replica.search': {
|
|
539
|
-
const { kind: _kind, ...ask } = request;
|
|
540
|
-
return searched(connection, ask);
|
|
541
|
-
}
|
|
542
|
-
case 'replica.received':
|
|
543
|
-
return connection.rows('SELECT key, head FROM replica_received').map((row) => ({
|
|
544
|
-
key: text(row.key),
|
|
545
|
-
head: JSON.parse(text(row.head)),
|
|
546
|
-
}));
|
|
547
|
-
case 'replica.receivedParts':
|
|
548
|
-
return receivedParts(connection, request.key, request.count);
|
|
549
641
|
case 'replica.stage':
|
|
550
642
|
return fenced(connection, request.locator) ? null : stage(connection, request);
|
|
551
|
-
case 'replica.
|
|
552
|
-
return
|
|
553
|
-
case 'replica.keepPart':
|
|
554
|
-
return fenced(connection, request.locator) ? null : keepPart(connection, request);
|
|
643
|
+
case 'replica.resume':
|
|
644
|
+
return fenced(connection, request.locator) ? null : resume(connection, request);
|
|
555
645
|
case 'replica.refresh':
|
|
556
646
|
return refreshing(connection, request);
|
|
557
647
|
case 'replica.unrefresh':
|
|
@@ -563,11 +653,13 @@ export function answerRuntime(connection, request, spool) {
|
|
|
563
653
|
case 'replica.erase':
|
|
564
654
|
return erased(connection, request);
|
|
565
655
|
case 'replica.abandon':
|
|
566
|
-
return abandon(connection, request.locator
|
|
656
|
+
return abandon(connection, request.locator);
|
|
657
|
+
case 'replica.unfence':
|
|
658
|
+
return unfenced(connection, request.locators);
|
|
567
659
|
case 'replica.release':
|
|
568
660
|
return release(connection, request.key);
|
|
569
661
|
case 'replica.rederive':
|
|
570
|
-
return rederive(connection, request.key, request.
|
|
662
|
+
return rederive(connection, request.key, request.composed, request.bytes, request.ms, request.floor);
|
|
571
663
|
case 'replica.fact':
|
|
572
664
|
connection.run('INSERT OR REPLACE INTO replica_facts (name, value) VALUES (?, ?)', [
|
|
573
665
|
request.name,
|
|
@@ -580,10 +672,6 @@ export function answerRuntime(connection, request, spool) {
|
|
|
580
672
|
request.value,
|
|
581
673
|
]);
|
|
582
674
|
return null;
|
|
583
|
-
case 'replica.receive':
|
|
584
|
-
return receive(connection, request);
|
|
585
|
-
case 'replica.unreceive':
|
|
586
|
-
return unreceive(connection, request.keys);
|
|
587
675
|
case 'opened.find':
|
|
588
676
|
return openedFile(connection, request);
|
|
589
677
|
case 'opened.begin':
|
|
@@ -599,17 +687,23 @@ export function answerRuntime(connection, request, spool) {
|
|
|
599
687
|
case 'file.part':
|
|
600
688
|
return filePart(connection, request.key, request.part);
|
|
601
689
|
case 'conversation.held':
|
|
602
|
-
return heldConversations(connection);
|
|
690
|
+
return heldConversations(connection, request.conversations);
|
|
603
691
|
case 'conversation.keep': {
|
|
604
692
|
const { kind: _kind, ...write } = request;
|
|
605
693
|
return keptMessages(connection, write);
|
|
606
694
|
}
|
|
607
695
|
case 'conversation.window':
|
|
608
|
-
return messageWindow(connection, request.conversation, request.limit, request.before);
|
|
696
|
+
return messageWindow(connection, request.conversation, request.limit, request.before, request.phrase);
|
|
609
697
|
case 'conversation.count':
|
|
610
|
-
return messageCount(connection, request.conversation);
|
|
698
|
+
return messageCount(connection, request.conversation, request.phrase);
|
|
611
699
|
case 'conversation.turn':
|
|
612
700
|
return turnArrived(connection, request.conversation, request.turn);
|
|
701
|
+
case 'conversation.rows':
|
|
702
|
+
return conversationRows(connection, request.conversations);
|
|
703
|
+
case 'conversation.jobs':
|
|
704
|
+
return jobMarkers(connection, request.conversation);
|
|
705
|
+
case 'conversation.tallies':
|
|
706
|
+
return conversationTallies(connection, request.conversations, request.since);
|
|
613
707
|
case 'conversation.drop':
|
|
614
708
|
chatDraft(connection, {
|
|
615
709
|
kind: 'authored.chatDraft',
|
|
@@ -620,5 +714,11 @@ export function answerRuntime(connection, request, spool) {
|
|
|
620
714
|
return null;
|
|
621
715
|
case 'space.probe':
|
|
622
716
|
return spool.probe(PROBE_BYTES).then(() => null);
|
|
717
|
+
case 'read.stored':
|
|
718
|
+
return storedRead(connection, request);
|
|
719
|
+
case 'read.keep':
|
|
720
|
+
return keptRead(connection, request, request.answer);
|
|
721
|
+
case 'read.builds':
|
|
722
|
+
return readsOfOtherBuildsForgotten(connection, request.build);
|
|
623
723
|
}
|
|
624
724
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type QueryRoom } from './compile.js';
|
|
2
|
+
import type { GroupTotal, Plan } from './query.js';
|
|
3
|
+
import type { Connection } from './tables.js';
|
|
4
|
+
export type RoomTally = {
|
|
5
|
+
readonly key: number;
|
|
6
|
+
readonly documents: GroupTotal;
|
|
7
|
+
readonly files: GroupTotal;
|
|
8
|
+
readonly documentTimes: readonly (readonly [string | null, string | null])[];
|
|
9
|
+
readonly chatTimes: readonly string[];
|
|
10
|
+
readonly messageTimes: readonly string[];
|
|
11
|
+
};
|
|
12
|
+
export type ConversationTally = {
|
|
13
|
+
readonly conversation: string;
|
|
14
|
+
readonly said: readonly string[];
|
|
15
|
+
};
|
|
16
|
+
export declare function roomTallies(connection: Connection, totals: Plan, rooms: readonly QueryRoom[], since: string): RoomTally[];
|
|
17
|
+
export declare function conversationTallies(connection: Connection, conversations: readonly string[] | null, since: string): ConversationTally[];
|
|
18
|
+
//# sourceMappingURL=tallies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tallies.d.ts","sourceRoot":"","sources":["../src/tallies.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAI1D,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;IAC7E,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAmHpG,wBAAgB,WAAW,CACzB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,KAAK,EAAE,MAAM,GACZ,SAAS,EAAE,CAwBb;AA0BD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EACvC,KAAK,EAAE,MAAM,GACZ,iBAAiB,EAAE,CAerB"}
|
package/dist/tallies.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { instantKey, sql } from '@agentshouse/mdmodel';
|
|
2
|
+
import { CHAT_MESSAGE_TYPE, CHAT_TYPE } from './chat-types.js';
|
|
3
|
+
import { answerQuery, VISIBLE, within } from './compile.js';
|
|
4
|
+
import { HOUSE_DIRECTORY } from './figures.js';
|
|
5
|
+
const NONE = { count: 0, size: 0 };
|
|
6
|
+
const { all, fragment, joined } = sql;
|
|
7
|
+
function instant(value) {
|
|
8
|
+
return typeof value === 'string' ? value : null;
|
|
9
|
+
}
|
|
10
|
+
function held(alias, keys) {
|
|
11
|
+
const reserved = within(alias, HOUSE_DIRECTORY);
|
|
12
|
+
return all([
|
|
13
|
+
fragment(`${alias}.key IN (SELECT value FROM json_each(?))`, [JSON.stringify(keys)]),
|
|
14
|
+
fragment(VISIBLE(alias)),
|
|
15
|
+
fragment(`NOT ${reserved.sql}`, reserved.bind),
|
|
16
|
+
]);
|
|
17
|
+
}
|
|
18
|
+
function valued(alias, document, field) {
|
|
19
|
+
return joined([
|
|
20
|
+
fragment(`${alias}.doc = ${document}.id AND `),
|
|
21
|
+
sql.grouped(sql.placed(alias, field, 'exact')),
|
|
22
|
+
fragment(` AND ${alias}.item = -1`),
|
|
23
|
+
], '');
|
|
24
|
+
}
|
|
25
|
+
function inboxed(card) {
|
|
26
|
+
return joined([
|
|
27
|
+
fragment('EXISTS (SELECT 1 FROM replica_values i WHERE '),
|
|
28
|
+
valued('i', card, '/inbox'),
|
|
29
|
+
fragment(" AND i.kind = 'string')"),
|
|
30
|
+
], '');
|
|
31
|
+
}
|
|
32
|
+
function rowsOf(connection, query) {
|
|
33
|
+
return connection.rows(query.sql, query.bind);
|
|
34
|
+
}
|
|
35
|
+
function documentTimes(connection, keys, since) {
|
|
36
|
+
return rowsOf(connection, joined([
|
|
37
|
+
fragment('SELECT d.key AS key, d.created_instant AS created, d.changed_instant AS changed FROM replica_entries d WHERE '),
|
|
38
|
+
held('d', keys),
|
|
39
|
+
fragment(" AND d.binary IS NULL AND COALESCE(d.type, '') NOT IN (?, ?) AND (d.created_instant >= ? OR d.changed_instant >= ?)", [CHAT_TYPE, CHAT_MESSAGE_TYPE, since, since]),
|
|
40
|
+
], ''));
|
|
41
|
+
}
|
|
42
|
+
function chatTimes(connection, keys, since) {
|
|
43
|
+
return rowsOf(connection, joined([
|
|
44
|
+
fragment('SELECT d.key AS key, d.created_instant AS at FROM replica_entries d WHERE '),
|
|
45
|
+
held('d', keys),
|
|
46
|
+
fragment(' AND d.type = ? AND d.created_instant >= ? AND ', [CHAT_TYPE, since]),
|
|
47
|
+
inboxed('d'),
|
|
48
|
+
], ''));
|
|
49
|
+
}
|
|
50
|
+
function messageTimes(connection, keys, since) {
|
|
51
|
+
return rowsOf(connection, joined([
|
|
52
|
+
fragment('SELECT m.key AS key, s.instant AS at FROM replica_entries m JOIN replica_values s ON '),
|
|
53
|
+
valued('s', 'm', '/sent_at'),
|
|
54
|
+
fragment(' AND s.instant >= ? JOIN replica_values r ON ', [since]),
|
|
55
|
+
valued('r', 'm', '/direction'),
|
|
56
|
+
fragment(" AND r.kind = 'string' AND r.value = 'in' WHERE "),
|
|
57
|
+
held('m', keys),
|
|
58
|
+
fragment(` AND m.type = ? AND EXISTS (SELECT 1 FROM replica_entries c WHERE c.key = m.key AND c.type = ? AND ${VISIBLE('c')} AND c.folder = m.folder AND `, [CHAT_MESSAGE_TYPE, CHAT_TYPE]),
|
|
59
|
+
inboxed('c'),
|
|
60
|
+
fragment(')'),
|
|
61
|
+
], ''));
|
|
62
|
+
}
|
|
63
|
+
function byKey(rows, read) {
|
|
64
|
+
const kept = new Map();
|
|
65
|
+
for (const row of rows) {
|
|
66
|
+
const key = Number(row.key);
|
|
67
|
+
const list = kept.get(key) ?? [];
|
|
68
|
+
list.push(read(row));
|
|
69
|
+
kept.set(key, list);
|
|
70
|
+
}
|
|
71
|
+
return kept;
|
|
72
|
+
}
|
|
73
|
+
export function roomTallies(connection, totals, rooms, since) {
|
|
74
|
+
const keys = rooms.map(({ key }) => key);
|
|
75
|
+
const from = instantKey(since);
|
|
76
|
+
const answered = answerQuery(connection, totals, rooms);
|
|
77
|
+
const summed = new Map(('groups' in answered ? answered.groups : []).map((group) => [String(group.key[0]), group]));
|
|
78
|
+
const documents = byKey(documentTimes(connection, keys, from), (row) => [instant(row.created), instant(row.changed)]);
|
|
79
|
+
const chats = byKey(chatTimes(connection, keys, from), (row) => instant(row.at));
|
|
80
|
+
const messages = byKey(messageTimes(connection, keys, from), (row) => instant(row.at));
|
|
81
|
+
return rooms.map(({ locator, key }) => {
|
|
82
|
+
const total = summed.get(locator);
|
|
83
|
+
return {
|
|
84
|
+
key,
|
|
85
|
+
documents: total?.documents ?? NONE,
|
|
86
|
+
files: total?.files ?? NONE,
|
|
87
|
+
documentTimes: documents.get(key) ?? [],
|
|
88
|
+
chatTimes: chats.get(key) ?? [],
|
|
89
|
+
messageTimes: messages.get(key) ?? [],
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const ACCEPTED = "message ->> '$.accepted_at'";
|
|
94
|
+
const NEWER = 'ORDER BY n.position DESC, n.identity DESC LIMIT 1';
|
|
95
|
+
const SAID = `WITH RECURSIVE
|
|
96
|
+
named(conversation) AS (SELECT value FROM json_each(?)),
|
|
97
|
+
walk(id, conversation, position, identity, at) AS (
|
|
98
|
+
SELECT m.id, m.conversation, m.position, m.identity, m.${ACCEPTED}
|
|
99
|
+
FROM named JOIN conversation_messages m ON m.id = (
|
|
100
|
+
SELECT n.id FROM conversation_messages n WHERE n.conversation = named.conversation ${NEWER}
|
|
101
|
+
)
|
|
102
|
+
UNION ALL
|
|
103
|
+
SELECT m.id, m.conversation, m.position, m.identity, m.${ACCEPTED}
|
|
104
|
+
FROM walk JOIN conversation_messages m ON m.id = (
|
|
105
|
+
SELECT n.id FROM conversation_messages n WHERE n.conversation = walk.conversation
|
|
106
|
+
AND (n.position < walk.position OR (n.position = walk.position AND n.identity < walk.identity))
|
|
107
|
+
${NEWER}
|
|
108
|
+
)
|
|
109
|
+
WHERE julianday(walk.at) >= julianday(?)
|
|
110
|
+
)
|
|
111
|
+
SELECT walk.conversation AS conversation, walk.at AS at
|
|
112
|
+
FROM walk JOIN conversation_messages m ON m.id = walk.id
|
|
113
|
+
WHERE m.message ->> '$.role' IN ('user', 'assistant') AND julianday(walk.at) >= julianday(?)`;
|
|
114
|
+
export function conversationTallies(connection, conversations, since) {
|
|
115
|
+
const named = conversations ??
|
|
116
|
+
connection
|
|
117
|
+
.rows('SELECT DISTINCT conversation FROM conversation_messages')
|
|
118
|
+
.map((row) => String(row.conversation));
|
|
119
|
+
const from = instantKey(since);
|
|
120
|
+
const said = new Map();
|
|
121
|
+
for (const row of connection.rows(SAID, [JSON.stringify(named), since, since])) {
|
|
122
|
+
const at = instantKey(row.at);
|
|
123
|
+
if (at === null || at < from)
|
|
124
|
+
continue;
|
|
125
|
+
const conversation = String(row.conversation);
|
|
126
|
+
said.set(conversation, [...(said.get(conversation) ?? []), at]);
|
|
127
|
+
}
|
|
128
|
+
return named.map((conversation) => ({ conversation, said: said.get(conversation) ?? [] }));
|
|
129
|
+
}
|
package/dist/transfer.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import type { Refusal } from '@agentshouse/mdmodel';
|
|
2
1
|
export type Unconfirmed = {
|
|
3
2
|
kind: 'unconfirmed';
|
|
4
3
|
};
|
|
5
|
-
export type Refused = {
|
|
6
|
-
kind: 'refused';
|
|
7
|
-
refusal: Refusal;
|
|
8
|
-
};
|
|
9
4
|
export declare const unconfirmed: Unconfirmed;
|
|
10
5
|
//# sourceMappingURL=transfer.d.ts.map
|
package/dist/transfer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAElD,eAAO,MAAM,WAAW,EAAE,WAAqC,CAAC"}
|