@agentshouse/mdruntime 0.1.0-c0bed82db8d73 → 0.1.0-c0c0511ef12ee
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 +3 -2
- 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 +107 -71
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +4 -10
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +35 -46
- package/dist/bootstrap.d.ts +16 -15
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +274 -131
- package/dist/cell.d.ts +6 -0
- package/dist/cell.d.ts.map +1 -0
- package/dist/cell.js +9 -0
- 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/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 +25 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +56 -7
- package/dist/collection.d.ts +7 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +24 -19
- package/dist/compile.d.ts +6 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +287 -297
- package/dist/connection.d.ts +6 -141
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +103 -5016
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +7 -0
- 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 +41 -45
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +870 -786
- 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 -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 +49 -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/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +4 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +33 -33
- 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 +27 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -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 +33 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +54 -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 +5 -4
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +61 -21
- 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 +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +218 -0
- package/dist/memory.d.ts +13 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +219 -91
- package/dist/messages.d.ts +27 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +103 -31
- package/dist/model.d.ts +8 -10
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +6 -18
- 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 +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +15 -15
- 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 +17 -6
- 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 +60 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +126 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +26 -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 +18 -208
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- 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 +20 -11
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +206 -126
- package/dist/react.d.ts +10 -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 -18
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +4 -10
- package/dist/reads.d.ts +36 -10
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +157 -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 +34 -10
- 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 +11 -12
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +56 -23
- package/dist/room-draft.d.ts +21 -7
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +101 -54
- 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 +18 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +45 -153
- 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 +7 -1
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +31 -24
- package/dist/saves.d.ts +70 -0
- package/dist/saves.d.ts.map +1 -0
- package/dist/saves.js +1005 -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 +11 -2
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +71 -1
- package/dist/shared.d.ts +1 -7
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +13 -105
- 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 +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/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 +105 -158
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +143 -401
- package/dist/stored.d.ts +66 -55
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +355 -273
- 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 +131 -69
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +221 -105
- 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 +25 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +9 -2
- package/package.json +2 -3
- package/AGENTS.md +0 -312
- 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,53 @@ 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)`;
|
|
103
|
+
const CLEANABLE_BYTES = `SELECT coalesce(sum(length(bytes)), 0) AS bytes FROM file_parts WHERE key NOT IN (${AUTHORED_KEYS})`;
|
|
97
104
|
const READS = new Set([
|
|
98
|
-
'authored.
|
|
105
|
+
'authored.status',
|
|
106
|
+
'authored.moving',
|
|
107
|
+
'authored.pending',
|
|
108
|
+
'authored.batch',
|
|
109
|
+
'authored.order',
|
|
110
|
+
'authored.queued',
|
|
99
111
|
'authored.roomDrafts',
|
|
112
|
+
'authored.chatDraft.read',
|
|
100
113
|
'authored.chatDrafts',
|
|
101
114
|
'authored.calls',
|
|
102
115
|
'authored.fences',
|
|
116
|
+
'authored.unsent',
|
|
103
117
|
'authored.fact',
|
|
104
118
|
'authored.file',
|
|
105
119
|
'replica.open',
|
|
120
|
+
'replica.rooms',
|
|
121
|
+
'replica.room',
|
|
122
|
+
'replica.covering',
|
|
123
|
+
'replica.offline',
|
|
124
|
+
'replica.held',
|
|
125
|
+
'replica.facts',
|
|
126
|
+
'replica.presentation',
|
|
106
127
|
'replica.query',
|
|
128
|
+
'replica.tallies',
|
|
107
129
|
'replica.entries',
|
|
108
130
|
'replica.typed',
|
|
109
131
|
'replica.referrers',
|
|
110
|
-
'replica.
|
|
111
|
-
'replica.files',
|
|
132
|
+
'replica.folders',
|
|
112
133
|
'replica.typedWithin',
|
|
113
|
-
'replica.counts',
|
|
114
|
-
'replica.search',
|
|
115
|
-
'replica.received',
|
|
116
|
-
'replica.receivedParts',
|
|
117
|
-
'replica.transferPart',
|
|
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,19 +153,19 @@ const KINDS = new Set([
|
|
|
132
153
|
'authored.claim',
|
|
133
154
|
'authored.end',
|
|
134
155
|
'replica.stage',
|
|
135
|
-
'replica.
|
|
156
|
+
'replica.resume',
|
|
136
157
|
'replica.refresh',
|
|
137
158
|
'replica.unrefresh',
|
|
138
159
|
'replica.commit',
|
|
139
160
|
'replica.fence',
|
|
140
161
|
'replica.erase',
|
|
141
162
|
'replica.abandon',
|
|
163
|
+
'replica.unfence',
|
|
142
164
|
'replica.release',
|
|
143
165
|
'replica.rederive',
|
|
166
|
+
'replica.demote',
|
|
144
167
|
'replica.fact',
|
|
145
168
|
'replica.present',
|
|
146
|
-
'replica.receive',
|
|
147
|
-
'replica.unreceive',
|
|
148
169
|
'opened.begin',
|
|
149
170
|
'opened.part',
|
|
150
171
|
'opened.keep',
|
|
@@ -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,29 +248,71 @@ 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
|
-
locator: text(row.locator),
|
|
237
|
-
id: text(row.id),
|
|
238
|
-
batch: text(row.batch),
|
|
239
|
-
state: text(row.state),
|
|
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
|
+
}),
|
|
241
272
|
};
|
|
242
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,
|
|
294
|
+
};
|
|
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));
|
|
246
314
|
}
|
|
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
|
-
}
|
|
315
|
+
function keptRows(connection, { locator, order, added, founded, roomDrafts, consumedRoomDrafts }) {
|
|
251
316
|
for (const path of consumedRoomDrafts ?? []) {
|
|
252
317
|
connection.run('DELETE FROM authored_room_drafts WHERE locator = ? AND path = ?', [
|
|
253
318
|
locator,
|
|
@@ -274,19 +339,26 @@ function keptRows(connection, { locator, order, added, founded, roomDrafts, cons
|
|
|
274
339
|
connection.run('DELETE FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
275
340
|
}
|
|
276
341
|
}
|
|
277
|
-
for (const { id, batch, state, files } of added ?? []) {
|
|
278
|
-
if (before.has(id)
|
|
342
|
+
for (const { id, batch, state, files, paths, moving } of added ?? []) {
|
|
343
|
+
if (before.has(id))
|
|
279
344
|
continue;
|
|
280
|
-
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]);
|
|
281
346
|
}
|
|
282
|
-
for (const { id, batch, files } of founded ?? []) {
|
|
347
|
+
for (const { id, batch, files, paths, moving } of founded ?? []) {
|
|
283
348
|
const [held] = connection.rows('SELECT files FROM authored_pending WHERE locator = ? AND id = ?', [locator, id]);
|
|
284
349
|
if (held === undefined || !before.has(id))
|
|
285
350
|
continue;
|
|
286
|
-
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
|
+
]);
|
|
287
359
|
}
|
|
288
360
|
}
|
|
289
|
-
async function kept(connection, { writes, files, whole
|
|
361
|
+
async function kept(connection, { writes, files, whole }) {
|
|
290
362
|
const refused = writes.find(({ locator }) => fenced(connection, locator));
|
|
291
363
|
if (refused !== undefined && whole)
|
|
292
364
|
return refused.locator;
|
|
@@ -295,8 +367,6 @@ async function kept(connection, { writes, files, whole, discards }) {
|
|
|
295
367
|
if (!fenced(connection, write.locator))
|
|
296
368
|
keptRows(connection, write);
|
|
297
369
|
}
|
|
298
|
-
for (const locator of discards ?? [])
|
|
299
|
-
roomWork(connection, locator);
|
|
300
370
|
unowned(connection);
|
|
301
371
|
return refused?.locator ?? null;
|
|
302
372
|
}
|
|
@@ -366,11 +436,15 @@ function fence(connection, locators) {
|
|
|
366
436
|
return fenceRooms(connection, locators);
|
|
367
437
|
}
|
|
368
438
|
function erased(connection, { locator, limit }) {
|
|
369
|
-
|
|
370
|
-
|
|
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) {
|
|
371
445
|
connection.run('DELETE FROM authored_fences WHERE locator = ?', [locator]);
|
|
372
446
|
}
|
|
373
|
-
return
|
|
447
|
+
return erased;
|
|
374
448
|
}
|
|
375
449
|
function claim(connection, holder) {
|
|
376
450
|
const held = fact(connection, 'holder');
|
|
@@ -433,9 +507,9 @@ function keptOpened(connection, { key, sha256, byteLength, parts }) {
|
|
|
433
507
|
if (fetched === null)
|
|
434
508
|
return false;
|
|
435
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]);
|
|
436
|
-
const whole = count(held
|
|
437
|
-
count(held
|
|
438
|
-
(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));
|
|
439
513
|
if (!whole) {
|
|
440
514
|
dropped(connection, key);
|
|
441
515
|
return false;
|
|
@@ -449,56 +523,82 @@ function keptOpened(connection, { key, sha256, byteLength, parts }) {
|
|
|
449
523
|
unowned(connection);
|
|
450
524
|
return true;
|
|
451
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
|
+
}
|
|
452
540
|
function cleaned(connection) {
|
|
453
541
|
connection.run('DELETE FROM opened_files');
|
|
454
|
-
const
|
|
542
|
+
const freed = cleanable(connection);
|
|
455
543
|
unowned(connection);
|
|
456
|
-
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
|
+
};
|
|
457
553
|
}
|
|
458
554
|
async function committed(connection, { authored, rooms }) {
|
|
459
555
|
const refused = authored === undefined ? null : await kept(connection, authored);
|
|
460
556
|
if (refused !== null && authored?.whole === true) {
|
|
461
|
-
return { fenced: refused,
|
|
557
|
+
return { fenced: refused, changed: {}, indexed: {} };
|
|
462
558
|
}
|
|
463
559
|
return {
|
|
464
560
|
fenced: refused,
|
|
465
561
|
...commit(connection, rooms.filter(({ locator }) => !fenced(connection, locator))),
|
|
466
562
|
};
|
|
467
563
|
}
|
|
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
564
|
export function answerRuntime(connection, request, spool) {
|
|
491
565
|
switch (request.kind) {
|
|
492
|
-
case 'authored.
|
|
493
|
-
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');
|
|
494
590
|
case 'authored.roomDrafts':
|
|
495
|
-
return
|
|
591
|
+
return roomDraftRecords(connection, request.locator, request.paths);
|
|
592
|
+
case 'authored.chatDraft.read':
|
|
593
|
+
return chatDraftRecord(connection, request.conversation);
|
|
496
594
|
case 'authored.chatDrafts':
|
|
497
595
|
return texts(connection.rows('SELECT record FROM authored_chat_drafts'), 'record');
|
|
498
596
|
case 'authored.calls':
|
|
499
597
|
return texts(connection.rows('SELECT record FROM authored_calls'), 'record');
|
|
500
598
|
case 'authored.fences':
|
|
501
599
|
return texts(connection.rows('SELECT locator FROM authored_fences'), 'locator');
|
|
600
|
+
case 'authored.unsent':
|
|
601
|
+
return unsent(connection);
|
|
502
602
|
case 'authored.fact':
|
|
503
603
|
return fact(connection, request.name);
|
|
504
604
|
case 'authored.file':
|
|
@@ -519,39 +619,43 @@ export function answerRuntime(connection, request, spool) {
|
|
|
519
619
|
return end(connection, request.holder);
|
|
520
620
|
case 'replica.open':
|
|
521
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);
|
|
522
641
|
case 'replica.query':
|
|
523
642
|
return answerQuery(connection, request.plan, request.rooms, request.budget);
|
|
643
|
+
case 'replica.tallies':
|
|
644
|
+
return roomTallies(connection, request.totals, request.rooms, request.since);
|
|
524
645
|
case 'replica.entries':
|
|
525
646
|
return entries(connection, request.key, request.view, request.paths);
|
|
526
647
|
case 'replica.typed':
|
|
527
648
|
return typed(connection, request.key, request.view, request.paths);
|
|
528
649
|
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);
|
|
650
|
+
return referrers(connection, request.key, request.view, request.targets);
|
|
651
|
+
case 'replica.folders':
|
|
652
|
+
return folders(connection, request.key, request.paths);
|
|
534
653
|
case 'replica.typedWithin':
|
|
535
654
|
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
655
|
case 'replica.stage':
|
|
550
656
|
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);
|
|
657
|
+
case 'replica.resume':
|
|
658
|
+
return fenced(connection, request.locator) ? null : resume(connection, request);
|
|
555
659
|
case 'replica.refresh':
|
|
556
660
|
return refreshing(connection, request);
|
|
557
661
|
case 'replica.unrefresh':
|
|
@@ -563,11 +667,13 @@ export function answerRuntime(connection, request, spool) {
|
|
|
563
667
|
case 'replica.erase':
|
|
564
668
|
return erased(connection, request);
|
|
565
669
|
case 'replica.abandon':
|
|
566
|
-
return abandon(connection, request.locator
|
|
670
|
+
return abandon(connection, request.locator);
|
|
671
|
+
case 'replica.unfence':
|
|
672
|
+
return unfenced(connection, request.locators);
|
|
567
673
|
case 'replica.release':
|
|
568
674
|
return release(connection, request.key);
|
|
569
675
|
case 'replica.rederive':
|
|
570
|
-
return rederive(connection, request.key, request.
|
|
676
|
+
return rederive(connection, request.key, request.composed, request.bytes, request.ms, request.floor);
|
|
571
677
|
case 'replica.fact':
|
|
572
678
|
connection.run('INSERT OR REPLACE INTO replica_facts (name, value) VALUES (?, ?)', [
|
|
573
679
|
request.name,
|
|
@@ -580,10 +686,6 @@ export function answerRuntime(connection, request, spool) {
|
|
|
580
686
|
request.value,
|
|
581
687
|
]);
|
|
582
688
|
return null;
|
|
583
|
-
case 'replica.receive':
|
|
584
|
-
return receive(connection, request);
|
|
585
|
-
case 'replica.unreceive':
|
|
586
|
-
return unreceive(connection, request.keys);
|
|
587
689
|
case 'opened.find':
|
|
588
690
|
return openedFile(connection, request);
|
|
589
691
|
case 'opened.begin':
|
|
@@ -596,20 +698,28 @@ export function answerRuntime(connection, request, spool) {
|
|
|
596
698
|
return dropped(connection, request.key);
|
|
597
699
|
case 'opened.clean':
|
|
598
700
|
return cleaned(connection);
|
|
701
|
+
case 'opened.held':
|
|
702
|
+
return openedHeld(connection);
|
|
599
703
|
case 'file.part':
|
|
600
704
|
return filePart(connection, request.key, request.part);
|
|
601
705
|
case 'conversation.held':
|
|
602
|
-
return heldConversations(connection);
|
|
706
|
+
return heldConversations(connection, request.conversations);
|
|
603
707
|
case 'conversation.keep': {
|
|
604
708
|
const { kind: _kind, ...write } = request;
|
|
605
709
|
return keptMessages(connection, write);
|
|
606
710
|
}
|
|
607
711
|
case 'conversation.window':
|
|
608
|
-
return messageWindow(connection, request.conversation, request.limit, request.before);
|
|
712
|
+
return messageWindow(connection, request.conversation, request.limit, request.before, request.phrase);
|
|
609
713
|
case 'conversation.count':
|
|
610
|
-
return messageCount(connection, request.conversation);
|
|
714
|
+
return messageCount(connection, request.conversation, request.phrase);
|
|
611
715
|
case 'conversation.turn':
|
|
612
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);
|
|
613
723
|
case 'conversation.drop':
|
|
614
724
|
chatDraft(connection, {
|
|
615
725
|
kind: 'authored.chatDraft',
|
|
@@ -620,5 +730,11 @@ export function answerRuntime(connection, request, spool) {
|
|
|
620
730
|
return null;
|
|
621
731
|
case 'space.probe':
|
|
622
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);
|
|
623
739
|
}
|
|
624
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"}
|