@lvce-editor/chat-view 3.10.0 → 4.1.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/chatViewWorkerMain.js +841 -108
- package/package.json +1 -1
|
@@ -1122,6 +1122,10 @@ const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
|
|
|
1122
1122
|
const sendMessagePortToChatNetworkWorker = async port => {
|
|
1123
1123
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatNetworkWorker', port, 'HandleMessagePort.handleMessagePort');
|
|
1124
1124
|
};
|
|
1125
|
+
const confirm = async (message, options) => {
|
|
1126
|
+
const result = await invoke('ConfirmPrompt.prompt', message, options);
|
|
1127
|
+
return result;
|
|
1128
|
+
};
|
|
1125
1129
|
const activateByEvent$1 = (event, assetDir, platform) => {
|
|
1126
1130
|
return invoke('ExtensionHostManagement.activateByEvent', event, assetDir, platform);
|
|
1127
1131
|
};
|
|
@@ -1134,6 +1138,9 @@ const getPreference = async key => {
|
|
|
1134
1138
|
const openExternal = async uri => {
|
|
1135
1139
|
await invoke('Open.openExternal', uri);
|
|
1136
1140
|
};
|
|
1141
|
+
const measureTextBlockHeight$1 = async (actualInput, fontFamily, fontSize, lineHeightPx, width) => {
|
|
1142
|
+
return invoke(`MeasureTextHeight.measureTextBlockHeight`, actualInput, fontFamily, fontSize, lineHeightPx, width);
|
|
1143
|
+
};
|
|
1137
1144
|
|
|
1138
1145
|
const toCommandId = key => {
|
|
1139
1146
|
const dotIndex = key.indexOf('.');
|
|
@@ -1256,7 +1263,7 @@ const terminate = () => {
|
|
|
1256
1263
|
};
|
|
1257
1264
|
|
|
1258
1265
|
const measureTextBlockHeight = async (text, fontFamily, fontSize, lineHeight, width) => {
|
|
1259
|
-
return
|
|
1266
|
+
return measureTextBlockHeight$1(text, fontFamily, fontSize, lineHeight, width);
|
|
1260
1267
|
};
|
|
1261
1268
|
|
|
1262
1269
|
const getComposerWidth = width => {
|
|
@@ -1336,6 +1343,12 @@ const backToChats = () => {
|
|
|
1336
1343
|
const settings = () => {
|
|
1337
1344
|
return i18nString('Settings');
|
|
1338
1345
|
};
|
|
1346
|
+
const chatFocusMode = () => {
|
|
1347
|
+
return i18nString('Switch to chat focus mode');
|
|
1348
|
+
};
|
|
1349
|
+
const normalChatMode = () => {
|
|
1350
|
+
return i18nString('Switch to normal chat mode');
|
|
1351
|
+
};
|
|
1339
1352
|
const closeChat = () => {
|
|
1340
1353
|
return i18nString('Close Chat');
|
|
1341
1354
|
};
|
|
@@ -1476,6 +1489,7 @@ const getDefaultModels = () => {
|
|
|
1476
1489
|
};
|
|
1477
1490
|
|
|
1478
1491
|
const createDefaultState = () => {
|
|
1492
|
+
const defaultProjectId = 'project-1';
|
|
1479
1493
|
const defaultSessionId = 'session-1';
|
|
1480
1494
|
const defaultModelId = 'test';
|
|
1481
1495
|
const chatMessageFontSize = 13;
|
|
@@ -1504,6 +1518,7 @@ const createDefaultState = () => {
|
|
|
1504
1518
|
height: 0,
|
|
1505
1519
|
initial: true,
|
|
1506
1520
|
inputSource: 'script',
|
|
1521
|
+
lastNormalViewMode: 'list',
|
|
1507
1522
|
lastSubmittedSessionId: '',
|
|
1508
1523
|
listItemHeight: 40,
|
|
1509
1524
|
maxComposerRows: 5,
|
|
@@ -1523,12 +1538,21 @@ const createDefaultState = () => {
|
|
|
1523
1538
|
openRouterApiKeyState: 'idle',
|
|
1524
1539
|
passIncludeObfuscation: false,
|
|
1525
1540
|
platform: 0,
|
|
1541
|
+
projectExpandedIds: [defaultProjectId],
|
|
1542
|
+
projectListScrollTop: 0,
|
|
1543
|
+
projects: [{
|
|
1544
|
+
id: defaultProjectId,
|
|
1545
|
+
name: '_blank',
|
|
1546
|
+
uri: ''
|
|
1547
|
+
}],
|
|
1526
1548
|
renamingSessionId: '',
|
|
1527
1549
|
selectedModelId: defaultModelId,
|
|
1550
|
+
selectedProjectId: defaultProjectId,
|
|
1528
1551
|
selectedSessionId: defaultSessionId,
|
|
1529
1552
|
sessions: [{
|
|
1530
1553
|
id: defaultSessionId,
|
|
1531
1554
|
messages: [],
|
|
1555
|
+
projectId: defaultProjectId,
|
|
1532
1556
|
title: defaultSessionTitle()
|
|
1533
1557
|
}],
|
|
1534
1558
|
streamingEnabled: true,
|
|
@@ -2148,29 +2172,49 @@ const createDefaultStorage = () => {
|
|
|
2148
2172
|
let chatSessionStorage = createDefaultStorage();
|
|
2149
2173
|
const listChatSessions = async () => {
|
|
2150
2174
|
const sessions = await chatSessionStorage.listSessions();
|
|
2151
|
-
return sessions.map(session =>
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2175
|
+
return sessions.map(session => {
|
|
2176
|
+
const summary = {
|
|
2177
|
+
id: session.id,
|
|
2178
|
+
messages: [],
|
|
2179
|
+
title: session.title
|
|
2180
|
+
};
|
|
2181
|
+
if (!session.projectId) {
|
|
2182
|
+
return summary;
|
|
2183
|
+
}
|
|
2184
|
+
return {
|
|
2185
|
+
...summary,
|
|
2186
|
+
projectId: session.projectId
|
|
2187
|
+
};
|
|
2188
|
+
});
|
|
2156
2189
|
};
|
|
2157
2190
|
const getChatSession = async id => {
|
|
2158
2191
|
const session = await chatSessionStorage.getSession(id);
|
|
2159
2192
|
if (!session) {
|
|
2160
2193
|
return undefined;
|
|
2161
2194
|
}
|
|
2162
|
-
|
|
2195
|
+
const result = {
|
|
2163
2196
|
id: session.id,
|
|
2164
2197
|
messages: [...session.messages],
|
|
2165
2198
|
title: session.title
|
|
2166
2199
|
};
|
|
2200
|
+
if (!session.projectId) {
|
|
2201
|
+
return result;
|
|
2202
|
+
}
|
|
2203
|
+
return {
|
|
2204
|
+
...result,
|
|
2205
|
+
projectId: session.projectId
|
|
2206
|
+
};
|
|
2167
2207
|
};
|
|
2168
2208
|
const saveChatSession = async session => {
|
|
2169
|
-
|
|
2209
|
+
const value = {
|
|
2170
2210
|
id: session.id,
|
|
2171
2211
|
messages: [...session.messages],
|
|
2172
2212
|
title: session.title
|
|
2173
|
-
}
|
|
2213
|
+
};
|
|
2214
|
+
await chatSessionStorage.setSession(session.projectId ? {
|
|
2215
|
+
...value,
|
|
2216
|
+
projectId: session.projectId
|
|
2217
|
+
} : value);
|
|
2174
2218
|
};
|
|
2175
2219
|
const deleteChatSession = async id => {
|
|
2176
2220
|
await chatSessionStorage.deleteSession(id);
|
|
@@ -2194,6 +2238,17 @@ const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
|
2194
2238
|
return sessions[nextIndex].id;
|
|
2195
2239
|
};
|
|
2196
2240
|
|
|
2241
|
+
const getVisibleSessions = (sessions, selectedProjectId) => {
|
|
2242
|
+
if (!selectedProjectId) {
|
|
2243
|
+
return sessions;
|
|
2244
|
+
}
|
|
2245
|
+
const hasAssignedProjects = sessions.some(session => !!session.projectId);
|
|
2246
|
+
if (!hasAssignedProjects) {
|
|
2247
|
+
return sessions;
|
|
2248
|
+
}
|
|
2249
|
+
return sessions.filter(session => session.projectId === selectedProjectId);
|
|
2250
|
+
};
|
|
2251
|
+
|
|
2197
2252
|
const deleteSession = async (state, id) => {
|
|
2198
2253
|
const {
|
|
2199
2254
|
renamingSessionId,
|
|
@@ -2232,10 +2287,8 @@ const deleteSession = async (state, id) => {
|
|
|
2232
2287
|
};
|
|
2233
2288
|
};
|
|
2234
2289
|
const deleteSessionAtIndex = async (state, index) => {
|
|
2235
|
-
const
|
|
2236
|
-
|
|
2237
|
-
} = state;
|
|
2238
|
-
const session = sessions[index];
|
|
2290
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
2291
|
+
const session = visibleSessions[index];
|
|
2239
2292
|
if (!session) {
|
|
2240
2293
|
return state;
|
|
2241
2294
|
}
|
|
@@ -2301,12 +2354,23 @@ const diffFocus = (oldState, newState) => {
|
|
|
2301
2354
|
return oldState.focus === newState.focus && oldState.focused === newState.focused;
|
|
2302
2355
|
};
|
|
2303
2356
|
|
|
2357
|
+
const isEqualProjectExpandedIds = (a, b) => {
|
|
2358
|
+
if (a.length !== b.length) {
|
|
2359
|
+
return false;
|
|
2360
|
+
}
|
|
2361
|
+
for (let i = 0; i < a.length; i++) {
|
|
2362
|
+
if (a[i] !== b[i]) {
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
return true;
|
|
2367
|
+
};
|
|
2304
2368
|
const isEqual = (oldState, newState) => {
|
|
2305
|
-
return oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.viewMode === newState.viewMode;
|
|
2369
|
+
return oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && oldState.projectListScrollTop === newState.projectListScrollTop && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.viewMode === newState.viewMode;
|
|
2306
2370
|
};
|
|
2307
2371
|
|
|
2308
2372
|
const diffScrollTop = (oldState, newState) => {
|
|
2309
|
-
return oldState.chatListScrollTop === newState.chatListScrollTop && oldState.messagesScrollTop === newState.messagesScrollTop;
|
|
2373
|
+
return oldState.chatListScrollTop === newState.chatListScrollTop && oldState.messagesScrollTop === newState.messagesScrollTop && oldState.projectListScrollTop === newState.projectListScrollTop;
|
|
2310
2374
|
};
|
|
2311
2375
|
|
|
2312
2376
|
const RenderItems = 4;
|
|
@@ -2745,7 +2809,8 @@ const handleChatListContextMenu = async (state, eventX, eventY) => {
|
|
|
2745
2809
|
if (index === -1) {
|
|
2746
2810
|
return state;
|
|
2747
2811
|
}
|
|
2748
|
-
const
|
|
2812
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
2813
|
+
const item = visibleSessions[index];
|
|
2749
2814
|
if (!item) {
|
|
2750
2815
|
return state;
|
|
2751
2816
|
}
|
|
@@ -2757,22 +2822,106 @@ const generateSessionId = () => {
|
|
|
2757
2822
|
return crypto.randomUUID();
|
|
2758
2823
|
};
|
|
2759
2824
|
|
|
2760
|
-
const createSession = async state => {
|
|
2825
|
+
const createSession = async (state, projectIdOverride = '') => {
|
|
2761
2826
|
const id = generateSessionId();
|
|
2827
|
+
const fallbackProjectId = state.projects.find(project => project.name === '_blank')?.id || state.projects[0]?.id || 'project-1';
|
|
2828
|
+
const projectId = projectIdOverride || state.selectedProjectId || fallbackProjectId;
|
|
2762
2829
|
const session = {
|
|
2763
2830
|
id,
|
|
2764
2831
|
messages: [],
|
|
2832
|
+
projectId,
|
|
2765
2833
|
title: `Chat ${state.sessions.length + 1}`
|
|
2766
2834
|
};
|
|
2767
2835
|
await saveChatSession(session);
|
|
2768
2836
|
return {
|
|
2769
2837
|
...state,
|
|
2838
|
+
projectExpandedIds: state.projectExpandedIds.includes(projectId) ? state.projectExpandedIds : [...state.projectExpandedIds, projectId],
|
|
2770
2839
|
renamingSessionId: '',
|
|
2840
|
+
selectedProjectId: projectId,
|
|
2771
2841
|
selectedSessionId: id,
|
|
2772
2842
|
sessions: [...state.sessions, session]
|
|
2773
2843
|
};
|
|
2774
2844
|
};
|
|
2775
2845
|
|
|
2846
|
+
const selectProject = async (state, projectId) => {
|
|
2847
|
+
if (!projectId || state.selectedProjectId === projectId) {
|
|
2848
|
+
return state;
|
|
2849
|
+
}
|
|
2850
|
+
const visibleSessions = getVisibleSessions(state.sessions, projectId);
|
|
2851
|
+
if (visibleSessions.length === 0) {
|
|
2852
|
+
return {
|
|
2853
|
+
...state,
|
|
2854
|
+
selectedProjectId: projectId,
|
|
2855
|
+
selectedSessionId: '',
|
|
2856
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'list'
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
const currentSessionVisible = visibleSessions.some(session => session.id === state.selectedSessionId);
|
|
2860
|
+
const nextSelectedSessionId = currentSessionVisible ? state.selectedSessionId : visibleSessions[0].id;
|
|
2861
|
+
const loadedSession = await getChatSession(nextSelectedSessionId);
|
|
2862
|
+
const sessions = state.sessions.map(session => {
|
|
2863
|
+
if (session.id !== nextSelectedSessionId || !loadedSession) {
|
|
2864
|
+
return session;
|
|
2865
|
+
}
|
|
2866
|
+
return loadedSession;
|
|
2867
|
+
});
|
|
2868
|
+
return {
|
|
2869
|
+
...state,
|
|
2870
|
+
selectedProjectId: projectId,
|
|
2871
|
+
selectedSessionId: nextSelectedSessionId,
|
|
2872
|
+
sessions,
|
|
2873
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
2874
|
+
};
|
|
2875
|
+
};
|
|
2876
|
+
|
|
2877
|
+
const getProjectName = (uri, fallbackIndex) => {
|
|
2878
|
+
if (!uri) {
|
|
2879
|
+
return `Project ${fallbackIndex}`;
|
|
2880
|
+
}
|
|
2881
|
+
const withoutScheme = uri.replace(/^file:\/\//, '');
|
|
2882
|
+
const normalized = withoutScheme.replace(/\/+$/, '');
|
|
2883
|
+
const lastSegment = normalized.split('/').pop();
|
|
2884
|
+
if (!lastSegment) {
|
|
2885
|
+
return `Project ${fallbackIndex}`;
|
|
2886
|
+
}
|
|
2887
|
+
return decodeURIComponent(lastSegment);
|
|
2888
|
+
};
|
|
2889
|
+
const getNextProjectId = projects => {
|
|
2890
|
+
return `project-${projects.length + 1}`;
|
|
2891
|
+
};
|
|
2892
|
+
const pickProjectUri = async () => {
|
|
2893
|
+
try {
|
|
2894
|
+
const workspaceUri = await getWorkspacePath();
|
|
2895
|
+
return workspaceUri;
|
|
2896
|
+
} catch {
|
|
2897
|
+
return '';
|
|
2898
|
+
}
|
|
2899
|
+
};
|
|
2900
|
+
const handleClickCreateProject = async state => {
|
|
2901
|
+
await confirm('project added');
|
|
2902
|
+
const uri = await pickProjectUri();
|
|
2903
|
+
if (!uri) {
|
|
2904
|
+
return state;
|
|
2905
|
+
}
|
|
2906
|
+
const existingProject = state.projects.find(project => project.uri === uri);
|
|
2907
|
+
if (existingProject) {
|
|
2908
|
+
return selectProject(state, existingProject.id);
|
|
2909
|
+
}
|
|
2910
|
+
const id = getNextProjectId(state.projects);
|
|
2911
|
+
const project = {
|
|
2912
|
+
id,
|
|
2913
|
+
name: getProjectName(uri, state.projects.length + 1),
|
|
2914
|
+
uri
|
|
2915
|
+
};
|
|
2916
|
+
return {
|
|
2917
|
+
...state,
|
|
2918
|
+
projects: [...state.projects, project],
|
|
2919
|
+
selectedProjectId: project.id,
|
|
2920
|
+
selectedSessionId: '',
|
|
2921
|
+
viewMode: 'list'
|
|
2922
|
+
};
|
|
2923
|
+
};
|
|
2924
|
+
|
|
2776
2925
|
const handleClickOpenApiApiKeySettings = async state => {
|
|
2777
2926
|
await invoke('Main.openUri', 'app://settings.json');
|
|
2778
2927
|
return state;
|
|
@@ -5822,13 +5971,35 @@ const ComposerDropTarget = 'composer-drop-target';
|
|
|
5822
5971
|
const Send = 'send';
|
|
5823
5972
|
const Back = 'back';
|
|
5824
5973
|
const Model = 'model';
|
|
5974
|
+
const ToggleChatFocus = 'toggle-chat-focus';
|
|
5975
|
+
const CreateProject = 'create-project';
|
|
5825
5976
|
const CreateSession = 'create-session';
|
|
5977
|
+
const CreateSessionInProjectPrefix = 'create-session-in-project:';
|
|
5826
5978
|
const SessionDebug = 'session-debug';
|
|
5827
5979
|
const Settings = 'settings';
|
|
5828
5980
|
const CloseChat = 'close-chat';
|
|
5829
5981
|
const SessionDelete = 'SessionDelete';
|
|
5982
|
+
const ProjectPrefix = 'project:';
|
|
5830
5983
|
const SessionPrefix = 'session:';
|
|
5831
5984
|
const RenamePrefix = 'session-rename:';
|
|
5985
|
+
const getProjectInputName = projectId => {
|
|
5986
|
+
return `${ProjectPrefix}${projectId}`;
|
|
5987
|
+
};
|
|
5988
|
+
const getCreateSessionInProjectInputName = projectId => {
|
|
5989
|
+
return `${CreateSessionInProjectPrefix}${projectId}`;
|
|
5990
|
+
};
|
|
5991
|
+
const isCreateSessionInProjectInputName = name => {
|
|
5992
|
+
return name.startsWith(CreateSessionInProjectPrefix);
|
|
5993
|
+
};
|
|
5994
|
+
const getProjectIdFromCreateSessionInProjectInputName = name => {
|
|
5995
|
+
return name.slice(CreateSessionInProjectPrefix.length);
|
|
5996
|
+
};
|
|
5997
|
+
const isProjectInputName = name => {
|
|
5998
|
+
return name.startsWith(ProjectPrefix);
|
|
5999
|
+
};
|
|
6000
|
+
const getProjectIdFromInputName = name => {
|
|
6001
|
+
return name.slice(ProjectPrefix.length);
|
|
6002
|
+
};
|
|
5832
6003
|
const getSessionInputName = sessionId => {
|
|
5833
6004
|
return `${SessionPrefix}${sessionId}`;
|
|
5834
6005
|
};
|
|
@@ -5873,10 +6044,11 @@ const selectSession = async (state, id) => {
|
|
|
5873
6044
|
});
|
|
5874
6045
|
return {
|
|
5875
6046
|
...state,
|
|
6047
|
+
lastNormalViewMode: state.viewMode === 'chat-focus' ? state.lastNormalViewMode : 'detail',
|
|
5876
6048
|
renamingSessionId: '',
|
|
5877
6049
|
selectedSessionId: id,
|
|
5878
6050
|
sessions,
|
|
5879
|
-
viewMode: 'detail'
|
|
6051
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
5880
6052
|
};
|
|
5881
6053
|
};
|
|
5882
6054
|
|
|
@@ -5897,14 +6069,61 @@ const startRename = (state, id) => {
|
|
|
5897
6069
|
};
|
|
5898
6070
|
};
|
|
5899
6071
|
|
|
6072
|
+
const toggleChatFocusMode = async state => {
|
|
6073
|
+
if (state.viewMode === 'chat-focus') {
|
|
6074
|
+
return {
|
|
6075
|
+
...state,
|
|
6076
|
+
viewMode: state.lastNormalViewMode
|
|
6077
|
+
};
|
|
6078
|
+
}
|
|
6079
|
+
if (state.viewMode === 'list' || state.viewMode === 'detail') {
|
|
6080
|
+
return {
|
|
6081
|
+
...state,
|
|
6082
|
+
lastNormalViewMode: state.viewMode,
|
|
6083
|
+
viewMode: 'chat-focus'
|
|
6084
|
+
};
|
|
6085
|
+
}
|
|
6086
|
+
return state;
|
|
6087
|
+
};
|
|
6088
|
+
|
|
6089
|
+
const toggleProjectExpanded = async (state, projectId) => {
|
|
6090
|
+
const isExpanded = state.projectExpandedIds.includes(projectId);
|
|
6091
|
+
const projectExpandedIds = isExpanded ? state.projectExpandedIds.filter(id => id !== projectId) : [...state.projectExpandedIds, projectId];
|
|
6092
|
+
const visibleSessions = getVisibleSessions(state.sessions, projectId);
|
|
6093
|
+
if (visibleSessions.length === 0) {
|
|
6094
|
+
return {
|
|
6095
|
+
...state,
|
|
6096
|
+
projectExpandedIds,
|
|
6097
|
+
selectedProjectId: projectId,
|
|
6098
|
+
selectedSessionId: '',
|
|
6099
|
+
viewMode: 'chat-focus'
|
|
6100
|
+
};
|
|
6101
|
+
}
|
|
6102
|
+
const selectedSessionVisible = visibleSessions.some(session => session.id === state.selectedSessionId);
|
|
6103
|
+
const selectedSessionId = selectedSessionVisible ? state.selectedSessionId : visibleSessions[0].id;
|
|
6104
|
+
const loadedSession = await getChatSession(selectedSessionId);
|
|
6105
|
+
const sessions = state.sessions.map(session => {
|
|
6106
|
+
if (session.id !== selectedSessionId || !loadedSession) {
|
|
6107
|
+
return session;
|
|
6108
|
+
}
|
|
6109
|
+
return loadedSession;
|
|
6110
|
+
});
|
|
6111
|
+
return {
|
|
6112
|
+
...state,
|
|
6113
|
+
projectExpandedIds,
|
|
6114
|
+
selectedProjectId: projectId,
|
|
6115
|
+
selectedSessionId,
|
|
6116
|
+
sessions,
|
|
6117
|
+
viewMode: 'chat-focus'
|
|
6118
|
+
};
|
|
6119
|
+
};
|
|
6120
|
+
|
|
5900
6121
|
const selectListIndex = async (state, index) => {
|
|
5901
|
-
const
|
|
5902
|
-
|
|
5903
|
-
} = state;
|
|
5904
|
-
if (index < 0 || index >= sessions.length) {
|
|
6122
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
6123
|
+
if (index < 0 || index >= visibleSessions.length) {
|
|
5905
6124
|
return state;
|
|
5906
6125
|
}
|
|
5907
|
-
const session =
|
|
6126
|
+
const session = visibleSessions[index];
|
|
5908
6127
|
return selectSession(state, session.id);
|
|
5909
6128
|
};
|
|
5910
6129
|
|
|
@@ -5920,6 +6139,23 @@ const handleClick = async (state, name, id = '') => {
|
|
|
5920
6139
|
if (name === CreateSession) {
|
|
5921
6140
|
return createSession(state);
|
|
5922
6141
|
}
|
|
6142
|
+
if (name === CreateProject) {
|
|
6143
|
+
return handleClickCreateProject(state);
|
|
6144
|
+
}
|
|
6145
|
+
if (isCreateSessionInProjectInputName(name)) {
|
|
6146
|
+
const projectId = getProjectIdFromCreateSessionInProjectInputName(name);
|
|
6147
|
+
return createSession(state, projectId);
|
|
6148
|
+
}
|
|
6149
|
+
if (name === ToggleChatFocus) {
|
|
6150
|
+
return toggleChatFocusMode(state);
|
|
6151
|
+
}
|
|
6152
|
+
if (isProjectInputName(name)) {
|
|
6153
|
+
const projectId = getProjectIdFromInputName(name);
|
|
6154
|
+
if (state.viewMode === 'chat-focus') {
|
|
6155
|
+
return toggleProjectExpanded(state, projectId);
|
|
6156
|
+
}
|
|
6157
|
+
return selectProject(state, projectId);
|
|
6158
|
+
}
|
|
5923
6159
|
if (isSessionInputName(name)) {
|
|
5924
6160
|
const sessionId = getSessionIdFromInputName(name);
|
|
5925
6161
|
return selectSession(state, sessionId);
|
|
@@ -5958,6 +6194,7 @@ const handleClick = async (state, name, id = '') => {
|
|
|
5958
6194
|
const handleClickBack = async state => {
|
|
5959
6195
|
return {
|
|
5960
6196
|
...state,
|
|
6197
|
+
lastNormalViewMode: 'list',
|
|
5961
6198
|
renamingSessionId: '',
|
|
5962
6199
|
viewMode: 'list'
|
|
5963
6200
|
};
|
|
@@ -6239,6 +6476,15 @@ const handleMessagesScroll = async (state, messagesScrollTop) => {
|
|
|
6239
6476
|
messagesScrollTop
|
|
6240
6477
|
};
|
|
6241
6478
|
};
|
|
6479
|
+
const handleProjectListScroll = async (state, projectListScrollTop) => {
|
|
6480
|
+
if (state.projectListScrollTop === projectListScrollTop) {
|
|
6481
|
+
return state;
|
|
6482
|
+
}
|
|
6483
|
+
return {
|
|
6484
|
+
...state,
|
|
6485
|
+
projectListScrollTop
|
|
6486
|
+
};
|
|
6487
|
+
};
|
|
6242
6488
|
|
|
6243
6489
|
const id = 7201;
|
|
6244
6490
|
const sendMessagePortToExtensionHostWorker = async port => {
|
|
@@ -6338,7 +6584,7 @@ const getSavedViewMode = savedState => {
|
|
|
6338
6584
|
const {
|
|
6339
6585
|
viewMode
|
|
6340
6586
|
} = savedState;
|
|
6341
|
-
if (viewMode !== 'list' && viewMode !== 'detail') {
|
|
6587
|
+
if (viewMode !== 'list' && viewMode !== 'detail' && viewMode !== 'chat-focus') {
|
|
6342
6588
|
return undefined;
|
|
6343
6589
|
}
|
|
6344
6590
|
return viewMode;
|
|
@@ -6455,11 +6701,97 @@ const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
|
|
|
6455
6701
|
};
|
|
6456
6702
|
|
|
6457
6703
|
const toSummarySession = session => {
|
|
6458
|
-
|
|
6704
|
+
const summary = {
|
|
6459
6705
|
id: session.id,
|
|
6460
6706
|
messages: [],
|
|
6461
6707
|
title: session.title
|
|
6462
6708
|
};
|
|
6709
|
+
if (!session.projectId) {
|
|
6710
|
+
return summary;
|
|
6711
|
+
}
|
|
6712
|
+
return {
|
|
6713
|
+
...summary,
|
|
6714
|
+
projectId: session.projectId
|
|
6715
|
+
};
|
|
6716
|
+
};
|
|
6717
|
+
const getSavedSelectedProjectId = savedState => {
|
|
6718
|
+
if (!isObject(savedState)) {
|
|
6719
|
+
return undefined;
|
|
6720
|
+
}
|
|
6721
|
+
const {
|
|
6722
|
+
selectedProjectId
|
|
6723
|
+
} = savedState;
|
|
6724
|
+
if (typeof selectedProjectId !== 'string') {
|
|
6725
|
+
return undefined;
|
|
6726
|
+
}
|
|
6727
|
+
return selectedProjectId;
|
|
6728
|
+
};
|
|
6729
|
+
const getSavedProjects = savedState => {
|
|
6730
|
+
if (!isObject(savedState)) {
|
|
6731
|
+
return undefined;
|
|
6732
|
+
}
|
|
6733
|
+
const {
|
|
6734
|
+
projects
|
|
6735
|
+
} = savedState;
|
|
6736
|
+
if (!Array.isArray(projects)) {
|
|
6737
|
+
return undefined;
|
|
6738
|
+
}
|
|
6739
|
+
const validProjects = projects.filter(project => {
|
|
6740
|
+
if (!isObject(project)) {
|
|
6741
|
+
return false;
|
|
6742
|
+
}
|
|
6743
|
+
return typeof project.id === 'string' && typeof project.name === 'string' && typeof project.uri === 'string';
|
|
6744
|
+
});
|
|
6745
|
+
if (validProjects.length === 0) {
|
|
6746
|
+
return undefined;
|
|
6747
|
+
}
|
|
6748
|
+
return validProjects;
|
|
6749
|
+
};
|
|
6750
|
+
const ensureBlankProject = (projects, fallbackBlankProject) => {
|
|
6751
|
+
if (projects.some(project => project.name === '_blank')) {
|
|
6752
|
+
return projects;
|
|
6753
|
+
}
|
|
6754
|
+
return [fallbackBlankProject, ...projects];
|
|
6755
|
+
};
|
|
6756
|
+
const getSavedProjectListScrollTop = savedState => {
|
|
6757
|
+
if (!isObject(savedState)) {
|
|
6758
|
+
return undefined;
|
|
6759
|
+
}
|
|
6760
|
+
const {
|
|
6761
|
+
projectListScrollTop
|
|
6762
|
+
} = savedState;
|
|
6763
|
+
if (typeof projectListScrollTop !== 'number') {
|
|
6764
|
+
return undefined;
|
|
6765
|
+
}
|
|
6766
|
+
return projectListScrollTop;
|
|
6767
|
+
};
|
|
6768
|
+
const getSavedProjectExpandedIds = savedState => {
|
|
6769
|
+
if (!isObject(savedState)) {
|
|
6770
|
+
return undefined;
|
|
6771
|
+
}
|
|
6772
|
+
const {
|
|
6773
|
+
projectExpandedIds
|
|
6774
|
+
} = savedState;
|
|
6775
|
+
if (!Array.isArray(projectExpandedIds)) {
|
|
6776
|
+
return undefined;
|
|
6777
|
+
}
|
|
6778
|
+
const ids = projectExpandedIds.filter(id => typeof id === 'string');
|
|
6779
|
+
if (ids.length === 0) {
|
|
6780
|
+
return undefined;
|
|
6781
|
+
}
|
|
6782
|
+
return ids;
|
|
6783
|
+
};
|
|
6784
|
+
const getSavedLastNormalViewMode = savedState => {
|
|
6785
|
+
if (!isObject(savedState)) {
|
|
6786
|
+
return undefined;
|
|
6787
|
+
}
|
|
6788
|
+
const {
|
|
6789
|
+
lastNormalViewMode
|
|
6790
|
+
} = savedState;
|
|
6791
|
+
if (lastNormalViewMode !== 'list' && lastNormalViewMode !== 'detail') {
|
|
6792
|
+
return undefined;
|
|
6793
|
+
}
|
|
6794
|
+
return lastNormalViewMode;
|
|
6463
6795
|
};
|
|
6464
6796
|
const loadContent = async (state, savedState) => {
|
|
6465
6797
|
const savedSelectedModelId = getSavedSelectedModelId(savedState);
|
|
@@ -6490,14 +6822,30 @@ const loadContent = async (state, savedState) => {
|
|
|
6490
6822
|
sessions = state.sessions.map(toSummarySession);
|
|
6491
6823
|
}
|
|
6492
6824
|
const preferredSessionId = getSavedSelectedSessionId(savedState) || state.selectedSessionId;
|
|
6825
|
+
const savedProjects = getSavedProjects(savedState);
|
|
6826
|
+
const baseProjects = savedProjects && savedProjects.length > 0 ? savedProjects : state.projects;
|
|
6827
|
+
const blankProject = state.projects.find(project => project.name === '_blank') || {
|
|
6828
|
+
id: 'project-blank',
|
|
6829
|
+
name: '_blank',
|
|
6830
|
+
uri: ''
|
|
6831
|
+
};
|
|
6832
|
+
const projects = ensureBlankProject(baseProjects, blankProject);
|
|
6833
|
+
const preferredProjectId = getSavedSelectedProjectId(savedState) || state.selectedProjectId;
|
|
6834
|
+
const selectedProjectId = projects.some(project => project.id === preferredProjectId) ? preferredProjectId : projects[0]?.id || '';
|
|
6493
6835
|
const preferredModelId = savedSelectedModelId || state.selectedModelId;
|
|
6494
6836
|
const chatListScrollTop = getSavedChatListScrollTop(savedState) ?? state.chatListScrollTop;
|
|
6495
6837
|
const messagesScrollTop = getSavedMessagesScrollTop(savedState) ?? state.messagesScrollTop;
|
|
6838
|
+
const projectListScrollTop = getSavedProjectListScrollTop(savedState) ?? state.projectListScrollTop;
|
|
6839
|
+
const savedProjectExpandedIds = getSavedProjectExpandedIds(savedState);
|
|
6840
|
+
const projectExpandedIds = (savedProjectExpandedIds || state.projectExpandedIds).filter(id => projects.some(project => project.id === id));
|
|
6496
6841
|
const selectedModelId = state.models.some(model => model.id === preferredModelId) ? preferredModelId : state.models[0]?.id || '';
|
|
6497
|
-
const
|
|
6842
|
+
const visibleSessions = getVisibleSessions(sessions, selectedProjectId);
|
|
6843
|
+
const selectedSessionId = visibleSessions.some(session => session.id === preferredSessionId) ? preferredSessionId : visibleSessions[0]?.id || '';
|
|
6498
6844
|
sessions = await loadSelectedSessionMessages(sessions, selectedSessionId);
|
|
6499
6845
|
const preferredViewMode = savedViewMode || state.viewMode;
|
|
6500
|
-
const
|
|
6846
|
+
const savedLastNormalViewMode = getSavedLastNormalViewMode(savedState);
|
|
6847
|
+
const lastNormalViewMode = savedLastNormalViewMode || (preferredViewMode === 'detail' ? 'detail' : state.lastNormalViewMode);
|
|
6848
|
+
const viewMode = sessions.length === 0 || !selectedSessionId ? 'list' : preferredViewMode;
|
|
6501
6849
|
return {
|
|
6502
6850
|
...state,
|
|
6503
6851
|
aiSessionTitleGenerationEnabled,
|
|
@@ -6506,13 +6854,18 @@ const loadContent = async (state, savedState) => {
|
|
|
6506
6854
|
composerDropEnabled,
|
|
6507
6855
|
emitStreamingFunctionCallEvents,
|
|
6508
6856
|
initial: false,
|
|
6857
|
+
lastNormalViewMode,
|
|
6509
6858
|
messagesScrollTop,
|
|
6510
6859
|
openApiApiKey,
|
|
6511
6860
|
openApiApiKeyInput: openApiApiKey,
|
|
6512
6861
|
openRouterApiKey,
|
|
6513
6862
|
openRouterApiKeyInput: openRouterApiKey,
|
|
6514
6863
|
passIncludeObfuscation,
|
|
6864
|
+
projectExpandedIds,
|
|
6865
|
+
projectListScrollTop,
|
|
6866
|
+
projects,
|
|
6515
6867
|
selectedModelId,
|
|
6868
|
+
selectedProjectId,
|
|
6516
6869
|
selectedSessionId,
|
|
6517
6870
|
sessions,
|
|
6518
6871
|
streamingEnabled,
|
|
@@ -6599,6 +6952,219 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
6599
6952
|
--ChatMessageLineHeight: ${chatMessageLineHeight}px;
|
|
6600
6953
|
--ChatMessageFontFamily: ${chatMessageFontFamily};
|
|
6601
6954
|
}
|
|
6955
|
+
|
|
6956
|
+
.Viewlet.Chat.ChatFocus {
|
|
6957
|
+
background: linear-gradient(180deg, var(--ColorViewBackground, #1d2229) 0%, #1f252d 100%);
|
|
6958
|
+
display: grid;
|
|
6959
|
+
grid-template-columns: 320px 1fr;
|
|
6960
|
+
grid-template-rows: auto 1fr auto;
|
|
6961
|
+
}
|
|
6962
|
+
|
|
6963
|
+
.Chat.ChatFocus .ChatHeader {
|
|
6964
|
+
grid-column: 1 / 3;
|
|
6965
|
+
}
|
|
6966
|
+
|
|
6967
|
+
.Chat.ChatFocus .ProjectSidebar {
|
|
6968
|
+
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 88%, #1f2b38 12%);
|
|
6969
|
+
border-right: 1px solid var(--ColorBorder, #3a3d41);
|
|
6970
|
+
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.2);
|
|
6971
|
+
display: flex;
|
|
6972
|
+
flex-direction: column;
|
|
6973
|
+
grid-column: 1;
|
|
6974
|
+
grid-row: 2 / 4;
|
|
6975
|
+
min-height: 0;
|
|
6976
|
+
}
|
|
6977
|
+
|
|
6978
|
+
.Chat.ChatFocus .ProjectList {
|
|
6979
|
+
min-height: 0;
|
|
6980
|
+
overflow: auto;
|
|
6981
|
+
padding: 10px 8px 12px;
|
|
6982
|
+
scrollbar-color: color-mix(in srgb, var(--ColorScrollBarSliderBackground, #4b5563) 78%, transparent)
|
|
6983
|
+
color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 92%, transparent);
|
|
6984
|
+
scrollbar-width: thin;
|
|
6985
|
+
}
|
|
6986
|
+
|
|
6987
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar {
|
|
6988
|
+
height: 10px;
|
|
6989
|
+
width: 10px;
|
|
6990
|
+
}
|
|
6991
|
+
|
|
6992
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-track {
|
|
6993
|
+
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 94%, transparent);
|
|
6994
|
+
border-radius: 999px;
|
|
6995
|
+
}
|
|
6996
|
+
|
|
6997
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-thumb {
|
|
6998
|
+
background: color-mix(in srgb, var(--ColorScrollBarSliderBackground, #4b5563) 70%, transparent);
|
|
6999
|
+
border: 2px solid color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 94%, transparent);
|
|
7000
|
+
border-radius: 999px;
|
|
7001
|
+
}
|
|
7002
|
+
|
|
7003
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-thumb:hover {
|
|
7004
|
+
background: color-mix(in srgb, var(--ColorScrollBarSliderHoverBackground, #667284) 80%, transparent);
|
|
7005
|
+
}
|
|
7006
|
+
|
|
7007
|
+
.ProjectListGroup {
|
|
7008
|
+
border: 1px solid transparent;
|
|
7009
|
+
border-radius: 8px;
|
|
7010
|
+
margin-bottom: 6px;
|
|
7011
|
+
overflow: hidden;
|
|
7012
|
+
}
|
|
7013
|
+
|
|
7014
|
+
.ProjectListItem {
|
|
7015
|
+
align-items: center;
|
|
7016
|
+
display: flex;
|
|
7017
|
+
gap: 6px;
|
|
7018
|
+
min-height: calc(var(--ChatListItemHeight) - 2px);
|
|
7019
|
+
}
|
|
7020
|
+
|
|
7021
|
+
.ProjectListItemLabel {
|
|
7022
|
+
align-items: center;
|
|
7023
|
+
border-radius: 6px;
|
|
7024
|
+
color: var(--ColorForeground, #d5dbe3);
|
|
7025
|
+
cursor: pointer;
|
|
7026
|
+
display: flex;
|
|
7027
|
+
flex: 1;
|
|
7028
|
+
font-weight: 500;
|
|
7029
|
+
gap: 2px;
|
|
7030
|
+
overflow: hidden;
|
|
7031
|
+
padding: 0 10px;
|
|
7032
|
+
text-overflow: ellipsis;
|
|
7033
|
+
transition: background-color 80ms ease, color 80ms ease;
|
|
7034
|
+
white-space: nowrap;
|
|
7035
|
+
}
|
|
7036
|
+
|
|
7037
|
+
.ProjectListChevron {
|
|
7038
|
+
color: color-mix(in srgb, var(--ColorForeground, #c8d0da) 70%, transparent);
|
|
7039
|
+
display: inline-block;
|
|
7040
|
+
flex: 0 0 12px;
|
|
7041
|
+
font-size: 11px;
|
|
7042
|
+
margin-right: 4px;
|
|
7043
|
+
text-align: center;
|
|
7044
|
+
width: 12px;
|
|
7045
|
+
}
|
|
7046
|
+
|
|
7047
|
+
.ProjectListItemSelected {
|
|
7048
|
+
background: color-mix(in srgb, var(--ColorListInactiveSelectionBackground, #39424d) 84%, #2f3741 16%);
|
|
7049
|
+
}
|
|
7050
|
+
|
|
7051
|
+
.ProjectListItem:not(.ProjectListItemSelected) .ProjectListItemLabel:hover,
|
|
7052
|
+
.ProjectListItem:not(.ProjectListItemSelected) .ProjectListItemLabel:focus-visible {
|
|
7053
|
+
background: color-mix(in srgb, var(--ColorListHoverBackground, #38414b) 50%, transparent);
|
|
7054
|
+
}
|
|
7055
|
+
|
|
7056
|
+
.ProjectListItemSelected .ProjectListItemLabel {
|
|
7057
|
+
color: var(--ColorListInactiveSelectionForeground, #e5ebf2);
|
|
7058
|
+
}
|
|
7059
|
+
|
|
7060
|
+
.ProjectListItemActions {
|
|
7061
|
+
display: flex;
|
|
7062
|
+
padding-right: 6px;
|
|
7063
|
+
}
|
|
7064
|
+
|
|
7065
|
+
.ProjectListItemAddChatButton {
|
|
7066
|
+
align-items: center;
|
|
7067
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryBackground, #3a434f) 76%, transparent);
|
|
7068
|
+
border: 0;
|
|
7069
|
+
border-radius: 5px;
|
|
7070
|
+
color: var(--ColorForeground, #d0d8e2);
|
|
7071
|
+
cursor: pointer;
|
|
7072
|
+
display: inline-flex;
|
|
7073
|
+
font-size: 13px;
|
|
7074
|
+
font-weight: 500;
|
|
7075
|
+
height: 18px;
|
|
7076
|
+
justify-content: center;
|
|
7077
|
+
opacity: 0;
|
|
7078
|
+
padding: 0;
|
|
7079
|
+
transition: opacity 90ms ease, background-color 90ms ease;
|
|
7080
|
+
visibility: hidden;
|
|
7081
|
+
width: 18px;
|
|
7082
|
+
}
|
|
7083
|
+
|
|
7084
|
+
.ProjectListItem:hover .ProjectListItemAddChatButton,
|
|
7085
|
+
.ProjectListItem:focus-within .ProjectListItemAddChatButton {
|
|
7086
|
+
opacity: 1;
|
|
7087
|
+
visibility: visible;
|
|
7088
|
+
}
|
|
7089
|
+
|
|
7090
|
+
.ProjectListItemAddChatButton:hover,
|
|
7091
|
+
.ProjectListItemAddChatButton:focus-visible {
|
|
7092
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryHoverBackground, #4a5460) 82%, transparent);
|
|
7093
|
+
}
|
|
7094
|
+
|
|
7095
|
+
.ProjectSessionItem {
|
|
7096
|
+
align-items: center;
|
|
7097
|
+
display: flex;
|
|
7098
|
+
min-height: calc(var(--ChatListItemHeight) - 5px);
|
|
7099
|
+
}
|
|
7100
|
+
|
|
7101
|
+
.ProjectSessionItemLabel {
|
|
7102
|
+
border-radius: 6px;
|
|
7103
|
+
color: color-mix(in srgb, var(--ColorForeground, #cfd7df) 92%, transparent);
|
|
7104
|
+
cursor: pointer;
|
|
7105
|
+
display: block;
|
|
7106
|
+
flex: 1;
|
|
7107
|
+
font-size: 12.5px;
|
|
7108
|
+
overflow: hidden;
|
|
7109
|
+
padding: 0 10px 0 28px;
|
|
7110
|
+
text-overflow: ellipsis;
|
|
7111
|
+
transition: background-color 80ms ease, color 80ms ease;
|
|
7112
|
+
white-space: nowrap;
|
|
7113
|
+
}
|
|
7114
|
+
|
|
7115
|
+
.ProjectSessionItemSelected {
|
|
7116
|
+
background: color-mix(in srgb, var(--ColorListInactiveSelectionBackground, #353f4a) 86%, #2c3540 14%);
|
|
7117
|
+
}
|
|
7118
|
+
|
|
7119
|
+
.ProjectSessionItem:not(.ProjectSessionItemSelected) .ProjectSessionItemLabel:hover,
|
|
7120
|
+
.ProjectSessionItem:not(.ProjectSessionItemSelected) .ProjectSessionItemLabel:focus-visible {
|
|
7121
|
+
background: color-mix(in srgb, var(--ColorListHoverBackground, #38414c) 46%, transparent);
|
|
7122
|
+
}
|
|
7123
|
+
|
|
7124
|
+
.ProjectSessionItemSelected .ProjectSessionItemLabel {
|
|
7125
|
+
color: var(--ColorListInactiveSelectionForeground, #f2f6fc);
|
|
7126
|
+
}
|
|
7127
|
+
|
|
7128
|
+
.Chat.ChatFocus .ProjectAddButton {
|
|
7129
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryBackground, #21252c) 72%, transparent);
|
|
7130
|
+
border: 0;
|
|
7131
|
+
border-top: 1px solid color-mix(in srgb, var(--ColorBorder, #3a3d41) 70%, transparent);
|
|
7132
|
+
color: var(--ColorForeground, #d2d9e2);
|
|
7133
|
+
cursor: pointer;
|
|
7134
|
+
font-size: 12.5px;
|
|
7135
|
+
letter-spacing: 0.01em;
|
|
7136
|
+
margin-top: auto;
|
|
7137
|
+
min-height: var(--ChatListItemHeight);
|
|
7138
|
+
padding: 0 12px;
|
|
7139
|
+
text-align: left;
|
|
7140
|
+
transition: background-color 80ms ease;
|
|
7141
|
+
}
|
|
7142
|
+
|
|
7143
|
+
.Chat.ChatFocus .ProjectAddButton:hover,
|
|
7144
|
+
.Chat.ChatFocus .ProjectAddButton:focus-visible {
|
|
7145
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryHoverBackground, #2a3039) 78%, transparent);
|
|
7146
|
+
}
|
|
7147
|
+
|
|
7148
|
+
.ChatList,
|
|
7149
|
+
.ChatListEmpty,
|
|
7150
|
+
.ChatMessages {
|
|
7151
|
+
min-height: 0;
|
|
7152
|
+
}
|
|
7153
|
+
|
|
7154
|
+
.Chat.ChatFocus .ChatList,
|
|
7155
|
+
.Chat.ChatFocus .ChatListEmpty {
|
|
7156
|
+
display: none;
|
|
7157
|
+
}
|
|
7158
|
+
|
|
7159
|
+
.Chat.ChatFocus .ChatMessages {
|
|
7160
|
+
grid-column: 2;
|
|
7161
|
+
grid-row: 2;
|
|
7162
|
+
}
|
|
7163
|
+
|
|
7164
|
+
.Chat.ChatFocus .ChatSendArea {
|
|
7165
|
+
grid-column: 2;
|
|
7166
|
+
grid-row: 3;
|
|
7167
|
+
}
|
|
6602
7168
|
`;
|
|
6603
7169
|
if (!renderHtmlCss.trim()) {
|
|
6604
7170
|
return baseCss;
|
|
@@ -6676,6 +7242,19 @@ const ChatList = 'ChatList';
|
|
|
6676
7242
|
const ChatListEmpty = 'ChatListEmpty';
|
|
6677
7243
|
const ChatListItem = 'ChatListItem';
|
|
6678
7244
|
const ChatListItemLabel = 'ChatListItemLabel';
|
|
7245
|
+
const ProjectAddButton = 'ProjectAddButton';
|
|
7246
|
+
const ProjectList = 'ProjectList';
|
|
7247
|
+
const ProjectListChevron = 'ProjectListChevron';
|
|
7248
|
+
const ProjectListGroup = 'ProjectListGroup';
|
|
7249
|
+
const ProjectListItem = 'ProjectListItem';
|
|
7250
|
+
const ProjectListItemActions = 'ProjectListItemActions';
|
|
7251
|
+
const ProjectListItemAddChatButton = 'ProjectListItemAddChatButton';
|
|
7252
|
+
const ProjectListItemLabel = 'ProjectListItemLabel';
|
|
7253
|
+
const ProjectListItemSelected = 'ProjectListItemSelected';
|
|
7254
|
+
const ProjectSessionItem = 'ProjectSessionItem';
|
|
7255
|
+
const ProjectSessionItemLabel = 'ProjectSessionItemLabel';
|
|
7256
|
+
const ProjectSessionItemSelected = 'ProjectSessionItemSelected';
|
|
7257
|
+
const ProjectSidebar = 'ProjectSidebar';
|
|
6679
7258
|
const Markdown = 'Markdown';
|
|
6680
7259
|
const MarkdownTable = 'MarkdownTable';
|
|
6681
7260
|
const Message = 'Message';
|
|
@@ -6726,6 +7305,7 @@ const HandleDragLeave = 28;
|
|
|
6726
7305
|
const HandleDrop = 29;
|
|
6727
7306
|
const HandleDragEnterChatView = 30;
|
|
6728
7307
|
const HandleDragOverChatView = 31;
|
|
7308
|
+
const HandleProjectListScroll = 32;
|
|
6729
7309
|
|
|
6730
7310
|
const getModelLabel = model => {
|
|
6731
7311
|
if (model.provider === 'openRouter') {
|
|
@@ -6842,82 +7422,6 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOvervie
|
|
|
6842
7422
|
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled)];
|
|
6843
7423
|
};
|
|
6844
7424
|
|
|
6845
|
-
const getBackButtonVirtualDom = () => {
|
|
6846
|
-
return [{
|
|
6847
|
-
childCount: 1,
|
|
6848
|
-
className: IconButton,
|
|
6849
|
-
name: Back,
|
|
6850
|
-
onClick: HandleClickBack,
|
|
6851
|
-
role: Button$2,
|
|
6852
|
-
title: backToChats(),
|
|
6853
|
-
type: Button$1
|
|
6854
|
-
}, {
|
|
6855
|
-
childCount: 0,
|
|
6856
|
-
className: 'MaskIcon MaskIconArrowLeft',
|
|
6857
|
-
type: Div
|
|
6858
|
-
}];
|
|
6859
|
-
};
|
|
6860
|
-
|
|
6861
|
-
const getHeaderActionVirtualDom = item => {
|
|
6862
|
-
return [{
|
|
6863
|
-
childCount: 1,
|
|
6864
|
-
className: IconButton,
|
|
6865
|
-
name: item.name,
|
|
6866
|
-
onClick: item.onClick,
|
|
6867
|
-
title: item.title,
|
|
6868
|
-
type: Button$1
|
|
6869
|
-
}, {
|
|
6870
|
-
childCount: 0,
|
|
6871
|
-
className: item.icon,
|
|
6872
|
-
type: Div
|
|
6873
|
-
}];
|
|
6874
|
-
};
|
|
6875
|
-
|
|
6876
|
-
const getChatHeaderActionsDom = () => {
|
|
6877
|
-
const items = [{
|
|
6878
|
-
icon: 'MaskIcon MaskIconDebugPause',
|
|
6879
|
-
name: SessionDebug,
|
|
6880
|
-
onClick: HandleClickSessionDebug,
|
|
6881
|
-
title: debug()
|
|
6882
|
-
}, {
|
|
6883
|
-
icon: 'MaskIcon MaskIconAdd',
|
|
6884
|
-
name: CreateSession,
|
|
6885
|
-
onClick: HandleClickNew,
|
|
6886
|
-
title: newChat()
|
|
6887
|
-
}, {
|
|
6888
|
-
icon: 'MaskIcon MaskIconSettingsGear',
|
|
6889
|
-
name: Settings,
|
|
6890
|
-
onClick: HandleClickSettings,
|
|
6891
|
-
title: settings()
|
|
6892
|
-
}, {
|
|
6893
|
-
icon: 'MaskIcon MaskIconClose',
|
|
6894
|
-
name: CloseChat,
|
|
6895
|
-
onClick: HandleClickClose,
|
|
6896
|
-
title: closeChat()
|
|
6897
|
-
}];
|
|
6898
|
-
return [{
|
|
6899
|
-
childCount: items.length,
|
|
6900
|
-
className: ChatActions,
|
|
6901
|
-
type: Div
|
|
6902
|
-
}, ...items.flatMap(getHeaderActionVirtualDom)];
|
|
6903
|
-
};
|
|
6904
|
-
|
|
6905
|
-
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
6906
|
-
return [{
|
|
6907
|
-
childCount: 2,
|
|
6908
|
-
className: ChatHeader,
|
|
6909
|
-
type: Div
|
|
6910
|
-
}, {
|
|
6911
|
-
childCount: 2,
|
|
6912
|
-
className: ChatName,
|
|
6913
|
-
type: Div
|
|
6914
|
-
}, ...getBackButtonVirtualDom(), {
|
|
6915
|
-
childCount: 1,
|
|
6916
|
-
className: Label,
|
|
6917
|
-
type: Span
|
|
6918
|
-
}, text(selectedSessionTitle), ...getChatHeaderActionsDom()];
|
|
6919
|
-
};
|
|
6920
|
-
|
|
6921
7425
|
const getInlineNodeDom = inlineNode => {
|
|
6922
7426
|
if (inlineNode.type === 'text') {
|
|
6923
7427
|
return [text(inlineNode.text)];
|
|
@@ -7457,8 +7961,12 @@ const getElementType = tagName => {
|
|
|
7457
7961
|
return inlineTags.has(tagName) ? Span : Div;
|
|
7458
7962
|
}
|
|
7459
7963
|
};
|
|
7964
|
+
const isHttpUrl$1 = url => {
|
|
7965
|
+
const normalized = url.trim().toLowerCase();
|
|
7966
|
+
return normalized.startsWith('http://') || normalized.startsWith('https://');
|
|
7967
|
+
};
|
|
7460
7968
|
const normalizeUrl = url => {
|
|
7461
|
-
return url
|
|
7969
|
+
return isHttpUrl$1(url) ? url : '#';
|
|
7462
7970
|
};
|
|
7463
7971
|
const getElementAttributes = node => {
|
|
7464
7972
|
const attributes = {};
|
|
@@ -7603,6 +8111,13 @@ const markdownInlineRegex = /\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|\*([^*]+)\*
|
|
|
7603
8111
|
const markdownTableSeparatorCellRegex = /^:?-{3,}:?$/;
|
|
7604
8112
|
const fencedCodeBlockRegex = /^```/;
|
|
7605
8113
|
const markdownHeadingRegex = /^\s*(#{1,6})\s+(.*)$/;
|
|
8114
|
+
const isHttpUrl = url => {
|
|
8115
|
+
const normalized = url.trim().toLowerCase();
|
|
8116
|
+
return normalized.startsWith('http://') || normalized.startsWith('https://');
|
|
8117
|
+
};
|
|
8118
|
+
const sanitizeUrl = url => {
|
|
8119
|
+
return isHttpUrl(url) ? url : '#';
|
|
8120
|
+
};
|
|
7606
8121
|
const normalizeEscapedNewlines = value => {
|
|
7607
8122
|
if (value.includes('\\n')) {
|
|
7608
8123
|
return value.replaceAll(/\\r\\n|\\n/g, '\n');
|
|
@@ -7672,7 +8187,7 @@ const parseInlineNodes = value => {
|
|
|
7672
8187
|
}
|
|
7673
8188
|
if (linkText && href) {
|
|
7674
8189
|
nodes.push({
|
|
7675
|
-
href,
|
|
8190
|
+
href: sanitizeUrl(href),
|
|
7676
8191
|
text: linkText,
|
|
7677
8192
|
type: 'link'
|
|
7678
8193
|
});
|
|
@@ -7880,6 +8395,204 @@ const getMessagesDom = (messages, openRouterApiKeyInput, openApiApiKeyInput = ''
|
|
|
7880
8395
|
}, ...messages.flatMap(message => getChatMessageDom(message, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState))];
|
|
7881
8396
|
};
|
|
7882
8397
|
|
|
8398
|
+
const getProjectSessionDom = (session, selectedSessionId) => {
|
|
8399
|
+
const className = mergeClassNames(ProjectSessionItem, session.id === selectedSessionId ? ProjectSessionItemSelected : Empty);
|
|
8400
|
+
return [{
|
|
8401
|
+
childCount: 1,
|
|
8402
|
+
className,
|
|
8403
|
+
type: Div
|
|
8404
|
+
}, {
|
|
8405
|
+
childCount: 1,
|
|
8406
|
+
className: ProjectSessionItemLabel,
|
|
8407
|
+
name: getSessionInputName(session.id),
|
|
8408
|
+
onClick: HandleClick,
|
|
8409
|
+
tabIndex: 0,
|
|
8410
|
+
type: Div
|
|
8411
|
+
}, text(session.title)];
|
|
8412
|
+
};
|
|
8413
|
+
const getProjectGroupDom = (project, sessions, projectExpandedIds, selectedProjectId, selectedSessionId) => {
|
|
8414
|
+
const expanded = projectExpandedIds.includes(project.id);
|
|
8415
|
+
const projectClassName = mergeClassNames(ProjectListItem, project.id === selectedProjectId ? ProjectListItemSelected : Empty);
|
|
8416
|
+
return [{
|
|
8417
|
+
childCount: 1 + (expanded ? sessions.length : 0),
|
|
8418
|
+
className: ProjectListGroup,
|
|
8419
|
+
type: Div
|
|
8420
|
+
}, {
|
|
8421
|
+
childCount: 2,
|
|
8422
|
+
className: projectClassName,
|
|
8423
|
+
type: Div
|
|
8424
|
+
}, {
|
|
8425
|
+
childCount: 2,
|
|
8426
|
+
className: ProjectListItemLabel,
|
|
8427
|
+
name: getProjectInputName(project.id),
|
|
8428
|
+
onClick: HandleClick,
|
|
8429
|
+
tabIndex: 0,
|
|
8430
|
+
type: Div
|
|
8431
|
+
}, {
|
|
8432
|
+
childCount: 1,
|
|
8433
|
+
className: ProjectListChevron,
|
|
8434
|
+
type: Span
|
|
8435
|
+
}, text(expanded ? '▾' : '▸'), text(project.name), {
|
|
8436
|
+
childCount: 1,
|
|
8437
|
+
className: ProjectListItemActions,
|
|
8438
|
+
type: Div
|
|
8439
|
+
}, {
|
|
8440
|
+
childCount: 1,
|
|
8441
|
+
className: ProjectListItemAddChatButton,
|
|
8442
|
+
name: getCreateSessionInProjectInputName(project.id),
|
|
8443
|
+
onClick: HandleClick,
|
|
8444
|
+
tabIndex: 0,
|
|
8445
|
+
title: 'New chat in this project',
|
|
8446
|
+
type: Button$1
|
|
8447
|
+
}, text('+'), ...(expanded ? sessions.flatMap(session => getProjectSessionDom(session, selectedSessionId)) : [])];
|
|
8448
|
+
};
|
|
8449
|
+
const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop) => {
|
|
8450
|
+
const blankProjectId = projects.find(project => project.name === '_blank')?.id || projects[0]?.id || '';
|
|
8451
|
+
const projectGroups = projects.map(project => {
|
|
8452
|
+
const projectSessions = sessions.filter(session => {
|
|
8453
|
+
const sessionProjectId = session.projectId || blankProjectId;
|
|
8454
|
+
return sessionProjectId === project.id;
|
|
8455
|
+
});
|
|
8456
|
+
return getProjectGroupDom(project, projectSessions, projectExpandedIds, selectedProjectId, selectedSessionId);
|
|
8457
|
+
});
|
|
8458
|
+
return [{
|
|
8459
|
+
childCount: 2,
|
|
8460
|
+
className: ProjectSidebar,
|
|
8461
|
+
type: Div
|
|
8462
|
+
}, {
|
|
8463
|
+
childCount: projects.length,
|
|
8464
|
+
className: ProjectList,
|
|
8465
|
+
onScroll: HandleProjectListScroll,
|
|
8466
|
+
scrollTop: projectListScrollTop,
|
|
8467
|
+
type: Div
|
|
8468
|
+
}, ...projectGroups.flat(), {
|
|
8469
|
+
childCount: 1,
|
|
8470
|
+
className: ProjectAddButton,
|
|
8471
|
+
name: CreateProject,
|
|
8472
|
+
onClick: HandleClick,
|
|
8473
|
+
tabIndex: 0,
|
|
8474
|
+
type: Button$1
|
|
8475
|
+
}, text('+ Add Project')];
|
|
8476
|
+
};
|
|
8477
|
+
|
|
8478
|
+
const getChatModeChatFocusVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0) => {
|
|
8479
|
+
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
8480
|
+
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
8481
|
+
const messages = selectedSession ? selectedSession.messages : [];
|
|
8482
|
+
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
8483
|
+
return [{
|
|
8484
|
+
childCount: 5,
|
|
8485
|
+
className: mergeClassNames(Viewlet, Chat, 'ChatFocus'),
|
|
8486
|
+
onDragEnter: HandleDragEnterChatView,
|
|
8487
|
+
onDragOver: HandleDragOverChatView,
|
|
8488
|
+
type: Div
|
|
8489
|
+
}, {
|
|
8490
|
+
childCount: 1,
|
|
8491
|
+
className: ChatHeader,
|
|
8492
|
+
type: Div
|
|
8493
|
+
}, {
|
|
8494
|
+
childCount: 1,
|
|
8495
|
+
className: Label,
|
|
8496
|
+
type: Span
|
|
8497
|
+
}, {
|
|
8498
|
+
text: selectedSessionTitle,
|
|
8499
|
+
type: Text
|
|
8500
|
+
}, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop), ...getMessagesDom(messages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight, composerFontSize, composerFontFamily, composerLineHeight), {
|
|
8501
|
+
childCount: 1,
|
|
8502
|
+
className: mergeClassNames(ChatViewDropOverlay, isDropOverlayVisible ? ChatViewDropOverlayActive : Empty),
|
|
8503
|
+
name: ComposerDropTarget,
|
|
8504
|
+
onDragLeave: HandleDragLeave,
|
|
8505
|
+
onDragOver: HandleDragOver,
|
|
8506
|
+
onDrop: HandleDrop,
|
|
8507
|
+
type: Div
|
|
8508
|
+
}, {
|
|
8509
|
+
text: attachImageAsContext(),
|
|
8510
|
+
type: Text
|
|
8511
|
+
}];
|
|
8512
|
+
};
|
|
8513
|
+
|
|
8514
|
+
const getBackButtonVirtualDom = () => {
|
|
8515
|
+
return [{
|
|
8516
|
+
childCount: 1,
|
|
8517
|
+
className: IconButton,
|
|
8518
|
+
name: Back,
|
|
8519
|
+
onClick: HandleClickBack,
|
|
8520
|
+
role: Button$2,
|
|
8521
|
+
title: backToChats(),
|
|
8522
|
+
type: Button$1
|
|
8523
|
+
}, {
|
|
8524
|
+
childCount: 0,
|
|
8525
|
+
className: 'MaskIcon MaskIconArrowLeft',
|
|
8526
|
+
type: Div
|
|
8527
|
+
}];
|
|
8528
|
+
};
|
|
8529
|
+
|
|
8530
|
+
const getHeaderActionVirtualDom = item => {
|
|
8531
|
+
return [{
|
|
8532
|
+
childCount: 1,
|
|
8533
|
+
className: IconButton,
|
|
8534
|
+
name: item.name,
|
|
8535
|
+
onClick: item.onClick,
|
|
8536
|
+
title: item.title,
|
|
8537
|
+
type: Button$1
|
|
8538
|
+
}, {
|
|
8539
|
+
childCount: 0,
|
|
8540
|
+
className: item.icon,
|
|
8541
|
+
type: Div
|
|
8542
|
+
}];
|
|
8543
|
+
};
|
|
8544
|
+
|
|
8545
|
+
const getChatHeaderActionsDom = viewMode => {
|
|
8546
|
+
const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
|
|
8547
|
+
const items = [{
|
|
8548
|
+
icon: 'MaskIcon MaskIconLayoutPanelLeft',
|
|
8549
|
+
name: ToggleChatFocus,
|
|
8550
|
+
onClick: HandleClick,
|
|
8551
|
+
title: toggleTitle
|
|
8552
|
+
}, {
|
|
8553
|
+
icon: 'MaskIcon MaskIconDebugPause',
|
|
8554
|
+
name: SessionDebug,
|
|
8555
|
+
onClick: HandleClickSessionDebug,
|
|
8556
|
+
title: debug()
|
|
8557
|
+
}, {
|
|
8558
|
+
icon: 'MaskIcon MaskIconAdd',
|
|
8559
|
+
name: CreateSession,
|
|
8560
|
+
onClick: HandleClickNew,
|
|
8561
|
+
title: newChat()
|
|
8562
|
+
}, {
|
|
8563
|
+
icon: 'MaskIcon MaskIconSettingsGear',
|
|
8564
|
+
name: Settings,
|
|
8565
|
+
onClick: HandleClickSettings,
|
|
8566
|
+
title: settings()
|
|
8567
|
+
}, {
|
|
8568
|
+
icon: 'MaskIcon MaskIconClose',
|
|
8569
|
+
name: CloseChat,
|
|
8570
|
+
onClick: HandleClickClose,
|
|
8571
|
+
title: closeChat()
|
|
8572
|
+
}];
|
|
8573
|
+
return [{
|
|
8574
|
+
childCount: items.length,
|
|
8575
|
+
className: ChatActions,
|
|
8576
|
+
type: Div
|
|
8577
|
+
}, ...items.flatMap(getHeaderActionVirtualDom)];
|
|
8578
|
+
};
|
|
8579
|
+
|
|
8580
|
+
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
8581
|
+
return [{
|
|
8582
|
+
childCount: 2,
|
|
8583
|
+
className: ChatHeader,
|
|
8584
|
+
type: Div
|
|
8585
|
+
}, {
|
|
8586
|
+
childCount: 2,
|
|
8587
|
+
className: ChatName,
|
|
8588
|
+
type: Div
|
|
8589
|
+
}, ...getBackButtonVirtualDom(), {
|
|
8590
|
+
childCount: 1,
|
|
8591
|
+
className: Label,
|
|
8592
|
+
type: Span
|
|
8593
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail')];
|
|
8594
|
+
};
|
|
8595
|
+
|
|
7883
8596
|
const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true) => {
|
|
7884
8597
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
7885
8598
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
@@ -7914,7 +8627,7 @@ const getChatHeaderListModeDom = () => {
|
|
|
7914
8627
|
childCount: 1,
|
|
7915
8628
|
className: Label,
|
|
7916
8629
|
type: Span
|
|
7917
|
-
}, text(chats()), ...getChatHeaderActionsDom()];
|
|
8630
|
+
}, text(chats()), ...getChatHeaderActionsDom('list')];
|
|
7918
8631
|
};
|
|
7919
8632
|
|
|
7920
8633
|
const getEmptyChatSessionsDom = () => {
|
|
@@ -8001,8 +8714,10 @@ const getChatModeUnsupportedVirtualDom = () => {
|
|
|
8001
8714
|
}, text(unknownViewMode())];
|
|
8002
8715
|
};
|
|
8003
8716
|
|
|
8004
|
-
const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive = false, composerDropEnabled = true) => {
|
|
8717
|
+
const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0) => {
|
|
8005
8718
|
switch (viewMode) {
|
|
8719
|
+
case 'chat-focus':
|
|
8720
|
+
return getChatModeChatFocusVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop);
|
|
8006
8721
|
case 'detail':
|
|
8007
8722
|
return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled);
|
|
8008
8723
|
case 'list':
|
|
@@ -8028,7 +8743,11 @@ const renderItems = (oldState, newState) => {
|
|
|
8028
8743
|
openApiApiKeyInput,
|
|
8029
8744
|
openRouterApiKeyInput,
|
|
8030
8745
|
openRouterApiKeyState,
|
|
8746
|
+
projectExpandedIds,
|
|
8747
|
+
projectListScrollTop,
|
|
8748
|
+
projects,
|
|
8031
8749
|
selectedModelId,
|
|
8750
|
+
selectedProjectId,
|
|
8032
8751
|
selectedSessionId,
|
|
8033
8752
|
sessions,
|
|
8034
8753
|
tokensMax,
|
|
@@ -8040,7 +8759,7 @@ const renderItems = (oldState, newState) => {
|
|
|
8040
8759
|
if (initial) {
|
|
8041
8760
|
return [SetDom2, uid, []];
|
|
8042
8761
|
}
|
|
8043
|
-
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive, composerDropEnabled);
|
|
8762
|
+
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop);
|
|
8044
8763
|
return [SetDom2, uid, dom];
|
|
8045
8764
|
};
|
|
8046
8765
|
|
|
@@ -8177,6 +8896,9 @@ const renderEventListeners = () => {
|
|
|
8177
8896
|
}, {
|
|
8178
8897
|
name: HandleMessagesScroll,
|
|
8179
8898
|
params: ['handleMessagesScroll', 'event.target.scrollTop']
|
|
8899
|
+
}, {
|
|
8900
|
+
name: HandleProjectListScroll,
|
|
8901
|
+
params: ['handleProjectListScroll', 'event.target.scrollTop']
|
|
8180
8902
|
}, {
|
|
8181
8903
|
name: HandleMessagesContextMenu,
|
|
8182
8904
|
params: ['handleMessagesContextMenu'],
|
|
@@ -8224,20 +8946,30 @@ const saveState = state => {
|
|
|
8224
8946
|
const {
|
|
8225
8947
|
chatListScrollTop,
|
|
8226
8948
|
composerValue,
|
|
8949
|
+
lastNormalViewMode,
|
|
8227
8950
|
messagesScrollTop,
|
|
8228
8951
|
nextMessageId,
|
|
8952
|
+
projectExpandedIds,
|
|
8953
|
+
projectListScrollTop,
|
|
8954
|
+
projects,
|
|
8229
8955
|
renamingSessionId,
|
|
8230
8956
|
selectedModelId,
|
|
8957
|
+
selectedProjectId,
|
|
8231
8958
|
selectedSessionId,
|
|
8232
8959
|
viewMode
|
|
8233
8960
|
} = state;
|
|
8234
8961
|
return {
|
|
8235
8962
|
chatListScrollTop,
|
|
8236
8963
|
composerValue,
|
|
8964
|
+
lastNormalViewMode,
|
|
8237
8965
|
messagesScrollTop,
|
|
8238
8966
|
nextMessageId,
|
|
8967
|
+
projectExpandedIds,
|
|
8968
|
+
projectListScrollTop,
|
|
8969
|
+
projects,
|
|
8239
8970
|
renamingSessionId,
|
|
8240
8971
|
selectedModelId,
|
|
8972
|
+
selectedProjectId,
|
|
8241
8973
|
selectedSessionId,
|
|
8242
8974
|
viewMode
|
|
8243
8975
|
};
|
|
@@ -8336,6 +9068,7 @@ const commandMap = {
|
|
|
8336
9068
|
'Chat.handleMessagesContextMenu': wrapCommand(handleMessagesContextMenu),
|
|
8337
9069
|
'Chat.handleMessagesScroll': wrapCommand(handleMessagesScroll),
|
|
8338
9070
|
'Chat.handleModelChange': wrapCommand(handleModelChange),
|
|
9071
|
+
'Chat.handleProjectListScroll': wrapCommand(handleProjectListScroll),
|
|
8339
9072
|
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
8340
9073
|
'Chat.initialize': initialize,
|
|
8341
9074
|
'Chat.loadContent': wrapCommand(loadContent),
|