@agentshouse/mdruntime 0.1.0-c5d3fa6fb67bc → 0.1.0-c5d81e5d5cb58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -15
- package/dist/adapter.d.ts +86 -34
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/binary.d.ts +0 -5
- package/dist/binary.d.ts.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/bootstrap.d.ts +31 -8
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +187 -85
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -16
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -89
- package/dist/change.d.ts +31 -1
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +10 -1
- package/dist/client.d.ts +13 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +95 -10
- package/dist/collection.d.ts +11 -19
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +53 -289
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +765 -0
- package/dist/connection.d.ts +28 -13
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2937 -1064
- package/dist/conversation.d.ts +18 -3
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +340 -117
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/durability.d.ts +3 -5
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +3 -1
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +18 -23
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/fulltext.d.ts +27 -0
- package/dist/fulltext.d.ts.map +1 -0
- package/dist/fulltext.js +368 -0
- package/dist/host.d.ts +8 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +84 -14
- 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 +14 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +124 -0
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +208 -0
- package/dist/memory.d.ts +8 -4
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +79 -32
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +90 -0
- package/dist/model.d.ts +6 -0
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -1
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +15 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +93 -3
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/outcome.d.ts +45 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +39 -0
- package/dist/overlay.d.ts +2 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +87 -172
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +35 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +46 -7
- package/dist/reach.d.ts +13 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +210 -68
- package/dist/react.d.ts +3 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/readiness.d.ts +20 -9
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +6 -6
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +100 -0
- package/dist/recovery.d.ts +2 -2
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +8 -7
- package/dist/refresh.d.ts +16 -15
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +113 -56
- package/dist/replica.d.ts +56 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +298 -188
- package/dist/room-draft.d.ts +16 -1
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +65 -25
- package/dist/rows.d.ts +38 -30
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +173 -96
- package/dist/save.d.ts +53 -14
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +529 -185
- package/dist/search.d.ts +25 -42
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +30 -169
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +8 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +129 -66
- package/dist/status.d.ts +5 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +106 -90
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +355 -659
- package/dist/stored.d.ts +154 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +624 -0
- package/dist/tables.d.ts +362 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +627 -0
- package/dist/turn.d.ts +5 -3
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +51 -21
- package/dist/validation.d.ts +30 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +162 -0
- package/dist/windows.d.ts +22 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +89 -0
- package/dist/wire.d.ts +33 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +9 -1
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +156 -0
- package/package.json +18 -19
- package/AGENTS.md +0 -299
- package/dist/acquisition.d.ts +0 -14
- package/dist/acquisition.d.ts.map +0 -1
- package/dist/acquisition.js +0 -24
- package/dist/chat/acts.d.ts +0 -33
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/context.d.ts +0 -3
- package/dist/chat/context.d.ts.map +0 -1
- package/dist/chat/context.js +0 -10
- package/dist/chat/input.d.ts +0 -9
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -99
- package/dist/chat/kit.d.ts +0 -61
- package/dist/chat/kit.d.ts.map +0 -1
- package/dist/chat/kit.js +0 -123
- package/dist/chat/lasting.d.ts +0 -6
- package/dist/chat/lasting.d.ts.map +0 -1
- package/dist/chat/lasting.js +0 -19
- package/dist/chat/list.d.ts +0 -27
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -63
- package/dist/chat/markdown.d.ts +0 -20
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -188
- package/dist/chat/message.d.ts +0 -6
- package/dist/chat/message.d.ts.map +0 -1
- package/dist/chat/message.js +0 -192
- package/dist/chat/messages.d.ts +0 -22
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -155
- package/dist/chat/name.d.ts +0 -6
- package/dist/chat/name.d.ts.map +0 -1
- package/dist/chat/name.js +0 -37
- package/dist/chat/opened.d.ts +0 -11
- package/dist/chat/opened.d.ts.map +0 -1
- package/dist/chat/opened.js +0 -17
- package/dist/chat/overlay.d.ts +0 -31
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -97
- package/dist/chat/parts.d.ts +0 -57
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -119
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -63
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -629
- package/dist/chat/question.d.ts +0 -9
- package/dist/chat/question.d.ts.map +0 -1
- package/dist/chat/question.js +0 -80
- package/dist/chat/questions.d.ts +0 -31
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/questions.js +0 -111
- package/dist/chat/read.d.ts +0 -5
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/read.js +0 -13
- package/dist/chat/ready.d.ts +0 -34
- package/dist/chat/ready.d.ts.map +0 -1
- package/dist/chat/ready.js +0 -91
- package/dist/chat/style.d.ts +0 -4
- package/dist/chat/style.d.ts.map +0 -1
- package/dist/chat/style.js +0 -302
- package/dist/chat.d.ts +0 -14
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -8
- package/dist/read-side.d.ts +0 -25
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -642
package/dist/conversation.js
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
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 { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
|
|
6
7
|
const QUIET = {
|
|
7
8
|
turn: null,
|
|
8
9
|
questions: [],
|
|
9
10
|
process: null,
|
|
10
11
|
commands: [],
|
|
11
12
|
options: [],
|
|
13
|
+
starting: null,
|
|
14
|
+
link: null,
|
|
15
|
+
deliveryUnknown: [],
|
|
12
16
|
};
|
|
17
|
+
const FACTS = [
|
|
18
|
+
'questions',
|
|
19
|
+
'process',
|
|
20
|
+
'commands',
|
|
21
|
+
'options',
|
|
22
|
+
'starting',
|
|
23
|
+
'link',
|
|
24
|
+
'deliveryUnknown',
|
|
25
|
+
];
|
|
13
26
|
export function unheldView(conversation) {
|
|
14
27
|
return {
|
|
15
28
|
conversation,
|
|
@@ -19,19 +32,25 @@ export function unheldView(conversation) {
|
|
|
19
32
|
process: null,
|
|
20
33
|
commands: [],
|
|
21
34
|
options: [],
|
|
35
|
+
starting: null,
|
|
36
|
+
link: null,
|
|
37
|
+
deliveryUnknown: [],
|
|
22
38
|
chatDraft: null,
|
|
23
39
|
};
|
|
24
40
|
}
|
|
25
41
|
export const SESSION_STARTED = 'Session started';
|
|
26
42
|
const NEW_CHAT = 'new:';
|
|
43
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
27
44
|
export function newChat(agent) {
|
|
28
45
|
return `${NEW_CHAT}${agent}`;
|
|
29
46
|
}
|
|
30
47
|
function creationOf(input) {
|
|
31
48
|
if (typeof input !== 'object' || input === null)
|
|
32
49
|
return null;
|
|
33
|
-
const { agent_id: agent, operation_id: operation } = input;
|
|
34
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
50
|
+
const { agent_id: agent, operation_id: operation, replaces, } = input;
|
|
51
|
+
return typeof agent === 'string' && typeof operation === 'string' && replaces === undefined
|
|
52
|
+
? { agent, operation }
|
|
53
|
+
: null;
|
|
35
54
|
}
|
|
36
55
|
function startedTurn(turn, operation) {
|
|
37
56
|
if (operation.op === 'begin')
|
|
@@ -82,19 +101,25 @@ function appliedTurn(held, operation) {
|
|
|
82
101
|
parts: held.parts.map((kept, at) => (at === operation.index ? changed : kept)),
|
|
83
102
|
};
|
|
84
103
|
}
|
|
85
|
-
function ordered(left, right) {
|
|
86
|
-
if (left.position !== right.position)
|
|
87
|
-
return left.position < right.position ? -1 : 1;
|
|
88
|
-
if (left.identity !== right.identity)
|
|
89
|
-
return left.identity < right.identity ? -1 : 1;
|
|
90
|
-
return 0;
|
|
91
|
-
}
|
|
92
104
|
function windowOf(held, arriving, limit) {
|
|
93
105
|
const byIdentity = new Map(held.map((message) => [message.identity, message]));
|
|
94
106
|
for (const message of arriving)
|
|
95
107
|
byIdentity.set(message.identity, message);
|
|
96
|
-
const next = [...byIdentity.values()].sort(
|
|
97
|
-
|
|
108
|
+
const next = [...byIdentity.values()].sort(messageOrder);
|
|
109
|
+
const start = Math.max(0, next.length - limit);
|
|
110
|
+
return { messages: next.slice(start), dropped: start > 0 };
|
|
111
|
+
}
|
|
112
|
+
function frameOf(asked, messages, more, total) {
|
|
113
|
+
const oldest = messages[0];
|
|
114
|
+
const next = !more
|
|
115
|
+
? undefined
|
|
116
|
+
: oldest === undefined
|
|
117
|
+
? (asked.after ?? FROM_START)
|
|
118
|
+
: cursorOf([oldest.position, oldest.identity]);
|
|
119
|
+
return {
|
|
120
|
+
...(next === undefined ? {} : { next }),
|
|
121
|
+
...(total === null ? {} : { total }),
|
|
122
|
+
};
|
|
98
123
|
}
|
|
99
124
|
function newestOf(arriving, from) {
|
|
100
125
|
return arriving.reduce((top, message) => (top === null || message.position > top ? message.position : top), from);
|
|
@@ -165,18 +190,34 @@ function answered(result, field) {
|
|
|
165
190
|
const value = answer[field];
|
|
166
191
|
return typeof value === 'string' ? value : null;
|
|
167
192
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
193
|
+
function beforeOf(after) {
|
|
194
|
+
if (after === undefined)
|
|
195
|
+
return null;
|
|
196
|
+
const decoded = typeof after === 'string' ? decodedCursor(after) : null;
|
|
197
|
+
if (decoded?.length === 0)
|
|
198
|
+
return null;
|
|
199
|
+
const [position, identity] = decoded ?? [];
|
|
200
|
+
if (decoded?.length !== 2 || typeof position !== 'string' || typeof identity !== 'string') {
|
|
201
|
+
throw runtimeError('invalid-after', `conversation after must be the next an earlier view returned, got ${String(after)}`);
|
|
202
|
+
}
|
|
203
|
+
return [position, identity];
|
|
204
|
+
}
|
|
205
|
+
function askedOf(options) {
|
|
206
|
+
const { limit, after, total } = options;
|
|
207
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 0)) {
|
|
173
208
|
throw runtimeError('invalid-limit', `conversation limit must be a non-negative integer, got ${String(limit)}`);
|
|
174
209
|
}
|
|
175
|
-
return limit;
|
|
210
|
+
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
176
211
|
}
|
|
177
212
|
const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
|
|
213
|
+
const DURABLE_WRITE = {
|
|
214
|
+
kind: 'rejected',
|
|
215
|
+
code: 'durable-write',
|
|
216
|
+
fields: {},
|
|
217
|
+
retryable: true,
|
|
218
|
+
};
|
|
178
219
|
function unwritten(draft) {
|
|
179
|
-
return draft.text === ''
|
|
220
|
+
return draft.text === '';
|
|
180
221
|
}
|
|
181
222
|
function pending(draft) {
|
|
182
223
|
return {
|
|
@@ -191,11 +232,13 @@ function withSubmitted(draft, submitted) {
|
|
|
191
232
|
const { submitted: _held, ...unsent } = draft;
|
|
192
233
|
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
193
234
|
}
|
|
235
|
+
function prepended(draft, said) {
|
|
236
|
+
return { text: [said.text, draft.text].filter((one) => one !== '').join('\n') };
|
|
237
|
+
}
|
|
194
238
|
function returned(draft, submission, others) {
|
|
195
239
|
return withSubmitted({
|
|
196
240
|
conversation: draft.conversation,
|
|
197
|
-
|
|
198
|
-
files: [...submission.files, ...draft.files],
|
|
241
|
+
...prepended(draft, submission),
|
|
199
242
|
revision: chatDraftRevision(),
|
|
200
243
|
}, others);
|
|
201
244
|
}
|
|
@@ -206,23 +249,29 @@ export function createConversationStore(deps) {
|
|
|
206
249
|
const drafts = new Map();
|
|
207
250
|
const sending = new Map();
|
|
208
251
|
const behind = new Set();
|
|
252
|
+
const catching = new Map();
|
|
209
253
|
const gaps = new Map();
|
|
210
254
|
const lives = new Map();
|
|
255
|
+
const unsent = new Map();
|
|
211
256
|
const views = new Map();
|
|
212
257
|
const listing = new Map();
|
|
213
258
|
const creations = new Set();
|
|
214
259
|
const listWatchers = new Set();
|
|
260
|
+
const unlisted = new Set();
|
|
215
261
|
let listKnown = false;
|
|
216
262
|
const agentWatchers = new Set();
|
|
263
|
+
const unnamed = new Set();
|
|
264
|
+
let agentsKnown = false;
|
|
217
265
|
let agentNames = new Map();
|
|
218
266
|
let retiredAgents = new Set();
|
|
219
267
|
let agentsRead = null;
|
|
268
|
+
let agentsFrom;
|
|
220
269
|
let replicated = new Set();
|
|
221
270
|
let handedReplicated;
|
|
222
271
|
function liveOf(conversation) {
|
|
223
272
|
return lives.get(conversation) ?? QUIET;
|
|
224
273
|
}
|
|
225
|
-
function viewOf(conversation, held) {
|
|
274
|
+
function viewOf(conversation, held, frame) {
|
|
226
275
|
const draft = drafts.get(conversation);
|
|
227
276
|
const facts = liveOf(conversation);
|
|
228
277
|
return {
|
|
@@ -233,14 +282,18 @@ export function createConversationStore(deps) {
|
|
|
233
282
|
text,
|
|
234
283
|
message,
|
|
235
284
|
})),
|
|
285
|
+
...frame,
|
|
236
286
|
turn: structuredClone(facts.turn),
|
|
237
287
|
questions: structuredClone(facts.questions),
|
|
238
288
|
process: facts.process === null ? null : { ...facts.process },
|
|
239
289
|
commands: structuredClone(facts.commands),
|
|
240
290
|
options: structuredClone(facts.options),
|
|
291
|
+
starting: facts.starting,
|
|
292
|
+
link: facts.link === null ? null : { ...facts.link },
|
|
293
|
+
deliveryUnknown: [...facts.deliveryUnknown],
|
|
241
294
|
chatDraft: draft === undefined || unwritten(draft)
|
|
242
295
|
? null
|
|
243
|
-
: { text: draft.text,
|
|
296
|
+
: { text: draft.text, revision: draft.revision },
|
|
244
297
|
};
|
|
245
298
|
}
|
|
246
299
|
function emit(conversation) {
|
|
@@ -252,21 +305,36 @@ export function createConversationStore(deps) {
|
|
|
252
305
|
const ready = [...view.watchers].filter((watcher) => watcher.ready);
|
|
253
306
|
if (ready.length === 0)
|
|
254
307
|
continue;
|
|
255
|
-
const value = viewOf(conversation, view.window);
|
|
308
|
+
const value = viewOf(conversation, view.window, sharedFrame(view, view.window));
|
|
256
309
|
for (const watcher of ready)
|
|
257
310
|
watcher.notify(value);
|
|
258
311
|
}
|
|
259
312
|
}
|
|
260
|
-
function
|
|
313
|
+
function sharedFrame(view, window) {
|
|
314
|
+
return frameOf(view.asked, window, view.more, view.total);
|
|
315
|
+
}
|
|
316
|
+
async function slide(local, conversation, arriving) {
|
|
317
|
+
let count;
|
|
261
318
|
for (const view of views.values()) {
|
|
262
319
|
if (view.conversation !== conversation || view.window === null)
|
|
263
320
|
continue;
|
|
264
|
-
|
|
321
|
+
if (arriving === null) {
|
|
322
|
+
view.window = [];
|
|
323
|
+
view.more = false;
|
|
324
|
+
if (view.total !== null)
|
|
325
|
+
view.total = 0;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const joining = arriving.filter((message) => precedes(message, view.asked.before));
|
|
329
|
+
const next = windowOf(view.window, joining, view.asked.limit);
|
|
330
|
+
view.window = next.messages;
|
|
331
|
+
view.more ||= next.dropped;
|
|
332
|
+
if (view.total !== null && arriving.length > 0) {
|
|
333
|
+
count ??= await local.messageCount(conversation);
|
|
334
|
+
view.total = count;
|
|
335
|
+
}
|
|
265
336
|
}
|
|
266
337
|
}
|
|
267
|
-
function changesOf(conversation, arriving) {
|
|
268
|
-
return arriving.map(({ identity, text }) => ({ conversation, identity, text }));
|
|
269
|
-
}
|
|
270
338
|
function stateOf(conversation) {
|
|
271
339
|
const facts = liveOf(conversation);
|
|
272
340
|
if (facts.questions.length > 0)
|
|
@@ -281,16 +349,44 @@ export function createConversationStore(deps) {
|
|
|
281
349
|
created: entry.created,
|
|
282
350
|
finished: entry.finished,
|
|
283
351
|
outcome: entry.outcome,
|
|
352
|
+
waiting: entry.waiting,
|
|
284
353
|
state: stateOf(entry.conversation),
|
|
285
354
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
286
355
|
}));
|
|
287
356
|
}
|
|
288
357
|
function emitList() {
|
|
289
|
-
if (deps.closed()
|
|
358
|
+
if (deps.closed())
|
|
290
359
|
return;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
watcher
|
|
360
|
+
if (listWatchers.size > 0) {
|
|
361
|
+
const value = entries();
|
|
362
|
+
for (const watcher of listWatchers)
|
|
363
|
+
watcher(value);
|
|
364
|
+
}
|
|
365
|
+
learned();
|
|
366
|
+
}
|
|
367
|
+
function unlearnable() {
|
|
368
|
+
return !deps.online() || (deps.listed() && deps.agents() === undefined);
|
|
369
|
+
}
|
|
370
|
+
function learned() {
|
|
371
|
+
if (deps.closed())
|
|
372
|
+
return;
|
|
373
|
+
const named = agentsKnown || unlearnable();
|
|
374
|
+
if (unlisted.size > 0 && named && (listKnown || deps.stream() === undefined || unlearnable())) {
|
|
375
|
+
const value = entries();
|
|
376
|
+
for (const watcher of [...unlisted]) {
|
|
377
|
+
unlisted.delete(watcher);
|
|
378
|
+
listWatchers.add(watcher);
|
|
379
|
+
watcher(value);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (unnamed.size > 0 && named) {
|
|
383
|
+
const value = agents();
|
|
384
|
+
for (const watcher of [...unnamed]) {
|
|
385
|
+
unnamed.delete(watcher);
|
|
386
|
+
agentWatchers.add(watcher);
|
|
387
|
+
watcher(value);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
294
390
|
}
|
|
295
391
|
function agents() {
|
|
296
392
|
return [...agentNames]
|
|
@@ -321,34 +417,46 @@ export function createConversationStore(deps) {
|
|
|
321
417
|
}
|
|
322
418
|
async function readAgents() {
|
|
323
419
|
const declaration = deps.agents();
|
|
420
|
+
agentsFrom = JSON.stringify(declaration);
|
|
324
421
|
if (declaration === undefined)
|
|
325
422
|
return;
|
|
326
|
-
const held = await deps.documents(declaration);
|
|
327
|
-
if ('pending' in held)
|
|
328
|
-
return;
|
|
329
|
-
const { documents } = held;
|
|
330
423
|
const names = new Map();
|
|
331
424
|
const retired = new Set();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
425
|
+
let covered = null;
|
|
426
|
+
for (let after;;) {
|
|
427
|
+
const read = await deps.documents(declaration, after);
|
|
428
|
+
if ('pending' in read)
|
|
429
|
+
return;
|
|
430
|
+
const coverage = JSON.stringify(read.coverage);
|
|
431
|
+
if (covered !== null && coverage !== covered)
|
|
432
|
+
return readAgents();
|
|
433
|
+
covered = coverage;
|
|
434
|
+
for (const document of read.documents) {
|
|
435
|
+
const identity = document.fields?.[declaration.identity];
|
|
436
|
+
const name = document.fields?.[declaration.name];
|
|
437
|
+
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
438
|
+
continue;
|
|
439
|
+
names.set(identity, name);
|
|
440
|
+
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
441
|
+
if (ended !== undefined && ended !== null)
|
|
442
|
+
retired.add(identity);
|
|
443
|
+
}
|
|
444
|
+
if (read.next === undefined)
|
|
445
|
+
break;
|
|
446
|
+
after = read.next;
|
|
343
447
|
}
|
|
448
|
+
agentsKnown = true;
|
|
344
449
|
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
345
|
-
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
450
|
+
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents])) {
|
|
451
|
+
learned();
|
|
346
452
|
return;
|
|
453
|
+
}
|
|
347
454
|
agentNames = names;
|
|
348
455
|
retiredAgents = retired;
|
|
456
|
+
emitAgents();
|
|
349
457
|
if (named)
|
|
350
458
|
emitList();
|
|
351
|
-
|
|
459
|
+
learned();
|
|
352
460
|
const ended = [...drafts.keys()].filter(retiredChat);
|
|
353
461
|
if (ended.length > 0)
|
|
354
462
|
await remove(ended);
|
|
@@ -363,9 +471,34 @@ export function createConversationStore(deps) {
|
|
|
363
471
|
return agentsRead;
|
|
364
472
|
}
|
|
365
473
|
function live(conversation, change) {
|
|
474
|
+
const owed = unsent.get(conversation);
|
|
475
|
+
for (const fact of FACTS.filter((one) => one in change))
|
|
476
|
+
owed?.delete(fact);
|
|
366
477
|
setLive(conversation, { ...liveOf(conversation), ...change });
|
|
367
478
|
emit(conversation);
|
|
368
479
|
}
|
|
480
|
+
function openingEnded() {
|
|
481
|
+
const owed = [...unsent];
|
|
482
|
+
unsent.clear();
|
|
483
|
+
for (const [conversation, facts] of owed) {
|
|
484
|
+
const held = lives.get(conversation);
|
|
485
|
+
if (held === undefined || facts.size === 0)
|
|
486
|
+
continue;
|
|
487
|
+
setLive(conversation, {
|
|
488
|
+
turn: held.turn,
|
|
489
|
+
questions: facts.has('questions') ? QUIET.questions : held.questions,
|
|
490
|
+
process: facts.has('process') ? QUIET.process : held.process,
|
|
491
|
+
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
492
|
+
options: facts.has('options') ? QUIET.options : held.options,
|
|
493
|
+
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
494
|
+
link: facts.has('link') ? QUIET.link : held.link,
|
|
495
|
+
deliveryUnknown: facts.has('deliveryUnknown')
|
|
496
|
+
? QUIET.deliveryUnknown
|
|
497
|
+
: held.deliveryUnknown,
|
|
498
|
+
});
|
|
499
|
+
emit(conversation);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
369
502
|
function relayed(conversation, turn, operation) {
|
|
370
503
|
const held = liveOf(conversation).turn;
|
|
371
504
|
const next = held?.turn === turn ? appliedTurn(held, operation) : startedTurn(turn, operation);
|
|
@@ -392,12 +525,6 @@ export function createConversationStore(deps) {
|
|
|
392
525
|
}
|
|
393
526
|
async function remove(leaving) {
|
|
394
527
|
await deps.durably(async (local) => {
|
|
395
|
-
const removed = [];
|
|
396
|
-
for (const conversation of leaving) {
|
|
397
|
-
for (const identity of await local.messageIdentities(conversation)) {
|
|
398
|
-
removed.push({ conversation, identity, text: null });
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
528
|
await local.dropConversations(leaving);
|
|
402
529
|
const changed = [];
|
|
403
530
|
for (const conversation of leaving) {
|
|
@@ -409,11 +536,12 @@ export function createConversationStore(deps) {
|
|
|
409
536
|
partials.delete(conversation);
|
|
410
537
|
drafts.delete(conversation);
|
|
411
538
|
behind.delete(conversation);
|
|
539
|
+
unsent.delete(conversation);
|
|
412
540
|
setLive(conversation, null);
|
|
413
|
-
slide(conversation, null);
|
|
541
|
+
await slide(local, conversation, null);
|
|
414
542
|
}
|
|
415
543
|
if (changed.length > 0)
|
|
416
|
-
deps.publish(conversationChangeSet(
|
|
544
|
+
deps.publish(conversationChangeSet(changed));
|
|
417
545
|
});
|
|
418
546
|
}
|
|
419
547
|
function gap(conversation) {
|
|
@@ -438,17 +566,18 @@ export function createConversationStore(deps) {
|
|
|
438
566
|
if (advances)
|
|
439
567
|
reads.set(conversation, message.position);
|
|
440
568
|
sealTurns(conversation, new Set([message.turn]));
|
|
441
|
-
slide(conversation, [message]);
|
|
442
|
-
deps.publish(conversationChangeSet(
|
|
569
|
+
await slide(local, conversation, [message]);
|
|
570
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
443
571
|
});
|
|
444
572
|
}
|
|
445
|
-
async function readHistories(conversations) {
|
|
573
|
+
async function readHistories(conversations, ended) {
|
|
446
574
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
447
|
-
let
|
|
575
|
+
let waiting = conversations.map((conversation) => ({
|
|
448
576
|
conversation,
|
|
449
577
|
after: reads.get(conversation) ?? undefined,
|
|
450
578
|
}));
|
|
451
|
-
while (
|
|
579
|
+
while (waiting.length > 0) {
|
|
580
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
452
581
|
const result = await deps.call('conversation.history', {
|
|
453
582
|
conversations: asking.map(({ conversation, after }) => ({
|
|
454
583
|
conversation,
|
|
@@ -468,10 +597,33 @@ export function createConversationStore(deps) {
|
|
|
468
597
|
following.push({ conversation: page.conversation, after: page.next });
|
|
469
598
|
}
|
|
470
599
|
}
|
|
471
|
-
asking
|
|
600
|
+
for (const { conversation } of asking) {
|
|
601
|
+
if (!following.some((next) => next.conversation === conversation))
|
|
602
|
+
ended(conversation);
|
|
603
|
+
}
|
|
604
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
472
605
|
}
|
|
473
606
|
return null;
|
|
474
607
|
}
|
|
608
|
+
function caughtUp(conversations) {
|
|
609
|
+
const ends = new Map();
|
|
610
|
+
for (const conversation of conversations) {
|
|
611
|
+
const held = new Promise((end) => ends.set(conversation, end));
|
|
612
|
+
catching.set(conversation, held);
|
|
613
|
+
void held.then(() => {
|
|
614
|
+
if (catching.get(conversation) === held)
|
|
615
|
+
catching.delete(conversation);
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
const ended = (conversation) => ends.get(conversation)?.();
|
|
619
|
+
const read = readHistories(conversations, ended);
|
|
620
|
+
const endAll = () => {
|
|
621
|
+
for (const conversation of conversations)
|
|
622
|
+
ended(conversation);
|
|
623
|
+
};
|
|
624
|
+
read.then(endAll, endAll);
|
|
625
|
+
return read;
|
|
626
|
+
}
|
|
475
627
|
function keepPage(conversation, arriving, from, next, generation) {
|
|
476
628
|
return deps.durably(async (local) => {
|
|
477
629
|
if (!replicated.has(conversation))
|
|
@@ -490,9 +642,9 @@ export function createConversationStore(deps) {
|
|
|
490
642
|
sealTurns(conversation, new Set(arriving.map((message) => message.turn)));
|
|
491
643
|
if (whole && (gaps.get(conversation) ?? 0) === generation)
|
|
492
644
|
behind.delete(conversation);
|
|
493
|
-
slide(conversation, arriving);
|
|
645
|
+
await slide(local, conversation, arriving);
|
|
494
646
|
if (arriving.length > 0 || sealing || whole) {
|
|
495
|
-
deps.publish(conversationChangeSet(
|
|
647
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
496
648
|
}
|
|
497
649
|
});
|
|
498
650
|
}
|
|
@@ -501,11 +653,8 @@ export function createConversationStore(deps) {
|
|
|
501
653
|
if (event.kind === 'gap') {
|
|
502
654
|
if (replicated.has(conversation))
|
|
503
655
|
gap(conversation);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
return;
|
|
507
|
-
setLive(conversation, { ...QUIET, turn: held.turn });
|
|
508
|
-
emit(conversation);
|
|
656
|
+
if (lives.has(conversation))
|
|
657
|
+
unsent.set(conversation, new Set(FACTS));
|
|
509
658
|
return;
|
|
510
659
|
}
|
|
511
660
|
if (event.kind === 'turn') {
|
|
@@ -528,11 +677,30 @@ export function createConversationStore(deps) {
|
|
|
528
677
|
live(conversation, { options: structuredClone(event.options) });
|
|
529
678
|
return;
|
|
530
679
|
}
|
|
680
|
+
if (event.kind === 'starting') {
|
|
681
|
+
live(conversation, { starting: event.step });
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (event.kind === 'link') {
|
|
685
|
+
live(conversation, { link: { connected: event.connected } });
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (event.kind === 'deliveries') {
|
|
689
|
+
live(conversation, { deliveryUnknown: [...event.unknown] });
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
531
692
|
const arriving = acceptedMessage(event.message);
|
|
532
693
|
if (arriving === null)
|
|
533
694
|
return;
|
|
534
695
|
if (replicated.has(conversation)) {
|
|
535
|
-
|
|
696
|
+
if (deps.full()) {
|
|
697
|
+
gap(conversation);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
void keep(conversation, arriving).catch((error) => {
|
|
701
|
+
if (refusedForSpace(error))
|
|
702
|
+
gap(conversation);
|
|
703
|
+
});
|
|
536
704
|
return;
|
|
537
705
|
}
|
|
538
706
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -567,7 +735,6 @@ export function createConversationStore(deps) {
|
|
|
567
735
|
const blank = {
|
|
568
736
|
conversation: from,
|
|
569
737
|
text: '',
|
|
570
|
-
files: [],
|
|
571
738
|
revision: chatDraftRevision(),
|
|
572
739
|
};
|
|
573
740
|
const { moves: _answered, ...unsent } = held ?? blank;
|
|
@@ -577,7 +744,7 @@ export function createConversationStore(deps) {
|
|
|
577
744
|
drafts.set(from, left);
|
|
578
745
|
for (const one of taken)
|
|
579
746
|
drafts.set(to, one);
|
|
580
|
-
deps.publish(conversationChangeSet([
|
|
747
|
+
deps.publish(conversationChangeSet([from, to]));
|
|
581
748
|
});
|
|
582
749
|
}
|
|
583
750
|
function withDraft(conversation, next) {
|
|
@@ -586,7 +753,7 @@ export function createConversationStore(deps) {
|
|
|
586
753
|
if (following === undefined)
|
|
587
754
|
return;
|
|
588
755
|
await kept(local, conversation, following);
|
|
589
|
-
deps.publish(conversationChangeSet([
|
|
756
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
590
757
|
});
|
|
591
758
|
}
|
|
592
759
|
async function submitted(conversation, operation, draft) {
|
|
@@ -598,17 +765,12 @@ export function createConversationStore(deps) {
|
|
|
598
765
|
if (submission !== undefined)
|
|
599
766
|
return undefined;
|
|
600
767
|
const said = draft ?? current;
|
|
601
|
-
submission = {
|
|
602
|
-
operation,
|
|
603
|
-
text: said?.text ?? '',
|
|
604
|
-
files: [...(said?.files ?? [])],
|
|
605
|
-
turn: null,
|
|
606
|
-
};
|
|
768
|
+
submission = { operation, text: said?.text ?? '', turn: null };
|
|
607
769
|
return {
|
|
608
770
|
conversation,
|
|
609
771
|
...(draft === undefined || current === undefined
|
|
610
|
-
? { text: '',
|
|
611
|
-
: { text: current.text,
|
|
772
|
+
? { text: '', revision: chatDraftRevision() }
|
|
773
|
+
: { text: current.text, revision: current.revision }),
|
|
612
774
|
submitted: [...(current?.submitted ?? []), submission],
|
|
613
775
|
};
|
|
614
776
|
});
|
|
@@ -623,15 +785,14 @@ export function createConversationStore(deps) {
|
|
|
623
785
|
});
|
|
624
786
|
}
|
|
625
787
|
async function dispatched(conversation, submission) {
|
|
626
|
-
const dispatch = {};
|
|
788
|
+
const dispatch = { answered: false };
|
|
627
789
|
sending.set(submission.operation, dispatch);
|
|
628
790
|
try {
|
|
629
|
-
const files = await Promise.all(submission.files.map(async (file) => ({ ...(await declaredFile(file)), blob: file.blob })));
|
|
630
791
|
const result = await invoke('conversation.send', conversation, {
|
|
631
792
|
text: submission.text,
|
|
632
|
-
files,
|
|
633
793
|
operation_id: submission.operation,
|
|
634
794
|
});
|
|
795
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
635
796
|
if (result.kind === 'revoked-authorization')
|
|
636
797
|
return result;
|
|
637
798
|
if (result.kind !== 'action' && result.retryable) {
|
|
@@ -664,11 +825,23 @@ export function createConversationStore(deps) {
|
|
|
664
825
|
const surface = {
|
|
665
826
|
async list() {
|
|
666
827
|
await agentsReady();
|
|
667
|
-
return
|
|
828
|
+
return new Promise((settle) => {
|
|
829
|
+
const answer = (listed) => {
|
|
830
|
+
unlisted.delete(answer);
|
|
831
|
+
listWatchers.delete(answer);
|
|
832
|
+
settle(listed);
|
|
833
|
+
};
|
|
834
|
+
unlisted.add(answer);
|
|
835
|
+
learned();
|
|
836
|
+
});
|
|
668
837
|
},
|
|
669
838
|
async read(conversation, options = {}) {
|
|
670
|
-
const
|
|
671
|
-
return deps.durably(async (local) =>
|
|
839
|
+
const asked = askedOf(options);
|
|
840
|
+
return deps.durably(async (local) => {
|
|
841
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
842
|
+
const total = asked.total ? await local.messageCount(conversation) : null;
|
|
843
|
+
return structuredClone(viewOf(conversation, messages, frameOf(asked, messages, more, total)));
|
|
844
|
+
});
|
|
672
845
|
},
|
|
673
846
|
async create(input) {
|
|
674
847
|
const result = await deps.call('conversation.create', input);
|
|
@@ -683,8 +856,17 @@ export function createConversationStore(deps) {
|
|
|
683
856
|
return result;
|
|
684
857
|
},
|
|
685
858
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
859
|
+
if (deps.full())
|
|
860
|
+
return DURABLE_WRITE;
|
|
686
861
|
if (deps.online()) {
|
|
687
|
-
const
|
|
862
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
863
|
+
if (refusedForSpace(error))
|
|
864
|
+
return null;
|
|
865
|
+
throw error;
|
|
866
|
+
});
|
|
867
|
+
if (held === null)
|
|
868
|
+
return DURABLE_WRITE;
|
|
869
|
+
const { submission, earlier } = held;
|
|
688
870
|
if (!earlier || !deps.expired(operation))
|
|
689
871
|
return dispatched(conversation, submission);
|
|
690
872
|
await forgotten(conversation, submission);
|
|
@@ -693,7 +875,7 @@ export function createConversationStore(deps) {
|
|
|
693
875
|
if (draft !== undefined) {
|
|
694
876
|
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
695
877
|
? undefined
|
|
696
|
-
: returned(current ?? { conversation, text: '',
|
|
878
|
+
: returned(current ?? { conversation, text: '', revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
|
|
697
879
|
}
|
|
698
880
|
return OFFLINE;
|
|
699
881
|
},
|
|
@@ -727,21 +909,22 @@ export function createConversationStore(deps) {
|
|
|
727
909
|
return withDraft(conversation, (current) => ({
|
|
728
910
|
conversation,
|
|
729
911
|
text: draft.text,
|
|
730
|
-
files: [...draft.files],
|
|
731
912
|
revision,
|
|
732
913
|
...(current === undefined ? {} : pending(current)),
|
|
733
914
|
}));
|
|
734
915
|
},
|
|
916
|
+
prepend(conversation, draft) {
|
|
917
|
+
return withDraft(conversation, (current) => ({
|
|
918
|
+
conversation,
|
|
919
|
+
...(current === undefined ? { text: draft.text } : prepended(current, draft)),
|
|
920
|
+
revision: chatDraftRevision(),
|
|
921
|
+
...(current === undefined ? {} : pending(current)),
|
|
922
|
+
}));
|
|
923
|
+
},
|
|
735
924
|
discard(conversation) {
|
|
736
925
|
return withDraft(conversation, (current) => current === undefined
|
|
737
926
|
? undefined
|
|
738
|
-
: {
|
|
739
|
-
conversation,
|
|
740
|
-
text: '',
|
|
741
|
-
files: [],
|
|
742
|
-
revision: chatDraftRevision(),
|
|
743
|
-
...pending(current),
|
|
744
|
-
});
|
|
927
|
+
: { conversation, text: '', revision: chatDraftRevision(), ...pending(current) });
|
|
745
928
|
},
|
|
746
929
|
};
|
|
747
930
|
return {
|
|
@@ -781,12 +964,25 @@ export function createConversationStore(deps) {
|
|
|
781
964
|
await remove(leaving);
|
|
782
965
|
},
|
|
783
966
|
async catchUp(progress) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
967
|
+
if (deps.full()) {
|
|
968
|
+
if (behind.size > 0)
|
|
969
|
+
progress.complete = false;
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
973
|
+
const read = async (conversations) => {
|
|
974
|
+
if (conversations.length === 0 || deps.closed())
|
|
975
|
+
return;
|
|
976
|
+
const failed = await caughtUp(conversations);
|
|
787
977
|
if (failed?.kind === 'transport-uncertainty')
|
|
788
978
|
progress.reachable = false;
|
|
789
|
-
}
|
|
979
|
+
};
|
|
980
|
+
const asking = [...behind].filter(owed).sort();
|
|
981
|
+
const awaited = asking.filter((conversation) => catching.has(conversation));
|
|
982
|
+
await Promise.all([
|
|
983
|
+
read(asking.filter((conversation) => !catching.has(conversation))),
|
|
984
|
+
Promise.all(awaited.map((conversation) => catching.get(conversation))).then(() => read(awaited.filter((conversation) => owed(conversation) && !catching.has(conversation)))),
|
|
985
|
+
]);
|
|
790
986
|
if (behind.size > 0)
|
|
791
987
|
progress.complete = false;
|
|
792
988
|
},
|
|
@@ -826,29 +1022,42 @@ export function createConversationStore(deps) {
|
|
|
826
1022
|
gap(conversation);
|
|
827
1023
|
},
|
|
828
1024
|
reopened() {
|
|
829
|
-
sending
|
|
1025
|
+
for (const [operation, dispatch] of sending)
|
|
1026
|
+
if (!dispatch.answered)
|
|
1027
|
+
sending.delete(operation);
|
|
1028
|
+
},
|
|
1029
|
+
lost() {
|
|
1030
|
+
catching.clear();
|
|
830
1031
|
},
|
|
831
1032
|
watch(conversation, options, deliver) {
|
|
832
|
-
const
|
|
833
|
-
const key = JSON.stringify([conversation, limit ?? null]);
|
|
1033
|
+
const asked = askedOf(options);
|
|
1034
|
+
const key = JSON.stringify([conversation, asked.limit, asked.after ?? null, asked.total]);
|
|
834
1035
|
const view = views.get(key) ?? {
|
|
835
1036
|
conversation,
|
|
836
|
-
|
|
1037
|
+
asked,
|
|
837
1038
|
watchers: new Set(),
|
|
838
1039
|
window: null,
|
|
1040
|
+
more: false,
|
|
1041
|
+
total: null,
|
|
839
1042
|
};
|
|
840
1043
|
views.set(key, view);
|
|
841
1044
|
const watcher = { notify: deliver, ready: false };
|
|
842
1045
|
view.watchers.add(watcher);
|
|
843
1046
|
void deps
|
|
844
1047
|
.durably(async (local) => {
|
|
845
|
-
view.window
|
|
1048
|
+
if (view.window !== null)
|
|
1049
|
+
return;
|
|
1050
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
1051
|
+
view.window = messages;
|
|
1052
|
+
view.more = more;
|
|
1053
|
+
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
846
1054
|
})
|
|
847
1055
|
.then(() => {
|
|
848
1056
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
849
1057
|
return;
|
|
850
1058
|
watcher.ready = true;
|
|
851
|
-
|
|
1059
|
+
const window = view.window ?? [];
|
|
1060
|
+
watcher.notify(viewOf(conversation, window, sharedFrame(view, window)));
|
|
852
1061
|
})
|
|
853
1062
|
.catch(() => { });
|
|
854
1063
|
return () => {
|
|
@@ -859,25 +1068,35 @@ export function createConversationStore(deps) {
|
|
|
859
1068
|
};
|
|
860
1069
|
},
|
|
861
1070
|
watchList(deliver) {
|
|
862
|
-
|
|
1071
|
+
let ended = false;
|
|
863
1072
|
void agentsReady().then(() => {
|
|
864
|
-
if (
|
|
865
|
-
|
|
1073
|
+
if (ended)
|
|
1074
|
+
return;
|
|
1075
|
+
unlisted.add(deliver);
|
|
1076
|
+
learned();
|
|
866
1077
|
});
|
|
867
1078
|
return () => {
|
|
1079
|
+
ended = true;
|
|
1080
|
+
unlisted.delete(deliver);
|
|
868
1081
|
listWatchers.delete(deliver);
|
|
869
1082
|
};
|
|
870
1083
|
},
|
|
871
1084
|
watchAgents(deliver) {
|
|
872
|
-
|
|
873
|
-
void agentsReady().then(
|
|
874
|
-
if (!deps.closed() && agentWatchers.has(deliver))
|
|
875
|
-
deliver(agents());
|
|
876
|
-
});
|
|
1085
|
+
unnamed.add(deliver);
|
|
1086
|
+
void agentsReady().then(learned);
|
|
877
1087
|
return () => {
|
|
1088
|
+
unnamed.delete(deliver);
|
|
878
1089
|
agentWatchers.delete(deliver);
|
|
879
1090
|
};
|
|
880
1091
|
},
|
|
1092
|
+
learned,
|
|
1093
|
+
declared() {
|
|
1094
|
+
if (JSON.stringify(deps.agents()) === agentsFrom)
|
|
1095
|
+
return;
|
|
1096
|
+
agentsRead = readAgents().catch(() => {
|
|
1097
|
+
agentsRead = null;
|
|
1098
|
+
});
|
|
1099
|
+
},
|
|
881
1100
|
changed(set) {
|
|
882
1101
|
for (const conversation of set.conversations)
|
|
883
1102
|
emit(conversation);
|
|
@@ -900,6 +1119,7 @@ export function createConversationStore(deps) {
|
|
|
900
1119
|
creations.delete(entry.conversation);
|
|
901
1120
|
}
|
|
902
1121
|
listKnown = true;
|
|
1122
|
+
openingEnded();
|
|
903
1123
|
}
|
|
904
1124
|
else if (event.kind === 'listed') {
|
|
905
1125
|
listing.set(event.entry.conversation, { ...event.entry });
|
|
@@ -926,8 +1146,11 @@ export function createConversationStore(deps) {
|
|
|
926
1146
|
close() {
|
|
927
1147
|
views.clear();
|
|
928
1148
|
lives.clear();
|
|
1149
|
+
unsent.clear();
|
|
929
1150
|
listWatchers.clear();
|
|
1151
|
+
unlisted.clear();
|
|
930
1152
|
agentWatchers.clear();
|
|
1153
|
+
unnamed.clear();
|
|
931
1154
|
},
|
|
932
1155
|
};
|
|
933
1156
|
}
|