@lvce-editor/chat-view 3.9.0 → 4.0.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 +850 -110
- 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
|
};
|
|
@@ -1336,6 +1340,12 @@ const backToChats = () => {
|
|
|
1336
1340
|
const settings = () => {
|
|
1337
1341
|
return i18nString('Settings');
|
|
1338
1342
|
};
|
|
1343
|
+
const chatFocusMode = () => {
|
|
1344
|
+
return i18nString('Switch to chat focus mode');
|
|
1345
|
+
};
|
|
1346
|
+
const normalChatMode = () => {
|
|
1347
|
+
return i18nString('Switch to normal chat mode');
|
|
1348
|
+
};
|
|
1339
1349
|
const closeChat = () => {
|
|
1340
1350
|
return i18nString('Close Chat');
|
|
1341
1351
|
};
|
|
@@ -1393,13 +1403,16 @@ const unknownViewMode = () => {
|
|
|
1393
1403
|
|
|
1394
1404
|
/* eslint-disable @cspell/spellchecker */
|
|
1395
1405
|
|
|
1396
|
-
const
|
|
1406
|
+
const getDefaultModelsTest = () => {
|
|
1397
1407
|
const defaultModelId = 'test';
|
|
1398
1408
|
return [{
|
|
1399
1409
|
id: defaultModelId,
|
|
1400
1410
|
name: 'test',
|
|
1401
1411
|
provider: 'test'
|
|
1402
|
-
}
|
|
1412
|
+
}];
|
|
1413
|
+
};
|
|
1414
|
+
const getDefaultModelsOpenAi = () => {
|
|
1415
|
+
return [{
|
|
1403
1416
|
id: 'openapi/gpt-5-mini',
|
|
1404
1417
|
name: 'GPT-5 Mini',
|
|
1405
1418
|
provider: 'openApi'
|
|
@@ -1415,7 +1428,10 @@ const getDefaultModels = () => {
|
|
|
1415
1428
|
id: 'openapi/gpt-4.1-mini',
|
|
1416
1429
|
name: 'GPT-4.1 Mini',
|
|
1417
1430
|
provider: 'openApi'
|
|
1418
|
-
}
|
|
1431
|
+
}];
|
|
1432
|
+
};
|
|
1433
|
+
const getDefaultModelsOpenRouter = () => {
|
|
1434
|
+
return [{
|
|
1419
1435
|
id: 'codex-5.3',
|
|
1420
1436
|
name: 'Codex 5.3',
|
|
1421
1437
|
provider: 'openRouter'
|
|
@@ -1465,7 +1481,12 @@ const getDefaultModels = () => {
|
|
|
1465
1481
|
provider: 'openRouter'
|
|
1466
1482
|
}];
|
|
1467
1483
|
};
|
|
1484
|
+
const getDefaultModels = () => {
|
|
1485
|
+
return [...getDefaultModelsTest(), ...getDefaultModelsOpenAi(), ...getDefaultModelsOpenRouter()];
|
|
1486
|
+
};
|
|
1487
|
+
|
|
1468
1488
|
const createDefaultState = () => {
|
|
1489
|
+
const defaultProjectId = 'project-1';
|
|
1469
1490
|
const defaultSessionId = 'session-1';
|
|
1470
1491
|
const defaultModelId = 'test';
|
|
1471
1492
|
const chatMessageFontSize = 13;
|
|
@@ -1494,6 +1515,7 @@ const createDefaultState = () => {
|
|
|
1494
1515
|
height: 0,
|
|
1495
1516
|
initial: true,
|
|
1496
1517
|
inputSource: 'script',
|
|
1518
|
+
lastNormalViewMode: 'list',
|
|
1497
1519
|
lastSubmittedSessionId: '',
|
|
1498
1520
|
listItemHeight: 40,
|
|
1499
1521
|
maxComposerRows: 5,
|
|
@@ -1513,12 +1535,21 @@ const createDefaultState = () => {
|
|
|
1513
1535
|
openRouterApiKeyState: 'idle',
|
|
1514
1536
|
passIncludeObfuscation: false,
|
|
1515
1537
|
platform: 0,
|
|
1538
|
+
projectExpandedIds: [defaultProjectId],
|
|
1539
|
+
projectListScrollTop: 0,
|
|
1540
|
+
projects: [{
|
|
1541
|
+
id: defaultProjectId,
|
|
1542
|
+
name: '_blank',
|
|
1543
|
+
uri: ''
|
|
1544
|
+
}],
|
|
1516
1545
|
renamingSessionId: '',
|
|
1517
1546
|
selectedModelId: defaultModelId,
|
|
1547
|
+
selectedProjectId: defaultProjectId,
|
|
1518
1548
|
selectedSessionId: defaultSessionId,
|
|
1519
1549
|
sessions: [{
|
|
1520
1550
|
id: defaultSessionId,
|
|
1521
1551
|
messages: [],
|
|
1552
|
+
projectId: defaultProjectId,
|
|
1522
1553
|
title: defaultSessionTitle()
|
|
1523
1554
|
}],
|
|
1524
1555
|
streamingEnabled: true,
|
|
@@ -2138,29 +2169,49 @@ const createDefaultStorage = () => {
|
|
|
2138
2169
|
let chatSessionStorage = createDefaultStorage();
|
|
2139
2170
|
const listChatSessions = async () => {
|
|
2140
2171
|
const sessions = await chatSessionStorage.listSessions();
|
|
2141
|
-
return sessions.map(session =>
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2172
|
+
return sessions.map(session => {
|
|
2173
|
+
const summary = {
|
|
2174
|
+
id: session.id,
|
|
2175
|
+
messages: [],
|
|
2176
|
+
title: session.title
|
|
2177
|
+
};
|
|
2178
|
+
if (!session.projectId) {
|
|
2179
|
+
return summary;
|
|
2180
|
+
}
|
|
2181
|
+
return {
|
|
2182
|
+
...summary,
|
|
2183
|
+
projectId: session.projectId
|
|
2184
|
+
};
|
|
2185
|
+
});
|
|
2146
2186
|
};
|
|
2147
2187
|
const getChatSession = async id => {
|
|
2148
2188
|
const session = await chatSessionStorage.getSession(id);
|
|
2149
2189
|
if (!session) {
|
|
2150
2190
|
return undefined;
|
|
2151
2191
|
}
|
|
2152
|
-
|
|
2192
|
+
const result = {
|
|
2153
2193
|
id: session.id,
|
|
2154
2194
|
messages: [...session.messages],
|
|
2155
2195
|
title: session.title
|
|
2156
2196
|
};
|
|
2197
|
+
if (!session.projectId) {
|
|
2198
|
+
return result;
|
|
2199
|
+
}
|
|
2200
|
+
return {
|
|
2201
|
+
...result,
|
|
2202
|
+
projectId: session.projectId
|
|
2203
|
+
};
|
|
2157
2204
|
};
|
|
2158
2205
|
const saveChatSession = async session => {
|
|
2159
|
-
|
|
2206
|
+
const value = {
|
|
2160
2207
|
id: session.id,
|
|
2161
2208
|
messages: [...session.messages],
|
|
2162
2209
|
title: session.title
|
|
2163
|
-
}
|
|
2210
|
+
};
|
|
2211
|
+
await chatSessionStorage.setSession(session.projectId ? {
|
|
2212
|
+
...value,
|
|
2213
|
+
projectId: session.projectId
|
|
2214
|
+
} : value);
|
|
2164
2215
|
};
|
|
2165
2216
|
const deleteChatSession = async id => {
|
|
2166
2217
|
await chatSessionStorage.deleteSession(id);
|
|
@@ -2184,6 +2235,17 @@ const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
|
2184
2235
|
return sessions[nextIndex].id;
|
|
2185
2236
|
};
|
|
2186
2237
|
|
|
2238
|
+
const getVisibleSessions = (sessions, selectedProjectId) => {
|
|
2239
|
+
if (!selectedProjectId) {
|
|
2240
|
+
return sessions;
|
|
2241
|
+
}
|
|
2242
|
+
const hasAssignedProjects = sessions.some(session => !!session.projectId);
|
|
2243
|
+
if (!hasAssignedProjects) {
|
|
2244
|
+
return sessions;
|
|
2245
|
+
}
|
|
2246
|
+
return sessions.filter(session => session.projectId === selectedProjectId);
|
|
2247
|
+
};
|
|
2248
|
+
|
|
2187
2249
|
const deleteSession = async (state, id) => {
|
|
2188
2250
|
const {
|
|
2189
2251
|
renamingSessionId,
|
|
@@ -2222,10 +2284,8 @@ const deleteSession = async (state, id) => {
|
|
|
2222
2284
|
};
|
|
2223
2285
|
};
|
|
2224
2286
|
const deleteSessionAtIndex = async (state, index) => {
|
|
2225
|
-
const
|
|
2226
|
-
|
|
2227
|
-
} = state;
|
|
2228
|
-
const session = sessions[index];
|
|
2287
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
2288
|
+
const session = visibleSessions[index];
|
|
2229
2289
|
if (!session) {
|
|
2230
2290
|
return state;
|
|
2231
2291
|
}
|
|
@@ -2291,12 +2351,23 @@ const diffFocus = (oldState, newState) => {
|
|
|
2291
2351
|
return oldState.focus === newState.focus && oldState.focused === newState.focused;
|
|
2292
2352
|
};
|
|
2293
2353
|
|
|
2354
|
+
const isEqualProjectExpandedIds = (a, b) => {
|
|
2355
|
+
if (a.length !== b.length) {
|
|
2356
|
+
return false;
|
|
2357
|
+
}
|
|
2358
|
+
for (let i = 0; i < a.length; i++) {
|
|
2359
|
+
if (a[i] !== b[i]) {
|
|
2360
|
+
return false;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
return true;
|
|
2364
|
+
};
|
|
2294
2365
|
const isEqual = (oldState, newState) => {
|
|
2295
|
-
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;
|
|
2366
|
+
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;
|
|
2296
2367
|
};
|
|
2297
2368
|
|
|
2298
2369
|
const diffScrollTop = (oldState, newState) => {
|
|
2299
|
-
return oldState.chatListScrollTop === newState.chatListScrollTop && oldState.messagesScrollTop === newState.messagesScrollTop;
|
|
2370
|
+
return oldState.chatListScrollTop === newState.chatListScrollTop && oldState.messagesScrollTop === newState.messagesScrollTop && oldState.projectListScrollTop === newState.projectListScrollTop;
|
|
2300
2371
|
};
|
|
2301
2372
|
|
|
2302
2373
|
const RenderItems = 4;
|
|
@@ -2735,7 +2806,8 @@ const handleChatListContextMenu = async (state, eventX, eventY) => {
|
|
|
2735
2806
|
if (index === -1) {
|
|
2736
2807
|
return state;
|
|
2737
2808
|
}
|
|
2738
|
-
const
|
|
2809
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
2810
|
+
const item = visibleSessions[index];
|
|
2739
2811
|
if (!item) {
|
|
2740
2812
|
return state;
|
|
2741
2813
|
}
|
|
@@ -2747,22 +2819,106 @@ const generateSessionId = () => {
|
|
|
2747
2819
|
return crypto.randomUUID();
|
|
2748
2820
|
};
|
|
2749
2821
|
|
|
2750
|
-
const createSession = async state => {
|
|
2822
|
+
const createSession = async (state, projectIdOverride = '') => {
|
|
2751
2823
|
const id = generateSessionId();
|
|
2824
|
+
const fallbackProjectId = state.projects.find(project => project.name === '_blank')?.id || state.projects[0]?.id || 'project-1';
|
|
2825
|
+
const projectId = projectIdOverride || state.selectedProjectId || fallbackProjectId;
|
|
2752
2826
|
const session = {
|
|
2753
2827
|
id,
|
|
2754
2828
|
messages: [],
|
|
2829
|
+
projectId,
|
|
2755
2830
|
title: `Chat ${state.sessions.length + 1}`
|
|
2756
2831
|
};
|
|
2757
2832
|
await saveChatSession(session);
|
|
2758
2833
|
return {
|
|
2759
2834
|
...state,
|
|
2835
|
+
projectExpandedIds: state.projectExpandedIds.includes(projectId) ? state.projectExpandedIds : [...state.projectExpandedIds, projectId],
|
|
2760
2836
|
renamingSessionId: '',
|
|
2837
|
+
selectedProjectId: projectId,
|
|
2761
2838
|
selectedSessionId: id,
|
|
2762
2839
|
sessions: [...state.sessions, session]
|
|
2763
2840
|
};
|
|
2764
2841
|
};
|
|
2765
2842
|
|
|
2843
|
+
const selectProject = async (state, projectId) => {
|
|
2844
|
+
if (!projectId || state.selectedProjectId === projectId) {
|
|
2845
|
+
return state;
|
|
2846
|
+
}
|
|
2847
|
+
const visibleSessions = getVisibleSessions(state.sessions, projectId);
|
|
2848
|
+
if (visibleSessions.length === 0) {
|
|
2849
|
+
return {
|
|
2850
|
+
...state,
|
|
2851
|
+
selectedProjectId: projectId,
|
|
2852
|
+
selectedSessionId: '',
|
|
2853
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'list'
|
|
2854
|
+
};
|
|
2855
|
+
}
|
|
2856
|
+
const currentSessionVisible = visibleSessions.some(session => session.id === state.selectedSessionId);
|
|
2857
|
+
const nextSelectedSessionId = currentSessionVisible ? state.selectedSessionId : visibleSessions[0].id;
|
|
2858
|
+
const loadedSession = await getChatSession(nextSelectedSessionId);
|
|
2859
|
+
const sessions = state.sessions.map(session => {
|
|
2860
|
+
if (session.id !== nextSelectedSessionId || !loadedSession) {
|
|
2861
|
+
return session;
|
|
2862
|
+
}
|
|
2863
|
+
return loadedSession;
|
|
2864
|
+
});
|
|
2865
|
+
return {
|
|
2866
|
+
...state,
|
|
2867
|
+
selectedProjectId: projectId,
|
|
2868
|
+
selectedSessionId: nextSelectedSessionId,
|
|
2869
|
+
sessions,
|
|
2870
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
2871
|
+
};
|
|
2872
|
+
};
|
|
2873
|
+
|
|
2874
|
+
const getProjectName = (uri, fallbackIndex) => {
|
|
2875
|
+
if (!uri) {
|
|
2876
|
+
return `Project ${fallbackIndex}`;
|
|
2877
|
+
}
|
|
2878
|
+
const withoutScheme = uri.replace(/^file:\/\//, '');
|
|
2879
|
+
const normalized = withoutScheme.replace(/\/+$/, '');
|
|
2880
|
+
const lastSegment = normalized.split('/').pop();
|
|
2881
|
+
if (!lastSegment) {
|
|
2882
|
+
return `Project ${fallbackIndex}`;
|
|
2883
|
+
}
|
|
2884
|
+
return decodeURIComponent(lastSegment);
|
|
2885
|
+
};
|
|
2886
|
+
const getNextProjectId = projects => {
|
|
2887
|
+
return `project-${projects.length + 1}`;
|
|
2888
|
+
};
|
|
2889
|
+
const pickProjectUri = async () => {
|
|
2890
|
+
try {
|
|
2891
|
+
const workspaceUri = await getWorkspacePath();
|
|
2892
|
+
return workspaceUri;
|
|
2893
|
+
} catch {
|
|
2894
|
+
return '';
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2897
|
+
const handleClickCreateProject = async state => {
|
|
2898
|
+
await confirm('project added');
|
|
2899
|
+
const uri = await pickProjectUri();
|
|
2900
|
+
if (!uri) {
|
|
2901
|
+
return state;
|
|
2902
|
+
}
|
|
2903
|
+
const existingProject = state.projects.find(project => project.uri === uri);
|
|
2904
|
+
if (existingProject) {
|
|
2905
|
+
return selectProject(state, existingProject.id);
|
|
2906
|
+
}
|
|
2907
|
+
const id = getNextProjectId(state.projects);
|
|
2908
|
+
const project = {
|
|
2909
|
+
id,
|
|
2910
|
+
name: getProjectName(uri, state.projects.length + 1),
|
|
2911
|
+
uri
|
|
2912
|
+
};
|
|
2913
|
+
return {
|
|
2914
|
+
...state,
|
|
2915
|
+
projects: [...state.projects, project],
|
|
2916
|
+
selectedProjectId: project.id,
|
|
2917
|
+
selectedSessionId: '',
|
|
2918
|
+
viewMode: 'list'
|
|
2919
|
+
};
|
|
2920
|
+
};
|
|
2921
|
+
|
|
2766
2922
|
const handleClickOpenApiApiKeySettings = async state => {
|
|
2767
2923
|
await invoke('Main.openUri', 'app://settings.json');
|
|
2768
2924
|
return state;
|
|
@@ -5812,13 +5968,35 @@ const ComposerDropTarget = 'composer-drop-target';
|
|
|
5812
5968
|
const Send = 'send';
|
|
5813
5969
|
const Back = 'back';
|
|
5814
5970
|
const Model = 'model';
|
|
5971
|
+
const ToggleChatFocus = 'toggle-chat-focus';
|
|
5972
|
+
const CreateProject = 'create-project';
|
|
5815
5973
|
const CreateSession = 'create-session';
|
|
5974
|
+
const CreateSessionInProjectPrefix = 'create-session-in-project:';
|
|
5816
5975
|
const SessionDebug = 'session-debug';
|
|
5817
5976
|
const Settings = 'settings';
|
|
5818
5977
|
const CloseChat = 'close-chat';
|
|
5819
5978
|
const SessionDelete = 'SessionDelete';
|
|
5979
|
+
const ProjectPrefix = 'project:';
|
|
5820
5980
|
const SessionPrefix = 'session:';
|
|
5821
5981
|
const RenamePrefix = 'session-rename:';
|
|
5982
|
+
const getProjectInputName = projectId => {
|
|
5983
|
+
return `${ProjectPrefix}${projectId}`;
|
|
5984
|
+
};
|
|
5985
|
+
const getCreateSessionInProjectInputName = projectId => {
|
|
5986
|
+
return `${CreateSessionInProjectPrefix}${projectId}`;
|
|
5987
|
+
};
|
|
5988
|
+
const isCreateSessionInProjectInputName = name => {
|
|
5989
|
+
return name.startsWith(CreateSessionInProjectPrefix);
|
|
5990
|
+
};
|
|
5991
|
+
const getProjectIdFromCreateSessionInProjectInputName = name => {
|
|
5992
|
+
return name.slice(CreateSessionInProjectPrefix.length);
|
|
5993
|
+
};
|
|
5994
|
+
const isProjectInputName = name => {
|
|
5995
|
+
return name.startsWith(ProjectPrefix);
|
|
5996
|
+
};
|
|
5997
|
+
const getProjectIdFromInputName = name => {
|
|
5998
|
+
return name.slice(ProjectPrefix.length);
|
|
5999
|
+
};
|
|
5822
6000
|
const getSessionInputName = sessionId => {
|
|
5823
6001
|
return `${SessionPrefix}${sessionId}`;
|
|
5824
6002
|
};
|
|
@@ -5863,10 +6041,11 @@ const selectSession = async (state, id) => {
|
|
|
5863
6041
|
});
|
|
5864
6042
|
return {
|
|
5865
6043
|
...state,
|
|
6044
|
+
lastNormalViewMode: state.viewMode === 'chat-focus' ? state.lastNormalViewMode : 'detail',
|
|
5866
6045
|
renamingSessionId: '',
|
|
5867
6046
|
selectedSessionId: id,
|
|
5868
6047
|
sessions,
|
|
5869
|
-
viewMode: 'detail'
|
|
6048
|
+
viewMode: state.viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
5870
6049
|
};
|
|
5871
6050
|
};
|
|
5872
6051
|
|
|
@@ -5887,14 +6066,61 @@ const startRename = (state, id) => {
|
|
|
5887
6066
|
};
|
|
5888
6067
|
};
|
|
5889
6068
|
|
|
6069
|
+
const toggleChatFocusMode = async state => {
|
|
6070
|
+
if (state.viewMode === 'chat-focus') {
|
|
6071
|
+
return {
|
|
6072
|
+
...state,
|
|
6073
|
+
viewMode: state.lastNormalViewMode
|
|
6074
|
+
};
|
|
6075
|
+
}
|
|
6076
|
+
if (state.viewMode === 'list' || state.viewMode === 'detail') {
|
|
6077
|
+
return {
|
|
6078
|
+
...state,
|
|
6079
|
+
lastNormalViewMode: state.viewMode,
|
|
6080
|
+
viewMode: 'chat-focus'
|
|
6081
|
+
};
|
|
6082
|
+
}
|
|
6083
|
+
return state;
|
|
6084
|
+
};
|
|
6085
|
+
|
|
6086
|
+
const toggleProjectExpanded = async (state, projectId) => {
|
|
6087
|
+
const isExpanded = state.projectExpandedIds.includes(projectId);
|
|
6088
|
+
const projectExpandedIds = isExpanded ? state.projectExpandedIds.filter(id => id !== projectId) : [...state.projectExpandedIds, projectId];
|
|
6089
|
+
const visibleSessions = getVisibleSessions(state.sessions, projectId);
|
|
6090
|
+
if (visibleSessions.length === 0) {
|
|
6091
|
+
return {
|
|
6092
|
+
...state,
|
|
6093
|
+
projectExpandedIds,
|
|
6094
|
+
selectedProjectId: projectId,
|
|
6095
|
+
selectedSessionId: '',
|
|
6096
|
+
viewMode: 'chat-focus'
|
|
6097
|
+
};
|
|
6098
|
+
}
|
|
6099
|
+
const selectedSessionVisible = visibleSessions.some(session => session.id === state.selectedSessionId);
|
|
6100
|
+
const selectedSessionId = selectedSessionVisible ? state.selectedSessionId : visibleSessions[0].id;
|
|
6101
|
+
const loadedSession = await getChatSession(selectedSessionId);
|
|
6102
|
+
const sessions = state.sessions.map(session => {
|
|
6103
|
+
if (session.id !== selectedSessionId || !loadedSession) {
|
|
6104
|
+
return session;
|
|
6105
|
+
}
|
|
6106
|
+
return loadedSession;
|
|
6107
|
+
});
|
|
6108
|
+
return {
|
|
6109
|
+
...state,
|
|
6110
|
+
projectExpandedIds,
|
|
6111
|
+
selectedProjectId: projectId,
|
|
6112
|
+
selectedSessionId,
|
|
6113
|
+
sessions,
|
|
6114
|
+
viewMode: 'chat-focus'
|
|
6115
|
+
};
|
|
6116
|
+
};
|
|
6117
|
+
|
|
5890
6118
|
const selectListIndex = async (state, index) => {
|
|
5891
|
-
const
|
|
5892
|
-
|
|
5893
|
-
} = state;
|
|
5894
|
-
if (index < 0 || index >= sessions.length) {
|
|
6119
|
+
const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
|
|
6120
|
+
if (index < 0 || index >= visibleSessions.length) {
|
|
5895
6121
|
return state;
|
|
5896
6122
|
}
|
|
5897
|
-
const session =
|
|
6123
|
+
const session = visibleSessions[index];
|
|
5898
6124
|
return selectSession(state, session.id);
|
|
5899
6125
|
};
|
|
5900
6126
|
|
|
@@ -5910,6 +6136,23 @@ const handleClick = async (state, name, id = '') => {
|
|
|
5910
6136
|
if (name === CreateSession) {
|
|
5911
6137
|
return createSession(state);
|
|
5912
6138
|
}
|
|
6139
|
+
if (name === CreateProject) {
|
|
6140
|
+
return handleClickCreateProject(state);
|
|
6141
|
+
}
|
|
6142
|
+
if (isCreateSessionInProjectInputName(name)) {
|
|
6143
|
+
const projectId = getProjectIdFromCreateSessionInProjectInputName(name);
|
|
6144
|
+
return createSession(state, projectId);
|
|
6145
|
+
}
|
|
6146
|
+
if (name === ToggleChatFocus) {
|
|
6147
|
+
return toggleChatFocusMode(state);
|
|
6148
|
+
}
|
|
6149
|
+
if (isProjectInputName(name)) {
|
|
6150
|
+
const projectId = getProjectIdFromInputName(name);
|
|
6151
|
+
if (state.viewMode === 'chat-focus') {
|
|
6152
|
+
return toggleProjectExpanded(state, projectId);
|
|
6153
|
+
}
|
|
6154
|
+
return selectProject(state, projectId);
|
|
6155
|
+
}
|
|
5913
6156
|
if (isSessionInputName(name)) {
|
|
5914
6157
|
const sessionId = getSessionIdFromInputName(name);
|
|
5915
6158
|
return selectSession(state, sessionId);
|
|
@@ -5948,6 +6191,7 @@ const handleClick = async (state, name, id = '') => {
|
|
|
5948
6191
|
const handleClickBack = async state => {
|
|
5949
6192
|
return {
|
|
5950
6193
|
...state,
|
|
6194
|
+
lastNormalViewMode: 'list',
|
|
5951
6195
|
renamingSessionId: '',
|
|
5952
6196
|
viewMode: 'list'
|
|
5953
6197
|
};
|
|
@@ -6229,6 +6473,15 @@ const handleMessagesScroll = async (state, messagesScrollTop) => {
|
|
|
6229
6473
|
messagesScrollTop
|
|
6230
6474
|
};
|
|
6231
6475
|
};
|
|
6476
|
+
const handleProjectListScroll = async (state, projectListScrollTop) => {
|
|
6477
|
+
if (state.projectListScrollTop === projectListScrollTop) {
|
|
6478
|
+
return state;
|
|
6479
|
+
}
|
|
6480
|
+
return {
|
|
6481
|
+
...state,
|
|
6482
|
+
projectListScrollTop
|
|
6483
|
+
};
|
|
6484
|
+
};
|
|
6232
6485
|
|
|
6233
6486
|
const id = 7201;
|
|
6234
6487
|
const sendMessagePortToExtensionHostWorker = async port => {
|
|
@@ -6328,7 +6581,7 @@ const getSavedViewMode = savedState => {
|
|
|
6328
6581
|
const {
|
|
6329
6582
|
viewMode
|
|
6330
6583
|
} = savedState;
|
|
6331
|
-
if (viewMode !== 'list' && viewMode !== 'detail') {
|
|
6584
|
+
if (viewMode !== 'list' && viewMode !== 'detail' && viewMode !== 'chat-focus') {
|
|
6332
6585
|
return undefined;
|
|
6333
6586
|
}
|
|
6334
6587
|
return viewMode;
|
|
@@ -6445,11 +6698,97 @@ const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
|
|
|
6445
6698
|
};
|
|
6446
6699
|
|
|
6447
6700
|
const toSummarySession = session => {
|
|
6448
|
-
|
|
6701
|
+
const summary = {
|
|
6449
6702
|
id: session.id,
|
|
6450
6703
|
messages: [],
|
|
6451
6704
|
title: session.title
|
|
6452
6705
|
};
|
|
6706
|
+
if (!session.projectId) {
|
|
6707
|
+
return summary;
|
|
6708
|
+
}
|
|
6709
|
+
return {
|
|
6710
|
+
...summary,
|
|
6711
|
+
projectId: session.projectId
|
|
6712
|
+
};
|
|
6713
|
+
};
|
|
6714
|
+
const getSavedSelectedProjectId = savedState => {
|
|
6715
|
+
if (!isObject(savedState)) {
|
|
6716
|
+
return undefined;
|
|
6717
|
+
}
|
|
6718
|
+
const {
|
|
6719
|
+
selectedProjectId
|
|
6720
|
+
} = savedState;
|
|
6721
|
+
if (typeof selectedProjectId !== 'string') {
|
|
6722
|
+
return undefined;
|
|
6723
|
+
}
|
|
6724
|
+
return selectedProjectId;
|
|
6725
|
+
};
|
|
6726
|
+
const getSavedProjects = savedState => {
|
|
6727
|
+
if (!isObject(savedState)) {
|
|
6728
|
+
return undefined;
|
|
6729
|
+
}
|
|
6730
|
+
const {
|
|
6731
|
+
projects
|
|
6732
|
+
} = savedState;
|
|
6733
|
+
if (!Array.isArray(projects)) {
|
|
6734
|
+
return undefined;
|
|
6735
|
+
}
|
|
6736
|
+
const validProjects = projects.filter(project => {
|
|
6737
|
+
if (!isObject(project)) {
|
|
6738
|
+
return false;
|
|
6739
|
+
}
|
|
6740
|
+
return typeof project.id === 'string' && typeof project.name === 'string' && typeof project.uri === 'string';
|
|
6741
|
+
});
|
|
6742
|
+
if (validProjects.length === 0) {
|
|
6743
|
+
return undefined;
|
|
6744
|
+
}
|
|
6745
|
+
return validProjects;
|
|
6746
|
+
};
|
|
6747
|
+
const ensureBlankProject = (projects, fallbackBlankProject) => {
|
|
6748
|
+
if (projects.some(project => project.name === '_blank')) {
|
|
6749
|
+
return projects;
|
|
6750
|
+
}
|
|
6751
|
+
return [fallbackBlankProject, ...projects];
|
|
6752
|
+
};
|
|
6753
|
+
const getSavedProjectListScrollTop = savedState => {
|
|
6754
|
+
if (!isObject(savedState)) {
|
|
6755
|
+
return undefined;
|
|
6756
|
+
}
|
|
6757
|
+
const {
|
|
6758
|
+
projectListScrollTop
|
|
6759
|
+
} = savedState;
|
|
6760
|
+
if (typeof projectListScrollTop !== 'number') {
|
|
6761
|
+
return undefined;
|
|
6762
|
+
}
|
|
6763
|
+
return projectListScrollTop;
|
|
6764
|
+
};
|
|
6765
|
+
const getSavedProjectExpandedIds = savedState => {
|
|
6766
|
+
if (!isObject(savedState)) {
|
|
6767
|
+
return undefined;
|
|
6768
|
+
}
|
|
6769
|
+
const {
|
|
6770
|
+
projectExpandedIds
|
|
6771
|
+
} = savedState;
|
|
6772
|
+
if (!Array.isArray(projectExpandedIds)) {
|
|
6773
|
+
return undefined;
|
|
6774
|
+
}
|
|
6775
|
+
const ids = projectExpandedIds.filter(id => typeof id === 'string');
|
|
6776
|
+
if (ids.length === 0) {
|
|
6777
|
+
return undefined;
|
|
6778
|
+
}
|
|
6779
|
+
return ids;
|
|
6780
|
+
};
|
|
6781
|
+
const getSavedLastNormalViewMode = savedState => {
|
|
6782
|
+
if (!isObject(savedState)) {
|
|
6783
|
+
return undefined;
|
|
6784
|
+
}
|
|
6785
|
+
const {
|
|
6786
|
+
lastNormalViewMode
|
|
6787
|
+
} = savedState;
|
|
6788
|
+
if (lastNormalViewMode !== 'list' && lastNormalViewMode !== 'detail') {
|
|
6789
|
+
return undefined;
|
|
6790
|
+
}
|
|
6791
|
+
return lastNormalViewMode;
|
|
6453
6792
|
};
|
|
6454
6793
|
const loadContent = async (state, savedState) => {
|
|
6455
6794
|
const savedSelectedModelId = getSavedSelectedModelId(savedState);
|
|
@@ -6480,14 +6819,30 @@ const loadContent = async (state, savedState) => {
|
|
|
6480
6819
|
sessions = state.sessions.map(toSummarySession);
|
|
6481
6820
|
}
|
|
6482
6821
|
const preferredSessionId = getSavedSelectedSessionId(savedState) || state.selectedSessionId;
|
|
6822
|
+
const savedProjects = getSavedProjects(savedState);
|
|
6823
|
+
const baseProjects = savedProjects && savedProjects.length > 0 ? savedProjects : state.projects;
|
|
6824
|
+
const blankProject = state.projects.find(project => project.name === '_blank') || {
|
|
6825
|
+
id: 'project-blank',
|
|
6826
|
+
name: '_blank',
|
|
6827
|
+
uri: ''
|
|
6828
|
+
};
|
|
6829
|
+
const projects = ensureBlankProject(baseProjects, blankProject);
|
|
6830
|
+
const preferredProjectId = getSavedSelectedProjectId(savedState) || state.selectedProjectId;
|
|
6831
|
+
const selectedProjectId = projects.some(project => project.id === preferredProjectId) ? preferredProjectId : projects[0]?.id || '';
|
|
6483
6832
|
const preferredModelId = savedSelectedModelId || state.selectedModelId;
|
|
6484
6833
|
const chatListScrollTop = getSavedChatListScrollTop(savedState) ?? state.chatListScrollTop;
|
|
6485
6834
|
const messagesScrollTop = getSavedMessagesScrollTop(savedState) ?? state.messagesScrollTop;
|
|
6835
|
+
const projectListScrollTop = getSavedProjectListScrollTop(savedState) ?? state.projectListScrollTop;
|
|
6836
|
+
const savedProjectExpandedIds = getSavedProjectExpandedIds(savedState);
|
|
6837
|
+
const projectExpandedIds = (savedProjectExpandedIds || state.projectExpandedIds).filter(id => projects.some(project => project.id === id));
|
|
6486
6838
|
const selectedModelId = state.models.some(model => model.id === preferredModelId) ? preferredModelId : state.models[0]?.id || '';
|
|
6487
|
-
const
|
|
6839
|
+
const visibleSessions = getVisibleSessions(sessions, selectedProjectId);
|
|
6840
|
+
const selectedSessionId = visibleSessions.some(session => session.id === preferredSessionId) ? preferredSessionId : visibleSessions[0]?.id || '';
|
|
6488
6841
|
sessions = await loadSelectedSessionMessages(sessions, selectedSessionId);
|
|
6489
6842
|
const preferredViewMode = savedViewMode || state.viewMode;
|
|
6490
|
-
const
|
|
6843
|
+
const savedLastNormalViewMode = getSavedLastNormalViewMode(savedState);
|
|
6844
|
+
const lastNormalViewMode = savedLastNormalViewMode || (preferredViewMode === 'detail' ? 'detail' : state.lastNormalViewMode);
|
|
6845
|
+
const viewMode = sessions.length === 0 || !selectedSessionId ? 'list' : preferredViewMode;
|
|
6491
6846
|
return {
|
|
6492
6847
|
...state,
|
|
6493
6848
|
aiSessionTitleGenerationEnabled,
|
|
@@ -6496,13 +6851,18 @@ const loadContent = async (state, savedState) => {
|
|
|
6496
6851
|
composerDropEnabled,
|
|
6497
6852
|
emitStreamingFunctionCallEvents,
|
|
6498
6853
|
initial: false,
|
|
6854
|
+
lastNormalViewMode,
|
|
6499
6855
|
messagesScrollTop,
|
|
6500
6856
|
openApiApiKey,
|
|
6501
6857
|
openApiApiKeyInput: openApiApiKey,
|
|
6502
6858
|
openRouterApiKey,
|
|
6503
6859
|
openRouterApiKeyInput: openRouterApiKey,
|
|
6504
6860
|
passIncludeObfuscation,
|
|
6861
|
+
projectExpandedIds,
|
|
6862
|
+
projectListScrollTop,
|
|
6863
|
+
projects,
|
|
6505
6864
|
selectedModelId,
|
|
6865
|
+
selectedProjectId,
|
|
6506
6866
|
selectedSessionId,
|
|
6507
6867
|
sessions,
|
|
6508
6868
|
streamingEnabled,
|
|
@@ -6589,6 +6949,219 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
6589
6949
|
--ChatMessageLineHeight: ${chatMessageLineHeight}px;
|
|
6590
6950
|
--ChatMessageFontFamily: ${chatMessageFontFamily};
|
|
6591
6951
|
}
|
|
6952
|
+
|
|
6953
|
+
.Viewlet.Chat.ChatFocus {
|
|
6954
|
+
background: linear-gradient(180deg, var(--ColorViewBackground, #1d2229) 0%, #1f252d 100%);
|
|
6955
|
+
display: grid;
|
|
6956
|
+
grid-template-columns: 320px 1fr;
|
|
6957
|
+
grid-template-rows: auto 1fr auto;
|
|
6958
|
+
}
|
|
6959
|
+
|
|
6960
|
+
.Chat.ChatFocus .ChatHeader {
|
|
6961
|
+
grid-column: 1 / 3;
|
|
6962
|
+
}
|
|
6963
|
+
|
|
6964
|
+
.Chat.ChatFocus .ProjectSidebar {
|
|
6965
|
+
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 88%, #1f2b38 12%);
|
|
6966
|
+
border-right: 1px solid var(--ColorBorder, #3a3d41);
|
|
6967
|
+
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.2);
|
|
6968
|
+
display: flex;
|
|
6969
|
+
flex-direction: column;
|
|
6970
|
+
grid-column: 1;
|
|
6971
|
+
grid-row: 2 / 4;
|
|
6972
|
+
min-height: 0;
|
|
6973
|
+
}
|
|
6974
|
+
|
|
6975
|
+
.Chat.ChatFocus .ProjectList {
|
|
6976
|
+
min-height: 0;
|
|
6977
|
+
overflow: auto;
|
|
6978
|
+
padding: 10px 8px 12px;
|
|
6979
|
+
scrollbar-color: color-mix(in srgb, var(--ColorScrollBarSliderBackground, #4b5563) 78%, transparent)
|
|
6980
|
+
color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 92%, transparent);
|
|
6981
|
+
scrollbar-width: thin;
|
|
6982
|
+
}
|
|
6983
|
+
|
|
6984
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar {
|
|
6985
|
+
height: 10px;
|
|
6986
|
+
width: 10px;
|
|
6987
|
+
}
|
|
6988
|
+
|
|
6989
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-track {
|
|
6990
|
+
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 94%, transparent);
|
|
6991
|
+
border-radius: 999px;
|
|
6992
|
+
}
|
|
6993
|
+
|
|
6994
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-thumb {
|
|
6995
|
+
background: color-mix(in srgb, var(--ColorScrollBarSliderBackground, #4b5563) 70%, transparent);
|
|
6996
|
+
border: 2px solid color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 94%, transparent);
|
|
6997
|
+
border-radius: 999px;
|
|
6998
|
+
}
|
|
6999
|
+
|
|
7000
|
+
.Chat.ChatFocus .ProjectList::-webkit-scrollbar-thumb:hover {
|
|
7001
|
+
background: color-mix(in srgb, var(--ColorScrollBarSliderHoverBackground, #667284) 80%, transparent);
|
|
7002
|
+
}
|
|
7003
|
+
|
|
7004
|
+
.ProjectListGroup {
|
|
7005
|
+
border: 1px solid transparent;
|
|
7006
|
+
border-radius: 8px;
|
|
7007
|
+
margin-bottom: 6px;
|
|
7008
|
+
overflow: hidden;
|
|
7009
|
+
}
|
|
7010
|
+
|
|
7011
|
+
.ProjectListItem {
|
|
7012
|
+
align-items: center;
|
|
7013
|
+
display: flex;
|
|
7014
|
+
gap: 6px;
|
|
7015
|
+
min-height: calc(var(--ChatListItemHeight) - 2px);
|
|
7016
|
+
}
|
|
7017
|
+
|
|
7018
|
+
.ProjectListItemLabel {
|
|
7019
|
+
align-items: center;
|
|
7020
|
+
border-radius: 6px;
|
|
7021
|
+
color: var(--ColorForeground, #d5dbe3);
|
|
7022
|
+
cursor: pointer;
|
|
7023
|
+
display: flex;
|
|
7024
|
+
flex: 1;
|
|
7025
|
+
font-weight: 500;
|
|
7026
|
+
gap: 2px;
|
|
7027
|
+
overflow: hidden;
|
|
7028
|
+
padding: 0 10px;
|
|
7029
|
+
text-overflow: ellipsis;
|
|
7030
|
+
transition: background-color 80ms ease, color 80ms ease;
|
|
7031
|
+
white-space: nowrap;
|
|
7032
|
+
}
|
|
7033
|
+
|
|
7034
|
+
.ProjectListChevron {
|
|
7035
|
+
color: color-mix(in srgb, var(--ColorForeground, #c8d0da) 70%, transparent);
|
|
7036
|
+
display: inline-block;
|
|
7037
|
+
flex: 0 0 12px;
|
|
7038
|
+
font-size: 11px;
|
|
7039
|
+
margin-right: 4px;
|
|
7040
|
+
text-align: center;
|
|
7041
|
+
width: 12px;
|
|
7042
|
+
}
|
|
7043
|
+
|
|
7044
|
+
.ProjectListItemSelected {
|
|
7045
|
+
background: color-mix(in srgb, var(--ColorListInactiveSelectionBackground, #39424d) 84%, #2f3741 16%);
|
|
7046
|
+
}
|
|
7047
|
+
|
|
7048
|
+
.ProjectListItem:not(.ProjectListItemSelected) .ProjectListItemLabel:hover,
|
|
7049
|
+
.ProjectListItem:not(.ProjectListItemSelected) .ProjectListItemLabel:focus-visible {
|
|
7050
|
+
background: color-mix(in srgb, var(--ColorListHoverBackground, #38414b) 50%, transparent);
|
|
7051
|
+
}
|
|
7052
|
+
|
|
7053
|
+
.ProjectListItemSelected .ProjectListItemLabel {
|
|
7054
|
+
color: var(--ColorListInactiveSelectionForeground, #e5ebf2);
|
|
7055
|
+
}
|
|
7056
|
+
|
|
7057
|
+
.ProjectListItemActions {
|
|
7058
|
+
display: flex;
|
|
7059
|
+
padding-right: 6px;
|
|
7060
|
+
}
|
|
7061
|
+
|
|
7062
|
+
.ProjectListItemAddChatButton {
|
|
7063
|
+
align-items: center;
|
|
7064
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryBackground, #3a434f) 76%, transparent);
|
|
7065
|
+
border: 0;
|
|
7066
|
+
border-radius: 5px;
|
|
7067
|
+
color: var(--ColorForeground, #d0d8e2);
|
|
7068
|
+
cursor: pointer;
|
|
7069
|
+
display: inline-flex;
|
|
7070
|
+
font-size: 13px;
|
|
7071
|
+
font-weight: 500;
|
|
7072
|
+
height: 18px;
|
|
7073
|
+
justify-content: center;
|
|
7074
|
+
opacity: 0;
|
|
7075
|
+
padding: 0;
|
|
7076
|
+
transition: opacity 90ms ease, background-color 90ms ease;
|
|
7077
|
+
visibility: hidden;
|
|
7078
|
+
width: 18px;
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
.ProjectListItem:hover .ProjectListItemAddChatButton,
|
|
7082
|
+
.ProjectListItem:focus-within .ProjectListItemAddChatButton {
|
|
7083
|
+
opacity: 1;
|
|
7084
|
+
visibility: visible;
|
|
7085
|
+
}
|
|
7086
|
+
|
|
7087
|
+
.ProjectListItemAddChatButton:hover,
|
|
7088
|
+
.ProjectListItemAddChatButton:focus-visible {
|
|
7089
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryHoverBackground, #4a5460) 82%, transparent);
|
|
7090
|
+
}
|
|
7091
|
+
|
|
7092
|
+
.ProjectSessionItem {
|
|
7093
|
+
align-items: center;
|
|
7094
|
+
display: flex;
|
|
7095
|
+
min-height: calc(var(--ChatListItemHeight) - 5px);
|
|
7096
|
+
}
|
|
7097
|
+
|
|
7098
|
+
.ProjectSessionItemLabel {
|
|
7099
|
+
border-radius: 6px;
|
|
7100
|
+
color: color-mix(in srgb, var(--ColorForeground, #cfd7df) 92%, transparent);
|
|
7101
|
+
cursor: pointer;
|
|
7102
|
+
display: block;
|
|
7103
|
+
flex: 1;
|
|
7104
|
+
font-size: 12.5px;
|
|
7105
|
+
overflow: hidden;
|
|
7106
|
+
padding: 0 10px 0 28px;
|
|
7107
|
+
text-overflow: ellipsis;
|
|
7108
|
+
transition: background-color 80ms ease, color 80ms ease;
|
|
7109
|
+
white-space: nowrap;
|
|
7110
|
+
}
|
|
7111
|
+
|
|
7112
|
+
.ProjectSessionItemSelected {
|
|
7113
|
+
background: color-mix(in srgb, var(--ColorListInactiveSelectionBackground, #353f4a) 86%, #2c3540 14%);
|
|
7114
|
+
}
|
|
7115
|
+
|
|
7116
|
+
.ProjectSessionItem:not(.ProjectSessionItemSelected) .ProjectSessionItemLabel:hover,
|
|
7117
|
+
.ProjectSessionItem:not(.ProjectSessionItemSelected) .ProjectSessionItemLabel:focus-visible {
|
|
7118
|
+
background: color-mix(in srgb, var(--ColorListHoverBackground, #38414c) 46%, transparent);
|
|
7119
|
+
}
|
|
7120
|
+
|
|
7121
|
+
.ProjectSessionItemSelected .ProjectSessionItemLabel {
|
|
7122
|
+
color: var(--ColorListInactiveSelectionForeground, #f2f6fc);
|
|
7123
|
+
}
|
|
7124
|
+
|
|
7125
|
+
.Chat.ChatFocus .ProjectAddButton {
|
|
7126
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryBackground, #21252c) 72%, transparent);
|
|
7127
|
+
border: 0;
|
|
7128
|
+
border-top: 1px solid color-mix(in srgb, var(--ColorBorder, #3a3d41) 70%, transparent);
|
|
7129
|
+
color: var(--ColorForeground, #d2d9e2);
|
|
7130
|
+
cursor: pointer;
|
|
7131
|
+
font-size: 12.5px;
|
|
7132
|
+
letter-spacing: 0.01em;
|
|
7133
|
+
margin-top: auto;
|
|
7134
|
+
min-height: var(--ChatListItemHeight);
|
|
7135
|
+
padding: 0 12px;
|
|
7136
|
+
text-align: left;
|
|
7137
|
+
transition: background-color 80ms ease;
|
|
7138
|
+
}
|
|
7139
|
+
|
|
7140
|
+
.Chat.ChatFocus .ProjectAddButton:hover,
|
|
7141
|
+
.Chat.ChatFocus .ProjectAddButton:focus-visible {
|
|
7142
|
+
background: color-mix(in srgb, var(--ColorButtonSecondaryHoverBackground, #2a3039) 78%, transparent);
|
|
7143
|
+
}
|
|
7144
|
+
|
|
7145
|
+
.ChatList,
|
|
7146
|
+
.ChatListEmpty,
|
|
7147
|
+
.ChatMessages {
|
|
7148
|
+
min-height: 0;
|
|
7149
|
+
}
|
|
7150
|
+
|
|
7151
|
+
.Chat.ChatFocus .ChatList,
|
|
7152
|
+
.Chat.ChatFocus .ChatListEmpty {
|
|
7153
|
+
display: none;
|
|
7154
|
+
}
|
|
7155
|
+
|
|
7156
|
+
.Chat.ChatFocus .ChatMessages {
|
|
7157
|
+
grid-column: 2;
|
|
7158
|
+
grid-row: 2;
|
|
7159
|
+
}
|
|
7160
|
+
|
|
7161
|
+
.Chat.ChatFocus .ChatSendArea {
|
|
7162
|
+
grid-column: 2;
|
|
7163
|
+
grid-row: 3;
|
|
7164
|
+
}
|
|
6592
7165
|
`;
|
|
6593
7166
|
if (!renderHtmlCss.trim()) {
|
|
6594
7167
|
return baseCss;
|
|
@@ -6666,6 +7239,19 @@ const ChatList = 'ChatList';
|
|
|
6666
7239
|
const ChatListEmpty = 'ChatListEmpty';
|
|
6667
7240
|
const ChatListItem = 'ChatListItem';
|
|
6668
7241
|
const ChatListItemLabel = 'ChatListItemLabel';
|
|
7242
|
+
const ProjectAddButton = 'ProjectAddButton';
|
|
7243
|
+
const ProjectList = 'ProjectList';
|
|
7244
|
+
const ProjectListChevron = 'ProjectListChevron';
|
|
7245
|
+
const ProjectListGroup = 'ProjectListGroup';
|
|
7246
|
+
const ProjectListItem = 'ProjectListItem';
|
|
7247
|
+
const ProjectListItemActions = 'ProjectListItemActions';
|
|
7248
|
+
const ProjectListItemAddChatButton = 'ProjectListItemAddChatButton';
|
|
7249
|
+
const ProjectListItemLabel = 'ProjectListItemLabel';
|
|
7250
|
+
const ProjectListItemSelected = 'ProjectListItemSelected';
|
|
7251
|
+
const ProjectSessionItem = 'ProjectSessionItem';
|
|
7252
|
+
const ProjectSessionItemLabel = 'ProjectSessionItemLabel';
|
|
7253
|
+
const ProjectSessionItemSelected = 'ProjectSessionItemSelected';
|
|
7254
|
+
const ProjectSidebar = 'ProjectSidebar';
|
|
6669
7255
|
const Markdown = 'Markdown';
|
|
6670
7256
|
const MarkdownTable = 'MarkdownTable';
|
|
6671
7257
|
const Message = 'Message';
|
|
@@ -6716,6 +7302,7 @@ const HandleDragLeave = 28;
|
|
|
6716
7302
|
const HandleDrop = 29;
|
|
6717
7303
|
const HandleDragEnterChatView = 30;
|
|
6718
7304
|
const HandleDragOverChatView = 31;
|
|
7305
|
+
const HandleProjectListScroll = 32;
|
|
6719
7306
|
|
|
6720
7307
|
const getModelLabel = model => {
|
|
6721
7308
|
if (model.provider === 'openRouter') {
|
|
@@ -6832,82 +7419,6 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOvervie
|
|
|
6832
7419
|
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled)];
|
|
6833
7420
|
};
|
|
6834
7421
|
|
|
6835
|
-
const getBackButtonVirtualDom = () => {
|
|
6836
|
-
return [{
|
|
6837
|
-
childCount: 1,
|
|
6838
|
-
className: IconButton,
|
|
6839
|
-
name: Back,
|
|
6840
|
-
onClick: HandleClickBack,
|
|
6841
|
-
role: Button$2,
|
|
6842
|
-
title: backToChats(),
|
|
6843
|
-
type: Button$1
|
|
6844
|
-
}, {
|
|
6845
|
-
childCount: 0,
|
|
6846
|
-
className: 'MaskIcon MaskIconArrowLeft',
|
|
6847
|
-
type: Div
|
|
6848
|
-
}];
|
|
6849
|
-
};
|
|
6850
|
-
|
|
6851
|
-
const getHeaderActionVirtualDom = item => {
|
|
6852
|
-
return [{
|
|
6853
|
-
childCount: 1,
|
|
6854
|
-
className: IconButton,
|
|
6855
|
-
name: item.name,
|
|
6856
|
-
onClick: item.onClick,
|
|
6857
|
-
title: item.title,
|
|
6858
|
-
type: Button$1
|
|
6859
|
-
}, {
|
|
6860
|
-
childCount: 0,
|
|
6861
|
-
className: item.icon,
|
|
6862
|
-
type: Div
|
|
6863
|
-
}];
|
|
6864
|
-
};
|
|
6865
|
-
|
|
6866
|
-
const getChatHeaderActionsDom = () => {
|
|
6867
|
-
const items = [{
|
|
6868
|
-
icon: 'MaskIcon MaskIconDebugPause',
|
|
6869
|
-
name: SessionDebug,
|
|
6870
|
-
onClick: HandleClickSessionDebug,
|
|
6871
|
-
title: debug()
|
|
6872
|
-
}, {
|
|
6873
|
-
icon: 'MaskIcon MaskIconAdd',
|
|
6874
|
-
name: CreateSession,
|
|
6875
|
-
onClick: HandleClickNew,
|
|
6876
|
-
title: newChat()
|
|
6877
|
-
}, {
|
|
6878
|
-
icon: 'MaskIcon MaskIconSettingsGear',
|
|
6879
|
-
name: Settings,
|
|
6880
|
-
onClick: HandleClickSettings,
|
|
6881
|
-
title: settings()
|
|
6882
|
-
}, {
|
|
6883
|
-
icon: 'MaskIcon MaskIconClose',
|
|
6884
|
-
name: CloseChat,
|
|
6885
|
-
onClick: HandleClickClose,
|
|
6886
|
-
title: closeChat()
|
|
6887
|
-
}];
|
|
6888
|
-
return [{
|
|
6889
|
-
childCount: items.length,
|
|
6890
|
-
className: ChatActions,
|
|
6891
|
-
type: Div
|
|
6892
|
-
}, ...items.flatMap(getHeaderActionVirtualDom)];
|
|
6893
|
-
};
|
|
6894
|
-
|
|
6895
|
-
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
6896
|
-
return [{
|
|
6897
|
-
childCount: 2,
|
|
6898
|
-
className: ChatHeader,
|
|
6899
|
-
type: Div
|
|
6900
|
-
}, {
|
|
6901
|
-
childCount: 2,
|
|
6902
|
-
className: ChatName,
|
|
6903
|
-
type: Div
|
|
6904
|
-
}, ...getBackButtonVirtualDom(), {
|
|
6905
|
-
childCount: 1,
|
|
6906
|
-
className: Label,
|
|
6907
|
-
type: Span
|
|
6908
|
-
}, text(selectedSessionTitle), ...getChatHeaderActionsDom()];
|
|
6909
|
-
};
|
|
6910
|
-
|
|
6911
7422
|
const getInlineNodeDom = inlineNode => {
|
|
6912
7423
|
if (inlineNode.type === 'text') {
|
|
6913
7424
|
return [text(inlineNode.text)];
|
|
@@ -7447,8 +7958,12 @@ const getElementType = tagName => {
|
|
|
7447
7958
|
return inlineTags.has(tagName) ? Span : Div;
|
|
7448
7959
|
}
|
|
7449
7960
|
};
|
|
7961
|
+
const isHttpUrl$1 = url => {
|
|
7962
|
+
const normalized = url.trim().toLowerCase();
|
|
7963
|
+
return normalized.startsWith('http://') || normalized.startsWith('https://');
|
|
7964
|
+
};
|
|
7450
7965
|
const normalizeUrl = url => {
|
|
7451
|
-
return url
|
|
7966
|
+
return isHttpUrl$1(url) ? url : '#';
|
|
7452
7967
|
};
|
|
7453
7968
|
const getElementAttributes = node => {
|
|
7454
7969
|
const attributes = {};
|
|
@@ -7593,6 +8108,13 @@ const markdownInlineRegex = /\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*|\*([^*]+)\*
|
|
|
7593
8108
|
const markdownTableSeparatorCellRegex = /^:?-{3,}:?$/;
|
|
7594
8109
|
const fencedCodeBlockRegex = /^```/;
|
|
7595
8110
|
const markdownHeadingRegex = /^\s*(#{1,6})\s+(.*)$/;
|
|
8111
|
+
const isHttpUrl = url => {
|
|
8112
|
+
const normalized = url.trim().toLowerCase();
|
|
8113
|
+
return normalized.startsWith('http://') || normalized.startsWith('https://');
|
|
8114
|
+
};
|
|
8115
|
+
const sanitizeUrl = url => {
|
|
8116
|
+
return isHttpUrl(url) ? url : '#';
|
|
8117
|
+
};
|
|
7596
8118
|
const normalizeEscapedNewlines = value => {
|
|
7597
8119
|
if (value.includes('\\n')) {
|
|
7598
8120
|
return value.replaceAll(/\\r\\n|\\n/g, '\n');
|
|
@@ -7662,7 +8184,7 @@ const parseInlineNodes = value => {
|
|
|
7662
8184
|
}
|
|
7663
8185
|
if (linkText && href) {
|
|
7664
8186
|
nodes.push({
|
|
7665
|
-
href,
|
|
8187
|
+
href: sanitizeUrl(href),
|
|
7666
8188
|
text: linkText,
|
|
7667
8189
|
type: 'link'
|
|
7668
8190
|
});
|
|
@@ -7870,6 +8392,204 @@ const getMessagesDom = (messages, openRouterApiKeyInput, openApiApiKeyInput = ''
|
|
|
7870
8392
|
}, ...messages.flatMap(message => getChatMessageDom(message, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState))];
|
|
7871
8393
|
};
|
|
7872
8394
|
|
|
8395
|
+
const getProjectSessionDom = (session, selectedSessionId) => {
|
|
8396
|
+
const className = mergeClassNames(ProjectSessionItem, session.id === selectedSessionId ? ProjectSessionItemSelected : Empty);
|
|
8397
|
+
return [{
|
|
8398
|
+
childCount: 1,
|
|
8399
|
+
className,
|
|
8400
|
+
type: Div
|
|
8401
|
+
}, {
|
|
8402
|
+
childCount: 1,
|
|
8403
|
+
className: ProjectSessionItemLabel,
|
|
8404
|
+
name: getSessionInputName(session.id),
|
|
8405
|
+
onClick: HandleClick,
|
|
8406
|
+
tabIndex: 0,
|
|
8407
|
+
type: Div
|
|
8408
|
+
}, text(session.title)];
|
|
8409
|
+
};
|
|
8410
|
+
const getProjectGroupDom = (project, sessions, projectExpandedIds, selectedProjectId, selectedSessionId) => {
|
|
8411
|
+
const expanded = projectExpandedIds.includes(project.id);
|
|
8412
|
+
const projectClassName = mergeClassNames(ProjectListItem, project.id === selectedProjectId ? ProjectListItemSelected : Empty);
|
|
8413
|
+
return [{
|
|
8414
|
+
childCount: 1 + (expanded ? sessions.length : 0),
|
|
8415
|
+
className: ProjectListGroup,
|
|
8416
|
+
type: Div
|
|
8417
|
+
}, {
|
|
8418
|
+
childCount: 2,
|
|
8419
|
+
className: projectClassName,
|
|
8420
|
+
type: Div
|
|
8421
|
+
}, {
|
|
8422
|
+
childCount: 2,
|
|
8423
|
+
className: ProjectListItemLabel,
|
|
8424
|
+
name: getProjectInputName(project.id),
|
|
8425
|
+
onClick: HandleClick,
|
|
8426
|
+
tabIndex: 0,
|
|
8427
|
+
type: Div
|
|
8428
|
+
}, {
|
|
8429
|
+
childCount: 1,
|
|
8430
|
+
className: ProjectListChevron,
|
|
8431
|
+
type: Span
|
|
8432
|
+
}, text(expanded ? '▾' : '▸'), text(project.name), {
|
|
8433
|
+
childCount: 1,
|
|
8434
|
+
className: ProjectListItemActions,
|
|
8435
|
+
type: Div
|
|
8436
|
+
}, {
|
|
8437
|
+
childCount: 1,
|
|
8438
|
+
className: ProjectListItemAddChatButton,
|
|
8439
|
+
name: getCreateSessionInProjectInputName(project.id),
|
|
8440
|
+
onClick: HandleClick,
|
|
8441
|
+
tabIndex: 0,
|
|
8442
|
+
title: 'New chat in this project',
|
|
8443
|
+
type: Button$1
|
|
8444
|
+
}, text('+'), ...(expanded ? sessions.flatMap(session => getProjectSessionDom(session, selectedSessionId)) : [])];
|
|
8445
|
+
};
|
|
8446
|
+
const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop) => {
|
|
8447
|
+
const blankProjectId = projects.find(project => project.name === '_blank')?.id || projects[0]?.id || '';
|
|
8448
|
+
const projectGroups = projects.map(project => {
|
|
8449
|
+
const projectSessions = sessions.filter(session => {
|
|
8450
|
+
const sessionProjectId = session.projectId || blankProjectId;
|
|
8451
|
+
return sessionProjectId === project.id;
|
|
8452
|
+
});
|
|
8453
|
+
return getProjectGroupDom(project, projectSessions, projectExpandedIds, selectedProjectId, selectedSessionId);
|
|
8454
|
+
});
|
|
8455
|
+
return [{
|
|
8456
|
+
childCount: 2,
|
|
8457
|
+
className: ProjectSidebar,
|
|
8458
|
+
type: Div
|
|
8459
|
+
}, {
|
|
8460
|
+
childCount: projects.length,
|
|
8461
|
+
className: ProjectList,
|
|
8462
|
+
onScroll: HandleProjectListScroll,
|
|
8463
|
+
scrollTop: projectListScrollTop,
|
|
8464
|
+
type: Div
|
|
8465
|
+
}, ...projectGroups.flat(), {
|
|
8466
|
+
childCount: 1,
|
|
8467
|
+
className: ProjectAddButton,
|
|
8468
|
+
name: CreateProject,
|
|
8469
|
+
onClick: HandleClick,
|
|
8470
|
+
tabIndex: 0,
|
|
8471
|
+
type: Button$1
|
|
8472
|
+
}, text('+ Add Project')];
|
|
8473
|
+
};
|
|
8474
|
+
|
|
8475
|
+
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) => {
|
|
8476
|
+
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
8477
|
+
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
8478
|
+
const messages = selectedSession ? selectedSession.messages : [];
|
|
8479
|
+
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
8480
|
+
return [{
|
|
8481
|
+
childCount: 5,
|
|
8482
|
+
className: mergeClassNames(Viewlet, Chat, 'ChatFocus'),
|
|
8483
|
+
onDragEnter: HandleDragEnterChatView,
|
|
8484
|
+
onDragOver: HandleDragOverChatView,
|
|
8485
|
+
type: Div
|
|
8486
|
+
}, {
|
|
8487
|
+
childCount: 1,
|
|
8488
|
+
className: ChatHeader,
|
|
8489
|
+
type: Div
|
|
8490
|
+
}, {
|
|
8491
|
+
childCount: 1,
|
|
8492
|
+
className: Label,
|
|
8493
|
+
type: Span
|
|
8494
|
+
}, {
|
|
8495
|
+
text: selectedSessionTitle,
|
|
8496
|
+
type: Text
|
|
8497
|
+
}, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop), ...getMessagesDom(messages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight, composerFontSize, composerFontFamily, composerLineHeight), {
|
|
8498
|
+
childCount: 1,
|
|
8499
|
+
className: mergeClassNames(ChatViewDropOverlay, isDropOverlayVisible ? ChatViewDropOverlayActive : Empty),
|
|
8500
|
+
name: ComposerDropTarget,
|
|
8501
|
+
onDragLeave: HandleDragLeave,
|
|
8502
|
+
onDragOver: HandleDragOver,
|
|
8503
|
+
onDrop: HandleDrop,
|
|
8504
|
+
type: Div
|
|
8505
|
+
}, {
|
|
8506
|
+
text: attachImageAsContext(),
|
|
8507
|
+
type: Text
|
|
8508
|
+
}];
|
|
8509
|
+
};
|
|
8510
|
+
|
|
8511
|
+
const getBackButtonVirtualDom = () => {
|
|
8512
|
+
return [{
|
|
8513
|
+
childCount: 1,
|
|
8514
|
+
className: IconButton,
|
|
8515
|
+
name: Back,
|
|
8516
|
+
onClick: HandleClickBack,
|
|
8517
|
+
role: Button$2,
|
|
8518
|
+
title: backToChats(),
|
|
8519
|
+
type: Button$1
|
|
8520
|
+
}, {
|
|
8521
|
+
childCount: 0,
|
|
8522
|
+
className: 'MaskIcon MaskIconArrowLeft',
|
|
8523
|
+
type: Div
|
|
8524
|
+
}];
|
|
8525
|
+
};
|
|
8526
|
+
|
|
8527
|
+
const getHeaderActionVirtualDom = item => {
|
|
8528
|
+
return [{
|
|
8529
|
+
childCount: 1,
|
|
8530
|
+
className: IconButton,
|
|
8531
|
+
name: item.name,
|
|
8532
|
+
onClick: item.onClick,
|
|
8533
|
+
title: item.title,
|
|
8534
|
+
type: Button$1
|
|
8535
|
+
}, {
|
|
8536
|
+
childCount: 0,
|
|
8537
|
+
className: item.icon,
|
|
8538
|
+
type: Div
|
|
8539
|
+
}];
|
|
8540
|
+
};
|
|
8541
|
+
|
|
8542
|
+
const getChatHeaderActionsDom = viewMode => {
|
|
8543
|
+
const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
|
|
8544
|
+
const items = [{
|
|
8545
|
+
icon: 'MaskIcon MaskIconLayoutPanelLeft',
|
|
8546
|
+
name: ToggleChatFocus,
|
|
8547
|
+
onClick: HandleClick,
|
|
8548
|
+
title: toggleTitle
|
|
8549
|
+
}, {
|
|
8550
|
+
icon: 'MaskIcon MaskIconDebugPause',
|
|
8551
|
+
name: SessionDebug,
|
|
8552
|
+
onClick: HandleClickSessionDebug,
|
|
8553
|
+
title: debug()
|
|
8554
|
+
}, {
|
|
8555
|
+
icon: 'MaskIcon MaskIconAdd',
|
|
8556
|
+
name: CreateSession,
|
|
8557
|
+
onClick: HandleClickNew,
|
|
8558
|
+
title: newChat()
|
|
8559
|
+
}, {
|
|
8560
|
+
icon: 'MaskIcon MaskIconSettingsGear',
|
|
8561
|
+
name: Settings,
|
|
8562
|
+
onClick: HandleClickSettings,
|
|
8563
|
+
title: settings()
|
|
8564
|
+
}, {
|
|
8565
|
+
icon: 'MaskIcon MaskIconClose',
|
|
8566
|
+
name: CloseChat,
|
|
8567
|
+
onClick: HandleClickClose,
|
|
8568
|
+
title: closeChat()
|
|
8569
|
+
}];
|
|
8570
|
+
return [{
|
|
8571
|
+
childCount: items.length,
|
|
8572
|
+
className: ChatActions,
|
|
8573
|
+
type: Div
|
|
8574
|
+
}, ...items.flatMap(getHeaderActionVirtualDom)];
|
|
8575
|
+
};
|
|
8576
|
+
|
|
8577
|
+
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
8578
|
+
return [{
|
|
8579
|
+
childCount: 2,
|
|
8580
|
+
className: ChatHeader,
|
|
8581
|
+
type: Div
|
|
8582
|
+
}, {
|
|
8583
|
+
childCount: 2,
|
|
8584
|
+
className: ChatName,
|
|
8585
|
+
type: Div
|
|
8586
|
+
}, ...getBackButtonVirtualDom(), {
|
|
8587
|
+
childCount: 1,
|
|
8588
|
+
className: Label,
|
|
8589
|
+
type: Span
|
|
8590
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail')];
|
|
8591
|
+
};
|
|
8592
|
+
|
|
7873
8593
|
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) => {
|
|
7874
8594
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
7875
8595
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
@@ -7904,7 +8624,7 @@ const getChatHeaderListModeDom = () => {
|
|
|
7904
8624
|
childCount: 1,
|
|
7905
8625
|
className: Label,
|
|
7906
8626
|
type: Span
|
|
7907
|
-
}, text(chats()), ...getChatHeaderActionsDom()];
|
|
8627
|
+
}, text(chats()), ...getChatHeaderActionsDom('list')];
|
|
7908
8628
|
};
|
|
7909
8629
|
|
|
7910
8630
|
const getEmptyChatSessionsDom = () => {
|
|
@@ -7991,8 +8711,10 @@ const getChatModeUnsupportedVirtualDom = () => {
|
|
|
7991
8711
|
}, text(unknownViewMode())];
|
|
7992
8712
|
};
|
|
7993
8713
|
|
|
7994
|
-
const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive = false, composerDropEnabled = true) => {
|
|
8714
|
+
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) => {
|
|
7995
8715
|
switch (viewMode) {
|
|
8716
|
+
case 'chat-focus':
|
|
8717
|
+
return getChatModeChatFocusVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop);
|
|
7996
8718
|
case 'detail':
|
|
7997
8719
|
return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled);
|
|
7998
8720
|
case 'list':
|
|
@@ -8018,7 +8740,11 @@ const renderItems = (oldState, newState) => {
|
|
|
8018
8740
|
openApiApiKeyInput,
|
|
8019
8741
|
openRouterApiKeyInput,
|
|
8020
8742
|
openRouterApiKeyState,
|
|
8743
|
+
projectExpandedIds,
|
|
8744
|
+
projectListScrollTop,
|
|
8745
|
+
projects,
|
|
8021
8746
|
selectedModelId,
|
|
8747
|
+
selectedProjectId,
|
|
8022
8748
|
selectedSessionId,
|
|
8023
8749
|
sessions,
|
|
8024
8750
|
tokensMax,
|
|
@@ -8030,7 +8756,7 @@ const renderItems = (oldState, newState) => {
|
|
|
8030
8756
|
if (initial) {
|
|
8031
8757
|
return [SetDom2, uid, []];
|
|
8032
8758
|
}
|
|
8033
|
-
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive, composerDropEnabled);
|
|
8759
|
+
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);
|
|
8034
8760
|
return [SetDom2, uid, dom];
|
|
8035
8761
|
};
|
|
8036
8762
|
|
|
@@ -8167,6 +8893,9 @@ const renderEventListeners = () => {
|
|
|
8167
8893
|
}, {
|
|
8168
8894
|
name: HandleMessagesScroll,
|
|
8169
8895
|
params: ['handleMessagesScroll', 'event.target.scrollTop']
|
|
8896
|
+
}, {
|
|
8897
|
+
name: HandleProjectListScroll,
|
|
8898
|
+
params: ['handleProjectListScroll', 'event.target.scrollTop']
|
|
8170
8899
|
}, {
|
|
8171
8900
|
name: HandleMessagesContextMenu,
|
|
8172
8901
|
params: ['handleMessagesContextMenu'],
|
|
@@ -8214,20 +8943,30 @@ const saveState = state => {
|
|
|
8214
8943
|
const {
|
|
8215
8944
|
chatListScrollTop,
|
|
8216
8945
|
composerValue,
|
|
8946
|
+
lastNormalViewMode,
|
|
8217
8947
|
messagesScrollTop,
|
|
8218
8948
|
nextMessageId,
|
|
8949
|
+
projectExpandedIds,
|
|
8950
|
+
projectListScrollTop,
|
|
8951
|
+
projects,
|
|
8219
8952
|
renamingSessionId,
|
|
8220
8953
|
selectedModelId,
|
|
8954
|
+
selectedProjectId,
|
|
8221
8955
|
selectedSessionId,
|
|
8222
8956
|
viewMode
|
|
8223
8957
|
} = state;
|
|
8224
8958
|
return {
|
|
8225
8959
|
chatListScrollTop,
|
|
8226
8960
|
composerValue,
|
|
8961
|
+
lastNormalViewMode,
|
|
8227
8962
|
messagesScrollTop,
|
|
8228
8963
|
nextMessageId,
|
|
8964
|
+
projectExpandedIds,
|
|
8965
|
+
projectListScrollTop,
|
|
8966
|
+
projects,
|
|
8229
8967
|
renamingSessionId,
|
|
8230
8968
|
selectedModelId,
|
|
8969
|
+
selectedProjectId,
|
|
8231
8970
|
selectedSessionId,
|
|
8232
8971
|
viewMode
|
|
8233
8972
|
};
|
|
@@ -8326,6 +9065,7 @@ const commandMap = {
|
|
|
8326
9065
|
'Chat.handleMessagesContextMenu': wrapCommand(handleMessagesContextMenu),
|
|
8327
9066
|
'Chat.handleMessagesScroll': wrapCommand(handleMessagesScroll),
|
|
8328
9067
|
'Chat.handleModelChange': wrapCommand(handleModelChange),
|
|
9068
|
+
'Chat.handleProjectListScroll': wrapCommand(handleProjectListScroll),
|
|
8329
9069
|
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
8330
9070
|
'Chat.initialize': initialize,
|
|
8331
9071
|
'Chat.loadContent': wrapCommand(loadContent),
|