@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
@@ -3,6 +3,7 @@ import { generateId } from "../../utils/id.js";
3
3
  import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-state.js";
4
4
  import { EMPTY_THREAD_CORE } from "../../runtimes/remote-thread-list/empty-thread-core.js";
5
5
  import { classifyThreads, createThreadMappingId, getThreadData, normalizeCursor, updateStatusReducer } from "../../runtimes/remote-thread-list/remote-thread-state.js";
6
+ import { ThreadListAdapterChangedError } from "../../runtimes/remote-thread-list/adapter-changed.js";
6
7
  import { useStableRuntimeAdapters } from "./useRuntimeAdapters.js";
7
8
  import { RuntimeAdapterProvider } from "./RuntimeAdapterProvider.js";
8
9
  import { isTitleSourceMessage } from "./RemoteThreadResource.js";
@@ -15,6 +16,45 @@ import { create } from "zustand";
15
16
  //#region src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx
16
17
  const threadNotFoundError = (threadIdOrRemoteId, action) => /* @__PURE__ */ new Error(`Thread "${threadIdOrRemoteId}" not found while ${action}.`);
17
18
  const threadStatusError = (threadIdOrRemoteId, status, action) => /* @__PURE__ */ new Error(`Thread "${threadIdOrRemoteId}" has status "${status}", so it cannot ${action}.`);
19
+ const EMPTY_REMOTE_STATE = {
20
+ isLoading: true,
21
+ isLoadingMore: false,
22
+ cursor: void 0,
23
+ newThreadId: void 0,
24
+ threadIds: [],
25
+ archivedThreadIds: [],
26
+ threadIdMap: {},
27
+ threadData: {}
28
+ };
29
+ const addNewThread = (state) => {
30
+ let id;
31
+ do
32
+ id = `__LOCALID_${generateId()}`;
33
+ while (state.threadIdMap[id]);
34
+ const mappingId = createThreadMappingId(id);
35
+ return {
36
+ id,
37
+ state: {
38
+ ...state,
39
+ newThreadId: id,
40
+ threadIdMap: {
41
+ ...state.threadIdMap,
42
+ [id]: mappingId
43
+ },
44
+ threadData: {
45
+ ...state.threadData,
46
+ [mappingId]: {
47
+ status: "new",
48
+ id,
49
+ remoteId: void 0,
50
+ externalId: void 0,
51
+ title: void 0,
52
+ custom: void 0
53
+ }
54
+ }
55
+ }
56
+ };
57
+ };
18
58
  var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
19
59
  _options;
20
60
  _hookManager;
@@ -22,19 +62,13 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
22
62
  _loadThreadsPromise;
23
63
  _loadMorePromise;
24
64
  _loadGeneration = 0;
65
+ _adapterGeneration = 0;
66
+ _replaceListOnNextLoad = false;
67
+ _staleThreadIdsOnReplace;
25
68
  _switchGeneration = 0;
26
69
  _switchTask;
27
70
  _mainThreadId;
28
- _state = new OptimisticState({
29
- isLoading: true,
30
- isLoadingMore: false,
31
- cursor: void 0,
32
- newThreadId: void 0,
33
- threadIds: [],
34
- archivedThreadIds: [],
35
- threadIdMap: {},
36
- threadData: {}
37
- });
71
+ _state = new OptimisticState(EMPTY_REMOTE_STATE);
38
72
  _useAdaptersProvider = ({ children }) => {
39
73
  const useAdapters = this._options.adapter.unstable_useAdapters;
40
74
  if (useAdapters === void 0) return children;
@@ -62,6 +96,7 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
62
96
  getLoadThreadsPromise() {
63
97
  if (!this._loadThreadsPromise) {
64
98
  const generation = this._loadGeneration;
99
+ let replacedList = false;
65
100
  this._loadThreadsPromise = this._state.optimisticUpdate({
66
101
  execute: () => this._options.adapter.list(),
67
102
  loading: (state) => {
@@ -72,6 +107,11 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
72
107
  },
73
108
  then: (state, l) => {
74
109
  if (generation !== this._loadGeneration) return state;
110
+ if (this._replaceListOnNextLoad) {
111
+ this._replaceListOnNextLoad = false;
112
+ replacedList = true;
113
+ return this._replaceWithThreads(state, l.threads, normalizeCursor(l.nextCursor));
114
+ }
75
115
  const fresh = classifyThreads(l.threads, {
76
116
  threadIds: [],
77
117
  archivedThreadIds: [],
@@ -98,11 +138,23 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
98
138
  if (generation !== this._loadGeneration) return;
99
139
  console.error("[assistant-ui] thread list load failed:", error);
100
140
  this._loadThreadsPromise = void 0;
101
- this._state.update({
102
- ...this._state.baseValue,
103
- isLoading: false
104
- });
105
- }).then(() => {});
141
+ if (!this._replaceListOnNextLoad) {
142
+ this._state.update({
143
+ ...this._state.baseValue,
144
+ isLoading: false
145
+ });
146
+ return;
147
+ }
148
+ this._replaceListOnNextLoad = false;
149
+ replacedList = true;
150
+ this._state.update(this._replaceWithThreads(this._state.baseValue, [], void 0));
151
+ }).then(() => {
152
+ if (!replacedList) return;
153
+ const threadId = this._options.threadId;
154
+ if (threadId === void 0) return;
155
+ if (this.getItemById(threadId)?.id === this._mainThreadId) return;
156
+ this._switchToThreadFromProp(threadId).catch(() => {});
157
+ });
106
158
  }
107
159
  return this._loadThreadsPromise;
108
160
  }
@@ -139,6 +191,7 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
139
191
  };
140
192
  }
