@assistant-ui/core 0.3.17 → 0.3.18
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.
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/attachment.js +5 -4
- package/dist/adapters/attachment.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +3 -2
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +10 -4
- package/dist/model-context/frame/host.js.map +1 -1
- package/dist/model-context/frame/provider.d.ts +2 -0
- package/dist/model-context/frame/provider.d.ts.map +1 -1
- package/dist/model-context/frame/provider.js +30 -7
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
- package/dist/model-context/interactable-composer-metadata.js +16 -9
- package/dist/model-context/interactable-composer-metadata.js.map +1 -1
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +3 -5
- package/dist/model-context/registry.js.map +1 -1
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js +5 -4
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +62 -56
- package/dist/react/client/InMemoryThreadList.js.map +1 -1
- package/dist/react/client/Interactables.d.ts.map +1 -1
- package/dist/react/client/Interactables.js +24 -27
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts +1 -0
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +151 -141
- package/dist/react/client/RemoteThreadList.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +18 -16
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +242 -121
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
- package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
- package/dist/react/model-context/makeAssistantTool.js +1 -1
- package/dist/react/model-context/makeAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantTool.d.ts +2 -2
- package/dist/react/model-context/useAssistantTool.js +1 -1
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +2 -1
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +103 -103
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
- package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadResource.js +13 -11
- package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +4 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +401 -34
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +2 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
- package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
- package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
- package/dist/react/runtimes/useRemoteThreadListRuntime.js +63 -23
- package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +2 -2
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +3 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +18 -14
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +4 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +1 -1
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +16 -12
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +6 -5
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +4 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/external-message-conversion.js +1 -1
- package/dist/runtime/utils/external-message-conversion.js.map +1 -1
- package/dist/runtime/utils/message-repository.d.ts +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +15 -6
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/thread-message-like.js +1 -1
- package/dist/runtime/utils/thread-message-like.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/internal.d.ts +2 -2
- package/dist/runtimes/internal.js +2 -2
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js +130 -42
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
- package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
- package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
- package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
- package/dist/runtimes/remote-thread-list/title.d.ts +3 -1
- package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/title.js +9 -1
- package/dist/runtimes/remote-thread-list/title.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +19 -3
- package/dist/store/clients/external-thread.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +2 -1
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/single-thread-list.d.ts.map +1 -1
- package/dist/store/clients/single-thread-list.js +1 -0
- package/dist/store/clients/single-thread-list.js.map +1 -1
- package/dist/store/clients/suggestions.d.ts.map +1 -1
- package/dist/store/clients/suggestions.js +5 -4
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +97 -61
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
- package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/message-runtime-client.js +221 -144
- package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
- package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-list-runtime-client.js +54 -52
- package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +193 -121
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +10 -2
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +30 -1
- package/dist/store/scopes/message.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +2 -2
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +8 -0
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +1 -0
- package/dist/store/scopes/threads.d.ts.map +1 -1
- package/dist/types/attachment.d.ts +2 -1
- package/dist/types/attachment.d.ts.map +1 -1
- package/dist/types/attachment.js +2 -1
- package/dist/types/attachment.js.map +1 -1
- package/dist/utils/abortable-iterable.d.ts +19 -0
- package/dist/utils/abortable-iterable.d.ts.map +1 -0
- package/dist/utils/abortable-iterable.js +72 -0
- package/dist/utils/abortable-iterable.js.map +1 -0
- package/dist/utils/composite-context-provider.d.ts.map +1 -1
- package/dist/utils/composite-context-provider.js +20 -2
- package/dist/utils/composite-context-provider.js.map +1 -1
- package/dist/utils/record.d.ts +11 -0
- package/dist/utils/record.d.ts.map +1 -0
- package/dist/utils/record.js +12 -0
- package/dist/utils/record.js.map +1 -0
- package/package.json +10 -10
- package/src/adapters/attachment.test.ts +50 -1
- package/src/adapters/attachment.ts +7 -4
- package/src/index.ts +1 -0
- package/src/internal.ts +4 -0
- package/src/model-context/frame/host.test.ts +24 -0
- package/src/model-context/frame/host.ts +10 -4
- package/src/model-context/frame/provider.test.ts +71 -0
- package/src/model-context/frame/provider.ts +37 -7
- package/src/model-context/interactable-composer-metadata.test.ts +28 -0
- package/src/model-context/interactable-composer-metadata.ts +9 -3
- package/src/model-context/registry.test.ts +12 -0
- package/src/model-context/registry.ts +3 -2
- package/src/model-context/types.test.ts +25 -0
- package/src/model-context/types.ts +9 -4
- package/src/react/RuntimeAdapter.test.ts +34 -0
- package/src/react/client/InMemoryThreadList.ts +1 -0
- package/src/react/client/Interactables.test.ts +28 -0
- package/src/react/client/Interactables.ts +15 -13
- package/src/react/client/RemoteThreadList.background.test.ts +148 -6
- package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
- package/src/react/client/RemoteThreadList.test.ts +345 -3
- package/src/react/client/RemoteThreadList.ts +166 -110
- package/src/react/client/Tools.ts +22 -11
- package/src/react/interactables-legacy/Interactables.ts +16 -16
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
- package/src/react/model-context/makeAssistantTool.ts +2 -2
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
- package/src/react/model-context/useToolArgsStatus.ts +2 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +136 -111
- package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
- package/src/react/runtimes/RemoteThreadResource.ts +19 -12
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +483 -6
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +504 -68
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +15 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +1 -0
- package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
- package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
- package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
- package/src/react/runtimes/useRemoteThreadListRuntime.ts +33 -0
- package/src/runtime/api/message-runtime.test.ts +75 -0
- package/src/runtime/api/thread-list-item-runtime.ts +10 -3
- package/src/runtime/api/thread-list-runtime.ts +21 -11
- package/src/runtime/api/thread-runtime.test.ts +78 -0
- package/src/runtime/api/thread-runtime.ts +8 -1
- package/src/runtime/base/base-composer-runtime-core.ts +36 -8
- package/src/runtime/base/base-thread-runtime-core.test.ts +55 -1
- package/src/runtime/base/base-thread-runtime-core.ts +6 -4
- package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
- package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
- package/src/runtime/utils/external-message-conversion.test.ts +68 -0
- package/src/runtime/utils/external-message-conversion.ts +1 -1
- package/src/runtime/utils/message-repository.ts +29 -17
- package/src/runtime/utils/thread-message-like.ts +1 -1
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
- package/src/runtimes/internal.ts +1 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
- package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
- package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
- package/src/runtimes/remote-thread-list/title.test.ts +62 -0
- package/src/runtimes/remote-thread-list/title.ts +13 -0
- package/src/runtimes/remote-thread-list/types.ts +10 -0
- package/src/store/clients/external-thread.ts +48 -3
- package/src/store/clients/model-context-client.ts +5 -1
- package/src/store/clients/single-thread-list.ts +1 -0
- package/src/store/clients/suggestions.test.ts +40 -0
- package/src/store/clients/suggestions.ts +13 -10
- package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
- package/src/store/runtime-clients/message-runtime-client.ts +54 -6
- package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
- package/src/store/runtime-clients/thread-list-runtime-client.ts +1 -0
- package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
- package/src/store/scopes/composer.ts +16 -4
- package/src/store/scopes/message.ts +14 -0
- package/src/store/scopes/thread-list-item.ts +5 -2
- package/src/store/scopes/thread.ts +4 -0
- package/src/store/scopes/threads.ts +1 -0
- package/src/tests/MessageRepository.test.ts +116 -0
- package/src/tests/OptimisticState-list-race.test.ts +1 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +47 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
- package/src/tests/attachment-adapters.test.ts +14 -0
- package/src/tests/base-composer-runtime-core.test.ts +39 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +27 -18
- package/src/tests/external-thread-attachments.test.tsx +139 -0
- package/src/tests/external-thread-parity.test.tsx +23 -0
- package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
- package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
- package/src/tests/thread-switch-events.test.tsx +78 -0
- package/src/tests/tools-scope-migration.test.tsx +28 -0
- package/src/types/attachment.ts +4 -0
- package/src/utils/abortable-iterable.test.ts +213 -0
- package/src/utils/abortable-iterable.ts +93 -0
- package/src/utils/composite-context-provider.test.ts +25 -0
- package/src/utils/composite-context-provider.ts +23 -2
- package/src/utils/record.test.ts +48 -0
- package/src/utils/record.ts +11 -0
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
createThreadMappingId,
|
|
26
26
|
getThreadData,
|
|
27
27
|
normalizeCursor,
|
|
28
|
+
reconcileInitializedThread,
|
|
29
|
+
promoteNewThreadReducer,
|
|
28
30
|
updateStatusReducer,
|
|
29
31
|
type RemoteThreadData,
|
|
30
32
|
type RemoteThreadState,
|
|
@@ -38,14 +40,23 @@ import type {
|
|
|
38
40
|
} from "../../runtimes/remote-thread-list/types";
|
|
39
41
|
import { ThreadListAdapterChangedError } from "../../runtimes/remote-thread-list/adapter-changed";
|
|
40
42
|
import type { ThreadMessage } from "../../types/message";
|
|
41
|
-
import { AssistantMessageStream } from "assistant-stream";
|
|
42
43
|
import { handleThreadListAction } from "../../store/runtime-clients/handle-thread-list-action";
|
|
43
44
|
import {
|
|
44
45
|
inMemoryThreadListTransformScopes,
|
|
45
46
|
type InMemoryThreadListProps,
|
|
46
47
|
} from "./InMemoryThreadList";
|
|
47
48
|
import { AdaptedRemoteThread } from "./AdaptedRemoteThread";
|
|
48
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
applyTitleStream,
|
|
51
|
+
isTitleSourceMessage,
|
|
52
|
+
} from "../../runtimes/remote-thread-list/title";
|
|
53
|
+
import {
|
|
54
|
+
clearThreadTitleState,
|
|
55
|
+
finishThreadTitleRename,
|
|
56
|
+
runThreadTitleGeneration,
|
|
57
|
+
startThreadTitleRename,
|
|
58
|
+
type ThreadTitleState,
|
|
59
|
+
} from "../../runtimes/remote-thread-list/title-generation";
|
|
49
60
|
|
|
50
61
|
const RESOLVED_PROMISE = Promise.resolve();
|
|
51
62
|
|
|
@@ -67,6 +78,7 @@ export type RemoteThreadListProps = {
|
|
|
67
78
|
onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;
|
|
68
79
|
onSwitchToThread?: ((threadId: string) => void) | undefined;
|
|
69
80
|
onSwitchToNewThread?: (() => void) | undefined;
|
|
81
|
+
/** Called after the backing adapter successfully deletes the thread. */
|
|
70
82
|
onDelete?: ((threadId: string) => void) | undefined;
|
|
71
83
|
/**
|
|
72
84
|
* Keeps every thread the session switched to mounted, so a run continues
|
|
@@ -101,16 +113,6 @@ const toInitializeResult = (
|
|
|
101
113
|
externalId: result.externalId,
|
|
102
114
|
});
|
|
103
115
|
|
|
104
|
-
const applyTitleStream = async (
|
|
105
|
-
stream: Parameters<typeof AssistantMessageStream.fromAssistantStream>[0],
|
|
106
|
-
onTitle: (title: string | undefined) => Promise<void>,
|
|
107
|
-
) => {
|
|
108
|
-
const messageStream = AssistantMessageStream.fromAssistantStream(stream);
|
|
109
|
-
for await (const result of messageStream) {
|
|
110
|
-
await onTitle(result.parts.filter((part) => part.type === "text")[0]?.text);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
116
|
const useThreadListItemClient = (props: {
|
|
115
117
|
data: RemoteThreadData;
|
|
116
118
|
isRunning: boolean;
|
|
@@ -120,7 +122,7 @@ const useThreadListItemClient = (props: {
|
|
|
120
122
|
onArchive: () => void;
|
|
121
123
|
onUnarchive: () => void;
|
|
122
124
|
onDelete: () => void;
|
|
123
|
-
onGenerateTitle: () => void;
|
|
125
|
+
onGenerateTitle: (options?: { automatic?: boolean }) => void;
|
|
124
126
|
onInitialize: () => Promise<{
|
|
125
127
|
remoteId: string;
|
|
126
128
|
externalId: string | undefined;
|
|
@@ -271,7 +273,7 @@ const useRemoteThreadBody = ({
|
|
|
271
273
|
useEffect(() => {
|
|
272
274
|
if (!hasTitleSource || titleFiredRef.current) return;
|
|
273
275
|
titleFiredRef.current = true;
|
|
274
|
-
client.threadListItem.generateTitle();
|
|
276
|
+
client.threadListItem.generateTitle({ automatic: true });
|
|
275
277
|
}, [hasTitleSource]);
|
|
276
278
|
return body.methods;
|
|
277
279
|
});
|
|
@@ -343,6 +345,7 @@ const useRemoteThreadListView = ({
|
|
|
343
345
|
onGenerateTitle: (
|
|
344
346
|
threadId: string,
|
|
345
347
|
messages: readonly ThreadMessage[] | undefined,
|
|
348
|
+
options?: { automatic?: boolean },
|
|
346
349
|
) => Promise<void>;
|
|
347
350
|
onInitialize: (threadId: string) => Promise<{
|
|
348
351
|
remoteId: string;
|
|
@@ -385,7 +388,7 @@ const useRemoteThreadListView = ({
|
|
|
385
388
|
onUnarchive: () =>
|
|
386
389
|
handleThreadListAction("unarchive", () => onUnarchive(data.id)),
|
|
387
390
|
onDelete: () => handleThreadListAction("delete", () => onDelete(data.id)),
|
|
388
|
-
onGenerateTitle: () =>
|
|
391
|
+
onGenerateTitle: (options) =>
|
|
389
392
|
handleThreadListAction("generate title", () =>
|
|
390
393
|
onGenerateTitle(
|
|
391
394
|
data.id,
|
|
@@ -394,6 +397,7 @@ const useRemoteThreadListView = ({
|
|
|
394
397
|
: mainThreadClient.state.messages) as
|
|
395
398
|
| readonly ThreadMessage[]
|
|
396
399
|
| undefined,
|
|
400
|
+
options,
|
|
397
401
|
),
|
|
398
402
|
),
|
|
399
403
|
onInitialize: () => onInitialize(data.id),
|
|
@@ -489,6 +493,7 @@ const useRemoteThreadList = (
|
|
|
489
493
|
adapter,
|
|
490
494
|
adapterAtLoad: adapter,
|
|
491
495
|
adapterGeneration: 0,
|
|
496
|
+
titleStates: new Map<string, ThreadTitleState>(),
|
|
492
497
|
loadGeneration: 0,
|
|
493
498
|
switchGeneration: 0,
|
|
494
499
|
loadPromise: undefined as Promise<void> | undefined,
|
|
@@ -560,7 +565,7 @@ const useRemoteThreadList = (
|
|
|
560
565
|
execute: () => adapter.list(),
|
|
561
566
|
loading: (state) => {
|
|
562
567
|
if (generation !== session.loadGeneration) return state;
|
|
563
|
-
return { ...state, isLoading: true };
|
|
568
|
+
return { ...state, isLoading: true, loadError: undefined };
|
|
564
569
|
},
|
|
565
570
|
then: (state, page) => {
|
|
566
571
|
if (generation !== session.loadGeneration) return state;
|
|
@@ -574,6 +579,7 @@ const useRemoteThreadList = (
|
|
|
574
579
|
const merged = {
|
|
575
580
|
...state,
|
|
576
581
|
isLoading: false,
|
|
582
|
+
loadError: undefined,
|
|
577
583
|
cursor: normalizeCursor(page.nextCursor),
|
|
578
584
|
threadIds: fresh.threadIds,
|
|
579
585
|
archivedThreadIds: fresh.archivedThreadIds,
|
|
@@ -590,6 +596,7 @@ const useRemoteThreadList = (
|
|
|
590
596
|
store.update({
|
|
591
597
|
...store.baseValue,
|
|
592
598
|
isLoading: false,
|
|
599
|
+
loadError: error,
|
|
593
600
|
});
|
|
594
601
|
})
|
|
595
602
|
.then(() => {});
|
|
@@ -603,6 +610,7 @@ const useRemoteThreadList = (
|
|
|
603
610
|
session.loadMorePromise = undefined;
|
|
604
611
|
if (adapterChanged) {
|
|
605
612
|
session.adapterGeneration++;
|
|
613
|
+
session.titleStates.clear();
|
|
606
614
|
session.switchGeneration++;
|
|
607
615
|
session.switchTask = undefined;
|
|
608
616
|
session.adapterAtLoad = adapter;
|
|
@@ -627,6 +635,26 @@ const useRemoteThreadList = (
|
|
|
627
635
|
store,
|
|
628
636
|
]);
|
|
629
637
|
|
|
638
|
+
useEffect(() => {
|
|
639
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
const retryAfterError = () => {
|
|
644
|
+
if (store.value.loadError !== undefined) void getLoadThreadsPromise();
|
|
645
|
+
};
|
|
646
|
+
const retryAfterVisible = () => {
|
|
647
|
+
if (document.visibilityState === "visible") retryAfterError();
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
window.addEventListener("online", retryAfterError);
|
|
651
|
+
document.addEventListener("visibilitychange", retryAfterVisible);
|
|
652
|
+
return () => {
|
|
653
|
+
window.removeEventListener("online", retryAfterError);
|
|
654
|
+
document.removeEventListener("visibilitychange", retryAfterVisible);
|
|
655
|
+
};
|
|
656
|
+
}, [getLoadThreadsPromise, store]);
|
|
657
|
+
|
|
630
658
|
useEffect(() => {
|
|
631
659
|
void getLoadThreadsPromise();
|
|
632
660
|
}, [getLoadThreadsPromise]);
|
|
@@ -881,70 +909,60 @@ const useRemoteThreadList = (
|
|
|
881
909
|
requireAdapterGeneration(adapterGeneration);
|
|
882
910
|
return result;
|
|
883
911
|
}
|
|
912
|
+
requireAdapterGeneration(adapterGeneration);
|
|
913
|
+
const initializeTask = currentAdapter.initialize(threadId);
|
|
914
|
+
let removedMappingId: string | undefined;
|
|
915
|
+
let replacementMainThreadId: string | undefined;
|
|
884
916
|
const result = await store.optimisticUpdate({
|
|
885
|
-
execute: () =>
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
},
|
|
889
|
-
optimistic: (state) => updateStatusReducer(state, threadId, "regular"),
|
|
890
|
-
loading: (state, task) => {
|
|
891
|
-
const mappingId = createThreadMappingId(threadId);
|
|
892
|
-
return {
|
|
893
|
-
...state,
|
|
894
|
-
threadData: {
|
|
895
|
-
...state.threadData,
|
|
896
|
-
[mappingId]: {
|
|
897
|
-
...state.threadData[mappingId],
|
|
898
|
-
initializeTask: task,
|
|
899
|
-
},
|
|
900
|
-
},
|
|
901
|
-
};
|
|
902
|
-
},
|
|
917
|
+
execute: () => initializeTask,
|
|
918
|
+
optimistic: (state) =>
|
|
919
|
+
promoteNewThreadReducer(state, threadId, initializeTask),
|
|
903
920
|
then: (state, { remoteId, externalId }) => {
|
|
904
921
|
if (adapterGeneration !== session.adapterGeneration) return state;
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
listedMappingId !== undefined && listedMappingId !== mappingId
|
|
914
|
-
? state.threadData[listedMappingId]
|
|
915
|
-
: undefined;
|
|
916
|
-
|
|
917
|
-
const threadData = { ...state.threadData };
|
|
918
|
-
if (orphan !== undefined) delete threadData[listedMappingId!];
|
|
919
|
-
threadData[mappingId] = {
|
|
920
|
-
...data,
|
|
921
|
-
initializeTask: Promise.resolve({ remoteId, externalId }),
|
|
922
|
+
// Background mode still owns the initializing body. Single-body mode
|
|
923
|
+
// has already replaced it, so retain the currently mounted body.
|
|
924
|
+
const retainedThreadId = backgroundThreads
|
|
925
|
+
? threadId
|
|
926
|
+
: session.mainThreadId;
|
|
927
|
+
const reconciliation = reconcileInitializedThread(
|
|
928
|
+
state,
|
|
929
|
+
threadId,
|
|
922
930
|
remoteId,
|
|
923
931
|
externalId,
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
threadIds: rewire(state.threadIds),
|
|
932
|
-
archivedThreadIds: rewire(state.archivedThreadIds),
|
|
933
|
-
threadIdMap: {
|
|
934
|
-
...state.threadIdMap,
|
|
935
|
-
[remoteId]: mappingId,
|
|
936
|
-
},
|
|
937
|
-
threadData,
|
|
938
|
-
};
|
|
932
|
+
retainedThreadId,
|
|
933
|
+
);
|
|
934
|
+
removedMappingId = reconciliation.removedMappingId;
|
|
935
|
+
if (removedMappingId === session.mainThreadId) {
|
|
936
|
+
replacementMainThreadId = reconciliation.survivorMappingId;
|
|
937
|
+
}
|
|
938
|
+
return reconciliation.state;
|
|
939
939
|
},
|
|
940
940
|
});
|
|
941
941
|
requireAdapterGeneration(adapterGeneration);
|
|
942
|
+
if (removedMappingId !== undefined) {
|
|
943
|
+
setStartedIds((prev) =>
|
|
944
|
+
prev.filter((startedId) => startedId !== removedMappingId),
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
if (
|
|
948
|
+
replacementMainThreadId !== undefined &&
|
|
949
|
+
session.mainThreadId === removedMappingId
|
|
950
|
+
) {
|
|
951
|
+
assignMainThreadId(replacementMainThreadId);
|
|
952
|
+
}
|
|
942
953
|
if (threadId === session.mainThreadId) {
|
|
943
954
|
notifyRemoteId(result.remoteId, true);
|
|
944
955
|
}
|
|
945
956
|
return toInitializeResult(result);
|
|
946
957
|
},
|
|
947
|
-
[
|
|
958
|
+
[
|
|
959
|
+
assignMainThreadId,
|
|
960
|
+
backgroundThreads,
|
|
961
|
+
notifyRemoteId,
|
|
962
|
+
requireAdapterGeneration,
|
|
963
|
+
session,
|
|
964
|
+
store,
|
|
965
|
+
],
|
|
948
966
|
);
|
|
949
967
|
|
|
950
968
|
const rename = useCallback(
|
|
@@ -956,27 +974,43 @@ const useRemoteThreadList = (
|
|
|
956
974
|
if (data.status === "new") {
|
|
957
975
|
throw threadStatusError(threadIdOrRemoteId, data.status, "be renamed");
|
|
958
976
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
977
|
+
const claim = startThreadTitleRename(
|
|
978
|
+
session.titleStates,
|
|
979
|
+
data.id,
|
|
980
|
+
newTitle,
|
|
981
|
+
);
|
|
982
|
+
return store
|
|
983
|
+
.optimisticUpdate({
|
|
984
|
+
execute: async () => {
|
|
985
|
+
const { remoteId } = await data.initializeTask;
|
|
986
|
+
requireAdapterGeneration(adapterGeneration);
|
|
987
|
+
return currentAdapter.rename(remoteId, newTitle);
|
|
988
|
+
},
|
|
989
|
+
optimistic: (state) => {
|
|
990
|
+
const current = getThreadData(state, threadIdOrRemoteId);
|
|
991
|
+
if (!current) return state;
|
|
992
|
+
return {
|
|
993
|
+
...state,
|
|
994
|
+
threadData: {
|
|
995
|
+
...state.threadData,
|
|
996
|
+
[current.id]: {
|
|
997
|
+
...current,
|
|
998
|
+
title: newTitle,
|
|
999
|
+
},
|
|
975
1000
|
},
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
|
|
1001
|
+
};
|
|
1002
|
+
},
|
|
1003
|
+
})
|
|
1004
|
+
.then(
|
|
1005
|
+
(result) => {
|
|
1006
|
+
finishThreadTitleRename(session.titleStates, data.id, claim, true);
|
|
1007
|
+
return result;
|
|
1008
|
+
},
|
|
1009
|
+
(error: unknown) => {
|
|
1010
|
+
finishThreadTitleRename(session.titleStates, data.id, claim, false);
|
|
1011
|
+
throw error;
|
|
1012
|
+
},
|
|
1013
|
+
);
|
|
980
1014
|
},
|
|
981
1015
|
[requireAdapterGeneration, session, store],
|
|
982
1016
|
);
|
|
@@ -1104,8 +1138,7 @@ const useRemoteThreadList = (
|
|
|
1104
1138
|
}
|
|
1105
1139
|
await ensureNotMain(data.id);
|
|
1106
1140
|
requireAdapterGeneration(adapterGeneration);
|
|
1107
|
-
|
|
1108
|
-
return store.optimisticUpdate({
|
|
1141
|
+
const result = await store.optimisticUpdate({
|
|
1109
1142
|
execute: async () => {
|
|
1110
1143
|
const { remoteId } = await data.initializeTask;
|
|
1111
1144
|
requireAdapterGeneration(adapterGeneration);
|
|
@@ -1113,6 +1146,13 @@ const useRemoteThreadList = (
|
|
|
1113
1146
|
},
|
|
1114
1147
|
optimistic: (state) => updateStatusReducer(state, data.id, "deleted"),
|
|
1115
1148
|
});
|
|
1149
|
+
// An adapter swap resets the optimistic layer, and a listed thread's slot
|
|
1150
|
+
// id is its remote id, so a replacement adapter can re-list this slot
|
|
1151
|
+
// while the deletion is in flight.
|
|
1152
|
+
if (getThreadData(store.value, data.id) !== undefined) return result;
|
|
1153
|
+
clearThreadTitleState(session.titleStates, data.id);
|
|
1154
|
+
onDelete?.(data.id);
|
|
1155
|
+
return result;
|
|
1116
1156
|
},
|
|
1117
1157
|
[ensureNotMain, onDelete, requireAdapterGeneration, session, store],
|
|
1118
1158
|
);
|
|
@@ -1121,6 +1161,7 @@ const useRemoteThreadList = (
|
|
|
1121
1161
|
async (
|
|
1122
1162
|
threadIdOrRemoteId: string,
|
|
1123
1163
|
messages: readonly ThreadMessage[] | undefined,
|
|
1164
|
+
options?: { automatic?: boolean },
|
|
1124
1165
|
) => {
|
|
1125
1166
|
const currentAdapter = session.adapter;
|
|
1126
1167
|
const adapterGeneration = session.adapterGeneration;
|
|
@@ -1144,27 +1185,39 @@ const useRemoteThreadList = (
|
|
|
1144
1185
|
return;
|
|
1145
1186
|
}
|
|
1146
1187
|
if (!messages) return;
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1188
|
+
await runThreadTitleGeneration({
|
|
1189
|
+
states: session.titleStates,
|
|
1190
|
+
threadId: data.id,
|
|
1191
|
+
automatic: options?.automatic === true,
|
|
1192
|
+
generate: async (onTitle) => {
|
|
1193
|
+
const stream = await currentAdapter.generateTitle(remoteId, messages);
|
|
1194
|
+
requireAdapterGeneration(adapterGeneration);
|
|
1195
|
+
await applyTitleStream(stream, onTitle);
|
|
1196
|
+
},
|
|
1197
|
+
rename: async (title) => {
|
|
1198
|
+
requireAdapterGeneration(adapterGeneration);
|
|
1199
|
+
await currentAdapter.rename(remoteId, title);
|
|
1200
|
+
},
|
|
1201
|
+
applyTitle: async (title) => {
|
|
1202
|
+
await store.optimisticUpdate({
|
|
1203
|
+
execute: async () => {},
|
|
1204
|
+
optimistic: (state) => {
|
|
1205
|
+
if (adapterGeneration !== session.adapterGeneration) return state;
|
|
1206
|
+
const current = getThreadData(state, data.id);
|
|
1207
|
+
if (!current) return state;
|
|
1208
|
+
return {
|
|
1209
|
+
...state,
|
|
1210
|
+
threadData: {
|
|
1211
|
+
...state.threadData,
|
|
1212
|
+
[current.id]: {
|
|
1213
|
+
...current,
|
|
1214
|
+
title,
|
|
1215
|
+
},
|
|
1163
1216
|
},
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1217
|
+
};
|
|
1218
|
+
},
|
|
1219
|
+
});
|
|
1220
|
+
},
|
|
1168
1221
|
});
|
|
1169
1222
|
},
|
|
1170
1223
|
[backgroundThreads, requireAdapterGeneration, session, store],
|
|
@@ -1192,7 +1245,8 @@ const useRemoteThreadList = (
|
|
|
1192
1245
|
onArchive: (id) => archive(id),
|
|
1193
1246
|
onUnarchive: (id) => unarchive(id),
|
|
1194
1247
|
onDelete: (id) => deleteThread(id),
|
|
1195
|
-
onGenerateTitle: (id, messages) =>
|
|
1248
|
+
onGenerateTitle: (id, messages, options) =>
|
|
1249
|
+
generateTitle(id, messages, options),
|
|
1196
1250
|
onInitialize: async (id) => toInitializeResult(await initialize(id)),
|
|
1197
1251
|
onDetach: (id) => detach(id),
|
|
1198
1252
|
});
|
|
@@ -1230,6 +1284,7 @@ const useRemoteThreadList = (
|
|
|
1230
1284
|
mainThreadId,
|
|
1231
1285
|
newThreadId: listState.newThreadId ?? null,
|
|
1232
1286
|
isLoading: listState.isLoading,
|
|
1287
|
+
loadError: listState.loadError,
|
|
1233
1288
|
isLoadingMore: listState.isLoadingMore,
|
|
1234
1289
|
hasMore: listState.cursor !== undefined,
|
|
1235
1290
|
threadIds: listState.threadIds,
|
|
@@ -1241,6 +1296,7 @@ const useRemoteThreadList = (
|
|
|
1241
1296
|
listState.archivedThreadIds,
|
|
1242
1297
|
listState.cursor,
|
|
1243
1298
|
listState.isLoading,
|
|
1299
|
+
listState.loadError,
|
|
1244
1300
|
listState.isLoadingMore,
|
|
1245
1301
|
listState.newThreadId,
|
|
1246
1302
|
listState.threadIds,
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from "../model-context/toolbox";
|
|
22
22
|
import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
23
23
|
import { ModelContext } from "../../store/clients/model-context-client";
|
|
24
|
+
import { nullProtoRecord } from "../../utils/record";
|
|
24
25
|
|
|
25
26
|
export type { McpAppResourceOutput };
|
|
26
27
|
|
|
@@ -44,7 +45,9 @@ const useTools = ({
|
|
|
44
45
|
const mcpAppOutputs = useResources(mcpApp ? [withKey("mcpApp", mcpApp)] : []);
|
|
45
46
|
const mcpAppOutput = mcpAppOutputs[0];
|
|
46
47
|
|
|
47
|
-
const [toolUIs, setToolUIs] = useState<ToolsState["toolUIs"]>(() =>
|
|
48
|
+
const [toolUIs, setToolUIs] = useState<ToolsState["toolUIs"]>(() =>
|
|
49
|
+
nullProtoRecord(),
|
|
50
|
+
);
|
|
48
51
|
|
|
49
52
|
const state = useMemo(
|
|
50
53
|
(): ToolsState => ({
|
|
@@ -73,20 +76,25 @@ const useTools = ({
|
|
|
73
76
|
standalone: options?.standalone ?? false,
|
|
74
77
|
};
|
|
75
78
|
|
|
76
|
-
setToolUIs((prev) =>
|
|
77
|
-
|
|
78
|
-
[toolName]
|
|
79
|
-
|
|
79
|
+
setToolUIs((prev) => {
|
|
80
|
+
const next = nullProtoRecord(prev);
|
|
81
|
+
next[toolName] = [...(next[toolName] ?? []), registration];
|
|
82
|
+
return next;
|
|
83
|
+
});
|
|
80
84
|
|
|
81
85
|
return () => {
|
|
82
86
|
setToolUIs((prev) => {
|
|
83
|
-
const
|
|
84
|
-
|
|
87
|
+
const registrations =
|
|
88
|
+
prev[toolName]?.filter((r) => r !== registration) ?? [];
|
|
89
|
+
const next = nullProtoRecord(prev);
|
|
90
|
+
if (registrations.length > 0) {
|
|
91
|
+
next[toolName] = registrations;
|
|
92
|
+
return next;
|
|
93
|
+
}
|
|
85
94
|
// Drop the key entirely so repeatedly mounted/unmounted tools
|
|
86
95
|
// don't leave empty arrays accumulating across a long session.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return rest;
|
|
96
|
+
delete next[toolName];
|
|
97
|
+
return next;
|
|
90
98
|
});
|
|
91
99
|
};
|
|
92
100
|
},
|
|
@@ -108,6 +116,9 @@ const useTools = ({
|
|
|
108
116
|
: undefined);
|
|
109
117
|
if (render) {
|
|
110
118
|
unsubscribes.push(
|
|
119
|
+
// Registration has to be undone on unmount, so the registry write and
|
|
120
|
+
// its unsubscribe belong to the same effect.
|
|
121
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
111
122
|
setToolUI(toolName, render, {
|
|
112
123
|
standalone: isStandaloneToolDisplay(tool),
|
|
113
124
|
renderText: toolRenderText,
|
|
@@ -141,7 +152,7 @@ const useTools = ({
|
|
|
141
152
|
acc[name] = rest as Tool<any, any>;
|
|
142
153
|
return acc;
|
|
143
154
|
},
|
|
144
|
-
|
|
155
|
+
nullProtoRecord<Tool<any, any>>(),
|
|
145
156
|
);
|
|
146
157
|
|
|
147
158
|
const modelContextProvider = {
|
|
@@ -18,11 +18,12 @@ import { ModelContext } from "../../store";
|
|
|
18
18
|
import { buildInteractableModelContext } from "./interactable-model-context";
|
|
19
19
|
import { notifySubscribers as notifyStateSubscribers } from "../../subscribable/subscribable";
|
|
20
20
|
import { useInteractablePersistenceQueue } from "../interactables-shared/useInteractablePersistenceQueue";
|
|
21
|
+
import { nullProtoRecord } from "../../utils/record";
|
|
21
22
|
|
|
22
23
|
const useInteractables = (): ClientOutput<"interactables"> => {
|
|
23
24
|
const [state, setState] = useState<InteractablesState>(() => ({
|
|
24
|
-
definitions:
|
|
25
|
-
persistence:
|
|
25
|
+
definitions: nullProtoRecord(),
|
|
26
|
+
persistence: nullProtoRecord(),
|
|
26
27
|
}));
|
|
27
28
|
|
|
28
29
|
const clientRef = useAssistantClientRef();
|
|
@@ -49,7 +50,7 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
49
50
|
);
|
|
50
51
|
|
|
51
52
|
const exportState = useCallback((): InteractablePersistedState => {
|
|
52
|
-
const result
|
|
53
|
+
const result = nullProtoRecord<InteractablePersistedState[string]>();
|
|
53
54
|
for (const [id, def] of Object.entries(stateRef.current.definitions)) {
|
|
54
55
|
result[id] = { name: def.name, state: def.state };
|
|
55
56
|
}
|
|
@@ -86,7 +87,7 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
86
87
|
}
|
|
87
88
|
setStateAndRef((prev) => {
|
|
88
89
|
let changed = false;
|
|
89
|
-
const definitions =
|
|
90
|
+
const definitions = nullProtoRecord(prev.definitions);
|
|
90
91
|
for (const [id, entry] of Object.entries(saved)) {
|
|
91
92
|
if (definitions[id]) {
|
|
92
93
|
definitions[id] = { ...definitions[id], state: entry.state };
|
|
@@ -114,10 +115,9 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
114
115
|
if (!existing) return prev;
|
|
115
116
|
return {
|
|
116
117
|
...prev,
|
|
117
|
-
definitions: {
|
|
118
|
-
...prev.definitions,
|
|
118
|
+
definitions: nullProtoRecord(prev.definitions, {
|
|
119
119
|
[id]: { ...existing, state: updater(existing.state) },
|
|
120
|
-
},
|
|
120
|
+
}),
|
|
121
121
|
};
|
|
122
122
|
});
|
|
123
123
|
if (stateRef.current.definitions[id]) schedulePersistence(id);
|
|
@@ -132,10 +132,9 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
132
132
|
if (!existing) return prev;
|
|
133
133
|
return {
|
|
134
134
|
...prev,
|
|
135
|
-
definitions: {
|
|
136
|
-
...prev.definitions,
|
|
135
|
+
definitions: nullProtoRecord(prev.definitions, {
|
|
137
136
|
[id]: { ...existing, selected },
|
|
138
|
-
},
|
|
137
|
+
}),
|
|
139
138
|
};
|
|
140
139
|
});
|
|
141
140
|
},
|
|
@@ -194,8 +193,7 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
194
193
|
|
|
195
194
|
setStateAndRef((prev) => ({
|
|
196
195
|
...prev,
|
|
197
|
-
definitions: {
|
|
198
|
-
...prev.definitions,
|
|
196
|
+
definitions: nullProtoRecord(prev.definitions, {
|
|
199
197
|
[def.id]: {
|
|
200
198
|
id: def.id,
|
|
201
199
|
name: def.name,
|
|
@@ -205,7 +203,7 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
205
203
|
prev.definitions[def.id]?.state ?? detached ?? def.initialState,
|
|
206
204
|
selected: def.selected,
|
|
207
205
|
},
|
|
208
|
-
},
|
|
206
|
+
}),
|
|
209
207
|
}));
|
|
210
208
|
|
|
211
209
|
return () => {
|
|
@@ -216,9 +214,11 @@ const useInteractables = (): ClientOutput<"interactables"> => {
|
|
|
216
214
|
detachedStateRef.current.set(def.id, existing.state);
|
|
217
215
|
}
|
|
218
216
|
partialSchemaCacheRef.current.delete(def.id);
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
|
|
217
|
+
const definitions = nullProtoRecord(prev.definitions);
|
|
218
|
+
const persistence = nullProtoRecord(prev.persistence);
|
|
219
|
+
delete definitions[def.id];
|
|
220
|
+
delete persistence[def.id];
|
|
221
|
+
return { ...prev, definitions, persistence };
|
|
222
222
|
});
|
|
223
223
|
};
|
|
224
224
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useRef, type RefObject } from "react";
|
|
2
|
+
import { nullProtoRecord } from "../../utils/record";
|
|
2
3
|
|
|
3
4
|
const PERSISTENCE_DEBOUNCE_MS = 500;
|
|
4
5
|
|
|
@@ -90,15 +91,13 @@ export const useInteractablePersistenceQueue = <State>({
|
|
|
90
91
|
const { adapter, payload, dirtyIds, seq } = resolved;
|
|
91
92
|
inFlightPersistenceRef.current += 1;
|
|
92
93
|
|
|
93
|
-
updatePersistenceStatus((prev) =>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
[
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
),
|
|
101
|
-
}));
|
|
94
|
+
updatePersistenceStatus((prev) => {
|
|
95
|
+
const persistence = nullProtoRecord(prev);
|
|
96
|
+
for (const id of dirtyIds) {
|
|
97
|
+
persistence[id] = { isPending: true, error: undefined };
|
|
98
|
+
}
|
|
99
|
+
return persistence;
|
|
100
|
+
});
|
|
102
101
|
|
|
103
102
|
const settleBatch = (status: PersistenceStatus | undefined) => {
|
|
104
103
|
const settledIds: string[] = [];
|
|
@@ -114,7 +113,7 @@ export const useInteractablePersistenceQueue = <State>({
|
|
|
114
113
|
if (settledIds.length === 0) return;
|
|
115
114
|
updatePersistenceStatus((prev) => {
|
|
116
115
|
let changed = false;
|
|
117
|
-
const persistence =
|
|
116
|
+
const persistence = nullProtoRecord(prev);
|
|
118
117
|
for (const id of settledIds) {
|
|
119
118
|
if (prev[id] === undefined) continue;
|
|
120
119
|
if (status === undefined) delete persistence[id];
|
|
@@ -8,7 +8,7 @@ import { type AssistantToolProps, useAssistantTool } from "./useAssistantTool";
|
|
|
8
8
|
* subtree.
|
|
9
9
|
*
|
|
10
10
|
* @deprecated Use a toolkit with `Tools({ toolkit })` and register it via
|
|
11
|
-
* `
|
|
11
|
+
* `AuiConfig({ tools: Tools({ toolkit }) })` on the provider's `config` prop instead. See
|
|
12
12
|
* https://assistant-ui.com/docs/migrations/toolkit-tools.
|
|
13
13
|
*/
|
|
14
14
|
export type AssistantTool = FC & {
|
|
@@ -25,7 +25,7 @@ export type AssistantTool = FC & {
|
|
|
25
25
|
* @param tool - Tool definition and name to register.
|
|
26
26
|
*
|
|
27
27
|
* @deprecated Use a toolkit with `Tools({ toolkit })` and register it via
|
|
28
|
-
* `
|
|
28
|
+
* `AuiConfig({ tools: Tools({ toolkit }) })` on the provider's `config` prop instead. See
|
|
29
29
|
* https://assistant-ui.com/docs/migrations/toolkit-tools.
|
|
30
30
|
*/
|
|
31
31
|
export const makeAssistantTool = <
|