@assistant-ui/core 0.3.14 → 0.3.15

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 (137) hide show
  1. package/dist/adapters/voice.js +11 -0
  2. package/dist/adapters/voice.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/internal.d.ts +2 -1
  5. package/dist/internal.js +2 -1
  6. package/dist/model-context/frame/host.d.ts +1 -1
  7. package/dist/model-context/frame/host.d.ts.map +1 -1
  8. package/dist/model-context/frame/host.js +17 -3
  9. package/dist/model-context/frame/host.js.map +1 -1
  10. package/dist/model-context/frame/provider.d.ts +4 -0
  11. package/dist/model-context/frame/provider.d.ts.map +1 -1
  12. package/dist/model-context/frame/provider.js +50 -3
  13. package/dist/model-context/frame/provider.js.map +1 -1
  14. package/dist/model-context/frame/types.d.ts +4 -1
  15. package/dist/model-context/frame/types.d.ts.map +1 -1
  16. package/dist/model-context/frame/types.js.map +1 -1
  17. package/dist/react/client/RemoteThreadList.d.ts +1 -1
  18. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  19. package/dist/react/client/RemoteThreadList.js +95 -23
  20. package/dist/react/client/RemoteThreadList.js.map +1 -1
  21. package/dist/react/primitive-hooks/useActionBarCopy.js +7 -1
  22. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  23. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts +3 -0
  24. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
  25. package/dist/react/primitive-hooks/useThreadIsEmpty.js +3 -0
  26. package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
  27. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts +3 -0
  28. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
  29. package/dist/react/primitive-hooks/useThreadIsRunning.js +3 -0
  30. package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
  31. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -0
  32. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  33. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +6 -0
  34. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  35. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +6 -0
  36. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  37. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +192 -50
  38. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  39. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  40. package/dist/react/runtimes/RemoteThreadResource.js +2 -0
  41. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  42. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  43. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +1 -1
  44. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  45. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  46. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +38 -5
  47. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  48. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  49. package/dist/runtime/utils/message-repository.js +27 -18
  50. package/dist/runtime/utils/message-repository.js.map +1 -1
  51. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  52. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +2 -0
  53. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  54. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +102 -0
  55. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -0
  56. package/dist/runtimes/inert/InertThreadRuntimeCore.js +156 -0
  57. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -0
  58. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  59. package/dist/runtimes/local/local-thread-runtime-core.js +25 -6
  60. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  61. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +12 -60
  62. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  63. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +10 -145
  64. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  65. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts +9 -0
  66. package/dist/runtimes/remote-thread-list/adapter-changed.d.ts.map +1 -0
  67. package/dist/runtimes/remote-thread-list/adapter-changed.js +13 -0
  68. package/dist/runtimes/remote-thread-list/adapter-changed.js.map +1 -0
  69. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  70. package/dist/runtimes/remote-thread-list/empty-thread-core.js +16 -155
  71. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  72. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +2 -0
  73. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  74. package/dist/runtimes/remote-thread-list/optimistic-state.js +11 -0
  75. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  76. package/dist/runtimes/remote-thread-list/types.d.ts +3 -0
  77. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  78. package/dist/store/clients/external-thread.js +1 -1
  79. package/dist/store/clients/external-thread.js.map +1 -1
  80. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -1
  81. package/dist/store/runtime-clients/handle-runtime-action.js +2 -0
  82. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -1
  83. package/dist/types/message.d.ts +1 -1
  84. package/dist/types/message.js.map +1 -1
  85. package/dist/utils/silent-runtime-action.d.ts +6 -0
  86. package/dist/utils/silent-runtime-action.d.ts.map +1 -0
  87. package/dist/utils/silent-runtime-action.js +7 -0
  88. package/dist/utils/silent-runtime-action.js.map +1 -0
  89. package/package.json +4 -4
  90. package/src/adapters/voice.test.ts +66 -1
  91. package/src/adapters/voice.ts +8 -0
  92. package/src/internal.ts +1 -0
  93. package/src/model-context/frame/host.test.ts +64 -5
  94. package/src/model-context/frame/host.ts +16 -3
  95. package/src/model-context/frame/provider.test.ts +347 -20
  96. package/src/model-context/frame/provider.ts +58 -2
  97. package/src/model-context/frame/types.ts +5 -0
  98. package/src/react/client/RemoteThreadList.test.ts +196 -0
  99. package/src/react/client/RemoteThreadList.ts +93 -24
  100. package/src/react/primitive-hooks/useActionBarCopy.test.ts +15 -0
  101. package/src/react/primitive-hooks/useActionBarCopy.ts +13 -3
  102. package/src/react/primitive-hooks/useThreadIsEmpty.ts +3 -0
  103. package/src/react/primitive-hooks/useThreadIsRunning.ts +3 -0
  104. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +12 -0
  105. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.republish.test.ts +87 -0
  106. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +268 -63
  107. package/src/react/runtimes/RemoteThreadResource.ts +2 -0
  108. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +58 -0
  109. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +3 -1
  110. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +98 -3
  111. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +68 -6
  112. package/src/react/runtimes/useLocalRuntime.test.tsx +5 -5
  113. package/src/runtime/utils/message-repository.ts +26 -18
  114. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +4 -0
  115. package/src/runtimes/inert/InertThreadRuntimeCore.test.ts +253 -0
  116. package/src/runtimes/inert/InertThreadRuntimeCore.ts +232 -0
  117. package/src/runtimes/local/local-thread-runtime-core.test.ts +319 -0
  118. package/src/runtimes/local/local-thread-runtime-core.ts +38 -8
  119. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +17 -209
  120. package/src/runtimes/remote-thread-list/adapter-changed.ts +10 -0
  121. package/src/runtimes/remote-thread-list/empty-thread-core.ts +28 -221
  122. package/src/runtimes/remote-thread-list/optimistic-state.test.ts +18 -0
  123. package/src/runtimes/remote-thread-list/optimistic-state.ts +13 -0
  124. package/src/runtimes/remote-thread-list/types.ts +4 -0
  125. package/src/store/clients/external-thread.ts +1 -1
  126. package/src/store/runtime-clients/handle-runtime-action.test.ts +40 -0
  127. package/src/store/runtime-clients/handle-runtime-action.ts +3 -0
  128. package/src/tests/MessageRepository.test.ts +48 -0
  129. package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +2 -2
  130. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +8 -6
  131. package/src/tests/empty-thread-core.test.ts +6 -0
  132. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +20 -0
  133. package/src/tests/external-thread-isEmpty.test.tsx +100 -0
  134. package/src/tests/remote-thread-list-adapter-switch.test.ts +383 -0
  135. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +67 -0
  136. package/src/types/message.ts +1 -1
  137. package/src/utils/silent-runtime-action.ts +6 -0
@@ -1,9 +1,8 @@
1
1
  import { ThreadMessage } from "../../types/message.js";
2
- import { Unsubscribe } from "../../types/unsubscribe.js";
3
- import { ThreadRuntimeCore } from "../../runtime/interfaces/thread-runtime-core.js";
4
- import { BaseSubscribable } from "../../subscribable/subscribable.js";
2
+ import { InertThreadRuntimeCore } from "../inert/InertThreadRuntimeCore.js";
5
3
  //#region src/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts
6
- declare class ReadonlyThreadRuntimeCore extends BaseSubscribable implements ThreadRuntimeCore {
4
+ declare class ReadonlyThreadRuntimeCore extends InertThreadRuntimeCore {
5
+ protected get error(): Error;
7
6
  private _messages;
8
7
  get messages(): readonly ThreadMessage[];
9
8
  setMessages(messages: readonly ThreadMessage[]): void;
@@ -13,28 +12,12 @@ declare class ReadonlyThreadRuntimeCore extends BaseSubscribable implements Thre
13
12
  index: number;
14
13
  } | undefined;
15
14
  getBranches(messageId: string): string[];
16
- switchToBranch(): void;
17
- append(): void;
18
- deleteMessage(): void;
19
- startRun(): void;
20
- resumeRun(): void;
21
- cancelRun(): void;
22
- addToolResult(): void;
23
- resumeToolCall(): void;
24
- respondToToolApproval(): void;
25
- speak(): void;
26
- stopSpeaking(): void;
27
- connectVoice(): void;
28
- disconnectVoice(): void;
29
- getVoiceVolume: () => number;
30
- subscribeVoiceVolume: () => Unsubscribe;
31
- muteVoice(): void;
32
- unmuteVoice(): void;
33
- submitFeedback(): void;
34
- getModelContext(): {};
35
- exportExternalState(): void;
36
- importExternalState(): void;
37
- unstable_notifySessionReset(): void;
15
+ export(): {
16
+ messages: {
17
+ message: ThreadMessage;
18
+ parentId: string | null;
19
+ }[];
20
+ };
38
21
  composer: {
39
22
  attachments: never[];
40
23
  attachmentAccept: string;
@@ -65,41 +48,10 @@ declare class ReadonlyThreadRuntimeCore extends BaseSubscribable implements Thre
65
48
  subscribe(): () => void;
66
49
  unstable_on(): () => void;
67
50
  };
68
- getEditComposer(): undefined;
69
- beginEdit(): void;
70
- speech: undefined;
71
- voice: undefined;
72
- capabilities: {
73
- readonly switchToBranch: false;
74
- readonly switchBranchDuringRun: false;
75
- readonly edit: false;
76
- readonly delete: false;
77
- readonly reload: false;
78
- readonly refetchThread: false;
79
- readonly cancel: false;
80
- readonly unstable_copy: false;
81
- readonly speech: false;
82
- readonly dictation: false;
83
- readonly voice: false;
84
- readonly attachments: false;
85
- readonly feedback: false;
86
- readonly queue: false;
87
- };
88
- isDisabled: boolean;
89
- isSendDisabled: boolean;
90
51
  isLoading: boolean;
91
- state: null;
92
- suggestions: never[];
93
- extras: undefined;
94
- import(): void;
95
- export(): {
96
- messages: {
97
- message: ThreadMessage;
98
- parentId: string | null;
99
- }[];
100
- };
101
- reset(): void;
102
- unstable_on(): Unsubscribe;
52
+ cancelRun(): void;
53
+ stopSpeaking(): void;
54
+ disconnectVoice(): void;
103
55
  }
