@agentshouse/mdruntime 0.1.0-ce15a88ae8478 → 0.1.0-ce41fec66d91b
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 +10 -8
- package/dist/adapter.d.ts +71 -59
- 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 +16 -8
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +142 -94
- package/dist/client.d.ts +8 -10
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -8
- package/dist/collection.d.ts +5 -3
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +24 -19
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +95 -30
- package/dist/connection.d.ts +8 -8
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1304 -1071
- package/dist/conversation.d.ts +13 -11
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +244 -136
- 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 +1 -0
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +1 -1
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/fulltext.d.ts.map +1 -1
- package/dist/fulltext.js +8 -6
- package/dist/host.d.ts +3 -4
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +40 -20
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- 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 +9 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +175 -98
- package/dist/model.d.ts +6 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -10
- package/dist/observation.d.ts +1 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +1 -1
- 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 +6 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/reach.d.ts +8 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +67 -51
- package/dist/readiness.d.ts +13 -14
- 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 +85 -30
- package/dist/replica.d.ts +5 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +4 -7
- package/dist/room-draft.d.ts +18 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +73 -6
- package/dist/rows.d.ts +15 -6
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +102 -74
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +13 -7
- 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 +20 -26
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +27 -51
- package/dist/stored.d.ts +10 -18
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +209 -193
- package/dist/tables.d.ts +28 -35
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +58 -50
- 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 +35 -96
- package/dist/wire.d.ts +5 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +2 -3
- package/dist/words.d.ts.map +1 -1
- package/dist/words.js +8 -2
- package/package.json +11 -18
- package/AGENTS.md +0 -319
- 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/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/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -98
package/dist/conversation.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { conversationChangeSet } from './change-set.js';
|
|
2
2
|
import { runtimeError } from './failure.js';
|
|
3
|
-
import {
|
|
3
|
+
import { refusedForSpace } from './durability.js';
|
|
4
4
|
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
5
5
|
import { OFFLINE } from './outcome.js';
|
|
6
|
+
import { untilAnswered } from './recovery.js';
|
|
6
7
|
import { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
|
|
7
8
|
const QUIET = {
|
|
8
9
|
turn: null,
|
|
@@ -11,6 +12,7 @@ const QUIET = {
|
|
|
11
12
|
commands: [],
|
|
12
13
|
options: [],
|
|
13
14
|
starting: null,
|
|
15
|
+
subagents: [],
|
|
14
16
|
link: null,
|
|
15
17
|
deliveryUnknown: [],
|
|
16
18
|
};
|
|
@@ -20,6 +22,7 @@ const FACTS = [
|
|
|
20
22
|
'commands',
|
|
21
23
|
'options',
|
|
22
24
|
'starting',
|
|
25
|
+
'subagents',
|
|
23
26
|
'link',
|
|
24
27
|
'deliveryUnknown',
|
|
25
28
|
];
|
|
@@ -33,6 +36,7 @@ export function unheldView(conversation) {
|
|
|
33
36
|
commands: [],
|
|
34
37
|
options: [],
|
|
35
38
|
starting: null,
|
|
39
|
+
subagents: [],
|
|
36
40
|
link: null,
|
|
37
41
|
deliveryUnknown: [],
|
|
38
42
|
chatDraft: null,
|
|
@@ -40,6 +44,7 @@ export function unheldView(conversation) {
|
|
|
40
44
|
}
|
|
41
45
|
export const SESSION_STARTED = 'Session started';
|
|
42
46
|
const NEW_CHAT = 'new:';
|
|
47
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
43
48
|
export function newChat(agent) {
|
|
44
49
|
return `${NEW_CHAT}${agent}`;
|
|
45
50
|
}
|
|
@@ -209,6 +214,12 @@ function askedOf(options) {
|
|
|
209
214
|
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
210
215
|
}
|
|
211
216
|
const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
|
|
217
|
+
const DURABLE_WRITE = {
|
|
218
|
+
kind: 'rejected',
|
|
219
|
+
code: 'durable-write',
|
|
220
|
+
fields: {},
|
|
221
|
+
retryable: true,
|
|
222
|
+
};
|
|
212
223
|
function unwritten(draft) {
|
|
213
224
|
return draft.text === '';
|
|
214
225
|
}
|
|
@@ -248,13 +259,19 @@ export function createConversationStore(deps) {
|
|
|
248
259
|
const unsent = new Map();
|
|
249
260
|
const views = new Map();
|
|
250
261
|
const listing = new Map();
|
|
262
|
+
let relisting = null;
|
|
263
|
+
let listCursor = null;
|
|
251
264
|
const creations = new Set();
|
|
252
265
|
const listWatchers = new Set();
|
|
266
|
+
const unlisted = new Set();
|
|
253
267
|
let listKnown = false;
|
|
268
|
+
let listHeld = false;
|
|
269
|
+
let listKept = false;
|
|
254
270
|
const agentWatchers = new Set();
|
|
255
|
-
|
|
256
|
-
let
|
|
257
|
-
let
|
|
271
|
+
const unnamed = new Set();
|
|
272
|
+
let agentsShown = null;
|
|
273
|
+
let listedAgents = null;
|
|
274
|
+
let agentsReading = false;
|
|
258
275
|
let replicated = new Set();
|
|
259
276
|
let handedReplicated;
|
|
260
277
|
function liveOf(conversation) {
|
|
@@ -278,6 +295,7 @@ export function createConversationStore(deps) {
|
|
|
278
295
|
commands: structuredClone(facts.commands),
|
|
279
296
|
options: structuredClone(facts.options),
|
|
280
297
|
starting: facts.starting,
|
|
298
|
+
subagents: structuredClone(facts.subagents),
|
|
281
299
|
link: facts.link === null ? null : { ...facts.link },
|
|
282
300
|
deliveryUnknown: [...facts.deliveryUnknown],
|
|
283
301
|
chatDraft: draft === undefined || unwritten(draft)
|
|
@@ -333,7 +351,7 @@ export function createConversationStore(deps) {
|
|
|
333
351
|
function entries() {
|
|
334
352
|
return [...listing.values()].map((entry) => ({
|
|
335
353
|
conversation: entry.conversation,
|
|
336
|
-
agent: { identity: entry.agent, name:
|
|
354
|
+
agent: { identity: entry.agent, name: entry.agentName },
|
|
337
355
|
name: entry.name,
|
|
338
356
|
created: entry.created,
|
|
339
357
|
finished: entry.finished,
|
|
@@ -343,25 +361,100 @@ export function createConversationStore(deps) {
|
|
|
343
361
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
344
362
|
}));
|
|
345
363
|
}
|
|
364
|
+
function keepList() {
|
|
365
|
+
if (!listKnown || listKept)
|
|
366
|
+
return;
|
|
367
|
+
listKept = true;
|
|
368
|
+
queueMicrotask(() => {
|
|
369
|
+
listKept = false;
|
|
370
|
+
if (deps.closed())
|
|
371
|
+
return;
|
|
372
|
+
const entries = [...listing.values()];
|
|
373
|
+
const cursor = listCursor;
|
|
374
|
+
void deps
|
|
375
|
+
.durably(async (local) => {
|
|
376
|
+
await local.fact('conversationList', entries);
|
|
377
|
+
await local.fact('conversationCursor', cursor);
|
|
378
|
+
})
|
|
379
|
+
.catch(() => { });
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function listed(entry) {
|
|
383
|
+
listing.set(entry.conversation, { ...entry });
|
|
384
|
+
creations.delete(entry.conversation);
|
|
385
|
+
}
|
|
346
386
|
function emitList() {
|
|
347
|
-
if (deps.closed()
|
|
387
|
+
if (deps.closed())
|
|
348
388
|
return;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
watcher
|
|
389
|
+
if (listWatchers.size > 0) {
|
|
390
|
+
const value = entries();
|
|
391
|
+
for (const watcher of listWatchers)
|
|
392
|
+
watcher(value);
|
|
393
|
+
}
|
|
394
|
+
emitAgents();
|
|
395
|
+
learned();
|
|
396
|
+
}
|
|
397
|
+
function learned() {
|
|
398
|
+
if (deps.closed())
|
|
399
|
+
return;
|
|
400
|
+
if (!listKnown && !listHeld && deps.stream() !== undefined && deps.online())
|
|
401
|
+
return;
|
|
402
|
+
if (unlisted.size > 0) {
|
|
403
|
+
const value = entries();
|
|
404
|
+
for (const watcher of [...unlisted]) {
|
|
405
|
+
unlisted.delete(watcher);
|
|
406
|
+
listWatchers.add(watcher);
|
|
407
|
+
watcher(value);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (unnamed.size > 0) {
|
|
411
|
+
const value = agents();
|
|
412
|
+
for (const watcher of [...unnamed]) {
|
|
413
|
+
unnamed.delete(watcher);
|
|
414
|
+
agentWatchers.add(watcher);
|
|
415
|
+
watcher(value);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
352
418
|
}
|
|
353
419
|
function agents() {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
.
|
|
420
|
+
const named = new Map();
|
|
421
|
+
for (const agent of listedAgents ?? [])
|
|
422
|
+
named.set(agent.agent, agent);
|
|
423
|
+
for (const entry of listing.values()) {
|
|
424
|
+
named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
|
|
425
|
+
}
|
|
426
|
+
return [...named]
|
|
427
|
+
.filter(([, agent]) => !agent.retired)
|
|
428
|
+
.map(([identity, agent]) => ({ identity, name: agent.name }))
|
|
357
429
|
.sort((left, right) => left.name === right.name
|
|
358
430
|
? left.identity.localeCompare(right.identity)
|
|
359
431
|
: left.name.localeCompare(right.name));
|
|
360
432
|
}
|
|
433
|
+
function readAgents() {
|
|
434
|
+
const stream = deps.stream();
|
|
435
|
+
if (stream?.agents === undefined || !deps.online() || agentsReading)
|
|
436
|
+
return;
|
|
437
|
+
agentsReading = true;
|
|
438
|
+
void stream
|
|
439
|
+
.agents()
|
|
440
|
+
.then((read) => {
|
|
441
|
+
if (read === null)
|
|
442
|
+
return;
|
|
443
|
+
listedAgents = read;
|
|
444
|
+
emitAgents();
|
|
445
|
+
}, () => { })
|
|
446
|
+
.finally(() => {
|
|
447
|
+
agentsReading = false;
|
|
448
|
+
});
|
|
449
|
+
}
|
|
361
450
|
function emitAgents() {
|
|
362
451
|
if (deps.closed() || agentWatchers.size === 0)
|
|
363
452
|
return;
|
|
364
453
|
const value = agents();
|
|
454
|
+
const shown = JSON.stringify(value);
|
|
455
|
+
if (shown === agentsShown)
|
|
456
|
+
return;
|
|
457
|
+
agentsShown = shown;
|
|
365
458
|
for (const watcher of agentWatchers)
|
|
366
459
|
watcher(value);
|
|
367
460
|
}
|
|
@@ -377,55 +470,11 @@ export function createConversationStore(deps) {
|
|
|
377
470
|
if (stateOf(conversation) !== before || next?.turn?.started !== began)
|
|
378
471
|
emitList();
|
|
379
472
|
}
|
|
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
473
|
function retiredChat(conversation) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
agentsRead = null;
|
|
427
|
-
});
|
|
428
|
-
return agentsRead;
|
|
474
|
+
if (!conversation.startsWith(NEW_CHAT))
|
|
475
|
+
return false;
|
|
476
|
+
const agent = conversation.slice(NEW_CHAT.length);
|
|
477
|
+
return [...listing.values()].some((entry) => entry.agent === agent && entry.agentRetired);
|
|
429
478
|
}
|
|
430
479
|
function live(conversation, change) {
|
|
431
480
|
const owed = unsent.get(conversation);
|
|
@@ -448,6 +497,7 @@ export function createConversationStore(deps) {
|
|
|
448
497
|
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
449
498
|
options: facts.has('options') ? QUIET.options : held.options,
|
|
450
499
|
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
500
|
+
subagents: facts.has('subagents') ? QUIET.subagents : held.subagents,
|
|
451
501
|
link: facts.has('link') ? QUIET.link : held.link,
|
|
452
502
|
deliveryUnknown: facts.has('deliveryUnknown')
|
|
453
503
|
? QUIET.deliveryUnknown
|
|
@@ -501,6 +551,20 @@ export function createConversationStore(deps) {
|
|
|
501
551
|
deps.publish(conversationChangeSet(changed));
|
|
502
552
|
});
|
|
503
553
|
}
|
|
554
|
+
function missed(conversation) {
|
|
555
|
+
const read = reads.get(conversation);
|
|
556
|
+
const newest = listing.get(conversation)?.newest;
|
|
557
|
+
return (read === undefined ||
|
|
558
|
+
newest === undefined ||
|
|
559
|
+
partials.has(conversation) ||
|
|
560
|
+
(newest !== null && (read === null || newest > read)));
|
|
561
|
+
}
|
|
562
|
+
function noted(conversation, message) {
|
|
563
|
+
const entry = listing.get(conversation);
|
|
564
|
+
if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
|
|
565
|
+
return;
|
|
566
|
+
listing.set(conversation, { ...entry, newest: message.position });
|
|
567
|
+
}
|
|
504
568
|
function gap(conversation) {
|
|
505
569
|
gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
|
|
506
570
|
behind.add(conversation);
|
|
@@ -529,12 +593,13 @@ export function createConversationStore(deps) {
|
|
|
529
593
|
}
|
|
530
594
|
async function readHistories(conversations, ended) {
|
|
531
595
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
532
|
-
let
|
|
596
|
+
let waiting = conversations.map((conversation) => ({
|
|
533
597
|
conversation,
|
|
534
598
|
after: reads.get(conversation) ?? undefined,
|
|
535
599
|
}));
|
|
536
|
-
while (
|
|
537
|
-
const
|
|
600
|
+
while (waiting.length > 0) {
|
|
601
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
602
|
+
const result = await deps.history({
|
|
538
603
|
conversations: asking.map(({ conversation, after }) => ({
|
|
539
604
|
conversation,
|
|
540
605
|
...(after === undefined ? {} : { after }),
|
|
@@ -557,7 +622,7 @@ export function createConversationStore(deps) {
|
|
|
557
622
|
if (!following.some((next) => next.conversation === conversation))
|
|
558
623
|
ended(conversation);
|
|
559
624
|
}
|
|
560
|
-
|
|
625
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
561
626
|
}
|
|
562
627
|
return null;
|
|
563
628
|
}
|
|
@@ -637,6 +702,10 @@ export function createConversationStore(deps) {
|
|
|
637
702
|
live(conversation, { starting: event.step });
|
|
638
703
|
return;
|
|
639
704
|
}
|
|
705
|
+
if (event.kind === 'subagents') {
|
|
706
|
+
live(conversation, { subagents: structuredClone(event.subagents) });
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
640
709
|
if (event.kind === 'link') {
|
|
641
710
|
live(conversation, { link: { connected: event.connected } });
|
|
642
711
|
return;
|
|
@@ -648,8 +717,16 @@ export function createConversationStore(deps) {
|
|
|
648
717
|
const arriving = acceptedMessage(event.message);
|
|
649
718
|
if (arriving === null)
|
|
650
719
|
return;
|
|
720
|
+
noted(conversation, arriving);
|
|
651
721
|
if (replicated.has(conversation)) {
|
|
652
|
-
|
|
722
|
+
if (deps.full()) {
|
|
723
|
+
gap(conversation);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
void keep(conversation, arriving).catch((error) => {
|
|
727
|
+
if (refusedForSpace(error))
|
|
728
|
+
gap(conversation);
|
|
729
|
+
});
|
|
653
730
|
return;
|
|
654
731
|
}
|
|
655
732
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -734,20 +811,21 @@ export function createConversationStore(deps) {
|
|
|
734
811
|
});
|
|
735
812
|
}
|
|
736
813
|
async function dispatched(conversation, submission) {
|
|
737
|
-
const dispatch = {};
|
|
814
|
+
const dispatch = { answered: false };
|
|
738
815
|
sending.set(submission.operation, dispatch);
|
|
739
816
|
try {
|
|
740
|
-
const result = await invoke('
|
|
741
|
-
text: submission.text,
|
|
817
|
+
const result = await invoke('conversations/send', conversation, {
|
|
742
818
|
operation_id: submission.operation,
|
|
819
|
+
text: submission.text,
|
|
743
820
|
});
|
|
821
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
744
822
|
if (result.kind === 'revoked-authorization')
|
|
745
823
|
return result;
|
|
746
824
|
if (result.kind !== 'action' && result.retryable) {
|
|
747
825
|
deps.unanswered();
|
|
748
826
|
return result;
|
|
749
827
|
}
|
|
750
|
-
const turn = answered(result, '
|
|
828
|
+
const turn = answered(result, 'message_id');
|
|
751
829
|
await withDraft(conversation, async (current, local) => {
|
|
752
830
|
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
753
831
|
if (current === undefined || held === undefined || held.turn !== null)
|
|
@@ -767,13 +845,20 @@ export function createConversationStore(deps) {
|
|
|
767
845
|
sending.delete(submission.operation);
|
|
768
846
|
}
|
|
769
847
|
}
|
|
770
|
-
function invoke(name, conversation, extra = {}) {
|
|
771
|
-
return deps.call(name, { conversation, ...extra });
|
|
848
|
+
function invoke(name, conversation, extra = { operation_id: changeBatchIdentity() }) {
|
|
849
|
+
return deps.call(name, { conversation_id: conversation, ...extra });
|
|
772
850
|
}
|
|
773
851
|
const surface = {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
852
|
+
list() {
|
|
853
|
+
return new Promise((settle) => {
|
|
854
|
+
const answer = (listed) => {
|
|
855
|
+
unlisted.delete(answer);
|
|
856
|
+
listWatchers.delete(answer);
|
|
857
|
+
settle(listed);
|
|
858
|
+
};
|
|
859
|
+
unlisted.add(answer);
|
|
860
|
+
learned();
|
|
861
|
+
});
|
|
777
862
|
},
|
|
778
863
|
async read(conversation, options = {}) {
|
|
779
864
|
const asked = askedOf(options);
|
|
@@ -784,8 +869,8 @@ export function createConversationStore(deps) {
|
|
|
784
869
|
});
|
|
785
870
|
},
|
|
786
871
|
async create(input) {
|
|
787
|
-
const result = await deps.call('
|
|
788
|
-
const conversation = answered(result, '
|
|
872
|
+
const result = await deps.call('conversations/create', input);
|
|
873
|
+
const conversation = answered(result, 'conversation_id');
|
|
789
874
|
if (conversation === null)
|
|
790
875
|
return result;
|
|
791
876
|
if (!listing.has(conversation))
|
|
@@ -796,8 +881,17 @@ export function createConversationStore(deps) {
|
|
|
796
881
|
return result;
|
|
797
882
|
},
|
|
798
883
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
884
|
+
if (deps.full())
|
|
885
|
+
return DURABLE_WRITE;
|
|
799
886
|
if (deps.online()) {
|
|
800
|
-
const
|
|
887
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
888
|
+
if (refusedForSpace(error))
|
|
889
|
+
return null;
|
|
890
|
+
throw error;
|
|
891
|
+
});
|
|
892
|
+
if (held === null)
|
|
893
|
+
return DURABLE_WRITE;
|
|
894
|
+
const { submission, earlier } = held;
|
|
801
895
|
if (!earlier || !deps.expired(operation))
|
|
802
896
|
return dispatched(conversation, submission);
|
|
803
897
|
await forgotten(conversation, submission);
|
|
@@ -810,38 +904,20 @@ export function createConversationStore(deps) {
|
|
|
810
904
|
}
|
|
811
905
|
return OFFLINE;
|
|
812
906
|
},
|
|
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
907
|
answer(conversation, answer) {
|
|
823
|
-
return invoke('
|
|
908
|
+
return invoke('conversations/interaction/answer', conversation, {
|
|
909
|
+
operation_id: changeBatchIdentity(),
|
|
910
|
+
...answer,
|
|
911
|
+
});
|
|
824
912
|
},
|
|
825
913
|
interrupt(conversation) {
|
|
826
|
-
return invoke('
|
|
914
|
+
return invoke('conversations/interrupt', conversation);
|
|
827
915
|
},
|
|
828
916
|
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;
|
|
917
|
+
return invoke('conversations/kill', conversation);
|
|
842
918
|
},
|
|
843
919
|
delete(conversation) {
|
|
844
|
-
return invoke('
|
|
920
|
+
return invoke('conversations/delete', conversation);
|
|
845
921
|
},
|
|
846
922
|
};
|
|
847
923
|
const chatDraft = {
|
|
@@ -870,7 +946,15 @@ export function createConversationStore(deps) {
|
|
|
870
946
|
return {
|
|
871
947
|
surface,
|
|
872
948
|
chatDraft,
|
|
873
|
-
hydrate(held, kept) {
|
|
949
|
+
hydrate(held, kept, list, cursor) {
|
|
950
|
+
if (list !== null && !listKnown) {
|
|
951
|
+
listing.clear();
|
|
952
|
+
for (const entry of list)
|
|
953
|
+
listing.set(entry.conversation, { ...entry });
|
|
954
|
+
listHeld = true;
|
|
955
|
+
listCursor = cursor;
|
|
956
|
+
deps.stream()?.hold(cursor);
|
|
957
|
+
}
|
|
874
958
|
stored.clear();
|
|
875
959
|
reads.clear();
|
|
876
960
|
partials.clear();
|
|
@@ -884,6 +968,8 @@ export function createConversationStore(deps) {
|
|
|
884
968
|
drafts.clear();
|
|
885
969
|
for (const record of kept)
|
|
886
970
|
drafts.set(record.conversation, record);
|
|
971
|
+
if (listHeld)
|
|
972
|
+
learned();
|
|
887
973
|
},
|
|
888
974
|
async reconcile() {
|
|
889
975
|
if (!listKnown)
|
|
@@ -895,7 +981,7 @@ export function createConversationStore(deps) {
|
|
|
895
981
|
!creations.has(conversation) &&
|
|
896
982
|
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
|
|
897
983
|
for (const conversation of named) {
|
|
898
|
-
if (!replicated.has(conversation))
|
|
984
|
+
if (!replicated.has(conversation) && missed(conversation))
|
|
899
985
|
behind.add(conversation);
|
|
900
986
|
}
|
|
901
987
|
replicated = named;
|
|
@@ -904,6 +990,11 @@ export function createConversationStore(deps) {
|
|
|
904
990
|
await remove(leaving);
|
|
905
991
|
},
|
|
906
992
|
async catchUp(progress) {
|
|
993
|
+
if (deps.full()) {
|
|
994
|
+
if (behind.size > 0)
|
|
995
|
+
progress.complete = false;
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
907
998
|
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
908
999
|
const read = async (conversations) => {
|
|
909
1000
|
if (conversations.length === 0 || deps.closed())
|
|
@@ -952,12 +1043,11 @@ export function createConversationStore(deps) {
|
|
|
952
1043
|
known() {
|
|
953
1044
|
return listKnown;
|
|
954
1045
|
},
|
|
955
|
-
reconnected() {
|
|
956
|
-
for (const conversation of replicated)
|
|
957
|
-
gap(conversation);
|
|
958
|
-
},
|
|
959
1046
|
reopened() {
|
|
960
|
-
|
|
1047
|
+
relisting = null;
|
|
1048
|
+
for (const [operation, dispatch] of sending)
|
|
1049
|
+
if (!dispatch.answered)
|
|
1050
|
+
sending.delete(operation);
|
|
961
1051
|
},
|
|
962
1052
|
lost() {
|
|
963
1053
|
catching.clear();
|
|
@@ -976,15 +1066,15 @@ export function createConversationStore(deps) {
|
|
|
976
1066
|
views.set(key, view);
|
|
977
1067
|
const watcher = { notify: deliver, ready: false };
|
|
978
1068
|
view.watchers.add(watcher);
|
|
979
|
-
|
|
980
|
-
|
|
1069
|
+
const reading = new AbortController();
|
|
1070
|
+
void untilAnswered(() => deps.durably(async (local) => {
|
|
981
1071
|
if (view.window !== null)
|
|
982
1072
|
return;
|
|
983
1073
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
984
1074
|
view.window = messages;
|
|
985
1075
|
view.more = more;
|
|
986
1076
|
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
987
|
-
})
|
|
1077
|
+
}), reading.signal)
|
|
988
1078
|
.then(() => {
|
|
989
1079
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
990
1080
|
return;
|
|
@@ -994,6 +1084,7 @@ export function createConversationStore(deps) {
|
|
|
994
1084
|
})
|
|
995
1085
|
.catch(() => { });
|
|
996
1086
|
return () => {
|
|
1087
|
+
reading.abort();
|
|
997
1088
|
if (!view.watchers.delete(watcher))
|
|
998
1089
|
return;
|
|
999
1090
|
if (view.watchers.size === 0)
|
|
@@ -1001,61 +1092,76 @@ export function createConversationStore(deps) {
|
|
|
1001
1092
|
};
|
|
1002
1093
|
},
|
|
1003
1094
|
watchList(deliver) {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
if (!deps.closed() && listWatchers.has(deliver))
|
|
1007
|
-
deliver(entries());
|
|
1008
|
-
});
|
|
1095
|
+
unlisted.add(deliver);
|
|
1096
|
+
learned();
|
|
1009
1097
|
return () => {
|
|
1098
|
+
unlisted.delete(deliver);
|
|
1010
1099
|
listWatchers.delete(deliver);
|
|
1011
1100
|
};
|
|
1012
1101
|
},
|
|
1013
1102
|
watchAgents(deliver) {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
deliver(agents());
|
|
1018
|
-
});
|
|
1103
|
+
unnamed.add(deliver);
|
|
1104
|
+
learned();
|
|
1105
|
+
readAgents();
|
|
1019
1106
|
return () => {
|
|
1107
|
+
unnamed.delete(deliver);
|
|
1020
1108
|
agentWatchers.delete(deliver);
|
|
1021
1109
|
};
|
|
1022
1110
|
},
|
|
1111
|
+
learned,
|
|
1023
1112
|
changed(set) {
|
|
1024
1113
|
for (const conversation of set.conversations)
|
|
1025
1114
|
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
1115
|
},
|
|
1034
1116
|
receive(event) {
|
|
1035
1117
|
if (deps.closed())
|
|
1036
1118
|
return false;
|
|
1037
1119
|
if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted') {
|
|
1038
1120
|
if (event.kind === 'list') {
|
|
1039
|
-
|
|
1121
|
+
if (event.whole)
|
|
1122
|
+
relisting ??= new Map();
|
|
1040
1123
|
for (const entry of event.entries) {
|
|
1041
|
-
|
|
1042
|
-
|
|
1124
|
+
if (relisting === null)
|
|
1125
|
+
listed(entry);
|
|
1126
|
+
else
|
|
1127
|
+
relisting.set(entry.conversation, { ...entry });
|
|
1043
1128
|
}
|
|
1129
|
+
if (event.more)
|
|
1130
|
+
return false;
|
|
1131
|
+
if (relisting !== null) {
|
|
1132
|
+
listing.clear();
|
|
1133
|
+
for (const entry of relisting.values())
|
|
1134
|
+
listed(entry);
|
|
1135
|
+
relisting = null;
|
|
1136
|
+
}
|
|
1137
|
+
listCursor = event.cursor;
|
|
1138
|
+
deps.stream()?.hold(event.cursor);
|
|
1044
1139
|
listKnown = true;
|
|
1140
|
+
for (const conversation of replicated) {
|
|
1141
|
+
if (!listing.has(conversation))
|
|
1142
|
+
continue;
|
|
1143
|
+
if (!missed(conversation))
|
|
1144
|
+
behind.delete(conversation);
|
|
1145
|
+
else if (!behind.has(conversation))
|
|
1146
|
+
gap(conversation);
|
|
1147
|
+
}
|
|
1045
1148
|
openingEnded();
|
|
1046
1149
|
}
|
|
1047
1150
|
else if (event.kind === 'listed') {
|
|
1048
|
-
|
|
1049
|
-
|
|
1151
|
+
listed(event.entry);
|
|
1152
|
+
relisting?.set(event.entry.conversation, { ...event.entry });
|
|
1050
1153
|
}
|
|
1051
1154
|
else {
|
|
1052
1155
|
listing.delete(event.conversation);
|
|
1156
|
+
relisting?.delete(event.conversation);
|
|
1053
1157
|
}
|
|
1158
|
+
keepList();
|
|
1054
1159
|
emitList();
|
|
1055
|
-
return (event.kind !== 'list' &&
|
|
1160
|
+
return ((event.kind !== 'list' &&
|
|
1056
1161
|
listKnown &&
|
|
1057
1162
|
(listing.size !== replicated.size ||
|
|
1058
|
-
[...listing.keys()].some((conversation) => !replicated.has(conversation))))
|
|
1163
|
+
[...listing.keys()].some((conversation) => !replicated.has(conversation)))) ||
|
|
1164
|
+
(listKnown && [...drafts.keys()].some(retiredChat)));
|
|
1059
1165
|
}
|
|
1060
1166
|
heard(event);
|
|
1061
1167
|
return false;
|
|
@@ -1071,7 +1177,9 @@ export function createConversationStore(deps) {
|
|
|
1071
1177
|
lives.clear();
|
|
1072
1178
|
unsent.clear();
|
|
1073
1179
|
listWatchers.clear();
|
|
1180
|
+
unlisted.clear();
|
|
1074
1181
|
agentWatchers.clear();
|
|
1182
|
+
unnamed.clear();
|
|
1075
1183
|
},
|
|
1076
1184
|
};
|
|
1077
1185
|
}
|
package/dist/durability.d.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import type { Persistence } from './readiness.js';
|
|
2
|
-
export type StorageEstimate = {
|
|
3
|
-
readonly usage: number;
|
|
4
|
-
readonly total: number;
|
|
5
|
-
};
|
|
6
2
|
export type RuntimeShell = {
|
|
7
3
|
persistence: Persistence;
|
|
8
4
|
generation: string | null;
|
|
9
5
|
keepGeneration(value: string): void | Promise<void>;
|
|
10
6
|
dropGeneration(): void | Promise<void>;
|
|
11
|
-
estimate?(): Promise<StorageEstimate | null>;
|
|
12
7
|
cleanUp?(): Promise<number>;
|
|
13
8
|
};
|
|
9
|
+
export declare function refusedForSpace(error: unknown): boolean;
|
|
14
10
|
export declare function detectStorageLoss(stored: string | null, reported: string | null): string | null;
|
|
15
11
|
export declare function nextGeneration(stored: string | null, reported: string | null): string;
|
|
16
12
|
//# sourceMappingURL=durability.d.ts.map
|