@agentshouse/mdruntime 0.1.0-c5b50992a4193 → 0.1.0-c698c0ebd65bd

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.
Files changed (169) hide show
  1. package/AGENTS.md +151 -96
  2. package/README.md +13 -3
  3. package/dist/adapter.d.ts +47 -14
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attempt.d.ts +16 -0
  6. package/dist/attempt.d.ts.map +1 -0
  7. package/dist/attempt.js +70 -0
  8. package/dist/binary.d.ts +23 -0
  9. package/dist/binary.d.ts.map +1 -0
  10. package/dist/binary.js +8 -0
  11. package/dist/bootstrap.d.ts +17 -5
  12. package/dist/bootstrap.d.ts.map +1 -1
  13. package/dist/bootstrap.js +92 -38
  14. package/dist/change-set.d.ts.map +1 -1
  15. package/dist/change-set.js +19 -12
  16. package/dist/change.d.ts +15 -0
  17. package/dist/change.d.ts.map +1 -1
  18. package/dist/change.js +26 -1
  19. package/dist/chat/acts.d.ts +33 -0
  20. package/dist/chat/acts.d.ts.map +1 -0
  21. package/dist/chat/acts.js +36 -0
  22. package/dist/chat/context.d.ts +3 -0
  23. package/dist/chat/context.d.ts.map +1 -0
  24. package/dist/chat/context.js +10 -0
  25. package/dist/chat/input.d.ts +9 -0
  26. package/dist/chat/input.d.ts.map +1 -0
  27. package/dist/chat/input.js +99 -0
  28. package/dist/chat/kit.d.ts +60 -0
  29. package/dist/chat/kit.d.ts.map +1 -0
  30. package/dist/chat/kit.js +123 -0
  31. package/dist/chat/lasting.d.ts +6 -0
  32. package/dist/chat/lasting.d.ts.map +1 -0
  33. package/dist/chat/lasting.js +19 -0
  34. package/dist/chat/list.d.ts +26 -0
  35. package/dist/chat/list.d.ts.map +1 -0
  36. package/dist/chat/list.js +62 -0
  37. package/dist/chat/markdown.d.ts +20 -0
  38. package/dist/chat/markdown.d.ts.map +1 -0
  39. package/dist/chat/markdown.js +188 -0
  40. package/dist/chat/message.d.ts +6 -0
  41. package/dist/chat/message.d.ts.map +1 -0
  42. package/dist/chat/message.js +192 -0
  43. package/dist/chat/messages.d.ts +21 -0
  44. package/dist/chat/messages.d.ts.map +1 -0
  45. package/dist/chat/messages.js +151 -0
  46. package/dist/chat/name.d.ts +6 -0
  47. package/dist/chat/name.d.ts.map +1 -0
  48. package/dist/chat/name.js +37 -0
  49. package/dist/chat/opened.d.ts +11 -0
  50. package/dist/chat/opened.d.ts.map +1 -0
  51. package/dist/chat/opened.js +17 -0
  52. package/dist/chat/overlay.d.ts +31 -0
  53. package/dist/chat/overlay.d.ts.map +1 -0
  54. package/dist/chat/overlay.js +97 -0
  55. package/dist/chat/parts.d.ts +57 -0
  56. package/dist/chat/parts.d.ts.map +1 -0
  57. package/dist/chat/parts.js +119 -0
  58. package/dist/chat/process.d.ts +20 -0
  59. package/dist/chat/process.d.ts.map +1 -0
  60. package/dist/chat/process.js +32 -0
  61. package/dist/chat/provider.d.ts +63 -0
  62. package/dist/chat/provider.d.ts.map +1 -0
  63. package/dist/chat/provider.js +620 -0
  64. package/dist/chat/question.d.ts +9 -0
  65. package/dist/chat/question.d.ts.map +1 -0
  66. package/dist/chat/question.js +80 -0
  67. package/dist/chat/questions.d.ts +31 -0
  68. package/dist/chat/questions.d.ts.map +1 -0
  69. package/dist/chat/questions.js +111 -0
  70. package/dist/chat/read.d.ts +5 -0
  71. package/dist/chat/read.d.ts.map +1 -0
  72. package/dist/chat/read.js +13 -0
  73. package/dist/chat/ready.d.ts +33 -0
  74. package/dist/chat/ready.d.ts.map +1 -0
  75. package/dist/chat/ready.js +91 -0
  76. package/dist/chat/style.d.ts +4 -0
  77. package/dist/chat/style.d.ts.map +1 -0
  78. package/dist/chat/style.js +302 -0
  79. package/dist/chat.d.ts +14 -0
  80. package/dist/chat.d.ts.map +1 -0
  81. package/dist/chat.js +8 -0
  82. package/dist/client.d.ts +15 -6
  83. package/dist/client.d.ts.map +1 -1
  84. package/dist/client.js +66 -16
  85. package/dist/collection.d.ts +6 -11
  86. package/dist/collection.d.ts.map +1 -1
  87. package/dist/collection.js +56 -19
  88. package/dist/connection.d.ts +22 -9
  89. package/dist/connection.d.ts.map +1 -1
  90. package/dist/connection.js +566 -175
  91. package/dist/conversation.d.ts +15 -5
  92. package/dist/conversation.d.ts.map +1 -1
  93. package/dist/conversation.js +189 -64
  94. package/dist/entry.d.ts +17 -0
  95. package/dist/entry.d.ts.map +1 -0
  96. package/dist/entry.js +156 -0
  97. package/dist/expectation.d.ts +21 -0
  98. package/dist/expectation.d.ts.map +1 -0
  99. package/dist/expectation.js +70 -0
  100. package/dist/failure.d.ts +13 -0
  101. package/dist/failure.d.ts.map +1 -0
  102. package/dist/failure.js +19 -0
  103. package/dist/fence.d.ts +6 -0
  104. package/dist/fence.d.ts.map +1 -0
  105. package/dist/fence.js +10 -0
  106. package/dist/host.d.ts +3 -1
  107. package/dist/host.d.ts.map +1 -1
  108. package/dist/host.js +16 -12
  109. package/dist/identity.d.ts +3 -0
  110. package/dist/identity.d.ts.map +1 -1
  111. package/dist/identity.js +13 -1
  112. package/dist/index.d.ts +9 -4
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +3 -0
  115. package/dist/memory.d.ts +5 -3
  116. package/dist/memory.d.ts.map +1 -1
  117. package/dist/memory.js +62 -20
  118. package/dist/model.d.ts +3 -2
  119. package/dist/model.d.ts.map +1 -1
  120. package/dist/open.d.ts +2 -0
  121. package/dist/open.d.ts.map +1 -0
  122. package/dist/open.js +1 -0
  123. package/dist/outcome.d.ts +32 -3
  124. package/dist/outcome.d.ts.map +1 -1
  125. package/dist/outcome.js +42 -1
  126. package/dist/overlay.d.ts +14 -3
  127. package/dist/overlay.d.ts.map +1 -1
  128. package/dist/overlay.js +75 -37
  129. package/dist/query.d.ts +4 -0
  130. package/dist/query.d.ts.map +1 -1
  131. package/dist/query.js +3 -0
  132. package/dist/reach.d.ts +2 -0
  133. package/dist/reach.d.ts.map +1 -1
  134. package/dist/reach.js +44 -20
  135. package/dist/react.d.ts +25 -16
  136. package/dist/react.d.ts.map +1 -1
  137. package/dist/react.js +8 -6
  138. package/dist/read-side.d.ts.map +1 -1
  139. package/dist/read-side.js +9 -2
  140. package/dist/refresh.d.ts +10 -0
  141. package/dist/refresh.d.ts.map +1 -1
  142. package/dist/refresh.js +42 -38
  143. package/dist/replica.d.ts +7 -4
  144. package/dist/replica.d.ts.map +1 -1
  145. package/dist/replica.js +74 -54
  146. package/dist/room-draft.d.ts +26 -9
  147. package/dist/room-draft.d.ts.map +1 -1
  148. package/dist/room-draft.js +132 -23
  149. package/dist/rows.d.ts +5 -1
  150. package/dist/rows.d.ts.map +1 -1
  151. package/dist/rows.js +10 -2
  152. package/dist/save.d.ts +26 -1
  153. package/dist/save.d.ts.map +1 -1
  154. package/dist/save.js +345 -37
  155. package/dist/search.d.ts +3 -2
  156. package/dist/search.d.ts.map +1 -1
  157. package/dist/status.d.ts +2 -2
  158. package/dist/status.d.ts.map +1 -1
  159. package/dist/status.js +0 -8
  160. package/dist/store.d.ts +48 -14
  161. package/dist/store.d.ts.map +1 -1
  162. package/dist/store.js +366 -170
  163. package/dist/wire.d.ts +7 -3
  164. package/dist/wire.d.ts.map +1 -1
  165. package/dist/wire.js +15 -2
  166. package/package.json +26 -14
  167. package/dist/attachment.d.ts +0 -3
  168. package/dist/attachment.d.ts.map +0 -1
  169. package/dist/attachment.js +0 -8