104
56
  //#endregion
105
57
  export { ReadonlyThreadRuntimeCore };
@@ -1 +1 @@
1
- {"version":3,"file":"ReadonlyThreadRuntimeCore.d.ts","names":[],"sources":["../../../src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts"],"mappings":";;;;;cASa,kCACH,4BACG;UAEH;MAEJ,qBAAQ;EAIZ,YAAY,mBAAmB;EAM/B,eAAe;;;;;EAUf,YAAY;EAMZ;EAIA;EAIA;EAIA;EAIA;EAIA;EAEA;EAIA;EAIA;EAIA;EAIA;EAEA;EAIA;EAEA;EACA,4BAA2B;EAE3B;EAIA;EAIA;EAIA;EAIA;EAIA;EAIA;EAIA;IACqB;;;;;;;;;;;;;;;;;;IAiDN;;;;;;;;;;;EA6Bf;EAIA;EAIA;EACA;EAEA;;;;;;;;;;;;;;;;EAiBA;EACA;EACA;EAEA;EACA;EACA;EAEA;EAIA;;;;;;EASA;EAIA,eAAe"}
1
+ {"version":3,"file":"ReadonlyThreadRuntimeCore.d.ts","names":[],"sources":["../../../src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts"],"mappings":";;;cAUa,kCAAkC;gBAC/B,SAAK;UAIX;MAEJ,qBAAQ;EAIZ,YAAY,mBAAmB;EAM/B,eAAe;;;;;EAUf,YAAY;EAMZ;;;;;;EASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEA;EAES;EAEA;EAEA"}
@@ -1,7 +1,10 @@
1
- import { BaseSubscribable } from "../../subscribable/subscribable.js";
1
+ import { InertThreadRuntimeCore, createInertComposer } from "../inert/InertThreadRuntimeCore.js";
2
2
  //#region src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts
3
3
  const READONLY_THREAD_ERROR = /* @__PURE__ */ new Error("This is a readonly thread. You cannot perform mutations on readonly threads.");
