@agentshouse/mdruntime 0.1.0-cee9c8aa4cd86 → 0.1.0-cf1e7fdb9c600
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 +11 -9
- package/dist/adapter.d.ts +96 -63
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +2 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +28 -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 +17 -9
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +143 -94
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/client.d.ts +12 -12
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -8
- 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 +1 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +118 -247
- package/dist/connection.d.ts +11 -11
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1602 -1147
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/{chat/context.js → context.js} +1 -4
- package/dist/conversation.d.ts +18 -14
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +266 -150
- package/dist/durability.d.ts +1 -5
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +3 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +15 -6
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/host.d.ts +3 -6
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +49 -35
- package/dist/index.d.ts +15 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/job.d.ts +14 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +28 -0
- package/dist/live.d.ts +2 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +9 -5
- 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 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +178 -100
- package/dist/messages.d.ts +2 -2
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +15 -16
- package/dist/model.d.ts +7 -3
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -13
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +8 -3
- package/dist/outcome.d.ts +13 -6
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +16 -5
- package/dist/overlay.js +1 -1
- 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 +10 -205
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -494
- package/dist/reach.d.ts +14 -9
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +81 -71
- package/dist/react.d.ts +3 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +13 -16
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +2 -8
- package/dist/recovery.d.ts +1 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +26 -0
- package/dist/refresh.d.ts +10 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +104 -30
- package/dist/replica.d.ts +6 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +8 -7
- package/dist/room-draft.d.ts +20 -3
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +131 -51
- package/dist/rows.d.ts +8 -15
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +51 -151
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +13 -7
- package/dist/search.d.ts +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- package/dist/shared.d.ts +0 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +0 -10
- 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 +32 -30
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +64 -58
- package/dist/stored.d.ts +42 -18
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +193 -194
- package/dist/tables.d.ts +60 -39
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +77 -59
- 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 +39 -97
- 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 +6 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +3 -3
- package/package.json +11 -18
- package/AGENTS.md +0 -320
- 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/earlier.d.ts +0 -10
- package/dist/chat/earlier.d.ts.map +0 -1
- package/dist/chat/earlier.js +0 -54
- package/dist/chat/house.d.ts +0 -25
- package/dist/chat/house.d.ts.map +0 -1
- package/dist/chat/house.js +0 -38
- package/dist/chat/input.d.ts +0 -11
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -92
- 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 -28
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -103
- package/dist/chat/markdown.d.ts +0 -21
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -246
- package/dist/chat/message.d.ts +0 -7
- package/dist/chat/message.d.ts.map +0 -1
- package/dist/chat/message.js +0 -254
- package/dist/chat/messages.d.ts +0 -35
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -210
- package/dist/chat/name.d.ts +0 -7
- package/dist/chat/name.d.ts.map +0 -1
- package/dist/chat/name.js +0 -37
- package/dist/chat/opened.d.ts +0 -12
- package/dist/chat/opened.d.ts.map +0 -1
- package/dist/chat/opened.js +0 -19
- package/dist/chat/overlay.d.ts +0 -32
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -103
- package/dist/chat/parts.d.ts +0 -58
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -120
- package/dist/chat/pieces.d.ts +0 -62
- package/dist/chat/pieces.d.ts.map +0 -1
- package/dist/chat/pieces.js +0 -1110
- 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 -70
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -635
- 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 -37
- package/dist/chat/ready.d.ts.map +0 -1
- package/dist/chat/ready.js +0 -93
- package/dist/chat/room-file.d.ts +0 -8
- package/dist/chat/room-file.d.ts.map +0 -1
- package/dist/chat/room-file.js +0 -72
- package/dist/chat/steady.d.ts +0 -3
- package/dist/chat/steady.d.ts.map +0 -1
- package/dist/chat/steady.js +0 -26
- package/dist/chat/style.d.ts +0 -4
- package/dist/chat/style.d.ts.map +0 -1
- package/dist/chat/style.js +0 -307
- package/dist/chat.d.ts +0 -15
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -8
- package/dist/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -368
- package/dist/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -98
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -150
package/dist/conversation.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { cursorOf, decodedCursor } from '@agentshouse/mdmodel';
|
|
1
2
|
import { conversationChangeSet } from './change-set.js';
|
|
2
3
|
import { runtimeError } from './failure.js';
|
|
3
|
-
import {
|
|
4
|
+
import { refusedForSpace } from './durability.js';
|
|
4
5
|
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
5
6
|
import { OFFLINE } from './outcome.js';
|
|
6
|
-
import {
|
|
7
|
+
import { untilAnswered } from './recovery.js';
|
|
8
|
+
import { capped, FROM_START, messageOrder, precedes } from './windows.js';
|
|
7
9
|
const QUIET = {
|
|
8
10
|
turn: null,
|
|
9
11
|
questions: [],
|
|
@@ -11,6 +13,7 @@ const QUIET = {
|
|
|
11
13
|
commands: [],
|
|
12
14
|
options: [],
|
|
13
15
|
starting: null,
|
|
16
|
+
subagents: [],
|
|
14
17
|
link: null,
|
|
15
18
|
deliveryUnknown: [],
|
|
16
19
|
};
|
|
@@ -20,6 +23,7 @@ const FACTS = [
|
|
|
20
23
|
'commands',
|
|
21
24
|
'options',
|
|
22
25
|
'starting',
|
|
26
|
+
'subagents',
|
|
23
27
|
'link',
|
|
24
28
|
'deliveryUnknown',
|
|
25
29
|
];
|
|
@@ -30,9 +34,11 @@ export function unheldView(conversation) {
|
|
|
30
34
|
turn: null,
|
|
31
35
|
questions: [],
|
|
32
36
|
process: null,
|
|
37
|
+
processEnded: null,
|
|
33
38
|
commands: [],
|
|
34
39
|
options: [],
|
|
35
40
|
starting: null,
|
|
41
|
+
subagents: [],
|
|
36
42
|
link: null,
|
|
37
43
|
deliveryUnknown: [],
|
|
38
44
|
chatDraft: null,
|
|
@@ -40,16 +46,15 @@ export function unheldView(conversation) {
|
|
|
40
46
|
}
|
|
41
47
|
export const SESSION_STARTED = 'Session started';
|
|
42
48
|
const NEW_CHAT = 'new:';
|
|
49
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
43
50
|
export function newChat(agent) {
|
|
44
51
|
return `${NEW_CHAT}${agent}`;
|
|
45
52
|
}
|
|
46
53
|
function creationOf(input) {
|
|
47
54
|
if (typeof input !== 'object' || input === null)
|
|
48
55
|
return null;
|
|
49
|
-
const { agent_id: agent, operation_id: operation
|
|
50
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
51
|
-
? { agent, operation }
|
|
52
|
-
: null;
|
|
56
|
+
const { agent_id: agent, operation_id: operation } = input;
|
|
57
|
+
return typeof agent === 'string' && typeof operation === 'string' ? { agent, operation } : null;
|
|
53
58
|
}
|
|
54
59
|
function startedTurn(turn, operation) {
|
|
55
60
|
if (operation.op === 'begin')
|
|
@@ -208,7 +213,21 @@ function askedOf(options) {
|
|
|
208
213
|
}
|
|
209
214
|
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
210
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
|
+
}
|
|
211
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
|
+
};
|
|
212
231
|
function unwritten(draft) {
|
|
213
232
|
return draft.text === '';
|
|
214
233
|
}
|
|
@@ -248,13 +267,19 @@ export function createConversationStore(deps) {
|
|
|
248
267
|
const unsent = new Map();
|
|
249
268
|
const views = new Map();
|
|
250
269
|
const listing = new Map();
|
|
270
|
+
let relisting = null;
|
|
271
|
+
let listCursor = null;
|
|
251
272
|
const creations = new Set();
|
|
252
273
|
const listWatchers = new Set();
|
|
274
|
+
const unlisted = new Set();
|
|
253
275
|
let listKnown = false;
|
|
276
|
+
let listHeld = false;
|
|
277
|
+
let listKept = false;
|
|
254
278
|
const agentWatchers = new Set();
|
|
255
|
-
|
|
256
|
-
let
|
|
257
|
-
let
|
|
279
|
+
const unnamed = new Set();
|
|
280
|
+
let agentsShown = null;
|
|
281
|
+
let listedAgents = null;
|
|
282
|
+
let agentsReading = false;
|
|
258
283
|
let replicated = new Set();
|
|
259
284
|
let handedReplicated;
|
|
260
285
|
function liveOf(conversation) {
|
|
@@ -275,9 +300,11 @@ export function createConversationStore(deps) {
|
|
|
275
300
|
turn: structuredClone(facts.turn),
|
|
276
301
|
questions: structuredClone(facts.questions),
|
|
277
302
|
process: facts.process === null ? null : { ...facts.process },
|
|
303
|
+
processEnded: listing.get(conversation)?.processEnded ?? null,
|
|
278
304
|
commands: structuredClone(facts.commands),
|
|
279
305
|
options: structuredClone(facts.options),
|
|
280
306
|
starting: facts.starting,
|
|
307
|
+
subagents: structuredClone(facts.subagents),
|
|
281
308
|
link: facts.link === null ? null : { ...facts.link },
|
|
282
309
|
deliveryUnknown: [...facts.deliveryUnknown],
|
|
283
310
|
chatDraft: draft === undefined || unwritten(draft)
|
|
@@ -333,7 +360,7 @@ export function createConversationStore(deps) {
|
|
|
333
360
|
function entries() {
|
|
334
361
|
return [...listing.values()].map((entry) => ({
|
|
335
362
|
conversation: entry.conversation,
|
|
336
|
-
agent: { identity: entry.agent, name:
|
|
363
|
+
agent: { identity: entry.agent, name: entry.agentName },
|
|
337
364
|
name: entry.name,
|
|
338
365
|
created: entry.created,
|
|
339
366
|
finished: entry.finished,
|
|
@@ -343,25 +370,103 @@ export function createConversationStore(deps) {
|
|
|
343
370
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
344
371
|
}));
|
|
345
372
|
}
|
|
373
|
+
function keepList() {
|
|
374
|
+
if (!listKnown || listKept)
|
|
375
|
+
return;
|
|
376
|
+
listKept = true;
|
|
377
|
+
queueMicrotask(() => {
|
|
378
|
+
listKept = false;
|
|
379
|
+
if (deps.closed())
|
|
380
|
+
return;
|
|
381
|
+
const entries = [...listing.values()];
|
|
382
|
+
const cursor = listCursor;
|
|
383
|
+
void deps
|
|
384
|
+
.durably(async (local) => {
|
|
385
|
+
await local.fact('conversationList', entries);
|
|
386
|
+
await local.fact('conversationCursor', cursor);
|
|
387
|
+
})
|
|
388
|
+
.catch(() => { });
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function listed(entry) {
|
|
392
|
+
const ended = listing.get(entry.conversation)?.processEnded ?? null;
|
|
393
|
+
listing.set(entry.conversation, { ...entry });
|
|
394
|
+
creations.delete(entry.conversation);
|
|
395
|
+
if (entry.processEnded !== ended)
|
|
396
|
+
emit(entry.conversation);
|
|
397
|
+
}
|
|
346
398
|
function emitList() {
|
|
347
|
-
if (deps.closed()
|
|
399
|
+
if (deps.closed())
|
|
348
400
|
return;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
watcher
|
|
401
|
+
if (listWatchers.size > 0) {
|
|
402
|
+
const value = entries();
|
|
403
|
+
for (const watcher of listWatchers)
|
|
404
|
+
watcher(value);
|
|
405
|
+
}
|
|
406
|
+
emitAgents();
|
|
407
|
+
learned();
|
|
408
|
+
}
|
|
409
|
+
function learned() {
|
|
410
|
+
if (deps.closed())
|
|
411
|
+
return;
|
|
412
|
+
if (!listKnown && !listHeld && deps.stream() !== undefined && deps.online())
|
|
413
|
+
return;
|
|
414
|
+
if (unlisted.size > 0) {
|
|
415
|
+
const value = entries();
|
|
416
|
+
for (const watcher of [...unlisted]) {
|
|
417
|
+
unlisted.delete(watcher);
|
|
418
|
+
listWatchers.add(watcher);
|
|
419
|
+
watcher(value);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (unnamed.size > 0) {
|
|
423
|
+
const value = agents();
|
|
424
|
+
for (const watcher of [...unnamed]) {
|
|
425
|
+
unnamed.delete(watcher);
|
|
426
|
+
agentWatchers.add(watcher);
|
|
427
|
+
watcher(value);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
352
430
|
}
|
|
353
431
|
function agents() {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
.
|
|
432
|
+
const named = new Map();
|
|
433
|
+
for (const agent of listedAgents ?? [])
|
|
434
|
+
named.set(agent.agent, agent);
|
|
435
|
+
for (const entry of listing.values()) {
|
|
436
|
+
named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
|
|
437
|
+
}
|
|
438
|
+
return [...named]
|
|
439
|
+
.filter(([, agent]) => !agent.retired)
|
|
440
|
+
.map(([identity, agent]) => ({ identity, name: agent.name }))
|
|
357
441
|
.sort((left, right) => left.name === right.name
|
|
358
442
|
? left.identity.localeCompare(right.identity)
|
|
359
443
|
: left.name.localeCompare(right.name));
|
|
360
444
|
}
|
|
445
|
+
function readAgents() {
|
|
446
|
+
const stream = deps.stream();
|
|
447
|
+
if (stream?.agents === undefined || !deps.online() || agentsReading)
|
|
448
|
+
return;
|
|
449
|
+
agentsReading = true;
|
|
450
|
+
void stream
|
|
451
|
+
.agents()
|
|
452
|
+
.then((read) => {
|
|
453
|
+
if (read === null)
|
|
454
|
+
return;
|
|
455
|
+
listedAgents = read;
|
|
456
|
+
emitAgents();
|
|
457
|
+
}, () => { })
|
|
458
|
+
.finally(() => {
|
|
459
|
+
agentsReading = false;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
361
462
|
function emitAgents() {
|
|
362
463
|
if (deps.closed() || agentWatchers.size === 0)
|
|
363
464
|
return;
|
|
364
465
|
const value = agents();
|
|
466
|
+
const shown = JSON.stringify(value);
|
|
467
|
+
if (shown === agentsShown)
|
|
468
|
+
return;
|
|
469
|
+
agentsShown = shown;
|
|
365
470
|
for (const watcher of agentWatchers)
|
|
366
471
|
watcher(value);
|
|
367
472
|
}
|
|
@@ -377,55 +482,11 @@ export function createConversationStore(deps) {
|
|
|
377
482
|
if (stateOf(conversation) !== before || next?.turn?.started !== began)
|
|
378
483
|
emitList();
|
|
379
484
|
}
|
|
380
|
-
async function readAgents() {
|
|
381
|
-
const declaration = deps.agents();
|
|
382
|
-
if (declaration === undefined)
|
|
383
|
-
return;
|
|
384
|
-
const names = new Map();
|
|
385
|
-
const retired = new Set();
|
|
386
|
-
let covered = null;
|
|
387
|
-
for (let after;;) {
|
|
388
|
-
const read = await deps.documents(declaration, after);
|
|
389
|
-
if ('pending' in read)
|
|
390
|
-
return;
|
|
391
|
-
const coverage = JSON.stringify(read.coverage);
|
|
392
|
-
if (covered !== null && coverage !== covered)
|
|
393
|
-
return readAgents();
|
|
394
|
-
covered = coverage;
|
|
395
|
-
for (const document of read.documents) {
|
|
396
|
-
const identity = document.fields?.[declaration.identity];
|
|
397
|
-
const name = document.fields?.[declaration.name];
|
|
398
|
-
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
399
|
-
continue;
|
|
400
|
-
names.set(identity, name);
|
|
401
|
-
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
402
|
-
if (ended !== undefined && ended !== null)
|
|
403
|
-
retired.add(identity);
|
|
404
|
-
}
|
|
405
|
-
if (read.next === undefined)
|
|
406
|
-
break;
|
|
407
|
-
after = read.next;
|
|
408
|
-
}
|
|
409
|
-
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
410
|
-
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
411
|
-
return;
|
|
412
|
-
agentNames = names;
|
|
413
|
-
retiredAgents = retired;
|
|
414
|
-
if (named)
|
|
415
|
-
emitList();
|
|
416
|
-
emitAgents();
|
|
417
|
-
const ended = [...drafts.keys()].filter(retiredChat);
|
|
418
|
-
if (ended.length > 0)
|
|
419
|
-
await remove(ended);
|
|
420
|
-
}
|
|
421
485
|
function retiredChat(conversation) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
agentsRead = null;
|
|
427
|
-
});
|
|
428
|
-
return agentsRead;
|
|
486
|
+
if (!conversation.startsWith(NEW_CHAT))
|
|
487
|
+
return false;
|
|
488
|
+
const agent = conversation.slice(NEW_CHAT.length);
|
|
489
|
+
return [...listing.values()].some((entry) => entry.agent === agent && entry.agentRetired);
|
|
429
490
|
}
|
|
430
491
|
function live(conversation, change) {
|
|
431
492
|
const owed = unsent.get(conversation);
|
|
@@ -448,6 +509,7 @@ export function createConversationStore(deps) {
|
|
|
448
509
|
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
449
510
|
options: facts.has('options') ? QUIET.options : held.options,
|
|
450
511
|
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
512
|
+
subagents: facts.has('subagents') ? QUIET.subagents : held.subagents,
|
|
451
513
|
link: facts.has('link') ? QUIET.link : held.link,
|
|
452
514
|
deliveryUnknown: facts.has('deliveryUnknown')
|
|
453
515
|
? QUIET.deliveryUnknown
|
|
@@ -501,6 +563,20 @@ export function createConversationStore(deps) {
|
|
|
501
563
|
deps.publish(conversationChangeSet(changed));
|
|
502
564
|
});
|
|
503
565
|
}
|
|
566
|
+
function missed(conversation) {
|
|
567
|
+
const read = reads.get(conversation);
|
|
568
|
+
const newest = listing.get(conversation)?.newest;
|
|
569
|
+
return (read === undefined ||
|
|
570
|
+
newest === undefined ||
|
|
571
|
+
partials.has(conversation) ||
|
|
572
|
+
(newest !== null && (read === null || newest > read)));
|
|
573
|
+
}
|
|
574
|
+
function noted(conversation, message) {
|
|
575
|
+
const entry = listing.get(conversation);
|
|
576
|
+
if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
|
|
577
|
+
return;
|
|
578
|
+
listing.set(conversation, { ...entry, newest: message.position });
|
|
579
|
+
}
|
|
504
580
|
function gap(conversation) {
|
|
505
581
|
gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
|
|
506
582
|
behind.add(conversation);
|
|
@@ -529,12 +605,13 @@ export function createConversationStore(deps) {
|
|
|
529
605
|
}
|
|
530
606
|
async function readHistories(conversations, ended) {
|
|
531
607
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
532
|
-
let
|
|
608
|
+
let waiting = conversations.map((conversation) => ({
|
|
533
609
|
conversation,
|
|
534
610
|
after: reads.get(conversation) ?? undefined,
|
|
535
611
|
}));
|
|
536
|
-
while (
|
|
537
|
-
const
|
|
612
|
+
while (waiting.length > 0) {
|
|
613
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
614
|
+
const result = await deps.history({
|
|
538
615
|
conversations: asking.map(({ conversation, after }) => ({
|
|
539
616
|
conversation,
|
|
540
617
|
...(after === undefined ? {} : { after }),
|
|
@@ -557,7 +634,7 @@ export function createConversationStore(deps) {
|
|
|
557
634
|
if (!following.some((next) => next.conversation === conversation))
|
|
558
635
|
ended(conversation);
|
|
559
636
|
}
|
|
560
|
-
|
|
637
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
561
638
|
}
|
|
562
639
|
return null;
|
|
563
640
|
}
|
|
@@ -637,6 +714,10 @@ export function createConversationStore(deps) {
|
|
|
637
714
|
live(conversation, { starting: event.step });
|
|
638
715
|
return;
|
|
639
716
|
}
|
|
717
|
+
if (event.kind === 'subagents') {
|
|
718
|
+
live(conversation, { subagents: structuredClone(event.subagents) });
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
640
721
|
if (event.kind === 'link') {
|
|
641
722
|
live(conversation, { link: { connected: event.connected } });
|
|
642
723
|
return;
|
|
@@ -648,8 +729,16 @@ export function createConversationStore(deps) {
|
|
|
648
729
|
const arriving = acceptedMessage(event.message);
|
|
649
730
|
if (arriving === null)
|
|
650
731
|
return;
|
|
732
|
+
noted(conversation, arriving);
|
|
651
733
|
if (replicated.has(conversation)) {
|
|
652
|
-
|
|
734
|
+
if (deps.full()) {
|
|
735
|
+
gap(conversation);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
void keep(conversation, arriving).catch((error) => {
|
|
739
|
+
if (refusedForSpace(error))
|
|
740
|
+
gap(conversation);
|
|
741
|
+
});
|
|
653
742
|
return;
|
|
654
743
|
}
|
|
655
744
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -734,20 +823,21 @@ export function createConversationStore(deps) {
|
|
|
734
823
|
});
|
|
735
824
|
}
|
|
736
825
|
async function dispatched(conversation, submission) {
|
|
737
|
-
const dispatch = {};
|
|
826
|
+
const dispatch = { answered: false };
|
|
738
827
|
sending.set(submission.operation, dispatch);
|
|
739
828
|
try {
|
|
740
|
-
const result = await invoke('
|
|
741
|
-
text: submission.text,
|
|
829
|
+
const result = await invoke('conversations/send', conversation, {
|
|
742
830
|
operation_id: submission.operation,
|
|
831
|
+
text: submission.text,
|
|
743
832
|
});
|
|
833
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
744
834
|
if (result.kind === 'revoked-authorization')
|
|
745
835
|
return result;
|
|
746
836
|
if (result.kind !== 'action' && result.retryable) {
|
|
747
837
|
deps.unanswered();
|
|
748
838
|
return result;
|
|
749
839
|
}
|
|
750
|
-
const turn = answered(result, '
|
|
840
|
+
const turn = answered(result, 'message_id');
|
|
751
841
|
await withDraft(conversation, async (current, local) => {
|
|
752
842
|
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
753
843
|
if (current === undefined || held === undefined || held.turn !== null)
|
|
@@ -767,25 +857,34 @@ export function createConversationStore(deps) {
|
|
|
767
857
|
sending.delete(submission.operation);
|
|
768
858
|
}
|
|
769
859
|
}
|
|
770
|
-
function invoke(name, conversation, extra = {}) {
|
|
771
|
-
return deps.call(name, { conversation, ...extra });
|
|
860
|
+
function invoke(name, conversation, extra = { operation_id: changeBatchIdentity() }) {
|
|
861
|
+
return deps.call(name, { conversation_id: conversation, ...extra });
|
|
772
862
|
}
|
|
773
863
|
const surface = {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
864
|
+
list() {
|
|
865
|
+
return new Promise((settle) => {
|
|
866
|
+
const answer = (listed) => {
|
|
867
|
+
unlisted.delete(answer);
|
|
868
|
+
listWatchers.delete(answer);
|
|
869
|
+
settle(listed);
|
|
870
|
+
};
|
|
871
|
+
unlisted.add(answer);
|
|
872
|
+
learned();
|
|
873
|
+
});
|
|
777
874
|
},
|
|
778
875
|
async read(conversation, options = {}) {
|
|
779
|
-
const
|
|
876
|
+
const { text, ...windowed } = options;
|
|
877
|
+
const asked = askedOf(windowed);
|
|
878
|
+
const phrase = phraseOf(text);
|
|
780
879
|
return deps.durably(async (local) => {
|
|
781
|
-
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
782
|
-
const total = asked.total ? await local.messageCount(conversation) : null;
|
|
880
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before, phrase);
|
|
881
|
+
const total = asked.total ? await local.messageCount(conversation, phrase) : null;
|
|
783
882
|
return structuredClone(viewOf(conversation, messages, frameOf(asked, messages, more, total)));
|
|
784
883
|
});
|
|
785
884
|
},
|
|
786
885
|
async create(input) {
|
|
787
|
-
const result = await deps.call('
|
|
788
|
-
const conversation = answered(result, '
|
|
886
|
+
const result = await deps.call('conversations/create', input);
|
|
887
|
+
const conversation = answered(result, 'conversation_id');
|
|
789
888
|
if (conversation === null)
|
|
790
889
|
return result;
|
|
791
890
|
if (!listing.has(conversation))
|
|
@@ -796,8 +895,17 @@ export function createConversationStore(deps) {
|
|
|
796
895
|
return result;
|
|
797
896
|
},
|
|
798
897
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
898
|
+
if (deps.full())
|
|
899
|
+
return DURABLE_WRITE;
|
|
799
900
|
if (deps.online()) {
|
|
800
|
-
const
|
|
901
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
902
|
+
if (refusedForSpace(error))
|
|
903
|
+
return null;
|
|
904
|
+
throw error;
|
|
905
|
+
});
|
|
906
|
+
if (held === null)
|
|
907
|
+
return DURABLE_WRITE;
|
|
908
|
+
const { submission, earlier } = held;
|
|
801
909
|
if (!earlier || !deps.expired(operation))
|
|
802
910
|
return dispatched(conversation, submission);
|
|
803
911
|
await forgotten(conversation, submission);
|
|
@@ -810,38 +918,20 @@ export function createConversationStore(deps) {
|
|
|
810
918
|
}
|
|
811
919
|
return OFFLINE;
|
|
812
920
|
},
|
|
813
|
-
async attach(room, file) {
|
|
814
|
-
if (!deps.online())
|
|
815
|
-
return OFFLINE;
|
|
816
|
-
return deps.call('conversation.attach', {
|
|
817
|
-
room,
|
|
818
|
-
...(await declaredFile(file)),
|
|
819
|
-
blob: file.blob,
|
|
820
|
-
});
|
|
821
|
-
},
|
|
822
921
|
answer(conversation, answer) {
|
|
823
|
-
return invoke('
|
|
922
|
+
return invoke('conversations/interaction/answer', conversation, {
|
|
923
|
+
operation_id: changeBatchIdentity(),
|
|
924
|
+
...answer,
|
|
925
|
+
});
|
|
824
926
|
},
|
|
825
927
|
interrupt(conversation) {
|
|
826
|
-
return invoke('
|
|
928
|
+
return invoke('conversations/interrupt', conversation);
|
|
827
929
|
},
|
|
828
930
|
kill(conversation) {
|
|
829
|
-
return invoke('
|
|
830
|
-
},
|
|
831
|
-
async cancel(conversation, turn) {
|
|
832
|
-
const result = await invoke('conversation.cancel', conversation, { turn });
|
|
833
|
-
if (result.kind !== 'action')
|
|
834
|
-
return result;
|
|
835
|
-
await withDraft(conversation, (current) => {
|
|
836
|
-
const held = current?.submitted?.find((one) => one.turn === turn);
|
|
837
|
-
if (current === undefined || held === undefined)
|
|
838
|
-
return undefined;
|
|
839
|
-
return returned(current, held, current.submitted.filter((one) => one !== held));
|
|
840
|
-
});
|
|
841
|
-
return result;
|
|
931
|
+
return invoke('conversations/kill', conversation);
|
|
842
932
|
},
|
|
843
933
|
delete(conversation) {
|
|
844
|
-
return invoke('
|
|
934
|
+
return invoke('conversations/delete', conversation);
|
|
845
935
|
},
|
|
846
936
|
};
|
|
847
937
|
const chatDraft = {
|
|
@@ -870,7 +960,15 @@ export function createConversationStore(deps) {
|
|
|
870
960
|
return {
|
|
871
961
|
surface,
|
|
872
962
|
chatDraft,
|
|
873
|
-
hydrate(held, kept) {
|
|
963
|
+
hydrate(held, kept, list, cursor) {
|
|
964
|
+
if (list !== null && !listKnown) {
|
|
965
|
+
listing.clear();
|
|
966
|
+
for (const entry of list)
|
|
967
|
+
listing.set(entry.conversation, { ...entry });
|
|
968
|
+
listHeld = true;
|
|
969
|
+
listCursor = cursor;
|
|
970
|
+
deps.stream()?.hold(cursor);
|
|
971
|
+
}
|
|
874
972
|
stored.clear();
|
|
875
973
|
reads.clear();
|
|
876
974
|
partials.clear();
|
|
@@ -884,6 +982,8 @@ export function createConversationStore(deps) {
|
|
|
884
982
|
drafts.clear();
|
|
885
983
|
for (const record of kept)
|
|
886
984
|
drafts.set(record.conversation, record);
|
|
985
|
+
if (listHeld)
|
|
986
|
+
learned();
|
|
887
987
|
},
|
|
888
988
|
async reconcile() {
|
|
889
989
|
if (!listKnown)
|
|
@@ -895,7 +995,7 @@ export function createConversationStore(deps) {
|
|
|
895
995
|
!creations.has(conversation) &&
|
|
896
996
|
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
|
|
897
997
|
for (const conversation of named) {
|
|
898
|
-
if (!replicated.has(conversation))
|
|
998
|
+
if (!replicated.has(conversation) && missed(conversation))
|
|
899
999
|
behind.add(conversation);
|
|
900
1000
|
}
|
|
901
1001
|
replicated = named;
|
|
@@ -904,6 +1004,11 @@ export function createConversationStore(deps) {
|
|
|
904
1004
|
await remove(leaving);
|
|
905
1005
|
},
|
|
906
1006
|
async catchUp(progress) {
|
|
1007
|
+
if (deps.full()) {
|
|
1008
|
+
if (behind.size > 0)
|
|
1009
|
+
progress.complete = false;
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
907
1012
|
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
908
1013
|
const read = async (conversations) => {
|
|
909
1014
|
if (conversations.length === 0 || deps.closed())
|
|
@@ -952,12 +1057,11 @@ export function createConversationStore(deps) {
|
|
|
952
1057
|
known() {
|
|
953
1058
|
return listKnown;
|
|
954
1059
|
},
|
|
955
|
-
reconnected() {
|
|
956
|
-
for (const conversation of replicated)
|
|
957
|
-
gap(conversation);
|
|
958
|
-
},
|
|
959
1060
|
reopened() {
|
|
960
|
-
|
|
1061
|
+
relisting = null;
|
|
1062
|
+
for (const [operation, dispatch] of sending)
|
|
1063
|
+
if (!dispatch.answered)
|
|
1064
|
+
sending.delete(operation);
|
|
961
1065
|
},
|
|
962
1066
|
lost() {
|
|
963
1067
|
catching.clear();
|
|
@@ -976,15 +1080,15 @@ export function createConversationStore(deps) {
|
|
|
976
1080
|
views.set(key, view);
|
|
977
1081
|
const watcher = { notify: deliver, ready: false };
|
|
978
1082
|
view.watchers.add(watcher);
|
|
979
|
-
|
|
980
|
-
|
|
1083
|
+
const reading = new AbortController();
|
|
1084
|
+
void untilAnswered(() => deps.durably(async (local) => {
|
|
981
1085
|
if (view.window !== null)
|
|
982
1086
|
return;
|
|
983
1087
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
984
1088
|
view.window = messages;
|
|
985
1089
|
view.more = more;
|
|
986
1090
|
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
987
|
-
})
|
|
1091
|
+
}), reading.signal)
|
|
988
1092
|
.then(() => {
|
|
989
1093
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
990
1094
|
return;
|
|
@@ -994,6 +1098,7 @@ export function createConversationStore(deps) {
|
|
|
994
1098
|
})
|
|
995
1099
|
.catch(() => { });
|
|
996
1100
|
return () => {
|
|
1101
|
+
reading.abort();
|
|
997
1102
|
if (!view.watchers.delete(watcher))
|
|
998
1103
|
return;
|
|
999
1104
|
if (view.watchers.size === 0)
|
|
@@ -1001,77 +1106,88 @@ export function createConversationStore(deps) {
|
|
|
1001
1106
|
};
|
|
1002
1107
|
},
|
|
1003
1108
|
watchList(deliver) {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
if (!deps.closed() && listWatchers.has(deliver))
|
|
1007
|
-
deliver(entries());
|
|
1008
|
-
});
|
|
1109
|
+
unlisted.add(deliver);
|
|
1110
|
+
learned();
|
|
1009
1111
|
return () => {
|
|
1112
|
+
unlisted.delete(deliver);
|
|
1010
1113
|
listWatchers.delete(deliver);
|
|
1011
1114
|
};
|
|
1012
1115
|
},
|
|
1013
1116
|
watchAgents(deliver) {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
deliver(agents());
|
|
1018
|
-
});
|
|
1117
|
+
unnamed.add(deliver);
|
|
1118
|
+
learned();
|
|
1119
|
+
readAgents();
|
|
1019
1120
|
return () => {
|
|
1121
|
+
unnamed.delete(deliver);
|
|
1020
1122
|
agentWatchers.delete(deliver);
|
|
1021
1123
|
};
|
|
1022
1124
|
},
|
|
1125
|
+
learned,
|
|
1023
1126
|
changed(set) {
|
|
1024
1127
|
for (const conversation of set.conversations)
|
|
1025
1128
|
emit(conversation);
|
|
1026
|
-
const declaration = deps.agents();
|
|
1027
|
-
if (declaration !== undefined &&
|
|
1028
|
-
set.documents.some((change) => change.locator === declaration.locator)) {
|
|
1029
|
-
agentsRead = readAgents().catch(() => {
|
|
1030
|
-
agentsRead = null;
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
1129
|
},
|
|
1034
1130
|
receive(event) {
|
|
1035
1131
|
if (deps.closed())
|
|
1036
1132
|
return false;
|
|
1037
1133
|
if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted') {
|
|
1038
1134
|
if (event.kind === 'list') {
|
|
1039
|
-
|
|
1135
|
+
if (event.whole)
|
|
1136
|
+
relisting ??= new Map();
|
|
1040
1137
|
for (const entry of event.entries) {
|
|
1041
|
-
|
|
1042
|
-
|
|
1138
|
+
if (relisting === null)
|
|
1139
|
+
listed(entry);
|
|
1140
|
+
else
|
|
1141
|
+
relisting.set(entry.conversation, { ...entry });
|
|
1142
|
+
}
|
|
1143
|
+
if (event.more)
|
|
1144
|
+
return false;
|
|
1145
|
+
if (relisting !== null) {
|
|
1146
|
+
listing.clear();
|
|
1147
|
+
for (const entry of relisting.values())
|
|
1148
|
+
listed(entry);
|
|
1149
|
+
relisting = null;
|
|
1043
1150
|
}
|
|
1151
|
+
listCursor = event.cursor;
|
|
1152
|
+
deps.stream()?.hold(event.cursor);
|
|
1044
1153
|
listKnown = true;
|
|
1154
|
+
for (const conversation of replicated) {
|
|
1155
|
+
if (!listing.has(conversation))
|
|
1156
|
+
continue;
|
|
1157
|
+
if (!missed(conversation))
|
|
1158
|
+
behind.delete(conversation);
|
|
1159
|
+
else if (!behind.has(conversation))
|
|
1160
|
+
gap(conversation);
|
|
1161
|
+
}
|
|
1045
1162
|
openingEnded();
|
|
1046
1163
|
}
|
|
1047
1164
|
else if (event.kind === 'listed') {
|
|
1048
|
-
|
|
1049
|
-
|
|
1165
|
+
listed(event.entry);
|
|
1166
|
+
relisting?.set(event.entry.conversation, { ...event.entry });
|
|
1050
1167
|
}
|
|
1051
1168
|
else {
|
|
1052
1169
|
listing.delete(event.conversation);
|
|
1170
|
+
relisting?.delete(event.conversation);
|
|
1053
1171
|
}
|
|
1172
|
+
keepList();
|
|
1054
1173
|
emitList();
|
|
1055
|
-
return (event.kind !== 'list' &&
|
|
1174
|
+
return ((event.kind !== 'list' &&
|
|
1056
1175
|
listKnown &&
|
|
1057
1176
|
(listing.size !== replicated.size ||
|
|
1058
|
-
[...listing.keys()].some((conversation) => !replicated.has(conversation))))
|
|
1177
|
+
[...listing.keys()].some((conversation) => !replicated.has(conversation)))) ||
|
|
1178
|
+
(listKnown && [...drafts.keys()].some(retiredChat)));
|
|
1059
1179
|
}
|
|
1060
1180
|
heard(event);
|
|
1061
1181
|
return false;
|
|
1062
1182
|
},
|
|
1063
|
-
searchable() {
|
|
1064
|
-
return [...(listKnown ? listing.keys() : stored)].sort();
|
|
1065
|
-
},
|
|
1066
|
-
acquired(conversation) {
|
|
1067
|
-
return reads.has(conversation) && !partials.has(conversation);
|
|
1068
|
-
},
|
|
1069
1183
|
close() {
|
|
1070
1184
|
views.clear();
|
|
1071
1185
|
lives.clear();
|
|
1072
1186
|
unsent.clear();
|
|
1073
1187
|
listWatchers.clear();
|
|
1188
|
+
unlisted.clear();
|
|
1074
1189
|
agentWatchers.clear();
|
|
1190
|
+
unnamed.clear();
|
|
1075
1191
|
},
|
|
1076
1192
|
};
|
|
1077
1193
|
}
|