@assistant-ui/react 0.7.23 → 0.7.25

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 (231) hide show
  1. package/dist/api/AssistantRuntime.d.ts +1 -1
  2. package/dist/api/AssistantRuntime.d.ts.map +1 -1
  3. package/dist/api/AssistantRuntime.js +1 -1
  4. package/dist/api/AssistantRuntime.js.map +1 -1
  5. package/dist/api/AssistantRuntime.mjs +1 -1
  6. package/dist/api/AssistantRuntime.mjs.map +1 -1
  7. package/dist/api/ComposerRuntime.d.ts +4 -2
  8. package/dist/api/ComposerRuntime.d.ts.map +1 -1
  9. package/dist/api/ComposerRuntime.js +6 -1
  10. package/dist/api/ComposerRuntime.js.map +1 -1
  11. package/dist/api/ComposerRuntime.mjs +6 -1
  12. package/dist/api/ComposerRuntime.mjs.map +1 -1
  13. package/dist/api/ThreadListItemRuntime.d.ts +3 -1
  14. package/dist/api/ThreadListItemRuntime.d.ts.map +1 -1
  15. package/dist/api/ThreadListItemRuntime.js.map +1 -1
  16. package/dist/api/ThreadListItemRuntime.mjs.map +1 -1
  17. package/dist/api/ThreadListRuntime.d.ts +8 -8
  18. package/dist/api/ThreadListRuntime.d.ts.map +1 -1
  19. package/dist/api/ThreadListRuntime.js +7 -5
  20. package/dist/api/ThreadListRuntime.js.map +1 -1
  21. package/dist/api/ThreadListRuntime.mjs +7 -5
  22. package/dist/api/ThreadListRuntime.mjs.map +1 -1
  23. package/dist/api/ThreadRuntime.d.ts +59 -32
  24. package/dist/api/ThreadRuntime.d.ts.map +1 -1
  25. package/dist/api/ThreadRuntime.js +2 -2
  26. package/dist/api/ThreadRuntime.js.map +1 -1
  27. package/dist/api/ThreadRuntime.mjs +2 -2
  28. package/dist/api/ThreadRuntime.mjs.map +1 -1
  29. package/dist/context/providers/AssistantRuntimeProvider.d.ts.map +1 -1
  30. package/dist/context/providers/AssistantRuntimeProvider.js +8 -3
  31. package/dist/context/providers/AssistantRuntimeProvider.js.map +1 -1
  32. package/dist/context/providers/AssistantRuntimeProvider.mjs +8 -3
  33. package/dist/context/providers/AssistantRuntimeProvider.mjs.map +1 -1
  34. package/dist/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  35. package/dist/primitives/threadList/ThreadListItems.js +2 -4
  36. package/dist/primitives/threadList/ThreadListItems.js.map +1 -1
  37. package/dist/primitives/threadList/ThreadListItems.mjs +2 -4
  38. package/dist/primitives/threadList/ThreadListItems.mjs.map +1 -1
  39. package/dist/runtimes/composer/BaseComposerRuntimeCore.d.ts +6 -6
  40. package/dist/runtimes/composer/BaseComposerRuntimeCore.d.ts.map +1 -1
  41. package/dist/runtimes/composer/BaseComposerRuntimeCore.js +29 -20
  42. package/dist/runtimes/composer/BaseComposerRuntimeCore.js.map +1 -1
  43. package/dist/runtimes/composer/BaseComposerRuntimeCore.mjs +29 -20
  44. package/dist/runtimes/composer/BaseComposerRuntimeCore.mjs.map +1 -1
  45. package/dist/runtimes/composer/DefaultEditComposerRuntimeCore.d.ts.map +1 -1
  46. package/dist/runtimes/composer/DefaultEditComposerRuntimeCore.js +2 -3
  47. package/dist/runtimes/composer/DefaultEditComposerRuntimeCore.js.map +1 -1
  48. package/dist/runtimes/composer/DefaultEditComposerRuntimeCore.mjs +2 -3
  49. package/dist/runtimes/composer/DefaultEditComposerRuntimeCore.mjs.map +1 -1
  50. package/dist/runtimes/composer/DefaultThreadComposerRuntimeCore.js +1 -1
  51. package/dist/runtimes/composer/DefaultThreadComposerRuntimeCore.js.map +1 -1
  52. package/dist/runtimes/composer/DefaultThreadComposerRuntimeCore.mjs +1 -1
  53. package/dist/runtimes/composer/DefaultThreadComposerRuntimeCore.mjs.map +1 -1
  54. package/dist/runtimes/core/AssistantRuntimeCore.d.ts +2 -0
  55. package/dist/runtimes/core/AssistantRuntimeCore.d.ts.map +1 -1
  56. package/dist/runtimes/core/AssistantRuntimeCore.js.map +1 -1
  57. package/dist/runtimes/core/ComposerRuntimeCore.d.ts +2 -1
  58. package/dist/runtimes/core/ComposerRuntimeCore.d.ts.map +1 -1
  59. package/dist/runtimes/core/ComposerRuntimeCore.js.map +1 -1
  60. package/dist/runtimes/core/ThreadListRuntimeCore.d.ts +4 -1
  61. package/dist/runtimes/core/ThreadListRuntimeCore.d.ts.map +1 -1
  62. package/dist/runtimes/core/ThreadListRuntimeCore.js.map +1 -1
  63. package/dist/runtimes/external-store/ExternalStoreAdapter.d.ts +1 -1
  64. package/dist/runtimes/external-store/ExternalStoreAdapter.d.ts.map +1 -1
  65. package/dist/runtimes/external-store/ExternalStoreAdapter.js.map +1 -1
  66. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.d.ts +1 -0
  67. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.d.ts.map +1 -1
  68. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.js +5 -1
  69. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.js.map +1 -1
  70. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.mjs +5 -1
  71. package/dist/runtimes/external-store/ExternalStoreThreadListRuntimeCore.mjs.map +1 -1
  72. package/dist/runtimes/index.d.ts +5 -4
  73. package/dist/runtimes/index.d.ts.map +1 -1
  74. package/dist/runtimes/index.js +11 -9
  75. package/dist/runtimes/index.js.map +1 -1
  76. package/dist/runtimes/index.mjs +5 -4
  77. package/dist/runtimes/index.mjs.map +1 -1
  78. package/dist/runtimes/local/LocalThreadListRuntimeCore.d.ts +2 -1
  79. package/dist/runtimes/local/LocalThreadListRuntimeCore.d.ts.map +1 -1
  80. package/dist/runtimes/local/LocalThreadListRuntimeCore.js +12 -8
  81. package/dist/runtimes/local/LocalThreadListRuntimeCore.js.map +1 -1
  82. package/dist/runtimes/local/LocalThreadListRuntimeCore.mjs +12 -8
  83. package/dist/runtimes/local/LocalThreadListRuntimeCore.mjs.map +1 -1
  84. package/dist/runtimes/remote-thread-list/BaseSubscribable.d.ts +8 -0
  85. package/dist/runtimes/remote-thread-list/BaseSubscribable.d.ts.map +1 -0
  86. package/dist/runtimes/remote-thread-list/BaseSubscribable.js +62 -0
  87. package/dist/runtimes/remote-thread-list/BaseSubscribable.js.map +1 -0
  88. package/dist/runtimes/remote-thread-list/BaseSubscribable.mjs +37 -0
  89. package/dist/runtimes/remote-thread-list/BaseSubscribable.mjs.map +1 -0
  90. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.d.ts +3 -0
  91. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +1 -0
  92. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.js +150 -0
  93. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.js.map +1 -0
  94. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.mjs +125 -0
  95. package/dist/runtimes/remote-thread-list/EMPTY_THREAD_CORE.mjs.map +1 -0
  96. package/dist/runtimes/remote-thread-list/OptimisticState.d.ts +23 -0
  97. package/dist/runtimes/remote-thread-list/OptimisticState.d.ts.map +1 -0
  98. package/dist/runtimes/remote-thread-list/OptimisticState.js +83 -0
  99. package/dist/runtimes/remote-thread-list/OptimisticState.js.map +1 -0
  100. package/dist/runtimes/remote-thread-list/OptimisticState.mjs +58 -0
  101. package/dist/runtimes/remote-thread-list/OptimisticState.mjs.map +1 -0
  102. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +75 -0
  103. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -0
  104. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.js +127 -0
  105. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.js.map +1 -0
  106. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.mjs +102 -0
  107. package/dist/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.mjs.map +1 -0
  108. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +76 -0
  109. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -0
  110. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +396 -0
  111. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js.map +1 -0
  112. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.mjs +371 -0
  113. package/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.mjs.map +1 -0
  114. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.d.ts +7 -0
  115. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.d.ts.map +1 -0
  116. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.js +39 -0
  117. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.js.map +1 -0
  118. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.mjs +14 -0
  119. package/dist/runtimes/remote-thread-list/cloud/AssistantCloud.mjs.map +1 -0
  120. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.d.ts +19 -0
  121. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.d.ts.map +1 -0
  122. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.js +79 -0
  123. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.js.map +1 -0
  124. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.mjs +57 -0
  125. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAPI.mjs.map +1 -0
  126. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.d.ts +20 -0
  127. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.d.ts.map +1 -0
  128. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.js +95 -0
  129. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.js.map +1 -0
  130. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.mjs +69 -0
  131. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.mjs.map +1 -0
  132. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.d.ts +46 -0
  133. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.d.ts.map +1 -0
  134. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.js +50 -0
  135. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.js.map +1 -0
  136. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.mjs +25 -0
  137. package/dist/runtimes/remote-thread-list/cloud/AssistantCloudThreads.mjs.map +1 -0
  138. package/dist/runtimes/remote-thread-list/cloud/CloudContext.d.ts +10 -0
  139. package/dist/runtimes/remote-thread-list/cloud/CloudContext.d.ts.map +1 -0
  140. package/dist/runtimes/remote-thread-list/cloud/CloudContext.js +32 -0
  141. package/dist/runtimes/remote-thread-list/cloud/CloudContext.js.map +1 -0
  142. package/dist/runtimes/remote-thread-list/cloud/CloudContext.mjs +7 -0
  143. package/dist/runtimes/remote-thread-list/cloud/CloudContext.mjs.map +1 -0
  144. package/dist/runtimes/remote-thread-list/cloud/index.d.ts +4 -0
  145. package/dist/runtimes/remote-thread-list/cloud/index.d.ts.map +1 -0
  146. package/dist/runtimes/remote-thread-list/cloud/index.js +37 -0
  147. package/dist/runtimes/remote-thread-list/cloud/index.js.map +1 -0
  148. package/dist/runtimes/remote-thread-list/cloud/index.mjs +10 -0
  149. package/dist/runtimes/remote-thread-list/cloud/index.mjs.map +1 -0
  150. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.d.ts +4 -0
  151. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.d.ts.map +1 -0
  152. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.js +46 -0
  153. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.js.map +1 -0
  154. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.mjs +22 -0
  155. package/dist/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.mjs.map +1 -0
  156. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.d.ts +14 -0
  157. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  158. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.js +103 -0
  159. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.js.map +1 -0
  160. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.mjs +79 -0
  161. package/dist/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.mjs.map +1 -0
  162. package/dist/runtimes/remote-thread-list/index.d.ts +2 -0
  163. package/dist/runtimes/remote-thread-list/index.d.ts.map +1 -0
  164. package/dist/runtimes/remote-thread-list/index.js +25 -0
  165. package/dist/runtimes/remote-thread-list/index.js.map +1 -0
  166. package/dist/runtimes/remote-thread-list/index.mjs +3 -0
  167. package/dist/runtimes/remote-thread-list/index.mjs.map +1 -0
  168. package/dist/runtimes/remote-thread-list/types.d.ts +25 -0
  169. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -0
  170. package/dist/runtimes/remote-thread-list/types.js +19 -0
  171. package/dist/runtimes/remote-thread-list/types.js.map +1 -0
  172. package/dist/runtimes/remote-thread-list/types.mjs +1 -0
  173. package/dist/runtimes/remote-thread-list/types.mjs.map +1 -0
  174. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.d.ts +3 -0
  175. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.d.ts.map +1 -0
  176. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.js +51 -0
  177. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.js.map +1 -0
  178. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.mjs +26 -0
  179. package/dist/runtimes/remote-thread-list/useRemoteThreadListRuntime.mjs.map +1 -0
  180. package/dist/styles/index.css +2 -0
  181. package/dist/styles/index.css.map +1 -1
  182. package/dist/styles/tailwindcss/thread.css +5 -1
  183. package/dist/styles/tailwindcss/thread.css.json +4 -1
  184. package/dist/ui/attachment-ui.d.ts.map +1 -1
  185. package/dist/ui/attachment-ui.js +12 -7
  186. package/dist/ui/attachment-ui.js.map +1 -1
  187. package/dist/ui/attachment-ui.mjs +12 -7
  188. package/dist/ui/attachment-ui.mjs.map +1 -1
  189. package/dist/utils/createActionButton.d.ts +2 -2
  190. package/dist/utils/createActionButton.d.ts.map +1 -1
  191. package/dist/utils/createActionButton.js +2 -4
  192. package/dist/utils/createActionButton.js.map +1 -1
  193. package/dist/utils/createActionButton.mjs +5 -5
  194. package/dist/utils/createActionButton.mjs.map +1 -1
  195. package/package.json +3 -3
  196. package/src/api/AssistantRuntime.ts +2 -6
  197. package/src/api/ComposerRuntime.ts +10 -2
  198. package/src/api/ThreadListItemRuntime.ts +3 -1
  199. package/src/api/ThreadListRuntime.ts +11 -9
  200. package/src/api/ThreadRuntime.ts +3 -3
  201. package/src/context/providers/AssistantRuntimeProvider.tsx +21 -6
  202. package/src/primitives/threadList/ThreadListItems.tsx +3 -5
  203. package/src/runtimes/composer/BaseComposerRuntimeCore.tsx +43 -25
  204. package/src/runtimes/composer/DefaultEditComposerRuntimeCore.tsx +2 -3
  205. package/src/runtimes/composer/DefaultThreadComposerRuntimeCore.tsx +1 -1
  206. package/src/runtimes/core/AssistantRuntimeCore.tsx +3 -0
  207. package/src/runtimes/core/ComposerRuntimeCore.tsx +2 -1
  208. package/src/runtimes/core/ThreadListRuntimeCore.tsx +5 -2
  209. package/src/runtimes/external-store/ExternalStoreAdapter.tsx +1 -1
  210. package/src/runtimes/external-store/ExternalStoreThreadListRuntimeCore.tsx +6 -1
  211. package/src/runtimes/index.ts +5 -4
  212. package/src/runtimes/local/LocalThreadListRuntimeCore.tsx +14 -9
  213. package/src/runtimes/remote-thread-list/BaseSubscribable.tsx +38 -0
  214. package/src/runtimes/remote-thread-list/EMPTY_THREAD_CORE.tsx +158 -0
  215. package/src/runtimes/remote-thread-list/OptimisticState.ts +82 -0
  216. package/src/runtimes/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +132 -0
  217. package/src/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +486 -0
  218. package/src/runtimes/remote-thread-list/cloud/AssistantCloud.tsx +11 -0
  219. package/src/runtimes/remote-thread-list/cloud/AssistantCloudAPI.tsx +81 -0
  220. package/src/runtimes/remote-thread-list/cloud/AssistantCloudAuthStrategy.tsx +95 -0
  221. package/src/runtimes/remote-thread-list/cloud/AssistantCloudThreads.tsx +72 -0
  222. package/src/runtimes/remote-thread-list/cloud/CloudContext.tsx +12 -0
  223. package/src/runtimes/remote-thread-list/cloud/index.ts +3 -0
  224. package/src/runtimes/remote-thread-list/cloud/useCloudGetOrCreateThread.tsx +19 -0
  225. package/src/runtimes/remote-thread-list/cloud/useCloudThreadListRuntime.tsx +100 -0
  226. package/src/runtimes/remote-thread-list/index.ts +2 -0
  227. package/src/runtimes/remote-thread-list/types.tsx +34 -0
  228. package/src/runtimes/remote-thread-list/useRemoteThreadListRuntime.tsx +28 -0
  229. package/src/styles/tailwindcss/thread.css +5 -1
  230. package/src/ui/attachment-ui.tsx +20 -14
  231. package/src/utils/createActionButton.tsx +11 -6