4
- var ReadonlyThreadRuntimeCore = class extends BaseSubscribable {
4
+ var ReadonlyThreadRuntimeCore = class extends InertThreadRuntimeCore {
5
+ get error() {
6
+ return READONLY_THREAD_ERROR;
7
+ }
5
8
  _messages = [];
6
9
  get messages() {
7
10
  return this._messages;
@@ -24,155 +27,17 @@ var ReadonlyThreadRuntimeCore = class extends BaseSubscribable {
24
27
  if (this._messages.findIndex((m) => m.id === messageId) === -1) return [];
25
28
  return [messageId];
26
29
  }
27
- switchToBranch() {
28
- throw READONLY_THREAD_ERROR;
29
- }
30
- append() {
31
- throw READONLY_THREAD_ERROR;
32
- }
33
- deleteMessage() {
34
- throw READONLY_THREAD_ERROR;
35
- }
36
- startRun() {
37
- throw READONLY_THREAD_ERROR;
38
- }
39
- resumeRun() {
40
- throw READONLY_THREAD_ERROR;
41
- }
42
- cancelRun() {}
43
- addToolResult() {
44
- throw READONLY_THREAD_ERROR;
45
- }
46
- resumeToolCall() {
47
- throw READONLY_THREAD_ERROR;
48
- }
49
- respondToToolApproval() {
50
- throw READONLY_THREAD_ERROR;
51
- }
52
- speak() {
53
- throw READONLY_THREAD_ERROR;
54
- }
55
- stopSpeaking() {}
56
- connectVoice() {
57
- throw READONLY_THREAD_ERROR;
58
- }
59
- disconnectVoice() {}
60
- getVoiceVolume = () => 0;
61
- subscribeVoiceVolume = () => () => {};
62
- muteVoice() {
63
- throw READONLY_THREAD_ERROR;
64
- }
65
- unmuteVoice() {
66
- throw READONLY_THREAD_ERROR;
67
- }
68
- submitFeedback() {
69
- throw READONLY_THREAD_ERROR;
70
- }
71
- getModelContext() {
72
- return {};
73
- }
74
- exportExternalState() {
75
- throw READONLY_THREAD_ERROR;
76
- }
77
- importExternalState() {
78
- throw READONLY_THREAD_ERROR;
79
- }
80
- unstable_notifySessionReset() {
81
- throw READONLY_THREAD_ERROR;
82
- }
83
- composer = {
84
- attachments: [],
85
- attachmentAccept: "*",
86
- async addAttachment() {
87
- throw READONLY_THREAD_ERROR;
88
- },
89
- async removeAttachment() {
90
- throw READONLY_THREAD_ERROR;
91
- },
92
- isEditing: false,
93
- canCancel: false,
94
- canSend: false,
95
- isEmpty: true,
96
- text: "",
97
- setText() {
98
- throw READONLY_THREAD_ERROR;
99
- },
100
- role: "user",
101
- setRole() {
102
- throw READONLY_THREAD_ERROR;
103
- },
104
- runConfig: {},
105
- setRunConfig() {
106
- throw READONLY_THREAD_ERROR;
107
- },
108
- async reset() {},
109
- async clearAttachments() {},
110
- send() {
111
- throw READONLY_THREAD_ERROR;
112
- },
113
- cancel() {},
114
- queue: [],
115
- moveQueueItem() {},
116
- removeQueueItem() {},
117
- dictation: void 0,
118
- startDictation() {
119
- throw READONLY_THREAD_ERROR;
120
- },
121
- stopDictation() {},
122
- quote: void 0,
123
- setQuote() {
124
- throw READONLY_THREAD_ERROR;
125
- },
126
- subscribe() {
127
- return () => {};
128
- },
129
- unstable_on() {
130
- return () => {};
131
- }
132
- };
133
- getEditComposer() {}
134
- beginEdit() {
135
- throw READONLY_THREAD_ERROR;
136
- }
137
- speech = void 0;
138
- voice = void 0;
139
- capabilities = {
140
- switchToBranch: false,
141
- switchBranchDuringRun: false,
142
- edit: false,
143
- delete: false,
144
- reload: false,
145
- refetchThread: false,
146
- cancel: false,
147
- unstable_copy: false,
148
- speech: false,
149
- dictation: false,
150
- voice: false,
151
- attachments: false,
152
- feedback: false,
153
- queue: false
154
- };
155
- isDisabled = false;
156
- isSendDisabled = false;
157
- isLoading = false;
158
- state = null;
159
- suggestions = [];
160
- extras = void 0;
161
- import() {
162
- throw READONLY_THREAD_ERROR;
163
- }
164
30
  export() {
165
31
  return { messages: this._messages.map((message, idx) => ({
166
32
  message,
167
33
  parentId: this._messages[idx - 1]?.id ?? null
168
34
  })) };
169
35
  }
170
- reset() {
171
- throw READONLY_THREAD_ERROR;
172
- }
173
- unstable_on() {
174
- return () => {};
175
- }
36
+ composer = createInertComposer(READONLY_THREAD_ERROR, false);
37
+ isLoading = false;
38
+ cancelRun() {}
39
+ stopSpeaking() {}
40
+ disconnectVoice() {}
176
41
  };
177
42
  //#endregion
178
43
  export { ReadonlyThreadRuntimeCore };
@@ -1 +1 @@
1
- {"version":3,"file":"ReadonlyThreadRuntimeCore.js","names":["Unsubscribe","ThreadMessage","ThreadRuntimeCore","BaseSubscribable","READONLY_THREAD_ERROR","Error","ReadonlyThreadRuntimeCore","_messages","messages","setMessages","_notifySubscribers","getMessageById","messageId","idx","findIndex","m","id","undefined","parentId","message","index","getBranches","switchToBranch","append","deleteMessage","startRun","resumeRun","cancelRun","addToolResult","resumeToolCall","respondToToolApproval","speak","stopSpeaking","connectVoice","disconnectVoice","getVoiceVolume","subscribeVoiceVolume","muteVoice","unmuteVoice","submitFeedback","getModelContext","exportExternalState","importExternalState","unstable_notifySessionReset","composer","attachments","attachmentAccept","addAttachment","removeAttachment","isEditing","const","canCancel","canSend","isEmpty","text","setText","role","setRole","runConfig","setRunConfig","reset","clearAttachments","send","cancel","queue","moveQueueItem","removeQueueItem","dictation","startDictation","stopDictation","quote","setQuote","subscribe","unstable_on","getEditComposer","beginEdit","speech","voice","capabilities","switchBranchDuringRun","edit","delete","reload","refetchThread","unstable_copy","feedback","isDisabled","isSendDisabled","isLoading","state","suggestions","extras","import","export","map"],"sources":["../../../src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ThreadMessage } from \"../../types/message\";\nimport type { ThreadRuntimeCore } from \"../../runtime/interfaces/thread-runtime-core\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\n\nconst READONLY_THREAD_ERROR = new Error(\n \"This is a readonly thread. You cannot perform mutations on readonly threads.\",\n);\n\nexport class ReadonlyThreadRuntimeCore\n extends BaseSubscribable\n implements ThreadRuntimeCore\n{\n private _messages: readonly ThreadMessage[] = [];\n\n get messages() {\n return this._messages;\n }\n\n setMessages(messages: readonly ThreadMessage[]) {\n if (this._messages === messages) return;\n this._messages = messages;\n this._notifySubscribers();\n }\n\n getMessageById(messageId: string) {\n const idx = this._messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return undefined;\n return {\n parentId: this._messages[idx - 1]?.id ?? null,\n message: this._messages[idx]!,\n index: idx,\n };\n }\n\n getBranches(messageId: string) {\n const idx = this._messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return [];\n return [messageId];\n }\n\n switchToBranch(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n append(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n deleteMessage(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n startRun(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n resumeRun(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n cancelRun(): void {}\n\n addToolResult(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n resumeToolCall(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n respondToToolApproval(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n speak(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n stopSpeaking(): void {}\n\n connectVoice(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n disconnectVoice(): void {}\n\n getVoiceVolume = () => 0;\n subscribeVoiceVolume = (): Unsubscribe => () => {};\n\n muteVoice(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n unmuteVoice(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n submitFeedback(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n getModelContext() {\n return {};\n }\n\n exportExternalState() {\n throw READONLY_THREAD_ERROR;\n }\n\n importExternalState(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n unstable_notifySessionReset(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n composer = {\n attachments: [] as never[],\n attachmentAccept: \"*\",\n\n async addAttachment() {\n throw READONLY_THREAD_ERROR;\n },\n\n async removeAttachment() {\n throw READONLY_THREAD_ERROR;\n },\n\n isEditing: false as const,\n canCancel: false,\n canSend: false,\n isEmpty: true,\n text: \"\",\n\n setText() {\n throw READONLY_THREAD_ERROR;\n },\n\n role: \"user\" as const,\n\n setRole() {\n throw READONLY_THREAD_ERROR;\n },\n\n runConfig: {},\n\n setRunConfig() {\n throw READONLY_THREAD_ERROR;\n },\n\n async reset() {\n // noop\n },\n\n async clearAttachments() {\n // noop\n },\n\n send() {\n throw READONLY_THREAD_ERROR;\n },\n\n cancel() {\n // noop\n },\n\n queue: [] as never[],\n moveQueueItem() {},\n removeQueueItem() {},\n\n dictation: undefined,\n\n startDictation() {\n throw READONLY_THREAD_ERROR;\n },\n\n stopDictation() {\n // noop\n },\n\n quote: undefined,\n\n setQuote() {\n throw READONLY_THREAD_ERROR;\n },\n\n subscribe() {\n return () => {};\n },\n\n unstable_on() {\n return () => {};\n },\n };\n\n getEditComposer() {\n return undefined;\n }\n\n beginEdit(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n speech = undefined;\n voice = undefined;\n\n capabilities = {\n switchToBranch: false,\n switchBranchDuringRun: false,\n edit: false,\n delete: false,\n reload: false,\n refetchThread: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n dictation: false,\n voice: false,\n attachments: false,\n feedback: false,\n queue: false,\n } as const;\n\n isDisabled = false;\n isSendDisabled = false;\n isLoading = false;\n\n state = null;\n suggestions = [] as never[];\n extras = undefined;\n\n import(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n export() {\n return {\n messages: this._messages.map((message, idx) => ({\n message,\n parentId: this._messages[idx - 1]?.id ?? null,\n })),\n };\n }\n\n reset(): void {\n throw READONLY_THREAD_ERROR;\n }\n\n unstable_on(): Unsubscribe {\n return () => {};\n }\n}\n"],"mappings":";;AAKA,MAAMI,wCAAwB,IAAIC,MAChC,8EACF;AAEA,IAAaC,4BAAb,cACUH,iBAEV;CACE,YAA8C,CAAA;CAE9C,IAAIK,WAAW;EACb,OAAO,KAAKD;CACd;CAEAE,YAAYD,UAAoC;EAC9C,IAAI,KAAKD,cAAcC,UAAU;EACjC,KAAKD,YAAYC;EACjB,KAAKE,mBAAmB;CAC1B;CAEAC,eAAeC,WAAmB;EAChC,MAAMC,MAAM,KAAKN,UAAUO,WAAWC,MAAMA,EAAEC,OAAOJ,SAAS;EAC9D,IAAIC,QAAQ,IAAI,OAAOI,KAAAA;EACvB,OAAO;GACLC,UAAU,KAAKX,UAAUM,MAAM,EAAE,EAAEG,MAAM;GACzCG,SAAS,KAAKZ,UAAUM;GACxBO,OAAOP;EACT;CACF;CAEAQ,YAAYT,WAAmB;EAE7B,IADY,KAAKL,UAAUO,WAAWC,MAAMA,EAAEC,OAAOJ,SACjDC,MAAQ,IAAI,OAAO,CAAA;EACvB,OAAO,CAACD,SAAS;CACnB;CAEAU,iBAAuB;EACrB,MAAMlB;CACR;CAEAmB,SAAe;EACb,MAAMnB;CACR;CAEAoB,gBAAsB;EACpB,MAAMpB;CACR;CAEAqB,WAAiB;EACf,MAAMrB;CACR;CAEAsB,YAAkB;EAChB,MAAMtB;CACR;CAEAuB,YAAkB,CAAC;CAEnBC,gBAAsB;EACpB,MAAMxB;CACR;CAEAyB,iBAAuB;EACrB,MAAMzB;CACR;CAEA0B,wBAA8B;EAC5B,MAAM1B;CACR;CAEA2B,QAAc;EACZ,MAAM3B;CACR;CAEA4B,eAAqB,CAAC;CAEtBC,eAAqB;EACnB,MAAM7B;CACR;CAEA8B,kBAAwB,CAAC;CAEzBC,uBAAuB;CACvBC,mCAAgD,CAAC;CAEjDC,YAAkB;EAChB,MAAMjC;CACR;CAEAkC,cAAoB;EAClB,MAAMlC;CACR;CAEAmC,iBAAuB;EACrB,MAAMnC;CACR;CAEAoC,kBAAkB;EAChB,OAAO,CAAC;CACV;CAEAC,sBAAsB;EACpB,MAAMrC;CACR;CAEAsC,sBAA4B;EAC1B,MAAMtC;CACR;CAEAuC,8BAAoC;EAClC,MAAMvC;CACR;CAEAwC,WAAW;EACTC,aAAa,CAAA;EACbC,kBAAkB;EAElB,MAAMC,gBAAgB;GACpB,MAAM3C;EACR;EAEA,MAAM4C,mBAAmB;GACvB,MAAM5C;EACR;EAEA6C,WAAW;EACXE,WAAW;EACXC,SAAS;EACTC,SAAS;EACTC,MAAM;EAENC,UAAU;GACR,MAAMnD;EACR;EAEAoD,MAAM;EAENC,UAAU;GACR,MAAMrD;EACR;EAEAsD,WAAW,CAAC;EAEZC,eAAe;GACb,MAAMvD;EACR;EAEA,MAAMwD,QAAQ,CACZ;EAGF,MAAMC,mBAAmB,CACvB;EAGFC,OAAO;GACL,MAAM1D;EACR;EAEA2D,SAAS,CACP;EAGFC,OAAO,CAAA;EACPC,gBAAgB,CAAC;EACjBC,kBAAkB,CAAC;EAEnBC,WAAWlD,KAAAA;EAEXmD,iBAAiB;GACf,MAAMhE;EACR;EAEAiE,gBAAgB,CACd;EAGFC,OAAOrD,KAAAA;EAEPsD,WAAW;GACT,MAAMnE;EACR;EAEAoE,YAAY;GACV,aAAa,CAAC;EAChB;EAEAC,cAAc;GACZ,aAAa,CAAC;EAChB;CACF;CAEAC,kBAAkB,CAElB;CAEAC,YAAkB;EAChB,MAAMvE;CACR;CAEAwE,SAAS3D,KAAAA;CACT4D,QAAQ5D,KAAAA;CAER6D,eAAe;EACbxD,gBAAgB;EAChByD,uBAAuB;EACvBC,MAAM;EACNC,QAAQ;EACRC,QAAQ;EACRC,eAAe;EACfpB,QAAQ;EACRqB,eAAe;EACfR,QAAQ;EACRT,WAAW;EACXU,OAAO;EACPhC,aAAa;EACbwC,UAAU;EACVrB,OAAO;CACT;CAEAsB,aAAa;CACbC,iBAAiB;CACjBC,YAAY;CAEZC,QAAQ;CACRC,cAAc,CAAA;CACdC,SAAS1E,KAAAA;CAET2E,SAAe;EACb,MAAMxF;CACR;CAEAyF,SAAS;EACP,OAAO,EACLrF,UAAU,KAAKD,UAAUuF,KAAK3E,SAASN,SAAS;GAC9CM;GACAD,UAAU,KAAKX,UAAUM,MAAM,EAAE,EAAEG,MAAM;EAC3C,EAAE,EACJ;CACF;CAEA4C,QAAc;EACZ,MAAMxD;CACR;CAEAqE,cAA2B;EACzB,aAAa,CAAC;CAChB;AACF"}
1
+ {"version":3,"file":"ReadonlyThreadRuntimeCore.js","names":["ThreadMessage","InertThreadRuntimeCore","createInertComposer","READONLY_THREAD_ERROR","Error","ReadonlyThreadRuntimeCore","error","_messages","messages","setMessages","_notifySubscribers","getMessageById","messageId","idx","findIndex","m","id","undefined","parentId","message","index","getBranches","export","map","composer","isLoading","cancelRun","stopSpeaking","disconnectVoice"],"sources":["../../../src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport {\n InertThreadRuntimeCore,\n createInertComposer,\n} from \"../inert/InertThreadRuntimeCore\";\n\nconst READONLY_THREAD_ERROR = new Error(\n \"This is a readonly thread. You cannot perform mutations on readonly threads.\",\n);\n\nexport class ReadonlyThreadRuntimeCore extends InertThreadRuntimeCore {\n protected get error() {\n return READONLY_THREAD_ERROR;\n }\n\n private _messages: readonly ThreadMessage[] = [];\n\n get messages() {\n return this._messages;\n }\n\n setMessages(messages: readonly ThreadMessage[]) {\n if (this._messages === messages) return;\n this._messages = messages;\n this._notifySubscribers();\n }\n\n getMessageById(messageId: string) {\n const idx = this._messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return undefined;\n return {\n parentId: this._messages[idx - 1]?.id ?? null,\n message: this._messages[idx]!,\n index: idx,\n };\n }\n\n getBranches(messageId: string) {\n const idx = this._messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return [];\n return [messageId];\n }\n\n export() {\n return {\n messages: this._messages.map((message, idx) => ({\n message,\n parentId: this._messages[idx - 1]?.id ?? null,\n })),\n };\n }\n\n composer = createInertComposer(READONLY_THREAD_ERROR, false);\n\n isLoading = false;\n\n override cancelRun(): void {}\n\n override stopSpeaking(): void {}\n\n override disconnectVoice(): void {}\n}\n"],"mappings":";;AAMA,MAAMG,wCAAwB,IAAIC,MAChC,8EACF;AAEA,IAAaC,4BAAb,cAA+CJ,uBAAuB;CACpE,IAAcK,QAAQ;EACpB,OAAOH;CACT;CAEA,YAA8C,CAAA;CAE9C,IAAIK,WAAW;EACb,OAAO,KAAKD;CACd;CAEAE,YAAYD,UAAoC;EAC9C,IAAI,KAAKD,cAAcC,UAAU;EACjC,KAAKD,YAAYC;EACjB,KAAKE,mBAAmB;CAC1B;CAEAC,eAAeC,WAAmB;EAChC,MAAMC,MAAM,KAAKN,UAAUO,WAAWC,MAAMA,EAAEC,OAAOJ,SAAS;EAC9D,IAAIC,QAAQ,IAAI,OAAOI,KAAAA;EACvB,OAAO;GACLC,UAAU,KAAKX,UAAUM,MAAM,EAAE,EAAEG,MAAM;GACzCG,SAAS,KAAKZ,UAAUM;GACxBO,OAAOP;EACT;CACF;CAEAQ,YAAYT,WAAmB;EAE7B,IADY,KAAKL,UAAUO,WAAWC,MAAMA,EAAEC,OAAOJ,SACjDC,MAAQ,IAAI,OAAO,CAAA;EACvB,OAAO,CAACD,SAAS;CACnB;CAEAU,SAAS;EACP,OAAO,EACLd,UAAU,KAAKD,UAAUgB,KAAKJ,SAASN,SAAS;GAC9CM;GACAD,UAAU,KAAKX,UAAUM,MAAM,EAAE,EAAEG,MAAM;EAC3C,EAAE,EACJ;CACF;CAEAQ,WAAWtB,oBAAoBC,uBAAuB,KAAK;CAE3DsB,YAAY;CAEZ,YAA2B,CAAC;CAE5B,eAA8B,CAAC;CAE/B,kBAAiC,CAAC;AACpC"}
@@ -0,0 +1,9 @@
1
+ import { SILENT_RUNTIME_ACTION } from "../../utils/silent-runtime-action.js";
2
+ //#region src/runtimes/remote-thread-list/adapter-changed.d.ts
3
+ declare class ThreadListAdapterChangedError extends Error {
4
+ readonly [SILENT_RUNTIME_ACTION] = true;
5
+ constructor();
6
+ }
7
+ //#endregion
8
+ export { ThreadListAdapterChangedError };
9
+ //# sourceMappingURL=adapter-changed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-changed.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/adapter-changed.ts"],"mappings":";;cAEa,sCAAsC;YACvC"}
@@ -0,0 +1,13 @@
1
+ import { SILENT_RUNTIME_ACTION } from "../../utils/silent-runtime-action.js";
2
+ //#region src/runtimes/remote-thread-list/adapter-changed.ts
3
+ var ThreadListAdapterChangedError = class extends Error {
4
+ [SILENT_RUNTIME_ACTION] = true;
5
+ constructor() {
6
+ super("Thread list adapter changed while an operation was pending.");
7
+ this.name = "ThreadListAdapterChangedError";
8
+ }
9
+ };
10
+ //#endregion
11
+ export { ThreadListAdapterChangedError };
12
+
13
+ //# sourceMappingURL=adapter-changed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-changed.js","names":["SILENT_RUNTIME_ACTION","ThreadListAdapterChangedError","Error","constructor","name"],"sources":["../../../src/runtimes/remote-thread-list/adapter-changed.ts"],"sourcesContent":["import { SILENT_RUNTIME_ACTION } from \"../../utils/silent-runtime-action\";\n\nexport class ThreadListAdapterChangedError extends Error {\n readonly [SILENT_RUNTIME_ACTION] = true;\n\n constructor() {\n super(\"Thread list adapter changed while an operation was pending.\");\n this.name = \"ThreadListAdapterChangedError\";\n }\n}\n"],"mappings":";;AAEA,IAAaC,gCAAb,cAAmDC,MAAM;CACvD,CAAUF,yBAAyB;CAEnCG,cAAc;EACZ,MAAM,6DAA6D;EACnE,KAAKC,OAAO;CACd;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"empty-thread-core.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/empty-thread-core.ts"],"mappings":";;cAKa,mBAAmB"}
1
+ {"version":3,"file":"empty-thread-core.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/empty-thread-core.ts"],"mappings":";;cA2Ca,mBAAmB"}
@@ -1,167 +1,28 @@
1
+ import { InertThreadRuntimeCore, createInertComposer } from "../inert/InertThreadRuntimeCore.js";
1
2
  //#region src/runtimes/remote-thread-list/empty-thread-core.ts
2
3
  const EMPTY_THREAD_ERROR = /* @__PURE__ */ new Error("This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.");
3
- const EMPTY_THREAD_CORE = {
4
- getMessageById() {},
4
+ var EmptyThreadRuntimeCore = class extends InertThreadRuntimeCore {
5
+ get error() {
6
+ return EMPTY_THREAD_ERROR;
7
+ }
8
+ messages = [];
9
+ composer = createInertComposer(EMPTY_THREAD_ERROR, true);
10
+ isLoading = true;
11
+ getMessageById() {}
5
12
  getBranches() {
6
13
  return [];
7
- },
8
- switchToBranch() {
9
- throw EMPTY_THREAD_ERROR;
10
- },
11
- append() {
12
- throw EMPTY_THREAD_ERROR;
13
- },
14
- deleteMessage() {
15
- throw EMPTY_THREAD_ERROR;
16
- },
17
- startRun() {
18
- throw EMPTY_THREAD_ERROR;
19
- },
20
- resumeRun() {
21
- throw EMPTY_THREAD_ERROR;
22
- },
23
- cancelRun() {
24
- throw EMPTY_THREAD_ERROR;
25
- },
26
- addToolResult() {
27
- throw EMPTY_THREAD_ERROR;
28
- },
29
- resumeToolCall() {
30
- throw EMPTY_THREAD_ERROR;
31
- },
32
- respondToToolApproval() {
33
- throw EMPTY_THREAD_ERROR;
34
- },
35
- speak() {
36
- throw EMPTY_THREAD_ERROR;
37
- },
38
- stopSpeaking() {
39
- throw EMPTY_THREAD_ERROR;
40
- },
41
- connectVoice() {
42
- throw EMPTY_THREAD_ERROR;
43
- },
44
- disconnectVoice() {
45
- throw EMPTY_THREAD_ERROR;
46
- },
47
- getVoiceVolume: () => 0,
48
- subscribeVoiceVolume: () => () => {},
49
- muteVoice() {
50
- throw EMPTY_THREAD_ERROR;
51
- },
52
- unmuteVoice() {
53
- throw EMPTY_THREAD_ERROR;
54
- },
55
- submitFeedback() {
56
- throw EMPTY_THREAD_ERROR;
57
- },
58
- getModelContext() {
59
- return {};
60
- },
61
- exportExternalState() {
62
- throw EMPTY_THREAD_ERROR;
63
- },
64
- importExternalState() {
65
- throw EMPTY_THREAD_ERROR;
66
- },
67
- unstable_notifySessionReset() {
68
- throw EMPTY_THREAD_ERROR;
69
- },
70
- composer: {
71
- attachments: [],
72
- attachmentAccept: "*",
73
- async addAttachment() {
74
- throw EMPTY_THREAD_ERROR;
75
- },
76
- async removeAttachment() {
77
- throw EMPTY_THREAD_ERROR;
78
- },
79
- isEditing: true,
80
- canCancel: false,
81
- canSend: false,
82
- isEmpty: true,
83
- text: "",
84
- setText() {
85
- throw EMPTY_THREAD_ERROR;
86
- },
87
- role: "user",
88
- setRole() {
89
- throw EMPTY_THREAD_ERROR;
90
- },
91
- runConfig: {},
92
- setRunConfig() {
93
- throw EMPTY_THREAD_ERROR;
94
- },
95
- async reset() {},
96
- async clearAttachments() {},
97
- send() {
98
- throw EMPTY_THREAD_ERROR;
99
- },
100
- cancel() {},
101
- queue: [],
102
- moveQueueItem() {},
103
- removeQueueItem() {},
104
- dictation: void 0,
105
- startDictation() {
106
- throw EMPTY_THREAD_ERROR;
107
- },
108
- stopDictation() {},
109
- quote: void 0,
110
- setQuote() {
111
- throw EMPTY_THREAD_ERROR;
112
- },
113
- subscribe() {
114
- return () => {};
115
- },
116
- unstable_on() {
117
- return () => {};
118
- }
119
- },
120
- getEditComposer() {},
121
- beginEdit() {
122
- throw EMPTY_THREAD_ERROR;
123
- },
124
- speech: void 0,
125
- voice: void 0,
126
- capabilities: {
127
- switchToBranch: false,
128
- switchBranchDuringRun: false,
129
- edit: false,
130
- delete: false,
131
- reload: false,
132
- refetchThread: false,
133
- cancel: false,
134
- unstable_copy: false,
135
- speech: false,
136
- dictation: false,
137
- voice: false,
138
- attachments: false,
139
- feedback: false,
140
- queue: false
141
- },
142
- isDisabled: false,
143
- isSendDisabled: false,
144
- isLoading: true,
145
- messages: [],
146
- state: null,
147
- suggestions: [],
148
- extras: void 0,
149
- subscribe() {
150
- return () => {};
151
- },
152
- import() {
153
- throw EMPTY_THREAD_ERROR;
154
- },
14
+ }
155
15
  export() {
156
16
  return { messages: [] };
157
- },
158
- reset() {
159
- throw EMPTY_THREAD_ERROR;
160
- },
161
- unstable_on() {
17
+ }
18
+ subscribe() {
162
19
  return () => {};
163
20
  }
21
+ waitForUpdate() {
22
+ return Promise.reject(EMPTY_THREAD_ERROR);
23
+ }
164
24
  };
25
+ const EMPTY_THREAD_CORE = new EmptyThreadRuntimeCore();
165
26
  //#endregion
166
27
  export { EMPTY_THREAD_CORE };
167
28
 
@@ -1 +1 @@
1
- {"version":3,"file":"empty-thread-core.js","names":["ThreadRuntimeCore","EMPTY_THREAD_ERROR","Error","EMPTY_THREAD_CORE","getMessageById","undefined","getBranches","switchToBranch","append","deleteMessage","startRun","resumeRun","cancelRun","addToolResult","resumeToolCall","respondToToolApproval","speak","stopSpeaking","connectVoice","disconnectVoice","getVoiceVolume","subscribeVoiceVolume","muteVoice","unmuteVoice","submitFeedback","getModelContext","exportExternalState","importExternalState","unstable_notifySessionReset","composer","attachments","attachmentAccept","addAttachment","removeAttachment","isEditing","canCancel","canSend","isEmpty","text","setText","role","setRole","runConfig","setRunConfig","reset","clearAttachments","send","cancel","queue","moveQueueItem","removeQueueItem","dictation","startDictation","stopDictation","quote","setQuote","subscribe","unstable_on","getEditComposer","beginEdit","speech","voice","capabilities","switchBranchDuringRun","edit","delete","reload","refetchThread","unstable_copy","feedback","isDisabled","isSendDisabled","isLoading","messages","state","suggestions","extras","import","export"],"sources":["../../../src/runtimes/remote-thread-list/empty-thread-core.ts"],"sourcesContent":["import type { ThreadRuntimeCore } from \"../../runtime/interfaces/thread-runtime-core\";\n\nconst EMPTY_THREAD_ERROR = new Error(\n \"This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.\",\n);\nexport const EMPTY_THREAD_CORE: ThreadRuntimeCore = {\n getMessageById() {\n return undefined;\n },\n\n getBranches() {\n return [];\n },\n\n switchToBranch() {\n throw EMPTY_THREAD_ERROR;\n },\n\n append() {\n throw EMPTY_THREAD_ERROR;\n },\n\n deleteMessage() {\n throw EMPTY_THREAD_ERROR;\n },\n\n startRun() {\n throw EMPTY_THREAD_ERROR;\n },\n\n resumeRun() {\n throw EMPTY_THREAD_ERROR;\n },\n\n cancelRun() {\n throw EMPTY_THREAD_ERROR;\n },\n\n addToolResult() {\n throw EMPTY_THREAD_ERROR;\n },\n\n resumeToolCall() {\n throw EMPTY_THREAD_ERROR;\n },\n\n respondToToolApproval() {\n throw EMPTY_THREAD_ERROR;\n },\n\n speak() {\n throw EMPTY_THREAD_ERROR;\n },\n\n stopSpeaking() {\n throw EMPTY_THREAD_ERROR;\n },\n\n connectVoice() {\n throw EMPTY_THREAD_ERROR;\n },\n\n disconnectVoice() {\n throw EMPTY_THREAD_ERROR;\n },\n\n getVoiceVolume: () => 0,\n subscribeVoiceVolume: () => () => {},\n\n muteVoice() {\n throw EMPTY_THREAD_ERROR;\n },\n\n unmuteVoice() {\n throw EMPTY_THREAD_ERROR;\n },\n\n submitFeedback() {\n throw EMPTY_THREAD_ERROR;\n },\n\n getModelContext() {\n return {};\n },\n\n exportExternalState() {\n throw EMPTY_THREAD_ERROR;\n },\n\n importExternalState() {\n throw EMPTY_THREAD_ERROR;\n },\n\n unstable_notifySessionReset() {\n throw EMPTY_THREAD_ERROR;\n },\n\n composer: {\n attachments: [],\n attachmentAccept: \"*\",\n\n async addAttachment() {\n throw EMPTY_THREAD_ERROR;\n },\n\n async removeAttachment() {\n throw EMPTY_THREAD_ERROR;\n },\n\n isEditing: true,\n\n canCancel: false,\n canSend: false,\n isEmpty: true,\n\n text: \"\",\n\n setText() {\n throw EMPTY_THREAD_ERROR;\n },\n\n role: \"user\",\n\n setRole() {\n throw EMPTY_THREAD_ERROR;\n },\n\n runConfig: {},\n\n setRunConfig() {\n throw EMPTY_THREAD_ERROR;\n },\n\n async reset() {\n // noop\n },\n\n async clearAttachments() {\n // noop\n },\n\n send() {\n throw EMPTY_THREAD_ERROR;\n },\n\n cancel() {\n // noop\n },\n\n queue: [] as never[],\n moveQueueItem() {},\n removeQueueItem() {},\n\n dictation: undefined,\n\n startDictation() {\n throw EMPTY_THREAD_ERROR;\n },\n\n stopDictation() {\n // noop\n },\n\n quote: undefined,\n\n setQuote() {\n throw EMPTY_THREAD_ERROR;\n },\n\n subscribe() {\n return () => {};\n },\n\n unstable_on() {\n return () => {};\n },\n },\n\n getEditComposer() {\n return undefined;\n },\n\n beginEdit() {\n throw EMPTY_THREAD_ERROR;\n },\n\n speech: undefined,\n voice: undefined,\n\n capabilities: {\n switchToBranch: false,\n switchBranchDuringRun: false,\n edit: false,\n delete: false,\n reload: false,\n refetchThread: false,\n cancel: false,\n unstable_copy: false,\n speech: false,\n dictation: false,\n voice: false,\n attachments: false,\n feedback: false,\n queue: false,\n },\n\n isDisabled: false,\n isSendDisabled: false,\n isLoading: true,\n\n messages: [],\n\n state: null,\n\n suggestions: [],\n\n extras: undefined,\n\n subscribe() {\n return () => {};\n },\n\n import() {\n throw EMPTY_THREAD_ERROR;\n },\n\n export() {\n return { messages: [] };\n },\n\n reset() {\n throw EMPTY_THREAD_ERROR;\n },\n\n unstable_on() {\n return () => {};\n },\n};\n"],"mappings":";AAEA,MAAMC,qCAAqB,IAAIC,MAC7B,mQACF;AACA,MAAaC,oBAAuC;CAClDC,iBAAiB,CAEjB;CAEAE,cAAc;EACZ,OAAO,CAAA;CACT;CAEAC,iBAAiB;EACf,MAAMN;CACR;CAEAO,SAAS;EACP,MAAMP;CACR;CAEAQ,gBAAgB;EACd,MAAMR;CACR;CAEAS,WAAW;EACT,MAAMT;CACR;CAEAU,YAAY;EACV,MAAMV;CACR;CAEAW,YAAY;EACV,MAAMX;CACR;CAEAY,gBAAgB;EACd,MAAMZ;CACR;CAEAa,iBAAiB;EACf,MAAMb;CACR;CAEAc,wBAAwB;EACtB,MAAMd;CACR;CAEAe,QAAQ;EACN,MAAMf;CACR;CAEAgB,eAAe;EACb,MAAMhB;CACR;CAEAiB,eAAe;EACb,MAAMjB;CACR;CAEAkB,kBAAkB;EAChB,MAAMlB;CACR;CAEAmB,sBAAsB;CACtBC,kCAAkC,CAAC;CAEnCC,YAAY;EACV,MAAMrB;CACR;CAEAsB,cAAc;EACZ,MAAMtB;CACR;CAEAuB,iBAAiB;EACf,MAAMvB;CACR;CAEAwB,kBAAkB;EAChB,OAAO,CAAC;CACV;CAEAC,sBAAsB;EACpB,MAAMzB;CACR;CAEA0B,sBAAsB;EACpB,MAAM1B;CACR;CAEA2B,8BAA8B;EAC5B,MAAM3B;CACR;CAEA4B,UAAU;EACRC,aAAa,CAAA;EACbC,kBAAkB;EAElB,MAAMC,gBAAgB;GACpB,MAAM/B;EACR;EAEA,MAAMgC,mBAAmB;GACvB,MAAMhC;EACR;EAEAiC,WAAW;EAEXC,WAAW;EACXC,SAAS;EACTC,SAAS;EAETC,MAAM;EAENC,UAAU;GACR,MAAMtC;EACR;EAEAuC,MAAM;EAENC,UAAU;GACR,MAAMxC;EACR;EAEAyC,WAAW,CAAC;EAEZC,eAAe;GACb,MAAM1C;EACR;EAEA,MAAM2C,QAAQ,CACZ;EAGF,MAAMC,mBAAmB,CACvB;EAGFC,OAAO;GACL,MAAM7C;EACR;EAEA8C,SAAS,CACP;EAGFC,OAAO,CAAA;EACPC,gBAAgB,CAAC;EACjBC,kBAAkB,CAAC;EAEnBC,WAAW9C,KAAAA;EAEX+C,iBAAiB;GACf,MAAMnD;EACR;EAEAoD,gBAAgB,CACd;EAGFC,OAAOjD,KAAAA;EAEPkD,WAAW;GACT,MAAMtD;EACR;EAEAuD,YAAY;GACV,aAAa,CAAC;EAChB;EAEAC,cAAc;GACZ,aAAa,CAAC;EAChB;CACF;CAEAC,kBAAkB,CAElB;CAEAC,YAAY;EACV,MAAM1D;CACR;CAEA2D,QAAQvD,KAAAA;CACRwD,OAAOxD,KAAAA;CAEPyD,cAAc;EACZvD,gBAAgB;EAChBwD,uBAAuB;EACvBC,MAAM;EACNC,QAAQ;EACRC,QAAQ;EACRC,eAAe;EACfpB,QAAQ;EACRqB,eAAe;EACfR,QAAQ;EACRT,WAAW;EACXU,OAAO;EACP/B,aAAa;EACbuC,UAAU;EACVrB,OAAO;CACT;CAEAsB,YAAY;CACZC,gBAAgB;CAChBC,WAAW;CAEXC,UAAU,CAAA;CAEVC,OAAO;CAEPC,aAAa,CAAA;CAEbC,QAAQvE,KAAAA;CAERmD,YAAY;EACV,aAAa,CAAC;CAChB;CAEAqB,SAAS;EACP,MAAM5E;CACR;CAEA6E,SAAS;EACP,OAAO,EAAEL,UAAU,CAAA,EAAG;CACxB;CAEA7B,QAAQ;EACN,MAAM3C;CACR;CAEAwD,cAAc;EACZ,aAAa,CAAC;CAChB;AACF"}
1
+ {"version":3,"file":"empty-thread-core.js","names":["Unsubscribe","ThreadRuntimeCore","InertThreadRuntimeCore","createInertComposer","EMPTY_THREAD_ERROR","Error","EmptyThreadRuntimeCore","error","messages","composer","isLoading","getMessageById","undefined","getBranches","export","subscribe","waitForUpdate","Promise","reject","EMPTY_THREAD_CORE"],"sources":["../../../src/runtimes/remote-thread-list/empty-thread-core.ts"],"sourcesContent":["import type { Unsubscribe } from \"../../types/unsubscribe\";\nimport type { ThreadRuntimeCore } from \"../../runtime/interfaces/thread-runtime-core\";\nimport {\n InertThreadRuntimeCore,\n createInertComposer,\n} from \"../inert/InertThreadRuntimeCore\";\n\nconst EMPTY_THREAD_ERROR = new Error(\n \"This is the empty thread, a placeholder for the main thread. You cannot perform any actions on this thread instance. This error is probably because you tried to call a thread method in your render function. Call the method inside a `useEffect` hook instead.\",\n);\n\nclass EmptyThreadRuntimeCore extends InertThreadRuntimeCore {\n protected get error() {\n return EMPTY_THREAD_ERROR;\n }\n\n messages = [] as never[];\n\n composer = createInertComposer(EMPTY_THREAD_ERROR, true);\n\n isLoading = true;\n\n getMessageById() {\n return undefined;\n }\n\n getBranches() {\n return [];\n }\n\n export() {\n return { messages: [] };\n }\n\n override subscribe(): Unsubscribe {\n return () => {};\n }\n\n override waitForUpdate(): Promise<void> {\n return Promise.reject(EMPTY_THREAD_ERROR);\n }\n}\n\nexport const EMPTY_THREAD_CORE: ThreadRuntimeCore =\n new EmptyThreadRuntimeCore();\n"],"mappings":";;AAOA,MAAMI,qCAAqB,IAAIC,MAC7B,mQACF;AAEA,IAAMC,yBAAN,cAAqCJ,uBAAuB;CAC1D,IAAcK,QAAQ;EACpB,OAAOH;CACT;CAEAI,WAAW,CAAA;CAEXC,WAAWN,oBAAoBC,oBAAoB,IAAI;CAEvDM,YAAY;CAEZC,iBAAiB,CAEjB;CAEAE,cAAc;EACZ,OAAO,CAAA;CACT;CAEAC,SAAS;EACP,OAAO,EAAEN,UAAU,CAAA,EAAG;CACxB;CAEA,YAAkC;EAChC,aAAa,CAAC;CAChB;CAEA,gBAAwC;EACtC,OAAOS,QAAQC,OAAOd,kBAAkB;CAC1C;AACF;AAEA,MAAae,oBACX,IAAIb,uBAAuB"}
@@ -20,6 +20,7 @@ declare class OptimisticState<TState> extends BaseSubscribable {
20
20
  */
21
21
  private readonly _completedOptimistics;
22
22
  private _nextTransformOrder;
23
+ private _epoch;
23
24
  private _baseValue;
24
25
  private _cachedValue;
25
26
  constructor(initialState: TState);
@@ -27,6 +28,7 @@ declare class OptimisticState<TState> extends BaseSubscribable {
27
28
  get baseValue(): TState;
28
29
  get value(): TState;
29
30
  update(state: TState): void;
31
+ reset(state: TState): void;
30
32
  optimisticUpdate<TResult>(transform: Transform<TState, TResult>): Promise<TResult>;
31
33
  }
32
34
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"optimistic-state.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/optimistic-state.ts"],"mappings":";;KAEK,UAAU,QAAQ;EACrB,eAAe,QAAQ;;EAGvB,QAAQ,OAAO,QAAQ,QAAQ,YAAY;;EAG3C,cAAc,OAAO,WAAW;;EAGhC,WAAW,OAAO,QAAQ,MAAM,QAAQ,aAAa;;cAuB1C,gBAAgB,gBAAgB;mBAC1B;;;;;;;;mBAUA;UAGT;UAEA;UACA;EAEW,YAAA,cAAc;UAMzB;MAwBG,aAAa;MAIb,SAAS;EAIb,OAAO,OAAO;EAKR,iBAAiB,SAC5B,WAAW,UAAU,QAAQ,WAC5B,QAAQ"}
1
+ {"version":3,"file":"optimistic-state.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/optimistic-state.ts"],"mappings":";;KAEK,UAAU,QAAQ;EACrB,eAAe,QAAQ;;EAGvB,QAAQ,OAAO,QAAQ,QAAQ,YAAY;;EAG3C,cAAc,OAAO,WAAW;;EAGhC,WAAW,OAAO,QAAQ,MAAM,QAAQ,aAAa;;cAuB1C,gBAAgB,gBAAgB;mBAC1B;;;;;;;;mBAUA;UAGT;UACA;UAEA;UACA;EAEW,YAAA,cAAc;UAMzB;MAwBG,aAAa;MAIb,SAAS;EAIb,OAAO,OAAO;EAKd,MAAM,OAAO;EAUP,iBAAiB,SAC5B,WAAW,UAAU,QAAQ,WAC5B,QAAQ"}
@@ -16,6 +16,7 @@ var OptimisticState = class extends BaseSubscribable {
16
16
  */
17
17
  _completedOptimistics = [];
18
18
  _nextTransformOrder = 0;
19
+ _epoch = 0;
19
20
  _baseValue;
20
21
  _cachedValue;
21
22
  constructor(initialState) {
@@ -44,7 +45,16 @@ var OptimisticState = class extends BaseSubscribable {
44
45
  this._baseValue = state;
45
46
  this._updateState();
46
47
  }
48
+ reset(state) {
49
+ this._epoch++;
50
+ this._pendingTransforms.length = 0;
51
+ this._completedOptimistics.length = 0;
52
+ this._baseValue = state;
53
+ this._cachedValue = state;
54
+ this._notifySubscribers();
55
+ }
47
56
  async optimisticUpdate(transform) {
57
+ const epoch = this._epoch;
48
58
  const order = this._nextTransformOrder++;
49
59
  const task = transform.execute();
50
60
  const pendingTransform = {
@@ -56,6 +66,7 @@ var OptimisticState = class extends BaseSubscribable {
56
66
  this._pendingTransforms.push(pendingTransform);
57
67
  this._updateState();
58
68
  const result = await task;
69
+ if (epoch !== this._epoch) return result;
59
70
  this._baseValue = pipeTransforms(this._baseValue, result, [transform.optimistic, transform.then]);
60
71
  for (const completed of this._completedOptimistics) if (transform.then || completed.order > pendingTransform.order) this._baseValue = completed.optimistic(this._baseValue);
61
72
  if (transform.optimistic) {
@@ -1 +1 @@
1
- {"version":3,"file":"optimistic-state.js","names":["BaseSubscribable","Transform","execute","Promise","TResult","then","state","TState","result","optimistic","loading","task","PendingTransform","order","CompletedOptimistic","pipeTransforms","initialState","extraParam","TExtra","transforms","extra","reduce","transform","OptimisticState","_pendingTransforms","Array","_completedOptimistics","_nextTransformOrder","_baseValue","_cachedValue","constructor","_updateState","activeTransforms","map","apply","sort","a","b","_notifySubscribers","baseValue","value","update","optimisticUpdate","pendingTransform","push","completed","index","indexOf","splice","length"],"sources":["../../../src/runtimes/remote-thread-list/optimistic-state.ts"],"sourcesContent":["import { BaseSubscribable } from \"../../subscribable/subscribable\";\n\ntype Transform<TState, TResult> = {\n execute: () => Promise<TResult>;\n\n /** transform the state after the promise resolves */\n then?: (state: TState, result: TResult) => TState;\n\n /** transform the state during resolution and afterwards */\n optimistic?: (state: TState) => TState;\n\n /** transform the state only while loading */\n loading?: (state: TState, task: Promise<TResult>) => TState;\n};\n\ntype PendingTransform<TState, TResult> = Transform<TState, TResult> & {\n order: number;\n task: Promise<TResult>;\n};\n\ntype CompletedOptimistic<TState> = {\n order: number;\n optimistic: (state: TState) => TState;\n};\n\nconst pipeTransforms = <TState, TExtra>(\n initialState: TState,\n extraParam: TExtra,\n transforms: (((state: TState, extra: TExtra) => TState) | undefined)[],\n): TState => {\n return transforms.reduce((state, transform) => {\n return transform?.(state, extraParam) ?? state;\n }, initialState);\n};\n\nexport class OptimisticState<TState> extends BaseSubscribable {\n private readonly _pendingTransforms: Array<PendingTransform<TState, any>> =\n [];\n\n /**\n * Completed optimistic callbacks remain active while any transform is\n * pending, so later state replacements cannot erase them. Invocation order\n * determines which overlapping optimistic update wins.\n *\n * Correctness requirement: `optimistic` callbacks must be idempotent.\n */\n private readonly _completedOptimistics: Array<CompletedOptimistic<TState>> =\n [];\n\n private _nextTransformOrder = 0;\n\n private _baseValue: TState;\n private _cachedValue: TState;\n\n public constructor(initialState: TState) {\n super();\n this._baseValue = initialState;\n this._cachedValue = initialState;\n }\n\n private _updateState(): void {\n const activeTransforms = [\n ...this._pendingTransforms.map((transform) => ({\n order: transform.order,\n apply: (state: TState) =>\n pipeTransforms(state, transform.task, [\n transform.loading,\n transform.optimistic,\n ]),\n })),\n ...this._completedOptimistics.map(({ order, optimistic }) => ({\n order,\n apply: optimistic,\n })),\n ].sort((a, b) => a.order - b.order);\n\n this._cachedValue = activeTransforms.reduce(\n (state, transform) => transform.apply(state),\n this._baseValue,\n );\n\n this._notifySubscribers();\n }\n\n public get baseValue(): TState {\n return this._baseValue;\n }\n\n public get value(): TState {\n return this._cachedValue;\n }\n\n public update(state: TState): void {\n this._baseValue = state;\n this._updateState();\n }\n\n public async optimisticUpdate<TResult>(\n transform: Transform<TState, TResult>,\n ): Promise<TResult> {\n const order = this._nextTransformOrder++;\n const task = transform.execute();\n const pendingTransform = {\n ...transform,\n order,\n task,\n };\n try {\n this._pendingTransforms.push(pendingTransform);\n this._updateState();\n\n const result = await task;\n this._baseValue = pipeTransforms(this._baseValue, result, [\n transform.optimistic,\n transform.then,\n ]);\n\n // `then` can replace state with a stale snapshot, so replay every\n // completed effect; otherwise replay only newer overlapping effects.\n for (const completed of this._completedOptimistics) {\n if (transform.then || completed.order > pendingTransform.order) {\n this._baseValue = completed.optimistic(this._baseValue);\n }\n }\n\n if (transform.optimistic) {\n this._completedOptimistics.push({\n order: pendingTransform.order,\n optimistic: transform.optimistic,\n });\n this._completedOptimistics.sort((a, b) => a.order - b.order);\n }\n\n return result;\n } finally {\n const index = this._pendingTransforms.indexOf(pendingTransform);\n if (index > -1) {\n this._pendingTransforms.splice(index, 1);\n }\n\n if (this._pendingTransforms.length === 0) {\n this._completedOptimistics.length = 0;\n }\n\n this._updateState();\n }\n }\n}\n"],"mappings":";;AAyBA,MAAMe,kBACJC,cACAC,YACAE,eACW;CACX,OAAOA,WAAWE,QAAQf,OAAOgB,cAAc;EAC7C,OAAOA,YAAYhB,OAAOW,UAAU,KAAKX;CAC3C,GAAGU,YAAY;AACjB;AAEA,IAAaO,kBAAb,cAA6CvB,iBAAiB;CAC5D,qBACE,CAAA;;;;;;;;CASF,wBACE,CAAA;CAEF,sBAA8B;CAE9B;CACA;CAEA,YAAmBgB,cAAsB;EACvC,MAAM;EACN,KAAKY,aAAaZ;EAClB,KAAKa,eAAeb;CACtB;CAEA,eAA6B;EAC3B,MAAMgB,mBAAmB,CACvB,GAAG,KAAKR,mBAAmBS,KAAKX,eAAe;GAC7CT,OAAOS,UAAUT;GACjBqB,QAAQ5B,UACNS,eAAeT,OAAOgB,UAAUX,MAAM,CACpCW,UAAUZ,SACVY,UAAUb,UAAU,CACrB;EACL,EAAE,GACF,GAAG,KAAKiB,sBAAsBO,KAAK,EAAEpB,OAAOJ,kBAAkB;GAC5DI;GACAqB,OAAOzB;EACT,EAAE,CAAC,CACJ,CAAC0B,MAAMC,GAAGC,MAAMD,EAAEvB,QAAQwB,EAAExB,KAAK;EAElC,KAAKgB,eAAeG,iBAAiBX,QAClCf,OAAOgB,cAAcA,UAAUY,MAAM5B,KAAK,GAC3C,KAAKsB,UACP;EAEA,KAAKU,mBAAmB;CAC1B;CAEA,IAAWC,YAAoB;EAC7B,OAAO,KAAKX;CACd;CAEA,IAAWY,QAAgB;EACzB,OAAO,KAAKX;CACd;CAEA,OAAcvB,OAAqB;EACjC,KAAKsB,aAAatB;EAClB,KAAKyB,aAAa;CACpB;CAEA,MAAaW,iBACXpB,WACkB;EAClB,MAAMT,QAAQ,KAAKc;EACnB,MAAMhB,OAAOW,UAAUpB,QAAQ;EAC/B,MAAMyC,mBAAmB;GACvB,GAAGrB;GACHT;GACAF;EACF;EACA,IAAI;GACF,KAAKa,mBAAmBoB,KAAKD,gBAAgB;GAC7C,KAAKZ,aAAa;GAElB,MAAMvB,SAAS,MAAMG;GACrB,KAAKiB,aAAab,eAAe,KAAKa,YAAYpB,QAAQ,CACxDc,UAAUb,YACVa,UAAUjB,IAAI,CACf;GAID,KAAK,MAAMwC,aAAa,KAAKnB,uBAC3B,IAAIJ,UAAUjB,QAAQwC,UAAUhC,QAAQ8B,iBAAiB9B,OACvD,KAAKe,aAAaiB,UAAUpC,WAAW,KAAKmB,UAAU;GAI1D,IAAIN,UAAUb,YAAY;IACxB,KAAKiB,sBAAsBkB,KAAK;KAC9B/B,OAAO8B,iBAAiB9B;KACxBJ,YAAYa,UAAUb;IACxB,CAAC;IACD,KAAKiB,sBAAsBS,MAAMC,GAAGC,MAAMD,EAAEvB,QAAQwB,EAAExB,KAAK;GAC7D;GAEA,OAAOL;EACT,UAAU;GACR,MAAMsC,QAAQ,KAAKtB,mBAAmBuB,QAAQJ,gBAAgB;GAC9D,IAAIG,QAAQ,IACV,KAAKtB,mBAAmBwB,OAAOF,OAAO,CAAC;GAGzC,IAAI,KAAKtB,mBAAmByB,WAAW,GACrC,KAAKvB,sBAAsBuB,SAAS;GAGtC,KAAKlB,aAAa;EACpB;CACF;AACF"}
1
+ {"version":3,"file":"optimistic-state.js","names":["BaseSubscribable","Transform","execute","Promise","TResult","then","state","TState","result","optimistic","loading","task","PendingTransform","order","CompletedOptimistic","pipeTransforms","initialState","extraParam","TExtra","transforms","extra","reduce","transform","OptimisticState","_pendingTransforms","Array","_completedOptimistics","_nextTransformOrder","_epoch","_baseValue","_cachedValue","constructor","_updateState","activeTransforms","map","apply","sort","a","b","_notifySubscribers","baseValue","value","update","reset","length","optimisticUpdate","epoch","pendingTransform","push","completed","index","indexOf","splice"],"sources":["../../../src/runtimes/remote-thread-list/optimistic-state.ts"],"sourcesContent":["import { BaseSubscribable } from \"../../subscribable/subscribable\";\n\ntype Transform<TState, TResult> = {\n execute: () => Promise<TResult>;\n\n /** transform the state after the promise resolves */\n then?: (state: TState, result: TResult) => TState;\n\n /** transform the state during resolution and afterwards */\n optimistic?: (state: TState) => TState;\n\n /** transform the state only while loading */\n loading?: (state: TState, task: Promise<TResult>) => TState;\n};\n\ntype PendingTransform<TState, TResult> = Transform<TState, TResult> & {\n order: number;\n task: Promise<TResult>;\n};\n\ntype CompletedOptimistic<TState> = {\n order: number;\n optimistic: (state: TState) => TState;\n};\n\nconst pipeTransforms = <TState, TExtra>(\n initialState: TState,\n extraParam: TExtra,\n transforms: (((state: TState, extra: TExtra) => TState) | undefined)[],\n): TState => {\n return transforms.reduce((state, transform) => {\n return transform?.(state, extraParam) ?? state;\n }, initialState);\n};\n\nexport class OptimisticState<TState> extends BaseSubscribable {\n private readonly _pendingTransforms: Array<PendingTransform<TState, any>> =\n [];\n\n /**\n * Completed optimistic callbacks remain active while any transform is\n * pending, so later state replacements cannot erase them. Invocation order\n * determines which overlapping optimistic update wins.\n *\n * Correctness requirement: `optimistic` callbacks must be idempotent.\n */\n private readonly _completedOptimistics: Array<CompletedOptimistic<TState>> =\n [];\n\n private _nextTransformOrder = 0;\n private _epoch = 0;\n\n private _baseValue: TState;\n private _cachedValue: TState;\n\n public constructor(initialState: TState) {\n super();\n this._baseValue = initialState;\n this._cachedValue = initialState;\n }\n\n private _updateState(): void {\n const activeTransforms = [\n ...this._pendingTransforms.map((transform) => ({\n order: transform.order,\n apply: (state: TState) =>\n pipeTransforms(state, transform.task, [\n transform.loading,\n transform.optimistic,\n ]),\n })),\n ...this._completedOptimistics.map(({ order, optimistic }) => ({\n order,\n apply: optimistic,\n })),\n ].sort((a, b) => a.order - b.order);\n\n this._cachedValue = activeTransforms.reduce(\n (state, transform) => transform.apply(state),\n this._baseValue,\n );\n\n this._notifySubscribers();\n }\n\n public get baseValue(): TState {\n return this._baseValue;\n }\n\n public get value(): TState {\n return this._cachedValue;\n }\n\n public update(state: TState): void {\n this._baseValue = state;\n this._updateState();\n }\n\n public reset(state: TState): void {\n // In-flight optimisticUpdate calls must not write into the replacement state.\n this._epoch++;\n this._pendingTransforms.length = 0;\n this._completedOptimistics.length = 0;\n this._baseValue = state;\n this._cachedValue = state;\n this._notifySubscribers();\n }\n\n public async optimisticUpdate<TResult>(\n transform: Transform<TState, TResult>,\n ): Promise<TResult> {\n const epoch = this._epoch;\n const order = this._nextTransformOrder++;\n const task = transform.execute();\n const pendingTransform = {\n ...transform,\n order,\n task,\n };\n try {\n this._pendingTransforms.push(pendingTransform);\n this._updateState();\n\n const result = await task;\n if (epoch !== this._epoch) return result;\n this._baseValue = pipeTransforms(this._baseValue, result, [\n transform.optimistic,\n transform.then,\n ]);\n\n // `then` can replace state with a stale snapshot, so replay every\n // completed effect; otherwise replay only newer overlapping effects.\n for (const completed of this._completedOptimistics) {\n if (transform.then || completed.order > pendingTransform.order) {\n this._baseValue = completed.optimistic(this._baseValue);\n }\n }\n\n if (transform.optimistic) {\n this._completedOptimistics.push({\n order: pendingTransform.order,\n optimistic: transform.optimistic,\n });\n this._completedOptimistics.sort((a, b) => a.order - b.order);\n }\n\n return result;\n } finally {\n const index = this._pendingTransforms.indexOf(pendingTransform);\n if (index > -1) {\n this._pendingTransforms.splice(index, 1);\n }\n\n if (this._pendingTransforms.length === 0) {\n this._completedOptimistics.length = 0;\n }\n\n this._updateState();\n }\n }\n}\n"],"mappings":";;AAyBA,MAAMe,kBACJC,cACAC,YACAE,eACW;CACX,OAAOA,WAAWE,QAAQf,OAAOgB,cAAc;EAC7C,OAAOA,YAAYhB,OAAOW,UAAU,KAAKX;CAC3C,GAAGU,YAAY;AACjB;AAEA,IAAaO,kBAAb,cAA6CvB,iBAAiB;CAC5D,qBACE,CAAA;;;;;;;;CASF,wBACE,CAAA;CAEF,sBAA8B;CAC9B,SAAiB;CAEjB;CACA;CAEA,YAAmBgB,cAAsB;EACvC,MAAM;EACN,KAAKa,aAAab;EAClB,KAAKc,eAAed;CACtB;CAEA,eAA6B;EAC3B,MAAMiB,mBAAmB,CACvB,GAAG,KAAKT,mBAAmBU,KAAKZ,eAAe;GAC7CT,OAAOS,UAAUT;GACjBsB,QAAQ7B,UACNS,eAAeT,OAAOgB,UAAUX,MAAM,CACpCW,UAAUZ,SACVY,UAAUb,UAAU,CACrB;EACL,EAAE,GACF,GAAG,KAAKiB,sBAAsBQ,KAAK,EAAErB,OAAOJ,kBAAkB;GAC5DI;GACAsB,OAAO1B;EACT,EAAE,CAAC,CACJ,CAAC2B,MAAMC,GAAGC,MAAMD,EAAExB,QAAQyB,EAAEzB,KAAK;EAElC,KAAKiB,eAAeG,iBAAiBZ,QAClCf,OAAOgB,cAAcA,UAAUa,MAAM7B,KAAK,GAC3C,KAAKuB,UACP;EAEA,KAAKU,mBAAmB;CAC1B;CAEA,IAAWC,YAAoB;EAC7B,OAAO,KAAKX;CACd;CAEA,IAAWY,QAAgB;EACzB,OAAO,KAAKX;CACd;CAEA,OAAcxB,OAAqB;EACjC,KAAKuB,aAAavB;EAClB,KAAK0B,aAAa;CACpB;CAEA,MAAa1B,OAAqB;EAEhC,KAAKsB;EACL,KAAKJ,mBAAmBoB,SAAS;EACjC,KAAKlB,sBAAsBkB,SAAS;EACpC,KAAKf,aAAavB;EAClB,KAAKwB,eAAexB;EACpB,KAAKiC,mBAAmB;CAC1B;CAEA,MAAaM,iBACXvB,WACkB;EAClB,MAAMwB,QAAQ,KAAKlB;EACnB,MAAMf,QAAQ,KAAKc;EACnB,MAAMhB,OAAOW,UAAUpB,QAAQ;EAC/B,MAAM6C,mBAAmB;GACvB,GAAGzB;GACHT;GACAF;EACF;EACA,IAAI;GACF,KAAKa,mBAAmBwB,KAAKD,gBAAgB;GAC7C,KAAKf,aAAa;GAElB,MAAMxB,SAAS,MAAMG;GACrB,IAAImC,UAAU,KAAKlB,QAAQ,OAAOpB;GAClC,KAAKqB,aAAad,eAAe,KAAKc,YAAYrB,QAAQ,CACxDc,UAAUb,YACVa,UAAUjB,IAAI,CACf;GAID,KAAK,MAAM4C,aAAa,KAAKvB,uBAC3B,IAAIJ,UAAUjB,QAAQ4C,UAAUpC,QAAQkC,iBAAiBlC,OACvD,KAAKgB,aAAaoB,UAAUxC,WAAW,KAAKoB,UAAU;GAI1D,IAAIP,UAAUb,YAAY;IACxB,KAAKiB,sBAAsBsB,KAAK;KAC9BnC,OAAOkC,iBAAiBlC;KACxBJ,YAAYa,UAAUb;IACxB,CAAC;IACD,KAAKiB,sBAAsBU,MAAMC,GAAGC,MAAMD,EAAExB,QAAQyB,EAAEzB,KAAK;GAC7D;GAEA,OAAOL;EACT,UAAU;GACR,MAAM0C,QAAQ,KAAK1B,mBAAmB2B,QAAQJ,gBAAgB;GAC9D,IAAIG,QAAQ,IACV,KAAK1B,mBAAmB4B,OAAOF,OAAO,CAAC;GAGzC,IAAI,KAAK1B,mBAAmBoB,WAAW,GACrC,KAAKlB,sBAAsBkB,SAAS;GAGtC,KAAKZ,aAAa;EACpB;CACF;AACF"}
@@ -77,6 +77,9 @@ type RemoteThreadListAdapter = {
77
77
  };
78
78
  type RemoteThreadListOptions = {
79
79
  runtimeHook: () => AssistantRuntime;
80
+ /**
81
+ * The adapter reference should remain stable across renders. Replacing it reloads the list and drops cached threads that are not in the replacement page. In-flight mutations from the previous adapter are cancelled.
82
+ */
80
83
  adapter: RemoteThreadListAdapter;
81
84
  /**
82
85
  * When provided, the runtime starts on this thread instead of creating a