@agentshouse/mdruntime 0.1.0-ca68e8b4bbebc → 0.1.0-ca6edc1abd618
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 +70 -36
- 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 +21 -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 +25 -8
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +150 -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 +37 -6
- package/dist/collection.d.ts +6 -19
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +31 -289
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +721 -0
- package/dist/connection.d.ts +22 -12
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2485 -1036
- package/dist/conversation.d.ts +16 -3
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +238 -96
- 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 -10
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +3 -120
- 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 +4 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +51 -18
- 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 +13 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +123 -0
- package/dist/memory.d.ts +4 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +32 -26
- 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.map +1 -1
- package/dist/model.js +1 -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 +14 -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 +34 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +25 -0
- package/dist/overlay.d.ts +2 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +87 -172
- package/dist/query.d.ts +26 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +41 -6
- package/dist/reach.d.ts +5 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +167 -59
- package/dist/react.d.ts +1 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +2 -14
- 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.map +1 -1
- package/dist/reads.js +4 -2
- 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 +15 -14
- 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 +297 -188
- package/dist/room-draft.d.ts +4 -1
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +62 -22
- package/dist/rows.d.ts +29 -30
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +113 -64
- package/dist/save.d.ts +51 -14
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +518 -180
- package/dist/search.d.ts +23 -42
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +28 -182
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +18 -4
- package/dist/shared.d.ts +8 -3
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +129 -66
- package/dist/store.d.ts +89 -89
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +329 -669
- package/dist/stored.d.ts +145 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +567 -0
- package/dist/tables.d.ts +354 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +624 -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 +29 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +8 -1
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +150 -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,29 @@
|
|
|
1
1
|
import { conversationChangeSet } from './change-set.js';
|
|
2
2
|
import { runtimeError } from './failure.js';
|
|
3
|
+
import { refusedForSpace } from './durability.js';
|
|
3
4
|
import { declaredFile } from './file.js';
|
|
4
5
|
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
5
6
|
import { OFFLINE } from './outcome.js';
|
|
7
|
+
import { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
|
|
6
8
|
const QUIET = {
|
|
7
9
|
turn: null,
|
|
8
10
|
questions: [],
|
|
9
11
|
process: null,
|
|
10
12
|
commands: [],
|
|
11
13
|
options: [],
|
|
14
|
+
starting: null,
|
|
15
|
+
link: null,
|
|
16
|
+
deliveryUnknown: [],
|
|
12
17
|
};
|
|
18
|
+
const FACTS = [
|
|
19
|
+
'questions',
|
|
20
|
+
'process',
|
|
21
|
+
'commands',
|
|
22
|
+
'options',
|
|
23
|
+
'starting',
|
|
24
|
+
'link',
|
|
25
|
+
'deliveryUnknown',
|
|
26
|
+
];
|
|
13
27
|
export function unheldView(conversation) {
|
|
14
28
|
return {
|
|
15
29
|
conversation,
|
|
@@ -19,19 +33,25 @@ export function unheldView(conversation) {
|
|
|
19
33
|
process: null,
|
|
20
34
|
commands: [],
|
|
21
35
|
options: [],
|
|
36
|
+
starting: null,
|
|
37
|
+
link: null,
|
|
38
|
+
deliveryUnknown: [],
|
|
22
39
|
chatDraft: null,
|
|
23
40
|
};
|
|
24
41
|
}
|
|
25
42
|
export const SESSION_STARTED = 'Session started';
|
|
26
43
|
const NEW_CHAT = 'new:';
|
|
44
|
+
export const HISTORY_CONVERSATIONS = 64;
|
|
27
45
|
export function newChat(agent) {
|
|
28
46
|
return `${NEW_CHAT}${agent}`;
|
|
29
47
|
}
|
|
30
48
|
function creationOf(input) {
|
|
31
49
|
if (typeof input !== 'object' || input === null)
|
|
32
50
|
return null;
|
|
33
|
-
const { agent_id: agent, operation_id: operation } = input;
|
|
34
|
-
return typeof agent === 'string' && typeof operation === 'string'
|
|
51
|
+
const { agent_id: agent, operation_id: operation, replaces, } = input;
|
|
52
|
+
return typeof agent === 'string' && typeof operation === 'string' && replaces === undefined
|
|
53
|
+
? { agent, operation }
|
|
54
|
+
: null;
|
|
35
55
|
}
|
|
36
56
|
function startedTurn(turn, operation) {
|
|
37
57
|
if (operation.op === 'begin')
|
|
@@ -82,19 +102,25 @@ function appliedTurn(held, operation) {
|
|
|
82
102
|
parts: held.parts.map((kept, at) => (at === operation.index ? changed : kept)),
|
|
83
103
|
};
|
|
84
104
|
}
|
|
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
105
|
function windowOf(held, arriving, limit) {
|
|
93
106
|
const byIdentity = new Map(held.map((message) => [message.identity, message]));
|
|
94
107
|
for (const message of arriving)
|
|
95
108
|
byIdentity.set(message.identity, message);
|
|
96
|
-
const next = [...byIdentity.values()].sort(
|
|
97
|
-
|
|
109
|
+
const next = [...byIdentity.values()].sort(messageOrder);
|
|
110
|
+
const start = Math.max(0, next.length - limit);
|
|
111
|
+
return { messages: next.slice(start), dropped: start > 0 };
|
|
112
|
+
}
|
|
113
|
+
function frameOf(asked, messages, more, total) {
|
|
114
|
+
const oldest = messages[0];
|
|
115
|
+
const next = !more
|
|
116
|
+
? undefined
|
|
117
|
+
: oldest === undefined
|
|
118
|
+
? (asked.after ?? FROM_START)
|
|
119
|
+
: cursorOf([oldest.position, oldest.identity]);
|
|
120
|
+
return {
|
|
121
|
+
...(next === undefined ? {} : { next }),
|
|
122
|
+
...(total === null ? {} : { total }),
|
|
123
|
+
};
|
|
98
124
|
}
|
|
99
125
|
function newestOf(arriving, from) {
|
|
100
126
|
return arriving.reduce((top, message) => (top === null || message.position > top ? message.position : top), from);
|
|
@@ -165,18 +191,34 @@ function answered(result, field) {
|
|
|
165
191
|
const value = answer[field];
|
|
166
192
|
return typeof value === 'string' ? value : null;
|
|
167
193
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
194
|
+
function beforeOf(after) {
|
|
195
|
+
if (after === undefined)
|
|
196
|
+
return null;
|
|
197
|
+
const decoded = typeof after === 'string' ? decodedCursor(after) : null;
|
|
198
|
+
if (decoded?.length === 0)
|
|
199
|
+
return null;
|
|
200
|
+
const [position, identity] = decoded ?? [];
|
|
201
|
+
if (decoded?.length !== 2 || typeof position !== 'string' || typeof identity !== 'string') {
|
|
202
|
+
throw runtimeError('invalid-after', `conversation after must be the next an earlier view returned, got ${String(after)}`);
|
|
203
|
+
}
|
|
204
|
+
return [position, identity];
|
|
205
|
+
}
|
|
206
|
+
function askedOf(options) {
|
|
207
|
+
const { limit, after, total } = options;
|
|
208
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 0)) {
|
|
173
209
|
throw runtimeError('invalid-limit', `conversation limit must be a non-negative integer, got ${String(limit)}`);
|
|
174
210
|
}
|
|
175
|
-
return limit;
|
|
211
|
+
return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
|
|
176
212
|
}
|
|
177
213
|
const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
|
|
214
|
+
const DURABLE_WRITE = {
|
|
215
|
+
kind: 'rejected',
|
|
216
|
+
code: 'durable-write',
|
|
217
|
+
fields: {},
|
|
218
|
+
retryable: true,
|
|
219
|
+
};
|
|
178
220
|
function unwritten(draft) {
|
|
179
|
-
return draft.text === ''
|
|
221
|
+
return draft.text === '';
|
|
180
222
|
}
|
|
181
223
|
function pending(draft) {
|
|
182
224
|
return {
|
|
@@ -191,11 +233,13 @@ function withSubmitted(draft, submitted) {
|
|
|
191
233
|
const { submitted: _held, ...unsent } = draft;
|
|
192
234
|
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
193
235
|
}
|
|
236
|
+
function prepended(draft, said) {
|
|
237
|
+
return { text: [said.text, draft.text].filter((one) => one !== '').join('\n') };
|
|
238
|
+
}
|
|
194
239
|
function returned(draft, submission, others) {
|
|
195
240
|
return withSubmitted({
|
|
196
241
|
conversation: draft.conversation,
|
|
197
|
-
|
|
198
|
-
files: [...submission.files, ...draft.files],
|
|
242
|
+
...prepended(draft, submission),
|
|
199
243
|
revision: chatDraftRevision(),
|
|
200
244
|
}, others);
|
|
201
245
|
}
|
|
@@ -209,6 +253,7 @@ export function createConversationStore(deps) {
|
|
|
209
253
|
const catching = new Map();
|
|
210
254
|
const gaps = new Map();
|
|
211
255
|
const lives = new Map();
|
|
256
|
+
const unsent = new Map();
|
|
212
257
|
const views = new Map();
|
|
213
258
|
const listing = new Map();
|
|
214
259
|
const creations = new Set();
|
|
@@ -223,7 +268,7 @@ export function createConversationStore(deps) {
|
|
|
223
268
|
function liveOf(conversation) {
|
|
224
269
|
return lives.get(conversation) ?? QUIET;
|
|
225
270
|
}
|
|
226
|
-
function viewOf(conversation, held) {
|
|
271
|
+
function viewOf(conversation, held, frame) {
|
|
227
272
|
const draft = drafts.get(conversation);
|
|
228
273
|
const facts = liveOf(conversation);
|
|
229
274
|
return {
|
|
@@ -234,14 +279,18 @@ export function createConversationStore(deps) {
|
|
|
234
279
|
text,
|
|
235
280
|
message,
|
|
236
281
|
})),
|
|
282
|
+
...frame,
|
|
237
283
|
turn: structuredClone(facts.turn),
|
|
238
284
|
questions: structuredClone(facts.questions),
|
|
239
285
|
process: facts.process === null ? null : { ...facts.process },
|
|
240
286
|
commands: structuredClone(facts.commands),
|
|
241
287
|
options: structuredClone(facts.options),
|
|
288
|
+
starting: facts.starting,
|
|
289
|
+
link: facts.link === null ? null : { ...facts.link },
|
|
290
|
+
deliveryUnknown: [...facts.deliveryUnknown],
|
|
242
291
|
chatDraft: draft === undefined || unwritten(draft)
|
|
243
292
|
? null
|
|
244
|
-
: { text: draft.text,
|
|
293
|
+
: { text: draft.text, revision: draft.revision },
|
|
245
294
|
};
|
|
246
295
|
}
|
|
247
296
|
function emit(conversation) {
|
|
@@ -253,21 +302,36 @@ export function createConversationStore(deps) {
|
|
|
253
302
|
const ready = [...view.watchers].filter((watcher) => watcher.ready);
|
|
254
303
|
if (ready.length === 0)
|
|
255
304
|
continue;
|
|
256
|
-
const value = viewOf(conversation, view.window);
|
|
305
|
+
const value = viewOf(conversation, view.window, sharedFrame(view, view.window));
|
|
257
306
|
for (const watcher of ready)
|
|
258
307
|
watcher.notify(value);
|
|
259
308
|
}
|
|
260
309
|
}
|
|
261
|
-
function
|
|
310
|
+
function sharedFrame(view, window) {
|
|
311
|
+
return frameOf(view.asked, window, view.more, view.total);
|
|
312
|
+
}
|
|
313
|
+
async function slide(local, conversation, arriving) {
|
|
314
|
+
let count;
|
|
262
315
|
for (const view of views.values()) {
|
|
263
316
|
if (view.conversation !== conversation || view.window === null)
|
|
264
317
|
continue;
|
|
265
|
-
|
|
318
|
+
if (arriving === null) {
|
|
319
|
+
view.window = [];
|
|
320
|
+
view.more = false;
|
|
321
|
+
if (view.total !== null)
|
|
322
|
+
view.total = 0;
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const joining = arriving.filter((message) => precedes(message, view.asked.before));
|
|
326
|
+
const next = windowOf(view.window, joining, view.asked.limit);
|
|
327
|
+
view.window = next.messages;
|
|
328
|
+
view.more ||= next.dropped;
|
|
329
|
+
if (view.total !== null && arriving.length > 0) {
|
|
330
|
+
count ??= await local.messageCount(conversation);
|
|
331
|
+
view.total = count;
|
|
332
|
+
}
|
|
266
333
|
}
|
|
267
334
|
}
|
|
268
|
-
function changesOf(conversation, arriving) {
|
|
269
|
-
return arriving.map(({ identity, text }) => ({ conversation, identity, text }));
|
|
270
|
-
}
|
|
271
335
|
function stateOf(conversation) {
|
|
272
336
|
const facts = liveOf(conversation);
|
|
273
337
|
if (facts.questions.length > 0)
|
|
@@ -282,6 +346,7 @@ export function createConversationStore(deps) {
|
|
|
282
346
|
created: entry.created,
|
|
283
347
|
finished: entry.finished,
|
|
284
348
|
outcome: entry.outcome,
|
|
349
|
+
waiting: entry.waiting,
|
|
285
350
|
state: stateOf(entry.conversation),
|
|
286
351
|
started: lives.get(entry.conversation)?.turn?.started ?? null,
|
|
287
352
|
}));
|
|
@@ -324,23 +389,30 @@ export function createConversationStore(deps) {
|
|
|
324
389
|
const declaration = deps.agents();
|
|
325
390
|
if (declaration === undefined)
|
|
326
391
|
return;
|
|
327
|
-
const held = await deps.documents(declaration);
|
|
328
|
-
if ('pending' in held)
|
|
329
|
-
return;
|
|
330
|
-
const { documents } = held;
|
|
331
392
|
const names = new Map();
|
|
332
393
|
const retired = new Set();
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
394
|
+
let covered = null;
|
|
395
|
+
for (let after;;) {
|
|
396
|
+
const read = await deps.documents(declaration, after);
|
|
397
|
+
if ('pending' in read)
|
|
398
|
+
return;
|
|
399
|
+
const coverage = JSON.stringify(read.coverage);
|
|
400
|
+
if (covered !== null && coverage !== covered)
|
|
401
|
+
return readAgents();
|
|
402
|
+
covered = coverage;
|
|
403
|
+
for (const document of read.documents) {
|
|
404
|
+
const identity = document.fields?.[declaration.identity];
|
|
405
|
+
const name = document.fields?.[declaration.name];
|
|
406
|
+
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
407
|
+
continue;
|
|
408
|
+
names.set(identity, name);
|
|
409
|
+
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
410
|
+
if (ended !== undefined && ended !== null)
|
|
411
|
+
retired.add(identity);
|
|
412
|
+
}
|
|
413
|
+
if (read.next === undefined)
|
|
414
|
+
break;
|
|
415
|
+
after = read.next;
|
|
344
416
|
}
|
|
345
417
|
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
346
418
|
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
@@ -364,9 +436,34 @@ export function createConversationStore(deps) {
|
|
|
364
436
|
return agentsRead;
|
|
365
437
|
}
|
|
366
438
|
function live(conversation, change) {
|
|
439
|
+
const owed = unsent.get(conversation);
|
|
440
|
+
for (const fact of FACTS.filter((one) => one in change))
|
|
441
|
+
owed?.delete(fact);
|
|
367
442
|
setLive(conversation, { ...liveOf(conversation), ...change });
|
|
368
443
|
emit(conversation);
|
|
369
444
|
}
|
|
445
|
+
function openingEnded() {
|
|
446
|
+
const owed = [...unsent];
|
|
447
|
+
unsent.clear();
|
|
448
|
+
for (const [conversation, facts] of owed) {
|
|
449
|
+
const held = lives.get(conversation);
|
|
450
|
+
if (held === undefined || facts.size === 0)
|
|
451
|
+
continue;
|
|
452
|
+
setLive(conversation, {
|
|
453
|
+
turn: held.turn,
|
|
454
|
+
questions: facts.has('questions') ? QUIET.questions : held.questions,
|
|
455
|
+
process: facts.has('process') ? QUIET.process : held.process,
|
|
456
|
+
commands: facts.has('commands') ? QUIET.commands : held.commands,
|
|
457
|
+
options: facts.has('options') ? QUIET.options : held.options,
|
|
458
|
+
starting: facts.has('starting') ? QUIET.starting : held.starting,
|
|
459
|
+
link: facts.has('link') ? QUIET.link : held.link,
|
|
460
|
+
deliveryUnknown: facts.has('deliveryUnknown')
|
|
461
|
+
? QUIET.deliveryUnknown
|
|
462
|
+
: held.deliveryUnknown,
|
|
463
|
+
});
|
|
464
|
+
emit(conversation);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
370
467
|
function relayed(conversation, turn, operation) {
|
|
371
468
|
const held = liveOf(conversation).turn;
|
|
372
469
|
const next = held?.turn === turn ? appliedTurn(held, operation) : startedTurn(turn, operation);
|
|
@@ -393,12 +490,6 @@ export function createConversationStore(deps) {
|
|
|
393
490
|
}
|
|
394
491
|
async function remove(leaving) {
|
|
395
492
|
await deps.durably(async (local) => {
|
|
396
|
-
const removed = [];
|
|
397
|
-
for (const conversation of leaving) {
|
|
398
|
-
for (const identity of await local.messageIdentities(conversation)) {
|
|
399
|
-
removed.push({ conversation, identity, text: null });
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
493
|
await local.dropConversations(leaving);
|
|
403
494
|
const changed = [];
|
|
404
495
|
for (const conversation of leaving) {
|
|
@@ -410,11 +501,12 @@ export function createConversationStore(deps) {
|
|
|
410
501
|
partials.delete(conversation);
|
|
411
502
|
drafts.delete(conversation);
|
|
412
503
|
behind.delete(conversation);
|
|
504
|
+
unsent.delete(conversation);
|
|
413
505
|
setLive(conversation, null);
|
|
414
|
-
slide(conversation, null);
|
|
506
|
+
await slide(local, conversation, null);
|
|
415
507
|
}
|
|
416
508
|
if (changed.length > 0)
|
|
417
|
-
deps.publish(conversationChangeSet(
|
|
509
|
+
deps.publish(conversationChangeSet(changed));
|
|
418
510
|
});
|
|
419
511
|
}
|
|
420
512
|
function gap(conversation) {
|
|
@@ -439,17 +531,18 @@ export function createConversationStore(deps) {
|
|
|
439
531
|
if (advances)
|
|
440
532
|
reads.set(conversation, message.position);
|
|
441
533
|
sealTurns(conversation, new Set([message.turn]));
|
|
442
|
-
slide(conversation, [message]);
|
|
443
|
-
deps.publish(conversationChangeSet(
|
|
534
|
+
await slide(local, conversation, [message]);
|
|
535
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
444
536
|
});
|
|
445
537
|
}
|
|
446
538
|
async function readHistories(conversations, ended) {
|
|
447
539
|
const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
|
|
448
|
-
let
|
|
540
|
+
let waiting = conversations.map((conversation) => ({
|
|
449
541
|
conversation,
|
|
450
542
|
after: reads.get(conversation) ?? undefined,
|
|
451
543
|
}));
|
|
452
|
-
while (
|
|
544
|
+
while (waiting.length > 0) {
|
|
545
|
+
const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
|
|
453
546
|
const result = await deps.call('conversation.history', {
|
|
454
547
|
conversations: asking.map(({ conversation, after }) => ({
|
|
455
548
|
conversation,
|
|
@@ -473,7 +566,7 @@ export function createConversationStore(deps) {
|
|
|
473
566
|
if (!following.some((next) => next.conversation === conversation))
|
|
474
567
|
ended(conversation);
|
|
475
568
|
}
|
|
476
|
-
|
|
569
|
+
waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
|
|
477
570
|
}
|
|
478
571
|
return null;
|
|
479
572
|
}
|
|
@@ -514,9 +607,9 @@ export function createConversationStore(deps) {
|
|
|
514
607
|
sealTurns(conversation, new Set(arriving.map((message) => message.turn)));
|
|
515
608
|
if (whole && (gaps.get(conversation) ?? 0) === generation)
|
|
516
609
|
behind.delete(conversation);
|
|
517
|
-
slide(conversation, arriving);
|
|
610
|
+
await slide(local, conversation, arriving);
|
|
518
611
|
if (arriving.length > 0 || sealing || whole) {
|
|
519
|
-
deps.publish(conversationChangeSet(
|
|
612
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
520
613
|
}
|
|
521
614
|
});
|
|
522
615
|
}
|
|
@@ -525,11 +618,8 @@ export function createConversationStore(deps) {
|
|
|
525
618
|
if (event.kind === 'gap') {
|
|
526
619
|
if (replicated.has(conversation))
|
|
527
620
|
gap(conversation);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
return;
|
|
531
|
-
setLive(conversation, { ...QUIET, turn: held.turn });
|
|
532
|
-
emit(conversation);
|
|
621
|
+
if (lives.has(conversation))
|
|
622
|
+
unsent.set(conversation, new Set(FACTS));
|
|
533
623
|
return;
|
|
534
624
|
}
|
|
535
625
|
if (event.kind === 'turn') {
|
|
@@ -552,11 +642,30 @@ export function createConversationStore(deps) {
|
|
|
552
642
|
live(conversation, { options: structuredClone(event.options) });
|
|
553
643
|
return;
|
|
554
644
|
}
|
|
645
|
+
if (event.kind === 'starting') {
|
|
646
|
+
live(conversation, { starting: event.step });
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (event.kind === 'link') {
|
|
650
|
+
live(conversation, { link: { connected: event.connected } });
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (event.kind === 'deliveries') {
|
|
654
|
+
live(conversation, { deliveryUnknown: [...event.unknown] });
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
555
657
|
const arriving = acceptedMessage(event.message);
|
|
556
658
|
if (arriving === null)
|
|
557
659
|
return;
|
|
558
660
|
if (replicated.has(conversation)) {
|
|
559
|
-
|
|
661
|
+
if (deps.full()) {
|
|
662
|
+
gap(conversation);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
void keep(conversation, arriving).catch((error) => {
|
|
666
|
+
if (refusedForSpace(error))
|
|
667
|
+
gap(conversation);
|
|
668
|
+
});
|
|
560
669
|
return;
|
|
561
670
|
}
|
|
562
671
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
@@ -591,7 +700,6 @@ export function createConversationStore(deps) {
|
|
|
591
700
|
const blank = {
|
|
592
701
|
conversation: from,
|
|
593
702
|
text: '',
|
|
594
|
-
files: [],
|
|
595
703
|
revision: chatDraftRevision(),
|
|
596
704
|
};
|
|
597
705
|
const { moves: _answered, ...unsent } = held ?? blank;
|
|
@@ -601,7 +709,7 @@ export function createConversationStore(deps) {
|
|
|
601
709
|
drafts.set(from, left);
|
|
602
710
|
for (const one of taken)
|
|
603
711
|
drafts.set(to, one);
|
|
604
|
-
deps.publish(conversationChangeSet([
|
|
712
|
+
deps.publish(conversationChangeSet([from, to]));
|
|
605
713
|
});
|
|
606
714
|
}
|
|
607
715
|
function withDraft(conversation, next) {
|
|
@@ -610,7 +718,7 @@ export function createConversationStore(deps) {
|
|
|
610
718
|
if (following === undefined)
|
|
611
719
|
return;
|
|
612
720
|
await kept(local, conversation, following);
|
|
613
|
-
deps.publish(conversationChangeSet([
|
|
721
|
+
deps.publish(conversationChangeSet([conversation]));
|
|
614
722
|
});
|
|
615
723
|
}
|
|
616
724
|
async function submitted(conversation, operation, draft) {
|
|
@@ -622,17 +730,12 @@ export function createConversationStore(deps) {
|
|
|
622
730
|
if (submission !== undefined)
|
|
623
731
|
return undefined;
|
|
624
732
|
const said = draft ?? current;
|
|
625
|
-
submission = {
|
|
626
|
-
operation,
|
|
627
|
-
text: said?.text ?? '',
|
|
628
|
-
files: [...(said?.files ?? [])],
|
|
629
|
-
turn: null,
|
|
630
|
-
};
|
|
733
|
+
submission = { operation, text: said?.text ?? '', turn: null };
|
|
631
734
|
return {
|
|
632
735
|
conversation,
|
|
633
736
|
...(draft === undefined || current === undefined
|
|
634
|
-
? { text: '',
|
|
635
|
-
: { text: current.text,
|
|
737
|
+
? { text: '', revision: chatDraftRevision() }
|
|
738
|
+
: { text: current.text, revision: current.revision }),
|
|
636
739
|
submitted: [...(current?.submitted ?? []), submission],
|
|
637
740
|
};
|
|
638
741
|
});
|
|
@@ -647,15 +750,14 @@ export function createConversationStore(deps) {
|
|
|
647
750
|
});
|
|
648
751
|
}
|
|
649
752
|
async function dispatched(conversation, submission) {
|
|
650
|
-
const dispatch = {};
|
|
753
|
+
const dispatch = { answered: false };
|
|
651
754
|
sending.set(submission.operation, dispatch);
|
|
652
755
|
try {
|
|
653
|
-
const files = await Promise.all(submission.files.map(async (file) => ({ ...(await declaredFile(file)), blob: file.blob })));
|
|
654
756
|
const result = await invoke('conversation.send', conversation, {
|
|
655
757
|
text: submission.text,
|
|
656
|
-
files,
|
|
657
758
|
operation_id: submission.operation,
|
|
658
759
|
});
|
|
760
|
+
dispatch.answered = result.kind !== 'transport-uncertainty';
|
|
659
761
|
if (result.kind === 'revoked-authorization')
|
|
660
762
|
return result;
|
|
661
763
|
if (result.kind !== 'action' && result.retryable) {
|
|
@@ -691,8 +793,12 @@ export function createConversationStore(deps) {
|
|
|
691
793
|
return entries();
|
|
692
794
|
},
|
|
693
795
|
async read(conversation, options = {}) {
|
|
694
|
-
const
|
|
695
|
-
return deps.durably(async (local) =>
|
|
796
|
+
const asked = askedOf(options);
|
|
797
|
+
return deps.durably(async (local) => {
|
|
798
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
799
|
+
const total = asked.total ? await local.messageCount(conversation) : null;
|
|
800
|
+
return structuredClone(viewOf(conversation, messages, frameOf(asked, messages, more, total)));
|
|
801
|
+
});
|
|
696
802
|
},
|
|
697
803
|
async create(input) {
|
|
698
804
|
const result = await deps.call('conversation.create', input);
|
|
@@ -707,8 +813,17 @@ export function createConversationStore(deps) {
|
|
|
707
813
|
return result;
|
|
708
814
|
},
|
|
709
815
|
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
816
|
+
if (deps.full())
|
|
817
|
+
return DURABLE_WRITE;
|
|
710
818
|
if (deps.online()) {
|
|
711
|
-
const
|
|
819
|
+
const held = await submitted(conversation, operation, draft).catch((error) => {
|
|
820
|
+
if (refusedForSpace(error))
|
|
821
|
+
return null;
|
|
822
|
+
throw error;
|
|
823
|
+
});
|
|
824
|
+
if (held === null)
|
|
825
|
+
return DURABLE_WRITE;
|
|
826
|
+
const { submission, earlier } = held;
|
|
712
827
|
if (!earlier || !deps.expired(operation))
|
|
713
828
|
return dispatched(conversation, submission);
|
|
714
829
|
await forgotten(conversation, submission);
|
|
@@ -717,10 +832,19 @@ export function createConversationStore(deps) {
|
|
|
717
832
|
if (draft !== undefined) {
|
|
718
833
|
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
719
834
|
? undefined
|
|
720
|
-
: returned(current ?? { conversation, text: '',
|
|
835
|
+
: returned(current ?? { conversation, text: '', revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
|
|
721
836
|
}
|
|
722
837
|
return OFFLINE;
|
|
723
838
|
},
|
|
839
|
+
async attach(room, file) {
|
|
840
|
+
if (!deps.online())
|
|
841
|
+
return OFFLINE;
|
|
842
|
+
return deps.call('conversation.attach', {
|
|
843
|
+
room,
|
|
844
|
+
...(await declaredFile(file)),
|
|
845
|
+
blob: file.blob,
|
|
846
|
+
});
|
|
847
|
+
},
|
|
724
848
|
answer(conversation, answer) {
|
|
725
849
|
return invoke('conversation.answer', conversation, { answer });
|
|
726
850
|
},
|
|
@@ -751,21 +875,22 @@ export function createConversationStore(deps) {
|
|
|
751
875
|
return withDraft(conversation, (current) => ({
|
|
752
876
|
conversation,
|
|
753
877
|
text: draft.text,
|
|
754
|
-
files: [...draft.files],
|
|
755
878
|
revision,
|
|
756
879
|
...(current === undefined ? {} : pending(current)),
|
|
757
880
|
}));
|
|
758
881
|
},
|
|
882
|
+
prepend(conversation, draft) {
|
|
883
|
+
return withDraft(conversation, (current) => ({
|
|
884
|
+
conversation,
|
|
885
|
+
...(current === undefined ? { text: draft.text } : prepended(current, draft)),
|
|
886
|
+
revision: chatDraftRevision(),
|
|
887
|
+
...(current === undefined ? {} : pending(current)),
|
|
888
|
+
}));
|
|
889
|
+
},
|
|
759
890
|
discard(conversation) {
|
|
760
891
|
return withDraft(conversation, (current) => current === undefined
|
|
761
892
|
? undefined
|
|
762
|
-
: {
|
|
763
|
-
conversation,
|
|
764
|
-
text: '',
|
|
765
|
-
files: [],
|
|
766
|
-
revision: chatDraftRevision(),
|
|
767
|
-
...pending(current),
|
|
768
|
-
});
|
|
893
|
+
: { conversation, text: '', revision: chatDraftRevision(), ...pending(current) });
|
|
769
894
|
},
|
|
770
895
|
};
|
|
771
896
|
return {
|
|
@@ -805,6 +930,11 @@ export function createConversationStore(deps) {
|
|
|
805
930
|
await remove(leaving);
|
|
806
931
|
},
|
|
807
932
|
async catchUp(progress) {
|
|
933
|
+
if (deps.full()) {
|
|
934
|
+
if (behind.size > 0)
|
|
935
|
+
progress.complete = false;
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
808
938
|
const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
|
|
809
939
|
const read = async (conversations) => {
|
|
810
940
|
if (conversations.length === 0 || deps.closed())
|
|
@@ -858,32 +988,42 @@ export function createConversationStore(deps) {
|
|
|
858
988
|
gap(conversation);
|
|
859
989
|
},
|
|
860
990
|
reopened() {
|
|
861
|
-
sending
|
|
991
|
+
for (const [operation, dispatch] of sending)
|
|
992
|
+
if (!dispatch.answered)
|
|
993
|
+
sending.delete(operation);
|
|
862
994
|
},
|
|
863
995
|
lost() {
|
|
864
996
|
catching.clear();
|
|
865
997
|
},
|
|
866
998
|
watch(conversation, options, deliver) {
|
|
867
|
-
const
|
|
868
|
-
const key = JSON.stringify([conversation, limit ?? null]);
|
|
999
|
+
const asked = askedOf(options);
|
|
1000
|
+
const key = JSON.stringify([conversation, asked.limit, asked.after ?? null, asked.total]);
|
|
869
1001
|
const view = views.get(key) ?? {
|
|
870
1002
|
conversation,
|
|
871
|
-
|
|
1003
|
+
asked,
|
|
872
1004
|
watchers: new Set(),
|
|
873
1005
|
window: null,
|
|
1006
|
+
more: false,
|
|
1007
|
+
total: null,
|
|
874
1008
|
};
|
|
875
1009
|
views.set(key, view);
|
|
876
1010
|
const watcher = { notify: deliver, ready: false };
|
|
877
1011
|
view.watchers.add(watcher);
|
|
878
1012
|
void deps
|
|
879
1013
|
.durably(async (local) => {
|
|
880
|
-
view.window
|
|
1014
|
+
if (view.window !== null)
|
|
1015
|
+
return;
|
|
1016
|
+
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
1017
|
+
view.window = messages;
|
|
1018
|
+
view.more = more;
|
|
1019
|
+
view.total = asked.total ? await local.messageCount(conversation) : null;
|
|
881
1020
|
})
|
|
882
1021
|
.then(() => {
|
|
883
1022
|
if (deps.closed() || !view.watchers.has(watcher))
|
|
884
1023
|
return;
|
|
885
1024
|
watcher.ready = true;
|
|
886
|
-
|
|
1025
|
+
const window = view.window ?? [];
|
|
1026
|
+
watcher.notify(viewOf(conversation, window, sharedFrame(view, window)));
|
|
887
1027
|
})
|
|
888
1028
|
.catch(() => { });
|
|
889
1029
|
return () => {
|
|
@@ -935,6 +1075,7 @@ export function createConversationStore(deps) {
|
|
|
935
1075
|
creations.delete(entry.conversation);
|
|
936
1076
|
}
|
|
937
1077
|
listKnown = true;
|
|
1078
|
+
openingEnded();
|
|
938
1079
|
}
|
|
939
1080
|
else if (event.kind === 'listed') {
|
|
940
1081
|
listing.set(event.entry.conversation, { ...event.entry });
|
|
@@ -961,6 +1102,7 @@ export function createConversationStore(deps) {
|
|
|
961
1102
|
close() {
|
|
962
1103
|
views.clear();
|
|
963
1104
|
lives.clear();
|
|
1105
|
+
unsent.clear();
|
|
964
1106
|
listWatchers.clear();
|
|
965
1107
|
agentWatchers.clear();
|
|
966
1108
|
},
|
package/dist/digest.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AA0EA,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,GAAG,IAAI,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,MAAM,IAAI,MAAM,CAoC/B;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxD"}
|