@agentshouse/mdruntime 0.1.0-c969b8dee6cc8 → 0.1.0-c96e80d38e5f0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -16
- package/dist/adapter.d.ts +134 -76
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/binary.d.ts +0 -5
- package/dist/binary.d.ts.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/bootstrap.d.ts +25 -10
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +180 -103
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -16
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -89
- package/dist/change.d.ts +31 -1
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +10 -1
- package/dist/client.d.ts +13 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +80 -7
- package/dist/collection.d.ts +10 -21
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +39 -291
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +789 -0
- package/dist/connection.d.ts +19 -15
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3020 -1417
- package/dist/conversation.d.ts +23 -14
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +337 -179
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/durability.d.ts +2 -5
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +4 -1
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +19 -23
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/host.d.ts +4 -10
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +49 -31
- 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 +14 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +123 -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 +11 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +198 -107
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +89 -0
- package/dist/model.d.ts +6 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -10
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +13 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +84 -0
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/outcome.d.ts +40 -8
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +38 -2
- package/dist/overlay.d.ts +2 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +87 -172
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/phrase.d.ts +3 -0
- package/dist/phrase.d.ts.map +1 -0
- package/dist/phrase.js +8 -0
- package/dist/query.d.ts +15 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +33 -2
- package/dist/reach.d.ts +13 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +200 -81
- package/dist/react.d.ts +1 -0
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +14 -17
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +2 -8
- package/dist/recovery.d.ts +3 -2
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +34 -7
- package/dist/refresh.d.ts +18 -15
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +155 -58
- package/dist/replica.d.ts +54 -36
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +282 -189
- package/dist/room-draft.d.ts +22 -4
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +154 -67
- package/dist/rows.d.ts +39 -31
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +178 -101
- package/dist/save.d.ts +52 -14
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +513 -185
- package/dist/search.d.ts +12 -95
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +10 -266
- package/dist/shared.d.ts +7 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +119 -66
- package/dist/status.d.ts +4 -3
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +91 -103
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +330 -693
- package/dist/stored.d.ts +162 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +549 -0
- package/dist/tables.d.ts +353 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +585 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/turn.d.ts +5 -3
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +51 -21
- package/dist/validation.d.ts +29 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +101 -0
- package/dist/windows.d.ts +2 -6
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +30 -34
- package/dist/wire.d.ts +18 -5
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +6 -2
- package/package.json +18 -19
- package/AGENTS.md +0 -305
- package/dist/acquisition.d.ts +0 -14
- package/dist/acquisition.d.ts.map +0 -1
- package/dist/acquisition.js +0 -24
- package/dist/chat/acts.d.ts +0 -33
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/context.d.ts +0 -3
- package/dist/chat/context.d.ts.map +0 -1
- package/dist/chat/context.js +0 -10
- package/dist/chat/earlier.d.ts +0 -10
- package/dist/chat/earlier.d.ts.map +0 -1
- package/dist/chat/earlier.js +0 -54
- package/dist/chat/input.d.ts +0 -9
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -99
- package/dist/chat/kit.d.ts +0 -61
- package/dist/chat/kit.d.ts.map +0 -1
- package/dist/chat/kit.js +0 -123
- package/dist/chat/lasting.d.ts +0 -6
- package/dist/chat/lasting.d.ts.map +0 -1
- package/dist/chat/lasting.js +0 -19
- package/dist/chat/list.d.ts +0 -27
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -99
- package/dist/chat/markdown.d.ts +0 -20
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -188
- package/dist/chat/message.d.ts +0 -6
- package/dist/chat/message.d.ts.map +0 -1
- package/dist/chat/message.js +0 -192
- package/dist/chat/messages.d.ts +0 -22
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -155
- package/dist/chat/name.d.ts +0 -6
- package/dist/chat/name.d.ts.map +0 -1
- package/dist/chat/name.js +0 -37
- package/dist/chat/opened.d.ts +0 -11
- package/dist/chat/opened.d.ts.map +0 -1
- package/dist/chat/opened.js +0 -17
- package/dist/chat/overlay.d.ts +0 -31
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -97
- package/dist/chat/parts.d.ts +0 -57
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -119
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -63
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -628
- package/dist/chat/question.d.ts +0 -9
- package/dist/chat/question.d.ts.map +0 -1
- package/dist/chat/question.js +0 -69
- package/dist/chat/questions.d.ts +0 -31
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/questions.js +0 -111
- package/dist/chat/read.d.ts +0 -5
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/read.js +0 -13
- package/dist/chat/ready.d.ts +0 -34
- package/dist/chat/ready.d.ts.map +0 -1
- package/dist/chat/ready.js +0 -91
- package/dist/chat/style.d.ts +0 -4
- package/dist/chat/style.d.ts.map +0 -1
- package/dist/chat/style.js +0 -302
- package/dist/chat.d.ts +0 -14
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -8
- package/dist/read-side.d.ts +0 -25
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -767
- package/dist/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -98
package/dist/conversation.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { conversationChangeSet } from './change-set.js';
|
|
2
2
|
import { runtimeError } from './failure.js';
|
|
3
|
-
import {
|
|
3
|
+
import { refusedForSpace } from './durability.js';
|
|
4
4
|
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
5
5
|
import { OFFLINE } from './outcome.js';
|
|
6
|
+
import { untilAnswered } from './recovery.js';
|
|
6
7
|
import { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
|
|
7
8
|
const QUIET = {
|
|
8
9
|
turn: null,
|
|
@@ -10,7 +11,21 @@ const QUIET = {
|
|
|
10
11
|
process: null,
|
|
11
12
|
commands: [],
|
|
12
13
|
options: [],
|
|
14
|
+
starting: null,
|
|
15
|
+
subagents: [],
|
|
16
|
+
link: null,
|
|
17
|
+
deliveryUnknown: [],
|
|
13
18
|
};
|
|
19
|
+
const FACTS = [
|
|
20
|
+
'questions',
|
|
21
|
+
'process',
|
|
22
|
+
'commands',
|
|
23
|
+
'options',
|
|
24
|
+
'starting',
|
|
25
|
+
'subagents',
|
|
26
|
+
'link',
|
|
27
|
+
'deliveryUnknown',
|
|
28
|
+
];
|
|
14
29
|
export function unheldView(conversation) {
|
|
15
30
|
return {
|
|
16
31
|
conversation,
|
|
@@ -20,19 +35,26 @@ export function unheldView(conversation) {
|
|
|
20
35
|
process: null,
|
|
21
36
|
commands: [],
|
|
22
37
|
options: [],
|
|
38
|
+
starting: null,
|
|
39
|
+
subagents: [],
|
|
40
|
+
link: null,
|
|
41
|
+
deliveryUnknown: [],
|
|
23
42
|
chatDraft: null,
|
|
24
43
|
};
|
|
25
44
|
}
|
|
26
45
|
export const SESSION_STARTED = 'Session started';
|
|
27
46
|
const NEW_CHAT = 'new:';
|
|
47
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
28
48
|
export function newChat(agent) {
|
|
29
49
|
return `${NEW_CHAT}${agent}`;
|
|
30
50
|
}
|
|
31
51
|
function creationOf(input) {
|
|
32
52
|
if (typeof input !== 'object' || input === null)
|
|
33
53
|
return null;
|
|
34
|
-
const { agent_id: agent, operation_id: operation } = input;
|
|
35
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
54
|
+
const { agent_id: agent, operation_id: operation, replaces, } = input;
|
|
55
|
+
return typeof agent === 'string' && typeof operation === 'string' && replaces === undefined
|
|
56
|
+
? { agent, operation }
|
|
57
|
+
: null;
|
|
36
58
|
}
|
|
37
59
|
function startedTurn(turn, operation) {
|
|
38
60
|
if (operation.op === 'begin')
|
|
@@ -191,9 +213,23 @@ function askedOf(options) {
|
|
|
191
213
|
}
|
|
192
214
|
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
193
215
|
}
|
|
216
|
+
function phraseOf(text) {
|
|
217
|
+
if (text === undefined)
|
|
218
|
+
return null;
|
|
219
|
+
if (typeof text !== 'string' || text === '') {
|
|
220
|
+
throw runtimeError('invalid-text', 'a conversation is found by a phrase');
|
|
221
|
+
}
|
|
222
|
+
return text;
|
|
223
|
+
}
|
|
194
224
|
const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
|
|
225
|
+
const DURABLE_WRITE = {
|
|
226
|
+
kind: 'rejected',
|
|
227
|
+
code: 'durable-write',
|
|
228
|
+
fields: {},
|
|
229
|
+
retryable: true,
|
|
230
|
+
};
|
|
195
231
|
function unwritten(draft) {
|
|
196
|
-
return draft.text === ''
|
|
232
|
+
return draft.text === '';
|
|
197
233
|
}
|
|
198
234
|
function pending(draft) {
|
|
199
235
|
return {
|
|
@@ -209,10 +245,7 @@ function withSubmitted(draft, submitted) {
|
|
|
209
245
|
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
210
246
|
}
|
|
211
247
|
function prepended(draft, said) {
|
|
212
|
-
return {
|
|
213
|
-
text: [said.text, draft.text].filter((one) => one !== '').join('\n'),
|
|
214
|
-
files: [...said.files, ...draft.files],
|
|
215
|
-
};
|
|
248
|
+
return { text: [said.text, draft.text].filter((one) => one !== '').join('\n') };
|
|
216
249
|
}
|
|
217
250
|
function returned(draft, submission, others) {
|
|
218
251
|
return withSubmitted({
|
|
@@ -231,15 +264,22 @@ export function createConversationStore(deps) {
|
|
|
231
264
|
const catching = new Map();
|
|
232
265
|
const gaps = new Map();
|
|
233
266
|
const lives = new Map();
|
|
267
|
+
const unsent = new Map();
|
|
234
268
|
const views = new Map();
|
|
235
269
|
const listing = new Map();
|
|
270
|
+
let relisting = null;
|
|
271
|
+
let listCursor = null;
|
|
236
272
|
const creations = new Set();
|
|
237
273
|
const listWatchers = new Set();
|
|
274
|
+
const unlisted = new Set();
|
|
238
275
|
let listKnown = false;
|
|
276
|
+
let listHeld = false;
|
|
277
|
+
let listKept = false;
|
|
239
278
|
const agentWatchers = new Set();
|
|
240
|
-
|
|
241
|
-
let
|
|
242
|
-
let
|
|
279
|
+
const unnamed = new Set();
|
|
280
|
+
let agentsShown = null;
|
|
281
|
+
let listedAgents = null;
|
|
282
|
+
let agentsReading = false;
|
|
243
283
|
let replicated = new Set();
|
|
244
284
|
let handedReplicated;
|
|
245
285
|
function liveOf(conversation) {
|
|
@@ -262,9 +302,13 @@ export function createConversationStore(deps) {
|
|
|
262
302
|
process: facts.process === null ? null : { ...facts.process },
|
|
263
303
|
commands: structuredClone(facts.commands),
|
|
264
304
|
options: structuredClone(facts.options),
|
|
305
|
+
starting: facts.starting,
|
|
306
|
+
subagents: structuredClone(facts.subagents),
|
|
307
|
+
link: facts.link === null ? null : { ...facts.link },
|
|
308
|
+
deliveryUnknown: [...facts.deliveryUnknown],
|
|
265
309
|
chatDraft: draft === undefined || unwritten(draft)
|
|
266
310
|
? null
|
|
267
|
-
: { text: draft.text,
|
|
311
|
+
: { text: draft.text, revision: draft.revision },
|
|
268
312
|
};
|
|
269
313
|
}
|
|
270
314
|
function emit(conversation) {
|
|
@@ -306,9 +350,6 @@ export function createConversationStore(deps) {
|
|
|
306
350
|
}
|
|
307
351
|
}
|
|
308
352
|
}
|
|
309
|
-
function changesOf(conversation, arriving) {
|
|
310
|
-
return arriving.map(({ identity, text }) => ({ conversation, identity, text }));
|
|
311
|
-
}
|
|
312
353
|
function stateOf(conversation) {
|
|
313
354
|
const facts = liveOf(conversation);
|
|
314
355
|
if (facts.questions.length > 0)
|
|
@@ -318,34 +359,110 @@ export function createConversationStore(deps) {
|
|
|
318
359
|
function entries() {
|
|
319
360
|
return [...listing.values()].map((entry) => ({
|
|
320
361
|
conversation: entry.conversation,
|
|
321
|
-
agent: { identity: entry.agent, name:
|
|
362
|
+
agent: { identity: entry.agent, name: entry.agentName },
|
|
322
363
|
name: entry.name,
|
|
323
364
|
created: entry.created,
|
|
324
365
|
finished: entry.finished,
|
|
325
366
|
outcome: entry.outcome,
|
|
367
|
+
waiting: entry.waiting,
|
|
326
368
|
state: stateOf(entry.conversation),
|
|
327
369
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
328
370
|
}));
|
|
329
371
|
}
|
|
372
|
+
function keepList() {
|
|
373
|
+
if (!listKnown || listKept)
|
|
374
|
+
return;
|
|
375
|
+
listKept = true;
|
|
376
|
+
queueMicrotask(() => {
|
|
377
|
+
listKept = false;
|
|
378
|
+
if (deps.closed())
|
|
379
|
+
return;
|
|
380
|
+
const entries = [...listing.values()];
|
|
381
|
+
const cursor = listCursor;
|
|
382
|
+
void deps
|
|
383
|
+
.durably(async (local) => {
|
|
384
|
+
await local.fact('conversationList', entries);
|
|
385
|
+
await local.fact('conversationCursor', cursor);
|
|
386
|
+
})
|
|
387
|
+
.catch(() => { });
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function listed(entry) {
|
|
391
|
+
listing.set(entry.conversation, { ...entry });
|
|
392
|
+
creations.delete(entry.conversation);
|
|
393
|
+
}
|
|
330
394
|
function emitList() {
|
|
331
|
-
if (deps.closed()
|
|
395
|
+
if (deps.closed())
|
|
332
396
|
return;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
watcher
|
|
397
|
+
if (listWatchers.size > 0) {
|
|
398
|
+
const value = entries();
|
|
399
|
+
for (const watcher of listWatchers)
|
|
400
|
+
watcher(value);
|
|
401
|
+
}
|
|
402
|
+
emitAgents();
|
|
403
|
+
learned();
|
|
404
|
+
}
|
|
405
|
+
function learned() {
|
|
406
|
+
if (deps.closed())
|
|
407
|
+
return;
|
|
408
|
+
if (!listKnown && !listHeld && deps.stream() !== undefined && deps.online())
|
|
409
|
+
return;
|
|
410
|
+
if (unlisted.size > 0) {
|
|
411
|
+
const value = entries();
|
|
412
|
+
for (const watcher of [...unlisted]) {
|
|
413
|
+
unlisted.delete(watcher);
|
|
414
|
+
listWatchers.add(watcher);
|
|
415
|
+
watcher(value);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (unnamed.size > 0) {
|
|
419
|
+
const value = agents();
|
|
420
|
+
for (const watcher of [...unnamed]) {
|
|
421
|
+
unnamed.delete(watcher);
|
|
422
|
+
agentWatchers.add(watcher);
|
|
423
|
+
watcher(value);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
336
426
|
}
|
|
337
427
|
function agents() {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.
|
|
428
|
+
const named = new Map();
|
|
429
|
+
for (const agent of listedAgents ?? [])
|
|
430
|
+
named.set(agent.agent, agent);
|
|
431
|
+
for (const entry of listing.values()) {
|
|
432
|
+
named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
|
|
433
|
+
}
|
|
434
|
+
return [...named]
|
|
435
|
+
.filter(([, agent]) => !agent.retired)
|
|
436
|
+
.map(([identity, agent]) => ({ identity, name: agent.name }))
|
|
341
437
|
.sort((left, right) => left.name === right.name
|
|
342
438
|
? left.identity.localeCompare(right.identity)
|
|
343
439
|
: left.name.localeCompare(right.name));
|
|
344
440
|
}
|
|
441
|
+
function readAgents() {
|
|
442
|
+
const stream = deps.stream();
|
|
443
|
+
if (stream?.agents === undefined || !deps.online() || agentsReading)
|
|
444
|
+
return;
|
|
445
|
+
agentsReading = true;
|
|
446
|
+
void stream
|
|
447
|
+
.agents()
|
|
448
|
+
.then((read) => {
|
|
449
|
+
if (read === null)
|
|
450
|
+
return;
|
|
451
|
+
listedAgents = read;
|
|
452
|
+
emitAgents();
|
|
453
|
+
}, () => { })
|
|
454
|
+
.finally(() => {
|
|
455
|
+
agentsReading = false;
|
|
456
|
+
});
|
|
457
|
+
}
|
|
345
458
|
function emitAgents() {
|
|
346
459
|
if (deps.closed() || agentWatchers.size === 0)
|
|
347
460
|
return;
|
|
348
461
|
const value = agents();
|
|
462
|
+
const shown = JSON.stringify(value);
|
|
463
|
+
if (shown === agentsShown)
|
|
464
|
+
return;
|
|
465
|
+
agentsShown = shown;
|
|
349
466
|
for (const watcher of agentWatchers)
|
|
350
467
|
watcher(value);
|
|
351
468
|
}
|
|
@@ -361,53 +478,42 @@ export function createConversationStore(deps) {
|
|
|
361
478
|
if (stateOf(conversation) !== before || next?.turn?.started !== began)
|
|
362
479
|
emitList();
|
|
363
480
|
}
|
|
364
|
-
async function readAgents() {
|
|
365
|
-
const declaration = deps.agents();
|
|
366
|
-
if (declaration === undefined)
|
|
367
|
-
return;
|
|
368
|
-
const held = await deps.documents(declaration);
|
|
369
|
-
if ('pending' in held)
|
|
370
|
-
return;
|
|
371
|
-
const { documents } = held;
|
|
372
|
-
const names = new Map();
|
|
373
|
-
const retired = new Set();
|
|
374
|
-
for (const document of documents) {
|
|
375
|
-
if (document.type !== declaration.type)
|
|
376
|
-
continue;
|
|
377
|
-
const identity = document.fields?.[declaration.identity];
|
|
378
|
-
const name = document.fields?.[declaration.name];
|
|
379
|
-
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
380
|
-
continue;
|
|
381
|
-
names.set(identity, name);
|
|
382
|
-
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
383
|
-
if (ended !== undefined && ended !== null)
|
|
384
|
-
retired.add(identity);
|
|
385
|
-
}
|
|
386
|
-
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
387
|
-
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
388
|
-
return;
|
|
389
|
-
agentNames = names;
|
|
390
|
-
retiredAgents = retired;
|
|
391
|
-
if (named)
|
|
392
|
-
emitList();
|
|
393
|
-
emitAgents();
|
|
394
|
-
const ended = [...drafts.keys()].filter(retiredChat);
|
|
395
|
-
if (ended.length > 0)
|
|
396
|
-
await remove(ended);
|
|
397
|
-
}
|
|
398
481
|
function retiredChat(conversation) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
agentsRead = null;
|
|
404
|
-
});
|
|
405
|
-
return agentsRead;
|
|
482
|
+
if (!conversation.startsWith(NEW_CHAT))
|
|
483
|
+
return false;
|
|
484
|
+
const agent = conversation.slice(NEW_CHAT.length);
|
|
485
|
+
return [...listing.values()].some((entry) => entry.agent === agent && entry.agentRetired);
|
|
406
486
|
}
|
|
407
487
|
function live(conversation, change) {
|
|
488
|
+
const owed = unsent.get(conversation);
|
|
489
|
+
for (const fact of FACTS.filter((one) => one in change))
|
|
490
|
+
owed?.delete(fact);
|
|
408
491
|
setLive(conversation, { ...liveOf(conversation), ...change });
|
|
409
492
|
emit(conversation);
|
|
410
493
|
}
|
|
494
|
+
function openingEnded() {
|
|
495
|
+
const owed = [...unsent];
|
|
496
|
+
unsent.clear();
|
|
497
|
+
for (const [conversation, facts] of owed) {
|
|
498
|
+
const held = lives.get(conversation);
|
|
499
|
+
if (held === undefined || facts.size === 0)
|
|
500
|
+
continue;
|
|
501
|
+
setLive(conversation, {
|
|
502
|
+
turn: held.turn,
|
|
503
|
+
questions: facts.has('questions') ? QUIET.questions : held.questions,
|
|
504
|
+
process: facts.has('process') ? QUIET.process : held.process,
|
|
505
|
+
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
506
|
+
options: facts.has('options') ? QUIET.options : held.options,
|
|
507
|
+
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
508
|
+
subagents: facts.has('subagents') ? QUIET.subagents : held.subagents,
|
|
509
|
+
link: facts.has('link') ? QUIET.link : held.link,
|
|
510
|
+
deliveryUnknown: facts.has('deliveryUnknown')
|
|
511
|
+
? QUIET.deliveryUnknown
|
|
512
|
+
: held.deliveryUnknown,
|
|
513
|
+
});
|
|
514
|
+
emit(conversation);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
411
517
|
function relayed(conversation, turn, operation) {
|
|
412
518
|
const held = liveOf(conversation).turn;
|
|
413
519
|
const next = held?.turn === turn ? appliedTurn(held, operation) : startedTurn(turn, operation);
|
|
@@ -434,12 +540,6 @@ export function createConversationStore(deps) {
|
|
|
434
540
|
}
|
|
435
541
|
async function remove(leaving) {
|
|
436
542
|
await deps.durably(async (local) => {
|
|
437
|
-
const removed = [];
|
|
438
|
-
for (const conversation of leaving) {
|
|
439
|
-
for (const identity of await local.messageIdentities(conversation)) {
|
|
440
|
-
removed.push({ conversation, identity, text: null });
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
543
|
await local.dropConversations(leaving);
|
|
444
544
|
const changed = [];
|
|
445
545
|
for (const conversation of leaving) {
|
|
@@ -451,13 +551,28 @@ export function createConversationStore(deps) {
|
|
|
451
551
|
partials.delete(conversation);
|
|
452
552
|
drafts.delete(conversation);
|
|
453
553
|
behind.delete(conversation);
|
|
554
|
+
unsent.delete(conversation);
|
|
454
555
|
setLive(conversation, null);
|
|
455
556
|
await slide(local, conversation, null);
|
|
456
557
|
}
|
|
457
558
|
if (changed.length > 0)
|
|
458
|
-
deps.publish(conversationChangeSet(
|
|
559
|
+
deps.publish(conversationChangeSet(changed));
|
|
459
560
|
});
|
|
460
561
|
}
|
|
562
|
+
function missed(conversation) {
|
|
563
|
+
const read = reads.get(conversation);
|
|
564
|
+
const newest = listing.get(conversation)?.newest;
|
|
565
|
+
return (read === undefined ||
|
|
566
|
+
newest === undefined ||
|
|
567
|
+
partials.has(conversation) ||
|
|
568
|
+
(newest !== null && (read === null || newest > read)));
|
|
569
|
+
}
|
|
570
|
+
function noted(conversation, message) {
|
|
571
|
+
const entry = listing.get(conversation);
|
|
572
|
+
if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
|
|
573
|
+
return;
|
|
574
|
+
listing.set(conversation, { ...entry, newest: message.position });
|
|
575
|
+
}
|
|
461
576
|
function gap(conversation) {
|
|
462
577
|
gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
|
|
463
578
|
behind.add(conversation);
|
|
@@ -481,17 +596,18 @@ export function createConversationStore(deps) {
|
|
|
481
596
|
reads.set(conversation, message.position);
|
|
482
597
|
sealTurns(conversation, new Set([message.turn]));
|
|
483
598
|
await slide(local, conversation, [message]);
|
|
484
|
-
deps.publish(conversationChangeSet(
|
|
599
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
485
600
|
});
|
|
486
601
|
}
|
|
487
602
|
async function readHistories(conversations, ended) {
|
|
488
603
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
489
|
-
let
|
|
604
|
+
let waiting = conversations.map((conversation) => ({
|
|
490
605
|
conversation,
|
|
491
606
|
after: reads.get(conversation) ?? undefined,
|
|
492
607
|
}));
|
|
493
|
-
while (
|
|
494
|
-
const
|
|
608
|
+
while (waiting.length > 0) {
|
|
609
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
610
|
+
const result = await deps.history({
|
|
495
611
|
conversations: asking.map(({ conversation, after }) => ({
|
|
496
612
|
conversation,
|
|
497
613
|
...(after === undefined ? {} : { after }),
|
|
@@ -514,7 +630,7 @@ export function createConversationStore(deps) {
|
|
|
514
630
|
if (!following.some((next) => next.conversation === conversation))
|
|
515
631
|
ended(conversation);
|
|
516
632
|
}
|
|
517
|
-
|
|
633
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
518
634
|
}
|
|
519
635
|
return null;
|
|
520
636
|
}
|
|
@@ -557,7 +673,7 @@ export function createConversationStore(deps) {
|
|
|
557
673
|
behind.delete(conversation);
|
|
558
674
|
await slide(local, conversation, arriving);
|
|
559
675
|
if (arriving.length > 0 || sealing || whole) {
|
|
560
|
-
deps.publish(conversationChangeSet(
|
|
676
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
561
677
|
}
|
|
562
678
|
});
|
|
563
679
|
}
|
|
@@ -566,11 +682,8 @@ export function createConversationStore(deps) {
|
|
|
566
682
|
if (event.kind === 'gap') {
|
|
567
683
|
if (replicated.has(conversation))
|
|
568
684
|
gap(conversation);
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
return;
|
|
572
|
-
setLive(conversation, { ...QUIET, turn: held.turn });
|
|
573
|
-
emit(conversation);
|
|
685
|
+
if (lives.has(conversation))
|
|
686
|
+
unsent.set(conversation, new Set(FACTS));
|
|
574
687
|
return;
|
|
575
688
|
}
|
|
576
689
|
if (event.kind === 'turn') {
|
|
@@ -593,11 +706,35 @@ export function createConversationStore(deps) {
|
|
|
593
706
|
live(conversation, { options: structuredClone(event.options) });
|
|
594
707
|
return;
|
|
595
708
|
}
|
|
709
|
+
if (event.kind === 'starting') {
|
|
710
|
+
live(conversation, { starting: event.step });
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
if (event.kind === 'subagents') {
|
|
714
|
+
live(conversation, { subagents: structuredClone(event.subagents) });
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
if (event.kind === 'link') {
|
|
718
|
+
live(conversation, { link: { connected: event.connected } });
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
if (event.kind === 'deliveries') {
|
|
722
|
+
live(conversation, { deliveryUnknown: [...event.unknown] });
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
596
725
|
const arriving = acceptedMessage(event.message);
|
|
597
726
|
if (arriving === null)
|
|
598
727
|
return;
|
|
728
|
+
noted(conversation, arriving);
|
|
599
729
|
if (replicated.has(conversation)) {
|
|
600
|
-
|
|
730
|
+
if (deps.full()) {
|
|
731
|
+
gap(conversation);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
void keep(conversation, arriving).catch((error) => {
|
|
735
|
+
if (refusedForSpace(error))
|
|
736
|
+
gap(conversation);
|
|
737
|
+
});
|
|
601
738
|
return;
|
|
602
739
|
}
|
|
603
740
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -632,7 +769,6 @@ export function createConversationStore(deps) {
|
|
|
632
769
|
const blank = {
|
|
633
770
|
conversation: from,
|
|
634
771
|
text: '',
|
|
635
|
-
files: [],
|
|
636
772
|
revision: chatDraftRevision(),
|
|
637
773
|
};
|
|
638
774
|
const { moves: _answered, ...unsent } = held ?? blank;
|
|
@@ -642,7 +778,7 @@ export function createConversationStore(deps) {
|
|
|
642
778
|
drafts.set(from, left);
|
|
643
779
|
for (const one of taken)
|
|
644
780
|
drafts.set(to, one);
|
|
645
|
-
deps.publish(conversationChangeSet([
|
|
781
|
+
deps.publish(conversationChangeSet([from, to]));
|
|
646
782
|
});
|
|
647
783
|
}
|
|
648
784
|
function withDraft(conversation, next) {
|
|
@@ -651,7 +787,7 @@ export function createConversationStore(deps) {
|
|
|
651
787
|
if (following === undefined)
|
|
652
788
|
return;
|
|
653
789
|
await kept(local, conversation, following);
|
|
654
|
-
deps.publish(conversationChangeSet([
|
|
790
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
655
791
|
});
|
|
656
792
|
}
|
|
657
793
|
async function submitted(conversation, operation, draft) {
|
|
@@ -663,17 +799,12 @@ export function createConversationStore(deps) {
|
|
|
663
799
|
if (submission !== undefined)
|
|
664
800
|
return undefined;
|
|
665
801
|
const said = draft ?? current;
|
|
666
|
-
submission = {
|
|
667
|
-
operation,
|
|
668
|
-
text: said?.text ?? '',
|
|
669
|
-
files: [...(said?.files ?? [])],
|
|
670
|
-
turn: null,
|
|
671
|
-
};
|
|
802
|
+
submission = { operation, text: said?.text ?? '', turn: null };
|
|
672
803
|
return {
|
|
673
804
|
conversation,
|
|
674
805
|
...(draft === undefined || current === undefined
|
|
675
|
-
? { text: '',
|
|
676
|
-
: { text: current.text,
|
|
806
|
+
? { text: '', revision: chatDraftRevision() }
|
|
807
|
+
: { text: current.text, revision: current.revision }),
|
|
677
808
|
submitted: [...(current?.submitted ?? []), submission],
|
|
678
809
|
};
|
|
679
810
|
});
|
|
@@ -688,22 +819,21 @@ export function createConversationStore(deps) {
|
|
|
688
819
|
});
|
|
689
820
|
}
|
|
690
821
|
async function dispatched(conversation, submission) {
|
|
691
|
-
const dispatch = {};
|
|
822
|
+
const dispatch = { answered: false };
|
|
692
823
|
sending.set(submission.operation, dispatch);
|
|
693
824
|
try {
|
|
694
|
-
const
|
|
695
|
-
const result = await invoke('conversation.send', conversation, {
|
|
696
|
-
text: submission.text,
|
|
697
|
-
files,
|
|
825
|
+
const result = await invoke('conversations/send', conversation, {
|
|
698
826
|
operation_id: submission.operation,
|
|
827
|
+
text: submission.text,
|
|
699
828
|
});
|
|
829
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
700
830
|
if (result.kind === 'revoked-authorization')
|
|
701
831
|
return result;
|
|
702
832
|
if (result.kind !== 'action' && result.retryable) {
|
|
703
833
|
deps.unanswered();
|
|
704
834
|
return result;
|
|
705
835
|
}
|
|
706
|
-
const turn = answered(result, '
|
|
836
|
+
const turn = answered(result, 'message_id');
|
|
707
837
|
await withDraft(conversation, async (current, local) => {
|
|
708
838
|
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
709
839
|
if (current === undefined || held === undefined || held.turn !== null)
|
|
@@ -723,25 +853,34 @@ export function createConversationStore(deps) {
|
|
|
723
853
|
sending.delete(submission.operation);
|
|
724
854
|
}
|
|
725
855
|
}
|
|
726
|
-
function invoke(name, conversation, extra = {}) {
|
|
727
|
-
return deps.call(name, { conversation, ...extra });
|
|
856
|
+
function invoke(name, conversation, extra = { operation_id: changeBatchIdentity() }) {
|
|
857
|
+
return deps.call(name, { conversation_id: conversation, ...extra });
|
|
728
858
|
}
|
|
729
859
|
const surface = {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
860
|
+
list() {
|
|
861
|
+
return new Promise((settle) => {
|
|
862
|
+
const answer = (listed) => {
|
|
863
|
+
unlisted.delete(answer);
|
|
864
|
+
listWatchers.delete(answer);
|
|
865
|
+
settle(listed);
|
|
866
|
+
};
|
|
867
|
+
unlisted.add(answer);
|
|
868
|
+
learned();
|
|
869
|
+
});
|
|
733
870
|
},
|
|
734
871
|
async read(conversation, options = {}) {
|
|
735
|
-
const
|
|
872
|
+
const { text, ...windowed } = options;
|
|
873
|
+
const asked = askedOf(windowed);
|
|
874
|
+
const phrase = phraseOf(text);
|
|
736
875
|
return deps.durably(async (local) => {
|
|
737
|
-
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
738
|
-
const total = asked.total ? await local.messageCount(conversation) : null;
|
|
876
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before, phrase);
|
|
877
|
+
const total = asked.total ? await local.messageCount(conversation, phrase) : null;
|
|
739
878
|
return structuredClone(viewOf(conversation, messages, frameOf(asked, messages, more, total)));
|
|
740
879
|
});
|
|
741
880
|
},
|
|
742
881
|
async create(input) {
|
|
743
|
-
const result = await deps.call('
|
|
744
|
-
const conversation = answered(result, '
|
|
882
|
+
const result = await deps.call('conversations/create', input);
|
|
883
|
+
const conversation = answered(result, 'conversation_id');
|
|
745
884
|
if (conversation === null)
|
|
746
885
|
return result;
|
|
747
886
|
if (!listing.has(conversation))
|
|
@@ -752,8 +891,17 @@ export function createConversationStore(deps) {
|
|
|
752
891
|
return result;
|
|
753
892
|
},
|
|
754
893
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
894
|
+
if (deps.full())
|
|
895
|
+
return DURABLE_WRITE;
|
|
755
896
|
if (deps.online()) {
|
|
756
|
-
const
|
|
897
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
898
|
+
if (refusedForSpace(error))
|
|
899
|
+
return null;
|
|
900
|
+
throw error;
|
|
901
|
+
});
|
|
902
|
+
if (held === null)
|
|
903
|
+
return DURABLE_WRITE;
|
|
904
|
+
const { submission, earlier } = held;
|
|
757
905
|
if (!earlier || !deps.expired(operation))
|
|
758
906
|
return dispatched(conversation, submission);
|
|
759
907
|
await forgotten(conversation, submission);
|
|
@@ -762,33 +910,24 @@ export function createConversationStore(deps) {
|
|
|
762
910
|
if (draft !== undefined) {
|
|
763
911
|
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
764
912
|
? undefined
|
|
765
|
-
: returned(current ?? { conversation, text: '',
|
|
913
|
+
: returned(current ?? { conversation, text: '', revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
|
|
766
914
|
}
|
|
767
915
|
return OFFLINE;
|
|
768
916
|
},
|
|
769
917
|
answer(conversation, answer) {
|
|
770
|
-
return invoke('
|
|
918
|
+
return invoke('conversations/interaction/answer', conversation, {
|
|
919
|
+
operation_id: changeBatchIdentity(),
|
|
920
|
+
...answer,
|
|
921
|
+
});
|
|
771
922
|
},
|
|
772
923
|
interrupt(conversation) {
|
|
773
|
-
return invoke('
|
|
924
|
+
return invoke('conversations/interrupt', conversation);
|
|
774
925
|
},
|
|
775
926
|
kill(conversation) {
|
|
776
|
-
return invoke('
|
|
777
|
-
},
|
|
778
|
-
async cancel(conversation, turn) {
|
|
779
|
-
const result = await invoke('conversation.cancel', conversation, { turn });
|
|
780
|
-
if (result.kind !== 'action')
|
|
781
|
-
return result;
|
|
782
|
-
await withDraft(conversation, (current) => {
|
|
783
|
-
const held = current?.submitted?.find((one) => one.turn === turn);
|
|
784
|
-
if (current === undefined || held === undefined)
|
|
785
|
-
return undefined;
|
|
786
|
-
return returned(current, held, current.submitted.filter((one) => one !== held));
|
|
787
|
-
});
|
|
788
|
-
return result;
|
|
927
|
+
return invoke('conversations/kill', conversation);
|
|
789
928
|
},
|
|
790
929
|
delete(conversation) {
|
|
791
|
-
return invoke('
|
|
930
|
+
return invoke('conversations/delete', conversation);
|
|
792
931
|
},
|
|
793
932
|
};
|
|
794
933
|
const chatDraft = {
|
|
@@ -796,7 +935,6 @@ export function createConversationStore(deps) {
|
|
|
796
935
|
return withDraft(conversation, (current) => ({
|
|
797
936
|
conversation,
|
|
798
937
|
text: draft.text,
|
|
799
|
-
files: [...draft.files],
|
|
800
938
|
revision,
|
|
801
939
|
...(current === undefined ? {} : pending(current)),
|
|
802
940
|
}));
|
|
@@ -804,9 +942,7 @@ export function createConversationStore(deps) {
|
|
|
804
942
|
prepend(conversation, draft) {
|
|
805
943
|
return withDraft(conversation, (current) => ({
|
|
806
944
|
conversation,
|
|
807
|
-
...(current === undefined
|
|
808
|
-
? { text: draft.text, files: [...draft.files] }
|
|
809
|
-
: prepended(current, draft)),
|
|
945
|
+
...(current === undefined ? { text: draft.text } : prepended(current, draft)),
|
|
810
946
|
revision: chatDraftRevision(),
|
|
811
947
|
...(current === undefined ? {} : pending(current)),
|
|
812
948
|
}));
|
|
@@ -814,19 +950,21 @@ export function createConversationStore(deps) {
|
|
|
814
950
|
discard(conversation) {
|
|
815
951
|
return withDraft(conversation, (current) => current === undefined
|
|
816
952
|
? undefined
|
|
817
|
-
: {
|
|
818
|
-
conversation,
|
|
819
|
-
text: '',
|
|
820
|
-
files: [],
|
|
821
|
-
revision: chatDraftRevision(),
|
|
822
|
-
...pending(current),
|
|
823
|
-
});
|
|
953
|
+
: { conversation, text: '', revision: chatDraftRevision(), ...pending(current) });
|
|
824
954
|
},
|
|
825
955
|
};
|
|
826
956
|
return {
|
|
827
957
|
surface,
|
|
828
958
|
chatDraft,
|
|
829
|
-
hydrate(held, kept) {
|
|
959
|
+
hydrate(held, kept, list, cursor) {
|
|
960
|
+
if (list !== null && !listKnown) {
|
|
961
|
+
listing.clear();
|
|
962
|
+
for (const entry of list)
|
|
963
|
+
listing.set(entry.conversation, { ...entry });
|
|
964
|
+
listHeld = true;
|
|
965
|
+
listCursor = cursor;
|
|
966
|
+
deps.stream()?.hold(cursor);
|
|
967
|
+
}
|
|
830
968
|
stored.clear();
|
|
831
969
|
reads.clear();
|
|
832
970
|
partials.clear();
|
|
@@ -840,6 +978,8 @@ export function createConversationStore(deps) {
|
|
|
840
978
|
drafts.clear();
|
|
841
979
|
for (const record of kept)
|
|
842
980
|
drafts.set(record.conversation, record);
|
|
981
|
+
if (listHeld)
|
|
982
|
+
learned();
|
|
843
983
|
},
|
|
844
984
|
async reconcile() {
|
|
845
985
|
if (!listKnown)
|
|
@@ -851,7 +991,7 @@ export function createConversationStore(deps) {
|
|
|
851
991
|
!creations.has(conversation) &&
|
|
852
992
|
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
|
|
853
993
|
for (const conversation of named) {
|
|
854
|
-
if (!replicated.has(conversation))
|
|
994
|
+
if (!replicated.has(conversation) && missed(conversation))
|
|
855
995
|
behind.add(conversation);
|
|
856
996
|
}
|
|
857
997
|
replicated = named;
|
|
@@ -860,6 +1000,11 @@ export function createConversationStore(deps) {
|
|
|
860
1000
|
await remove(leaving);
|
|
861
1001
|
},
|
|
862
1002
|
async catchUp(progress) {
|
|
1003
|
+
if (deps.full()) {
|
|
1004
|
+
if (behind.size > 0)
|
|
1005
|
+
progress.complete = false;
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
863
1008
|
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
864
1009
|
const read = async (conversations) => {
|
|
865
1010
|
if (conversations.length === 0 || deps.closed())
|
|
@@ -908,12 +1053,11 @@ export function createConversationStore(deps) {
|
|
|
908
1053
|
known() {
|
|
909
1054
|
return listKnown;
|
|
910
1055
|
},
|
|
911
|
-
reconnected() {
|
|
912
|
-
for (const conversation of replicated)
|
|
913
|
-
gap(conversation);
|
|
914
|
-
},
|
|
915
1056
|
reopened() {
|
|
916
|
-
|
|
1057
|
+
relisting = null;
|
|
1058
|
+
for (const [operation, dispatch] of sending)
|
|
1059
|
+
if (!dispatch.answered)
|
|
1060
|
+
sending.delete(operation);
|
|
917
1061
|
},
|
|
918
1062
|
lost() {
|
|
919
1063
|
catching.clear();
|
|
@@ -932,15 +1076,15 @@ export function createConversationStore(deps) {
|
|
|
932
1076
|
views.set(key, view);
|
|
933
1077
|
const watcher = { notify: deliver, ready: false };
|
|
934
1078
|
view.watchers.add(watcher);
|
|
935
|
-
|
|
936
|
-
|
|
1079
|
+
const reading = new AbortController();
|
|
1080
|
+
void untilAnswered(() => deps.durably(async (local) => {
|
|
937
1081
|
if (view.window !== null)
|
|
938
1082
|
return;
|
|
939
1083
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
940
1084
|
view.window = messages;
|
|
941
1085
|
view.more = more;
|
|
942
1086
|
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
943
|
-
})
|
|
1087
|
+
}), reading.signal)
|
|
944
1088
|
.then(() => {
|
|
945
1089
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
946
1090
|
return;
|
|
@@ -950,6 +1094,7 @@ export function createConversationStore(deps) {
|
|
|
950
1094
|
})
|
|
951
1095
|
.catch(() => { });
|
|
952
1096
|
return () => {
|
|
1097
|
+
reading.abort();
|
|
953
1098
|
if (!view.watchers.delete(watcher))
|
|
954
1099
|
return;
|
|
955
1100
|
if (view.watchers.size === 0)
|
|
@@ -957,75 +1102,88 @@ export function createConversationStore(deps) {
|
|
|
957
1102
|
};
|
|
958
1103
|
},
|
|
959
1104
|
watchList(deliver) {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
if (!deps.closed() && listWatchers.has(deliver))
|
|
963
|
-
deliver(entries());
|
|
964
|
-
});
|
|
1105
|
+
unlisted.add(deliver);
|
|
1106
|
+
learned();
|
|
965
1107
|
return () => {
|
|
1108
|
+
unlisted.delete(deliver);
|
|
966
1109
|
listWatchers.delete(deliver);
|
|
967
1110
|
};
|
|
968
1111
|
},
|
|
969
1112
|
watchAgents(deliver) {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
deliver(agents());
|
|
974
|
-
});
|
|
1113
|
+
unnamed.add(deliver);
|
|
1114
|
+
learned();
|
|
1115
|
+
readAgents();
|
|
975
1116
|
return () => {
|
|
1117
|
+
unnamed.delete(deliver);
|
|
976
1118
|
agentWatchers.delete(deliver);
|
|
977
1119
|
};
|
|
978
1120
|
},
|
|
1121
|
+
learned,
|
|
979
1122
|
changed(set) {
|
|
980
1123
|
for (const conversation of set.conversations)
|
|
981
1124
|
emit(conversation);
|
|
982
|
-
const declaration = deps.agents();
|
|
983
|
-
if (declaration !== undefined &&
|
|
984
|
-
set.documents.some((change) => change.locator === declaration.locator)) {
|
|
985
|
-
agentsRead = readAgents().catch(() => {
|
|
986
|
-
agentsRead = null;
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
1125
|
},
|
|
990
1126
|
receive(event) {
|
|
991
1127
|
if (deps.closed())
|
|
992
1128
|
return false;
|
|
993
1129
|
if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted') {
|
|
994
1130
|
if (event.kind === 'list') {
|
|
995
|
-
|
|
1131
|
+
if (event.whole)
|
|
1132
|
+
relisting ??= new Map();
|
|
996
1133
|
for (const entry of event.entries) {
|
|
997
|
-
|
|
998
|
-
|
|
1134
|
+
if (relisting === null)
|
|
1135
|
+
listed(entry);
|
|
1136
|
+
else
|
|
1137
|
+
relisting.set(entry.conversation, { ...entry });
|
|
1138
|
+
}
|
|
1139
|
+
if (event.more)
|
|
1140
|
+
return false;
|
|
1141
|
+
if (relisting !== null) {
|
|
1142
|
+
listing.clear();
|
|
1143
|
+
for (const entry of relisting.values())
|
|
1144
|
+
listed(entry);
|
|
1145
|
+
relisting = null;
|
|
999
1146
|
}
|
|
1147
|
+
listCursor = event.cursor;
|
|
1148
|
+
deps.stream()?.hold(event.cursor);
|
|
1000
1149
|
listKnown = true;
|
|
1150
|
+
for (const conversation of replicated) {
|
|
1151
|
+
if (!listing.has(conversation))
|
|
1152
|
+
continue;
|
|
1153
|
+
if (!missed(conversation))
|
|
1154
|
+
behind.delete(conversation);
|
|
1155
|
+
else if (!behind.has(conversation))
|
|
1156
|
+
gap(conversation);
|
|
1157
|
+
}
|
|
1158
|
+
openingEnded();
|
|
1001
1159
|
}
|
|
1002
1160
|
else if (event.kind === 'listed') {
|
|
1003
|
-
|
|
1004
|
-
|
|
1161
|
+
listed(event.entry);
|
|
1162
|
+
relisting?.set(event.entry.conversation, { ...event.entry });
|
|
1005
1163
|
}
|
|
1006
1164
|
else {
|
|
1007
1165
|
listing.delete(event.conversation);
|
|
1166
|
+
relisting?.delete(event.conversation);
|
|
1008
1167
|
}
|
|
1168
|
+
keepList();
|
|
1009
1169
|
emitList();
|
|
1010
|
-
return (event.kind !== 'list' &&
|
|
1170
|
+
return ((event.kind !== 'list' &&
|
|
1011
1171
|
listKnown &&
|
|
1012
1172
|
(listing.size !== replicated.size ||
|
|
1013
|
-
[...listing.keys()].some((conversation) => !replicated.has(conversation))))
|
|
1173
|
+
[...listing.keys()].some((conversation) => !replicated.has(conversation)))) ||
|
|
1174
|
+
(listKnown && [...drafts.keys()].some(retiredChat)));
|
|
1014
1175
|
}
|
|
1015
1176
|
heard(event);
|
|
1016
1177
|
return false;
|
|
1017
1178
|
},
|
|
1018
|
-
searchable() {
|
|
1019
|
-
return [...(listKnown ? listing.keys() : stored)].sort();
|
|
1020
|
-
},
|
|
1021
|
-
acquired(conversation) {
|
|
1022
|
-
return reads.has(conversation) && !partials.has(conversation);
|
|
1023
|
-
},
|
|
1024
1179
|
close() {
|
|
1025
1180
|
views.clear();
|
|
1026
1181
|
lives.clear();
|
|
1182
|
+
unsent.clear();
|
|
1027
1183
|
listWatchers.clear();
|
|
1184
|
+
unlisted.clear();
|
|
1028
1185
|
agentWatchers.clear();
|
|
1186
|
+
unnamed.clear();
|
|
1029
1187
|
},
|
|
1030
1188
|
};
|
|
1031
1189
|
}
|