@agentshouse/mdruntime 0.1.0-cf1e7fdb9c600 → 0.1.0-cf281e8224a5d
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 +9 -9
- package/dist/acceptance.d.ts +6 -0
- package/dist/acceptance.d.ts.map +1 -0
- package/dist/acceptance.js +385 -0
- package/dist/actions.d.ts +20 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +251 -0
- package/dist/adapter.d.ts +24 -25
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +3 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +21 -56
- package/dist/bootstrap.d.ts +8 -4
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +207 -76
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- package/dist/change.d.ts +1 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +4 -2
- package/dist/chat-types.d.ts +5 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +13 -0
- package/dist/client.d.ts +18 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -2
- package/dist/compile.d.ts +5 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +202 -80
- package/dist/connection.d.ts +5 -141
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +101 -5280
- package/dist/conversation-live.d.ts +136 -0
- package/dist/conversation-live.d.ts.map +1 -0
- package/dist/conversation-live.js +248 -0
- package/dist/conversation-row.d.ts +33 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +53 -0
- package/dist/conversation.d.ts +29 -35
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +838 -840
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +175 -0
- package/dist/durability.d.ts +15 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +4 -3
- package/dist/expectation.d.ts +4 -2
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +33 -11
- package/dist/figures.d.ts +49 -0
- package/dist/figures.d.ts.map +1 -0
- package/dist/figures.js +197 -0
- package/dist/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +11 -4
- 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 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/install.d.ts +56 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +554 -0
- package/dist/job.d.ts +20 -1
- package/dist/job.d.ts.map +1 -1
- package/dist/job.js +26 -0
- package/dist/lifecycle.d.ts +7 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +268 -0
- package/dist/listing.d.ts +53 -0
- package/dist/listing.d.ts.map +1 -0
- package/dist/listing.js +176 -0
- package/dist/live.d.ts +4 -4
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +52 -16
- package/dist/locks.d.ts +9 -0
- package/dist/locks.d.ts.map +1 -0
- package/dist/locks.js +61 -0
- package/dist/log.d.ts +1 -0
- package/dist/log.d.ts.map +1 -1
- package/dist/lost.d.ts +5 -0
- package/dist/lost.d.ts.map +1 -0
- package/dist/lost.js +61 -0
- package/dist/media.d.ts +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +3 -3
- package/dist/memory.d.ts +3 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +45 -6
- package/dist/messages.d.ts +25 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +89 -16
- package/dist/model.d.ts +1 -7
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -6
- package/dist/models.d.ts +14 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +195 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +12 -17
- package/dist/opened.js +3 -3
- package/dist/opening.d.ts +4 -0
- package/dist/opening.d.ts.map +1 -0
- package/dist/opening.js +57 -0
- package/dist/outcome.d.ts +4 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +3 -0
- 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 +60 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +126 -0
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +22 -0
- package/dist/preparation.d.ts +20 -0
- package/dist/preparation.d.ts.map +1 -0
- package/dist/preparation.js +226 -0
- package/dist/queries.d.ts +16 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +272 -0
- package/dist/query.d.ts +10 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/questions.d.ts +34 -0
- package/dist/questions.d.ts.map +1 -0
- package/dist/questions.js +122 -0
- package/dist/reach.d.ts +8 -6
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +159 -100
- package/dist/react.d.ts +11 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +10 -1
- package/dist/read.d.ts +7 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +17 -0
- package/dist/readiness.d.ts +0 -1
- package/dist/readiness.d.ts.map +1 -1
- package/dist/reads.d.ts +37 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +171 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +9 -1
- package/dist/refresh.d.ts +1 -1
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +8 -20
- package/dist/refusal.d.ts +5 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +55 -0
- package/dist/replica.d.ts +7 -7
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +51 -19
- package/dist/room-draft.d.ts +2 -4
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +3 -3
- package/dist/room-drafts.d.ts +24 -0
- package/dist/room-drafts.d.ts.map +1 -0
- package/dist/room-drafts.js +217 -0
- package/dist/rows.d.ts +14 -5
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +50 -58
- package/dist/runtime.d.ts +43 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1 -0
- package/dist/save.d.ts +5 -1
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +21 -20
- package/dist/saves.d.ts +70 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +1005 -0
- package/dist/seed.d.ts +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -1
- package/dist/shared.d.ts +1 -6
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +13 -95
- package/dist/shown.d.ts +31 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +292 -0
- package/dist/socket/admission.d.ts +7 -0
- package/dist/socket/admission.d.ts.map +1 -0
- package/dist/socket/admission.js +39 -0
- package/dist/socket/answers.d.ts +6 -0
- package/dist/socket/answers.d.ts.map +1 -0
- package/dist/socket/answers.js +20 -0
- package/dist/socket/lanes.d.ts +20 -0
- package/dist/socket/lanes.d.ts.map +1 -0
- package/dist/socket/lanes.js +77 -0
- package/dist/socket/reads.d.ts +10 -0
- package/dist/socket/reads.d.ts.map +1 -0
- package/dist/socket/reads.js +31 -0
- package/dist/socket/rooms.d.ts +44 -0
- package/dist/socket/rooms.d.ts.map +1 -0
- package/dist/socket/rooms.js +90 -0
- package/dist/socket/session.d.ts +38 -0
- package/dist/socket/session.d.ts.map +1 -0
- package/dist/socket/session.js +23 -0
- package/dist/socket.d.ts +70 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +175 -0
- package/dist/source.d.ts +61 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +82 -0
- package/dist/status.d.ts +0 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -6
- 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/readiness.d.ts +10 -0
- package/dist/store/readiness.d.ts.map +1 -0
- package/dist/store/readiness.js +52 -0
- package/dist/store/records.d.ts +212 -0
- package/dist/store/records.d.ts.map +1 -0
- package/dist/store/records.js +431 -0
- package/dist/store/room-held.d.ts +8 -0
- package/dist/store/room-held.d.ts.map +1 -0
- package/dist/store/room-held.js +17 -0
- package/dist/store/space.d.ts +11 -0
- package/dist/store/space.d.ts.map +1 -0
- package/dist/store/space.js +41 -0
- package/dist/store/watchers.d.ts +17 -0
- package/dist/store/watchers.d.ts.map +1 -0
- package/dist/store/watchers.js +56 -0
- package/dist/store/writes.d.ts +24 -0
- package/dist/store/writes.d.ts.map +1 -0
- package/dist/store/writes.js +125 -0
- package/dist/store.d.ts +107 -153
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +143 -396
- package/dist/stored.d.ts +59 -65
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +255 -149
- package/dist/surface.d.ts +88 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +223 -0
- package/dist/sync.d.ts +19 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +532 -0
- package/dist/tables.d.ts +114 -51
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +209 -57
- package/dist/tallies.d.ts +18 -0
- package/dist/tallies.d.ts.map +1 -0
- package/dist/tallies.js +129 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +4 -4
- package/dist/wire.d.ts +16 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +6 -0
- 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/tables.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { sql } from '@agentshouse/mdmodel';
|
|
2
2
|
import { answerQuery } from './compile.js';
|
|
3
|
-
import { droppedMessages, forgottenMessages, heldConversations, keptMessages, messageCount, messageWindow, MESSAGE_TABLES, turnArrived, } from './messages.js';
|
|
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();
|
|
@@ -76,7 +78,7 @@ const TABLES = [
|
|
|
76
78
|
['authored_queues', 'locator TEXT PRIMARY KEY, ids TEXT NOT NULL'],
|
|
77
79
|
[
|
|
78
80
|
'authored_pending',
|
|
79
|
-
'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)',
|
|
80
82
|
],
|
|
81
83
|
[
|
|
82
84
|
'authored_room_drafts',
|
|
@@ -93,34 +95,53 @@ export const RUNTIME_TABLES = [
|
|
|
93
95
|
'CREATE INDEX opened_files_name ON opened_files (locator, path, revision)',
|
|
94
96
|
...REPLICA_TABLES,
|
|
95
97
|
...MESSAGE_TABLES,
|
|
98
|
+
...READ_TABLES,
|
|
96
99
|
];
|
|
97
100
|
const OWNERS = ['authored_pending', 'authored_room_drafts', 'authored_calls'];
|
|
98
101
|
const AUTHORED_KEYS = OWNERS.map((table) => `SELECT value FROM ${table}, json_each(${table}.files)`).join(' UNION ');
|
|
99
102
|
const UNOWNED_PARTS = `DELETE FROM file_parts WHERE key NOT IN (${AUTHORED_KEYS} UNION SELECT key FROM opened_files)`;
|
|
103
|
+
const CLEANABLE_BYTES = `SELECT coalesce(sum(length(bytes)), 0) AS bytes FROM file_parts WHERE key NOT IN (${AUTHORED_KEYS})`;
|
|
100
104
|
const READS = new Set([
|
|
101
|
-
'authored.
|
|
105
|
+
'authored.status',
|
|
106
|
+
'authored.moving',
|
|
107
|
+
'authored.pending',
|
|
108
|
+
'authored.batch',
|
|
109
|
+
'authored.order',
|
|
110
|
+
'authored.queued',
|
|
102
111
|
'authored.roomDrafts',
|
|
112
|
+
'authored.chatDraft.read',
|
|
103
113
|
'authored.chatDrafts',
|
|
104
114
|
'authored.calls',
|
|
105
115
|
'authored.fences',
|
|
116
|
+
'authored.unsent',
|
|
106
117
|
'authored.fact',
|
|
107
118
|
'authored.file',
|
|
108
119
|
'replica.open',
|
|
120
|
+
'replica.rooms',
|
|
121
|
+
'replica.room',
|
|
122
|
+
'replica.covering',
|
|
123
|
+
'replica.offline',
|
|
124
|
+
'replica.held',
|
|
125
|
+
'replica.facts',
|
|
126
|
+
'replica.presentation',
|
|
109
127
|
'replica.query',
|
|
128
|
+
'replica.tallies',
|
|
110
129
|
'replica.entries',
|
|
111
130
|
'replica.typed',
|
|
112
131
|
'replica.referrers',
|
|
113
|
-
'replica.files',
|
|
114
132
|
'replica.folders',
|
|
115
133
|
'replica.typedWithin',
|
|
116
|
-
'replica.counts',
|
|
117
|
-
'replica.wanted',
|
|
118
134
|
'opened.find',
|
|
135
|
+
'opened.held',
|
|
119
136
|
'file.part',
|
|
120
137
|
'conversation.held',
|
|
121
138
|
'conversation.window',
|
|
122
139
|
'conversation.count',
|
|
123
140
|
'conversation.turn',
|
|
141
|
+
'conversation.rows',
|
|
142
|
+
'conversation.jobs',
|
|
143
|
+
'conversation.tallies',
|
|
144
|
+
'read.stored',
|
|
124
145
|
]);
|
|
125
146
|
const KINDS = new Set([
|
|
126
147
|
...READS,
|
|
@@ -132,17 +153,17 @@ const KINDS = new Set([
|
|
|
132
153
|
'authored.claim',
|
|
133
154
|
'authored.end',
|
|
134
155
|
'replica.stage',
|
|
156
|
+
'replica.resume',
|
|
135
157
|
'replica.refresh',
|
|
136
158
|
'replica.unrefresh',
|
|
137
159
|
'replica.commit',
|
|
138
160
|
'replica.fence',
|
|
139
161
|
'replica.erase',
|
|
140
162
|
'replica.abandon',
|
|
163
|
+
'replica.unfence',
|
|
141
164
|
'replica.release',
|
|
142
165
|
'replica.rederive',
|
|
143
|
-
'replica.
|
|
144
|
-
'replica.remember',
|
|
145
|
-
'replica.unhold',
|
|
166
|
+
'replica.demote',
|
|
146
167
|
'replica.fact',
|
|
147
168
|
'replica.present',
|
|
148
169
|
'opened.begin',
|
|
@@ -153,6 +174,8 @@ const KINDS = new Set([
|
|
|
153
174
|
'conversation.keep',
|
|
154
175
|
'conversation.drop',
|
|
155
176
|
'space.probe',
|
|
177
|
+
'read.keep',
|
|
178
|
+
'read.builds',
|
|
156
179
|
]);
|
|
157
180
|
export function isRuntime(request) {
|
|
158
181
|
return KINDS.has(request.kind);
|
|
@@ -225,21 +248,66 @@ function unowned(connection) {
|
|
|
225
248
|
connection.run(UNOWNED_PARTS);
|
|
226
249
|
}
|
|
227
250
|
function queued(connection) {
|
|
251
|
+
return connection.rows('SELECT locator, ids FROM authored_queues').map((row) => ({
|
|
252
|
+
locator: text(row.locator),
|
|
253
|
+
ids: JSON.parse(text(row.ids)),
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
function heldWork(connection, locator) {
|
|
257
|
+
const room = heldRoom(connection, locator);
|
|
258
|
+
const pending = new Map(connection
|
|
259
|
+
.rows('SELECT id, batch, state FROM authored_pending WHERE locator = ?', [locator])
|
|
260
|
+
.map((row) => [
|
|
261
|
+
text(row.id),
|
|
262
|
+
{ id: text(row.id), batch: text(row.batch), state: text(row.state) },
|
|
263
|
+
]));
|
|
228
264
|
return {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
265
|
+
room: room === null ? null : { ...room, overlaid: overlaid(connection, room.key) },
|
|
266
|
+
queue: heldOrder(connection, locator).map((id) => {
|
|
267
|
+
const held = pending.get(id);
|
|
268
|
+
if (held === undefined)
|
|
269
|
+
throw new Error(`Missing Pending Change ${locator}/${id}`);
|
|
270
|
+
return held;
|
|
271
|
+
}),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function status(connection) {
|
|
275
|
+
const [completed] = connection.rows("SELECT value FROM replica_facts WHERE name = 'lastCompleted'");
|
|
276
|
+
return {
|
|
277
|
+
queued: texts(connection.rows('SELECT locator FROM authored_queues'), 'locator'),
|
|
278
|
+
lastCompleted: completed === undefined ? null : text(completed.value),
|
|
279
|
+
changes: connection
|
|
280
|
+
.rows('SELECT p.locator, c.value AS path FROM authored_pending p, json_each(p.paths) c')
|
|
281
|
+
.map((row) => ({ locator: text(row.locator), path: text(row.path) })),
|
|
282
|
+
resets: connection
|
|
283
|
+
.rows(`SELECT locator, json_extract(state, '$.submission.reset') AS reset FROM authored_pending
|
|
284
|
+
WHERE json_extract(state, '$.submission.state') = 'reset'`)
|
|
285
|
+
.map((row) => ({ locator: text(row.locator), reset: text(row.reset) })),
|
|
286
|
+
returned: texts(connection.rows(`SELECT record FROM authored_room_drafts WHERE json_type(record, '$.returned') = 'object'`), 'record'),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function pendingOf(connection, locator, id) {
|
|
290
|
+
const [held] = connection.rows('SELECT state FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
291
|
+
return {
|
|
292
|
+
state: held === undefined ? null : text(held.state),
|
|
293
|
+
room: connection.rows('SELECT 1 FROM replica_rooms WHERE locator = ?', [locator]).length > 0,
|
|
241
294
|
};
|
|
242
295
|
}
|
|
296
|
+
function roomDraftRecords(connection, locator, paths) {
|
|
297
|
+
if (locator === null) {
|
|
298
|
+
return texts(connection.rows('SELECT record FROM authored_room_drafts'), 'record');
|
|
299
|
+
}
|
|
300
|
+
if (paths === null) {
|
|
301
|
+
return texts(connection.rows('SELECT record FROM authored_room_drafts WHERE locator = ?', [locator]), 'record');
|
|
302
|
+
}
|
|
303
|
+
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');
|
|
304
|
+
}
|
|
305
|
+
function chatDraftRecord(connection, conversation) {
|
|
306
|
+
const [held] = connection.rows('SELECT record FROM authored_chat_drafts WHERE conversation = ?', [
|
|
307
|
+
conversation,
|
|
308
|
+
]);
|
|
309
|
+
return held === undefined ? null : text(held.record);
|
|
310
|
+
}
|
|
243
311
|
function heldOrder(connection, locator) {
|
|
244
312
|
const [held] = connection.rows('SELECT ids FROM authored_queues WHERE locator = ?', [locator]);
|
|
245
313
|
return held === undefined ? [] : JSON.parse(text(held.ids));
|
|
@@ -271,19 +339,26 @@ function keptRows(connection, { locator, order, added, founded, roomDrafts, cons
|
|
|
271
339
|
connection.run('DELETE FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
272
340
|
}
|
|
273
341
|
}
|
|
274
|
-
for (const { id, batch, state, files } of added ?? []) {
|
|
275
|
-
if (before.has(id)
|
|
342
|
+
for (const { id, batch, state, files, paths, moving } of added ?? []) {
|
|
343
|
+
if (before.has(id))
|
|
276
344
|
continue;
|
|
277
|
-
connection.run('INSERT OR REPLACE INTO authored_pending (locator, id, batch, state, files) VALUES (?, ?, ?, ?, ?)', [locator, id, batch, state, owned(files)]);
|
|
345
|
+
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]);
|
|
278
346
|
}
|
|
279
|
-
for (const { id, batch, files } of founded ?? []) {
|
|
347
|
+
for (const { id, batch, files, paths, moving } of founded ?? []) {
|
|
280
348
|
const [held] = connection.rows('SELECT files FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
281
349
|
if (held === undefined || !before.has(id))
|
|
282
350
|
continue;
|
|
283
|
-
connection.run('UPDATE authored_pending SET batch = ?, files = ? WHERE locator = ? AND id = ?', [
|
|
351
|
+
connection.run('UPDATE authored_pending SET batch = ?, files = ?, paths = ?, moving = ? WHERE locator = ? AND id = ?', [
|
|
352
|
+
batch,
|
|
353
|
+
owned([...JSON.parse(text(held.files)), ...files]),
|
|
354
|
+
JSON.stringify(paths),
|
|
355
|
+
moving ? 1 : 0,
|
|
356
|
+
locator,
|
|
357
|
+
id,
|
|
358
|
+
]);
|
|
284
359
|
}
|
|
285
360
|
}
|
|
286
|
-
async function kept(connection, { writes, files, whole
|
|
361
|
+
async function kept(connection, { writes, files, whole }) {
|
|
287
362
|
const refused = writes.find(({ locator }) => fenced(connection, locator));
|
|
288
363
|
if (refused !== undefined && whole)
|
|
289
364
|
return refused.locator;
|
|
@@ -292,8 +367,6 @@ async function kept(connection, { writes, files, whole, discards }) {
|
|
|
292
367
|
if (!fenced(connection, write.locator))
|
|
293
368
|
keptRows(connection, write);
|
|
294
369
|
}
|
|
295
|
-
for (const locator of discards ?? [])
|
|
296
|
-
roomWork(connection, locator);
|
|
297
370
|
unowned(connection);
|
|
298
371
|
return refused?.locator ?? null;
|
|
299
372
|
}
|
|
@@ -363,11 +436,15 @@ function fence(connection, locators) {
|
|
|
363
436
|
return fenceRooms(connection, locators);
|
|
364
437
|
}
|
|
365
438
|
function erased(connection, { locator, limit }) {
|
|
366
|
-
|
|
367
|
-
|
|
439
|
+
return erase(connection, locator, limit);
|
|
440
|
+
}
|
|
441
|
+
function unfenced(connection, locators) {
|
|
442
|
+
const erased = locators.filter((locator) => connection.rows('SELECT 1 FROM replica_erasing WHERE locator = ? LIMIT 1', [locator])
|
|
443
|
+
.length === 0);
|
|
444
|
+
for (const locator of erased) {
|
|
368
445
|
connection.run('DELETE FROM authored_fences WHERE locator = ?', [locator]);
|
|
369
446
|
}
|
|
370
|
-
return
|
|
447
|
+
return erased;
|
|
371
448
|
}
|
|
372
449
|
function claim(connection, holder) {
|
|
373
450
|
const held = fact(connection, 'holder');
|
|
@@ -430,9 +507,9 @@ function keptOpened(connection, { key, sha256, byteLength, parts }) {
|
|
|
430
507
|
if (fetched === null)
|
|
431
508
|
return false;
|
|
432
509
|
const [held] = connection.rows('SELECT count(*) AS parts, min(part) AS first, max(part) AS last, coalesce(sum(length(bytes)), 0) AS bytes FROM file_parts WHERE key = ?', [key]);
|
|
433
|
-
const whole = count(held
|
|
434
|
-
count(held
|
|
435
|
-
(parts === 0 || (count(held
|
|
510
|
+
const whole = count(held.parts) === parts &&
|
|
511
|
+
count(held.bytes) === byteLength &&
|
|
512
|
+
(parts === 0 || (count(held.first) === 0 && count(held.last) === parts - 1));
|
|
436
513
|
if (!whole) {
|
|
437
514
|
dropped(connection, key);
|
|
438
515
|
return false;
|
|
@@ -446,16 +523,38 @@ function keptOpened(connection, { key, sha256, byteLength, parts }) {
|
|
|
446
523
|
unowned(connection);
|
|
447
524
|
return true;
|
|
448
525
|
}
|
|
526
|
+
const UNSENT = [
|
|
527
|
+
['pending-change', 'authored_pending'],
|
|
528
|
+
['call', 'authored_calls'],
|
|
529
|
+
['room-draft', 'authored_room_drafts'],
|
|
530
|
+
['chat-draft', 'authored_chat_drafts'],
|
|
531
|
+
];
|
|
532
|
+
function unsent(connection) {
|
|
533
|
+
const [held] = connection.rows(`SELECT ${UNSENT.map(([kind, table]) => `(SELECT count(*) FROM ${table}) AS "${kind}"`).join(', ')}`);
|
|
534
|
+
return UNSENT.map(([kind]) => ({ kind, count: count(held[kind]) })).filter((work) => work.count > 0);
|
|
535
|
+
}
|
|
536
|
+
function cleanable(connection) {
|
|
537
|
+
const [held] = connection.rows(CLEANABLE_BYTES);
|
|
538
|
+
return count(held.bytes);
|
|
539
|
+
}
|
|
449
540
|
function cleaned(connection) {
|
|
450
541
|
connection.run('DELETE FROM opened_files');
|
|
451
|
-
const
|
|
542
|
+
const freed = cleanable(connection);
|
|
452
543
|
unowned(connection);
|
|
453
|
-
return
|
|
544
|
+
return freed;
|
|
545
|
+
}
|
|
546
|
+
function openedHeld(connection) {
|
|
547
|
+
return {
|
|
548
|
+
rooms: connection
|
|
549
|
+
.rows('SELECT locator, count(*) AS files, sum(byte_length) AS bytes FROM opened_files WHERE byte_length IS NOT NULL GROUP BY locator ORDER BY locator')
|
|
550
|
+
.map((row) => ({ room: text(row.locator), count: count(row.files), size: count(row.bytes) })),
|
|
551
|
+
cleanable: cleanable(connection),
|
|
552
|
+
};
|
|
454
553
|
}
|
|
455
554
|
async function committed(connection, { authored, rooms }) {
|
|
456
555
|
const refused = authored === undefined ? null : await kept(connection, authored);
|
|
457
556
|
if (refused !== null && authored?.whole === true) {
|
|
458
|
-
return { fenced: refused,
|
|
557
|
+
return { fenced: refused, changed: {}, indexed: {} };
|
|
459
558
|
}
|
|
460
559
|
return {
|
|
461
560
|
fenced: refused,
|
|
@@ -464,16 +563,42 @@ async function committed(connection, { authored, rooms }) {
|
|
|
464
563
|
}
|
|
465
564
|
export function answerRuntime(connection, request, spool) {
|
|
466
565
|
switch (request.kind) {
|
|
467
|
-
case 'authored.
|
|
468
|
-
return
|
|
566
|
+
case 'authored.status':
|
|
567
|
+
return status(connection);
|
|
568
|
+
case 'authored.moving':
|
|
569
|
+
return {
|
|
570
|
+
queues: queued(connection),
|
|
571
|
+
pending: connection
|
|
572
|
+
.rows('SELECT locator, id, batch, state FROM authored_pending WHERE moving = 1 ORDER BY locator')
|
|
573
|
+
.map((row) => ({
|
|
574
|
+
locator: text(row.locator),
|
|
575
|
+
id: text(row.id),
|
|
576
|
+
batch: text(row.batch),
|
|
577
|
+
state: text(row.state),
|
|
578
|
+
})),
|
|
579
|
+
};
|
|
580
|
+
case 'authored.pending':
|
|
581
|
+
return pendingOf(connection, request.locator, request.id);
|
|
582
|
+
case 'authored.batch': {
|
|
583
|
+
const [held] = connection.rows('SELECT batch FROM authored_pending WHERE locator = ? AND id = ?', [request.locator, request.id]);
|
|
584
|
+
return held === undefined ? null : text(held.batch);
|
|
585
|
+
}
|
|
586
|
+
case 'authored.order':
|
|
587
|
+
return heldOrder(connection, request.locator);
|
|
588
|
+
case 'authored.queued':
|
|
589
|
+
return texts(connection.rows('SELECT locator FROM authored_queues'), 'locator');
|
|
469
590
|
case 'authored.roomDrafts':
|
|
470
|
-
return
|
|
591
|
+
return roomDraftRecords(connection, request.locator, request.paths);
|
|
592
|
+
case 'authored.chatDraft.read':
|
|
593
|
+
return chatDraftRecord(connection, request.conversation);
|
|
471
594
|
case 'authored.chatDrafts':
|
|
472
595
|
return texts(connection.rows('SELECT record FROM authored_chat_drafts'), 'record');
|
|
473
596
|
case 'authored.calls':
|
|
474
597
|
return texts(connection.rows('SELECT record FROM authored_calls'), 'record');
|
|
475
598
|
case 'authored.fences':
|
|
476
599
|
return texts(connection.rows('SELECT locator FROM authored_fences'), 'locator');
|
|
600
|
+
case 'authored.unsent':
|
|
601
|
+
return unsent(connection);
|
|
477
602
|
case 'authored.fact':
|
|
478
603
|
return fact(connection, request.name);
|
|
479
604
|
case 'authored.file':
|
|
@@ -494,24 +619,43 @@ export function answerRuntime(connection, request, spool) {
|
|
|
494
619
|
return end(connection, request.holder);
|
|
495
620
|
case 'replica.open':
|
|
496
621
|
return opened(connection);
|
|
622
|
+
case 'replica.rooms':
|
|
623
|
+
return heldRooms(connection, request.locators);
|
|
624
|
+
case 'replica.room':
|
|
625
|
+
return heldWork(connection, request.locator);
|
|
626
|
+
case 'replica.covering':
|
|
627
|
+
return {
|
|
628
|
+
rooms: covering(connection),
|
|
629
|
+
queues: queued(connection),
|
|
630
|
+
};
|
|
631
|
+
case 'replica.offline':
|
|
632
|
+
return offlineMode(connection, request.locator);
|
|
633
|
+
case 'replica.held':
|
|
634
|
+
return { held: heldLocators(connection), staged: stagedLocators(connection) };
|
|
635
|
+
case 'replica.demote':
|
|
636
|
+
return demoted(connection);
|
|
637
|
+
case 'replica.facts':
|
|
638
|
+
return facts(connection);
|
|
639
|
+
case 'replica.presentation':
|
|
640
|
+
return presentation(connection, request.app);
|
|
497
641
|
case 'replica.query':
|
|
498
642
|
return answerQuery(connection, request.plan, request.rooms, request.budget);
|
|
643
|
+
case 'replica.tallies':
|
|
644
|
+
return roomTallies(connection, request.totals, request.rooms, request.since);
|
|
499
645
|
case 'replica.entries':
|
|
500
646
|
return entries(connection, request.key, request.view, request.paths);
|
|
501
647
|
case 'replica.typed':
|
|
502
648
|
return typed(connection, request.key, request.view, request.paths);
|
|
503
649
|
case 'replica.referrers':
|
|
504
|
-
return referrers(connection, request.key, request.view, request.targets
|
|
505
|
-
case 'replica.files':
|
|
506
|
-
return files(connection, request.key, request.view, request.after, request.limit);
|
|
650
|
+
return referrers(connection, request.key, request.view, request.targets);
|
|
507
651
|
case 'replica.folders':
|
|
508
|
-
return folders(connection, request.key, request.
|
|
652
|
+
return folders(connection, request.key, request.paths);
|
|
509
653
|
case 'replica.typedWithin':
|
|
510
654
|
return typedWithin(connection, request.key, request.view, request.roots, request.within);
|
|
511
|
-
case 'replica.counts':
|
|
512
|
-
return counts(connection, request.rooms);
|
|
513
655
|
case 'replica.stage':
|
|
514
656
|
return fenced(connection, request.locator) ? null : stage(connection, request);
|
|
657
|
+
case 'replica.resume':
|
|
658
|
+
return fenced(connection, request.locator) ? null : resume(connection, request);
|
|
515
659
|
case 'replica.refresh':
|
|
516
660
|
return refreshing(connection, request);
|
|
517
661
|
case 'replica.unrefresh':
|
|
@@ -524,18 +668,12 @@ export function answerRuntime(connection, request, spool) {
|
|
|
524
668
|
return erased(connection, request);
|
|
525
669
|
case 'replica.abandon':
|
|
526
670
|
return abandon(connection, request.locator);
|
|
671
|
+
case 'replica.unfence':
|
|
672
|
+
return unfenced(connection, request.locators);
|
|
527
673
|
case 'replica.release':
|
|
528
674
|
return release(connection, request.key);
|
|
529
675
|
case 'replica.rederive':
|
|
530
676
|
return rederive(connection, request.key, request.composed, request.bytes, request.ms, request.floor);
|
|
531
|
-
case 'replica.hold':
|
|
532
|
-
return holdTexts(connection, request);
|
|
533
|
-
case 'replica.unhold':
|
|
534
|
-
return unholdTexts(connection, request);
|
|
535
|
-
case 'replica.wanted':
|
|
536
|
-
return wanted(connection, request);
|
|
537
|
-
case 'replica.remember':
|
|
538
|
-
return remembered(connection, request);
|
|
539
677
|
case 'replica.fact':
|
|
540
678
|
connection.run('INSERT OR REPLACE INTO replica_facts (name, value) VALUES (?, ?)', [
|
|
541
679
|
request.name,
|
|
@@ -560,10 +698,12 @@ export function answerRuntime(connection, request, spool) {
|
|
|
560
698
|
return dropped(connection, request.key);
|
|
561
699
|
case 'opened.clean':
|
|
562
700
|
return cleaned(connection);
|
|
701
|
+
case 'opened.held':
|
|
702
|
+
return openedHeld(connection);
|
|
563
703
|
case 'file.part':
|
|
564
704
|
return filePart(connection, request.key, request.part);
|
|
565
705
|
case 'conversation.held':
|
|
566
|
-
return heldConversations(connection);
|
|
706
|
+
return heldConversations(connection, request.conversations);
|
|
567
707
|
case 'conversation.keep': {
|
|
568
708
|
const { kind: _kind, ...write } = request;
|
|
569
709
|
return keptMessages(connection, write);
|
|
@@ -574,6 +714,12 @@ export function answerRuntime(connection, request, spool) {
|
|
|
574
714
|
return messageCount(connection, request.conversation, request.phrase);
|
|
575
715
|
case 'conversation.turn':
|
|
576
716
|
return turnArrived(connection, request.conversation, request.turn);
|
|
717
|
+
case 'conversation.rows':
|
|
718
|
+
return conversationRows(connection, request.conversations);
|
|
719
|
+
case 'conversation.jobs':
|
|
720
|
+
return jobMarkers(connection, request.conversation);
|
|
721
|
+
case 'conversation.tallies':
|
|
722
|
+
return conversationTallies(connection, request.conversations, request.since);
|
|
577
723
|
case 'conversation.drop':
|
|
578
724
|
chatDraft(connection, {
|
|
579
725
|
kind: 'authored.chatDraft',
|
|
@@ -584,5 +730,11 @@ export function answerRuntime(connection, request, spool) {
|
|
|
584
730
|
return null;
|
|
585
731
|
case 'space.probe':
|
|
586
732
|
return spool.probe(PROBE_BYTES).then(() => null);
|
|
733
|
+
case 'read.stored':
|
|
734
|
+
return storedRead(connection, request);
|
|
735
|
+
case 'read.keep':
|
|
736
|
+
return keptRead(connection, request, request.answer);
|
|
737
|
+
case 'read.builds':
|
|
738
|
+
return readsOfOtherBuildsForgotten(connection, request.build);
|
|
587
739
|
}
|
|
588
740
|
}
|
|
@@ -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(conversation, position, identity, at, role) AS (
|
|
98
|
+
SELECT m.conversation, m.position, m.identity, m.${ACCEPTED}, m.message ->> '$.role'
|
|
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.conversation, m.position, m.identity, m.${ACCEPTED}, m.message ->> '$.role'
|
|
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
|
|
113
|
+
WHERE walk.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/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,UAAU,EAGhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAM7D,KAAK,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,KAAK,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpF,MAAM,MAAM,IAAI,GAAG,CACjB,KAAK,EAAE,MAAM,GAAG,IAAI,KACjB,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC;AAEtF,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAwBvF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,UAAU,CAAC,CA6CrB;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1F,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CAChF,CAAC;AAkBF,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,UAAU,CAAC,CAgCrB"}
|
package/dist/validation.js
CHANGED
|
@@ -5,8 +5,7 @@ const NO_TYPES = { types: {} };
|
|
|
5
5
|
function modelOf(model) {
|
|
6
6
|
return model.status === 'unavailable' ? NO_TYPES : { types: model.types };
|
|
7
7
|
}
|
|
8
|
-
function typedText(
|
|
9
|
-
const read = parse(content);
|
|
8
|
+
function typedText(read) {
|
|
10
9
|
return read.ok && read.document.type !== undefined && read.document.type !== 'any';
|
|
11
10
|
}
|
|
12
11
|
function partVerdict(part) {
|
|
@@ -28,10 +27,11 @@ export async function validatedCollection(walk, lookup, composition) {
|
|
|
28
27
|
if (content === null)
|
|
29
28
|
continue;
|
|
30
29
|
const part = partOf(path);
|
|
31
|
-
|
|
30
|
+
const parsed = parse(content, path);
|
|
31
|
+
if (part.model.status === 'unavailable' && part.unmodeled === null && typedText(parsed)) {
|
|
32
32
|
part.unmodeled = path;
|
|
33
33
|
}
|
|
34
|
-
const assessment = assess(path,
|
|
34
|
+
const assessment = assess(path, parsed, false, modelOf(part.model), {
|
|
35
35
|
anyRoom: true,
|
|
36
36
|
typedPaths: composition.typedPaths,
|
|
37
37
|
});
|