@agentshouse/mdruntime 0.1.0-c2aaa9c0e3ca4 → 0.1.0-c2c52158b7381

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 (199) hide show
  1. package/AGENTS.md +285 -276
  2. package/README.md +9 -8
  3. package/dist/adapter.d.ts +80 -21
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attached-model.d.ts +4 -1
  6. package/dist/attached-model.d.ts.map +1 -1
  7. package/dist/attached-model.js +13 -3
  8. package/dist/attempt.d.ts.map +1 -1
  9. package/dist/attempt.js +14 -1
  10. package/dist/bootstrap.d.ts +3 -2
  11. package/dist/bootstrap.d.ts.map +1 -1
  12. package/dist/bootstrap.js +83 -26
  13. package/dist/change-set.d.ts +7 -2
  14. package/dist/change-set.d.ts.map +1 -1
  15. package/dist/change-set.js +37 -10
  16. package/dist/change.d.ts +31 -1
  17. package/dist/change.d.ts.map +1 -1
  18. package/dist/change.js +10 -1
  19. package/dist/chat/acts.d.ts +3 -4
  20. package/dist/chat/acts.d.ts.map +1 -1
  21. package/dist/chat/acts.js +10 -10
  22. package/dist/chat/earlier.d.ts +10 -0
  23. package/dist/chat/earlier.d.ts.map +1 -0
  24. package/dist/chat/earlier.js +54 -0
  25. package/dist/chat/house.d.ts +25 -0
  26. package/dist/chat/house.d.ts.map +1 -0
  27. package/dist/chat/house.js +38 -0
  28. package/dist/chat/input.d.ts +3 -1
  29. package/dist/chat/input.d.ts.map +1 -1
  30. package/dist/chat/input.js +11 -18
  31. package/dist/chat/kit.d.ts +2 -1
  32. package/dist/chat/kit.d.ts.map +1 -1
  33. package/dist/chat/kit.js +3 -3
  34. package/dist/chat/list.d.ts +9 -1
  35. package/dist/chat/list.d.ts.map +1 -1
  36. package/dist/chat/list.js +53 -9
  37. package/dist/chat/markdown.d.ts +3 -1
  38. package/dist/chat/markdown.d.ts.map +1 -1
  39. package/dist/chat/markdown.js +85 -26
  40. package/dist/chat/message.d.ts +1 -0
  41. package/dist/chat/message.d.ts.map +1 -1
  42. package/dist/chat/message.js +57 -12
  43. package/dist/chat/messages.d.ts +9 -1
  44. package/dist/chat/messages.d.ts.map +1 -1
  45. package/dist/chat/messages.js +67 -28
  46. package/dist/chat/name.d.ts +1 -0
  47. package/dist/chat/name.d.ts.map +1 -1
  48. package/dist/chat/name.js +1 -1
  49. package/dist/chat/opened.d.ts +1 -0
  50. package/dist/chat/opened.d.ts.map +1 -1
  51. package/dist/chat/opened.js +2 -0
  52. package/dist/chat/overlay.d.ts +1 -0
  53. package/dist/chat/overlay.d.ts.map +1 -1
  54. package/dist/chat/overlay.js +11 -5
  55. package/dist/chat/parts.d.ts +1 -0
  56. package/dist/chat/parts.d.ts.map +1 -1
  57. package/dist/chat/parts.js +3 -2
  58. package/dist/chat/pieces.d.ts +62 -0
  59. package/dist/chat/pieces.d.ts.map +1 -0
  60. package/dist/chat/pieces.js +1110 -0
  61. package/dist/chat/provider.d.ts +7 -2
  62. package/dist/chat/provider.d.ts.map +1 -1
  63. package/dist/chat/provider.js +129 -155
  64. package/dist/chat/question.d.ts +1 -1
  65. package/dist/chat/question.d.ts.map +1 -1
  66. package/dist/chat/question.js +7 -18
  67. package/dist/chat/ready.d.ts +5 -1
  68. package/dist/chat/ready.d.ts.map +1 -1
  69. package/dist/chat/ready.js +9 -7
  70. package/dist/chat/room-file.d.ts +8 -0
  71. package/dist/chat/room-file.d.ts.map +1 -0
  72. package/dist/chat/room-file.js +72 -0
  73. package/dist/chat/steady.d.ts +3 -0
  74. package/dist/chat/steady.d.ts.map +1 -0
  75. package/dist/chat/steady.js +26 -0
  76. package/dist/chat/style.d.ts.map +1 -1
  77. package/dist/chat/style.js +8 -4
  78. package/dist/chat.d.ts +3 -2
  79. package/dist/chat.d.ts.map +1 -1
  80. package/dist/chat.js +2 -2
  81. package/dist/client.d.ts +21 -9
  82. package/dist/client.d.ts.map +1 -1
  83. package/dist/client.js +47 -8
  84. package/dist/collection.d.ts +21 -6
  85. package/dist/collection.d.ts.map +1 -1
  86. package/dist/collection.js +332 -40
  87. package/dist/connection.d.ts +39 -11
  88. package/dist/connection.d.ts.map +1 -1
  89. package/dist/connection.js +2294 -492
  90. package/dist/conversation.d.ts +28 -9
  91. package/dist/conversation.d.ts.map +1 -1
  92. package/dist/conversation.js +500 -165
  93. package/dist/digest.d.ts +7 -0
  94. package/dist/digest.d.ts.map +1 -0
  95. package/dist/digest.js +113 -0
  96. package/dist/durability.d.ts +8 -1
  97. package/dist/durability.d.ts.map +1 -1
  98. package/dist/entry.d.ts +18 -0
  99. package/dist/entry.d.ts.map +1 -0
  100. package/dist/entry.js +157 -0
  101. package/dist/fence.d.ts +6 -0
  102. package/dist/fence.d.ts.map +1 -0
  103. package/dist/fence.js +10 -0
  104. package/dist/file.d.ts +2 -10
  105. package/dist/file.d.ts.map +1 -1
  106. package/dist/file.js +3 -120
  107. package/dist/host.d.ts +15 -3
  108. package/dist/host.d.ts.map +1 -1
  109. package/dist/host.js +103 -13
  110. package/dist/identity.d.ts +2 -0
  111. package/dist/identity.d.ts.map +1 -1
  112. package/dist/identity.js +6 -0
  113. package/dist/index.d.ts +15 -9
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +5 -0
  116. package/dist/memory.d.ts +8 -2
  117. package/dist/memory.d.ts.map +1 -1
  118. package/dist/memory.js +43 -12
  119. package/dist/model.d.ts +4 -2
  120. package/dist/model.d.ts.map +1 -1
  121. package/dist/model.js +10 -1
  122. package/dist/name.d.ts +4 -0
  123. package/dist/name.d.ts.map +1 -0
  124. package/dist/name.js +122 -0
  125. package/dist/observation.d.ts +7 -2
  126. package/dist/observation.d.ts.map +1 -1
  127. package/dist/observation.js +29 -12
  128. package/dist/opened.d.ts +22 -0
  129. package/dist/opened.d.ts.map +1 -0
  130. package/dist/opened.js +107 -0
  131. package/dist/outcome.d.ts +39 -4
  132. package/dist/outcome.d.ts.map +1 -1
  133. package/dist/outcome.js +29 -0
  134. package/dist/overlay.d.ts +6 -4
  135. package/dist/overlay.d.ts.map +1 -1
  136. package/dist/overlay.js +229 -161
  137. package/dist/query.d.ts +57 -4
  138. package/dist/query.d.ts.map +1 -1
  139. package/dist/query.js +37 -7
  140. package/dist/reach.d.ts +11 -4
  141. package/dist/reach.d.ts.map +1 -1
  142. package/dist/reach.js +192 -41
  143. package/dist/react.d.ts +8 -6
  144. package/dist/react.d.ts.map +1 -1
  145. package/dist/react.js +7 -17
  146. package/dist/read-side.d.ts +18 -9
  147. package/dist/read-side.d.ts.map +1 -1
  148. package/dist/read-side.js +894 -155
  149. package/dist/readiness.d.ts +53 -0
  150. package/dist/readiness.d.ts.map +1 -0
  151. package/dist/readiness.js +33 -0
  152. package/dist/reads.d.ts +11 -0
  153. package/dist/reads.d.ts.map +1 -0
  154. package/dist/reads.js +98 -0
  155. package/dist/recovery.d.ts +25 -0
  156. package/dist/recovery.d.ts.map +1 -0
  157. package/dist/recovery.js +198 -0
  158. package/dist/refresh.d.ts +4 -4
  159. package/dist/refresh.d.ts.map +1 -1
  160. package/dist/refresh.js +46 -20
  161. package/dist/replica.d.ts +12 -7
  162. package/dist/replica.d.ts.map +1 -1
  163. package/dist/replica.js +151 -64
  164. package/dist/room-draft.d.ts +16 -2
  165. package/dist/room-draft.d.ts.map +1 -1
  166. package/dist/room-draft.js +32 -25
  167. package/dist/rows.d.ts +6 -13
  168. package/dist/rows.d.ts.map +1 -1
  169. package/dist/rows.js +10 -13
  170. package/dist/save.d.ts +52 -10
  171. package/dist/save.d.ts.map +1 -1
  172. package/dist/save.js +519 -159
  173. package/dist/search.d.ts +49 -6
  174. package/dist/search.d.ts.map +1 -1
  175. package/dist/search.js +242 -46
  176. package/dist/seed.d.ts +16 -0
  177. package/dist/seed.d.ts.map +1 -0
  178. package/dist/seed.js +75 -0
  179. package/dist/shared.d.ts +19 -0
  180. package/dist/shared.d.ts.map +1 -0
  181. package/dist/shared.js +461 -0
  182. package/dist/status.d.ts +4 -0
  183. package/dist/status.d.ts.map +1 -1
  184. package/dist/store.d.ts +61 -17
  185. package/dist/store.d.ts.map +1 -1
  186. package/dist/store.js +581 -310
  187. package/dist/tables.d.ts +242 -0
  188. package/dist/tables.d.ts.map +1 -0
  189. package/dist/tables.js +406 -0
  190. package/dist/turn.d.ts +9 -0
  191. package/dist/turn.d.ts.map +1 -0
  192. package/dist/turn.js +67 -0
  193. package/dist/windows.d.ts +21 -0
  194. package/dist/windows.d.ts.map +1 -0
  195. package/dist/windows.js +84 -0
  196. package/dist/wire.d.ts +168 -32
  197. package/dist/wire.d.ts.map +1 -1
  198. package/dist/wire.js +56 -31
  199. package/package.json +10 -2
