@agentshouse/mdruntime 0.1.0-c91a238f9703e → 0.1.0-c9260f23cccf4
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 +18 -15
- package/dist/adapter.d.ts +72 -37
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/binary.d.ts +0 -5
- package/dist/binary.d.ts.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/bootstrap.d.ts +26 -8
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +174 -102
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +68 -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 +9 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +80 -6
- package/dist/collection.d.ts +11 -19
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +53 -289
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +773 -0
- package/dist/connection.d.ts +18 -12
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2729 -1085
- package/dist/conversation.d.ts +14 -6
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +263 -94
- 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 +3 -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 +18 -23
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/fulltext.d.ts +27 -0
- package/dist/fulltext.d.ts.map +1 -0
- package/dist/fulltext.js +370 -0
- package/dist/host.d.ts +4 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +45 -18
- 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 +12 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +124 -0
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +208 -0
- package/dist/memory.d.ts +4 -4
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +67 -29
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +90 -0
- package/dist/model.d.ts +6 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -1
- 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 -5
- 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/query.d.ts +11 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +13 -1
- package/dist/reach.d.ts +13 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +201 -72
- package/dist/readiness.d.ts +19 -9
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +6 -6
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +10 -17
- package/dist/recovery.d.ts +2 -2
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +8 -7
- package/dist/refresh.d.ts +15 -14
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +113 -56
- package/dist/replica.d.ts +55 -36
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +280 -186
- package/dist/room-draft.d.ts +21 -3
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +102 -28
- package/dist/rows.d.ts +38 -31
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +173 -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 +11 -43
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +0 -213
- package/dist/shared.d.ts +8 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +129 -66
- package/dist/status.d.ts +5 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +85 -93
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +323 -687
- package/dist/stored.d.ts +135 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +569 -0
- package/dist/tables.d.ts +352 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +621 -0
- 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 +30 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +162 -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 +17 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +5 -1
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +156 -0
- 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/conversation.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
6
|
import { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
|
|
@@ -10,7 +10,19 @@ const QUIET = {
|
|
|
10
10
|
process: null,
|
|
11
11
|
commands: [],
|
|
12
12
|
options: [],
|
|
13
|
+
starting: null,
|
|
14
|
+
link: null,
|
|
15
|
+
deliveryUnknown: [],
|
|
13
16
|
};
|
|
17
|
+
const FACTS = [
|
|
18
|
+
'questions',
|
|
19
|
+
'process',
|
|
20
|
+
'commands',
|
|
21
|
+
'options',
|
|
22
|
+
'starting',
|
|
23
|
+
'link',
|
|
24
|
+
'deliveryUnknown',
|
|
25
|
+
];
|
|
14
26
|
export function unheldView(conversation) {
|
|
15
27
|
return {
|
|
16
28
|
conversation,
|
|
@@ -20,19 +32,25 @@ export function unheldView(conversation) {
|
|
|
20
32
|
process: null,
|
|
21
33
|
commands: [],
|
|
22
34
|
options: [],
|
|
35
|
+
starting: null,
|
|
36
|
+
link: null,
|
|
37
|
+
deliveryUnknown: [],
|
|
23
38
|
chatDraft: null,
|
|
24
39
|
};
|
|
25
40
|
}
|
|
26
41
|
export const SESSION_STARTED = 'Session started';
|
|
27
42
|
const NEW_CHAT = 'new:';
|
|
43
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
28
44
|
export function newChat(agent) {
|
|
29
45
|
return `${NEW_CHAT}${agent}`;
|
|
30
46
|
}
|
|
31
47
|
function creationOf(input) {
|
|
32
48
|
if (typeof input !== 'object' || input === null)
|
|
33
49
|
return null;
|
|
34
|
-
const { agent_id: agent, operation_id: operation } = input;
|
|
35
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
50
|
+
const { agent_id: agent, operation_id: operation, replaces, } = input;
|
|
51
|
+
return typeof agent === 'string' && typeof operation === 'string' && replaces === undefined
|
|
52
|
+
? { agent, operation }
|
|
53
|
+
: null;
|
|
36
54
|
}
|
|
37
55
|
function startedTurn(turn, operation) {
|
|
38
56
|
if (operation.op === 'begin')
|
|
@@ -192,8 +210,14 @@ function askedOf(options) {
|
|
|
192
210
|
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
193
211
|
}
|
|
194
212
|
const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
|
|
213
|
+
const DURABLE_WRITE = {
|
|
214
|
+
kind: 'rejected',
|
|
215
|
+
code: 'durable-write',
|
|
216
|
+
fields: {},
|
|
217
|
+
retryable: true,
|
|
218
|
+
};
|
|
195
219
|
function unwritten(draft) {
|
|
196
|
-
return draft.text === ''
|
|
220
|
+
return draft.text === '';
|
|
197
221
|
}
|
|
198
222
|
function pending(draft) {
|
|
199
223
|
return {
|
|
@@ -209,10 +233,7 @@ function withSubmitted(draft, submitted) {
|
|
|
209
233
|
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
210
234
|
}
|
|
211
235
|
function prepended(draft, said) {
|
|
212
|
-
return {
|
|
213
|
-
text: [said.text, draft.text].filter((one) => one !== '').join('\n'),
|
|
214
|
-
files: [...said.files, ...draft.files],
|
|
215
|
-
};
|
|
236
|
+
return { text: [said.text, draft.text].filter((one) => one !== '').join('\n') };
|
|
216
237
|
}
|
|
217
238
|
function returned(draft, submission, others) {
|
|
218
239
|
return withSubmitted({
|
|
@@ -231,15 +252,22 @@ export function createConversationStore(deps) {
|
|
|
231
252
|
const catching = new Map();
|
|
232
253
|
const gaps = new Map();
|
|
233
254
|
const lives = new Map();
|
|
255
|
+
const unsent = new Map();
|
|
234
256
|
const views = new Map();
|
|
235
257
|
const listing = new Map();
|
|
236
258
|
const creations = new Set();
|
|
237
259
|
const listWatchers = new Set();
|
|
260
|
+
const unlisted = new Set();
|
|
238
261
|
let listKnown = false;
|
|
262
|
+
let listHeld = false;
|
|
263
|
+
let listKept = false;
|
|
239
264
|
const agentWatchers = new Set();
|
|
265
|
+
const unnamed = new Set();
|
|
266
|
+
let agentsKnown = false;
|
|
240
267
|
let agentNames = new Map();
|
|
241
268
|
let retiredAgents = new Set();
|
|
242
269
|
let agentsRead = null;
|
|
270
|
+
let agentsFrom;
|
|
243
271
|
let replicated = new Set();
|
|
244
272
|
let handedReplicated;
|
|
245
273
|
function liveOf(conversation) {
|
|
@@ -262,9 +290,12 @@ export function createConversationStore(deps) {
|
|
|
262
290
|
process: facts.process === null ? null : { ...facts.process },
|
|
263
291
|
commands: structuredClone(facts.commands),
|
|
264
292
|
options: structuredClone(facts.options),
|
|
293
|
+
starting: facts.starting,
|
|
294
|
+
link: facts.link === null ? null : { ...facts.link },
|
|
295
|
+
deliveryUnknown: [...facts.deliveryUnknown],
|
|
265
296
|
chatDraft: draft === undefined || unwritten(draft)
|
|
266
297
|
? null
|
|
267
|
-
: { text: draft.text,
|
|
298
|
+
: { text: draft.text, revision: draft.revision },
|
|
268
299
|
};
|
|
269
300
|
}
|
|
270
301
|
function emit(conversation) {
|
|
@@ -306,9 +337,6 @@ export function createConversationStore(deps) {
|
|
|
306
337
|
}
|
|
307
338
|
}
|
|
308
339
|
}
|
|
309
|
-
function changesOf(conversation, arriving) {
|
|
310
|
-
return arriving.map(({ identity, text }) => ({ conversation, identity, text }));
|
|
311
|
-
}
|
|
312
340
|
function stateOf(conversation) {
|
|
313
341
|
const facts = liveOf(conversation);
|
|
314
342
|
if (facts.questions.length > 0)
|
|
@@ -323,16 +351,58 @@ export function createConversationStore(deps) {
|
|
|
323
351
|
created: entry.created,
|
|
324
352
|
finished: entry.finished,
|
|
325
353
|
outcome: entry.outcome,
|
|
354
|
+
waiting: entry.waiting,
|
|
326
355
|
state: stateOf(entry.conversation),
|
|
327
356
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
328
357
|
}));
|
|
329
358
|
}
|
|
359
|
+
function keepList() {
|
|
360
|
+
if (!listKnown || listKept)
|
|
361
|
+
return;
|
|
362
|
+
listKept = true;
|
|
363
|
+
queueMicrotask(() => {
|
|
364
|
+
listKept = false;
|
|
365
|
+
if (deps.closed())
|
|
366
|
+
return;
|
|
367
|
+
const entries = [...listing.values()];
|
|
368
|
+
void deps.durably((local) => local.fact('conversationList', entries)).catch(() => { });
|
|
369
|
+
});
|
|
370
|
+
}
|
|
330
371
|
function emitList() {
|
|
331
|
-
if (deps.closed()
|
|
372
|
+
if (deps.closed())
|
|
332
373
|
return;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
watcher
|
|
374
|
+
if (listWatchers.size > 0) {
|
|
375
|
+
const value = entries();
|
|
376
|
+
for (const watcher of listWatchers)
|
|
377
|
+
watcher(value);
|
|
378
|
+
}
|
|
379
|
+
learned();
|
|
380
|
+
}
|
|
381
|
+
function unlearnable() {
|
|
382
|
+
return !deps.online() || (deps.listed() && deps.agents() === undefined);
|
|
383
|
+
}
|
|
384
|
+
function learned() {
|
|
385
|
+
if (deps.closed())
|
|
386
|
+
return;
|
|
387
|
+
const named = agentsKnown || unlearnable();
|
|
388
|
+
if (unlisted.size > 0 &&
|
|
389
|
+
named &&
|
|
390
|
+
(listKnown || listHeld || deps.stream() === undefined || unlearnable())) {
|
|
391
|
+
const value = entries();
|
|
392
|
+
for (const watcher of [...unlisted]) {
|
|
393
|
+
unlisted.delete(watcher);
|
|
394
|
+
listWatchers.add(watcher);
|
|
395
|
+
watcher(value);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (unnamed.size > 0 && named) {
|
|
399
|
+
const value = agents();
|
|
400
|
+
for (const watcher of [...unnamed]) {
|
|
401
|
+
unnamed.delete(watcher);
|
|
402
|
+
agentWatchers.add(watcher);
|
|
403
|
+
watcher(value);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
336
406
|
}
|
|
337
407
|
function agents() {
|
|
338
408
|
return [...agentNames]
|
|
@@ -363,34 +433,46 @@ export function createConversationStore(deps) {
|
|
|
363
433
|
}
|
|
364
434
|
async function readAgents() {
|
|
365
435
|
const declaration = deps.agents();
|
|
436
|
+
agentsFrom = JSON.stringify(declaration);
|
|
366
437
|
if (declaration === undefined)
|
|
367
438
|
return;
|
|
368
|
-
const held = await deps.documents(declaration);
|
|
369
|
-
if ('pending' in held)
|
|
370
|
-
return;
|
|
371
|
-
const { documents } = held;
|
|
372
439
|
const names = new Map();
|
|
373
440
|
const retired = new Set();
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
441
|
+
let covered = null;
|
|
442
|
+
for (let after;;) {
|
|
443
|
+
const read = await deps.documents(declaration, after);
|
|
444
|
+
if ('pending' in read)
|
|
445
|
+
return;
|
|
446
|
+
const coverage = JSON.stringify(read.coverage);
|
|
447
|
+
if (covered !== null && coverage !== covered)
|
|
448
|
+
return readAgents();
|
|
449
|
+
covered = coverage;
|
|
450
|
+
for (const document of read.documents) {
|
|
451
|
+
const identity = document.fields?.[declaration.identity];
|
|
452
|
+
const name = document.fields?.[declaration.name];
|
|
453
|
+
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
454
|
+
continue;
|
|
455
|
+
names.set(identity, name);
|
|
456
|
+
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
457
|
+
if (ended !== undefined && ended !== null)
|
|
458
|
+
retired.add(identity);
|
|
459
|
+
}
|
|
460
|
+
if (read.next === undefined)
|
|
461
|
+
break;
|
|
462
|
+
after = read.next;
|
|
385
463
|
}
|
|
464
|
+
agentsKnown = true;
|
|
386
465
|
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
387
|
-
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
466
|
+
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents])) {
|
|
467
|
+
learned();
|
|
388
468
|
return;
|
|
469
|
+
}
|
|
389
470
|
agentNames = names;
|
|
390
471
|
retiredAgents = retired;
|
|
472
|
+
emitAgents();
|
|
391
473
|
if (named)
|
|
392
474
|
emitList();
|
|
393
|
-
|
|
475
|
+
learned();
|
|
394
476
|
const ended = [...drafts.keys()].filter(retiredChat);
|
|
395
477
|
if (ended.length > 0)
|
|
396
478
|
await remove(ended);
|
|
@@ -405,9 +487,34 @@ export function createConversationStore(deps) {
|
|
|
405
487
|
return agentsRead;
|
|
406
488
|
}
|
|
407
489
|
function live(conversation, change) {
|
|
490
|
+
const owed = unsent.get(conversation);
|
|
491
|
+
for (const fact of FACTS.filter((one) => one in change))
|
|
492
|
+
owed?.delete(fact);
|
|
408
493
|
setLive(conversation, { ...liveOf(conversation), ...change });
|
|
409
494
|
emit(conversation);
|
|
410
495
|
}
|
|
496
|
+
function openingEnded() {
|
|
497
|
+
const owed = [...unsent];
|
|
498
|
+
unsent.clear();
|
|
499
|
+
for (const [conversation, facts] of owed) {
|
|
500
|
+
const held = lives.get(conversation);
|
|
501
|
+
if (held === undefined || facts.size === 0)
|
|
502
|
+
continue;
|
|
503
|
+
setLive(conversation, {
|
|
504
|
+
turn: held.turn,
|
|
505
|
+
questions: facts.has('questions') ? QUIET.questions : held.questions,
|
|
506
|
+
process: facts.has('process') ? QUIET.process : held.process,
|
|
507
|
+
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
508
|
+
options: facts.has('options') ? QUIET.options : held.options,
|
|
509
|
+
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
510
|
+
link: facts.has('link') ? QUIET.link : held.link,
|
|
511
|
+
deliveryUnknown: facts.has('deliveryUnknown')
|
|
512
|
+
? QUIET.deliveryUnknown
|
|
513
|
+
: held.deliveryUnknown,
|
|
514
|
+
});
|
|
515
|
+
emit(conversation);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
411
518
|
function relayed(conversation, turn, operation) {
|
|
412
519
|
const held = liveOf(conversation).turn;
|
|
413
520
|
const next = held?.turn === turn ? appliedTurn(held, operation) : startedTurn(turn, operation);
|
|
@@ -434,12 +541,6 @@ export function createConversationStore(deps) {
|
|
|
434
541
|
}
|
|
435
542
|
async function remove(leaving) {
|
|
436
543
|
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
544
|
await local.dropConversations(leaving);
|
|
444
545
|
const changed = [];
|
|
445
546
|
for (const conversation of leaving) {
|
|
@@ -451,13 +552,28 @@ export function createConversationStore(deps) {
|
|
|
451
552
|
partials.delete(conversation);
|
|
452
553
|
drafts.delete(conversation);
|
|
453
554
|
behind.delete(conversation);
|
|
555
|
+
unsent.delete(conversation);
|
|
454
556
|
setLive(conversation, null);
|
|
455
557
|
await slide(local, conversation, null);
|
|
456
558
|
}
|
|
457
559
|
if (changed.length > 0)
|
|
458
|
-
deps.publish(conversationChangeSet(
|
|
560
|
+
deps.publish(conversationChangeSet(changed));
|
|
459
561
|
});
|
|
460
562
|
}
|
|
563
|
+
function missed(conversation) {
|
|
564
|
+
const read = reads.get(conversation);
|
|
565
|
+
const newest = listing.get(conversation)?.newest;
|
|
566
|
+
return (read === undefined ||
|
|
567
|
+
newest === undefined ||
|
|
568
|
+
partials.has(conversation) ||
|
|
569
|
+
(newest !== null && (read === null || newest > read)));
|
|
570
|
+
}
|
|
571
|
+
function noted(conversation, message) {
|
|
572
|
+
const entry = listing.get(conversation);
|
|
573
|
+
if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
|
|
574
|
+
return;
|
|
575
|
+
listing.set(conversation, { ...entry, newest: message.position });
|
|
576
|
+
}
|
|
461
577
|
function gap(conversation) {
|
|
462
578
|
gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
|
|
463
579
|
behind.add(conversation);
|
|
@@ -481,16 +597,17 @@ export function createConversationStore(deps) {
|
|
|
481
597
|
reads.set(conversation, message.position);
|
|
482
598
|
sealTurns(conversation, new Set([message.turn]));
|
|
483
599
|
await slide(local, conversation, [message]);
|
|
484
|
-
deps.publish(conversationChangeSet(
|
|
600
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
485
601
|
});
|
|
486
602
|
}
|
|
487
603
|
async function readHistories(conversations, ended) {
|
|
488
604
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
489
|
-
let
|
|
605
|
+
let waiting = conversations.map((conversation) => ({
|
|
490
606
|
conversation,
|
|
491
607
|
after: reads.get(conversation) ?? undefined,
|
|
492
608
|
}));
|
|
493
|
-
while (
|
|
609
|
+
while (waiting.length > 0) {
|
|
610
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
494
611
|
const result = await deps.call('conversation.history', {
|
|
495
612
|
conversations: asking.map(({ conversation, after }) => ({
|
|
496
613
|
conversation,
|
|
@@ -514,7 +631,7 @@ export function createConversationStore(deps) {
|
|
|
514
631
|
if (!following.some((next) => next.conversation === conversation))
|
|
515
632
|
ended(conversation);
|
|
516
633
|
}
|
|
517
|
-
|
|
634
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
518
635
|
}
|
|
519
636
|
return null;
|
|
520
637
|
}
|
|
@@ -557,7 +674,7 @@ export function createConversationStore(deps) {
|
|
|
557
674
|
behind.delete(conversation);
|
|
558
675
|
await slide(local, conversation, arriving);
|
|
559
676
|
if (arriving.length > 0 || sealing || whole) {
|
|
560
|
-
deps.publish(conversationChangeSet(
|
|
677
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
561
678
|
}
|
|
562
679
|
});
|
|
563
680
|
}
|
|
@@ -566,11 +683,8 @@ export function createConversationStore(deps) {
|
|
|
566
683
|
if (event.kind === 'gap') {
|
|
567
684
|
if (replicated.has(conversation))
|
|
568
685
|
gap(conversation);
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
return;
|
|
572
|
-
setLive(conversation, { ...QUIET, turn: held.turn });
|
|
573
|
-
emit(conversation);
|
|
686
|
+
if (lives.has(conversation))
|
|
687
|
+
unsent.set(conversation, new Set(FACTS));
|
|
574
688
|
return;
|
|
575
689
|
}
|
|
576
690
|
if (event.kind === 'turn') {
|
|
@@ -593,11 +707,31 @@ export function createConversationStore(deps) {
|
|
|
593
707
|
live(conversation, { options: structuredClone(event.options) });
|
|
594
708
|
return;
|
|
595
709
|
}
|
|
710
|
+
if (event.kind === 'starting') {
|
|
711
|
+
live(conversation, { starting: event.step });
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (event.kind === 'link') {
|
|
715
|
+
live(conversation, { link: { connected: event.connected } });
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
if (event.kind === 'deliveries') {
|
|
719
|
+
live(conversation, { deliveryUnknown: [...event.unknown] });
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
596
722
|
const arriving = acceptedMessage(event.message);
|
|
597
723
|
if (arriving === null)
|
|
598
724
|
return;
|
|
725
|
+
noted(conversation, arriving);
|
|
599
726
|
if (replicated.has(conversation)) {
|
|
600
|
-
|
|
727
|
+
if (deps.full()) {
|
|
728
|
+
gap(conversation);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
void keep(conversation, arriving).catch((error) => {
|
|
732
|
+
if (refusedForSpace(error))
|
|
733
|
+
gap(conversation);
|
|
734
|
+
});
|
|
601
735
|
return;
|
|
602
736
|
}
|
|
603
737
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -632,7 +766,6 @@ export function createConversationStore(deps) {
|
|
|
632
766
|
const blank = {
|
|
633
767
|
conversation: from,
|
|
634
768
|
text: '',
|
|
635
|
-
files: [],
|
|
636
769
|
revision: chatDraftRevision(),
|
|
637
770
|
};
|
|
638
771
|
const { moves: _answered, ...unsent } = held ?? blank;
|
|
@@ -642,7 +775,7 @@ export function createConversationStore(deps) {
|
|
|
642
775
|
drafts.set(from, left);
|
|
643
776
|
for (const one of taken)
|
|
644
777
|
drafts.set(to, one);
|
|
645
|
-
deps.publish(conversationChangeSet([
|
|
778
|
+
deps.publish(conversationChangeSet([from, to]));
|
|
646
779
|
});
|
|
647
780
|
}
|
|
648
781
|
function withDraft(conversation, next) {
|
|
@@ -651,7 +784,7 @@ export function createConversationStore(deps) {
|
|
|
651
784
|
if (following === undefined)
|
|
652
785
|
return;
|
|
653
786
|
await kept(local, conversation, following);
|
|
654
|
-
deps.publish(conversationChangeSet([
|
|
787
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
655
788
|
});
|
|
656
789
|
}
|
|
657
790
|
async function submitted(conversation, operation, draft) {
|
|
@@ -663,17 +796,12 @@ export function createConversationStore(deps) {
|
|
|
663
796
|
if (submission !== undefined)
|
|
664
797
|
return undefined;
|
|
665
798
|
const said = draft ?? current;
|
|
666
|
-
submission = {
|
|
667
|
-
operation,
|
|
668
|
-
text: said?.text ?? '',
|
|
669
|
-
files: [...(said?.files ?? [])],
|
|
670
|
-
turn: null,
|
|
671
|
-
};
|
|
799
|
+
submission = { operation, text: said?.text ?? '', turn: null };
|
|
672
800
|
return {
|
|
673
801
|
conversation,
|
|
674
802
|
...(draft === undefined || current === undefined
|
|
675
|
-
? { text: '',
|
|
676
|
-
: { text: current.text,
|
|
803
|
+
? { text: '', revision: chatDraftRevision() }
|
|
804
|
+
: { text: current.text, revision: current.revision }),
|
|
677
805
|
submitted: [...(current?.submitted ?? []), submission],
|
|
678
806
|
};
|
|
679
807
|
});
|
|
@@ -688,15 +816,14 @@ export function createConversationStore(deps) {
|
|
|
688
816
|
});
|
|
689
817
|
}
|
|
690
818
|
async function dispatched(conversation, submission) {
|
|
691
|
-
const dispatch = {};
|
|
819
|
+
const dispatch = { answered: false };
|
|
692
820
|
sending.set(submission.operation, dispatch);
|
|
693
821
|
try {
|
|
694
|
-
const files = await Promise.all(submission.files.map(async (file) => ({ ...(await declaredFile(file)), blob: file.blob })));
|
|
695
822
|
const result = await invoke('conversation.send', conversation, {
|
|
696
823
|
text: submission.text,
|
|
697
|
-
files,
|
|
698
824
|
operation_id: submission.operation,
|
|
699
825
|
});
|
|
826
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
700
827
|
if (result.kind === 'revoked-authorization')
|
|
701
828
|
return result;
|
|
702
829
|
if (result.kind !== 'action' && result.retryable) {
|
|
@@ -729,7 +856,15 @@ export function createConversationStore(deps) {
|
|
|
729
856
|
const surface = {
|
|
730
857
|
async list() {
|
|
731
858
|
await agentsReady();
|
|
732
|
-
return
|
|
859
|
+
return new Promise((settle) => {
|
|
860
|
+
const answer = (listed) => {
|
|
861
|
+
unlisted.delete(answer);
|
|
862
|
+
listWatchers.delete(answer);
|
|
863
|
+
settle(listed);
|
|
864
|
+
};
|
|
865
|
+
unlisted.add(answer);
|
|
866
|
+
learned();
|
|
867
|
+
});
|
|
733
868
|
},
|
|
734
869
|
async read(conversation, options = {}) {
|
|
735
870
|
const asked = askedOf(options);
|
|
@@ -752,8 +887,17 @@ export function createConversationStore(deps) {
|
|
|
752
887
|
return result;
|
|
753
888
|
},
|
|
754
889
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
890
|
+
if (deps.full())
|
|
891
|
+
return DURABLE_WRITE;
|
|
755
892
|
if (deps.online()) {
|
|
756
|
-
const
|
|
893
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
894
|
+
if (refusedForSpace(error))
|
|
895
|
+
return null;
|
|
896
|
+
throw error;
|
|
897
|
+
});
|
|
898
|
+
if (held === null)
|
|
899
|
+
return DURABLE_WRITE;
|
|
900
|
+
const { submission, earlier } = held;
|
|
757
901
|
if (!earlier || !deps.expired(operation))
|
|
758
902
|
return dispatched(conversation, submission);
|
|
759
903
|
await forgotten(conversation, submission);
|
|
@@ -762,7 +906,7 @@ export function createConversationStore(deps) {
|
|
|
762
906
|
if (draft !== undefined) {
|
|
763
907
|
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
764
908
|
? undefined
|
|
765
|
-
: returned(current ?? { conversation, text: '',
|
|
909
|
+
: returned(current ?? { conversation, text: '', revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
|
|
766
910
|
}
|
|
767
911
|
return OFFLINE;
|
|
768
912
|
},
|
|
@@ -796,7 +940,6 @@ export function createConversationStore(deps) {
|
|
|
796
940
|
return withDraft(conversation, (current) => ({
|
|
797
941
|
conversation,
|
|
798
942
|
text: draft.text,
|
|
799
|
-
files: [...draft.files],
|
|
800
943
|
revision,
|
|
801
944
|
...(current === undefined ? {} : pending(current)),
|
|
802
945
|
}));
|
|
@@ -804,9 +947,7 @@ export function createConversationStore(deps) {
|
|
|
804
947
|
prepend(conversation, draft) {
|
|
805
948
|
return withDraft(conversation, (current) => ({
|
|
806
949
|
conversation,
|
|
807
|
-
...(current === undefined
|
|
808
|
-
? { text: draft.text, files: [...draft.files] }
|
|
809
|
-
: prepended(current, draft)),
|
|
950
|
+
...(current === undefined ? { text: draft.text } : prepended(current, draft)),
|
|
810
951
|
revision: chatDraftRevision(),
|
|
811
952
|
...(current === undefined ? {} : pending(current)),
|
|
812
953
|
}));
|
|
@@ -814,19 +955,19 @@ export function createConversationStore(deps) {
|
|
|
814
955
|
discard(conversation) {
|
|
815
956
|
return withDraft(conversation, (current) => current === undefined
|
|
816
957
|
? undefined
|
|
817
|
-
: {
|
|
818
|
-
conversation,
|
|
819
|
-
text: '',
|
|
820
|
-
files: [],
|
|
821
|
-
revision: chatDraftRevision(),
|
|
822
|
-
...pending(current),
|
|
823
|
-
});
|
|
958
|
+
: { conversation, text: '', revision: chatDraftRevision(), ...pending(current) });
|
|
824
959
|
},
|
|
825
960
|
};
|
|
826
961
|
return {
|
|
827
962
|
surface,
|
|
828
963
|
chatDraft,
|
|
829
|
-
hydrate(held, kept) {
|
|
964
|
+
hydrate(held, kept, list) {
|
|
965
|
+
if (list !== null && !listKnown) {
|
|
966
|
+
listing.clear();
|
|
967
|
+
for (const entry of list)
|
|
968
|
+
listing.set(entry.conversation, { ...entry });
|
|
969
|
+
listHeld = true;
|
|
970
|
+
}
|
|
830
971
|
stored.clear();
|
|
831
972
|
reads.clear();
|
|
832
973
|
partials.clear();
|
|
@@ -840,6 +981,8 @@ export function createConversationStore(deps) {
|
|
|
840
981
|
drafts.clear();
|
|
841
982
|
for (const record of kept)
|
|
842
983
|
drafts.set(record.conversation, record);
|
|
984
|
+
if (listHeld)
|
|
985
|
+
learned();
|
|
843
986
|
},
|
|
844
987
|
async reconcile() {
|
|
845
988
|
if (!listKnown)
|
|
@@ -851,7 +994,7 @@ export function createConversationStore(deps) {
|
|
|
851
994
|
!creations.has(conversation) &&
|
|
852
995
|
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
|
|
853
996
|
for (const conversation of named) {
|
|
854
|
-
if (!replicated.has(conversation))
|
|
997
|
+
if (!replicated.has(conversation) && missed(conversation))
|
|
855
998
|
behind.add(conversation);
|
|
856
999
|
}
|
|
857
1000
|
replicated = named;
|
|
@@ -860,6 +1003,11 @@ export function createConversationStore(deps) {
|
|
|
860
1003
|
await remove(leaving);
|
|
861
1004
|
},
|
|
862
1005
|
async catchUp(progress) {
|
|
1006
|
+
if (deps.full()) {
|
|
1007
|
+
if (behind.size > 0)
|
|
1008
|
+
progress.complete = false;
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
863
1011
|
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
864
1012
|
const read = async (conversations) => {
|
|
865
1013
|
if (conversations.length === 0 || deps.closed())
|
|
@@ -908,12 +1056,10 @@ export function createConversationStore(deps) {
|
|
|
908
1056
|
known() {
|
|
909
1057
|
return listKnown;
|
|
910
1058
|
},
|
|
911
|
-
reconnected() {
|
|
912
|
-
for (const conversation of replicated)
|
|
913
|
-
gap(conversation);
|
|
914
|
-
},
|
|
915
1059
|
reopened() {
|
|
916
|
-
sending
|
|
1060
|
+
for (const [operation, dispatch] of sending)
|
|
1061
|
+
if (!dispatch.answered)
|
|
1062
|
+
sending.delete(operation);
|
|
917
1063
|
},
|
|
918
1064
|
lost() {
|
|
919
1065
|
catching.clear();
|
|
@@ -957,25 +1103,35 @@ export function createConversationStore(deps) {
|
|
|
957
1103
|
};
|
|
958
1104
|
},
|
|
959
1105
|
watchList(deliver) {
|
|
960
|
-
|
|
1106
|
+
let ended = false;
|
|
961
1107
|
void agentsReady().then(() => {
|
|
962
|
-
if (
|
|
963
|
-
|
|
1108
|
+
if (ended)
|
|
1109
|
+
return;
|
|
1110
|
+
unlisted.add(deliver);
|
|
1111
|
+
learned();
|
|
964
1112
|
});
|
|
965
1113
|
return () => {
|
|
1114
|
+
ended = true;
|
|
1115
|
+
unlisted.delete(deliver);
|
|
966
1116
|
listWatchers.delete(deliver);
|
|
967
1117
|
};
|
|
968
1118
|
},
|
|
969
1119
|
watchAgents(deliver) {
|
|
970
|
-
|
|
971
|
-
void agentsReady().then(
|
|
972
|
-
if (!deps.closed() && agentWatchers.has(deliver))
|
|
973
|
-
deliver(agents());
|
|
974
|
-
});
|
|
1120
|
+
unnamed.add(deliver);
|
|
1121
|
+
void agentsReady().then(learned);
|
|
975
1122
|
return () => {
|
|
1123
|
+
unnamed.delete(deliver);
|
|
976
1124
|
agentWatchers.delete(deliver);
|
|
977
1125
|
};
|
|
978
1126
|
},
|
|
1127
|
+
learned,
|
|
1128
|
+
declared() {
|
|
1129
|
+
if (JSON.stringify(deps.agents()) === agentsFrom)
|
|
1130
|
+
return;
|
|
1131
|
+
agentsRead = readAgents().catch(() => {
|
|
1132
|
+
agentsRead = null;
|
|
1133
|
+
});
|
|
1134
|
+
},
|
|
979
1135
|
changed(set) {
|
|
980
1136
|
for (const conversation of set.conversations)
|
|
981
1137
|
emit(conversation);
|
|
@@ -998,6 +1154,15 @@ export function createConversationStore(deps) {
|
|
|
998
1154
|
creations.delete(entry.conversation);
|
|
999
1155
|
}
|
|
1000
1156
|
listKnown = true;
|
|
1157
|
+
for (const conversation of replicated) {
|
|
1158
|
+
if (!listing.has(conversation))
|
|
1159
|
+
continue;
|
|
1160
|
+
if (!missed(conversation))
|
|
1161
|
+
behind.delete(conversation);
|
|
1162
|
+
else if (!behind.has(conversation))
|
|
1163
|
+
gap(conversation);
|
|
1164
|
+
}
|
|
1165
|
+
openingEnded();
|
|
1001
1166
|
}
|
|
1002
1167
|
else if (event.kind === 'listed') {
|
|
1003
1168
|
listing.set(event.entry.conversation, { ...event.entry });
|
|
@@ -1006,6 +1171,7 @@ export function createConversationStore(deps) {
|
|
|
1006
1171
|
else {
|
|
1007
1172
|
listing.delete(event.conversation);
|
|
1008
1173
|
}
|
|
1174
|
+
keepList();
|
|
1009
1175
|
emitList();
|
|
1010
1176
|
return (event.kind !== 'list' &&
|
|
1011
1177
|
listKnown &&
|
|
@@ -1024,8 +1190,11 @@ export function createConversationStore(deps) {
|
|
|
1024
1190
|
close() {
|
|
1025
1191
|
views.clear();
|
|
1026
1192
|
lives.clear();
|
|
1193
|
+
unsent.clear();
|
|
1027
1194
|
listWatchers.clear();
|
|
1195
|
+
unlisted.clear();
|
|
1028
1196
|
agentWatchers.clear();
|
|
1197
|
+
unnamed.clear();
|
|
1029
1198
|
},
|
|
1030
1199
|
};
|
|
1031
1200
|
}
|