@assistant-ui/core 0.1.16 → 0.2.0
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/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts +5 -0
- package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -0
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +11 -0
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -0
- package/dist/react/primitives/message/MessageGroupedParts.d.ts +104 -0
- package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -0
- package/dist/react/primitives/message/MessageGroupedParts.js +74 -0
- package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -0
- package/dist/react/primitives/message/MessageParts.d.ts +8 -1
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +45 -42
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -4
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +4 -3
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -6
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +86 -38
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +1 -1
- package/dist/react/utils/groupParts.d.ts +49 -0
- package/dist/react/utils/groupParts.d.ts.map +1 -0
- package/dist/react/utils/groupParts.js +97 -0
- package/dist/react/utils/groupParts.js.map +1 -0
- package/dist/runtime/api/assistant-runtime.d.ts +0 -33
- package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
- package/dist/runtime/api/assistant-runtime.js +0 -23
- package/dist/runtime/api/assistant-runtime.js.map +1 -1
- package/dist/runtime/api/bindings.d.ts +1 -3
- package/dist/runtime/api/bindings.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +3 -3
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +1 -1
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/message-runtime.d.ts +1 -6
- package/dist/runtime/api/message-runtime.d.ts.map +1 -1
- package/dist/runtime/api/message-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.d.ts +18 -3
- package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js +1 -1
- package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
- package/dist/runtime/api/thread-list-runtime.d.ts +4 -0
- package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-list-runtime.js +6 -0
- package/dist/runtime/api/thread-list-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +6 -29
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +2 -21
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +4 -3
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +47 -33
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +3 -4
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +11 -11
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +28 -2
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +3 -0
- package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +35 -4
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/utils/chat-model-adapter.d.ts +0 -4
- package/dist/runtime/utils/chat-model-adapter.d.ts.map +1 -1
- package/dist/runtime/utils/external-store-message.d.ts +0 -4
- package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
- package/dist/runtime/utils/external-store-message.js +0 -7
- package/dist/runtime/utils/external-store-message.js.map +1 -1
- package/dist/runtimes/assistant-transport/utils.d.ts +0 -9
- package/dist/runtimes/assistant-transport/utils.d.ts.map +1 -1
- package/dist/runtimes/assistant-transport/utils.js +0 -13
- package/dist/runtimes/assistant-transport/utils.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +0 -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 +2 -5
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +0 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +2 -6
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +0 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +0 -3
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +0 -3
- package/dist/runtimes/remote-thread-list/empty-thread-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 +34 -0
- package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
- package/dist/runtimes/remote-thread-list/types.d.ts +5 -1
- package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
- package/dist/store/clients/thread-message-client.d.ts.map +1 -1
- package/dist/store/clients/thread-message-client.js +0 -1
- package/dist/store/clients/thread-message-client.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +5 -6
- package/dist/store/runtime-clients/composer-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 +3 -0
- 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 +0 -1
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +11 -1
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/message.d.ts +1 -3
- package/dist/store/scopes/message.d.ts.map +1 -1
- package/dist/store/scopes/thread-list-item.d.ts +10 -0
- package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +17 -4
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/store/scopes/threads.d.ts +3 -0
- package/dist/store/scopes/threads.d.ts.map +1 -1
- package/dist/subscribable/subscribable.d.ts +4 -4
- package/dist/subscribable/subscribable.d.ts.map +1 -1
- package/dist/subscribable/subscribable.js +4 -4
- package/dist/subscribable/subscribable.js.map +1 -1
- package/package.json +25 -13
- package/src/index.ts +12 -6
- package/src/react/index.ts +3 -0
- package/src/react/primitive-hooks/useThreadListLoadMore.ts +15 -0
- package/src/react/primitives/message/MessageGroupedParts.tsx +186 -0
- package/src/react/primitives/message/MessageParts.tsx +80 -55
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +7 -6
- package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +96 -43
- package/src/react/utils/groupParts.ts +152 -0
- package/src/runtime/api/assistant-runtime.ts +0 -62
- package/src/runtime/api/bindings.ts +1 -6
- package/src/runtime/api/composer-runtime.ts +10 -9
- package/src/runtime/api/message-runtime.ts +1 -8
- package/src/runtime/api/thread-list-item-runtime.ts +28 -6
- package/src/runtime/api/thread-list-runtime.ts +10 -0
- package/src/runtime/api/thread-runtime.ts +12 -53
- package/src/runtime/base/base-composer-runtime-core.ts +85 -42
- package/src/runtime/base/base-thread-runtime-core.ts +21 -13
- package/src/runtime/interfaces/composer-runtime-core.ts +39 -7
- package/src/runtime/interfaces/thread-list-runtime-core.ts +3 -0
- package/src/runtime/interfaces/thread-runtime-core.ts +42 -9
- package/src/runtime/utils/chat-model-adapter.ts +0 -5
- package/src/runtime/utils/external-store-message.ts +0 -8
- package/src/runtimes/assistant-transport/utils.ts +0 -28
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +2 -6
- package/src/runtimes/local/local-thread-runtime-core.ts +2 -7
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +0 -4
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +0 -4
- package/src/runtimes/remote-thread-list/remote-thread-state.ts +54 -1
- package/src/runtimes/remote-thread-list/types.ts +6 -1
- package/src/store/clients/thread-message-client.ts +0 -1
- package/src/store/runtime-clients/composer-runtime-client.ts +5 -9
- package/src/store/runtime-clients/thread-list-runtime-client.ts +3 -0
- package/src/store/runtime-clients/thread-runtime-client.ts +0 -1
- package/src/store/scopes/composer.ts +11 -0
- package/src/store/scopes/message.ts +1 -6
- package/src/store/scopes/thread-list-item.ts +10 -0
- package/src/store/scopes/thread.ts +17 -5
- package/src/store/scopes/threads.ts +3 -0
- package/src/subscribable/subscribable.ts +10 -7
- package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +448 -0
- package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +6 -1
- package/src/tests/base-composer-runtime-core-addAttachment.test.ts +63 -0
- package/src/tests/groupParts.test.ts +114 -0
|
@@ -5,12 +5,13 @@ import { OptimisticState } from "../../runtimes/remote-thread-list/optimistic-st
|
|
|
5
5
|
import { EMPTY_THREAD_CORE } from "../../runtimes/remote-thread-list/empty-thread-core";
|
|
6
6
|
import type {
|
|
7
7
|
RemoteThreadData,
|
|
8
|
-
THREAD_MAPPING_ID,
|
|
9
8
|
RemoteThreadState,
|
|
10
9
|
} from "../../runtimes/remote-thread-list/remote-thread-state";
|
|
11
10
|
import {
|
|
11
|
+
classifyThreads,
|
|
12
12
|
createThreadMappingId,
|
|
13
13
|
getThreadData,
|
|
14
|
+
normalizeCursor,
|
|
14
15
|
updateStatusReducer,
|
|
15
16
|
} from "../../runtimes/remote-thread-list/remote-thread-state";
|
|
16
17
|
import type { RemoteThreadListOptions } from "../../runtimes/remote-thread-list/types";
|
|
@@ -29,11 +30,14 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
29
30
|
private readonly _hookManager: RemoteThreadListHookInstanceManager;
|
|
30
31
|
|
|
31
32
|
private _loadThreadsPromise: Promise<void> | undefined;
|
|
33
|
+
private _loadMorePromise: Promise<void> | undefined;
|
|
32
34
|
private _loadGeneration = 0;
|
|
33
35
|
|
|
34
36
|
private _mainThreadId!: string;
|
|
35
37
|
private readonly _state = new OptimisticState<RemoteThreadState>({
|
|
36
38
|
isLoading: true,
|
|
39
|
+
isLoadingMore: false,
|
|
40
|
+
cursor: undefined,
|
|
37
41
|
newThreadId: undefined,
|
|
38
42
|
threadIds: [],
|
|
39
43
|
archivedThreadIds: [],
|
|
@@ -61,62 +65,33 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
61
65
|
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
62
66
|
then: (state, l) => {
|
|
63
67
|
if (generation !== this._loadGeneration) return state;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
>;
|
|
71
|
-
|
|
72
|
-
for (const thread of l.threads) {
|
|
73
|
-
switch (thread.status) {
|
|
74
|
-
case "regular":
|
|
75
|
-
newThreadIds.push(thread.remoteId);
|
|
76
|
-
break;
|
|
77
|
-
case "archived":
|
|
78
|
-
newArchivedThreadIds.push(thread.remoteId);
|
|
79
|
-
break;
|
|
80
|
-
default: {
|
|
81
|
-
const _exhaustiveCheck: never = thread.status;
|
|
82
|
-
throw new Error(`Unsupported state: ${_exhaustiveCheck}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const mappingId = createThreadMappingId(thread.remoteId);
|
|
87
|
-
newThreadIdMap[thread.remoteId] = mappingId;
|
|
88
|
-
newThreadData[mappingId] = {
|
|
89
|
-
id: thread.remoteId,
|
|
90
|
-
remoteId: thread.remoteId,
|
|
91
|
-
externalId: thread.externalId,
|
|
92
|
-
status: thread.status,
|
|
93
|
-
title: thread.title,
|
|
94
|
-
custom: thread.custom,
|
|
95
|
-
initializeTask: Promise.resolve({
|
|
96
|
-
remoteId: thread.remoteId,
|
|
97
|
-
externalId: thread.externalId,
|
|
98
|
-
}),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
68
|
+
const fresh = classifyThreads(l.threads, {
|
|
69
|
+
threadIds: [],
|
|
70
|
+
archivedThreadIds: [],
|
|
71
|
+
threadIdMap: {},
|
|
72
|
+
threadData: {},
|
|
73
|
+
});
|
|
101
74
|
|
|
102
75
|
return {
|
|
103
76
|
...state,
|
|
104
77
|
isLoading: false,
|
|
105
|
-
|
|
106
|
-
|
|
78
|
+
cursor: normalizeCursor(l.nextCursor),
|
|
79
|
+
threadIds: fresh.threadIds,
|
|
80
|
+
archivedThreadIds: fresh.archivedThreadIds,
|
|
107
81
|
threadIdMap: {
|
|
108
82
|
...state.threadIdMap,
|
|
109
|
-
...
|
|
83
|
+
...fresh.threadIdMap,
|
|
110
84
|
},
|
|
111
85
|
threadData: {
|
|
112
86
|
...state.threadData,
|
|
113
|
-
...
|
|
87
|
+
...fresh.threadData,
|
|
114
88
|
},
|
|
115
89
|
};
|
|
116
90
|
},
|
|
117
91
|
})
|
|
118
|
-
.catch(() => {
|
|
92
|
+
.catch((error: unknown) => {
|
|
119
93
|
if (generation !== this._loadGeneration) return;
|
|
94
|
+
console.error("[assistant-ui] thread list load failed:", error);
|
|
120
95
|
this._loadThreadsPromise = undefined;
|
|
121
96
|
this._state.update({
|
|
122
97
|
...this._state.baseValue,
|
|
@@ -129,6 +104,58 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
129
104
|
return this._loadThreadsPromise;
|
|
130
105
|
}
|
|
131
106
|
|
|
107
|
+
public loadMore(): Promise<void> {
|
|
108
|
+
if (this._loadMorePromise) return this._loadMorePromise;
|
|
109
|
+
|
|
110
|
+
const initialState = this._state.value;
|
|
111
|
+
if (initialState.cursor === undefined || initialState.isLoading) {
|
|
112
|
+
return Promise.resolve();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const generation = this._loadGeneration;
|
|
116
|
+
const adapter = this._options.adapter;
|
|
117
|
+
const cursor = initialState.cursor;
|
|
118
|
+
|
|
119
|
+
const dedup = this._state
|
|
120
|
+
.optimisticUpdate({
|
|
121
|
+
execute: () => adapter.list({ after: cursor }),
|
|
122
|
+
loading: (state) => ({ ...state, isLoadingMore: true }),
|
|
123
|
+
// biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
|
|
124
|
+
then: (state, l) => {
|
|
125
|
+
if (generation !== this._loadGeneration) return state;
|
|
126
|
+
if (adapter !== this._options.adapter) return state;
|
|
127
|
+
|
|
128
|
+
const appended = classifyThreads(l.threads, {
|
|
129
|
+
threadIds: [...state.threadIds],
|
|
130
|
+
archivedThreadIds: [...state.archivedThreadIds],
|
|
131
|
+
threadIdMap: { ...state.threadIdMap },
|
|
132
|
+
threadData: { ...state.threadData },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
...state,
|
|
137
|
+
isLoadingMore: false,
|
|
138
|
+
cursor: normalizeCursor(l.nextCursor),
|
|
139
|
+
threadIds: appended.threadIds,
|
|
140
|
+
archivedThreadIds: appended.archivedThreadIds,
|
|
141
|
+
threadIdMap: appended.threadIdMap,
|
|
142
|
+
threadData: appended.threadData,
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
.catch((error: unknown) => {
|
|
147
|
+
console.error("[assistant-ui] thread list loadMore failed:", error);
|
|
148
|
+
})
|
|
149
|
+
.then(() => {
|
|
150
|
+
if (this._loadMorePromise === dedup) {
|
|
151
|
+
this._loadMorePromise = undefined;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
this._loadMorePromise = dedup;
|
|
156
|
+
return dedup;
|
|
157
|
+
}
|
|
158
|
+
|
|
132
159
|
private readonly contextProvider: ModelContextProvider;
|
|
133
160
|
|
|
134
161
|
constructor(
|
|
@@ -156,6 +183,9 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
156
183
|
public __internal_setOptions(options: RemoteThreadListOptions) {
|
|
157
184
|
if (this._options === options) return;
|
|
158
185
|
|
|
186
|
+
const adapterChanged =
|
|
187
|
+
this._options !== undefined && this._options.adapter !== options.adapter;
|
|
188
|
+
|
|
159
189
|
this._options = options;
|
|
160
190
|
|
|
161
191
|
const Provider = options.adapter.unstable_Provider ?? Fragment;
|
|
@@ -164,6 +194,16 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
164
194
|
}
|
|
165
195
|
|
|
166
196
|
this._hookManager.setRuntimeHook(options.runtimeHook);
|
|
197
|
+
|
|
198
|
+
if (adapterChanged) {
|
|
199
|
+
this._loadGeneration++;
|
|
200
|
+
this._loadThreadsPromise = undefined;
|
|
201
|
+
this._loadMorePromise = undefined;
|
|
202
|
+
this._state.update({
|
|
203
|
+
...this._state.baseValue,
|
|
204
|
+
cursor: undefined,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
167
207
|
}
|
|
168
208
|
|
|
169
209
|
public __internal_load() {
|
|
@@ -179,6 +219,11 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
179
219
|
public reload() {
|
|
180
220
|
this._loadGeneration++;
|
|
181
221
|
this._loadThreadsPromise = undefined;
|
|
222
|
+
this._loadMorePromise = undefined;
|
|
223
|
+
this._state.update({
|
|
224
|
+
...this._state.baseValue,
|
|
225
|
+
cursor: undefined,
|
|
226
|
+
});
|
|
182
227
|
return this.getLoadThreadsPromise();
|
|
183
228
|
}
|
|
184
229
|
|
|
@@ -186,6 +231,14 @@ export class RemoteThreadListThreadListRuntimeCore
|
|
|
186
231
|
return this._state.value.isLoading;
|
|
187
232
|
}
|
|
188
233
|
|
|
234
|
+
public get isLoadingMore() {
|
|
235
|
+
return this._state.value.isLoadingMore;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public get hasMore() {
|
|
239
|
+
return this._state.value.cursor !== undefined;
|
|
240
|
+
}
|
|
241
|
+
|
|
189
242
|
public get threadIds() {
|
|
190
243
|
return this._state.value.threadIds;
|
|
191
244
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hierarchical adjacent-coalescing grouping for message parts.
|
|
3
|
+
*
|
|
4
|
+
* Given a group path per part (from `groupBy`), builds a tree of group
|
|
5
|
+
* nodes wrapping individual parts. Adjacent parts sharing a path prefix
|
|
6
|
+
* coalesce into the same group; ungrouped parts are direct children of
|
|
7
|
+
* the root.
|
|
8
|
+
*
|
|
9
|
+
* Each node gets a structural `nodeKey` built from sibling indices
|
|
10
|
+
* (`"0.1.0"`), stable under append-only streaming.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Public group key type. Group keys must be prefixed with `group-` so
|
|
15
|
+
* that a unified `switch (part.type)` in the renderer can distinguish
|
|
16
|
+
* a group key (e.g. `"group-thought"`) from a real part type
|
|
17
|
+
* (`"text"`, `"tool-call"`).
|
|
18
|
+
*/
|
|
19
|
+
export type GroupKey<TKey extends `group-${string}` = `group-${string}`> =
|
|
20
|
+
| TKey
|
|
21
|
+
| readonly TKey[]
|
|
22
|
+
| null
|
|
23
|
+
| undefined;
|
|
24
|
+
|
|
25
|
+
export type GroupNode = GroupNodeGroup | GroupNodePart;
|
|
26
|
+
|
|
27
|
+
export interface GroupNodeGroup {
|
|
28
|
+
readonly type: "group";
|
|
29
|
+
/** Current-level group key (last segment of the path). */
|
|
30
|
+
readonly key: string;
|
|
31
|
+
/** Structural React key: sibling-index path, e.g. `"0.1.0"`. */
|
|
32
|
+
readonly nodeKey: string;
|
|
33
|
+
/** Indices of parts in this subtree, in order. */
|
|
34
|
+
readonly indices: readonly number[];
|
|
35
|
+
readonly children: readonly GroupNode[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface GroupNodePart {
|
|
39
|
+
readonly type: "part";
|
|
40
|
+
/** Index of the part in the message. */
|
|
41
|
+
readonly index: number;
|
|
42
|
+
/** Structural React key: sibling-index path within parent. */
|
|
43
|
+
readonly nodeKey: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const EMPTY_PATH: readonly string[] = Object.freeze([]);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Normalize a `groupBy` return value to a path array.
|
|
50
|
+
* `null`/`undefined`/`[]` → `[]` (ungrouped).
|
|
51
|
+
* `"foo"` → `["foo"]`. Arrays pass through.
|
|
52
|
+
*/
|
|
53
|
+
export const normalizeGroupKey = (key: GroupKey): readonly string[] => {
|
|
54
|
+
if (key == null) return EMPTY_PATH;
|
|
55
|
+
if (typeof key === "string") return [key];
|
|
56
|
+
return key;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
interface BuildFrame {
|
|
60
|
+
key: string;
|
|
61
|
+
nodeKey: string;
|
|
62
|
+
indices: number[];
|
|
63
|
+
children: GroupNode[];
|
|
64
|
+
nextChildIdx: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const makeChildNodeKey = (parent: BuildFrame): string => {
|
|
68
|
+
const idx = parent.nextChildIdx++;
|
|
69
|
+
return parent.nodeKey === "" ? String(idx) : `${parent.nodeKey}.${idx}`;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build the group tree from an array of normalized group paths.
|
|
74
|
+
* `paths[i]` is the path for part `i`. The output tree contains one
|
|
75
|
+
* `part` node per part and one `group` node per coalesced run.
|
|
76
|
+
*/
|
|
77
|
+
export const buildGroupTree = (
|
|
78
|
+
paths: readonly (readonly string[])[],
|
|
79
|
+
): readonly GroupNode[] => {
|
|
80
|
+
const root: BuildFrame = {
|
|
81
|
+
key: "",
|
|
82
|
+
nodeKey: "",
|
|
83
|
+
indices: [],
|
|
84
|
+
children: [],
|
|
85
|
+
nextChildIdx: 0,
|
|
86
|
+
};
|
|
87
|
+
const stack: BuildFrame[] = [root];
|
|
88
|
+
|
|
89
|
+
const closeTop = (): void => {
|
|
90
|
+
const closing = stack.pop()!;
|
|
91
|
+
const parent = stack[stack.length - 1]!;
|
|
92
|
+
parent.children.push({
|
|
93
|
+
type: "group",
|
|
94
|
+
key: closing.key,
|
|
95
|
+
nodeKey: closing.nodeKey,
|
|
96
|
+
indices: closing.indices,
|
|
97
|
+
children: closing.children,
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < paths.length; i++) {
|
|
102
|
+
const path = paths[i]!;
|
|
103
|
+
|
|
104
|
+
// Find the longest prefix shared between currently-open groups
|
|
105
|
+
// (excluding root) and this part's path.
|
|
106
|
+
let common = 0;
|
|
107
|
+
while (
|
|
108
|
+
common < stack.length - 1 &&
|
|
109
|
+
common < path.length &&
|
|
110
|
+
stack[common + 1]!.key === path[common]
|
|
111
|
+
) {
|
|
112
|
+
common++;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Close groups not on this path.
|
|
116
|
+
while (stack.length - 1 > common) {
|
|
117
|
+
closeTop();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Open new groups down to the part's depth.
|
|
121
|
+
while (stack.length - 1 < path.length) {
|
|
122
|
+
const parent = stack[stack.length - 1]!;
|
|
123
|
+
stack.push({
|
|
124
|
+
key: path[stack.length - 1]!,
|
|
125
|
+
nodeKey: makeChildNodeKey(parent),
|
|
126
|
+
indices: [],
|
|
127
|
+
children: [],
|
|
128
|
+
nextChildIdx: 0,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Push this part as a leaf in the deepest open group (or root).
|
|
133
|
+
const top = stack[stack.length - 1]!;
|
|
134
|
+
top.children.push({
|
|
135
|
+
type: "part",
|
|
136
|
+
index: i,
|
|
137
|
+
nodeKey: makeChildNodeKey(top),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Record the part index in every open ancestor group.
|
|
141
|
+
for (let s = 1; s < stack.length; s++) {
|
|
142
|
+
stack[s]!.indices.push(i);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Close any still-open groups.
|
|
147
|
+
while (stack.length > 1) {
|
|
148
|
+
closeTop();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return root.children;
|
|
152
|
+
};
|
|
@@ -6,8 +6,6 @@ import {
|
|
|
6
6
|
type ThreadListRuntime,
|
|
7
7
|
ThreadListRuntimeImpl,
|
|
8
8
|
} from "./thread-list-runtime";
|
|
9
|
-
import { ExportedMessageRepository } from "../utils/message-repository";
|
|
10
|
-
import type { ThreadMessageLike } from "../utils/thread-message-like";
|
|
11
9
|
|
|
12
10
|
export type AssistantRuntime = {
|
|
13
11
|
/**
|
|
@@ -20,49 +18,16 @@ export type AssistantRuntime = {
|
|
|
20
18
|
*/
|
|
21
19
|
readonly thread: ThreadRuntime;
|
|
22
20
|
|
|
23
|
-
/**
|
|
24
|
-
* @deprecated This field was renamed to `threads`.
|
|
25
|
-
*/
|
|
26
|
-
readonly threadList: ThreadListRuntime;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Switch to a new thread.
|
|
30
|
-
*
|
|
31
|
-
* @deprecated This method was moved to `threads.switchToNewThread`.
|
|
32
|
-
*/
|
|
33
|
-
switchToNewThread(): void;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Switch to a thread.
|
|
37
|
-
*
|
|
38
|
-
* @param threadId The thread ID to switch to.
|
|
39
|
-
* @deprecated This method was moved to `threads.switchToThread`.
|
|
40
|
-
*/
|
|
41
|
-
switchToThread(threadId: string): void;
|
|
42
|
-
|
|
43
21
|
/**
|
|
44
22
|
* Register a model context provider. Model context providers are configuration such as system message, temperature, etc. that are set in the frontend.
|
|
45
23
|
*
|
|
46
24
|
* @param provider The model context provider to register.
|
|
47
25
|
*/
|
|
48
26
|
registerModelContextProvider(provider: ModelContextProvider): Unsubscribe;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @deprecated This method was renamed to `registerModelContextProvider`.
|
|
52
|
-
*/
|
|
53
|
-
registerModelConfigProvider(provider: ModelContextProvider): Unsubscribe;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @deprecated Use `runtime.thread.reset(initialMessages)`.
|
|
57
|
-
*/
|
|
58
|
-
reset: unknown; // make it a type error
|
|
59
27
|
};
|
|
60
28
|
|
|
61
29
|
export class AssistantRuntimeImpl implements AssistantRuntime {
|
|
62
30
|
public readonly threads;
|
|
63
|
-
public get threadList() {
|
|
64
|
-
return this.threads;
|
|
65
|
-
}
|
|
66
31
|
|
|
67
32
|
public readonly _thread: ThreadRuntime;
|
|
68
33
|
|
|
@@ -74,42 +39,15 @@ export class AssistantRuntimeImpl implements AssistantRuntime {
|
|
|
74
39
|
}
|
|
75
40
|
|
|
76
41
|
protected __internal_bindMethods() {
|
|
77
|
-
this.switchToNewThread = this.switchToNewThread.bind(this);
|
|
78
|
-
this.switchToThread = this.switchToThread.bind(this);
|
|
79
42
|
this.registerModelContextProvider =
|
|
80
43
|
this.registerModelContextProvider.bind(this);
|
|
81
|
-
this.registerModelConfigProvider =
|
|
82
|
-
this.registerModelConfigProvider.bind(this);
|
|
83
|
-
this.reset = this.reset.bind(this);
|
|
84
44
|
}
|
|
85
45
|
|
|
86
46
|
public get thread() {
|
|
87
47
|
return this._thread;
|
|
88
48
|
}
|
|
89
49
|
|
|
90
|
-
public switchToNewThread() {
|
|
91
|
-
return this._core.threads.switchToNewThread();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public switchToThread(threadId: string) {
|
|
95
|
-
return this._core.threads.switchToThread(threadId);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
50
|
public registerModelContextProvider(provider: ModelContextProvider) {
|
|
99
51
|
return this._core.registerModelContextProvider(provider);
|
|
100
52
|
}
|
|
101
|
-
|
|
102
|
-
public registerModelConfigProvider(provider: ModelContextProvider) {
|
|
103
|
-
return this.registerModelContextProvider(provider);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public reset({
|
|
107
|
-
initialMessages,
|
|
108
|
-
}: {
|
|
109
|
-
initialMessages?: ThreadMessageLike[];
|
|
110
|
-
} = {}) {
|
|
111
|
-
return this._core.threads
|
|
112
|
-
.getMainThreadRuntimeCore()
|
|
113
|
-
.import(ExportedMessageRepository.fromArray(initialMessages ?? []));
|
|
114
|
-
}
|
|
115
53
|
}
|
|
@@ -5,10 +5,7 @@ import type {
|
|
|
5
5
|
EditComposerRuntimeCore,
|
|
6
6
|
ThreadComposerRuntimeCore,
|
|
7
7
|
} from "../interfaces/composer-runtime-core";
|
|
8
|
-
import type {
|
|
9
|
-
SpeechState,
|
|
10
|
-
SubmittedFeedback,
|
|
11
|
-
} from "../interfaces/thread-runtime-core";
|
|
8
|
+
import type { SpeechState } from "../interfaces/thread-runtime-core";
|
|
12
9
|
import type { ComposerRuntimePath, MessageRuntimePath } from "./paths";
|
|
13
10
|
|
|
14
11
|
export type ComposerRuntimeCoreBinding = SubscribableWithState<
|
|
@@ -34,8 +31,6 @@ export type MessageStateBinding = SubscribableWithState<
|
|
|
34
31
|
readonly branchNumber: number;
|
|
35
32
|
readonly branchCount: number;
|
|
36
33
|
readonly speech: SpeechState | undefined;
|
|
37
|
-
/** @deprecated Use `message.metadata.submittedFeedback` instead. This will be removed in 0.12.0. */
|
|
38
|
-
readonly submittedFeedback: SubmittedFeedback | undefined;
|
|
39
34
|
},
|
|
40
35
|
MessageRuntimePath
|
|
41
36
|
>;
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
SKIP_UPDATE,
|
|
13
13
|
} from "../../subscribable/subscribable";
|
|
14
14
|
import type {
|
|
15
|
+
ComposerRuntimeEventCallback,
|
|
15
16
|
ComposerRuntimeEventType,
|
|
16
17
|
DictationState,
|
|
17
18
|
EditComposerRuntimeCore,
|
|
@@ -222,9 +223,9 @@ export type ComposerRuntime = {
|
|
|
222
223
|
/**
|
|
223
224
|
* @deprecated This API is still under active development and might change without notice.
|
|
224
225
|
*/
|
|
225
|
-
unstable_on(
|
|
226
|
-
event:
|
|
227
|
-
callback:
|
|
226
|
+
unstable_on<E extends ComposerRuntimeEventType>(
|
|
227
|
+
event: E,
|
|
228
|
+
callback: ComposerRuntimeEventCallback<E>,
|
|
228
229
|
): Unsubscribe;
|
|
229
230
|
};
|
|
230
231
|
|
|
@@ -332,19 +333,19 @@ export abstract class ComposerRuntimeImpl implements ComposerRuntime {
|
|
|
332
333
|
EventSubscriptionSubject<ComposerRuntimeEventType>
|
|
333
334
|
>();
|
|
334
335
|
|
|
335
|
-
public unstable_on(
|
|
336
|
-
event:
|
|
337
|
-
callback:
|
|
336
|
+
public unstable_on<E extends ComposerRuntimeEventType>(
|
|
337
|
+
event: E,
|
|
338
|
+
callback: ComposerRuntimeEventCallback<E>,
|
|
338
339
|
): Unsubscribe {
|
|
339
340
|
let subject = this._eventSubscriptionSubjects.get(event);
|
|
340
341
|
if (!subject) {
|
|
341
|
-
subject = new EventSubscriptionSubject({
|
|
342
|
-
event
|
|
342
|
+
subject = new EventSubscriptionSubject<ComposerRuntimeEventType>({
|
|
343
|
+
event,
|
|
343
344
|
binding: this._core,
|
|
344
345
|
});
|
|
345
346
|
this._eventSubscriptionSubjects.set(event, subject);
|
|
346
347
|
}
|
|
347
|
-
return subject.subscribe(callback);
|
|
348
|
+
return subject.subscribe(callback as (payload?: unknown) => void);
|
|
348
349
|
}
|
|
349
350
|
|
|
350
351
|
public abstract getAttachmentByIndex(idx: number): AttachmentRuntime;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
SpeechState,
|
|
3
|
-
SubmittedFeedback,
|
|
4
|
-
} from "../interfaces/thread-runtime-core";
|
|
1
|
+
import type { SpeechState } from "../interfaces/thread-runtime-core";
|
|
5
2
|
import { symbolInnerMessage } from "../utils/external-store-message";
|
|
6
3
|
import type {
|
|
7
4
|
ToolCallMessagePartStatus,
|
|
@@ -90,10 +87,6 @@ export type MessageState = ThreadMessage & {
|
|
|
90
87
|
* @deprecated This API is still under active development and might change without notice.
|
|
91
88
|
*/
|
|
92
89
|
readonly speech: SpeechState | undefined;
|
|
93
|
-
/**
|
|
94
|
-
* @deprecated Use `message.metadata.submittedFeedback` instead. This will be removed in 0.12.0.
|
|
95
|
-
*/
|
|
96
|
-
readonly submittedFeedback: SubmittedFeedback | undefined;
|
|
97
90
|
};
|
|
98
91
|
|
|
99
92
|
export type { MessageStateBinding } from "./bindings";
|
|
@@ -3,7 +3,26 @@ import type { SubscribableWithState } from "../../subscribable/subscribable";
|
|
|
3
3
|
import type { ThreadListItemRuntimePath } from "./paths";
|
|
4
4
|
import type { ThreadListRuntimeCoreBinding } from "./thread-list-runtime";
|
|
5
5
|
|
|
6
|
-
export type
|
|
6
|
+
export type ThreadListItemEventPayload = {
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated State-derivable. Compare `s.threads.mainThreadId` against the
|
|
9
|
+
* item's `s.threadListItem.id` via `useAuiState` instead. Kept for backward
|
|
10
|
+
* compatibility.
|
|
11
|
+
*/
|
|
12
|
+
switchedTo: Record<string, never>;
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated State-derivable. Compare `s.threads.mainThreadId` against the
|
|
15
|
+
* item's `s.threadListItem.id` via `useAuiState` instead. Kept for backward
|
|
16
|
+
* compatibility.
|
|
17
|
+
*/
|
|
18
|
+
switchedAway: Record<string, never>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type ThreadListItemEventType = keyof ThreadListItemEventPayload;
|
|
22
|
+
|
|
23
|
+
export type ThreadListItemEventCallback<E extends ThreadListItemEventType> = (
|
|
24
|
+
payload: ThreadListItemEventPayload[E],
|
|
25
|
+
) => void;
|
|
7
26
|
|
|
8
27
|
import type { ThreadListItemState } from "./bindings";
|
|
9
28
|
import type { ThreadListItemStatus } from "../interfaces/thread-list-runtime-core";
|
|
@@ -27,9 +46,9 @@ export type ThreadListItemRuntime = {
|
|
|
27
46
|
|
|
28
47
|
subscribe(callback: () => void): Unsubscribe;
|
|
29
48
|
|
|
30
|
-
unstable_on(
|
|
31
|
-
event:
|
|
32
|
-
callback:
|
|
49
|
+
unstable_on<E extends ThreadListItemEventType>(
|
|
50
|
+
event: E,
|
|
51
|
+
callback: ThreadListItemEventCallback<E>,
|
|
33
52
|
): Unsubscribe;
|
|
34
53
|
|
|
35
54
|
__internal_getRuntime(): ThreadListItemRuntime;
|
|
@@ -112,7 +131,10 @@ export class ThreadListItemRuntimeImpl implements ThreadListItemRuntime {
|
|
|
112
131
|
return this._threadListBinding.generateTitle(state.id);
|
|
113
132
|
}
|
|
114
133
|
|
|
115
|
-
public unstable_on
|
|
134
|
+
public unstable_on<E extends ThreadListItemEventType>(
|
|
135
|
+
event: E,
|
|
136
|
+
callback: ThreadListItemEventCallback<E>,
|
|
137
|
+
) {
|
|
116
138
|
let prevIsMain = this._core.getState().isMain;
|
|
117
139
|
let prevThreadId = this._core.getState().id;
|
|
118
140
|
return this.subscribe(() => {
|
|
@@ -125,7 +147,7 @@ export class ThreadListItemRuntimeImpl implements ThreadListItemRuntime {
|
|
|
125
147
|
|
|
126
148
|
if (event === "switchedTo" && !newIsMain) return;
|
|
127
149
|
if (event === "switchedAway" && newIsMain) return;
|
|
128
|
-
callback();
|
|
150
|
+
(callback as (payload?: unknown) => void)({});
|
|
129
151
|
});
|
|
130
152
|
}
|
|
131
153
|
|
|
@@ -28,6 +28,8 @@ export type ThreadListState = {
|
|
|
28
28
|
readonly threadIds: readonly string[];
|
|
29
29
|
readonly archivedThreadIds: readonly string[];
|
|
30
30
|
readonly isLoading: boolean;
|
|
31
|
+
readonly isLoadingMore: boolean;
|
|
32
|
+
readonly hasMore: boolean;
|
|
31
33
|
readonly threadItems: Readonly<
|
|
32
34
|
Record<string, Omit<ThreadListItemState, "isMain" | "threadId">>
|
|
33
35
|
>;
|
|
@@ -51,6 +53,7 @@ export type ThreadListRuntime = {
|
|
|
51
53
|
|
|
52
54
|
getLoadThreadsPromise(): Promise<void>;
|
|
53
55
|
reload(): Promise<void>;
|
|
56
|
+
loadMore(): Promise<void>;
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
const getThreadListState = (
|
|
@@ -62,6 +65,8 @@ const getThreadListState = (
|
|
|
62
65
|
threadIds: threadList.threadIds,
|
|
63
66
|
archivedThreadIds: threadList.archivedThreadIds,
|
|
64
67
|
isLoading: threadList.isLoading,
|
|
68
|
+
isLoadingMore: threadList.isLoadingMore ?? false,
|
|
69
|
+
hasMore: threadList.hasMore ?? false,
|
|
65
70
|
threadItems: threadList.threadItems,
|
|
66
71
|
};
|
|
67
72
|
};
|
|
@@ -138,6 +143,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
138
143
|
this.switchToNewThread = this.switchToNewThread.bind(this);
|
|
139
144
|
this.getLoadThreadsPromise = this.getLoadThreadsPromise.bind(this);
|
|
140
145
|
this.reload = this.reload.bind(this);
|
|
146
|
+
this.loadMore = this.loadMore.bind(this);
|
|
141
147
|
this.getState = this.getState.bind(this);
|
|
142
148
|
this.subscribe = this.subscribe.bind(this);
|
|
143
149
|
this.getById = this.getById.bind(this);
|
|
@@ -162,6 +168,10 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
|
|
|
162
168
|
return this._core.reload?.() ?? RESOLVED_PROMISE;
|
|
163
169
|
}
|
|
164
170
|
|
|
171
|
+
public loadMore(): Promise<void> {
|
|
172
|
+
return this._core.loadMore?.() ?? RESOLVED_PROMISE;
|
|
173
|
+
}
|
|
174
|
+
|
|
165
175
|
public getState(): ThreadListState {
|
|
166
176
|
return this._getState();
|
|
167
177
|
}
|