141
193
  }).catch((error) => {
194
+ if (generation !== this._loadGeneration) return;
142
195
  console.error("[assistant-ui] thread list loadMore failed:", error);
143
196
  }).then(() => {
144
197
  if (this._loadMorePromise === dedup) this._loadMorePromise = void 0;
@@ -156,6 +209,9 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
156
209
  this._hookManager = new RemoteThreadListHookInstanceManager(options.runtimeHook, this);
157
210
  this._hookManager.__internal_setDefaultAdapters(this._runtimeAdapters);
158
211
  this._hookManager.__internal_subscribeRunningChanged(() => this._notifySubscribers());
212
+ this._hookManager.__internal_subscribeRuntimeReplaced(() => {
213
+ queueMicrotask(() => this._notifySubscribers());
214
+ });
159
215
  this.useProvider = create(() => ({ Provider: this.resolveProvider(options.adapter) }));
160
216
  this.__internal_setOptions(options);
161
217
  this.switchToNewThread();
@@ -172,8 +228,13 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
172
228
  this._hookManager.setRuntimeHook(options.runtimeHook);
173
229
  if (adapterChanged) {
174
230
  this._loadGeneration++;
231
+ this._adapterGeneration++;
232
+ this._switchGeneration++;
233
+ this._switchTask = void 0;
175
234
  this._loadThreadsPromise = void 0;
176
235
  this._loadMorePromise = void 0;
236
+ this._replaceListOnNextLoad = true;
237
+ this._staleThreadIdsOnReplace = new Set(Object.values(this._state.baseValue.threadData).filter((item) => item.status !== "new").map((item) => item.id));
177
238
  this._state.update({
178
239
  ...this._state.baseValue,
179
240
  cursor: void 0
@@ -181,6 +242,71 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
181
242
  }
182
243
  if (controlledThreadIdChanged) this._switchToThreadFromProp(options.threadId).catch(() => {});
183
244
  }
245
+ _requireAdapterGeneration(generation) {
246
+ if (generation !== this._adapterGeneration) throw new ThreadListAdapterChangedError();
247
+ }
248
+ _requireAdapterSettled() {
249
+ if (this._replaceListOnNextLoad) throw new ThreadListAdapterChangedError();
250
+ }
251
+ _replaceWithThreads(state, threads, cursor) {
252
+ const fresh = classifyThreads(threads, {
253
+ threadIds: [],
254
+ archivedThreadIds: [],
255
+ threadIdMap: {},
256
+ threadData: {}
257
+ });
258
+ const threadIdMap = { ...fresh.threadIdMap };
259
+ const threadData = { ...fresh.threadData };
260
+ const threadIds = [...fresh.threadIds];
261
+ const archivedThreadIds = [...fresh.archivedThreadIds];
262
+ if (state.newThreadId) {
263
+ const mappingId = state.threadIdMap[state.newThreadId];
264
+ const draft = mappingId ? state.threadData[mappingId] : void 0;
265
+ if (draft?.status === "new") {
266
+ threadIdMap[state.newThreadId] = mappingId;
267
+ threadData[mappingId] = draft;
268
+ }
269
+ }
270
+ const stale = this._staleThreadIdsOnReplace;
271
+ if (stale) for (const item of Object.values(state.threadData)) {
272
+ if (stale.has(item.id)) continue;
273
+ if (item.status !== "new" && item.remoteId === void 0) continue;
274
+ const mappingId = createThreadMappingId(item.id);
275
+ if (threadData[mappingId]) continue;
276
+ threadIdMap[item.id] = mappingId;
277
+ if (item.remoteId !== void 0) threadIdMap[item.remoteId] = mappingId;
278
+ threadData[mappingId] = item;
279
+ if (item.remoteId === void 0) continue;
280
+ if (item.status === "regular" && !threadIds.includes(item.remoteId)) threadIds.push(item.remoteId);
281
+ else if (item.status === "archived" && !archivedThreadIds.includes(item.remoteId)) archivedThreadIds.push(item.remoteId);
282
+ }
283
+ this._staleThreadIdsOnReplace = void 0;
284
+ let nextState = {
285
+ ...state,
286
+ isLoading: false,
287
+ cursor,
288
+ threadIds,
289
+ archivedThreadIds,
290
+ threadIdMap,
291
+ threadData,
292
+ newThreadId: state.newThreadId !== void 0 && threadIdMap[state.newThreadId] === void 0 ? void 0 : state.newThreadId
293
+ };
294
+ if (getThreadData(nextState, this._mainThreadId) === void 0) {
295
+ const preservedDraft = nextState.newThreadId;
296
+ if (preservedDraft !== void 0) this._mainThreadId = preservedDraft;
297
+ else {
298
+ const seeded = addNewThread(nextState);
299
+ this._mainThreadId = seeded.id;
300
+ nextState = seeded.state;
301
+ }
302
+ if (this._options.threadId === void 0) this._notifyThreadIdChange();
303
+ else this._lastNotifiedThreadId = void 0;
304
+ }
305
+ const nextIds = new Set(Object.values(nextState.threadData).map((item) => item.id));
306
+ for (const item of Object.values(state.threadData)) if (!nextIds.has(item.id)) this._hookManager.stopThreadRuntime(item.id);
307
+ this._hookManager.startThreadRuntime(this._mainThreadId).then(() => this._notifySubscribers(), () => void 0);
308
+ return nextState;
309
+ }
184
310
  __internal_load() {
185
311
  this.getLoadThreadsPromise();
186
312
  if (this._initialThreadLoaded) return;
@@ -275,6 +401,7 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
275
401
  return task;
276
402
  }
277
403
  async _switchToThread(threadIdOrRemoteId, options, generation, emitThreadIdChange) {
404
+ if (this._replaceListOnNextLoad && threadIdOrRemoteId !== this._state.value.newThreadId) throw new ThreadListAdapterChangedError();
278
405
  let data = this.getItemById(threadIdOrRemoteId);
279
406
  if (!data) {
280
407
  const remoteMetadata = await this._options.adapter.fetch(threadIdOrRemoteId);
@@ -350,38 +477,22 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
350
477
  const state = this._state.baseValue;
351
478
  let id = this._state.value.newThreadId;
352
479
  if (id === void 0) {
353
- do
354
- id = `__LOCALID_${generateId()}`;
355
- while (state.threadIdMap[id]);
356
- const mappingId = createThreadMappingId(id);
357
- this._state.update({
358
- ...state,
359
- newThreadId: id,
360
- threadIdMap: {
361
- ...state.threadIdMap,
362
- [id]: mappingId
363
- },
364
- threadData: {
365
- ...state.threadData,
366
- [mappingId]: {
367
- status: "new",
368
- id,
369
- remoteId: void 0,
370
- externalId: void 0,
371
- title: void 0,
372
- custom: void 0
373
- }
374
- }
375
- });
480
+ const next = addNewThread(state);
481
+ id = next.id;
482
+ this._state.update(next.state);
376
483
  }
377
484
  return this._switchToThread(id, void 0, generation, emitThreadIdChange);
378
485
  }
379
486
  initialize = async (threadId) => {
487
+ const adapter = this._options.adapter;
488
+ const adapterGeneration = this._adapterGeneration;
380
489
  if (this._state.value.newThreadId !== threadId) {
490
+ this._requireAdapterSettled();
381
491
  const data = this.getItemById(threadId);
382
492
  if (!data) throw threadNotFoundError(threadId, "initializing it");
383
493
  if (data.status === "new") throw threadStatusError(threadId, data.status, "be initialized here");
384
494
  const { remoteId, externalId } = await data.initializeTask;
495
+ this._requireAdapterGeneration(adapterGeneration);
385
496
  return {
386
497
  remoteId,
387
498
  externalId
@@ -389,7 +500,8 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
389
500
  }
390
501
  const { remoteId, externalId } = await this._state.optimisticUpdate({
391
502
  execute: () => {
392
- return this._options.adapter.initialize(threadId);
503
+ this._requireAdapterGeneration(adapterGeneration);
504
+ return adapter.initialize(threadId);
393
505
  },
394
506
  optimistic: (state) => {
395
507
  return updateStatusReducer(state, threadId, "regular");
@@ -408,6 +520,7 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
408
520
  };
409
521
  },
410
522
  then: (state, { remoteId, externalId }) => {
523
+ if (adapterGeneration !== this._adapterGeneration) return state;
411
524
  const data = getThreadData(state, threadId);
412
525
  if (!data) return state;
413
526
  const mappingId = createThreadMappingId(threadId);
@@ -432,22 +545,28 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
432
545
  };
433
546
  }
434
547
  });
548
+ this._requireAdapterGeneration(adapterGeneration);
435
549
  return {
436
550
  remoteId,
437
551
  externalId
438
552
  };
439
553
  };
440
554
  generateTitle = async (threadId) => {
555
+ this._requireAdapterSettled();
556
+ const adapter = this._options.adapter;
557
+ const adapterGeneration = this._adapterGeneration;
441
558
  const data = this.getItemById(threadId);
442
559
  if (!data) throw threadNotFoundError(threadId, "generating its title");
443
560
  if (data.status === "new") throw threadStatusError(threadId, data.status, "generate a title");
444
561
  const { remoteId } = await data.initializeTask;
562
+ this._requireAdapterGeneration(adapterGeneration);
445
563
  const runtimeCore = this._hookManager.getThreadRuntimeCore(data.id);
446
564
  if (!runtimeCore) return;
447
565
  const messages = runtimeCore.messages.filter(isTitleSourceMessage);
448
- const stream = await this._options.adapter.generateTitle(remoteId, messages);
566
+ const stream = await adapter.generateTitle(remoteId, messages);
449
567
  const messageStream = AssistantMessageStream.fromAssistantStream(stream);
450
568
  for await (const result of messageStream) {
569
+ if (adapterGeneration !== this._adapterGeneration) return;
451
570
  const newTitle = result.parts.filter((c) => c.type === "text")[0]?.text;
452
571
  const state = this._state.baseValue;
453
572
  const currentData = getThreadData(state, data.id);
@@ -464,14 +583,18 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
464
583
  });
465
584
  }
466
585
  };
467
- rename(threadIdOrRemoteId, newTitle) {
586
+ async rename(threadIdOrRemoteId, newTitle) {
587
+ this._requireAdapterSettled();
588
+ const adapter = this._options.adapter;
589
+ const adapterGeneration = this._adapterGeneration;
468
590
  const data = this.getItemById(threadIdOrRemoteId);
469
591
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "renaming it");
470
592
  if (data.status === "new") throw threadStatusError(threadIdOrRemoteId, data.status, "be renamed");
471
593
  return this._state.optimisticUpdate({
472
594
  execute: async () => {
473
595
  const { remoteId } = await data.initializeTask;
474
- return this._options.adapter.rename(remoteId, newTitle);
596
+ this._requireAdapterGeneration(adapterGeneration);
597
+ return adapter.rename(remoteId, newTitle);
475
598
  },
476
599
  optimistic: (state) => {
477
600
  const data = getThreadData(state, threadIdOrRemoteId);
@@ -489,15 +612,18 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
489
612
  }
490
613
  });
491
614
  }
492
- updateCustom(threadIdOrRemoteId, custom) {
615
+ async updateCustom(threadIdOrRemoteId, custom) {
616
+ this._requireAdapterSettled();
617
+ const adapter = this._options.adapter;
618
+ const adapterGeneration = this._adapterGeneration;
493
619
  const data = this.getItemById(threadIdOrRemoteId);
494
620
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "updating its custom metadata");
495
621
  if (data.status === "new") throw threadStatusError(threadIdOrRemoteId, data.status, "update custom metadata");
496
- if (!this._options.adapter.updateCustom) throw new Error("Remote thread list adapter does not support updating custom metadata");
622
+ if (!adapter.updateCustom) throw new Error("Remote thread list adapter does not support updating custom metadata");
497
623
  return this._state.optimisticUpdate({
498
624
  execute: async () => {
499
625
  const { remoteId } = await data.initializeTask;
500
- const adapter = this._options.adapter;
626
+ this._requireAdapterGeneration(adapterGeneration);
501
627
  if (!adapter.updateCustom) throw new Error("Remote thread list adapter does not support updating custom metadata");
502
628
  return adapter.updateCustom(remoteId, custom);
503
629
  },
@@ -533,21 +659,29 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
533
659
  }
534
660
  }
535
661
  async archive(threadIdOrRemoteId) {
662
+ this._requireAdapterSettled();
663
+ const adapter = this._options.adapter;
664
+ const adapterGeneration = this._adapterGeneration;
536
665
  const data = this.getItemById(threadIdOrRemoteId);
537
666
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "archiving it");
538
667
  if (data.status !== "regular") throw threadStatusError(threadIdOrRemoteId, data.status, "be archived");
539
668
  await this._ensureThreadIsNotMain(data.id);
669
+ this._requireAdapterGeneration(adapterGeneration);
540
670
  return this._state.optimisticUpdate({
541
671
  execute: async () => {
542
672
  const { remoteId } = await data.initializeTask;
543
- return this._options.adapter.archive(remoteId);
673
+ this._requireAdapterGeneration(adapterGeneration);
674
+ return adapter.archive(remoteId);
544
675
  },
545
676
  optimistic: (state) => {
546
677
  return updateStatusReducer(state, data.id, "archived");
547
678
  }
548
679
  });
549
680
  }
550
- unarchive(threadIdOrRemoteId) {
681
+ async unarchive(threadIdOrRemoteId) {
682
+ this._requireAdapterSettled();
683
+ const adapter = this._options.adapter;
684
+ const adapterGeneration = this._adapterGeneration;
551
685
  const data = this.getItemById(threadIdOrRemoteId);
552
686
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "unarchiving it");
553
687
  if (data.status !== "archived") throw threadStatusError(threadIdOrRemoteId, data.status, "be unarchived");
@@ -555,9 +689,10 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
555
689
  execute: async () => {
556
690
  try {
557
691
  const { remoteId } = await data.initializeTask;
558
- return await this._options.adapter.unarchive(remoteId);
692
+ this._requireAdapterGeneration(adapterGeneration);
693
+ return await adapter.unarchive(remoteId);
559
694
  } catch (error) {
560
- await this._ensureThreadIsNotMain(data.id);
695
+ if (adapterGeneration === this._adapterGeneration) await this._ensureThreadIsNotMain(data.id);
561
696
  throw error;
562
697
  }
563
698
  },
@@ -567,15 +702,20 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
567
702
  });
