@assistant-ui/core 0.3.15 → 0.3.16
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/internal.d.ts +7 -2
- package/dist/internal.js +8 -3
- package/dist/model-context/frame/host.d.ts.map +1 -1
- package/dist/model-context/frame/host.js +3 -2
- 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 +88 -25
- package/dist/model-context/frame/provider.js.map +1 -1
- package/dist/model-context/interactable-composer-metadata.d.ts +1 -1
- package/dist/model-context/interactable-composer-metadata.js +1 -1
- package/dist/model-context/interactable-composer-metadata.js.map +1 -1
- package/dist/model-context/registry.d.ts +2 -2
- package/dist/model-context/registry.d.ts.map +1 -1
- package/dist/model-context/registry.js +9 -28
- package/dist/model-context/registry.js.map +1 -1
- package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/react/client/InMemoryThreadList.js +24 -20
- 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 +59 -177
- package/dist/react/client/Interactables.js.map +1 -1
- package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
- package/dist/react/client/RemoteThreadList.js +23 -56
- package/dist/react/client/RemoteThreadList.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
- package/dist/react/interactables-legacy/Interactables.js +56 -174
- package/dist/react/interactables-legacy/Interactables.js.map +1 -1
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts +24 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +138 -0
- package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -0
- package/dist/react/primitives/composer/ComposerIf.js.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts +2 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +23 -55
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -1
- package/dist/react/runtimes/assistant-transport/runManager.js +2 -12
- package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +3 -10
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +20 -67
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts +12 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.d.ts.map +1 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js +10 -0
- package/dist/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.js.map +1 -0
- package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -1
- package/dist/react/runtimes/createMessageConverter.d.ts +2 -1
- package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.d.ts +6 -25
- package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
- package/dist/react/runtimes/external-message-converter.js +33 -233
- package/dist/react/runtimes/external-message-converter.js.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +1 -2
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +14 -29
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -4
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +3 -9
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +1 -1
- package/dist/runtime/internal.d.ts +2 -1
- package/dist/runtime/internal.js +2 -1
- package/dist/runtime/queue/external-thread-queue-adapter.d.ts +1 -1
- package/dist/runtime/queue/message-queue.d.ts.map +1 -1
- package/dist/runtime/queue/message-queue.js +1 -1
- package/dist/runtime/queue/message-queue.js.map +1 -1
- package/dist/runtime/queue/queue-item.d.ts +12 -0
- package/dist/runtime/queue/queue-item.d.ts.map +1 -0
- package/dist/runtime/queue/queue-item.js +6 -0
- package/dist/runtime/queue/queue-item.js.map +1 -0
- package/dist/runtime/utils/abortable-thread-load.d.ts +15 -0
- package/dist/runtime/utils/abortable-thread-load.d.ts.map +1 -0
- package/dist/runtime/utils/abortable-thread-load.js +35 -0
- package/dist/runtime/utils/abortable-thread-load.js.map +1 -0
- package/dist/runtime/utils/attachment-add-operations.d.ts +18 -0
- package/dist/runtime/utils/attachment-add-operations.d.ts.map +1 -0
- package/dist/runtime/utils/attachment-add-operations.js +43 -0
- package/dist/runtime/utils/attachment-add-operations.js.map +1 -0
- package/dist/runtime/utils/auto-status.d.ts +6 -1
- package/dist/runtime/utils/auto-status.d.ts.map +1 -1
- package/dist/runtime/utils/auto-status.js +7 -1
- package/dist/runtime/utils/auto-status.js.map +1 -1
- package/dist/runtime/utils/external-message-conversion.d.ts +47 -0
- package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -0
- package/dist/runtime/utils/external-message-conversion.js +221 -0
- package/dist/runtime/utils/external-message-conversion.js.map +1 -0
- package/dist/runtime/utils/external-store-message.d.ts +2 -1
- package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
- package/dist/runtime/utils/external-store-message.js +2 -1
- package/dist/runtime/utils/external-store-message.js.map +1 -1
- package/dist/runtime/utils/message-repository-session.d.ts +30 -0
- package/dist/runtime/utils/message-repository-session.d.ts.map +1 -0
- package/dist/runtime/utils/message-repository-session.js +130 -0
- package/dist/runtime/utils/message-repository-session.js.map +1 -0
- package/dist/runtime/utils/message-repository.d.ts.map +1 -1
- package/dist/runtime/utils/message-repository.js +3 -4
- package/dist/runtime/utils/message-repository.js.map +1 -1
- package/dist/runtime/utils/pending-tool-calls.d.ts +20 -0
- package/dist/runtime/utils/pending-tool-calls.d.ts.map +1 -0
- package/dist/runtime/utils/pending-tool-calls.js +22 -0
- package/dist/runtime/utils/pending-tool-calls.js.map +1 -0
- package/dist/runtime/utils/thread-message-like.d.ts +2 -1
- package/dist/runtime/utils/thread-message-like.d.ts.map +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 +2 -5
- 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 +3 -10
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +19 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +122 -20
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +20 -2
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +12 -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 +77 -1
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -0
- package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
- package/dist/store/clients/external-thread.d.ts.map +1 -1
- package/dist/store/clients/external-thread.js +74 -99
- package/dist/store/clients/external-thread.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 -1
- 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 +16 -7
- package/dist/store/clients/suggestions.js.map +1 -1
- package/dist/store/index.d.ts +4 -2
- package/dist/store/scope-registration.d.ts +1 -1
- package/dist/store/scopes/composer.d.ts +2 -1
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +1 -1
- package/dist/store/scopes/queue-item.d.ts +2 -9
- package/dist/store/scopes/queue-item.d.ts.map +1 -1
- package/dist/store/scopes/queue-item.js +0 -6
- package/dist/types/message.d.ts +7 -3
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js.map +1 -1
- package/dist/utils/data-url.d.ts +14 -1
- package/dist/utils/data-url.d.ts.map +1 -1
- package/dist/utils/data-url.js +13 -1
- package/dist/utils/data-url.js.map +1 -1
- package/dist/utils/invoke-user-callback.d.ts +5 -0
- package/dist/utils/invoke-user-callback.d.ts.map +1 -0
- package/dist/utils/invoke-user-callback.js +19 -0
- package/dist/utils/invoke-user-callback.js.map +1 -0
- package/dist/utils/normalizePartStatus.js.map +1 -1
- package/package.json +10 -10
- package/src/internal.ts +12 -0
- package/src/model-context/frame/host.test.ts +91 -7
- package/src/model-context/frame/host.ts +7 -2
- package/src/model-context/frame/provider.test.ts +267 -12
- package/src/model-context/frame/provider.ts +113 -31
- package/src/model-context/interactable-composer-metadata.ts +1 -1
- package/src/model-context/registry.test.ts +44 -0
- package/src/model-context/registry.ts +13 -35
- package/src/react/client/InMemoryThreadList.test.tsx +49 -0
- package/src/react/client/InMemoryThreadList.ts +7 -1
- package/src/react/client/Interactables.ts +19 -178
- package/src/react/client/RemoteThreadList.test.ts +96 -0
- package/src/react/client/RemoteThreadList.ts +27 -59
- package/src/react/interactables-legacy/Interactables.ts +20 -177
- package/src/react/interactables-shared/useInteractablePersistenceQueue.test.tsx +161 -0
- package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +206 -0
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +26 -56
- package/src/react/runtimes/assistant-transport/runManager.ts +4 -17
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +92 -0
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +40 -141
- package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.test.ts +37 -0
- package/src/react/runtimes/cloud/createCloudThreadListAdapterCreateFallback.ts +18 -0
- package/src/react/runtimes/external-message-converter.test.ts +0 -14
- package/src/react/runtimes/external-message-converter.test.tsx +77 -0
- package/src/react/runtimes/external-message-converter.ts +58 -481
- package/src/runtime/api/composer-runtime.ts +1 -1
- package/src/runtime/api/message-runtime.test.ts +28 -1
- package/src/runtime/base/base-composer-runtime-core.ts +20 -40
- package/src/runtime/base/base-thread-runtime-core.test.ts +16 -0
- package/src/runtime/base/base-thread-runtime-core.ts +6 -11
- package/src/runtime/base/default-thread-composer-runtime-core.ts +1 -4
- package/src/runtime/interfaces/composer-runtime-core.ts +1 -1
- package/src/runtime/interfaces/thread-runtime-core.ts +1 -1
- package/src/runtime/internal.ts +5 -0
- package/src/runtime/queue/external-thread-queue-adapter.ts +1 -1
- package/src/runtime/queue/message-queue.ts +1 -4
- package/src/runtime/queue/queue-item.ts +10 -0
- package/src/runtime/utils/abortable-thread-load.test.ts +87 -0
- package/src/runtime/utils/abortable-thread-load.ts +53 -0
- package/src/runtime/utils/attachment-add-operations.ts +59 -0
- package/src/runtime/utils/auto-status.ts +33 -0
- package/src/runtime/utils/external-message-conversion.test.ts +113 -0
- package/src/runtime/utils/external-message-conversion.ts +494 -0
- package/src/runtime/utils/external-store-message.ts +2 -0
- package/src/runtime/utils/message-repository-session.test.ts +195 -0
- package/src/runtime/utils/message-repository-session.ts +176 -0
- package/src/runtime/utils/message-repository.ts +7 -4
- package/src/runtime/utils/pending-tool-calls.test.ts +57 -0
- package/src/runtime/utils/pending-tool-calls.ts +35 -0
- package/src/runtime/utils/thread-message-like.ts +2 -0
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +6 -14
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +175 -28
- package/src/runtimes/local/local-thread-runtime-core.test.ts +172 -1
- package/src/runtimes/local/local-thread-runtime-core.ts +48 -3
- package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +37 -0
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +123 -0
- package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +140 -0
- package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +3 -0
- package/src/store/clients/external-thread.ts +16 -61
- package/src/store/clients/single-thread-list.ts +4 -1
- package/src/store/clients/suggestions.test.ts +31 -0
- package/src/store/clients/suggestions.ts +18 -19
- package/src/store/scopes/message.ts +1 -1
- package/src/store/scopes/queue-item.ts +2 -9
- package/src/tests/MessageRepository.test.ts +77 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +194 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +158 -0
- package/src/tests/external-store-thread-runtime-core-adapter.test.ts +164 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +642 -0
- package/src/tests/external-thread-attachments.test.tsx +173 -0
- package/src/tests/single-thread-list-item.test.tsx +47 -0
- package/src/tests/thread-message-like.test.ts +39 -1
- package/src/types/message.ts +8 -3
- package/src/utils/data-url.test.ts +52 -1
- package/src/utils/data-url.ts +21 -0
- package/src/utils/invoke-user-callback.test.ts +82 -0
- package/src/utils/invoke-user-callback.ts +31 -0
- package/src/utils/normalizePartStatus.ts +1 -1
- package/dist/store/scopes/queue-item.js.map +0 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ThreadListRuntimeCore } from "../../runtime/interfaces/thread-list-runtime-core";
|
|
2
|
-
import { generateId } from "../../utils/id";
|
|
3
2
|
import { BaseSubscribable } from "../../subscribable/subscribable";
|
|
4
3
|
import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-state";
|
|
5
4
|
import { EMPTY_THREAD_CORE } from "../../runtimes/remote-thread-list/empty-thread-core";
|
|
@@ -9,10 +8,14 @@ import type {
|
|
|
9
8
|
} from "../../runtimes/remote-thread-list/remote-thread-state";
|
|
10
9
|
import {
|
|
11
10
|
classifyThreads,
|
|
11
|
+
createEmptyRemoteThreadState,
|
|
12
12
|
createThreadMappingId,
|
|
13
13
|
getThreadData,
|
|
14
14
|
normalizeCursor,
|
|
15
15
|
updateStatusReducer,
|
|
16
|
+
preserveMidLoadTransitions,
|
|
17
|
+
seedNewThread,
|
|
18
|
+
statusSnapshot,
|
|
16
19
|
} from "../../runtimes/remote-thread-list/remote-thread-state";
|
|
17
20
|
import type {
|
|
18
21
|
RemoteThreadListAdapter,
|
|
@@ -49,47 +52,7 @@ const threadStatusError = (
|
|
|
49
52
|
`Thread "${threadIdOrRemoteId}" has status "${status}", so it cannot ${action}.`,
|
|
50
53
|
);
|
|
51
54
|
|
|
52
|
-
const EMPTY_REMOTE_STATE
|
|
53
|
-
isLoading: true,
|
|
54
|
-
isLoadingMore: false,
|
|
55
|
-
cursor: undefined,
|
|
56
|
-
newThreadId: undefined,
|
|
57
|
-
threadIds: [],
|
|
58
|
-
archivedThreadIds: [],
|
|
59
|
-
threadIdMap: {},
|
|
60
|
-
threadData: {},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const addNewThread = (state: RemoteThreadState) => {
|
|
64
|
-
let id: string;
|
|
65
|
-
do {
|
|
66
|
-
id = `__LOCALID_${generateId()}`;
|
|
67
|
-
} while (state.threadIdMap[id]);
|
|
68
|
-
|
|
69
|
-
const mappingId = createThreadMappingId(id);
|
|
70
|
-
return {
|
|
71
|
-
id,
|
|
72
|
-
state: {
|
|
73
|
-
...state,
|
|
74
|
-
newThreadId: id,
|
|
75
|
-
threadIdMap: {
|
|
76
|
-
...state.threadIdMap,
|
|
77
|
-
[id]: mappingId,
|
|
78
|
-
},
|
|
79
|
-
threadData: {
|
|
80
|
-
...state.threadData,
|
|
81
|
-
[mappingId]: {
|
|
82
|
-
status: "new",
|
|
83
|
-
id,
|
|
84
|
-
remoteId: undefined,
|
|
85
|
-
externalId: undefined,
|
|
86
|
-
title: undefined,
|
|
87
|
-
custom: undefined,
|
|
88
|
-
} satisfies RemoteThreadData,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
};
|
|
55
|
+
const EMPTY_REMOTE_STATE = createEmptyRemoteThreadState();
|
|
93
56
|
|
|
94
57
|
export class RemoteThreadListThreadListRuntimeCore
|
|
95
58
|
extends BaseSubscribable
|
|
@@ -158,6 +121,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
158
121
|
if (!this._loadThreadsPromise) {
|
|
159
122
|
const generation = this._loadGeneration;
|
|
160
123
|
let replacedList = false;
|
|
124
|
+
const statusAtRequest = statusSnapshot(this._state.baseValue);
|
|
161
125
|
this._loadThreadsPromise = this._state
|
|
162
126
|
.optimisticUpdate({
|
|
163
127
|
execute: () => this._options.adapter.list(),
|
|
@@ -186,7 +150,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
186
150
|
threadIdMap: {},
|
|
187
151
|
threadData: {},
|
|
188
152
|
});
|
|
189
|
-
|
|
153
|
+
const merged = {
|
|
190
154
|
...state,
|
|
191
155
|
isLoading: false,
|
|
192
156
|
cursor: normalizeCursor(l.nextCursor),
|
|
@@ -195,6 +159,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
195
159
|
threadIdMap: { ...state.threadIdMap, ...fresh.threadIdMap },
|
|
196
160
|
threadData: { ...state.threadData, ...fresh.threadData },
|
|
197
161
|
};
|
|
162
|
+
return preserveMidLoadTransitions(merged, state, statusAtRequest);
|
|
198
163
|
},
|
|
199
164
|
})
|
|
200
165
|
.catch((error: unknown) => {
|
|
@@ -437,7 +402,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
437
402
|
if (preservedDraft !== undefined) {
|
|
438
403
|
this._mainThreadId = preservedDraft;
|
|
439
404
|
} else {
|
|
440
|
-
const seeded =
|
|
405
|
+
const seeded = seedNewThread(nextState);
|
|
441
406
|
this._mainThreadId = seeded.id;
|
|
442
407
|
nextState = seeded.state;
|
|
443
408
|
}
|
|
@@ -762,7 +727,7 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
762
727
|
const state = this._state.baseValue;
|
|
763
728
|
let id: string | undefined = this._state.value.newThreadId;
|
|
764
729
|
if (id === undefined) {
|
|
765
|
-
const next =
|
|
730
|
+
const next = seedNewThread(state);
|
|
766
731
|
id = next.id;
|
|
767
732
|
this._state.update(next.state);
|
|
768
733
|
}
|
|
@@ -857,17 +822,22 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
857
822
|
for await (const result of messageStream) {
|
|
858
823
|
if (adapterGeneration !== this._adapterGeneration) return;
|
|
859
824
|
const newTitle = result.parts.filter((c) => c.type === "text")[0]?.text;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
825
|
+
await this._state.optimisticUpdate({
|
|
826
|
+
execute: async () => {},
|
|
827
|
+
optimistic: (state) => {
|
|
828
|
+
if (adapterGeneration !== this._adapterGeneration) return state;
|
|
829
|
+
const currentData = getThreadData(state, data.id);
|
|
830
|
+
if (!currentData) return state;
|
|
831
|
+
return {
|
|
832
|
+
...state,
|
|
833
|
+
threadData: {
|
|
834
|
+
...state.threadData,
|
|
835
|
+
[currentData.id]: {
|
|
836
|
+
...currentData,
|
|
837
|
+
title: newTitle,
|
|
838
|
+
},
|
|
839
|
+
},
|
|
840
|
+
};
|
|
871
841
|
},
|
|
872
842
|
});
|
|
873
843
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { invokeUserCallback } from "../../../utils/invoke-user-callback";
|
|
2
3
|
import { useLatestRef } from "./useLatestRef";
|
|
3
4
|
|
|
4
5
|
export type RunManager = Readonly<{
|
|
@@ -11,25 +12,11 @@ const disposeReason = Symbol("assistant-transport-dispose");
|
|
|
11
12
|
|
|
12
13
|
type LifecycleCallbackName = "onCancel" | "onError" | "onFinish";
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
console.error(
|
|
16
|
-
`[assistant-ui] Assistant transport ${name} callback threw an error`,
|
|
17
|
-
error,
|
|
18
|
-
);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const invokeCallback = async (
|
|
15
|
+
const invokeCallback = (
|
|
22
16
|
name: LifecycleCallbackName,
|
|
23
17
|
callback: (() => unknown) | undefined,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
await callback?.();
|
|
27
|
-
} catch (error) {
|
|
28
|
-
try {
|
|
29
|
-
reportCallbackError(name, error);
|
|
30
|
-
} catch {}
|
|
31
|
-
}
|
|
32
|
-
};
|
|
18
|
+
) =>
|
|
19
|
+
invokeUserCallback("assistant-ui", `Assistant transport ${name}`, callback);
|
|
33
20
|
|
|
34
21
|
export function useRunManager(config: {
|
|
35
22
|
onRun: (signal: AbortSignal) => Promise<void>;
|
|
@@ -188,6 +188,98 @@ describe("useAssistantCloudThreadHistoryAdapter", () => {
|
|
|
188
188
|
);
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
it("reports frontend and MCP sources for ai-sdk/v6 tool calls", () => {
|
|
192
|
+
mocks.aui = mocks.makeClient("thread-1");
|
|
193
|
+
const cloud = makeCloud();
|
|
194
|
+
const cloudRef = { current: cloud };
|
|
195
|
+
const { result } = renderHook(() =>
|
|
196
|
+
useAssistantCloudThreadHistoryAdapter(cloudRef),
|
|
197
|
+
);
|
|
198
|
+
const formatted = result.current.withFormat({
|
|
199
|
+
format: "ai-sdk/v6",
|
|
200
|
+
encode: ({ message }) => message,
|
|
201
|
+
decode: ({ parent_id, content }) => ({
|
|
202
|
+
parentId: parent_id,
|
|
203
|
+
message: content as { id: string },
|
|
204
|
+
}),
|
|
205
|
+
getId: (message: { id: string }) => message.id,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
formatted.reportTelemetry([
|
|
209
|
+
{
|
|
210
|
+
parentId: null,
|
|
211
|
+
message: {
|
|
212
|
+
id: "message-1",
|
|
213
|
+
role: "assistant",
|
|
214
|
+
parts: [
|
|
215
|
+
{ type: "step-start" },
|
|
216
|
+
{
|
|
217
|
+
type: "tool-search",
|
|
218
|
+
toolCallId: "static-1",
|
|
219
|
+
input: { query: "test" },
|
|
220
|
+
output: { result: "ok" },
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
type: "dynamic-tool",
|
|
224
|
+
toolName: "mcp-search",
|
|
225
|
+
toolCallId: "dynamic-1",
|
|
226
|
+
input: { query: "test" },
|
|
227
|
+
output: { result: "ok" },
|
|
228
|
+
},
|
|
229
|
+
{ type: "step-start" },
|
|
230
|
+
{
|
|
231
|
+
type: "tool-search",
|
|
232
|
+
toolCallId: "static-2",
|
|
233
|
+
input: { query: "again" },
|
|
234
|
+
output: { result: "ok" },
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
expect(cloud.runs.report).toHaveBeenCalledWith(
|
|
242
|
+
expect.objectContaining({
|
|
243
|
+
tool_calls: [
|
|
244
|
+
expect.objectContaining({
|
|
245
|
+
tool_call_id: "static-1",
|
|
246
|
+
tool_source: "frontend",
|
|
247
|
+
}),
|
|
248
|
+
expect.objectContaining({
|
|
249
|
+
tool_call_id: "dynamic-1",
|
|
250
|
+
tool_source: "mcp",
|
|
251
|
+
}),
|
|
252
|
+
expect.objectContaining({
|
|
253
|
+
tool_call_id: "static-2",
|
|
254
|
+
tool_source: "frontend",
|
|
255
|
+
}),
|
|
256
|
+
],
|
|
257
|
+
steps: [
|
|
258
|
+
{
|
|
259
|
+
tool_calls: [
|
|
260
|
+
expect.objectContaining({
|
|
261
|
+
tool_call_id: "static-1",
|
|
262
|
+
tool_source: "frontend",
|
|
263
|
+
}),
|
|
264
|
+
expect.objectContaining({
|
|
265
|
+
tool_call_id: "dynamic-1",
|
|
266
|
+
tool_source: "mcp",
|
|
267
|
+
}),
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
tool_calls: [
|
|
272
|
+
expect.objectContaining({
|
|
273
|
+
tool_call_id: "static-2",
|
|
274
|
+
tool_source: "frontend",
|
|
275
|
+
}),
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
191
283
|
it("initializes the pinned item instead of the new main thread", async () => {
|
|
192
284
|
mocks.aui = mocks.makeClient(undefined, "new-thread", "thread-1");
|
|
193
285
|
const cloud = makeCloud();
|
|
@@ -9,8 +9,13 @@ import type {
|
|
|
9
9
|
import type { ExportedMessageRepositoryItem } from "../../../runtime/utils/message-repository";
|
|
10
10
|
import {
|
|
11
11
|
type AssistantCloud,
|
|
12
|
+
type AssistantCloudRunReportToolCall,
|
|
12
13
|
CloudMessagePersistence,
|
|
13
14
|
createFormattedPersistence,
|
|
15
|
+
createRunTelemetryToolCall,
|
|
16
|
+
normalizeRunTelemetryUsage,
|
|
17
|
+
type RunTelemetryUsageInit,
|
|
18
|
+
truncateRunTelemetryText,
|
|
14
19
|
} from "assistant-cloud";
|
|
15
20
|
import { auiV0Decode, auiV0Encode } from "./auiV0";
|
|
16
21
|
import { type AssistantClient, getClientId, useAui } from "@assistant-ui/store";
|
|
@@ -268,85 +273,12 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
268
273
|
}
|
|
269
274
|
}
|
|
270
275
|
|
|
271
|
-
const MAX_SPAN_CONTENT = 50_000;
|
|
272
|
-
|
|
273
|
-
function truncateStr(value: string): string {
|
|
274
|
-
if (value.length <= MAX_SPAN_CONTENT) return value;
|
|
275
|
-
return value.slice(0, MAX_SPAN_CONTENT);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function safeStringify(value: unknown): string | undefined {
|
|
279
|
-
if (value == null) return undefined;
|
|
280
|
-
try {
|
|
281
|
-
return truncateStr(JSON.stringify(value));
|
|
282
|
-
} catch {
|
|
283
|
-
return undefined;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
type TelemetryToolCall = {
|
|
288
|
-
tool_name: string;
|
|
289
|
-
tool_call_id: string;
|
|
290
|
-
tool_args?: string;
|
|
291
|
-
tool_result?: string;
|
|
292
|
-
tool_source?: "mcp" | "frontend" | "backend";
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
const BASE64_PATTERN = /^[A-Za-z0-9+/]{100,}={0,2}$/;
|
|
296
|
-
|
|
297
|
-
function summarizeMcpResult(value: unknown): string | undefined {
|
|
298
|
-
if (value == null) return undefined;
|
|
299
|
-
try {
|
|
300
|
-
const parsed = typeof value === "string" ? JSON.parse(value) : value;
|
|
301
|
-
if (Array.isArray(parsed)) {
|
|
302
|
-
const summarized = parsed.map((item) => {
|
|
303
|
-
if (item && typeof item === "object" && item.type) {
|
|
304
|
-
if (
|
|
305
|
-
(item.type === "image" || item.type === "audio") &&
|
|
306
|
-
typeof item.data === "string" &&
|
|
307
|
-
BASE64_PATTERN.test(item.data.slice(0, 200))
|
|
308
|
-
) {
|
|
309
|
-
const sizeKB = ((item.data.length * 3) / 4 / 1024).toFixed(1);
|
|
310
|
-
return { ...item, data: `[${item.type}: ${sizeKB}KB]` };
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return item;
|
|
314
|
-
});
|
|
315
|
-
return truncateStr(JSON.stringify(summarized));
|
|
316
|
-
}
|
|
317
|
-
} catch {
|
|
318
|
-
// not JSON array, fall through
|
|
319
|
-
}
|
|
320
|
-
return safeStringify(value);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function buildToolCall(
|
|
324
|
-
toolName: string,
|
|
325
|
-
toolCallId: string,
|
|
326
|
-
args: unknown,
|
|
327
|
-
result: unknown,
|
|
328
|
-
argsText?: string,
|
|
329
|
-
toolSource?: "mcp" | "frontend" | "backend",
|
|
330
|
-
): TelemetryToolCall {
|
|
331
|
-
const call: TelemetryToolCall = {
|
|
332
|
-
tool_name: toolName,
|
|
333
|
-
tool_call_id: toolCallId,
|
|
334
|
-
};
|
|
335
|
-
const toolArgs = argsText ?? safeStringify(args);
|
|
336
|
-
if (toolArgs !== undefined) call.tool_args = toolArgs;
|
|
337
|
-
const toolResult =
|
|
338
|
-
toolSource === "mcp" ? summarizeMcpResult(result) : safeStringify(result);
|
|
339
|
-
if (toolResult !== undefined) call.tool_result = toolResult;
|
|
340
|
-
if (toolSource) call.tool_source = toolSource;
|
|
341
|
-
return call;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
276
|
type TelemetryStepData = {
|
|
345
277
|
input_tokens?: number;
|
|
346
278
|
output_tokens?: number;
|
|
347
279
|
reasoning_tokens?: number;
|
|
348
280
|
cached_input_tokens?: number;
|
|
349
|
-
tool_calls?:
|
|
281
|
+
tool_calls?: AssistantCloudRunReportToolCall[];
|
|
350
282
|
start_ms?: number;
|
|
351
283
|
end_ms?: number;
|
|
352
284
|
};
|
|
@@ -369,7 +301,7 @@ function mergeStepTimestamps(
|
|
|
369
301
|
|
|
370
302
|
type TelemetryData = {
|
|
371
303
|
status: "completed" | "incomplete" | "error";
|
|
372
|
-
toolCalls?:
|
|
304
|
+
toolCalls?: AssistantCloudRunReportToolCall[];
|
|
373
305
|
totalSteps?: number;
|
|
374
306
|
inputTokens?: number;
|
|
375
307
|
outputTokens?: number;
|
|
@@ -446,13 +378,19 @@ export function extractAuiV0<T>(content: T): TelemetryData | null {
|
|
|
446
378
|
const toolCalls = msg.content
|
|
447
379
|
?.filter((p) => p.type === "tool-call" && p.toolName && p.toolCallId)
|
|
448
380
|
.map((p) =>
|
|
449
|
-
|
|
381
|
+
createRunTelemetryToolCall({
|
|
382
|
+
toolName: p.toolName!,
|
|
383
|
+
toolCallId: p.toolCallId!,
|
|
384
|
+
args: p.args,
|
|
385
|
+
result: p.result,
|
|
386
|
+
argsText: p.argsText,
|
|
387
|
+
}),
|
|
450
388
|
);
|
|
451
389
|
|
|
452
390
|
const textParts = msg.content?.filter((p) => p.type === "text" && p.text);
|
|
453
391
|
const outputText =
|
|
454
392
|
textParts && textParts.length > 0
|
|
455
|
-
?
|
|
393
|
+
? truncateRunTelemetryText(textParts.map((p) => p.text).join(""))
|
|
456
394
|
: undefined;
|
|
457
395
|
|
|
458
396
|
const steps = msg.metadata?.steps;
|
|
@@ -564,29 +502,28 @@ function isDynamicToolPart(p: AiSdkV6Part): boolean {
|
|
|
564
502
|
return p.type === "dynamic-tool" || p.type.startsWith("dynamic-tool-");
|
|
565
503
|
}
|
|
566
504
|
|
|
567
|
-
function partToToolCall(p: AiSdkV6Part):
|
|
568
|
-
const toolSource: "mcp" |
|
|
505
|
+
function partToToolCall(p: AiSdkV6Part): AssistantCloudRunReportToolCall {
|
|
506
|
+
const toolSource: "mcp" | "frontend" = isDynamicToolPart(p)
|
|
569
507
|
? "mcp"
|
|
570
|
-
:
|
|
571
|
-
return
|
|
572
|
-
p.toolName ?? p.type.slice(5),
|
|
573
|
-
p.toolCallId!,
|
|
574
|
-
p.args ?? p.input,
|
|
575
|
-
p.result ?? p.output,
|
|
576
|
-
undefined,
|
|
508
|
+
: "frontend";
|
|
509
|
+
return createRunTelemetryToolCall({
|
|
510
|
+
toolName: p.toolName ?? p.type.slice(5),
|
|
511
|
+
toolCallId: p.toolCallId!,
|
|
512
|
+
args: p.args ?? p.input,
|
|
513
|
+
result: p.result ?? p.output,
|
|
577
514
|
toolSource,
|
|
578
|
-
);
|
|
515
|
+
});
|
|
579
516
|
}
|
|
580
517
|
|
|
581
518
|
function collectAiSdkV6Parts(parts: readonly AiSdkV6Part[]): {
|
|
582
519
|
textParts: string[];
|
|
583
|
-
toolCalls:
|
|
584
|
-
stepsData: { tool_calls:
|
|
520
|
+
toolCalls: AssistantCloudRunReportToolCall[];
|
|
521
|
+
stepsData: { tool_calls: AssistantCloudRunReportToolCall[] }[];
|
|
585
522
|
} {
|
|
586
523
|
const textParts: string[] = [];
|
|
587
|
-
const toolCalls:
|
|
588
|
-
const stepsData: { tool_calls:
|
|
589
|
-
let currentStepToolCalls:
|
|
524
|
+
const toolCalls: AssistantCloudRunReportToolCall[] = [];
|
|
525
|
+
const stepsData: { tool_calls: AssistantCloudRunReportToolCall[] }[] = [];
|
|
526
|
+
let currentStepToolCalls: AssistantCloudRunReportToolCall[] | null = null;
|
|
590
527
|
|
|
591
528
|
for (const p of parts) {
|
|
592
529
|
if (p.type === "step-start") {
|
|
@@ -624,10 +561,10 @@ function extractModelId(
|
|
|
624
561
|
|
|
625
562
|
function buildAiSdkV6Result(
|
|
626
563
|
textParts: string[],
|
|
627
|
-
toolCalls:
|
|
564
|
+
toolCalls: AssistantCloudRunReportToolCall[],
|
|
628
565
|
totalSteps: number,
|
|
629
566
|
metadata?: Record<string, unknown>,
|
|
630
|
-
stepsData?: { tool_calls:
|
|
567
|
+
stepsData?: { tool_calls: AssistantCloudRunReportToolCall[] }[],
|
|
631
568
|
usage?: {
|
|
632
569
|
inputTokens?: number;
|
|
633
570
|
outputTokens?: number;
|
|
@@ -636,7 +573,9 @@ function buildAiSdkV6Result(
|
|
|
636
573
|
},
|
|
637
574
|
): TelemetryData {
|
|
638
575
|
const hasText = textParts.length > 0;
|
|
639
|
-
const outputText = hasText
|
|
576
|
+
const outputText = hasText
|
|
577
|
+
? truncateRunTelemetryText(textParts.join(""))
|
|
578
|
+
: undefined;
|
|
640
579
|
const modelId = extractModelId(metadata);
|
|
641
580
|
|
|
642
581
|
const steps: TelemetryStepData[] | undefined =
|
|
@@ -671,46 +610,6 @@ function buildAiSdkV6Result(
|
|
|
671
610
|
};
|
|
672
611
|
}
|
|
673
612
|
|
|
674
|
-
type UsageFields = {
|
|
675
|
-
inputTokens?: number;
|
|
676
|
-
outputTokens?: number;
|
|
677
|
-
promptTokens?: number;
|
|
678
|
-
completionTokens?: number;
|
|
679
|
-
reasoningTokens?: number;
|
|
680
|
-
cachedInputTokens?: number;
|
|
681
|
-
};
|
|
682
|
-
|
|
683
|
-
function normalizeUsage(u: UsageFields):
|
|
684
|
-
| {
|
|
685
|
-
inputTokens?: number;
|
|
686
|
-
outputTokens?: number;
|
|
687
|
-
reasoningTokens?: number;
|
|
688
|
-
cachedInputTokens?: number;
|
|
689
|
-
}
|
|
690
|
-
| undefined {
|
|
691
|
-
const input = u.inputTokens ?? u.promptTokens;
|
|
692
|
-
const output = u.outputTokens ?? u.completionTokens;
|
|
693
|
-
if (
|
|
694
|
-
input == null &&
|
|
695
|
-
output == null &&
|
|
696
|
-
u.reasoningTokens == null &&
|
|
697
|
-
u.cachedInputTokens == null
|
|
698
|
-
) {
|
|
699
|
-
return undefined;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
return {
|
|
703
|
-
...(input != null ? { inputTokens: input } : undefined),
|
|
704
|
-
...(output != null ? { outputTokens: output } : undefined),
|
|
705
|
-
...(u.reasoningTokens != null
|
|
706
|
-
? { reasoningTokens: u.reasoningTokens }
|
|
707
|
-
: undefined),
|
|
708
|
-
...(u.cachedInputTokens != null
|
|
709
|
-
? { cachedInputTokens: u.cachedInputTokens }
|
|
710
|
-
: undefined),
|
|
711
|
-
};
|
|
712
|
-
}
|
|
713
|
-
|
|
714
613
|
function extractAiSdkV6Usage(metadata?: Record<string, unknown>):
|
|
715
614
|
| {
|
|
716
615
|
inputTokens?: number;
|
|
@@ -720,15 +619,15 @@ function extractAiSdkV6Usage(metadata?: Record<string, unknown>):
|
|
|
720
619
|
}
|
|
721
620
|
| undefined {
|
|
722
621
|
// Try top-level metadata.usage
|
|
723
|
-
const usage = metadata?.usage as
|
|
622
|
+
const usage = metadata?.usage as RunTelemetryUsageInit | undefined;
|
|
724
623
|
if (usage) {
|
|
725
|
-
const normalized =
|
|
624
|
+
const normalized = normalizeRunTelemetryUsage(usage);
|
|
726
625
|
if (normalized) return normalized;
|
|
727
626
|
}
|
|
728
627
|
|
|
729
628
|
// Try aggregating from metadata.steps[].usage
|
|
730
629
|
const steps = metadata?.steps as
|
|
731
|
-
| readonly { usage?:
|
|
630
|
+
| readonly { usage?: RunTelemetryUsageInit }[]
|
|
732
631
|
| undefined;
|
|
733
632
|
if (steps && steps.length > 0) {
|
|
734
633
|
let inputTokens = 0;
|
|
@@ -742,7 +641,7 @@ function extractAiSdkV6Usage(metadata?: Record<string, unknown>):
|
|
|
742
641
|
let hasAny = false;
|
|
743
642
|
for (const s of steps) {
|
|
744
643
|
if (!s.usage) continue;
|
|
745
|
-
const n =
|
|
644
|
+
const n = normalizeRunTelemetryUsage(s.usage);
|
|
746
645
|
if (n) {
|
|
747
646
|
if (n.inputTokens != null) {
|
|
748
647
|
inputTokens += n.inputTokens;
|
|
@@ -795,8 +694,8 @@ function extractAiSdkV6<T>(content: T): TelemetryData | null {
|
|
|
795
694
|
|
|
796
695
|
function aggregateAiSdkV6RunSteps<T>(stepMessages: T[]): TelemetryData | null {
|
|
797
696
|
const allTextParts: string[] = [];
|
|
798
|
-
const allToolCalls:
|
|
799
|
-
const allStepsData: { tool_calls:
|
|
697
|
+
const allToolCalls: AssistantCloudRunReportToolCall[] = [];
|
|
698
|
+
const allStepsData: { tool_calls: AssistantCloudRunReportToolCall[] }[] = [];
|
|
800
699
|
let hasAssistant = false;
|
|
801
700
|
let metadata: Record<string, unknown> | undefined;
|
|
802
701
|
let inputTokens = 0;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createCloudThreadListAdapterCreateFallback } from "./createCloudThreadListAdapterCreateFallback";
|
|
3
|
+
|
|
4
|
+
describe("createCloudThreadListAdapterCreateFallback", () => {
|
|
5
|
+
it("prefers the custom create function", async () => {
|
|
6
|
+
const create = vi.fn().mockResolvedValue({ externalId: "custom" });
|
|
7
|
+
const initialize = vi.fn().mockResolvedValue({ externalId: "nested" });
|
|
8
|
+
const fallback = createCloudThreadListAdapterCreateFallback(create, {
|
|
9
|
+
source: {},
|
|
10
|
+
initialize,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
await expect(fallback()).resolves.toEqual({ externalId: "custom" });
|
|
14
|
+
expect(initialize).not.toHaveBeenCalled();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("initializes a sourced thread list item", async () => {
|
|
18
|
+
const result = { externalId: "nested" };
|
|
19
|
+
const fallback = createCloudThreadListAdapterCreateFallback(undefined, {
|
|
20
|
+
source: {},
|
|
21
|
+
initialize: vi.fn().mockResolvedValue(result),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
await expect(fallback()).resolves.toBe(result);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("falls back to an undefined external ID", async () => {
|
|
28
|
+
const initialize = vi.fn();
|
|
29
|
+
const fallback = createCloudThreadListAdapterCreateFallback(undefined, {
|
|
30
|
+
source: null,
|
|
31
|
+
initialize,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await expect(fallback()).resolves.toEqual({ externalId: undefined });
|
|
35
|
+
expect(initialize).not.toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type ThreadData = {
|
|
2
|
+
externalId: string | undefined;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
type ThreadListItem = {
|
|
6
|
+
source: unknown;
|
|
7
|
+
initialize: () => Promise<ThreadData>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const createCloudThreadListAdapterCreateFallback = (
|
|
11
|
+
create: (() => Promise<ThreadData>) | undefined,
|
|
12
|
+
threadListItem: ThreadListItem,
|
|
13
|
+
): (() => Promise<ThreadData>) =>
|
|
14
|
+
async function createThread() {
|
|
15
|
+
if (create) return create();
|
|
16
|
+
if (threadListItem.source) return threadListItem.initialize();
|
|
17
|
+
return { externalId: undefined };
|
|
18
|
+
};
|
|
@@ -542,19 +542,5 @@ describe("convertExternalMessages", () => {
|
|
|
542
542
|
convertExternalMessages(messages, callback, false, {}),
|
|
543
543
|
).toThrowError(/returned an invalid message \(\{"role":"user"\}\)/);
|
|
544
544
|
});
|
|
545
|
-
|
|
546
|
-
it("tolerates a tool message without toolCallId as an orphaned tool result", () => {
|
|
547
|
-
const messages = [{ id: "m1", role: "user" as const, content: "hi" }];
|
|
548
|
-
const callback = ((msg: (typeof messages)[number]) => [
|
|
549
|
-
msg,
|
|
550
|
-
{ role: "tool", result: "ok" },
|
|
551
|
-
]) as unknown as useExternalMessageConverter.Callback<
|
|
552
|
-
(typeof messages)[number]
|
|
553
|
-
>;
|
|
554
|
-
|
|
555
|
-
const result = convertExternalMessages(messages, callback, false, {});
|
|
556
|
-
expect(result[0]!.role).toBe("user");
|
|
557
|
-
expect(result[1]!.content).toHaveLength(0);
|
|
558
|
-
});
|
|
559
545
|
});
|
|
560
546
|
});
|