@@ -1,8 +1,9 @@
1
1
  import { type ReactElement, type ReactNode } from 'react';
2
2
  import type { TurnContext } from '../adapter.js';
3
3
  import type { MdRuntimeClient } from '../client.js';
4
- import type { ChatDraft, ConversationAgent, ConversationEntry, ConversationView } from '../conversation.js';
4
+ import { type ChatDraft, type ConversationAgent, type ConversationEntry, type ConversationView } from '../conversation.js';
5
5
  import { type ChatOutcome } from './acts.js';
6
+ import type { ChatRequest } from './house.js';
6
7
  import { type ChatCommand, type ChatOption } from './process.js';
7
8
  import { type ChatLone, type ChatQuestion } from './questions.js';
8
9
  export type ChatOpened = {
@@ -21,6 +22,7 @@ export type ChatState = ChatOpened & {
21
22
  readonly conversations: readonly ConversationEntry[];
22
23
  readonly agents: readonly ConversationAgent[];
23
24
  readonly view: ConversationView | null;
25
+ readonly waiting: ChatRequest | null;
24
26
  readonly running: boolean;
25
27
  readonly questions: readonly ChatQuestion[];
26
28
  readonly lone: ChatLone | null;
@@ -35,10 +37,12 @@ export type ChatState = ChatOpened & {
35
37
  open(conversation: string): void;
36
38
  start(agent: string): void;
37
39
  send(draft: ChatDraft): void;
40
+ attach: ((files: readonly File[]) => Promise<boolean>) | null;
38
41
  answer(question: ChatQuestion, response: unknown): Promise<boolean>;
39
42
  choose(option: string, value: string): Promise<boolean>;
40
43
  stop(): Promise<boolean>;
41
44
  kill(): Promise<boolean>;
45
+ retry(message: string): Promise<boolean>;
42
46
  done(): Promise<boolean>;
43
47
  rename(name: string): Promise<boolean>;
44
48
  remove(): Promise<boolean>;
@@ -49,6 +53,7 @@ export type ChatProviderProps = {
49
53
  readonly client: MdRuntimeClient;
50
54
  readonly conversation?: string | null;
51
55
  readonly agent?: string | null;
56
+ readonly attachTo?: string | null;
52
57
  readonly onOpen?: (opened: ChatOpened) => void;
53
58
  readonly children?: ReactNode;
54
59
  };
@@ -58,6 +63,6 @@ type Scope = {
58
63
  };
59
64
  export declare function useChatScope(): Scope;
60
65
  export declare function useChat(): ChatState;
61
- export declare function ChatProvider({ client, conversation, agent, onOpen, children, }: ChatProviderProps): ReactElement;
66
+ export declare function ChatProvider({ client, conversation, agent, attachTo, onOpen, children, }: ChatProviderProps): ReactElement;
62
67
  export {};
63
68
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAaf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAM5B,OAAO,EAML,KAAK,WAAW,EAGjB,MAAM,WAAW,CAAC;AAanB,OAAO,EAAoC,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,EAAuB,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGvF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG;IACnC,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,CAAC;IACvE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC/B,CAAC;AAuNF,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAI3E,wBAAgB,YAAY,IAAI,KAAK,CAIpC;AAED,wBAAgB,OAAO,IAAI,SAAS,CAInC;AAED,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,YAAmB,EACnB,KAAY,EACZ,MAAM,EACN,QAAQ,GACT,EAAE,iBAAiB,GAAG,YAAY,CAyhBlC"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,20 @@
1
1
  import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore, } from 'react';
2
- import { AssistantRuntimeProvider, createMessageQueue, generateId, useExternalStoreRuntime, } from '@assistant-ui/react';
2
+ import { AssistantRuntimeProvider, createMessageQueue, useExternalStoreRuntime, } from '@assistant-ui/react';
3
3
  import { attempts } from '../attempt.js';
4
+ import { newChat, } from '../conversation.js';
4
5
  import { expectedList } from '../expectation.js';
5
6
  import { chatDraftRevision } from '../identity.js';
6
7
  import { useObserve } from '../react.js';
7
8
  import { accepted, answeredOf, outcomeOf, sender, unanswered, } from './acts.js';
8
- import { askedBefore, chatMessages, contextOf } from './messages.js';
9
- import { conversationChanged, conversationGone, conversationListed, optionChosen, overlay, questionAnswered, sentMessage, } from './overlay.js';
9
+ import { CHAT_WINDOW, useEarlier } from './earlier.js';
10
+ import { askedBefore, chatMessages, contextOf, requestIn } from './messages.js';
11
+ import { useSteady } from './steady.js';
12
+ import { conversationChanged, conversationGone, conversationListed, deliveryRetried, optionChosen, overlay, questionAnswered, sentMessage, } from './overlay.js';
10
13
  import { commandIn, commandsOf, optionsOf } from './process.js';
11
14
  import { loneOf, questionsOf } from './questions.js';
12
15
  import { record, text } from './read.js';
13
16
  const SHARED = new WeakMap();
17
+ const LATEST = { limit: CHAT_WINDOW };
14
18
  function sharedOf(client) {
15
19
  const held = SHARED.get(client);
16
20
  if (held !== undefined)
@@ -19,53 +23,18 @@ function sharedOf(client) {
19
23
  SHARED.set(client, fresh);
20
24
  return fresh;
21
25
  }
22
- function newChat(agent) {
23
- return `new:${agent}`;
24
- }
25
26
  function ready(observed) {
26
27
  return observed.state === 'ready' ? observed.value : null;
27
28
  }
28
- async function alike(one, other) {
29
- if (one.type !== other.type || one.size !== other.size)
30
- return false;
31
- const [mine, theirs] = await Promise.all([one.arrayBuffer(), other.arrayBuffer()]);
32
- const bytes = new Uint8Array(theirs);
33
- return new Uint8Array(mine).every((byte, at) => byte === bytes[at]);
34
- }
35
- async function same(one, other) {
36
- if (one.text !== other.text || one.files.length !== other.files.length)
37
- return false;
38
- const files = await Promise.all(one.files.map(async (file, at) => {
39
- const twin = other.files[at];
40
- return twin !== undefined && file.name === twin.name && (await alike(file.blob, twin.blob));
41
- }));
42
- return files.every(Boolean);
43
- }
44
29
  function turnOf(result) {
45
30
  return accepted(result) ? text(record(result.result), 'turn') : null;
46
31
  }
47
- async function deliver(client, send, conversation, said, key, refused, noted) {
48
- const typed = (await client.conversation.read(conversation)).chatDraft;
49
- const kept = chatDraftRevision();
50
- noted(conversation, kept);
51
- await client.chatDraft.write(conversation, said, kept);
52
- const result = await send.carried('conversation.send', { conversation, key }, () => {
53
- noted(conversation, null);
54
- noted(conversation, kept);
55
- return client.conversation.send(conversation);
56
- });
57
- if (typed !== null && !(await same(typed, said))) {
58
- const now = (await client.conversation.read(conversation)).chatDraft;
59
- if (now === null || now.revision === kept) {
60
- const back = chatDraftRevision();
61
- noted(conversation, back);
62
- await client.chatDraft.write(conversation, typed, back);
63
- }
64
- }
32
+ async function deliver(client, send, conversation, said, key, idle) {
33
+ const result = await send.numbered('conversation.send', { conversation, key }, (operation) => client.conversation.send(conversation, operation, said));
65
34
  if (accepted(result))
66
35
  send.expect(sentMessage(key, [conversation], said, turnOf(result)));
67
36
  else if (!unanswered(result))
68
- refused();
37
+ idle();
69
38
  return result;
70
39
  }
71
40
  const IDLE = { busy: false, outcome: null };
@@ -122,46 +91,21 @@ function useActs(overlay, online) {
122
91
  }, [overlay, online, tried]);
123
92
  return { ...running, call, clear };
124
93
  }
125
- const ATTACHMENTS = {
126
- accept: '*',
127
- add: ({ file }) => Promise.resolve({
128
- id: generateId(),
129
- type: 'file',
130
- name: file.name,
131
- contentType: file.type,
132
- file,
133
- status: { type: 'requires-action', reason: 'composer-send' },
134
- }),
135
- send: (attachment) => Promise.resolve({ ...attachment, status: { type: 'complete' }, content: [] }),
136
- remove: () => Promise.resolve(),
137
- };
138
- function filesOf(attachments) {
139
- return attachments.flatMap((one) => one.file === undefined ? [] : [{ name: one.name, blob: one.file }]);
140
- }
141
- function fileOf(file) {
142
- return file.blob instanceof File && file.blob.name === file.name
143
- ? file.blob
144
- : new File([file.blob], file.name, { type: file.blob.type });
145
- }
94
+ const AS_IT_IS = (message) => message;
146
95
  function textOf(parts) {
147
96
  return parts.map((part) => (part.type === 'text' ? (part.text ?? '') : '')).join('');
148
97
  }
149
98
  function draftOf(message) {
150
- return { text: textOf(message.content), files: filesOf(message.attachments ?? []) };
99
+ return { text: textOf(message.content) };
100
+ }
101
+ function linkOf(path) {
102
+ return `[${path.slice(path.lastIndexOf('/') + 1)}](${path})`;
151
103
  }
152
104
  function appended(draft) {
153
105
  return {
154
106
  role: 'user',
155
107
  content: [{ type: 'text', text: draft.text }],
156
- attachments: draft.files.map((file) => ({
157
- id: generateId(),
158
- type: 'file',
159
- name: file.name,
160
- contentType: file.blob.type,
161
- file: fileOf(file),
162
- status: { type: 'complete' },
163
- content: [],
164
- })),
108
+ attachments: [],
165
109
  metadata: { custom: {} },
166
110
  createdAt: new Date(),
167
111
  parentId: null,
@@ -169,9 +113,6 @@ function appended(draft) {
169
113
  runConfig: undefined,
170
114
  };
171
115
  }
172
- function composed(state) {
173
- return JSON.stringify([state.text, state.attachments.map((one) => one.id)]);
174
- }
175
116
  const ChatContext = createContext(null);
176
117
  const ScopeContext = createContext(null);
177
118
  export function useChatScope() {
@@ -186,7 +127,7 @@ export function useChat() {
186
127
  throw new Error('useChat is called outside a ChatProvider');
187
128
  return chat;
188
129
  }
189
- export function ChatProvider({ client, conversation = null, agent = null, onOpen, children, }) {
130
+ export function ChatProvider({ client, conversation = null, agent = null, attachTo = null, onOpen, children, }) {
190
131
  const shared = sharedOf(client);
191
132
  const asked = JSON.stringify([conversation, agent]);
192
133
  const [followed, setFollowed] = useState(asked);
@@ -206,11 +147,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
206
147
  }, []);
207
148
  const listedHeld = ready(useObserve(client, 'conversations'));
208
149
  const agentsHeld = ready(useObserve(client, 'agents'));
209
- const sync = ready(useObserve(client, 'sync-status'));
150
+ const readiness = ready(useObserve(client, 'readiness'));
210
151
  const refusal = ready(useObserve(client, 'connection-refusal'));
211
- const online = sync !== null && !sync.providerUnreachable && refusal === null;
212
- const thread = open.conversation ?? (open.agent === null ? null : newChat(open.agent));
213
- const held = ready(useObserve(thread === null ? null : client, 'conversation', thread ?? '', {}));
152
+ const online = readiness?.connection !== 'unreachable' && refusal === null;
153
+ const thread = open.conversation ??
154
+ (open.agent === null ? null : (shared.created.get(open.agent) ?? newChat(open.agent)));
155
+ const observed = ready(useObserve(thread === null ? null : client, 'conversation', thread ?? '', LATEST));
156
+ const held = observed !== null && observed.conversation === thread ? observed : null;
157
+ const paged = useEarlier(client, thread, useSteady(held));
214
158
  const version = useSyncExternalStore(shared.overlay.subscribe, shared.overlay.version);
215
159
  useEffect(() => {
216
160
  if (listedHeld !== null)
@@ -221,7 +165,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
221
165
  shared.overlay.heard(held);
222
166
  }, [shared, held, version]);
223
167
  const conversations = useMemo(() => shared.overlay.conversations(listedHeld ?? []), [shared, listedHeld, version]);
224
- const view = useMemo(() => held === null || held.conversation !== thread ? null : shared.overlay.conversation(held), [shared, held, thread, version]);
168
+ const view = useMemo(() => (paged.view === null ? null : shared.overlay.conversation(paged.view)), [shared, paged.view, version]);
225
169
  const agents = agentsHeld ?? [];
226
170
  const known = useRef(agents);
227
171
  known.current = agents;
@@ -231,6 +175,10 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
231
175
  const lone = loneOf(questions);
232
176
  const commands = useMemo(() => commandsOf(view), [view]);
233
177
  const messages = useMemo(() => chatMessages(view), [view]);
178
+ const awaiting = useMemo(() => {
179
+ const held = requestIn(view);
180
+ return held?.waiting === true ? held.request : null;
181
+ }, [view]);
234
182
  const sending = useActs(shared.overlay, online);
235
183
  const behind = useActs(shared.overlay, online);
236
184
  const acting = useActs(shared.overlay, online);
@@ -238,6 +186,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
238
186
  const current = useRef(thread);
239
187
  current.current = thread;
240
188
  const seeding = useRef(false);
189
+ const mounted = useRef(true);
190
+ useEffect(() => {
191
+ mounted.current = true;
192
+ return () => {
193
+ mounted.current = false;
194
+ };
195
+ }, []);
196
+ const was = useRef(null);
241
197
  const heard = useRef('');
242
198
  const shown = useRef('');
243
199
  const own = useRef([]);
@@ -245,7 +201,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
245
201
  own.current = [...own.current, `${to}\u0000${revision ?? ''}`];
246
202
  }, []);
247
203
  const keep = useCallback((to, draft) => {
248
- const revision = draft.text === '' && draft.files.length === 0 ? null : chatDraftRevision();
204
+ const revision = draft.text === '' ? null : chatDraftRevision();
249
205
  noted(to, revision);
250
206
  void (revision === null
251
207
  ? client.chatDraft.discard(to)
@@ -255,21 +211,26 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
255
211
  heard.current = '';
256
212
  shown.current = '';
257
213
  own.current = own.current.filter((one) => one.startsWith(`${thread}\u0000`));
214
+ const created = was.current === open;
215
+ was.current = open;
216
+ if (created)
217
+ return;
258
218
  sending.clear();
259
219
  acting.clear();
260
220
  setAgain(null);
261
221
  }, [thread, sending.clear, acting.clear]);
262
- const sendTo = (to, said, key, refused, acts = sending) => acts.call((send) => deliver(client, send, to, said, key, refused, noted), sentMessage(key, [to], said, null));
263
- const first = (to, said, key, refused) => {
222
+ const sendTo = (to, said, key, idle, acts = sending) => acts.call((send) => deliver(client, send, to, said, key, idle), sentMessage(key, [to], said, null));
223
+ const first = (to, said, key, returning, idle) => {
264
224
  const drafted = [newChat(to)];
265
- let made = null;
266
225
  return sending.call(async (send) => {
267
226
  let conversation = shared.created.get(to);
268
227
  if (conversation === undefined) {
269
228
  const answer = await send.carried('conversation.create', { agent: to }, (operation) => client.conversation.create({ agent_id: to, operation_id: operation }));
270
229
  if (!accepted(answer)) {
271
- if (!unanswered(answer))
272
- refused();
230
+ if (!unanswered(answer)) {
231
+ returning();
232
+ idle();
233
+ }
273
234
  return answer;
274
235
  }
275
236
  const named = text(record(answer.result), 'conversation');
@@ -285,43 +246,34 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
285
246
  created: new Date().toISOString(),
286
247
  finished: null,
287
248
  outcome: null,
249
+ waiting: false,
288
250
  state: 'idle',
289
251
  started: null,
290
252
  }));
291
253
  }
292
- made = conversation;
293
254
  send.draw(sentMessage(key, [...drafted, conversation], said, null));
294
- const result = await deliver(client, send, conversation, said, key, refused, noted);
295
- if (accepted(result))
296
- shared.created.delete(to);
297
- return result;
298
- }, sentMessage(key, drafted, said, null), () => {
299
- if (made === null)
300
- return;
301
- void client.chatDraft.discard(newChat(to));
255
+ const result = await deliver(client, send, conversation, said, key, idle);
256
+ if (!accepted(result))
257
+ return result;
258
+ shared.created.delete(to);
302
259
  const now = opened.current;
303
- if (now.conversation === null && now.agent === to)
304
- go({ conversation: made, agent: to });
305
- });
306
- };
307
- const returned = async (to, one) => {
308
- const now = (await client.conversation.read(to)).chatDraft;
309
- await client.chatDraft.write(to, {
310
- text: now === null || now.text === '' ? one.text : `${one.text}\n${now.text}`,
311
- files: [...one.files, ...(now?.files ?? [])],
312
- });
260
+ if (mounted.current && now.conversation === null && now.agent === to) {
261
+ go({ conversation, agent: to });
262
+ }
263
+ return result;
264
+ }, sentMessage(key, drafted, said, null));
313
265
  };