568
703
  }
569
704
  async delete(threadIdOrRemoteId) {
705
+ this._requireAdapterSettled();
706
+ const adapter = this._options.adapter;
707
+ const adapterGeneration = this._adapterGeneration;
570
708
  const data = this.getItemById(threadIdOrRemoteId);
571
709
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "deleting it");
572
710
  if (data.status !== "regular" && data.status !== "archived") throw threadStatusError(threadIdOrRemoteId, data.status, "be deleted");
573
711
  await this._ensureThreadIsNotMain(data.id);
712
+ this._requireAdapterGeneration(adapterGeneration);
574
713
  this._hookManager.stopThreadRuntime(data.id);
575
714
  return this._state.optimisticUpdate({
576
715
  execute: async () => {
577
716
  const { remoteId } = await data.initializeTask;
578
- return await this._options.adapter.delete(remoteId);
717
+ this._requireAdapterGeneration(adapterGeneration);
718
+ return await adapter.delete(remoteId);
579
719
  },
580
720
  optimistic: (state) => {
581
721
  return updateStatusReducer(state, data.id, "deleted");
@@ -586,10 +726,12 @@ var RemoteThreadListThreadListRuntimeCore = class extends BaseSubscribable {
586
726
  this._hookManager.__internal_dispose();
587
727
  }
588
728
  async detach(threadIdOrRemoteId) {
729
+ const adapterGeneration = this._adapterGeneration;
589
730
  const data = this.getItemById(threadIdOrRemoteId);
590
731
  if (!data) throw threadNotFoundError(threadIdOrRemoteId, "detaching it");
591
732
  if (data.status !== "regular" && data.status !== "archived") throw threadStatusError(threadIdOrRemoteId, data.status, "be detached");
592
733
  await this._ensureThreadIsNotMain(data.id);
734
+ this._requireAdapterGeneration(adapterGeneration);
593
735
  this._hookManager.stopThreadRuntime(data.id);
594
736
  }
595
737
  useBoundIds = create(() => []);