@@ -0,0 +1,486 @@
1
+ import { ThreadListRuntimeCore } from "../core/ThreadListRuntimeCore";
2
+ import { generateId } from "../../internal";
3
+ import { RemoteThreadListAdapter } from "./types";
4
+ import { RemoteThreadListHookInstanceManager } from "./RemoteThreadListHookInstanceManager";
5
+ import { BaseSubscribable } from "./BaseSubscribable";
6
+ import { EMPTY_THREAD_CORE } from "./EMPTY_THREAD_CORE";
7
+ import { OptimisticState } from "./OptimisticState";
8
+ import { FC, PropsWithChildren, useEffect, useId } from "react";
9
+ import { create } from "zustand";
10
+ import { CloudInitializeResponse } from "./cloud/CloudContext";
11
+
12
+ type RemoteThreadData =
13
+ | {
14
+ readonly threadId: string;
15
+ readonly remoteId?: undefined;
16
+ readonly externalId?: undefined;
17
+ readonly status: "new";
18
+ readonly title: undefined;
19
+ }
20
+ | {
21
+ readonly threadId: string;
22
+ readonly remoteId: string;
23
+ readonly externalId: string | undefined;
24
+ readonly status: "regular" | "archived";
25
+ readonly title?: string | undefined;
26
+ };
27
+
28
+ const DEFAULT_RENDER_COMPONENT: FC<PropsWithChildren> = ({ children }) => {
29
+ return children;
30
+ };
31
+
32
+ type THREAD_MAPPING_ID = string & { __brand: "THREAD_MAPPING_ID" };
33
+ function createThreadMappingId(id: string): THREAD_MAPPING_ID {
34
+ return id as THREAD_MAPPING_ID;
35
+ }
36
+
37
+ type RemoteThreadState = {
38
+ readonly isLoading: boolean;
39
+ readonly newThreadId: string | undefined;
40
+ readonly threadIds: readonly string[];
41
+ readonly archivedThreadIds: readonly string[];
42
+ readonly threadIdMap: Readonly<Record<string, THREAD_MAPPING_ID>>;
43
+ readonly threadData: Readonly<Record<THREAD_MAPPING_ID, RemoteThreadData>>;
44
+ };
45
+
46
+ const getThreadData = (
47
+ state: RemoteThreadState,
48
+ threadIdOrRemoteId: string,
49
+ ) => {
50
+ const idx = state.threadIdMap[threadIdOrRemoteId];
51
+ if (idx === undefined) return undefined;
52
+ return state.threadData[idx];
53
+ };
54
+
55
+ const updateStatusReducer = (
56
+ state: RemoteThreadState,
57
+ threadIdOrRemoteId: string,
58
+ newStatus: "regular" | "archived" | "deleted",
59
+ ) => {
60
+ const data = getThreadData(state, threadIdOrRemoteId);
61
+ if (!data) return state;
62
+
63
+ const { threadId, remoteId, status: lastStatus } = data;
64
+ if (lastStatus === newStatus) return state;
65
+
66
+ const newState = { ...state };
67
+
68
+ // lastStatus
69
+ switch (lastStatus) {
70
+ case "new":
71
+ newState.newThreadId = undefined;
72
+ break;
73
+ case "regular":
74
+ newState.threadIds = newState.threadIds.filter((t) => t !== threadId);
75
+ break;
76
+ case "archived":
77
+ newState.archivedThreadIds = newState.archivedThreadIds.filter(
78
+ (t) => t !== threadId,
79
+ );
80
+ break;
81
+
82
+ default: {
83
+ const _exhaustiveCheck: never = lastStatus;
84
+ throw new Error(`Unsupported state: ${_exhaustiveCheck}`);
85
+ }
86
+ }
87
+
88
+ // newStatus
89
+ switch (newStatus) {
90
+ case "regular":
91
+ newState.threadIds = [...newState.threadIds, threadId];
92
+ break;
93
+
94
+ case "archived":
95
+ newState.archivedThreadIds = [...newState.archivedThreadIds, threadId];
96
+ break;
97
+
98
+ case "deleted":
99
+ newState.threadData = Object.fromEntries(
100
+ Object.entries(newState.threadData).filter(([key]) => key !== threadId),
101
+ );
102
+ newState.threadIdMap = Object.fromEntries(
103
+ Object.entries(newState.threadIdMap).filter(
104
+ ([key]) => key !== threadId && key !== remoteId,
105
+ ),
106
+ );
107
+ break;
108
+
109
+ default: {
110
+ const _exhaustiveCheck: never = newStatus;
111
+ throw new Error(`Unsupported state: ${_exhaustiveCheck}`);
112
+ }
113
+ }
114
+
115
+ if (newStatus !== "deleted") {
116
+ newState.threadData = {
117
+ ...newState.threadData,
118
+ [threadId]: {
119
+ ...data,
120
+ status: newStatus,
121
+ },
122
+ };
123
+ }
124
+
125
+ return newState;
126
+ };
127
+
128
+ export class RemoteThreadListThreadListRuntimeCore
129
+ extends BaseSubscribable
130
+ implements ThreadListRuntimeCore
131
+ {
132
+ private _adapter!: RemoteThreadListAdapter;
133
+ private _disposeOldAdapter?: () => void;
134
+ private readonly _hookManager: RemoteThreadListHookInstanceManager;
135
+
136
+ private readonly _loadThreadsPromise: Promise<void>;
137
+
138
+ private _mainThreadId!: string;
139
+ private readonly _state = new OptimisticState<RemoteThreadState>({
140
+ isLoading: false,
141
+ newThreadId: undefined,
142
+ threadIds: [],
143
+ archivedThreadIds: [],
144
+ threadIdMap: {},
145
+ threadData: {},
146
+ });
147
+
148
+ public getLoadThreadsPromise() {
149
+ return this._loadThreadsPromise;
150
+ }
151
+
152
+ constructor(adapter: RemoteThreadListAdapter) {
153
+ super();
154
+
155
+ this._state.subscribe(() => this._notifySubscribers());
156
+ this._hookManager = new RemoteThreadListHookInstanceManager(
157
+ adapter.runtimeHook,
158
+ );
159
+ this.useRenderComponent = create(() => ({
160
+ RenderComponent:
161
+ adapter.__internal_RenderComponent ?? DEFAULT_RENDER_COMPONENT,
162
+ }));
163
+ this.__internal_setAdapter(adapter);
164
+
165
+ this._loadThreadsPromise = this._state
166
+ .optimisticUpdate({
167
+ execute: () => adapter.list(),
168
+ loading: (state) => {
169
+ return {
170
+ ...state,
171
+ isLoading: true,
172
+ };
173
+ },
174
+ then: (state, l) => {
175
+ const newThreadIds = [];
176
+ const newArchivedThreadIds = [];
177
+ const newThreadIdMap = {} as Record<string, THREAD_MAPPING_ID>;
178
+ const newThreadData = {} as Record<
179
+ THREAD_MAPPING_ID,
180
+ RemoteThreadData
181
+ >;
182
+
183
+ for (const thread of l.threads) {
184
+ switch (thread.status) {
185
+ case "regular":
186
+ newThreadIds.push(thread.remoteId);
187
+ break;
188
+ case "archived":
189
+ newArchivedThreadIds.push(thread.remoteId);
190
+ break;
191
+ default: {
192
+ const _exhaustiveCheck: never = thread.status;
193
+ throw new Error(`Unsupported state: ${_exhaustiveCheck}`);
194
+ }
195
+ }
196
+
197
+ const mappingId = createThreadMappingId(thread.remoteId);
198
+ newThreadIdMap[thread.remoteId] = mappingId;
199
+ newThreadData[mappingId] = {
200
+ threadId: thread.remoteId,
201
+ remoteId: thread.remoteId,
202
+ externalId: thread.externalId,
203
+ status: thread.status,
204
+ title: thread.title,
205
+ };
206
+ }
207
+
208
+ return {
209
+ ...state,
210
+ threadIds: newThreadIds,
211
+ archivedThreadIds: newArchivedThreadIds,
212
+ threadIdMap: {
213
+ ...state.threadIdMap,
214
+ ...newThreadIdMap,
215
+ },
216
+ threadData: {
217
+ ...state.threadData,
218
+ ...newThreadData,
219
+ },
220
+ };
221
+ },
222
+ })
223
+ .then(() => {});
224
+
225
+ this.switchToNewThread();
226
+ }
227
+
228
+ private useRenderComponent;
229
+
230
+ public __internal_setAdapter(adapter: RemoteThreadListAdapter) {
231
+ if (this._adapter === adapter) return;
232
+
233
+ this._adapter = adapter;
234
+ this._disposeOldAdapter?.();
235
+ this._disposeOldAdapter = this._adapter.onInitialize(this._onInitialize);
236
+
237
+ const RenderComponent =
238
+ adapter.__internal_RenderComponent ?? DEFAULT_RENDER_COMPONENT;
239
+ if (
240
+ RenderComponent !== this.useRenderComponent.getState().RenderComponent
241
+ ) {
242
+ this.useRenderComponent.setState({ RenderComponent }, true);
243
+ }
244
+
245
+ this._hookManager.setRuntimeHook(adapter.runtimeHook);
246
+ }
247
+
248
+ public get threadIds() {
249
+ return this._state.value.threadIds;
250
+ }
251
+
252
+ public get archivedThreadIds() {
253
+ return this._state.value.archivedThreadIds;
254
+ }
255
+
256
+ public get newThreadId() {
257
+ return this._state.value.newThreadId;
258
+ }
259
+
260
+ public get mainThreadId(): string {
261
+ return this._mainThreadId;
262
+ }
263
+
264
+ public getMainThreadRuntimeCore() {
265
+ const result = this._hookManager.getThreadRuntimeCore(this._mainThreadId);
266
+ if (!result) return EMPTY_THREAD_CORE;
267
+ return result;
268
+ }
269
+
270
+ public getItemById(threadIdOrRemoteId: string) {
271
+ return getThreadData(this._state.value, threadIdOrRemoteId);
272
+ }
273
+
274
+ public async switchToThread(threadIdOrRemoteId: string): Promise<void> {
275
+ const data = this.getItemById(threadIdOrRemoteId);
276
+ if (!data) throw new Error("Thread not found");
277
+
278
+ if (this._mainThreadId === data.threadId) return;
279
+
280
+ const task = this._hookManager.startThreadRuntime(data.threadId);
281
+ if (this.mainThreadId !== undefined) {
282
+ await task;
283
+ } else {
284
+ task.then(() => this._notifySubscribers());
285
+ }
286
+
287
+ if (data.status === "archived") await this.unarchive(data.threadId);
288
+ this._mainThreadId = data.threadId;
289
+
290
+ this._notifySubscribers();
291
+ }
292
+
293
+ public async switchToNewThread(): Promise<void> {
294
+ // an initialization transaction is in progress, wait for it to settle
295
+ while (
296
+ this._state.baseValue.newThreadId !== undefined &&
297
+ this._state.value.newThreadId === undefined
298
+ ) {
299
+ await this._state.waitForUpdate();
300
+ }
301
+
302
+ const state = this._state.value;
303
+ let threadId: string | undefined = this._state.value.newThreadId;
304
+ if (threadId === undefined) {
305
+ do {
306
+ threadId = `__LOCALID_${generateId()}`;
307
+ } while (state.threadIdMap[threadId]);
308
+
309
+ const mappingId = createThreadMappingId(threadId);
310
+ this._state.update({
311
+ ...state,
312
+ newThreadId: threadId,
313
+ threadIdMap: {
314
+ ...state.threadIdMap,
315
+ [threadId]: mappingId,
316
+ },
317
+ threadData: {
318
+ ...state.threadData,
319
+ [threadId]: {
320
+ status: "new",
321
+ threadId,
322
+ },
323
+ },
324
+ });
325
+ }
326
+
327
+ return this.switchToThread(threadId);
328
+ }
329
+
330
+ private _onInitialize = async (task: Promise<CloudInitializeResponse>) => {
331
+ const threadId = this._state.value.newThreadId;
332
+ if (!threadId)
333
+ throw new Error(
334
+ "ThreadListAdapter called onInitialize before switching to new thread",
335
+ );
336
+
337
+ await this._state.optimisticUpdate({
338
+ execute: () => {
339
+ return task;
340
+ },
341
+ optimistic: (state) => {
342
+ return updateStatusReducer(state, threadId, "regular");
343
+ },
344
+ then: (state, { remoteId, externalId }) => {
345
+ const data = getThreadData(state, threadId);
346
+ if (!data) return state;
347
+
348
+ const mappingId = createThreadMappingId(remoteId);
349
+ return {
350
+ ...state,
351
+ threadIdMap: {
352
+ ...state.threadIdMap,
353
+ [remoteId]: mappingId,
354
+ },
355
+ threadData: {
356
+ ...state.threadData,
357
+ [threadId]: {
358
+ ...data,
359
+ remoteId,
360
+ externalId,
361
+ },
362
+ },
363
+ };
364
+ },
365
+ });
366
+ };
367
+
368
+ public rename(threadIdOrRemoteId: string, newTitle: string): Promise<void> {
369
+ const data = this.getItemById(threadIdOrRemoteId);
370
+ if (!data) throw new Error("Thread not found");
371
+ if (data.status === "new") throw new Error("Thread is not yet initialized");
372
+
373
+ return this._state.optimisticUpdate({
374
+ execute: () => {
375
+ return this._adapter.rename(data.remoteId, newTitle);
376
+ },
377
+ optimistic: (state) => {
378
+ const data = getThreadData(state, threadIdOrRemoteId);
379
+ if (!data) return state;
380
+
381
+ return {
382
+ ...state,
383
+ threadData: {
384
+ ...state.threadData,
385
+ [data.threadId]: {
386
+ ...data,
387
+ title: newTitle,
388
+ },
389
+ },
390
+ };
391
+ },
392
+ });
393
+ }
394
+
395
+ private async _ensureThreadIsNotMain(threadId: string) {
396
+ // if thread is main thread, switch to another thread
397
+ if (threadId === this._mainThreadId) {
398
+ const lastThreadId = this._state.value.threadIds[0];
399
+ if (lastThreadId) {
400
+ await this.switchToThread(lastThreadId);
401
+ } else {
402
+ await this.switchToNewThread();
403
+ }
404
+ }
405
+ }
406
+
407
+ public async archive(threadIdOrRemoteId: string) {
408
+ const data = this.getItemById(threadIdOrRemoteId);
409
+ if (!data) throw new Error("Thread not found");
410
+ if (data.status !== "regular")
411
+ throw new Error("Thread is not yet initialized or already archived");
412
+
413
+ return this._state.optimisticUpdate({
414
+ execute: async () => {
415
+ await this._ensureThreadIsNotMain(data.threadId);
416
+ return this._adapter.archive(data.remoteId);
417
+ },
418
+ optimistic: (state) => {
419
+ return updateStatusReducer(state, data.threadId, "archived");
420
+ },
421
+ });
422
+ }
423
+
424
+ public unarchive(threadIdOrRemoteId: string): Promise<void> {
425
+ const data = this.getItemById(threadIdOrRemoteId);
426
+ if (!data) throw new Error("Thread not found");
427
+ if (data.status !== "archived") throw new Error("Thread is not archived");
428
+
429
+ return this._state.optimisticUpdate({
430
+ execute: async () => {
431
+ try {
432
+ return await this._adapter.unarchive(data.remoteId);
433
+ } catch (error) {
434
+ await this._ensureThreadIsNotMain(data.threadId);
435
+ throw error;
436
+ }
437
+ },
438
+ optimistic: (state) => {
439
+ return updateStatusReducer(state, data.threadId, "regular");
440
+ },
441
+ });
442
+ }
443
+
444
+ public async delete(threadIdOrRemoteId: string) {
445
+ const data = this.getItemById(threadIdOrRemoteId);
446
+ if (!data) throw new Error("Thread not found");
447
+ if (data.status !== "regular" && data.status !== "archived")
448
+ throw new Error("Thread is not yet initialized");
449
+
450
+ return this._state.optimisticUpdate({
451
+ execute: async () => {
452
+ await this._ensureThreadIsNotMain(data.threadId);
453
+ return await this._adapter.delete(data.remoteId);
454
+ },
455
+ optimistic: (state) => {
456
+ return updateStatusReducer(state, data.threadId, "deleted");
457
+ },
458
+ });
459
+ }
460
+
461
+ private useBoundIds = create<string[]>(() => []);
462
+
463
+ public __internal_RenderComponent: FC<PropsWithChildren> = ({ children }) => {
464
+ const id = useId();
465
+ useEffect(() => {
466
+ this.useBoundIds.setState((s) => [...s, id], true);
467
+ return () => {
468
+ this.useBoundIds.setState((s) => s.filter((i) => i !== id), true);
469
+ };
470
+ }, []);
471
+
472
+ const boundIds = this.useBoundIds();
473
+ const { RenderComponent } = this.useRenderComponent();
474
+
475
+ return (
476
+ <RenderComponent>
477
+ {(boundIds.length === 0 || boundIds[0] === id) && (
478
+ // only render if the component is the first one mounted
479
+ <this._hookManager.__internal_RenderThreadRuntimes />
480
+ )}
481
+
482
+ {children}
483
+ </RenderComponent>
484
+ );
485
+ };
486
+ }
@@ -0,0 +1,11 @@
1
+ import { AssistantCloudAPI, AssistantCloudConfig } from "./AssistantCloudAPI";
2
+ import { AssistantCloudThreads } from "./AssistantCloudThreads";
3
+
4
+ export class AssistantCloud {
5
+ public readonly threads;
6
+
7
+ constructor(config: AssistantCloudConfig) {
8
+ const api = new AssistantCloudAPI(config);
9
+ this.threads = new AssistantCloudThreads(api);
10
+ }
11
+ }
@@ -0,0 +1,81 @@
1
+ import {
2
+ AssistantCloudAuthStrategy,
3
+ AssistantCloudJWTAuthStrategy,
4
+ AssistantCloudAPIKeyAuthStrategy,
5
+ } from "./AssistantCloudAuthStrategy";
6
+
7
+ export type AssistantCloudConfig =
8
+ | {
9
+ baseUrl: string;
10
+ // TODO use baseUrl to construct the projectId
11
+ unstable_projectId: string;
12
+ authToken(): Promise<string>;
13
+ }
14
+ | {
15
+ apiKey: string;
16
+ workspaceId: string;
17
+ };
18
+
19
+ export class AssistantCloudAPI {
20
+ private _tokenManager: AssistantCloudAuthStrategy;
21
+ private _baseUrl;
22
+
23
+ constructor(config: AssistantCloudConfig) {
24
+ if ("authToken" in config) {
25
+ this._baseUrl = config.baseUrl;
26
+ this._tokenManager = new AssistantCloudJWTAuthStrategy(
27
+ config.unstable_projectId,
28
+ config.authToken,
29
+ );
30
+ } else {
31
+ this._baseUrl = "https://api.assistant-ui.com";
32
+ this._tokenManager = new AssistantCloudAPIKeyAuthStrategy(
33
+ config.apiKey,
34
+ config.workspaceId,
35
+ );
36
+ }
37
+ }
38
+
39
+ public async makeRequest(
40
+ endpoint: string,
41
+ options: {
42
+ method?: "POST" | "PUT" | "DELETE" | undefined;
43
+ query?: Record<string, string | number | boolean> | undefined;
44
+ body?: object | undefined;
45
+ } = {},
46
+ ) {
47
+ const authHeaders = await this._tokenManager.getAuthHeaders();
48
+ const headers = {
49
+ ...authHeaders,
50
+ "Content-Type": "application/json",
51
+ };
52
+
53
+ const queryParams = new URLSearchParams();
54
+ if (options.query) {
55
+ for (const [key, value] of Object.entries(options.query)) {
56
+ if (value === false) continue;
57
+ if (value === true) {
58
+ queryParams.set(key, "true");
59
+ } else {
60
+ queryParams.set(key, value.toString());
61
+ }
62
+ }
63
+ }
64
+
65
+ const url = new URL(`${this._baseUrl}${endpoint}`);
66
+ url.search = queryParams.toString();
67
+
68
+ const response = await fetch(url, {
69
+ method: options.method ?? "GET",
70
+ headers,
71
+ body: options.body ? JSON.stringify(options.body) : null,
72
+ });
73
+
74
+ if (!response.ok) {
75
+ // TODO better error handling
76
+ throw new Error(`Request failed with status ${response.status}`);
77
+ }
78
+
79
+ return response.json();
80
+ }
81
+ }
@@ -0,0 +1,95 @@
1
+ export type AssistantCloudAuthStrategy = {
2
+ readonly strategy: "jwt" | "api-key";
3
+ getAuthHeaders(): Promise<Record<string, string>>;
4
+ };
5
+
6
+ export class AssistantCloudJWTAuthStrategy
7
+ implements AssistantCloudAuthStrategy
8
+ {
9
+ public readonly strategy = "jwt";
10
+
11
+ private cachedToken: string | null = null;
12
+ private tokenExpiry: number | null = null;
13
+
14
+ #projectId;
15
+ #authTokenCallback;
16
+
17
+ constructor(projectId: string, authTokenCallback: () => Promise<string>) {
18
+ this.#projectId = projectId;
19
+ this.#authTokenCallback = authTokenCallback;
20
+ }
21
+
22
+ private getJwtExpiry(jwt: string): number {
23
+ try {
24
+ const bodyPart = jwt.split(".").at(1);
25
+ if (!bodyPart) {
26
+ throw new Error("Invalid JWT format");
27
+ }
28
+
29
+ // Base64Url decode
30
+ const payload = Buffer.from(
31
+ bodyPart.replace(/-/g, "+").replace(/_/g, "/"),
32
+ "base64",
33
+ ).toString();
34
+ const payloadObj = JSON.parse(payload);
35
+
36
+ const exp = payloadObj.exp;
37
+ if (!exp || typeof exp !== "number") {
38
+ throw new Error('JWT does not contain a valid "exp" field');
39
+ }
40
+
41
+ // Convert exp to milliseconds
42
+ return exp * 1000;
43
+ } catch (error) {
44
+ throw new Error("Unable to determine the token expiry " + error);
45
+ }
46
+ }
47
+
48
+ public async getAuthHeaders(): Promise<Record<string, string>> {
49
+ const currentTime = Date.now();
50
+
51
+ // Check if the cached token is valid for at least 30 seconds
52
+ if (
53
+ this.cachedToken &&
54
+ this.tokenExpiry &&
55
+ this.tokenExpiry - currentTime > 30 * 1000 // 30 seconds
56
+ ) {
57
+ return {
58
+ Authorization: `Bearer ${this.cachedToken}`,
59
+ "Aui-Project-Id": this.#projectId,
60
+ };
61
+ }
62
+
63
+ // Fetch a new token
64
+ const newToken = await this.#authTokenCallback();
65
+ const expiry = this.getJwtExpiry(newToken);
66
+
67
+ this.cachedToken = newToken;
68
+ this.tokenExpiry = expiry;
69
+
70
+ return {
71
+ Authorization: `Bearer ${newToken}`,
72
+ "Aui-Project-Id": this.#projectId,
73
+ };
74
+ }
75
+ }
76
+ export class AssistantCloudAPIKeyAuthStrategy
77
+ implements AssistantCloudAuthStrategy
78
+ {
79
+ public readonly strategy = "api-key";
80
+
81
+ #apiKey;
82
+ #workspaceId;
83
+
84
+ constructor(apiKey: string, workspaceId: string) {
85
+ this.#apiKey = apiKey;
86
+ this.#workspaceId = workspaceId;
87
+ }
88
+
89
+ public async getAuthHeaders(): Promise<Record<string, string>> {
90
+ return {
91
+ Authorization: `Bearer ${this.#apiKey}`,
92
+ "Aui-Workspace-Id": this.#workspaceId,
93
+ };
94
+ }
95
+ }