314
266
  const sent = () => {
315
267
  shared.sends += 1;
316
268
  return `sent ${shared.sends}`;
317
269
  };
318
- const deliverDraft = (said, refused) => {
270
+ const deliverDraft = (said, returning, idle) => {
319
271
  const key = sent();
320
272
  const { conversation: to, agent: by } = opened.current;
321
273
  const attempt = to !== null
322
- ? () => void sendTo(to, said, key, refused)
274
+ ? () => void sendTo(to, said, key, idle)
323
275
  : by !== null
324
- ? () => void first(by, said, key, refused)
276
+ ? () => void first(by, said, key, returning, idle)
325
277
  : null;
326
278
  if (attempt === null)
327
279
  return;
@@ -349,6 +301,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
349
301
  return Promise.resolve(false);
350
302
  return control('conversation.setOption', { conversation_id: to, option, value }, optionChosen(to, option, value));
351
303
  };
304
+ const retry = (message) => {
305
+ const to = opened.current.conversation;
306
+ if (to === null)
307
+ return Promise.resolve(false);
308
+ return control('conversation.retry', { conversation_id: to, message_id: message }, deliveryRetried(to, message));
309
+ };
352
310
  const done = (to = opened.current.conversation) => to === null
353
311
  ? Promise.resolve(false)
354
312
  : control('conversation.markDone', { conversation_id: to }, conversationChanged(to, { finished: new Date().toISOString() }, (one) => one.finished !== null));
@@ -424,7 +382,9 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
424
382
  const aui = useExternalStoreRuntime({
425
383
  messages,
426
384
  isRunning: running,
427
- convertMessage: (message) => message,
385
+ hasEarlier: paged.hasEarlier,
386
+ onLoadEarlier: paged.loadEarlier,
387
+ convertMessage: AS_IT_IS,
428
388
  queue: lined(),
429
389
  onNew: async (message) => lined().enqueue(message),
430
390
  onCancel: async () => {
@@ -436,12 +396,11 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
436
396
  const said = askedBefore(view, parent);
437
397
  if (said === null)
438
398
  return;
439
- const draft = { text: said, files: [] };
399
+ const draft = { text: said };
440
400
  const into = thread;
441
- deliverDraft(draft, () => back(draft, into));
401
+ deliverDraft(draft, () => back(draft, into), () => undefined);
442
402
  },
443
403
  adapters: {
444
- attachments: ATTACHMENTS,
445
404
  threadList: {
446
405
  ...(thread === null ? {} : { threadId: thread }),
447
406
  threads: threads.regular,
@@ -466,15 +425,39 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
466
425
  });
467
426
  function back(one, into) {
468
427
  if (current.current !== into) {
469
- void returned(into, one);
428
+ void client.chatDraft.prepend(into, one);
470
429
  return;
471
430
  }
472
431
  const composer = aui.thread.composer;
473
432
  const now = composer.getState().text;
474
433
  composer.setText(now === '' ? one.text : `${one.text}\n${now}`);
475
- for (const file of one.files)
476
- void composer.addAttachment(fileOf(file));
477
434
  }
435
+ function linked(path, into) {
436
+ if (current.current !== into) {
437
+ void client.chatDraft.prepend(into, { text: linkOf(path) });
438
+ return;
439
+ }
440
+ const composer = aui.thread.composer;
441
+ const now = composer.getState().text;
442
+ composer.setText(now === '' ? linkOf(path) : `${now}\n${linkOf(path)}`);
443
+ }
444
+ const attach = (room, files) => {
445
+ const into = thread;
446
+ if (into === null || files.length === 0)
447
+ return Promise.resolve(false);
448
+ return acting.call(async (send) => {
449
+ let result = { kind: 'offline' };
450
+ for (const file of files) {
451
+ result = await send.numbered('conversation.attach', { room, name: file.name }, () => client.conversation.attach(room, { name: file.name, blob: file }));
452
+ if (!accepted(result))
453
+ return result;
454
+ const path = text(record(result.result), 'path');
455
+ if (path !== null)
456
+ linked(path, into);
457
+ }
458
+ return result;
459
+ });
460
+ };
478
461
  function taken(message) {
479
462
  const said = textOf(message.content);
480
463
  if (lone === null || commandIn(said, commands))
@@ -486,6 +469,15 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
486
469
  const holding = (put) => (message) => {
487
470
  if (taken(message))
488
471
  return;
472
+ if (!online) {
473
+ const draft = draftOf(message);
474
+ const at = current.current;
475
+ deliverDraft(draft, () => {
476
+ if (at !== null)
477
+ back(draft, at);
478
+ }, () => undefined);
479
+ return;
480
+ }
489
481
  const known = new Set(lanes().map((one) => one.id));
490
482
  if (!lane.running)
491
483
  queue.notifyIdle();
@@ -513,18 +505,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
513
505
  const draft = draftOf(message);
514
506
  const idle = () => queues.current.get(key)?.queue.notifyIdle();
515
507
  if (key !== (current.current ?? '')) {
516
- void sendTo(key, draft, sent(), () => {
517
- back(draft, key);
518
- idle();
519
- }, behind);
508
+ void sendTo(key, draft, sent(), idle, behind);
520
509
  return;
521
510
  }
522
511
  const into = current.current;
523
512
  deliverDraft(draft, () => {
524
513
  if (into !== null)
525
514
  back(draft, into);
526
- idle();
527
- });
515
+ }, idle);
528
516
  };
529
517
  const unqueue = (id) => {
530
518
  const message = waiting.current.get(id);
@@ -537,7 +525,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
537
525
  const message = unqueue(id);
538
526
  if (thread === null || item === undefined)
539
527
  return;
540
- back(message === undefined ? { text: textOf(item.parts), files: [] } : draftOf(message), thread);
528
+ back(message === undefined ? { text: textOf(item.parts) } : draftOf(message), thread);
541
529
  };
542
530
  const reconcile = useRef(() => undefined);
543
531
  reconcile.current = () => {
@@ -556,42 +544,25 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
556
544
  }
557
545
  own.current = own.current.filter((one) => !one.startsWith(at));
558
546
  const composer = aui.thread.composer;
559
- const state = composer.getState();
547
+ const typed = composer.getState().text;
560
548
  const stored = view.chatDraft;
561
- const typed = { text: state.text, files: filesOf(state.attachments) };
562
- const kept = !known && (typed.text !== '' || typed.files.length > 0);
549
+ const kept = !known && typed !== '';
563
550
  if (kept && stored === null) {
564
- shown.current = `${at}${composed(state)}`;
565
- keep(thread, typed);
551
+ shown.current = `${at}${typed}`;
552
+ keep(thread, { text: typed });
566
553
  return;
567
554
  }
568
555
  const draft = kept
569
- ? {
570
- text: [stored?.text ?? '', typed.text].filter((one) => one !== '').join('\n'),
571
- files: [...(stored?.files ?? []), ...typed.files],
572
- }
573
- : stored;
574
- if (state.text === (draft?.text ?? '') &&
575
- state.attachments.length === 0 &&
576
- (draft?.files.length ?? 0) === 0) {
577
- shown.current = `${at}${composed(state)}`;
556
+ ? [stored?.text ?? '', typed].filter((one) => one !== '').join('\n')
557
+ : (stored?.text ?? '');
558
+ shown.current = `${at}${draft}`;
559
+ if (typed === draft)
578
560
  return;
579
- }
580
561
  seeding.current = true;
581
- composer.setText(draft?.text ?? '');
582
- void composer
583
- .clearAttachments()
584
- .then(() => Promise.all((draft?.files ?? []).map((file) => composer.addAttachment(fileOf(file)))))
585
- .finally(() => {
586
- seeding.current = false;
587
- if (current.current !== thread)
588
- return;
589
- const seeded = composer.getState();
590
- shown.current = `${at}${composed(seeded)}`;
591
- if (kept)
592
- keep(thread, { text: seeded.text, files: filesOf(seeded.attachments) });
593
- reconcile.current();
594
- });
562
+ composer.setText(draft);
563
+ seeding.current = false;
564
+ if (kept)
565
+ keep(thread, { text: draft });
595
566
  };
596
567
  useEffect(() => reconcile.current(), [aui, thread, view]);
597
568
  useEffect(() => {
@@ -602,12 +573,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
602
573
  return composer.subscribe(() => {
603
574
  if (seeding.current || !heard.current.startsWith(at))
604
575
  return;
605
- const state = composer.getState();
606
- const next = `${at}${composed(state)}`;
576
+ const typed = composer.getState().text;
577
+ const next = `${at}${typed}`;
607
578
  if (next === shown.current)
608
579
  return;
609
580
  shown.current = next;
610
- keep(thread, { text: state.text, files: filesOf(state.attachments) });
581
+ keep(thread, { text: typed });
611
582
  });
612
583
  }, [aui, thread, keep]);
613
584
  const queued = lanes().map((item) => ({ id: item.id, text: textOf(item.parts) }));
@@ -616,6 +587,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
616
587
  conversations,
617
588
  agents,
618
589
  view,
590
+ waiting: awaiting,
619
591
  running,
620
592
  questions,
621
593
  lone,
@@ -628,10 +600,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
628
600
  open: openConversation,
629
601
  start,
630
602
  send: (draft) => lined().enqueue(appended(draft)),
603
+ attach: attachTo === null ? null : (files) => attach(attachTo, files),
631
604
  answer,
632
605
  choose,
633
606
  stop,
634
607
  kill,
608
+ retry,
635
609
  done: () => done(),
636
610
  rename: (name) => rename(name),
637
611
  remove: () => remove(),
@@ -1,5 +1,5 @@
1
1
  import { type ReactElement } from 'react';
2
- import { type MdRuntimeClient } from '../client.js';
2
+ import type { MdRuntimeClient } from '../client.js';
3
3
  import type { ChatQuestion } from './questions.js';
4
4
  export declare function forgetAnswers(client: MdRuntimeClient, conversation: string, interaction?: string): Promise<void>;
5
5
  export type ChatQuestionCardProps = {
@@ -1 +1 @@
1
- {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/chat/question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGhE,OAAO,EAAU,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAM5D,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAoB9D,wBAAgB,aAAa,CAC3B,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,EACpB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAQf;AAeD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAmHlF"}
1
+ {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/chat/question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAMpD,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9D,wBAAsB,aAAa,CACjC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,EACpB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAOf;AAeD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAmHlF"}
@@ -2,41 +2,30 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  import { useContext, useState } from 'react';
3
3
  import Check from 'lucide-react/dist/esm/icons/check.mjs';
4
4
  import CircleHelp from 'lucide-react/dist/esm/icons/circle-help.mjs';
5
- import { inTurn } from '../client.js';
6
5
  import { useObserve } from '../react.js';
7
6
  import { Button, Scoped } from './kit.js';
8
7
  import { Markdown } from './markdown.js';
9
8
  import { Linked, Undelivered } from './message.js';
10
9
  import { useChat, useChatScope } from './provider.js';
11
10
  import { record, text } from './read.js';
12
- const TYPED = 'typed';
13
11
  function answerKey(conversation, interaction) {
14
- return `answer:${conversation}:${interaction}`;
12
+ return `typed:answer:${conversation}:${interaction}`;
15
13
  }
16
- function changeTyped(client, update) {
17
- return inTurn(client, async () => {
18
- const held = record(await client.presentation.read());
19
- const typed = update(record(held[TYPED]));
20
- if (typed !== null)
21
- await client.presentation.write({ ...held, [TYPED]: typed });
22
- });
23
- }
24
- export function forgetAnswers(client, conversation, interaction = '') {
14
+ export async function forgetAnswers(client, conversation, interaction = '') {
25
15
  const at = answerKey(conversation, interaction);
26
- return changeTyped(client, (typed) => {
27
- const kept = Object.entries(typed).filter(([key]) => interaction === '' ? !key.startsWith(at) : key !== at);
28
- return kept.length === Object.keys(typed).length ? null : Object.fromEntries(kept);
29
- });
16
+ const gone = Object.keys(record(await client.presentation.read())).filter((key) => interaction === '' ? key.startsWith(at) : key === at);
17
+ if (gone.length > 0)
18
+ await client.presentation.edit(Object.fromEntries(gone.map((key) => [key, null])));
30
19
  }
31
20
  function useTyped(client, key) {
32
21
  const held = useObserve(client, 'presentation');
33
- const kept = record(record(record(held.state === 'ready' ? held.value : null)[TYPED])[key]);
22
+ const kept = record(record(held.state === 'ready' ? held.value : null)[key]);
34
23
  const [local, setLocal] = useState(null);
35
24
  return [
36
25
  local !== null && local.key === key ? local.value : kept,
37
26
  (next) => {
38
27
  setLocal({ key, value: next });
39
- void changeTyped(client, (typed) => ({ ...typed, [key]: next }));
28
+ void client.presentation.edit({ [key]: next });
40
29
  },
41
30
  ];
42
31
  }