@agentshouse/mdruntime 0.1.0-c967d1ca66fee → 0.1.0-ca14c49c06d90
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 +142 -112
- package/README.md +11 -1
- package/dist/adapter.d.ts +59 -13
- 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 +70 -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 +2 -2
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +33 -14
- 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 +33 -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 +26 -0
- package/dist/chat/list.d.ts.map +1 -0
- package/dist/chat/list.js +62 -0
- package/dist/chat/markdown.d.ts +20 -0
- package/dist/chat/markdown.d.ts.map +1 -0
- package/dist/chat/markdown.js +188 -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 +620 -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 +11 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +12 -2
- package/dist/connection.d.ts +13 -6
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +573 -193
- package/dist/conversation.d.ts +14 -4
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +188 -63
- package/dist/entry.d.ts +17 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +156 -0
- package/dist/expectation.d.ts +21 -0
- package/dist/expectation.d.ts.map +1 -0
- package/dist/expectation.js +70 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/host.d.ts +3 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +13 -6
- 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 +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/memory.d.ts +4 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +40 -11
- package/dist/outcome.d.ts +11 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +7 -0
- package/dist/overlay.d.ts +13 -2
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +64 -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 +26 -4
- 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 +23 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +309 -18
- package/dist/store.d.ts +36 -18
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +291 -172
- package/dist/wire.d.ts +3 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +3 -0
- package/package.json +26 -14
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
package/dist/conversation.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ConversationAction, ConversationAgents, ConversationEvent, Convers
|
|
|
2
2
|
import { type ChangeSet } from './change-set.js';
|
|
3
3
|
import { type ChatDraftFile } from './file.js';
|
|
4
4
|
import type { Open } from './open.js';
|
|
5
|
-
import type
|
|
5
|
+
import { type CallResult, type Offline } from './outcome.js';
|
|
6
6
|
import type { DocumentResult } from './query.js';
|
|
7
7
|
import type { SearchedMessage } from './search.js';
|
|
8
8
|
import type { CycleProgress } from './status.js';
|
|
@@ -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,13 +48,15 @@ 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[]>;
|
|
51
57
|
read(conversation: string, options?: ConversationOptions): Promise<ConversationView>;
|
|
52
58
|
create(input: unknown): Promise<CallResult>;
|
|
53
|
-
send(conversation: string): Promise<CallResult>;
|
|
59
|
+
send(conversation: string, operation?: string, draft?: ChatDraft): Promise<CallResult | Offline>;
|
|
54
60
|
answer(conversation: string, answer: unknown): Promise<CallResult>;
|
|
55
61
|
interrupt(conversation: string): Promise<CallResult>;
|
|
56
62
|
kill(conversation: string): Promise<CallResult>;
|
|
@@ -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 = {
|
|
@@ -68,6 +74,7 @@ export type ConversationDependencies = {
|
|
|
68
74
|
durably<T>(work: (local: RuntimeStore) => Promise<T>): Promise<T>;
|
|
69
75
|
stream(): ConversationStream | undefined;
|
|
70
76
|
publish(set: ChangeSet): void;
|
|
77
|
+
online(): boolean;
|
|
71
78
|
closed(): boolean;
|
|
72
79
|
};
|
|
73
80
|
export type ConversationStore = {
|
|
@@ -76,10 +83,12 @@ export type ConversationStore = {
|
|
|
76
83
|
hydrate(held: readonly HeldConversation[], drafts: readonly ChatDraftRecord[]): void;
|
|
77
84
|
reconcile(): Promise<void>;
|
|
78
85
|
catchUp(progress: CycleProgress): Promise<void>;
|
|
86
|
+
resend(progress: CycleProgress): Promise<void>;
|
|
79
87
|
current(): boolean;
|
|
80
88
|
reconnected(): void;
|
|
81
89
|
watch(conversation: string, options: ConversationOptions, deliver: (view: ConversationView) => void): () => void;
|
|
82
90
|
watchList(deliver: (entries: readonly ConversationEntry[]) => void): () => void;
|
|
91
|
+
watchAgents(deliver: (agents: readonly ConversationAgent[]) => void): () => void;
|
|
83
92
|
changed(set: ChangeSet): void;
|
|
84
93
|
receive(event: ConversationEvent): boolean;
|
|
85
94
|
messages(): readonly SearchedMessage[];
|
|
@@ -87,5 +96,6 @@ export type ConversationStore = {
|
|
|
87
96
|
close(): void;
|
|
88
97
|
};
|
|
89
98
|
export declare function unheldView(conversation: string): ConversationView;
|
|
99
|
+
export declare const SESSION_STARTED = "Session started";
|
|
90
100
|
export declare function createConversationStore(deps: ConversationDependencies): ConversationStore;
|
|
91
101
|
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -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":"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"}
|
package/dist/conversation.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { conversationChangeSet } from './change-set.js';
|
|
2
2
|
import { runtimeError } from './failure.js';
|
|
3
3
|
import { declaredFile } from './file.js';
|
|
4
|
+
import { changeBatchIdentity, chatDraftRevision } from './identity.js';
|
|
5
|
+
import { OFFLINE } from './outcome.js';
|
|
4
6
|
const QUIET = {
|
|
5
7
|
turn: null,
|
|
6
8
|
questions: [],
|
|
@@ -20,6 +22,7 @@ export function unheldView(conversation) {
|
|
|
20
22
|
chatDraft: null,
|
|
21
23
|
};
|
|
22
24
|
}
|
|
25
|
+
export const SESSION_STARTED = 'Session started';
|
|
23
26
|
function startedTurn(turn, operation) {
|
|
24
27
|
if (operation.op === 'begin')
|
|
25
28
|
return { turn, started: operation.at, parts: [], context: null };
|
|
@@ -157,11 +160,29 @@ function limitOf(options) {
|
|
|
157
160
|
}
|
|
158
161
|
return limit;
|
|
159
162
|
}
|
|
163
|
+
function unwritten(draft) {
|
|
164
|
+
return draft.text === '' && draft.files.length === 0;
|
|
165
|
+
}
|
|
166
|
+
function pending(draft) {
|
|
167
|
+
return draft.submitted === undefined ? {} : { submitted: draft.submitted };
|
|
168
|
+
}
|
|
169
|
+
function withSubmitted(draft, submitted) {
|
|
170
|
+
const { submitted: _held, ...unsent } = draft;
|
|
171
|
+
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
172
|
+
}
|
|
173
|
+
function returned(draft, submission, others) {
|
|
174
|
+
return withSubmitted({
|
|
175
|
+
conversation: draft.conversation,
|
|
176
|
+
text: [submission.text, draft.text].filter((one) => one !== '').join('\n'),
|
|
177
|
+
files: [...submission.files, ...draft.files],
|
|
178
|
+
revision: chatDraftRevision(),
|
|
179
|
+
}, others);
|
|
180
|
+
}
|
|
160
181
|
export function createConversationStore(deps) {
|
|
161
182
|
const messages = new Map();
|
|
162
183
|
const reads = new Map();
|
|
163
184
|
const drafts = new Map();
|
|
164
|
-
const sending = new
|
|
185
|
+
const sending = new Set();
|
|
165
186
|
const behind = new Set();
|
|
166
187
|
const gaps = new Map();
|
|
167
188
|
const lives = new Map();
|
|
@@ -169,7 +190,9 @@ export function createConversationStore(deps) {
|
|
|
169
190
|
const listing = new Map();
|
|
170
191
|
const listWatchers = new Set();
|
|
171
192
|
let listKnown = false;
|
|
193
|
+
const agentWatchers = new Set();
|
|
172
194
|
let agentNames = new Map();
|
|
195
|
+
let retiredAgents = new Set();
|
|
173
196
|
let agentsRead = null;
|
|
174
197
|
let replicated = new Set();
|
|
175
198
|
let handedReplicated;
|
|
@@ -197,9 +220,9 @@ export function createConversationStore(deps) {
|
|
|
197
220
|
process: facts.process === null ? null : { ...facts.process },
|
|
198
221
|
commands: structuredClone(facts.commands),
|
|
199
222
|
options: structuredClone(facts.options),
|
|
200
|
-
chatDraft: draft === undefined || draft
|
|
223
|
+
chatDraft: draft === undefined || unwritten(draft)
|
|
201
224
|
? null
|
|
202
|
-
: { text: draft.text, files: [...draft.files] },
|
|
225
|
+
: { text: draft.text, files: [...draft.files], revision: draft.revision },
|
|
203
226
|
};
|
|
204
227
|
}
|
|
205
228
|
function emit(conversation, messagesChanged = true) {
|
|
@@ -244,6 +267,21 @@ export function createConversationStore(deps) {
|
|
|
244
267
|
for (const watcher of listWatchers)
|
|
245
268
|
watcher(value);
|
|
246
269
|
}
|
|
270
|
+
function agents() {
|
|
271
|
+
return [...agentNames]
|
|
272
|
+
.filter(([identity]) => !retiredAgents.has(identity))
|
|
273
|
+
.map(([identity, name]) => ({ identity, name }))
|
|
274
|
+
.sort((left, right) => left.name === right.name
|
|
275
|
+
? left.identity.localeCompare(right.identity)
|
|
276
|
+
: left.name.localeCompare(right.name));
|
|
277
|
+
}
|
|
278
|
+
function emitAgents() {
|
|
279
|
+
if (deps.closed() || agentWatchers.size === 0)
|
|
280
|
+
return;
|
|
281
|
+
const value = agents();
|
|
282
|
+
for (const watcher of agentWatchers)
|
|
283
|
+
watcher(value);
|
|
284
|
+
}
|
|
247
285
|
function setLive(conversation, next) {
|
|
248
286
|
const before = stateOf(conversation);
|
|
249
287
|
const began = lives.get(conversation)?.turn?.started;
|
|
@@ -262,18 +300,27 @@ export function createConversationStore(deps) {
|
|
|
262
300
|
return;
|
|
263
301
|
const { documents } = await deps.documents(declaration.locator);
|
|
264
302
|
const names = new Map();
|
|
303
|
+
const retired = new Set();
|
|
265
304
|
for (const document of documents) {
|
|
266
305
|
if (document.type !== declaration.type)
|
|
267
306
|
continue;
|
|
268
307
|
const identity = document.fields?.[declaration.identity];
|
|
269
308
|
const name = document.fields?.[declaration.name];
|
|
270
|
-
if (typeof identity
|
|
271
|
-
|
|
309
|
+
if (typeof identity !== 'string' || typeof name !== 'string')
|
|
310
|
+
continue;
|
|
311
|
+
names.set(identity, name);
|
|
312
|
+
const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
|
|
313
|
+
if (ended !== undefined && ended !== null)
|
|
314
|
+
retired.add(identity);
|
|
272
315
|
}
|
|
273
|
-
|
|
316
|
+
const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
|
|
317
|
+
if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
|
|
274
318
|
return;
|
|
275
319
|
agentNames = names;
|
|
276
|
-
|
|
320
|
+
retiredAgents = retired;
|
|
321
|
+
if (named)
|
|
322
|
+
emitList();
|
|
323
|
+
emitAgents();
|
|
277
324
|
}
|
|
278
325
|
function agentsReady() {
|
|
279
326
|
agentsRead ??= readAgents().catch(() => {
|
|
@@ -343,18 +390,15 @@ export function createConversationStore(deps) {
|
|
|
343
390
|
const advances = read !== undefined &&
|
|
344
391
|
!behind.has(conversation) &&
|
|
345
392
|
(read === null || message.position > read);
|
|
346
|
-
|
|
393
|
+
await sealed(local, conversation, new Set([message.turn]));
|
|
347
394
|
await local.keepMessages({
|
|
348
395
|
conversation,
|
|
349
396
|
messages: [message],
|
|
350
397
|
...(advances ? { read: message.position } : {}),
|
|
351
|
-
sealed,
|
|
352
398
|
});
|
|
353
399
|
messages.set(conversation, merged(messages.get(conversation) ?? [], [message]));
|
|
354
400
|
if (advances)
|
|
355
401
|
reads.set(conversation, message.position);
|
|
356
|
-
if (sealed)
|
|
357
|
-
drafts.delete(conversation);
|
|
358
402
|
sealTurns(conversation, new Set([message.turn]));
|
|
359
403
|
deps.publish(conversationChangeSet([{ conversation, identity: message.identity }], [conversation]));
|
|
360
404
|
});
|
|
@@ -406,17 +450,14 @@ export function createConversationStore(deps) {
|
|
|
406
450
|
if (!replicated.has(conversation))
|
|
407
451
|
return;
|
|
408
452
|
const newest = arriving.reduce((top, message) => (top === null || message.position > top ? message.position : top), from ?? null);
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
await local.keepMessages({ conversation, messages: arriving, read: newest, sealed });
|
|
453
|
+
const sealing = await sealed(local, conversation, new Set(arriving.map((message) => message.turn)));
|
|
454
|
+
await local.keepMessages({ conversation, messages: arriving, read: newest });
|
|
412
455
|
messages.set(conversation, merged(messages.get(conversation) ?? [], arriving));
|
|
413
456
|
reads.set(conversation, newest);
|
|
414
|
-
if (sealed)
|
|
415
|
-
drafts.delete(conversation);
|
|
416
457
|
sealTurns(conversation, new Set(arriving.map((message) => message.turn)));
|
|
417
458
|
if ((gaps.get(conversation) ?? 0) === generation)
|
|
418
459
|
behind.delete(conversation);
|
|
419
|
-
if (arriving.length > 0 ||
|
|
460
|
+
if (arriving.length > 0 || sealing) {
|
|
420
461
|
deps.publish(conversationChangeSet(arriving.map((message) => ({ conversation, identity: message.identity })), [conversation]));
|
|
421
462
|
}
|
|
422
463
|
});
|
|
@@ -463,22 +504,89 @@ export function createConversationStore(deps) {
|
|
|
463
504
|
if (sealTurns(conversation, new Set([arriving.turn])))
|
|
464
505
|
emit(conversation);
|
|
465
506
|
}
|
|
507
|
+
async function kept(local, conversation, following) {
|
|
508
|
+
if (following === null || (unwritten(following) && following.submitted === undefined)) {
|
|
509
|
+
await local.dropChatDraft(conversation);
|
|
510
|
+
drafts.delete(conversation);
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
await local.keepChatDraft(following);
|
|
514
|
+
drafts.set(conversation, following);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async function sealed(local, conversation, turns) {
|
|
518
|
+
const held = drafts.get(conversation);
|
|
519
|
+
const submitted = held?.submitted ?? [];
|
|
520
|
+
const left = submitted.filter((one) => one.turn === null || !turns.has(one.turn));
|
|
521
|
+
if (held === undefined || left.length === submitted.length)
|
|
522
|
+
return false;
|
|
523
|
+
await kept(local, conversation, withSubmitted(held, left));
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
466
526
|
function withDraft(conversation, next) {
|
|
467
527
|
return deps.durably(async (local) => {
|
|
468
528
|
const following = next(drafts.get(conversation));
|
|
469
529
|
if (following === undefined)
|
|
470
530
|
return;
|
|
471
|
-
|
|
472
|
-
await local.dropChatDraft(conversation);
|
|
473
|
-
drafts.delete(conversation);
|
|
474
|
-
}
|
|
475
|
-
else {
|
|
476
|
-
await local.keepChatDraft(following);
|
|
477
|
-
drafts.set(conversation, following);
|
|
478
|
-
}
|
|
531
|
+
await kept(local, conversation, following);
|
|
479
532
|
deps.publish(conversationChangeSet([], [conversation]));
|
|
480
533
|
});
|
|
481
534
|
}
|
|
535
|
+
async function submitted(conversation, operation, draft) {
|
|
536
|
+
let submission;
|
|
537
|
+
await withDraft(conversation, (current) => {
|
|
538
|
+
submission = current?.submitted?.find((one) => one.operation === operation);
|
|
539
|
+
if (submission !== undefined)
|
|
540
|
+
return undefined;
|
|
541
|
+
const said = draft ?? current;
|
|
542
|
+
submission = {
|
|
543
|
+
operation,
|
|
544
|
+
text: said?.text ?? '',
|
|
545
|
+
files: [...(said?.files ?? [])],
|
|
546
|
+
turn: null,
|
|
547
|
+
};
|
|
548
|
+
return {
|
|
549
|
+
conversation,
|
|
550
|
+
...(draft === undefined || current === undefined
|
|
551
|
+
? { text: '', files: [], revision: chatDraftRevision() }
|
|
552
|
+
: { text: current.text, files: current.files, revision: current.revision }),
|
|
553
|
+
submitted: [...(current?.submitted ?? []), submission],
|
|
554
|
+
};
|
|
555
|
+
});
|
|
556
|
+
return submission;
|
|
557
|
+
}
|
|
558
|
+
async function dispatched(conversation, submission) {
|
|
559
|
+
sending.add(submission.operation);
|
|
560
|
+
try {
|
|
561
|
+
const files = await Promise.all(submission.files.map(async (file) => ({ ...(await declaredFile(file)), blob: file.blob })));
|
|
562
|
+
const result = await invoke('conversation.send', conversation, {
|
|
563
|
+
text: submission.text,
|
|
564
|
+
files,
|
|
565
|
+
operation_id: submission.operation,
|
|
566
|
+
});
|
|
567
|
+
if (result.kind === 'revoked-authorization')
|
|
568
|
+
return result;
|
|
569
|
+
if (result.kind !== 'action' && result.retryable)
|
|
570
|
+
return result;
|
|
571
|
+
const turn = turnOf(result);
|
|
572
|
+
await withDraft(conversation, (current) => {
|
|
573
|
+
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
574
|
+
if (current === undefined || held === undefined || held.turn !== null)
|
|
575
|
+
return undefined;
|
|
576
|
+
const others = current.submitted.filter((one) => one !== held);
|
|
577
|
+
if (result.kind !== 'action')
|
|
578
|
+
return returned(current, held, others);
|
|
579
|
+
const arrived = (messages.get(conversation) ?? []).some((message) => message.turn === turn);
|
|
580
|
+
return withSubmitted(current, turn === null || arrived
|
|
581
|
+
? others
|
|
582
|
+
: current.submitted.map((one) => (one === held ? { ...held, turn } : one)));
|
|
583
|
+
});
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
finally {
|
|
587
|
+
sending.delete(submission.operation);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
482
590
|
function invoke(name, conversation, extra = {}) {
|
|
483
591
|
return deps.call(name, { conversation, ...extra });
|
|
484
592
|
}
|
|
@@ -494,41 +602,16 @@ export function createConversationStore(deps) {
|
|
|
494
602
|
create(input) {
|
|
495
603
|
return deps.call('conversation.create', input);
|
|
496
604
|
},
|
|
497
|
-
async send(conversation) {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if (pending !== undefined) {
|
|
501
|
-
sending.set(conversation, pending);
|
|
502
|
-
deps.publish(conversationChangeSet([], [conversation]));
|
|
605
|
+
async send(conversation, operation = changeBatchIdentity(), draft) {
|
|
606
|
+
if (deps.online()) {
|
|
607
|
+
return dispatched(conversation, await submitted(conversation, operation, draft));
|
|
503
608
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
})));
|
|
509
|
-
const result = await invoke('conversation.send', conversation, {
|
|
510
|
-
text: draft?.text ?? '',
|
|
511
|
-
files,
|
|
512
|
-
});
|
|
513
|
-
const turn = turnOf(result);
|
|
514
|
-
if (turn === null || draft === undefined)
|
|
515
|
-
return result;
|
|
516
|
-
await withDraft(conversation, (current) => {
|
|
517
|
-
if (current !== draft)
|
|
518
|
-
return undefined;
|
|
519
|
-
const sealed = (messages.get(conversation) ?? []).some((message) => message.turn === turn);
|
|
520
|
-
return sealed ? null : { ...draft, turn };
|
|
521
|
-
});
|
|
522
|
-
return result;
|
|
523
|
-
}
|
|
524
|
-
finally {
|
|
525
|
-
if (pending !== undefined && sending.get(conversation) === pending) {
|
|
526
|
-
sending.delete(conversation);
|
|
527
|
-
if (drafts.get(conversation) === draft) {
|
|
528
|
-
deps.publish(conversationChangeSet([], [conversation]));
|
|
529
|
-
}
|
|
530
|
-
}
|
|
609
|
+
if (draft !== undefined) {
|
|
610
|
+
await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
|
|
611
|
+
? undefined
|
|
612
|
+
: returned(current ?? { conversation, text: '', files: [], revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
|
|
531
613
|
}
|
|
614
|
+
return OFFLINE;
|
|
532
615
|
},
|
|
533
616
|
answer(conversation, answer) {
|
|
534
617
|
return invoke('conversation.answer', conversation, { answer });
|
|
@@ -543,7 +626,12 @@ export function createConversationStore(deps) {
|
|
|
543
626
|
const result = await invoke('conversation.cancel', conversation, { turn });
|
|
544
627
|
if (result.kind !== 'action')
|
|
545
628
|
return result;
|
|
546
|
-
await withDraft(conversation, (current) =>
|
|
629
|
+
await withDraft(conversation, (current) => {
|
|
630
|
+
const held = current?.submitted?.find((one) => one.turn === turn);
|
|
631
|
+
if (current === undefined || held === undefined)
|
|
632
|
+
return undefined;
|
|
633
|
+
return returned(current, held, current.submitted.filter((one) => one !== held));
|
|
634
|
+
});
|
|
547
635
|
return result;
|
|
548
636
|
},
|
|
549
637
|
delete(conversation) {
|
|
@@ -551,16 +639,25 @@ export function createConversationStore(deps) {
|
|
|
551
639
|
},
|
|
552
640
|
};
|
|
553
641
|
const chatDraft = {
|
|
554
|
-
write(conversation, draft) {
|
|
555
|
-
return withDraft(conversation, () => ({
|
|
642
|
+
write(conversation, draft, revision = chatDraftRevision()) {
|
|
643
|
+
return withDraft(conversation, (current) => ({
|
|
556
644
|
conversation,
|
|
557
645
|
text: draft.text,
|
|
558
646
|
files: [...draft.files],
|
|
559
|
-
|
|
647
|
+
revision,
|
|
648
|
+
...(current?.submitted === undefined ? {} : { submitted: current.submitted }),
|
|
560
649
|
}));
|
|
561
650
|
},
|
|
562
651
|
discard(conversation) {
|
|
563
|
-
return withDraft(conversation, (current) =>
|
|
652
|
+
return withDraft(conversation, (current) => current === undefined
|
|
653
|
+
? undefined
|
|
654
|
+
: {
|
|
655
|
+
conversation,
|
|
656
|
+
text: '',
|
|
657
|
+
files: [],
|
|
658
|
+
revision: chatDraftRevision(),
|
|
659
|
+
...pending(current),
|
|
660
|
+
});
|
|
564
661
|
},
|
|
565
662
|
};
|
|
566
663
|
return {
|
|
@@ -606,6 +703,23 @@ export function createConversationStore(deps) {
|
|
|
606
703
|
if (behind.size > 0)
|
|
607
704
|
progress.complete = false;
|
|
608
705
|
},
|
|
706
|
+
async resend(progress) {
|
|
707
|
+
for (const [conversation, held] of [...drafts]) {
|
|
708
|
+
for (const submission of held.submitted ?? []) {
|
|
709
|
+
if (submission.turn !== null || sending.has(submission.operation))
|
|
710
|
+
continue;
|
|
711
|
+
if (deps.closed())
|
|
712
|
+
return;
|
|
713
|
+
const result = await dispatched(conversation, submission);
|
|
714
|
+
if (result.kind === 'revoked-authorization')
|
|
715
|
+
return;
|
|
716
|
+
if (result.kind === 'transport-uncertainty') {
|
|
717
|
+
progress.reachable = false;
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
},
|
|
609
723
|
current() {
|
|
610
724
|
return behind.size === 0;
|
|
611
725
|
},
|
|
@@ -651,6 +765,16 @@ export function createConversationStore(deps) {
|
|
|
651
765
|
listWatchers.delete(deliver);
|
|
652
766
|
};
|
|
653
767
|
},
|
|
768
|
+
watchAgents(deliver) {
|
|
769
|
+
agentWatchers.add(deliver);
|
|
770
|
+
void agentsReady().then(() => {
|
|
771
|
+
if (!deps.closed() && agentWatchers.has(deliver))
|
|
772
|
+
deliver(agents());
|
|
773
|
+
});
|
|
774
|
+
return () => {
|
|
775
|
+
agentWatchers.delete(deliver);
|
|
776
|
+
};
|
|
777
|
+
},
|
|
654
778
|
changed(set) {
|
|
655
779
|
for (const conversation of set.conversations)
|
|
656
780
|
emit(conversation);
|
|
@@ -698,6 +822,7 @@ export function createConversationStore(deps) {
|
|
|
698
822
|
views.clear();
|
|
699
823
|
lives.clear();
|
|
700
824
|
listWatchers.clear();
|
|
825
|
+
agentWatchers.clear();
|
|
701
826
|
},
|
|
702
827
|
};
|
|
703
828
|
}
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type QueryResult } from './query.js';
|
|
2
|
+
export { QueryError } from './query.js';
|
|
3
|
+
export type EntryRoom = {
|
|
4
|
+
locator: string;
|
|
5
|
+
schema: string | null;
|
|
6
|
+
documents: Readonly<Record<string, string>>;
|
|
7
|
+
};
|
|
8
|
+
export type EntryArguments = Readonly<Record<string, string>>;
|
|
9
|
+
export type EntryParameterKind = 'string' | 'integer' | 'number' | 'boolean';
|
|
10
|
+
export declare function boundQuery(template: unknown, args: EntryArguments): unknown;
|
|
11
|
+
export declare function entryParameters(template: unknown): readonly string[];
|
|
12
|
+
export declare function entryRefusal(template: unknown): string | null;
|
|
13
|
+
export type EntryScope = {
|
|
14
|
+
results(queries: Readonly<Record<string, unknown>>): Promise<Record<string, QueryResult>>;
|
|
15
|
+
};
|
|
16
|
+
export declare function entryScope(rooms: readonly EntryRoom[]): EntryScope;
|
|
17
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AA0D7E,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAE3E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAMpE;AAkCD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQ7D;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CAC3F,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,UAAU,CAqDlE"}
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { attachedModel } from './attached-model.js';
|
|
2
|
+
import { collectionOf, passingDocument } from './collection.js';
|
|
3
|
+
import { NO_MODEL } from './model.js';
|
|
4
|
+
import { invalid, planOf, plain, QueryError, } from './query.js';
|
|
5
|
+
import { createReadSide } from './read-side.js';
|
|
6
|
+
import { rowsOf } from './rows.js';
|
|
7
|
+
export { QueryError } from './query.js';
|
|
8
|
+
const PARAMETER = '$param';
|
|
9
|
+
const KIND = 'as';
|
|
10
|
+
const INTEGER = /^-?(?:0|[1-9][0-9]*)$/u;
|
|
11
|
+
const NUMBER = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/u;
|
|
12
|
+
function parameterOf(value) {
|
|
13
|
+
if (!plain(value) || !Object.hasOwn(value, PARAMETER))
|
|
14
|
+
return null;
|
|
15
|
+
const { [PARAMETER]: name, [KIND]: kind = 'string', ...rest } = value;
|
|
16
|
+
if (typeof name !== 'string' || Object.keys(rest).length > 0)
|
|
17
|
+
return null;
|
|
18
|
+
if (kind !== 'string' && kind !== 'integer' && kind !== 'number' && kind !== 'boolean') {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return { name, kind };
|
|
22
|
+
}
|
|
23
|
+
function converted(text, kind, at) {
|
|
24
|
+
if (kind === 'string')
|
|
25
|
+
return text;
|
|
26
|
+
if (kind === 'boolean') {
|
|
27
|
+
if (text === 'true' || text === 'false')
|
|
28
|
+
return text === 'true';
|
|
29
|
+
return invalid(at, 'expects true or false');
|
|
30
|
+
}
|
|
31
|
+
if (!(kind === 'integer' ? INTEGER : NUMBER).test(text))
|
|
32
|
+
invalid(at, `expects ${kind === 'integer' ? 'an integer' : 'a number'}`);
|
|
33
|
+
const number = Number(text);
|
|
34
|
+
if (!Number.isFinite(number) || (kind === 'integer' && !Number.isSafeInteger(number))) {
|
|
35
|
+
invalid(at, 'is out of range');
|
|
36
|
+
}
|
|
37
|
+
return number;
|
|
38
|
+
}
|
|
39
|
+
function bound(template, args, at) {
|
|
40
|
+
const parameter = parameterOf(template);
|
|
41
|
+
if (parameter !== null) {
|
|
42
|
+
const text = args[parameter.name];
|
|
43
|
+
if (text === undefined || !Object.hasOwn(args, parameter.name)) {
|
|
44
|
+
invalid(at, `names the parameter ${parameter.name}, which the route lacks`);
|
|
45
|
+
}
|
|
46
|
+
return converted(text, parameter.kind, at);
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(template)) {
|
|
49
|
+
return template.map((item, index) => bound(item, args, `${at}[${index}]`));
|
|
50
|
+
}
|
|
51
|
+
if (plain(template)) {
|
|
52
|
+
return Object.fromEntries(Object.entries(template).map(([name, value]) => [
|
|
53
|
+
name,
|
|
54
|
+
bound(value, args, at === '' ? name : `${at}.${name}`),
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
57
|
+
return template;
|
|
58
|
+
}
|
|
59
|
+
export function boundQuery(template, args) {
|
|
60
|
+
return bound(template, args, '');
|
|
61
|
+
}
|
|
62
|
+
export function entryParameters(template) {
|
|
63
|
+
const parameter = parameterOf(template);
|
|
64
|
+
if (parameter !== null)
|
|
65
|
+
return [parameter.name];
|
|
66
|
+
if (Array.isArray(template))
|
|
67
|
+
return [...new Set(template.flatMap(entryParameters))];
|
|
68
|
+
if (plain(template))
|
|
69
|
+
return [...new Set(Object.values(template).flatMap(entryParameters))];
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const SAMPLED = {
|
|
73
|
+
direction: 'asc',
|
|
74
|
+
nulls: 'last',
|
|
75
|
+
stringSort: 'lexical',
|
|
76
|
+
locale: 'en',
|
|
77
|
+
limit: 0,
|
|
78
|
+
pathPrefix: 'entry',
|
|
79
|
+
field: '/entry',
|
|
80
|
+
fields: '/entry',
|
|
81
|
+
types: 'any',
|
|
82
|
+
$in: 'entry',
|
|
83
|
+
$nin: 'entry',
|
|
84
|
+
$all: 'entry',
|
|
85
|
+
$size: 0,
|
|
86
|
+
$exists: true,
|
|
87
|
+
$gt: 0,
|
|
88
|
+
$gte: 0,
|
|
89
|
+
$lt: 0,
|
|
90
|
+
$lte: 0,
|
|
91
|
+
};
|
|
92
|
+
function sampled(template, key) {
|
|
93
|
+
if (parameterOf(template) !== null)
|
|
94
|
+
return Object.hasOwn(SAMPLED, key) ? SAMPLED[key] : null;
|
|
95
|
+
if (Array.isArray(template))
|
|
96
|
+
return template.map((item) => sampled(item, key));
|
|
97
|
+
if (plain(template)) {
|
|
98
|
+
return Object.fromEntries(Object.entries(template).map(([name, value]) => [name, sampled(value, name)]));
|
|
99
|
+
}
|
|
100
|
+
return template;
|
|
101
|
+
}
|
|
102
|
+
export function entryRefusal(template) {
|
|
103
|
+
try {
|
|
104
|
+
planOf(sampled(template, ''), { listed: false, rooms: [] });
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof QueryError)
|
|
109
|
+
return error.message;
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export function entryScope(rooms) {
|
|
114
|
+
const readSide = createReadSide();
|
|
115
|
+
const held = [];
|
|
116
|
+
const documents = rooms.flatMap((room) => {
|
|
117
|
+
const model = attachedModel({
|
|
118
|
+
kind: 'model',
|
|
119
|
+
snapshot: { identity: room.locator, version: '', schema: room.schema, revision: null },
|
|
120
|
+
}, NO_MODEL).state;
|
|
121
|
+
held.push({
|
|
122
|
+
locator: room.locator,
|
|
123
|
+
available: model.status !== 'unavailable',
|
|
124
|
+
types: model.status === 'unavailable' ? [] : Object.values(model.types),
|
|
125
|
+
});
|
|
126
|
+
const composition = { model, selection: null };
|
|
127
|
+
const collection = collectionOf(room.documents, composition);
|
|
128
|
+
return Object.keys(room.documents)
|
|
129
|
+
.sort()
|
|
130
|
+
.map((path) => ({
|
|
131
|
+
locator: room.locator,
|
|
132
|
+
path,
|
|
133
|
+
before: [],
|
|
134
|
+
after: rowsOf(room.locator, path, passingDocument(collection, path) ?? null, composition, null, null),
|
|
135
|
+
}));
|
|
136
|
+
});
|
|
137
|
+
readSide.apply({
|
|
138
|
+
documents,
|
|
139
|
+
drafts: [],
|
|
140
|
+
rooms: [],
|
|
141
|
+
queues: [],
|
|
142
|
+
presentations: [],
|
|
143
|
+
messages: [],
|
|
144
|
+
conversations: [],
|
|
145
|
+
});
|
|
146
|
+
const planned = { listed: true, rooms: held };
|
|
147
|
+
return {
|
|
148
|
+
async results(queries) {
|
|
149
|
+
const results = {};
|
|
150
|
+
for (const [name, query] of Object.entries(queries)) {
|
|
151
|
+
results[name] = await readSide.query(planOf(query, planned));
|
|
152
|
+
}
|
|
153
|
+
return results;
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|