@@ -1,12 +1,13 @@
1
1
  import type { ConversationAction, ConversationAgents, ConversationEvent, ConversationMessage, ConversationStream, ProcessCommand, SessionOption, TurnContext } from './adapter.js';
2
2
  import { type ChangeSet } from './change-set.js';
3
3
  import { type ChatDraftFile } from './file.js';
4
- import type { CallResult } from './outcome.js';
4
+ import type { Open } from './open.js';
5
+ import { type CallResult, type Offline } from './outcome.js';
5
6
  import type { DocumentResult } from './query.js';
6
7
  import type { SearchedMessage } from './search.js';
7
8
  import type { CycleProgress } from './status.js';
8
9
  import type { ChatDraftRecord, HeldConversation, RuntimeStore } from './store.js';
9
- export type ConversationState = 'working' | 'asking' | 'idle';
10
+ export type ConversationState = Open<'working' | 'asking' | 'idle'>;
10
11
  export type ConversationEntry = {
11
12
  conversation: string;
12
13
  agent: {
@@ -20,6 +21,10 @@ export type ConversationEntry = {
20
21
  state: ConversationState;
21
22
  started: string | null;
22
23
  };
24
+ export type ConversationAgent = {
25
+ identity: string;
26
+ name: string;
27
+ };
23
28
  export type RunningTurn = {
24
29
  turn: string;
25
30
  started: string | null;
@@ -43,13 +48,15 @@ export type ConversationView = {
43
48
  } | null;
44
49
  commands: readonly ProcessCommand[];
45
50
  options: readonly SessionOption[];
46
- chatDraft: ChatDraft | null;
51
+ chatDraft: (ChatDraft & {
52
+ readonly revision: string;
53
+ }) | null;
47
54
  };
48
55
  export type ConversationSurface = {
49
56
  list(): Promise<readonly ConversationEntry[]>;
50
57
  read(conversation: string, options?: ConversationOptions): Promise<ConversationView>;
51
58
  create(input: unknown): Promise<CallResult>;
52
- send(conversation: string): Promise<CallResult>;
59
+ send(conversation: string, operation?: string, draft?: ChatDraft): Promise<CallResult | Offline>;
53
60
  answer(conversation: string, answer: unknown): Promise<CallResult>;
54
61
  interrupt(conversation: string): Promise<CallResult>;
55
62
  kill(conversation: string): Promise<CallResult>;
@@ -57,7 +64,7 @@ export type ConversationSurface = {
57
64
  delete(conversation: string): Promise<CallResult>;
58
65
  };
59
66
  export type ChatDraftSurface = {
60
- write(conversation: string, draft: ChatDraft): Promise<void>;
67
+ write(conversation: string, draft: ChatDraft, revision?: string): Promise<void>;
61
68
  discard(conversation: string): Promise<void>;
62
69
  };
63
70
  export type ConversationDependencies = {
@@ -67,6 +74,7 @@ export type ConversationDependencies = {
67
74
  durably<T>(work: (local: RuntimeStore) => Promise<T>): Promise<T>;
68
75
  stream(): ConversationStream | undefined;
69
76
  publish(set: ChangeSet): void;
77
+ online(): boolean;
70
78
  closed(): boolean;
71
79
  };
72
80
  export type ConversationStore = {
@@ -75,10 +83,12 @@ export type ConversationStore = {
75
83
  hydrate(held: readonly HeldConversation[], drafts: readonly ChatDraftRecord[]): void;
76
84
  reconcile(): Promise<void>;
77
85
  catchUp(progress: CycleProgress): Promise<void>;
86
+ resend(progress: CycleProgress): Promise<void>;
78
87
  current(): boolean;
79
88
  reconnected(): void;
80
89
  watch(conversation: string, options: ConversationOptions, deliver: (view: ConversationView) => void): () => void;
81
90
  watchList(deliver: (entries: readonly ConversationEntry[]) => void): () => void;
91
+ watchAgents(deliver: (agents: readonly ConversationAgent[]) => void): () => void;
82
92
  changed(set: ChangeSet): void;
83
93
  receive(event: ConversationEvent): boolean;
84
94
  messages(): readonly SearchedMessage[];
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/conversation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../src/conversation.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
1
  import { conversationChangeSet } from './change-set.js';
2
+ import { runtimeError } from './failure.js';
2
3
  import { declaredFile } from './file.js';
4
+ import { changeBatchIdentity, chatDraftRevision } from './identity.js';
5
+ import { OFFLINE } from './outcome.js';
3
6
  const QUIET = {
4
7
  turn: null,
5
8
  questions: [],
@@ -152,15 +155,33 @@ function limitOf(options) {
152
155
  if (limit === undefined)
153
156
  return undefined;
154
157
  if (!Number.isInteger(limit) || limit < 0) {
155
- throw new Error(`conversation limit must be a non-negative integer, got ${String(limit)}`);
158
+ throw runtimeError('invalid-limit', `conversation limit must be a non-negative integer, got ${String(limit)}`);
156
159
  }
157
160
  return limit;
158
161
  }
162
+ function unwritten(draft) {
163
+ return draft.text === '' && draft.files.length === 0;
164
+ }
165
+ function pending(draft) {
166
+ return draft.submitted === undefined ? {} : { submitted: draft.submitted };
167
+ }
168
+ function withSubmitted(draft, submitted) {
169
+ const { submitted: _held, ...unsent } = draft;
170
+ return submitted.length === 0 ? unsent : { ...unsent, submitted };
171
+ }
172
+ function returned(draft, submission, others) {
173
+ return withSubmitted({
174
+ conversation: draft.conversation,
175
+ text: [submission.text, draft.text].filter((one) => one !== '').join('\n'),
176
+ files: [...submission.files, ...draft.files],
177
+ revision: chatDraftRevision(),
178
+ }, others);
179
+ }
159
180
  export function createConversationStore(deps) {
160
181
  const messages = new Map();
161
182
  const reads = new Map();
162
183
  const drafts = new Map();
163
- const sending = new Map();
184
+ const sending = new Set();
164
185
  const behind = new Set();
165
186
  const gaps = new Map();
166
187
  const lives = new Map();
@@ -168,7 +189,9 @@ export function createConversationStore(deps) {
168
189
  const listing = new Map();
169
190
  const listWatchers = new Set();
170
191
  let listKnown = false;
192
+ const agentWatchers = new Set();
171
193
  let agentNames = new Map();
194
+ let retiredAgents = new Set();
172
195
  let agentsRead = null;
173
196
  let replicated = new Set();
174
197
  let handedReplicated;
@@ -196,9 +219,9 @@ export function createConversationStore(deps) {
196
219
  process: facts.process === null ? null : { ...facts.process },
197
220
  commands: structuredClone(facts.commands),
198
221
  options: structuredClone(facts.options),
199
- chatDraft: draft === undefined || draft.turn !== null || sending.get(conversation)?.draft === draft
222
+ chatDraft: draft === undefined || unwritten(draft)
200
223
  ? null
201
- : { text: draft.text, files: [...draft.files] },
224
+ : { text: draft.text, files: [...draft.files], revision: draft.revision },
202
225
  };
203
226
  }
204
227
  function emit(conversation, messagesChanged = true) {
@@ -243,6 +266,21 @@ export function createConversationStore(deps) {
243
266
  for (const watcher of listWatchers)
244
267
  watcher(value);
245
268
  }
269
+ function agents() {
270
+ return [...agentNames]
271
+ .filter(([identity]) => !retiredAgents.has(identity))
272
+ .map(([identity, name]) => ({ identity, name }))
273
+ .sort((left, right) => left.name === right.name
274
+ ? left.identity.localeCompare(right.identity)
275
+ : left.name.localeCompare(right.name));
276
+ }
277
+ function emitAgents() {
278
+ if (deps.closed() || agentWatchers.size === 0)
279
+ return;
280
+ const value = agents();
281
+ for (const watcher of agentWatchers)
282
+ watcher(value);
283
+ }
246
284
  function setLive(conversation, next) {
247
285
  const before = stateOf(conversation);
248
286
  const began = lives.get(conversation)?.turn?.started;
@@ -261,18 +299,27 @@ export function createConversationStore(deps) {
261
299
  return;
262
300
  const { documents } = await deps.documents(declaration.locator);
263
301
  const names = new Map();
302
+ const retired = new Set();
264
303
  for (const document of documents) {
265
304
  if (document.type !== declaration.type)
266
305
  continue;
267
306
  const identity = document.fields?.[declaration.identity];
268
307
  const name = document.fields?.[declaration.name];
269
- if (typeof identity === 'string' && typeof name === 'string')
270
- names.set(identity, name);
308
+ if (typeof identity !== 'string' || typeof name !== 'string')
309
+ continue;
310
+ names.set(identity, name);
311
+ const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
312
+ if (ended !== undefined && ended !== null)
313
+ retired.add(identity);
271
314
  }
272
- if (JSON.stringify([...names]) === JSON.stringify([...agentNames]))
315
+ const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
316
+ if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
273
317
  return;
274
318
  agentNames = names;
275
- emitList();
319
+ retiredAgents = retired;
320
+ if (named)
321
+ emitList();
322
+ emitAgents();
276
323
  }
277
324
  function agentsReady() {
278
325
  agentsRead ??= readAgents().catch(() => {
@@ -342,18 +389,15 @@ export function createConversationStore(deps) {
342
389
  const advances = read !== undefined &&
343
390
  !behind.has(conversation) &&
344
391
  (read === null || message.position > read);
345
- const sealed = drafts.get(conversation)?.turn === message.turn;
392
+ await sealed(local, conversation, new Set([message.turn]));
346
393
  await local.keepMessages({
347
394
  conversation,
348
395
  messages: [message],
349
396
  ...(advances ? { read: message.position } : {}),
350
- sealed,
351
397
  });
352
398
  messages.set(conversation, merged(messages.get(conversation) ?? [], [message]));
353
399
  if (advances)
354
400
  reads.set(conversation, message.position);
355
- if (sealed)
356
- drafts.delete(conversation);
357
401
  sealTurns(conversation, new Set([message.turn]));
358
402
  deps.publish(conversationChangeSet([{ conversation, identity: message.identity }], [conversation]));
359
403
  });
@@ -405,17 +449,14 @@ export function createConversationStore(deps) {
405
449
  if (!replicated.has(conversation))
406
450
  return;
407
451
  const newest = arriving.reduce((top, message) => (top === null || message.position > top ? message.position : top), from ?? null);
408
- const turn = drafts.get(conversation)?.turn;
409
- const sealed = arriving.some((message) => message.turn === turn);
410
- await local.keepMessages({ conversation, messages: arriving, read: newest, sealed });
452
+ const sealing = await sealed(local, conversation, new Set(arriving.map((message) => message.turn)));
453
+ await local.keepMessages({ conversation, messages: arriving, read: newest });
411
454
  messages.set(conversation, merged(messages.get(conversation) ?? [], arriving));
412
455
  reads.set(conversation, newest);
413
- if (sealed)
414
- drafts.delete(conversation);
415
456
  sealTurns(conversation, new Set(arriving.map((message) => message.turn)));
416
457
  if ((gaps.get(conversation) ?? 0) === generation)
417
458
  behind.delete(conversation);
418
- if (arriving.length > 0 || sealed) {
459
+ if (arriving.length > 0 || sealing) {
419
460
  deps.publish(conversationChangeSet(arriving.map((message) => ({ conversation, identity: message.identity })), [conversation]));
420
461
  }
421
462
  });
@@ -462,22 +503,89 @@ export function createConversationStore(deps) {
462
503
  if (sealTurns(conversation, new Set([arriving.turn])))
463
504
  emit(conversation);
464
505
  }
506
+ async function kept(local, conversation, following) {
507
+ if (following === null || (unwritten(following) && following.submitted === undefined)) {
508
+ await local.dropChatDraft(conversation);
509
+ drafts.delete(conversation);
510
+ }
511
+ else {
512
+ await local.keepChatDraft(following);
513
+ drafts.set(conversation, following);
514
+ }
515
+ }
516
+ async function sealed(local, conversation, turns) {
517
+ const held = drafts.get(conversation);
518
+ const submitted = held?.submitted ?? [];
519
+ const left = submitted.filter((one) => one.turn === null || !turns.has(one.turn));
520
+ if (held === undefined || left.length === submitted.length)
521
+ return false;
522
+ await kept(local, conversation, withSubmitted(held, left));
523
+ return true;
524
+ }
465
525
  function withDraft(conversation, next) {
466
526
  return deps.durably(async (local) => {
467
527
  const following = next(drafts.get(conversation));
468
528
  if (following === undefined)
469
529
  return;
470
- if (following === null) {
471
- await local.dropChatDraft(conversation);
472
- drafts.delete(conversation);
473
- }
474
- else {
475
- await local.keepChatDraft(following);
476
- drafts.set(conversation, following);
477
- }
530
+ await kept(local, conversation, following);
478
531
  deps.publish(conversationChangeSet([], [conversation]));
479
532
  });
480
533
  }
534
+ async function submitted(conversation, operation, draft) {
535
+ let submission;
536
+ await withDraft(conversation, (current) => {
537
+ submission = current?.submitted?.find((one) => one.operation === operation);
538
+ if (submission !== undefined)
539
+ return undefined;
540
+ const said = draft ?? current;
541
+ submission = {
542
+ operation,
543
+ text: said?.text ?? '',
544
+ files: [...(said?.files ?? [])],
545
+ turn: null,
546
+ };
547
+ return {
548
+ conversation,
549
+ ...(draft === undefined || current === undefined
550
+ ? { text: '', files: [], revision: chatDraftRevision() }
551
+ : { text: current.text, files: current.files, revision: current.revision }),
552
+ submitted: [...(current?.submitted ?? []), submission],
553
+ };
554
+ });
555
+ return submission;
556
+ }
557
+ async function dispatched(conversation, submission) {
558
+ sending.add(submission.operation);
559
+ try {
560
+ const files = await Promise.all(submission.files.map(async (file) => ({ ...(await declaredFile(file)), blob: file.blob })));
561
+ const result = await invoke('conversation.send', conversation, {
562
+ text: submission.text,
563
+ files,
564
+ operation_id: submission.operation,
565
+ });
566
+ if (result.kind === 'revoked-authorization')
567
+ return result;
568
+ if (result.kind !== 'action' && result.retryable)
569
+ return result;
570
+ const turn = turnOf(result);
571
+ await withDraft(conversation, (current) => {
572
+ const held = current?.submitted?.find((one) => one.operation === submission.operation);
573
+ if (current === undefined || held === undefined || held.turn !== null)
574
+ return undefined;
575
+ const others = current.submitted.filter((one) => one !== held);
576
+ if (result.kind !== 'action')
577
+ return returned(current, held, others);
578
+ const arrived = (messages.get(conversation) ?? []).some((message) => message.turn === turn);
579
+ return withSubmitted(current, turn === null || arrived
580
+ ? others
581
+ : current.submitted.map((one) => (one === held ? { ...held, turn } : one)));
582
+ });
583
+ return result;
584
+ }
585
+ finally {
586
+ sending.delete(submission.operation);
587
+ }
588
+ }
481
589
  function invoke(name, conversation, extra = {}) {
482
590
  return deps.call(name, { conversation, ...extra });
483
591
  }
@@ -493,41 +601,16 @@ export function createConversationStore(deps) {
493
601
  create(input) {
494
602
  return deps.call('conversation.create', input);
495
603
  },
496
- async send(conversation) {
497
- const draft = drafts.get(conversation);
498
- const pending = draft === undefined ? undefined : { draft };
499
- if (pending !== undefined) {
500
- sending.set(conversation, pending);
501
- deps.publish(conversationChangeSet([], [conversation]));
604
+ async send(conversation, operation = changeBatchIdentity(), draft) {
605
+ if (deps.online()) {
606
+ return dispatched(conversation, await submitted(conversation, operation, draft));
502
607
  }
503
- try {
504
- const files = await Promise.all((draft?.files ?? []).map(async (file) => ({
505
- ...(await declaredFile(file)),
506
- blob: file.blob,
507
- })));
508
- const result = await invoke('conversation.send', conversation, {
509
- text: draft?.text ?? '',
510
- files,
511
- });
512
- const turn = turnOf(result);
513
- if (turn === null || draft === undefined)
514
- return result;
515
- await withDraft(conversation, (current) => {
516
- if (current !== draft)
517
- return undefined;
518
- const sealed = (messages.get(conversation) ?? []).some((message) => message.turn === turn);
519
- return sealed ? null : { ...draft, turn };
520
- });
521
- return result;
522
- }
523
- finally {
524
- if (pending !== undefined && sending.get(conversation) === pending) {
525
- sending.delete(conversation);
526
- if (drafts.get(conversation) === draft) {
527
- deps.publish(conversationChangeSet([], [conversation]));
528
- }
529
- }
608
+ if (draft !== undefined) {
609
+ await withDraft(conversation, (current) => current?.submitted?.some((one) => one.operation === operation) === true
610
+ ? undefined
611
+ : returned(current ?? { conversation, text: '', files: [], revision: '' }, { operation, ...draft, turn: null }, current?.submitted ?? []));
530
612
  }
613
+ return OFFLINE;
531
614
  },
532
615
  answer(conversation, answer) {
533
616
  return invoke('conversation.answer', conversation, { answer });
@@ -542,7 +625,12 @@ export function createConversationStore(deps) {
542
625
  const result = await invoke('conversation.cancel', conversation, { turn });
543
626
  if (result.kind !== 'action')
544
627
  return result;
545
- await withDraft(conversation, (current) => current === undefined || current.turn !== turn ? undefined : { ...current, turn: null });
628
+ await withDraft(conversation, (current) => {
629
+ const held = current?.submitted?.find((one) => one.turn === turn);
630
+ if (current === undefined || held === undefined)
631
+ return undefined;
632
+ return returned(current, held, current.submitted.filter((one) => one !== held));
633
+ });
546
634
  return result;
547
635
  },
548
636
  delete(conversation) {
@@ -550,16 +638,25 @@ export function createConversationStore(deps) {
550
638
  },
551
639
  };
552
640
  const chatDraft = {
553
- write(conversation, draft) {
554
- return withDraft(conversation, () => ({
641
+ write(conversation, draft, revision = chatDraftRevision()) {
642
+ return withDraft(conversation, (current) => ({
555
643
  conversation,
556
644
  text: draft.text,
557
645
  files: [...draft.files],
558
- turn: null,
646
+ revision,
647
+ ...(current?.submitted === undefined ? {} : { submitted: current.submitted }),
559
648
  }));
560
649
  },
561
650
  discard(conversation) {
562
- return withDraft(conversation, (current) => (current === undefined ? undefined : null));
651
+ return withDraft(conversation, (current) => current === undefined
652
+ ? undefined
653
+ : {
654
+ conversation,
655
+ text: '',
656
+ files: [],
657
+ revision: chatDraftRevision(),
658
+ ...pending(current),
659
+ });
563
660
  },
564
661
  };
565
662
  return {
@@ -605,6 +702,23 @@ export function createConversationStore(deps) {
605
702
  if (behind.size > 0)
606
703
  progress.complete = false;
607
704
  },
705
+ async resend(progress) {
706
+ for (const [conversation, held] of [...drafts]) {
707
+ for (const submission of held.submitted ?? []) {
708
+ if (submission.turn !== null || sending.has(submission.operation))
709
+ continue;
710
+ if (deps.closed())
711
+ return;
712
+ const result = await dispatched(conversation, submission);
713
+ if (result.kind === 'revoked-authorization')
714
+ return;
715
+ if (result.kind === 'transport-uncertainty') {
716
+ progress.reachable = false;
717
+ return;
718
+ }
719
+ }
720
+ }
721
+ },
608
722
  current() {
609
723
  return behind.size === 0;
610
724
  },
@@ -650,6 +764,16 @@ export function createConversationStore(deps) {
650
764
  listWatchers.delete(deliver);
651
765
  };
652
766
  },
767
+ watchAgents(deliver) {
768
+ agentWatchers.add(deliver);
769
+ void agentsReady().then(() => {
770
+ if (!deps.closed() && agentWatchers.has(deliver))
771
+ deliver(agents());
772
+ });
773
+ return () => {
774
+ agentWatchers.delete(deliver);
775
+ };
776
+ },
653
777
  changed(set) {
654
778
  for (const conversation of set.conversations)
655
779
  emit(conversation);
@@ -697,6 +821,7 @@ export function createConversationStore(deps) {
697
821
  views.clear();
698
822
  lives.clear();
699
823
  listWatchers.clear();
824
+ agentWatchers.clear();
700
825
  },
701
826
  };
702
827
  }
@@ -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
+ }