@agentshouse/mdruntime 0.1.0-ccbe92df1c4f6 → 0.1.0-ccc0e3407f107
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 +91 -58
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -11
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +36 -47
- package/dist/bootstrap.d.ts +11 -14
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +101 -89
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/client.d.ts +15 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +56 -7
- package/dist/collection.d.ts +7 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +24 -19
- package/dist/compile.d.ts +1 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +108 -243
- package/dist/connection.d.ts +14 -11
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1256 -1225
- 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 +16 -15
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +234 -167
- package/dist/durability.d.ts +6 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +3 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +17 -8
- 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 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +53 -36
- 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 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- 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 +12 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +210 -91
- 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 +8 -8
- 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 -5
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +16 -2
- 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 +8 -207
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -505
- package/dist/reach.d.ts +14 -7
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +83 -53
- package/dist/react.d.ts +3 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +3 -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 +7 -5
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +30 -10
- package/dist/replica.d.ts +10 -9
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +30 -15
- package/dist/room-draft.d.ts +22 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +131 -51
- package/dist/rows.d.ts +18 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +45 -153
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +20 -12
- 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 +21 -39
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +33 -73
- package/dist/stored.d.ts +11 -27
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +187 -230
- package/dist/tables.d.ts +34 -51
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +75 -68
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/validation.d.ts +3 -4
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +42 -100
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +17 -8
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +5 -2
- package/package.json +10 -17
- package/AGENTS.md +0 -317
- 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 -20
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -229
- 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 -100
- 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,10 +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
4
|
import { refusedForSpace } from './durability.js';
|
|
4
|
-
import { declaredFile } from './file.js';
|
|
5
5
|
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
6
6
|
import { OFFLINE } from './outcome.js';
|
|
7
|
-
import {
|
|
7
|
+
import { untilAnswered } from './recovery.js';
|
|
8
|
+
import { capped, FROM_START, messageOrder, precedes } from './windows.js';
|
|
8
9
|
const QUIET = {
|
|
9
10
|
turn: null,
|
|
10
11
|
questions: [],
|
|
@@ -12,6 +13,7 @@ const QUIET = {
|
|
|
12
13
|
commands: [],
|
|
13
14
|
options: [],
|
|
14
15
|
starting: null,
|
|
16
|
+
subagents: [],
|
|
15
17
|
link: null,
|
|
16
18
|
deliveryUnknown: [],
|
|
17
19
|
};
|
|
@@ -21,6 +23,7 @@ const FACTS = [
|
|
|
21
23
|
'commands',
|
|
22
24
|
'options',
|
|
23
25
|
'starting',
|
|
26
|
+
'subagents',
|
|
24
27
|
'link',
|
|
25
28
|
'deliveryUnknown',
|
|
26
29
|
];
|
|
@@ -31,9 +34,11 @@ export function unheldView(conversation) {
|
|
|
31
34
|
turn: null,
|
|
32
35
|
questions: [],
|
|
33
36
|
process: null,
|
|
37
|
+
processEnded: null,
|
|
34
38
|
commands: [],
|
|
35
39
|
options: [],
|
|
36
40
|
starting: null,
|
|
41
|
+
subagents: [],
|
|
37
42
|
link: null,
|
|
38
43
|
deliveryUnknown: [],
|
|
39
44
|
chatDraft: null,
|
|
@@ -48,10 +53,8 @@ export function newChat(agent) {
|
|
|
48
53
|
function creationOf(input) {
|
|
49
54
|
if (typeof input !== 'object' || input === null)
|
|
50
55
|
return null;
|
|
51
|
-
const { agent_id: agent, operation_id: operation
|
|
52
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
53
|
-
? { agent, operation }
|
|
54
|
-
: null;
|
|
56
|
+
const { agent_id: agent, operation_id: operation } = input;
|
|
57
|
+
return typeof agent === 'string' && typeof operation === 'string' ? { agent, operation } : null;
|
|
55
58
|
}
|
|
56
59
|
function startedTurn(turn, operation) {
|
|
57
60
|
if (operation.op === 'begin')
|
|
@@ -210,7 +213,14 @@ function askedOf(options) {
|
|
|
210
213
|
}
|
|
211
214
|
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
212
215
|
}
|
|
213
|
-
|
|
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
|
+
}
|
|
214
224
|
const DURABLE_WRITE = {
|
|
215
225
|
kind: 'rejected',
|
|
216
226
|
code: 'durable-write',
|
|
@@ -256,13 +266,19 @@ export function createConversationStore(deps) {
|
|
|
256
266
|
const unsent = new Map();
|
|
257
267
|
const views = new Map();
|
|
258
268
|
const listing = new Map();
|
|
269
|
+
let relisting = null;
|
|
270
|
+
let listCursor = null;
|
|
259
271
|
const creations = new Set();
|
|
260
272
|
const listWatchers = new Set();
|
|
273
|
+
const unlisted = new Set();
|
|
261
274
|
let listKnown = false;
|
|
275
|
+
let listHeld = false;
|
|
276
|
+
let listKept = false;
|
|
262
277
|
const agentWatchers = new Set();
|
|
263
|
-
|
|
264
|
-
let
|
|
265
|
-
let
|
|
278
|
+
const unnamed = new Set();
|
|
279
|
+
let agentsShown = null;
|
|
280
|
+
let listedAgents = null;
|
|
281
|
+
let agentsReading = false;
|
|
266
282
|
let replicated = new Set();
|
|
267
283
|
let handedReplicated;
|
|
268
284
|
function liveOf(conversation) {
|
|
@@ -283,9 +299,11 @@ export function createConversationStore(deps) {
|
|
|
283
299
|
turn: structuredClone(facts.turn),
|
|
284
300
|
questions: structuredClone(facts.questions),
|
|
285
301
|
process: facts.process === null ? null : { ...facts.process },
|
|
302
|
+
processEnded: listing.get(conversation)?.processEnded ?? null,
|
|
286
303
|
commands: structuredClone(facts.commands),
|
|
287
304
|
options: structuredClone(facts.options),
|
|
288
305
|
starting: facts.starting,
|
|
306
|
+
subagents: structuredClone(facts.subagents),
|
|
289
307
|
link: facts.link === null ? null : { ...facts.link },
|
|
290
308
|
deliveryUnknown: [...facts.deliveryUnknown],
|
|
291
309
|
chatDraft: draft === undefined || unwritten(draft)
|
|
@@ -341,7 +359,7 @@ export function createConversationStore(deps) {
|
|
|
341
359
|
function entries() {
|
|
342
360
|
return [...listing.values()].map((entry) => ({
|
|
343
361
|
conversation: entry.conversation,
|
|
344
|
-
agent: { identity: entry.agent, name:
|
|
362
|
+
agent: { identity: entry.agent, name: entry.agentName },
|
|
345
363
|
name: entry.name,
|
|
346
364
|
created: entry.created,
|
|
347
365
|
finished: entry.finished,
|
|
@@ -351,25 +369,103 @@ export function createConversationStore(deps) {
|
|
|
351
369
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
352
370
|
}));
|
|
353
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
|
+
const ended = listing.get(entry.conversation)?.processEnded ?? null;
|
|
392
|
+
listing.set(entry.conversation, { ...entry });
|
|
393
|
+
creations.delete(entry.conversation);
|
|
394
|
+
if (entry.processEnded !== ended)
|
|
395
|
+
emit(entry.conversation);
|
|
396
|
+
}
|
|
354
397
|
function emitList() {
|
|
355
|
-
if (deps.closed()
|
|
398
|
+
if (deps.closed())
|
|
356
399
|
return;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
watcher
|
|
400
|
+
if (listWatchers.size > 0) {
|
|
401
|
+
const value = entries();
|
|
402
|
+
for (const watcher of listWatchers)
|
|
403
|
+
watcher(value);
|
|
404
|
+
}
|
|
405
|
+
emitAgents();
|
|
406
|
+
learned();
|
|
407
|
+
}
|
|
408
|
+
function learned() {
|
|
409
|
+
if (deps.closed())
|
|
410
|
+
return;
|
|
411
|
+
if (!listKnown && !listHeld && deps.stream() !== undefined && deps.online())
|
|
412
|
+
return;
|
|
413
|
+
if (unlisted.size > 0) {
|
|
414
|
+
const value = entries();
|
|
415
|
+
for (const watcher of [...unlisted]) {
|
|
416
|
+
unlisted.delete(watcher);
|
|
417
|
+
listWatchers.add(watcher);
|
|
418
|
+
watcher(value);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (unnamed.size > 0) {
|
|
422
|
+
const value = agents();
|
|
423
|
+
for (const watcher of [...unnamed]) {
|
|
424
|
+
unnamed.delete(watcher);
|
|
425
|
+
agentWatchers.add(watcher);
|
|
426
|
+
watcher(value);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
360
429
|
}
|
|
361
430
|
function agents() {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
.
|
|
431
|
+
const named = new Map();
|
|
432
|
+
for (const agent of listedAgents ?? [])
|
|
433
|
+
named.set(agent.agent, agent);
|
|
434
|
+
for (const entry of listing.values()) {
|
|
435
|
+
named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
|
|
436
|
+
}
|
|
437
|
+
return [...named]
|
|
438
|
+
.filter(([, agent]) => !agent.retired)
|
|
439
|
+
.map(([identity, agent]) => ({ identity, name: agent.name }))
|
|
365
440
|
.sort((left, right) => left.name === right.name
|
|
366
441
|
? left.identity.localeCompare(right.identity)
|
|
367
442
|
: left.name.localeCompare(right.name));
|
|
368
443
|
}
|
|
444
|
+
function readAgents() {
|
|
445
|
+
const stream = deps.stream();
|
|
446
|
+
if (stream?.agents === undefined || !deps.online() || agentsReading)
|
|
447
|
+
return;
|
|
448
|
+
agentsReading = true;
|
|
449
|
+
void stream
|
|
450
|
+
.agents()
|
|
451
|
+
.then((read) => {
|
|
452
|
+
if (read === null)
|
|
453
|
+
return;
|
|
454
|
+
listedAgents = read;
|
|
455
|
+
emitAgents();
|
|
456
|
+
}, () => { })
|
|
457
|
+
.finally(() => {
|
|
458
|
+
agentsReading = false;
|
|
459
|
+
});
|
|
460
|
+
}
|
|
369
461
|
function emitAgents() {
|
|
370
462
|
if (deps.closed() || agentWatchers.size === 0)
|
|
371
463
|
return;
|
|
372
464
|
const value = agents();
|
|
465
|
+
const shown = JSON.stringify(value);
|
|
466
|
+
if (shown === agentsShown)
|
|
467
|
+
return;
|
|
468
|
+
agentsShown = shown;
|
|
373
469
|
for (const watcher of agentWatchers)
|
|
374
470
|
watcher(value);
|
|
375
471
|
}
|
|
@@ -385,55 +481,11 @@ export function createConversationStore(deps) {
|
|
|
385
481
|
if (stateOf(conversation) !== before || next?.turn?.started !== began)
|
|
386
482
|
emitList();
|
|
387
483
|
}
|
|
388
|
-
async function readAgents() {
|
|
389
|
-
const declaration = deps.agents();
|
|
390
|
-
if (declaration === undefined)
|
|
391
|
-
return;
|
|
392
|
-
const names = new Map();
|
|
393
|
-
const retired = new Set();
|
|
394
|
-
let covered = null;
|
|
395
|
-
for (let after;;) {
|
|
396
|
-
const read = await deps.documents(declaration, after);
|
|
397
|
-
if ('pending' in read)
|
|
398
|
-
return;
|
|
399
|
-
const coverage = JSON.stringify(read.coverage);
|
|
400
|
-
if (covered !== null && coverage !== covered)
|
|
401
|
-
return readAgents();
|
|
402
|
-
covered = coverage;
|
|
403
|
-
for (const document of read.documents) {
|
|
404
|
-
const identity = document.fields?.[declaration.identity];
|
|
405
|
-
const name = document.fields?.[declaration.name];
|
|
406
|
-
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
407
|
-
continue;
|
|
408
|
-
names.set(identity, name);
|
|
409
|
-
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
410
|
-
if (ended !== undefined && ended !== null)
|
|
411
|
-
retired.add(identity);
|
|
412
|
-
}
|
|
413
|
-
if (read.next === undefined)
|
|
414
|
-
break;
|
|
415
|
-
after = read.next;
|
|
416
|
-
}
|
|
417
|
-
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
418
|
-
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
419
|
-
return;
|
|
420
|
-
agentNames = names;
|
|
421
|
-
retiredAgents = retired;
|
|
422
|
-
if (named)
|
|
423
|
-
emitList();
|
|
424
|
-
emitAgents();
|
|
425
|
-
const ended = [...drafts.keys()].filter(retiredChat);
|
|
426
|
-
if (ended.length > 0)
|
|
427
|
-
await remove(ended);
|
|
428
|
-
}
|
|
429
484
|
function retiredChat(conversation) {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
agentsRead = null;
|
|
435
|
-
});
|
|
436
|
-
return agentsRead;
|
|
485
|
+
if (!conversation.startsWith(NEW_CHAT))
|
|
486
|
+
return false;
|
|
487
|
+
const agent = conversation.slice(NEW_CHAT.length);
|
|
488
|
+
return [...listing.values()].some((entry) => entry.agent === agent && entry.agentRetired);
|
|
437
489
|
}
|
|
438
490
|
function live(conversation, change) {
|
|
439
491
|
const owed = unsent.get(conversation);
|
|
@@ -456,6 +508,7 @@ export function createConversationStore(deps) {
|
|
|
456
508
|
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
457
509
|
options: facts.has('options') ? QUIET.options : held.options,
|
|
458
510
|
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
511
|
+
subagents: facts.has('subagents') ? QUIET.subagents : held.subagents,
|
|
459
512
|
link: facts.has('link') ? QUIET.link : held.link,
|
|
460
513
|
deliveryUnknown: facts.has('deliveryUnknown')
|
|
461
514
|
? QUIET.deliveryUnknown
|
|
@@ -509,6 +562,20 @@ export function createConversationStore(deps) {
|
|
|
509
562
|
deps.publish(conversationChangeSet(changed));
|
|
510
563
|
});
|
|
511
564
|
}
|
|
565
|
+
function missed(conversation) {
|
|
566
|
+
const read = reads.get(conversation);
|
|
567
|
+
const newest = listing.get(conversation)?.newest;
|
|
568
|
+
return (read === undefined ||
|
|
569
|
+
newest === undefined ||
|
|
570
|
+
partials.has(conversation) ||
|
|
571
|
+
(newest !== null && (read === null || newest > read)));
|
|
572
|
+
}
|
|
573
|
+
function noted(conversation, message) {
|
|
574
|
+
const entry = listing.get(conversation);
|
|
575
|
+
if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
|
|
576
|
+
return;
|
|
577
|
+
listing.set(conversation, { ...entry, newest: message.position });
|
|
578
|
+
}
|
|
512
579
|
function gap(conversation) {
|
|
513
580
|
gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
|
|
514
581
|
behind.add(conversation);
|
|
@@ -543,7 +610,7 @@ export function createConversationStore(deps) {
|
|
|
543
610
|
}));
|
|
544
611
|
while (waiting.length > 0) {
|
|
545
612
|
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
546
|
-
const result = await deps.
|
|
613
|
+
const result = await deps.history({
|
|
547
614
|
conversations: asking.map(({ conversation, after }) => ({
|
|
548
615
|
conversation,
|
|
549
616
|
...(after === undefined ? {} : { after }),
|
|
@@ -646,6 +713,10 @@ export function createConversationStore(deps) {
|
|
|
646
713
|
live(conversation, { starting: event.step });
|
|
647
714
|
return;
|
|
648
715
|
}
|
|
716
|
+
if (event.kind === 'subagents') {
|
|
717
|
+
live(conversation, { subagents: structuredClone(event.subagents) });
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
649
720
|
if (event.kind === 'link') {
|
|
650
721
|
live(conversation, { link: { connected: event.connected } });
|
|
651
722
|
return;
|
|
@@ -657,6 +728,7 @@ export function createConversationStore(deps) {
|
|
|
657
728
|
const arriving = acceptedMessage(event.message);
|
|
658
729
|
if (arriving === null)
|
|
659
730
|
return;
|
|
731
|
+
noted(conversation, arriving);
|
|
660
732
|
if (replicated.has(conversation)) {
|
|
661
733
|
if (deps.full()) {
|
|
662
734
|
gap(conversation);
|
|
@@ -694,7 +766,7 @@ export function createConversationStore(deps) {
|
|
|
694
766
|
const from = newChat(agent);
|
|
695
767
|
return deps.durably(async (local) => {
|
|
696
768
|
const held = drafts.get(from);
|
|
697
|
-
const earlier =
|
|
769
|
+
const earlier = held?.moves ?? [];
|
|
698
770
|
if (earlier.includes(operation))
|
|
699
771
|
return;
|
|
700
772
|
const blank = {
|
|
@@ -723,10 +795,8 @@ export function createConversationStore(deps) {
|
|
|
723
795
|
}
|
|
724
796
|
async function submitted(conversation, operation, draft) {
|
|
725
797
|
let submission;
|
|
726
|
-
let earlier = false;
|
|
727
798
|
await withDraft(conversation, (current) => {
|
|
728
799
|
submission = current?.submitted?.find((one) => one.operation === operation);
|
|
729
|
-
earlier = submission !== undefined;
|
|
730
800
|
if (submission !== undefined)
|
|
731
801
|
return undefined;
|
|
732
802
|
const said = draft ?? current;
|
|
@@ -739,31 +809,24 @@ export function createConversationStore(deps) {
|
|
|
739
809
|
submitted: [...(current?.submitted ?? []), submission],
|
|
740
810
|
};
|
|
741
811
|
});
|
|
742
|
-
return
|
|
743
|
-
}
|
|
744
|
-
function forgotten(conversation, submission) {
|
|
745
|
-
return withDraft(conversation, (current) => {
|
|
746
|
-
const held = current?.submitted ?? [];
|
|
747
|
-
if (current === undefined || !held.includes(submission))
|
|
748
|
-
return undefined;
|
|
749
|
-
return withSubmitted(current, held.filter((one) => one !== submission));
|
|
750
|
-
});
|
|
812
|
+
return submission;
|
|
751
813
|
}
|
|
752
814
|
async function dispatched(conversation, submission) {
|
|
753
|
-
const dispatch = {};
|
|
815
|
+
const dispatch = { answered: false };
|
|
754
816
|
sending.set(submission.operation, dispatch);
|
|
755
817
|
try {
|
|
756
|
-
const result = await invoke('
|
|
757
|
-
text: submission.text,
|
|
818
|
+
const result = await invoke('conversations/send', conversation, {
|
|
758
819
|
operation_id: submission.operation,
|
|
820
|
+
text: submission.text,
|
|
759
821
|
});
|
|
822
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
760
823
|
if (result.kind === 'revoked-authorization')
|
|
761
824
|
return result;
|
|
762
825
|
if (result.kind !== 'action' && result.retryable) {
|
|
763
826
|
deps.unanswered();
|
|
764
827
|
return result;
|
|
765
828
|
}
|
|
766
|
-
const turn = answered(result, '
|
|
829
|
+
const turn = answered(result, 'message_id');
|
|
767
830
|
await withDraft(conversation, async (current, local) => {
|
|
768
831
|
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
769
832
|
if (current === undefined || held === undefined || held.turn !== null)
|
|
@@ -783,25 +846,34 @@ export function createConversationStore(deps) {
|
|
|
783
846
|
sending.delete(submission.operation);
|
|
784
847
|
}
|
|
785
848
|
}
|
|
786
|
-
function invoke(name, conversation, extra = {}) {
|
|
787
|
-
return deps.call(name, { conversation, ...extra });
|
|
849
|
+
function invoke(name, conversation, extra = { operation_id: changeBatchIdentity() }) {
|
|
850
|
+
return deps.call(name, { conversation_id: conversation, ...extra });
|
|
788
851
|
}
|
|
789
852
|
const surface = {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
853
|
+
list() {
|
|
854
|
+
return new Promise((settle) => {
|
|
855
|
+
const answer = (listed) => {
|
|
856
|
+
unlisted.delete(answer);
|
|
857
|
+
listWatchers.delete(answer);
|
|
858
|
+
settle(listed);
|
|
859
|
+
};
|
|
860
|
+
unlisted.add(answer);
|
|
861
|
+
learned();
|
|
862
|
+
});
|
|
793
863
|
},
|
|
794
864
|
async read(conversation, options = {}) {
|
|
795
|
-
const
|
|
865
|
+
const { text, ...windowed } = options;
|
|
866
|
+
const asked = askedOf(windowed);
|
|
867
|
+
const phrase = phraseOf(text);
|
|
796
868
|
return deps.durably(async (local) => {
|
|
797
|
-
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
798
|
-
const total = asked.total ? await local.messageCount(conversation) : null;
|
|
869
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before, phrase);
|
|
870
|
+
const total = asked.total ? await local.messageCount(conversation, phrase) : null;
|
|
799
871
|
return structuredClone(viewOf(conversation, messages, frameOf(asked, messages, more, total)));
|
|
800
872
|
});
|
|
801
873
|
},
|
|
802
874
|
async create(input) {
|
|
803
|
-
const result = await deps.call('
|
|
804
|
-
const conversation = answered(result, '
|
|
875
|
+
const result = await deps.call('conversations/create', input);
|
|
876
|
+
const conversation = answered(result, 'conversation_id');
|
|
805
877
|
if (conversation === null)
|
|
806
878
|
return result;
|
|
807
879
|
if (!listing.has(conversation))
|
|
@@ -822,11 +894,7 @@ export function createConversationStore(deps) {
|
|
|
822
894
|
});
|
|
823
895
|
if (held === null)
|
|
824
896
|
return DURABLE_WRITE;
|
|
825
|
-
|
|
826
|
-
if (!earlier || !deps.expired(operation))
|
|
827
|
-
return dispatched(conversation, submission);
|
|
828
|
-
await forgotten(conversation, submission);
|
|
829
|
-
return EXPIRED;
|
|
897
|
+
return dispatched(conversation, held);
|
|
830
898
|
}
|
|
831
899
|
if (draft !== undefined) {
|
|
832
900
|
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
@@ -835,38 +903,20 @@ export function createConversationStore(deps) {
|
|
|
835
903
|
}
|
|
836
904
|
return OFFLINE;
|
|
837
905
|
},
|
|
838
|
-
async attach(room, file) {
|
|
839
|
-
if (!deps.online())
|
|
840
|
-
return OFFLINE;
|
|
841
|
-
return deps.call('conversation.attach', {
|
|
842
|
-
room,
|
|
843
|
-
...(await declaredFile(file)),
|
|
844
|
-
blob: file.blob,
|
|
845
|
-
});
|
|
846
|
-
},
|
|
847
906
|
answer(conversation, answer) {
|
|
848
|
-
return invoke('
|
|
907
|
+
return invoke('conversations/interaction/answer', conversation, {
|
|
908
|
+
operation_id: changeBatchIdentity(),
|
|
909
|
+
...answer,
|
|
910
|
+
});
|
|
849
911
|
},
|
|
850
912
|
interrupt(conversation) {
|
|
851
|
-
return invoke('
|
|
913
|
+
return invoke('conversations/interrupt', conversation);
|
|
852
914
|
},
|
|
853
915
|
kill(conversation) {
|
|
854
|
-
return invoke('
|
|
855
|
-
},
|
|
856
|
-
async cancel(conversation, turn) {
|
|
857
|
-
const result = await invoke('conversation.cancel', conversation, { turn });
|
|
858
|
-
if (result.kind !== 'action')
|
|
859
|
-
return result;
|
|
860
|
-
await withDraft(conversation, (current) => {
|
|
861
|
-
const held = current?.submitted?.find((one) => one.turn === turn);
|
|
862
|
-
if (current === undefined || held === undefined)
|
|
863
|
-
return undefined;
|
|
864
|
-
return returned(current, held, current.submitted.filter((one) => one !== held));
|
|
865
|
-
});
|
|
866
|
-
return result;
|
|
916
|
+
return invoke('conversations/kill', conversation);
|
|
867
917
|
},
|
|
868
918
|
delete(conversation) {
|
|
869
|
-
return invoke('
|
|
919
|
+
return invoke('conversations/delete', conversation);
|
|
870
920
|
},
|
|
871
921
|
};
|
|
872
922
|
const chatDraft = {
|
|
@@ -895,7 +945,15 @@ export function createConversationStore(deps) {
|
|
|
895
945
|
return {
|
|
896
946
|
surface,
|
|
897
947
|
chatDraft,
|
|
898
|
-
hydrate(held, kept) {
|
|
948
|
+
hydrate(held, kept, list, cursor) {
|
|
949
|
+
if (list !== null && !listKnown) {
|
|
950
|
+
listing.clear();
|
|
951
|
+
for (const entry of list)
|
|
952
|
+
listing.set(entry.conversation, { ...entry });
|
|
953
|
+
listHeld = true;
|
|
954
|
+
listCursor = cursor;
|
|
955
|
+
deps.stream()?.hold(cursor);
|
|
956
|
+
}
|
|
899
957
|
stored.clear();
|
|
900
958
|
reads.clear();
|
|
901
959
|
partials.clear();
|
|
@@ -909,6 +967,8 @@ export function createConversationStore(deps) {
|
|
|
909
967
|
drafts.clear();
|
|
910
968
|
for (const record of kept)
|
|
911
969
|
drafts.set(record.conversation, record);
|
|
970
|
+
if (listHeld)
|
|
971
|
+
learned();
|
|
912
972
|
},
|
|
913
973
|
async reconcile() {
|
|
914
974
|
if (!listKnown)
|
|
@@ -920,7 +980,7 @@ export function createConversationStore(deps) {
|
|
|
920
980
|
!creations.has(conversation) &&
|
|
921
981
|
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
|
|
922
982
|
for (const conversation of named) {
|
|
923
|
-
if (!replicated.has(conversation))
|
|
983
|
+
if (!replicated.has(conversation) && missed(conversation))
|
|
924
984
|
behind.add(conversation);
|
|
925
985
|
}
|
|
926
986
|
replicated = named;
|
|
@@ -958,10 +1018,6 @@ export function createConversationStore(deps) {
|
|
|
958
1018
|
continue;
|
|
959
1019
|
if (deps.closed())
|
|
960
1020
|
return;
|
|
961
|
-
if (deps.expired(submission.operation)) {
|
|
962
|
-
await forgotten(conversation, submission);
|
|
963
|
-
continue;
|
|
964
|
-
}
|
|
965
1021
|
const result = await dispatched(conversation, submission);
|
|
966
1022
|
if (result.kind === 'revoked-authorization')
|
|
967
1023
|
return;
|
|
@@ -982,12 +1038,11 @@ export function createConversationStore(deps) {
|
|
|
982
1038
|
known() {
|
|
983
1039
|
return listKnown;
|
|
984
1040
|
},
|
|
985
|
-
reconnected() {
|
|
986
|
-
for (const conversation of replicated)
|
|
987
|
-
gap(conversation);
|
|
988
|
-
},
|
|
989
1041
|
reopened() {
|
|
990
|
-
|
|
1042
|
+
relisting = null;
|
|
1043
|
+
for (const [operation, dispatch] of sending)
|
|
1044
|
+
if (!dispatch.answered)
|
|
1045
|
+
sending.delete(operation);
|
|
991
1046
|
},
|
|
992
1047
|
lost() {
|
|
993
1048
|
catching.clear();
|
|
@@ -1006,15 +1061,15 @@ export function createConversationStore(deps) {
|
|
|
1006
1061
|
views.set(key, view);
|
|
1007
1062
|
const watcher = { notify: deliver, ready: false };
|
|
1008
1063
|
view.watchers.add(watcher);
|
|
1009
|
-
|
|
1010
|
-
|
|
1064
|
+
const reading = new AbortController();
|
|
1065
|
+
void untilAnswered(() => deps.durably(async (local) => {
|
|
1011
1066
|
if (view.window !== null)
|
|
1012
1067
|
return;
|
|
1013
1068
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
1014
1069
|
view.window = messages;
|
|
1015
1070
|
view.more = more;
|
|
1016
1071
|
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
1017
|
-
})
|
|
1072
|
+
}), reading.signal)
|
|
1018
1073
|
.then(() => {
|
|
1019
1074
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
1020
1075
|
return;
|
|
@@ -1024,6 +1079,7 @@ export function createConversationStore(deps) {
|
|
|
1024
1079
|
})
|
|
1025
1080
|
.catch(() => { });
|
|
1026
1081
|
return () => {
|
|
1082
|
+
reading.abort();
|
|
1027
1083
|
if (!view.watchers.delete(watcher))
|
|
1028
1084
|
return;
|
|
1029
1085
|
if (view.watchers.size === 0)
|
|
@@ -1031,77 +1087,88 @@ export function createConversationStore(deps) {
|
|
|
1031
1087
|
};
|
|
1032
1088
|
},
|
|
1033
1089
|
watchList(deliver) {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
if (!deps.closed() && listWatchers.has(deliver))
|
|
1037
|
-
deliver(entries());
|
|
1038
|
-
});
|
|
1090
|
+
unlisted.add(deliver);
|
|
1091
|
+
learned();
|
|
1039
1092
|
return () => {
|
|
1093
|
+
unlisted.delete(deliver);
|
|
1040
1094
|
listWatchers.delete(deliver);
|
|
1041
1095
|
};
|
|
1042
1096
|
},
|
|
1043
1097
|
watchAgents(deliver) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
deliver(agents());
|
|
1048
|
-
});
|
|
1098
|
+
unnamed.add(deliver);
|
|
1099
|
+
learned();
|
|
1100
|
+
readAgents();
|
|
1049
1101
|
return () => {
|
|
1102
|
+
unnamed.delete(deliver);
|
|
1050
1103
|
agentWatchers.delete(deliver);
|
|
1051
1104
|
};
|
|
1052
1105
|
},
|
|
1106
|
+
learned,
|
|
1053
1107
|
changed(set) {
|
|
1054
1108
|
for (const conversation of set.conversations)
|
|
1055
1109
|
emit(conversation);
|
|
1056
|
-
const declaration = deps.agents();
|
|
1057
|
-
if (declaration !== undefined &&
|
|
1058
|
-
set.documents.some((change) => change.locator === declaration.locator)) {
|
|
1059
|
-
agentsRead = readAgents().catch(() => {
|
|
1060
|
-
agentsRead = null;
|
|
1061
|
-
});
|
|
1062
|
-
}
|
|
1063
1110
|
},
|
|
1064
1111
|
receive(event) {
|
|
1065
1112
|
if (deps.closed())
|
|
1066
1113
|
return false;
|
|
1067
1114
|
if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted') {
|
|
1068
1115
|
if (event.kind === 'list') {
|
|
1069
|
-
|
|
1116
|
+
if (event.whole)
|
|
1117
|
+
relisting ??= new Map();
|
|
1070
1118
|
for (const entry of event.entries) {
|
|
1071
|
-
|
|
1072
|
-
|
|
1119
|
+
if (relisting === null)
|
|
1120
|
+
listed(entry);
|
|
1121
|
+
else
|
|
1122
|
+
relisting.set(entry.conversation, { ...entry });
|
|
1123
|
+
}
|
|
1124
|
+
if (event.more)
|
|
1125
|
+
return false;
|
|
1126
|
+
if (relisting !== null) {
|
|
1127
|
+
listing.clear();
|
|
1128
|
+
for (const entry of relisting.values())
|
|
1129
|
+
listed(entry);
|
|
1130
|
+
relisting = null;
|
|
1073
1131
|
}
|
|
1132
|
+
listCursor = event.cursor;
|
|
1133
|
+
deps.stream()?.hold(event.cursor);
|
|
1074
1134
|
listKnown = true;
|
|
1135
|
+
for (const conversation of replicated) {
|
|
1136
|
+
if (!listing.has(conversation))
|
|
1137
|
+
continue;
|
|
1138
|
+
if (!missed(conversation))
|
|
1139
|
+
behind.delete(conversation);
|
|
1140
|
+
else if (!behind.has(conversation))
|
|
1141
|
+
gap(conversation);
|
|
1142
|
+
}
|
|
1075
1143
|
openingEnded();
|
|
1076
1144
|
}
|
|
1077
1145
|
else if (event.kind === 'listed') {
|
|
1078
|
-
|
|
1079
|
-
|
|
1146
|
+
listed(event.entry);
|
|
1147
|
+
relisting?.set(event.entry.conversation, { ...event.entry });
|
|
1080
1148
|
}
|
|
1081
1149
|
else {
|
|
1082
1150
|
listing.delete(event.conversation);
|
|
1151
|
+
relisting?.delete(event.conversation);
|
|
1083
1152
|
}
|
|
1153
|
+
keepList();
|
|
1084
1154
|
emitList();
|
|
1085
|
-
return (event.kind !== 'list' &&
|
|
1155
|
+
return ((event.kind !== 'list' &&
|
|
1086
1156
|
listKnown &&
|
|
1087
1157
|
(listing.size !== replicated.size ||
|
|
1088
|
-
[...listing.keys()].some((conversation) => !replicated.has(conversation))))
|
|
1158
|
+
[...listing.keys()].some((conversation) => !replicated.has(conversation)))) ||
|
|
1159
|
+
(listKnown && [...drafts.keys()].some(retiredChat)));
|
|
1089
1160
|
}
|
|
1090
1161
|
heard(event);
|
|
1091
1162
|
return false;
|
|
1092
1163
|
},
|
|
1093
|
-
searchable() {
|
|
1094
|
-
return [...(listKnown ? listing.keys() : stored)].sort();
|
|
1095
|
-
},
|
|
1096
|
-
acquired(conversation) {
|
|
1097
|
-
return reads.has(conversation) && !partials.has(conversation);
|
|
1098
|
-
},
|
|
1099
1164
|
close() {
|
|
1100
1165
|
views.clear();
|
|
1101
1166
|
lives.clear();
|
|
1102
1167
|
unsent.clear();
|
|
1103
1168
|
listWatchers.clear();
|
|
1169
|
+
unlisted.clear();
|
|
1104
1170
|
agentWatchers.clear();
|
|
1171
|
+
unnamed.clear();
|
|
1105
1172
|
},
|
|
1106
1173
|
};
|
|
1107
1174
|
}
|