@assistant-ui/react 0.7.23 → 0.7.25

Sign up to get free protection for your applications and to get access to all the features.
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
+ }