@agentshouse/mdruntime 0.1.0-cd1c52311c638 → 0.1.0-cd3ee807e46ae
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/AGENTS.md +75 -26
- package/README.md +11 -1
- package/dist/adapter.d.ts +35 -11
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attempt.d.ts +16 -0
- package/dist/attempt.d.ts.map +1 -0
- package/dist/attempt.js +57 -0
- package/dist/binary.d.ts +23 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +8 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +5 -8
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +8 -7
- package/dist/change.d.ts +11 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +26 -1
- package/dist/chat/acts.d.ts +34 -0
- package/dist/chat/acts.d.ts.map +1 -0
- package/dist/chat/acts.js +36 -0
- package/dist/chat/context.d.ts +3 -0
- package/dist/chat/context.d.ts.map +1 -0
- package/dist/chat/context.js +10 -0
- package/dist/chat/input.d.ts +9 -0
- package/dist/chat/input.d.ts.map +1 -0
- package/dist/chat/input.js +99 -0
- package/dist/chat/kit.d.ts +60 -0
- package/dist/chat/kit.d.ts.map +1 -0
- package/dist/chat/kit.js +123 -0
- package/dist/chat/lasting.d.ts +6 -0
- package/dist/chat/lasting.d.ts.map +1 -0
- package/dist/chat/lasting.js +19 -0
- package/dist/chat/list.d.ts +20 -0
- package/dist/chat/list.d.ts.map +1 -0
- package/dist/chat/list.js +59 -0
- package/dist/chat/markdown.d.ts +19 -0
- package/dist/chat/markdown.d.ts.map +1 -0
- package/dist/chat/markdown.js +187 -0
- package/dist/chat/message.d.ts +6 -0
- package/dist/chat/message.d.ts.map +1 -0
- package/dist/chat/message.js +192 -0
- package/dist/chat/messages.d.ts +21 -0
- package/dist/chat/messages.d.ts.map +1 -0
- package/dist/chat/messages.js +151 -0
- package/dist/chat/name.d.ts +6 -0
- package/dist/chat/name.d.ts.map +1 -0
- package/dist/chat/name.js +37 -0
- package/dist/chat/opened.d.ts +11 -0
- package/dist/chat/opened.d.ts.map +1 -0
- package/dist/chat/opened.js +17 -0
- package/dist/chat/overlay.d.ts +31 -0
- package/dist/chat/overlay.d.ts.map +1 -0
- package/dist/chat/overlay.js +97 -0
- package/dist/chat/parts.d.ts +57 -0
- package/dist/chat/parts.d.ts.map +1 -0
- package/dist/chat/parts.js +119 -0
- package/dist/chat/process.d.ts +20 -0
- package/dist/chat/process.d.ts.map +1 -0
- package/dist/chat/process.js +32 -0
- package/dist/chat/provider.d.ts +63 -0
- package/dist/chat/provider.d.ts.map +1 -0
- package/dist/chat/provider.js +645 -0
- package/dist/chat/question.d.ts +9 -0
- package/dist/chat/question.d.ts.map +1 -0
- package/dist/chat/question.js +80 -0
- package/dist/chat/questions.d.ts +31 -0
- package/dist/chat/questions.d.ts.map +1 -0
- package/dist/chat/questions.js +111 -0
- package/dist/chat/read.d.ts +5 -0
- package/dist/chat/read.d.ts.map +1 -0
- package/dist/chat/read.js +13 -0
- package/dist/chat/ready.d.ts +33 -0
- package/dist/chat/ready.d.ts.map +1 -0
- package/dist/chat/ready.js +91 -0
- package/dist/chat/style.d.ts +4 -0
- package/dist/chat/style.d.ts.map +1 -0
- package/dist/chat/style.js +302 -0
- package/dist/chat.d.ts +14 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +8 -0
- package/dist/client.d.ts +10 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -1
- package/dist/connection.d.ts +12 -6
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +239 -46
- package/dist/conversation.d.ts +9 -2
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +45 -6
- package/dist/expectation.d.ts +21 -0
- package/dist/expectation.d.ts.map +1 -0
- package/dist/expectation.js +70 -0
- package/dist/host.d.ts +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +6 -2
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/memory.d.ts +3 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +31 -11
- package/dist/outcome.d.ts +7 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +6 -0
- package/dist/overlay.d.ts +13 -2
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +56 -22
- package/dist/query.d.ts +2 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/reach.d.ts +2 -0
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +25 -3
- package/dist/react.d.ts +2 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +9 -2
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +12 -17
- package/dist/replica.d.ts +5 -2
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +33 -28
- package/dist/room-draft.d.ts +19 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +119 -1
- package/dist/rows.d.ts +3 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +3 -1
- package/dist/save.d.ts +24 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +304 -14
- package/dist/store.d.ts +13 -12
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +150 -157
- package/dist/wire.d.ts +3 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +3 -0
- package/package.json +22 -14
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
package/dist/connection.js
CHANGED
|
@@ -8,14 +8,16 @@ import { createSearchIndex, searchPlanOf, } from './search.js';
|
|
|
8
8
|
import { bootstrapRoom } from './bootstrap.js';
|
|
9
9
|
import { changeSet, mergeChangeSets } from './change-set.js';
|
|
10
10
|
import { createConversationStore, } from './conversation.js';
|
|
11
|
+
import { queuedFile } from './change.js';
|
|
11
12
|
import { validRoot } from './collection.js';
|
|
12
13
|
import { runtimeError } from './failure.js';
|
|
13
14
|
import { createLog } from './log.js';
|
|
14
|
-
import {
|
|
15
|
+
import { binaryRecord } from './binary.js';
|
|
16
|
+
import { absentBinary, binaryAnswer, calledResult, historyAnswer, undeclared, UNCERTAIN, } from './outcome.js';
|
|
15
17
|
import { refreshRoom } from './refresh.js';
|
|
16
|
-
import { buildBatch } from './save.js';
|
|
18
|
+
import { buildBatch, joined, limitedIn, requeued } from './save.js';
|
|
17
19
|
import { applyReturned, compositionOf, confirmedOf, landed, readReclassified, replicaOf, sameMembership, withdrawals, } from './replica.js';
|
|
18
|
-
import { changedParts, changesOf, held, readParts, returnedBy, returnedInto, staleWrite, underneath, } from './room-draft.js';
|
|
20
|
+
import { binaryBase, changedParts, changesOf, held, heldFile, joinedDraft, readParts, returnedBy, returnedInto, staleWrite, underneath, withdrawnDrafts, } from './room-draft.js';
|
|
19
21
|
import { same, saving, STARTING, transferring, } from './status.js';
|
|
20
22
|
import { detectStorageLoss, nextGeneration } from './durability.js';
|
|
21
23
|
import { roomDraftRevision } from './identity.js';
|
|
@@ -42,6 +44,7 @@ export function composeRuntime(options) {
|
|
|
42
44
|
let opening;
|
|
43
45
|
let store;
|
|
44
46
|
const replicas = new Map();
|
|
47
|
+
const queuesWithoutReplica = new Map();
|
|
45
48
|
const pendings = new Map();
|
|
46
49
|
const roomDrafts = new Map();
|
|
47
50
|
const presentations = new Map();
|
|
@@ -194,7 +197,9 @@ export function composeRuntime(options) {
|
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
function pending() {
|
|
197
|
-
return !localSaves &&
|
|
200
|
+
return (!localSaves &&
|
|
201
|
+
(queuesWithoutReplica.size > 0 ||
|
|
202
|
+
[...replicas.values()].some((replica) => replica.queue.length > 0)));
|
|
198
203
|
}
|
|
199
204
|
function attention() {
|
|
200
205
|
const attentionRequired = [];
|
|
@@ -304,10 +309,7 @@ export function composeRuntime(options) {
|
|
|
304
309
|
return Object.freeze({ batch, ...(state?.submission ?? { state: 'waiting' }) });
|
|
305
310
|
}
|
|
306
311
|
function entriesOf(locator) {
|
|
307
|
-
|
|
308
|
-
if (replica === undefined)
|
|
309
|
-
return [];
|
|
310
|
-
return replica.queue.map(entryOf);
|
|
312
|
+
return (replicas.get(locator)?.queue ?? queuesWithoutReplica.get(locator) ?? []).map(entryOf);
|
|
311
313
|
}
|
|
312
314
|
function emitQueue(locator) {
|
|
313
315
|
const entries = entriesOf(locator);
|
|
@@ -404,10 +406,7 @@ export function composeRuntime(options) {
|
|
|
404
406
|
const revoked = { status: 'unavailable', reason: 'revoked' };
|
|
405
407
|
try {
|
|
406
408
|
const local = await openLocal();
|
|
407
|
-
await local.revokeModels([...replicas.values()].map((replica) =>
|
|
408
|
-
record: replica.confirmed.record,
|
|
409
|
-
queue: replica.queue,
|
|
410
|
-
})));
|
|
409
|
+
await local.revokeModels([...replicas.values()].map((replica) => replica.confirmed.record));
|
|
411
410
|
}
|
|
412
411
|
catch {
|
|
413
412
|
journal.record('model revocation persistence failed');
|
|
@@ -474,7 +473,6 @@ export function composeRuntime(options) {
|
|
|
474
473
|
},
|
|
475
474
|
providerOwnedPaths: room.providerOwnedPaths,
|
|
476
475
|
roomVersion: replicas.get(room.locator)?.confirmed.record.roomVersion ?? null,
|
|
477
|
-
attachments: replicas.get(room.locator)?.confirmed.record.attachments ?? [],
|
|
478
476
|
synchronizationAvailable,
|
|
479
477
|
refusal: scopedRefusals.get(room.locator) ?? sourceRefusals.get(room.locator) ?? null,
|
|
480
478
|
});
|
|
@@ -499,7 +497,14 @@ export function composeRuntime(options) {
|
|
|
499
497
|
emitRooms();
|
|
500
498
|
}
|
|
501
499
|
function unlistedHeld(listed) {
|
|
502
|
-
return [
|
|
500
|
+
return [
|
|
501
|
+
...new Set([
|
|
502
|
+
...rooms.keys(),
|
|
503
|
+
...roomDrafts.keys(),
|
|
504
|
+
...transfers.keys(),
|
|
505
|
+
...queuesWithoutReplica.keys(),
|
|
506
|
+
]),
|
|
507
|
+
].filter((locator) => !listed.has(locator));
|
|
503
508
|
}
|
|
504
509
|
async function dropUnlisted(listed, local) {
|
|
505
510
|
if (unlistedHeld(listed).length === 0)
|
|
@@ -513,9 +518,10 @@ export function composeRuntime(options) {
|
|
|
513
518
|
drafts: [...(roomDrafts.get(locator)?.keys() ?? [])],
|
|
514
519
|
}));
|
|
515
520
|
for (const locator of unlisted) {
|
|
516
|
-
for (const batch of replicas.get(locator)?.queue ?? [])
|
|
521
|
+
for (const batch of replicas.get(locator)?.queue ?? queuesWithoutReplica.get(locator) ?? [])
|
|
517
522
|
pendings.delete(batch.id);
|
|
518
523
|
replicas.delete(locator);
|
|
524
|
+
queuesWithoutReplica.delete(locator);
|
|
519
525
|
rooms.delete(locator);
|
|
520
526
|
roomDrafts.delete(locator);
|
|
521
527
|
transfers.delete(locator);
|
|
@@ -589,6 +595,12 @@ export function composeRuntime(options) {
|
|
|
589
595
|
}
|
|
590
596
|
const previousReplicas = new Map(replicas);
|
|
591
597
|
replicas.clear();
|
|
598
|
+
queuesWithoutReplica.clear();
|
|
599
|
+
const replicated = new Set(records.map((record) => record.locator));
|
|
600
|
+
for (const [locator, queue] of queuedBatches) {
|
|
601
|
+
if (!replicated.has(locator))
|
|
602
|
+
queuesWithoutReplica.set(locator, queue);
|
|
603
|
+
}
|
|
592
604
|
for (const record of records) {
|
|
593
605
|
const model = restored(modelKey(record.locator, 'collection'), record.model);
|
|
594
606
|
const selectionModel = restored(modelKey(record.locator, 'typed-selection'), record.selectionModel);
|
|
@@ -602,7 +614,6 @@ export function composeRuntime(options) {
|
|
|
602
614
|
rooms.set(record.locator, {
|
|
603
615
|
...existing,
|
|
604
616
|
roomVersion: record.roomVersion,
|
|
605
|
-
attachments: record.attachments,
|
|
606
617
|
operations: record.operations,
|
|
607
618
|
replica: record.replica,
|
|
608
619
|
model: modelTypes(model),
|
|
@@ -675,6 +686,7 @@ export function composeRuntime(options) {
|
|
|
675
686
|
return state !== undefined && state.submission.state !== 'submitted' && !state.lost;
|
|
676
687
|
}
|
|
677
688
|
async function settle(local, locator, before, confirmed, queue, settling = {}) {
|
|
689
|
+
const previousQueue = before?.queue ?? queuesWithoutReplica.get(locator) ?? [];
|
|
678
690
|
const withdrawn = withdrawals(confirmed, queue, withdrawable, localSaves);
|
|
679
691
|
const kept = queue.filter((batch) => !withdrawn.includes(batch));
|
|
680
692
|
const unqueued = withdrawn.map((batch) => ({
|
|
@@ -700,20 +712,36 @@ export function composeRuntime(options) {
|
|
|
700
712
|
});
|
|
701
713
|
}
|
|
702
714
|
}
|
|
703
|
-
await local.
|
|
704
|
-
|
|
705
|
-
previous: before?.confirmed.record ?? null,
|
|
706
|
-
...(settling.stored === undefined ? {} : { stored: settling.stored }),
|
|
707
|
-
queue: kept,
|
|
708
|
-
previousQueue: before?.queue ?? [],
|
|
709
|
-
roomDrafts: [...written.values()],
|
|
710
|
-
});
|
|
711
|
-
for (const batch of before?.queue ?? []) {
|
|
715
|
+
await local.keepAuthored({ locator, queue: kept, roomDrafts: [...written.values()] });
|
|
716
|
+
for (const batch of previousQueue) {
|
|
712
717
|
if (!kept.includes(batch))
|
|
713
718
|
pendings.delete(batch.id);
|
|
714
719
|
}
|
|
715
720
|
for (const record of written.values())
|
|
716
721
|
rememberRoomDraft(record);
|
|
722
|
+
try {
|
|
723
|
+
await local.write({
|
|
724
|
+
next: confirmed.record,
|
|
725
|
+
previous: before?.confirmed.record ?? null,
|
|
726
|
+
...(settling.stored === undefined ? {} : { stored: settling.stored }),
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
catch (error) {
|
|
730
|
+
const held = before === undefined ? null : replicaOf(before.confirmed, kept, before);
|
|
731
|
+
if (held !== null)
|
|
732
|
+
replicas.set(locator, held);
|
|
733
|
+
else if (kept.length > 0)
|
|
734
|
+
queuesWithoutReplica.set(locator, kept);
|
|
735
|
+
else
|
|
736
|
+
queuesWithoutReplica.delete(locator);
|
|
737
|
+
publishChangeSet(changeSet(locator, before ?? null, held, {
|
|
738
|
+
queue: kept.length !== previousQueue.length,
|
|
739
|
+
drafts: [...written.keys()],
|
|
740
|
+
}));
|
|
741
|
+
moveTo({ ...status, ...attention() });
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
queuesWithoutReplica.delete(locator);
|
|
717
745
|
for (const { batch, returned } of unqueued) {
|
|
718
746
|
const outcome = localSaves ? 'dropped' : returned === null ? 'landed' : 'withdrawn';
|
|
719
747
|
journal.record(`outcome ${locator} ${batch.id} ${outcome}`);
|
|
@@ -721,7 +749,7 @@ export function composeRuntime(options) {
|
|
|
721
749
|
replicas.set(locator, replicaOf(confirmed, kept, before));
|
|
722
750
|
return changeSet(locator, before ?? null, replicas.get(locator) ?? null, {
|
|
723
751
|
room: settling.room,
|
|
724
|
-
queue: kept.length !==
|
|
752
|
+
queue: kept.length !== previousQueue.length,
|
|
725
753
|
drafts: [...written.keys()],
|
|
726
754
|
});
|
|
727
755
|
}
|
|
@@ -768,7 +796,7 @@ export function composeRuntime(options) {
|
|
|
768
796
|
return false;
|
|
769
797
|
}
|
|
770
798
|
adoptModels(room.locator, confirmed.record);
|
|
771
|
-
const queue = prior?.queue ?? [];
|
|
799
|
+
const queue = prior?.queue ?? queuesWithoutReplica.get(room.locator) ?? [];
|
|
772
800
|
const roomVersion = confirmed.record.roomVersion;
|
|
773
801
|
const accepted = queue.filter((batch) => {
|
|
774
802
|
const accepted = pendings.get(batch.id)?.accepted;
|
|
@@ -810,7 +838,24 @@ export function composeRuntime(options) {
|
|
|
810
838
|
if (changed.length > 0)
|
|
811
839
|
return { outcome: 'refused', code: 'changed-underneath', retryable: false, parts: changed };
|
|
812
840
|
const parts = saved.map(({ path, parts }) => changesOf(path, parts));
|
|
813
|
-
const
|
|
841
|
+
const changes = parts.flatMap(({ changes }) => changes);
|
|
842
|
+
const requeue = requeued(replica.queue, changes, replica.visible, withdrawable, (queue) => replicaOf(replica.confirmed, queue, replica).visible);
|
|
843
|
+
if (requeue.kind === 'refused')
|
|
844
|
+
return { outcome: 'refused', ...requeue.refusal };
|
|
845
|
+
const foreign = [...requeue.withdrawn.keys()].some((origin) => {
|
|
846
|
+
const writer = replica.queue.find((batch) => batch.id === origin)?.writtenBy;
|
|
847
|
+
return writer?.app !== writtenBy?.app || writer?.release !== writtenBy?.release;
|
|
848
|
+
});
|
|
849
|
+
if (foreign) {
|
|
850
|
+
return {
|
|
851
|
+
outcome: 'refused',
|
|
852
|
+
code: 'unknown-revision',
|
|
853
|
+
retryable: false,
|
|
854
|
+
file: [...requeue.queued].at(-1),
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
const withdrawing = requeue.withdrawn.size > 0;
|
|
858
|
+
const input = {
|
|
814
859
|
local: localSaves,
|
|
815
860
|
baseRoomVersion: replica.confirmed.record.roomVersion,
|
|
816
861
|
composition: compositionFor(replica.confirmed.record),
|
|
@@ -819,28 +864,84 @@ export function composeRuntime(options) {
|
|
|
819
864
|
providerLimits: limits,
|
|
820
865
|
handle: room.handle,
|
|
821
866
|
visible: replica.visible,
|
|
822
|
-
changes
|
|
867
|
+
changes,
|
|
823
868
|
bases: parts.flatMap(({ bases }) => bases),
|
|
824
869
|
writtenBy,
|
|
870
|
+
};
|
|
871
|
+
const checked = withdrawing ? buildBatch({ ...input, queued: requeue.queued }) : null;
|
|
872
|
+
if (checked?.kind === 'refused')
|
|
873
|
+
return { outcome: 'refused', ...checked.refusal };
|
|
874
|
+
const owners = [...requeue.owners].flatMap((origin) => {
|
|
875
|
+
const batch = requeue.withdrawn.get(origin);
|
|
876
|
+
return batch === undefined || batch === null ? [] : [{ origin, batch }];
|
|
825
877
|
});
|
|
826
|
-
if (
|
|
878
|
+
if (owners.length > 1) {
|
|
879
|
+
return {
|
|
880
|
+
outcome: 'refused',
|
|
881
|
+
code: 'unknown-revision',
|
|
882
|
+
retryable: false,
|
|
883
|
+
file: [...requeue.queued].at(-1),
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
const built = !withdrawing
|
|
887
|
+
? buildBatch(input)
|
|
888
|
+
: requeue.changes.length === 0
|
|
889
|
+
? null
|
|
890
|
+
: buildBatch({
|
|
891
|
+
...input,
|
|
892
|
+
visible: replicaOf(replica.confirmed, requeue.queue, replica).visible,
|
|
893
|
+
changes: requeue.changes,
|
|
894
|
+
});
|
|
895
|
+
if (built?.kind === 'refused')
|
|
827
896
|
return { outcome: 'refused', ...built.refusal };
|
|
828
|
-
const
|
|
897
|
+
const [owner] = owners;
|
|
898
|
+
const join = built === null || owner === undefined
|
|
899
|
+
? null
|
|
900
|
+
: joined(requeue.queue, owner.batch, built.batch);
|
|
901
|
+
if (join?.kind === 'refused')
|
|
902
|
+
return { outcome: 'refused', ...join.refusal };
|
|
903
|
+
const withdrawn = new Map(requeue.withdrawn);
|
|
904
|
+
if (join !== null && owner !== undefined)
|
|
905
|
+
withdrawn.set(owner.origin, join.batch);
|
|
906
|
+
const drafted = new Map();
|
|
907
|
+
for (const [origin, replaced] of withdrawn) {
|
|
908
|
+
if (replaced === null)
|
|
909
|
+
continue;
|
|
910
|
+
const carried = withdrawnDrafts(pendings.get(origin)?.drafts ?? [], changes);
|
|
911
|
+
drafted.set(replaced.id, replaced === join?.batch
|
|
912
|
+
? [
|
|
913
|
+
...carried.map((held) => joinedDraft(held, saved)),
|
|
914
|
+
...saved.filter((draft) => !carried.some((held) => held.path === draft.path)),
|
|
915
|
+
]
|
|
916
|
+
: carried);
|
|
917
|
+
}
|
|
918
|
+
if (built !== null && join === null)
|
|
919
|
+
drafted.set(built.batch.id, saved);
|
|
920
|
+
const batches = join !== null ? join.queue : built === null ? requeue.queue : [...requeue.queue, built.batch];
|
|
921
|
+
for (const replaced of withdrawn.values()) {
|
|
922
|
+
if (replaced === null || !batches.includes(replaced))
|
|
923
|
+
continue;
|
|
924
|
+
const limited = limitedIn(batches, replaced, limits, (queue) => replicaOf(replica.confirmed, queue, replica).visible);
|
|
925
|
+
if (limited !== null)
|
|
926
|
+
return { outcome: 'refused', ...limited };
|
|
927
|
+
}
|
|
829
928
|
const consumed = saved.map(({ path }) => path);
|
|
830
929
|
try {
|
|
831
|
-
await local.
|
|
832
|
-
|
|
833
|
-
previous: replica.confirmed.record,
|
|
930
|
+
await local.keepAuthored({
|
|
931
|
+
locator,
|
|
834
932
|
queue: batches,
|
|
835
|
-
|
|
836
|
-
saved,
|
|
933
|
+
saved: drafted,
|
|
837
934
|
consumedRoomDrafts: consumed,
|
|
838
935
|
});
|
|
839
936
|
}
|
|
840
937
|
catch {
|
|
841
938
|
return { outcome: 'refused', code: 'durable-write', retryable: true };
|
|
842
939
|
}
|
|
843
|
-
|
|
940
|
+
for (const origin of withdrawn.keys())
|
|
941
|
+
pendings.delete(origin);
|
|
942
|
+
for (const [id, drafts] of drafted) {
|
|
943
|
+
pendings.set(id, { drafts, submission: { state: 'waiting' }, lost: false });
|
|
944
|
+
}
|
|
844
945
|
if (!localSaves)
|
|
845
946
|
recorded = false;
|
|
846
947
|
for (const path of consumed)
|
|
@@ -852,7 +953,10 @@ export function composeRuntime(options) {
|
|
|
852
953
|
}));
|
|
853
954
|
moveTo({ ...(localSaves ? status : saving(status)), ...attention() });
|
|
854
955
|
submitLater(locator);
|
|
855
|
-
|
|
956
|
+
const identifier = join?.batch.id ??
|
|
957
|
+
built?.batch.id ??
|
|
958
|
+
[...requeue.withdrawn].map(([origin, replaced]) => replaced?.id ?? origin).at(-1);
|
|
959
|
+
return { outcome: 'saved', identifier };
|
|
856
960
|
}
|
|
857
961
|
async function mark(local, locator, identifier, submission, lost) {
|
|
858
962
|
const state = pendings.get(identifier);
|
|
@@ -915,6 +1019,90 @@ export function composeRuntime(options) {
|
|
|
915
1019
|
return UNCERTAIN;
|
|
916
1020
|
}
|
|
917
1021
|
}
|
|
1022
|
+
function queuedBlob(locator, path, localId) {
|
|
1023
|
+
for (const batch of replicas.get(locator)?.queue ?? []) {
|
|
1024
|
+
const change = batch.changes[queuedFile(batch, path, localId)];
|
|
1025
|
+
if (change?.kind === 'binary')
|
|
1026
|
+
return change.blob;
|
|
1027
|
+
}
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
async function readBinary(request) {
|
|
1031
|
+
if (closed || refusal !== null)
|
|
1032
|
+
return UNCERTAIN;
|
|
1033
|
+
try {
|
|
1034
|
+
await ensureAuthorization();
|
|
1035
|
+
}
|
|
1036
|
+
catch {
|
|
1037
|
+
return UNCERTAIN;
|
|
1038
|
+
}
|
|
1039
|
+
if (closed || authorization === undefined || refusal !== null)
|
|
1040
|
+
return UNCERTAIN;
|
|
1041
|
+
journal.record(request.kind === 'path'
|
|
1042
|
+
? `transfer binary ${request.locator} ${request.path}`
|
|
1043
|
+
: `transfer binary ${request.fileRef}`);
|
|
1044
|
+
try {
|
|
1045
|
+
const result = await options.adapter.binary(authorization, request);
|
|
1046
|
+
journal.record(`outcome binary ${result.kind}`);
|
|
1047
|
+
if (result.kind === 'scoped-refusal') {
|
|
1048
|
+
const room = replicas.get(result.locator)?.confirmed.record;
|
|
1049
|
+
if (room !== undefined)
|
|
1050
|
+
await scoped(result, room, await openLocal());
|
|
1051
|
+
}
|
|
1052
|
+
if (result.kind === 'revoked-authorization')
|
|
1053
|
+
await refuse('revoked-authorization');
|
|
1054
|
+
return binaryAnswer(result);
|
|
1055
|
+
}
|
|
1056
|
+
catch {
|
|
1057
|
+
journal.record('outcome binary transport-uncertainty');
|
|
1058
|
+
return UNCERTAIN;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
async function readBinaryPath(locator, path, revision) {
|
|
1062
|
+
await ready;
|
|
1063
|
+
if (revision !== undefined)
|
|
1064
|
+
return readBinary({ kind: 'path', locator, path, revision });
|
|
1065
|
+
const visible = replicas.get(locator)?.visible;
|
|
1066
|
+
const held = visible?.binaries[path];
|
|
1067
|
+
if (visible === undefined || held === undefined)
|
|
1068
|
+
return absentBinary(path);
|
|
1069
|
+
if (held.state === 'pending') {
|
|
1070
|
+
const blob = queuedBlob(locator, path, held.localId);
|
|
1071
|
+
return blob === null ? absentBinary(path) : { kind: 'binary', blob };
|
|
1072
|
+
}
|
|
1073
|
+
const record = binaryRecord(path, held, visible.revisions[path]);
|
|
1074
|
+
if (record.state !== 'accepted')
|
|
1075
|
+
return absentBinary(path);
|
|
1076
|
+
const replica = replicas.get(locator);
|
|
1077
|
+
const queued = (replica?.queue ?? []).flatMap((batch) => batch.changes);
|
|
1078
|
+
const holds = (at) => {
|
|
1079
|
+
const kept = replica?.confirmed.record.binaries[at];
|
|
1080
|
+
return (kept?.state === 'accepted' &&
|
|
1081
|
+
kept.fileRef === record.fileRef &&
|
|
1082
|
+
replica?.confirmed.record.revisions[at] === record.revision);
|
|
1083
|
+
};
|
|
1084
|
+
let confirmed = path;
|
|
1085
|
+
for (let index = queued.length - 1; index >= 0 && !holds(confirmed); index -= 1) {
|
|
1086
|
+
const change = queued[index];
|
|
1087
|
+
if (change.kind === 'move' && change.to === confirmed)
|
|
1088
|
+
confirmed = change.path;
|
|
1089
|
+
}
|
|
1090
|
+
return readBinary({
|
|
1091
|
+
kind: 'path',
|
|
1092
|
+
locator,
|
|
1093
|
+
path: confirmed,
|
|
1094
|
+
revision: record.revision,
|
|
1095
|
+
fileRef: record.fileRef,
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
async function readBinaryReference(reference) {
|
|
1099
|
+
await ready;
|
|
1100
|
+
return readBinary({
|
|
1101
|
+
kind: 'reference',
|
|
1102
|
+
fileRef: reference.fileRef,
|
|
1103
|
+
referrer: reference.referrer,
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
918
1106
|
function declaredAgents() {
|
|
919
1107
|
for (const capability of capabilities) {
|
|
920
1108
|
if (capability.conversationAgents !== undefined)
|
|
@@ -1138,7 +1326,7 @@ export function composeRuntime(options) {
|
|
|
1138
1326
|
logAccepted(room.locator, submitted, accepted);
|
|
1139
1327
|
const applied = options.adapter.reached(room.locator, held, accepted.roomVersion)
|
|
1140
1328
|
? { kind: 'staged', confirmed: current.confirmed }
|
|
1141
|
-
: applyReturned(current.confirmed,
|
|
1329
|
+
: applyReturned(current.confirmed, submitted, accepted, options.adapter.follows(room.locator, held, accepted.roomVersion)
|
|
1142
1330
|
? accepted.roomVersion
|
|
1143
1331
|
: held, accepted.roomVersion);
|
|
1144
1332
|
if (applied.kind !== 'staged') {
|
|
@@ -1357,11 +1545,7 @@ export function composeRuntime(options) {
|
|
|
1357
1545
|
const read = reclassified.kind === 'deferred'
|
|
1358
1546
|
? { kind: 'staged', confirmed: confirmedOf(record, held.confirmed) }
|
|
1359
1547
|
: reclassified;
|
|
1360
|
-
await local.write({
|
|
1361
|
-
next: record,
|
|
1362
|
-
previous: held.confirmed.record,
|
|
1363
|
-
queue: held.queue,
|
|
1364
|
-
});
|
|
1548
|
+
await local.write({ next: record, previous: held.confirmed.record });
|
|
1365
1549
|
if (read.kind === 'staged') {
|
|
1366
1550
|
replicas.set(room.locator, replicaOf(read.confirmed, held.queue, held));
|
|
1367
1551
|
if (declarationRefusals.delete(room.locator)) {
|
|
@@ -1429,7 +1613,6 @@ export function composeRuntime(options) {
|
|
|
1429
1613
|
roomVersion: record.roomVersion,
|
|
1430
1614
|
documents: record.documents,
|
|
1431
1615
|
revisions: record.revisions,
|
|
1432
|
-
attachments: record.attachments,
|
|
1433
1616
|
},
|
|
1434
1617
|
];
|
|
1435
1618
|
});
|
|
@@ -2022,6 +2205,8 @@ export function composeRuntime(options) {
|
|
|
2022
2205
|
}
|
|
2023
2206
|
if (topic === 'conversations')
|
|
2024
2207
|
return conversations.watchList(deliver);
|
|
2208
|
+
if (topic === 'agents')
|
|
2209
|
+
return conversations.watchAgents(deliver);
|
|
2025
2210
|
if (topic === 'presentation') {
|
|
2026
2211
|
const listener = {
|
|
2027
2212
|
app: input[0],
|
|
@@ -2135,11 +2320,14 @@ export function composeRuntime(options) {
|
|
|
2135
2320
|
if ((current?.revision ?? null) !== revision) {
|
|
2136
2321
|
return staleWrite(current === undefined ? null : roomDraftOf(current));
|
|
2137
2322
|
}
|
|
2323
|
+
const file = parts.file === undefined
|
|
2324
|
+
? undefined
|
|
2325
|
+
: await heldFile(parts.file.blob, binaryBase(replicas.get(room)?.visible, path));
|
|
2138
2326
|
const record = {
|
|
2139
2327
|
locator: room,
|
|
2140
2328
|
path,
|
|
2141
2329
|
revision: roomDraftRevision(),
|
|
2142
|
-
parts: held(current?.parts, parts),
|
|
2330
|
+
parts: held(current?.parts, parts, file),
|
|
2143
2331
|
returned: current?.returned ?? null,
|
|
2144
2332
|
};
|
|
2145
2333
|
await local.keepRoomDraft(record);
|
|
@@ -2188,6 +2376,10 @@ export function composeRuntime(options) {
|
|
|
2188
2376
|
history(locator, path, query) {
|
|
2189
2377
|
return readHistory(locator, path, query);
|
|
2190
2378
|
},
|
|
2379
|
+
binaryFile: {
|
|
2380
|
+
read: readBinaryPath,
|
|
2381
|
+
readReference: readBinaryReference,
|
|
2382
|
+
},
|
|
2191
2383
|
call(name, input) {
|
|
2192
2384
|
return invokeAction(name, input);
|
|
2193
2385
|
},
|
|
@@ -2220,6 +2412,7 @@ export function composeRuntime(options) {
|
|
|
2220
2412
|
const reachable = {
|
|
2221
2413
|
md,
|
|
2222
2414
|
watch,
|
|
2415
|
+
referrerScope: (referrer) => options.adapter.referrerScope(referrer),
|
|
2223
2416
|
plan: planned,
|
|
2224
2417
|
query: (plan) => rowsQuery(plan),
|
|
2225
2418
|
watchPlan,
|
package/dist/conversation.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ export type ConversationEntry = {
|
|
|
21
21
|
state: ConversationState;
|
|
22
22
|
started: string | null;
|
|
23
23
|
};
|
|
24
|
+
export type ConversationAgent = {
|
|
25
|
+
identity: string;
|
|
26
|
+
name: string;
|
|
27
|
+
};
|
|
24
28
|
export type RunningTurn = {
|
|
25
29
|
turn: string;
|
|
26
30
|
started: string | null;
|
|
@@ -44,7 +48,9 @@ export type ConversationView = {
|
|
|
44
48
|
} | null;
|
|
45
49
|
commands: readonly ProcessCommand[];
|
|
46
50
|
options: readonly SessionOption[];
|
|
47
|
-
chatDraft: ChatDraft
|
|
51
|
+
chatDraft: (ChatDraft & {
|
|
52
|
+
readonly revision: string;
|
|
53
|
+
}) | null;
|
|
48
54
|
};
|
|
49
55
|
export type ConversationSurface = {
|
|
50
56
|
list(): Promise<readonly ConversationEntry[]>;
|
|
@@ -58,7 +64,7 @@ export type ConversationSurface = {
|
|
|
58
64
|
delete(conversation: string): Promise<CallResult>;
|
|
59
65
|
};
|
|
60
66
|
export type ChatDraftSurface = {
|
|
61
|
-
write(conversation: string, draft: ChatDraft): Promise<void>;
|
|
67
|
+
write(conversation: string, draft: ChatDraft, revision?: string): Promise<void>;
|
|
62
68
|
discard(conversation: string): Promise<void>;
|
|
63
69
|
};
|
|
64
70
|
export type ConversationDependencies = {
|
|
@@ -80,6 +86,7 @@ export type ConversationStore = {
|
|
|
80
86
|
reconnected(): void;
|
|
81
87
|
watch(conversation: string, options: ConversationOptions, deliver: (view: ConversationView) => void): () => void;
|
|
82
88
|
watchList(deliver: (entries: readonly ConversationEntry[]) => void): () => void;
|
|
89
|
+
watchAgents(deliver: (agents: readonly ConversationAgent[]) => void): () => void;
|
|
83
90
|
changed(set: ChangeSet): void;
|
|
84
91
|
receive(event: ConversationEvent): boolean;
|
|
85
92
|
messages(): readonly SearchedMessage[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EAEjB,mBAAmB,EACnB,kBAAkB,EAElB,cAAc,EACd,aAAa,EACb,WAAW,EAEZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAyB,KAAK,SAAS,EAAsB,MAAM,iBAAiB,CAAC;AAE5F,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EAEjB,mBAAmB,EACnB,kBAAkB,EAElB,cAAc,EACd,aAAa,EACb,WAAW,EAEZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAyB,KAAK,SAAS,EAAsB,MAAM,iBAAiB,CAAC;AAE5F,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACzC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;IAC9B,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACrC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IACpC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,SAAS,EAAE,CAAC,SAAS,GAAG;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,IAAI,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrF,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACnE,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,IAAI,kBAAkB,GAAG,SAAS,CAAC;IACzC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpD,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpE,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,IAAI,kBAAkB,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,MAAM,IAAI,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,OAAO,CAAC,IAAI,EAAE,SAAS,gBAAgB,EAAE,EAAE,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,IAAI,CAAC;IACrF,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,IAAI,OAAO,CAAC;IACnB,WAAW,IAAI,IAAI,CAAC;IACpB,KAAK,CACH,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GACxC,MAAM,IAAI,CAAC;IACd,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAChF,WAAW,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACjF,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAC3C,QAAQ,IAAI,SAAS,eAAe,EAAE,CAAC;IACvC,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAC;IACxE,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAyBF,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAWjE;AAmJD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG,iBAAiB,CAklBzF"}
|
package/dist/conversation.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { conversationChangeSet } from './change-set.js';
|
|
2
2
|
import { runtimeError } from './failure.js';
|
|
3
3
|
import { declaredFile } from './file.js';
|
|
4
|
+
import { chatDraftRevision } from './identity.js';
|
|
4
5
|
const QUIET = {
|
|
5
6
|
turn: null,
|
|
6
7
|
questions: [],
|
|
@@ -169,7 +170,9 @@ export function createConversationStore(deps) {
|
|
|
169
170
|
const listing = new Map();
|
|
170
171
|
const listWatchers = new Set();
|
|
171
172
|
let listKnown = false;
|
|
173
|
+
const agentWatchers = new Set();
|
|
172
174
|
let agentNames = new Map();
|
|
175
|
+
let retiredAgents = new Set();
|
|
173
176
|
let agentsRead = null;
|
|
174
177
|
let replicated = new Set();
|
|
175
178
|
let handedReplicated;
|
|
@@ -199,7 +202,7 @@ export function createConversationStore(deps) {
|
|
|
199
202
|
options: structuredClone(facts.options),
|
|
200
203
|
chatDraft: draft === undefined || draft.turn !== null || sending.get(conversation)?.draft === draft
|
|
201
204
|
? null
|
|
202
|
-
: { text: draft.text, files: [...draft.files] },
|
|
205
|
+
: { text: draft.text, files: [...draft.files], revision: draft.revision },
|
|
203
206
|
};
|
|
204
207
|
}
|
|
205
208
|
function emit(conversation, messagesChanged = true) {
|
|
@@ -244,6 +247,21 @@ export function createConversationStore(deps) {
|
|
|
244
247
|
for (const watcher of listWatchers)
|
|
245
248
|
watcher(value);
|
|
246
249
|
}
|
|
250
|
+
function agents() {
|
|
251
|
+
return [...agentNames]
|
|
252
|
+
.filter(([identity]) => !retiredAgents.has(identity))
|
|
253
|
+
.map(([identity, name]) => ({ identity, name }))
|
|
254
|
+
.sort((left, right) => left.name === right.name
|
|
255
|
+
? left.identity.localeCompare(right.identity)
|
|
256
|
+
: left.name.localeCompare(right.name));
|
|
257
|
+
}
|
|
258
|
+
function emitAgents() {
|
|
259
|
+
if (deps.closed() || agentWatchers.size === 0)
|
|
260
|
+
return;
|
|
261
|
+
const value = agents();
|
|
262
|
+
for (const watcher of agentWatchers)
|
|
263
|
+
watcher(value);
|
|
264
|
+
}
|
|
247
265
|
function setLive(conversation, next) {
|
|
248
266
|
const before = stateOf(conversation);
|
|
249
267
|
const began = lives.get(conversation)?.turn?.started;
|
|
@@ -262,18 +280,27 @@ export function createConversationStore(deps) {
|
|
|
262
280
|
return;
|
|
263
281
|
const { documents } = await deps.documents(declaration.locator);
|
|
264
282
|
const names = new Map();
|
|
283
|
+
const retired = new Set();
|
|
265
284
|
for (const document of documents) {
|
|
266
285
|
if (document.type !== declaration.type)
|
|
267
286
|
continue;
|
|
268
287
|
const identity = document.fields?.[declaration.identity];
|
|
269
288
|
const name = document.fields?.[declaration.name];
|
|
270
|
-
if (typeof identity
|
|
271
|
-
|
|
289
|
+
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
290
|
+
continue;
|
|
291
|
+
names.set(identity, name);
|
|
292
|
+
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
293
|
+
if (ended !== undefined && ended !== null)
|
|
294
|
+
retired.add(identity);
|
|
272
295
|
}
|
|
273
|
-
|
|
296
|
+
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
297
|
+
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
274
298
|
return;
|
|
275
299
|
agentNames = names;
|
|
276
|
-
|
|
300
|
+
retiredAgents = retired;
|
|
301
|
+
if (named)
|
|
302
|
+
emitList();
|
|
303
|
+
emitAgents();
|
|
277
304
|
}
|
|
278
305
|
function agentsReady() {
|
|
279
306
|
agentsRead ??= readAgents().catch(() => {
|
|
@@ -551,12 +578,13 @@ export function createConversationStore(deps) {
|
|
|
551
578
|
},
|
|
552
579
|
};
|
|
553
580
|
const chatDraft = {
|
|
554
|
-
write(conversation, draft) {
|
|
581
|
+
write(conversation, draft, revision = chatDraftRevision()) {
|
|
555
582
|
return withDraft(conversation, () => ({
|
|
556
583
|
conversation,
|
|
557
584
|
text: draft.text,
|
|
558
585
|
files: [...draft.files],
|
|
559
586
|
turn: null,
|
|
587
|
+
revision,
|
|
560
588
|
}));
|
|
561
589
|
},
|
|
562
590
|
discard(conversation) {
|
|
@@ -651,6 +679,16 @@ export function createConversationStore(deps) {
|
|
|
651
679
|
listWatchers.delete(deliver);
|
|
652
680
|
};
|
|
653
681
|
},
|
|
682
|
+
watchAgents(deliver) {
|
|
683
|
+
agentWatchers.add(deliver);
|
|
684
|
+
void agentsReady().then(() => {
|
|
685
|
+
if (!deps.closed() && agentWatchers.has(deliver))
|
|
686
|
+
deliver(agents());
|
|
687
|
+
});
|
|
688
|
+
return () => {
|
|
689
|
+
agentWatchers.delete(deliver);
|
|
690
|
+
};
|
|
691
|
+
},
|
|
654
692
|
changed(set) {
|
|
655
693
|
for (const conversation of set.conversations)
|
|
656
694
|
emit(conversation);
|
|
@@ -698,6 +736,7 @@ export function createConversationStore(deps) {
|
|
|
698
736
|
views.clear();
|
|
699
737
|
lives.clear();
|
|
700
738
|
listWatchers.clear();
|
|
739
|
+
agentWatchers.clear();
|
|
701
740
|
},
|
|
702
741
|
};
|
|
703
742
|
}
|