@lvce-editor/chat-view 6.21.0 → 6.23.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.
@@ -1197,9 +1197,7 @@ const Shift = 1 << 10 >>> 0;
1197
1197
 
1198
1198
  const Chat$1 = 97;
1199
1199
 
1200
- const Separator = 1;
1201
1200
  const None = 0;
1202
- const RestoreFocus = 6;
1203
1201
 
1204
1202
  const ChatNetworkWorker = 6002;
1205
1203
  const ChatToolWorker = 6005;
@@ -1407,6 +1405,104 @@ const terminate = () => {
1407
1405
  globalThis.close();
1408
1406
  };
1409
1407
 
1408
+ const getVisibleSessions = (sessions, selectedProjectId) => {
1409
+ if (!selectedProjectId) {
1410
+ return sessions;
1411
+ }
1412
+ const hasAssignedProjects = sessions.some(session => !!session.projectId);
1413
+ if (!hasAssignedProjects) {
1414
+ return sessions;
1415
+ }
1416
+ return sessions.filter(session => session.projectId === selectedProjectId);
1417
+ };
1418
+
1419
+ const chatListFocusFirst = async state => {
1420
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
1421
+ if (visibleSessions.length === 0) {
1422
+ return {
1423
+ ...state,
1424
+ focus: 'list',
1425
+ focused: true,
1426
+ listFocusedIndex: -1
1427
+ };
1428
+ }
1429
+ return {
1430
+ ...state,
1431
+ focus: 'list',
1432
+ focused: true,
1433
+ listFocusedIndex: 0
1434
+ };
1435
+ };
1436
+
1437
+ const chatListFocusLast = async state => {
1438
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
1439
+ if (visibleSessions.length === 0) {
1440
+ return {
1441
+ ...state,
1442
+ focus: 'list',
1443
+ focused: true,
1444
+ listFocusedIndex: -1
1445
+ };
1446
+ }
1447
+ return {
1448
+ ...state,
1449
+ focus: 'list',
1450
+ focused: true,
1451
+ listFocusedIndex: visibleSessions.length - 1
1452
+ };
1453
+ };
1454
+
1455
+ const getListFocusIndex = state => {
1456
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
1457
+ if (visibleSessions.length === 0) {
1458
+ return -1;
1459
+ }
1460
+ if (state.listFocusedIndex >= 0 && state.listFocusedIndex < visibleSessions.length) {
1461
+ return state.listFocusedIndex;
1462
+ }
1463
+ return -1;
1464
+ };
1465
+
1466
+ const chatListFocusNext = async state => {
1467
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
1468
+ if (visibleSessions.length === 0) {
1469
+ return {
1470
+ ...state,
1471
+ focus: 'list',
1472
+ focused: true,
1473
+ listFocusedIndex: -1
1474
+ };
1475
+ }
1476
+ const currentIndex = getListFocusIndex(state);
1477
+ const nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, visibleSessions.length - 1);
1478
+ return {
1479
+ ...state,
1480
+ focus: 'list',
1481
+ focused: true,
1482
+ listFocusedIndex: nextIndex
1483
+ };
1484
+ };
1485
+
1486
+ const chatListFocusPrevious = async state => {
1487
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
1488
+ if (visibleSessions.length === 0) {
1489
+ return {
1490
+ ...state,
1491
+ focus: 'list',
1492
+ focused: true,
1493
+ listFocusedIndex: -1
1494
+ };
1495
+ }
1496
+ const currentIndex = getListFocusIndex(state);
1497
+ const previousIndex = currentIndex === -1 ? visibleSessions.length - 1 : Math.max(currentIndex - 1, 0);
1498
+ return {
1499
+ ...state,
1500
+ focus: 'list',
1501
+ focused: true,
1502
+ listFocusedIndex: previousIndex
1503
+ };
1504
+ };
1505
+
1410
1506
  const measureTextBlockHeight = async (text, fontFamily, fontSize, lineHeight, width) => {
1411
1507
  // Upstream renderer types currently require number, but runtime accepts px strings.
1412
1508
  // Keep forwarding the string to preserve chat-view behavior until upstream is updated.
@@ -1495,12 +1591,18 @@ const chats = () => {
1495
1591
  const newChat = () => {
1496
1592
  return i18nString('New Chat');
1497
1593
  };
1594
+ const addProject$1 = () => {
1595
+ return i18nString('Add Project');
1596
+ };
1498
1597
  const debug = () => {
1499
1598
  return i18nString('Debug');
1500
1599
  };
1501
1600
  const backToChats = () => {
1502
1601
  return i18nString('Back to chats');
1503
1602
  };
1603
+ const backToChatList = () => {
1604
+ return i18nString('Back to chat list');
1605
+ };
1504
1606
  const settings = () => {
1505
1607
  return i18nString('Settings');
1506
1608
  };
@@ -1714,6 +1816,7 @@ const createDefaultState = () => {
1714
1816
  inputSource: 'script',
1715
1817
  lastNormalViewMode: 'list',
1716
1818
  lastSubmittedSessionId: '',
1819
+ listFocusedIndex: -1,
1717
1820
  listItemHeight: 40,
1718
1821
  maxComposerRows: 5,
1719
1822
  messagesAutoScrollEnabled: true,
@@ -2485,17 +2588,6 @@ const getNextSelectedSessionId = (sessions, deletedId) => {
2485
2588
  return sessions[nextIndex].id;
2486
2589
  };
2487
2590
 
2488
- const getVisibleSessions = (sessions, selectedProjectId) => {
2489
- if (!selectedProjectId) {
2490
- return sessions;
2491
- }
2492
- const hasAssignedProjects = sessions.some(session => !!session.projectId);
2493
- if (!hasAssignedProjects) {
2494
- return sessions;
2495
- }
2496
- return sessions.filter(session => session.projectId === selectedProjectId);
2497
- };
2498
-
2499
2591
  const deleteSession = async (state, id) => {
2500
2592
  const {
2501
2593
  renamingSessionId,
@@ -2613,7 +2705,7 @@ const isEqualProjectExpandedIds = (a, b) => {
2613
2705
  return true;
2614
2706
  };
2615
2707
  const isEqual = (oldState, newState) => {
2616
- return oldState.addContextButtonEnabled === newState.addContextButtonEnabled && oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage && oldState.authStatus === newState.authStatus && oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.modelPickerOpen === newState.modelPickerOpen && oldState.modelPickerSearchValue === newState.modelPickerSearchValue && oldState.newChatModelPickerEnabled === newState.newChatModelPickerEnabled && 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.showRunMode === newState.showRunMode && oldState.runMode === newState.runMode && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
2708
+ return oldState.addContextButtonEnabled === newState.addContextButtonEnabled && oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage && oldState.authStatus === newState.authStatus && oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.modelPickerOpen === newState.modelPickerOpen && oldState.modelPickerSearchValue === newState.modelPickerSearchValue && oldState.newChatModelPickerEnabled === newState.newChatModelPickerEnabled && oldState.listFocusedIndex === newState.listFocusedIndex && 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.showRunMode === newState.showRunMode && oldState.runMode === newState.runMode && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
2617
2709
  };
2618
2710
 
2619
2711
  const diffScrollTop = (oldState, newState) => {
@@ -2985,22 +3077,12 @@ const getKeyBindings = () => {
2985
3077
  };
2986
3078
 
2987
3079
  const Copy = 'Copy';
2988
- const CopyPath = 'Copy Path';
2989
- const CopyRelativePath = 'Copy Relative Path';
2990
3080
  const Cut = 'Cut';
2991
- const Delete = 'Delete';
2992
- const OpenContainingFolder = 'Open Containing Folder';
2993
- const OpenInIntegratedTerminal = 'Open in integrated Terminal';
2994
3081
  const Paste = 'Paste';
2995
3082
  const Rename = 'Rename';
2996
3083
  const Archive = 'Archive';
3084
+ const AddProject = 'Add Project...';
2997
3085
 
2998
- const openContainingFolder = () => {
2999
- return i18nString(OpenContainingFolder);
3000
- };
3001
- const openInIntegratedTerminal = () => {
3002
- return i18nString(OpenInIntegratedTerminal);
3003
- };
3004
3086
  const cut = () => {
3005
3087
  return i18nString(Cut);
3006
3088
  };
@@ -3010,117 +3092,195 @@ const copy = () => {
3010
3092
  const paste = () => {
3011
3093
  return i18nString(Paste);
3012
3094
  };
3013
- const copyPath = () => {
3014
- return i18nString(CopyPath);
3015
- };
3016
- const copyRelativePath = () => {
3017
- return i18nString(CopyRelativePath);
3018
- };
3019
3095
  const rename = () => {
3020
3096
  return i18nString(Rename);
3021
3097
  };
3022
3098
  const archive = () => {
3023
3099
  return i18nString(Archive);
3024
3100
  };
3025
- const deleteItem = () => {
3026
- return i18nString(Delete);
3101
+ const addProject = () => {
3102
+ return i18nString(AddProject);
3103
+ };
3104
+
3105
+ const getMenuEntriesChatHeader = () => {
3106
+ // TODO
3107
+ return [{
3108
+ command: 'Chat.handleInputCut',
3109
+ flags: None,
3110
+ id: 'cut',
3111
+ label: cut()
3112
+ }, {
3113
+ command: 'Chat.handleInputCopy',
3114
+ flags: None,
3115
+ id: 'copy',
3116
+ label: copy()
3117
+ }, {
3118
+ command: 'Chat.handleInputPaste',
3119
+ flags: None,
3120
+ id: 'copy',
3121
+ label: paste()
3122
+ }];
3123
+ };
3124
+
3125
+ const getMenuEntriesChatInput = () => {
3126
+ return [{
3127
+ command: 'Chat.handleInputCut',
3128
+ flags: None,
3129
+ id: 'cut',
3130
+ label: cut()
3131
+ }, {
3132
+ command: 'Chat.handleInputCopy',
3133
+ flags: None,
3134
+ id: 'copy',
3135
+ label: copy()
3136
+ }, {
3137
+ command: 'Chat.handleInputPaste',
3138
+ flags: None,
3139
+ id: 'copy',
3140
+ label: paste()
3141
+ }];
3027
3142
  };
3028
3143
 
3029
- const getMenuEntriesChatList = () => {
3144
+ const getMenuEntriesChatList = (sessionId = '') => {
3030
3145
  return [{
3146
+ args: [sessionId],
3031
3147
  command: 'Chat.handleClickRename',
3032
3148
  flags: None,
3033
3149
  id: 'rename',
3034
3150
  label: rename()
3035
3151
  }, {
3036
- command: 'Chat.handleClickArchive',
3152
+ args: [sessionId],
3153
+ command: 'Chat.handleClickDelete',
3037
3154
  flags: None,
3038
3155
  id: 'archive',
3039
3156
  label: archive()
3040
3157
  }];
3041
3158
  };
3042
3159
 
3043
- const MenuChatList = 2178;
3044
- const getMenuEntryIds = () => {
3045
- return [Chat$1, MenuChatList];
3160
+ const Composer = 'composer';
3161
+ const Search = 'search';
3162
+ const ComposerDropTarget = 'composer-drop-target';
3163
+ const AddContext = 'add-context';
3164
+ const Dictate = 'dictate';
3165
+ const Send = 'send';
3166
+ const Back = 'back';
3167
+ const Model = 'model';
3168
+ const ModelPickerToggle = 'model-picker-toggle';
3169
+ const ModelPickerSearch = 'model-picker-search';
3170
+ const ModelPickerSettings = 'model-picker-settings';
3171
+ const RunMode = 'runMode';
3172
+ const ToggleChatFocus = 'toggle-chat-focus';
3173
+ const ToggleSearch = 'toggle-search';
3174
+ const ChatList$1 = 'chat-list';
3175
+ const CreateProject = 'create-project';
3176
+ const CreateSession = 'create-session';
3177
+ const CreateSessionInProjectPrefix = 'create-session-in-project:';
3178
+ const SessionDebug = 'session-debug';
3179
+ const Settings = 'settings';
3180
+ const Login = 'login';
3181
+ const Logout = 'logout';
3182
+ const CloseChat = 'close-chat';
3183
+ const SessionDelete = 'SessionDelete';
3184
+ const ProjectPrefix = 'project:';
3185
+ const SessionPrefix = 'session:';
3186
+ const RenamePrefix = 'session-rename:';
3187
+ const ModelPickerItemPrefix = 'model-picker-item:';
3188
+ const getProjectInputName = projectId => {
3189
+ return `${ProjectPrefix}${projectId}`;
3046
3190
  };
3047
-
3048
- const menuEntrySeparator = {
3049
- command: '',
3050
- flags: Separator,
3051
- id: 'separator',
3052
- label: ''
3191
+ const getCreateSessionInProjectInputName = projectId => {
3192
+ return `${CreateSessionInProjectPrefix}${projectId}`;
3053
3193
  };
3054
-
3055
- const menuEntryOpenContainingFolder = {
3056
- command: 'Explorer.openContainingFolder',
3057
- flags: RestoreFocus,
3058
- id: 'openContainingFolder',
3059
- label: openContainingFolder()
3194
+ const isCreateSessionInProjectInputName = name => {
3195
+ return name.startsWith(CreateSessionInProjectPrefix);
3060
3196
  };
3061
- const menuEntryOpenInIntegratedTerminal = {
3062
- command: /* TODO */'-1',
3063
- flags: None,
3064
- id: 'openInIntegratedTerminal',
3065
- label: openInIntegratedTerminal()
3066
- };
3067
- const menuEntryCut = {
3068
- command: 'Explorer.handleCut',
3069
- flags: RestoreFocus,
3070
- id: 'cut',
3071
- label: cut()
3072
- };
3073
- const menuEntryCopy = {
3074
- command: 'Explorer.handleCopy',
3075
- flags: RestoreFocus,
3076
- id: 'copy',
3077
- label: copy()
3078
- };
3079
- const menuEntryPaste = {
3080
- command: 'Explorer.handlePaste',
3081
- flags: None,
3082
- id: 'paste',
3083
- label: paste()
3197
+ const getProjectIdFromCreateSessionInProjectInputName = name => {
3198
+ return name.slice(CreateSessionInProjectPrefix.length);
3084
3199
  };
3085
- const menuEntryCopyPath = {
3086
- command: 'Explorer.copyPath',
3087
- flags: RestoreFocus,
3088
- id: 'copyPath',
3089
- label: copyPath()
3200
+ const isProjectInputName = name => {
3201
+ return name.startsWith(ProjectPrefix);
3090
3202
  };
3091
- const menuEntryCopyAsE2eTest = {
3092
- command: 'Chat.copyAsE2eTest',
3093
- flags: None,
3094
- id: 'copyAsE2eTest',
3095
- label: copyPath()
3203
+ const getProjectIdFromInputName = name => {
3204
+ return name.slice(ProjectPrefix.length);
3096
3205
  };
3097
- const menuEntryCopyRelativePath = {
3098
- command: 'Explorer.copyRelativePath',
3099
- flags: RestoreFocus,
3100
- id: 'copyRelativePath',
3101
- label: copyRelativePath()
3206
+ const getSessionInputName = sessionId => {
3207
+ return `${SessionPrefix}${sessionId}`;
3102
3208
  };
3103
- const menuEntryRename = {
3104
- command: 'Explorer.renameDirent',
3105
- flags: None,
3106
- id: 'rename',
3107
- label: rename()
3209
+ const isSessionInputName = name => {
3210
+ return name.startsWith(SessionPrefix);
3211
+ };
3212
+ const getSessionIdFromInputName = name => {
3213
+ return name.slice(SessionPrefix.length);
3214
+ };
3215
+ const isRenameInputName = name => {
3216
+ return name.startsWith(RenamePrefix);
3217
+ };
3218
+ const getRenameIdFromInputName = name => {
3219
+ return name.slice(RenamePrefix.length);
3220
+ };
3221
+ const getModelPickerItemInputName = modelId => {
3222
+ return `${ModelPickerItemPrefix}${modelId}`;
3223
+ };
3224
+ const isModelPickerItemInputName = name => {
3225
+ return name.startsWith(ModelPickerItemPrefix);
3226
+ };
3227
+ const getModelIdFromModelPickerItemInputName = name => {
3228
+ return name.slice(ModelPickerItemPrefix.length);
3108
3229
  };
3109
- const menuEntryDelete = {
3110
- command: 'Explorer.removeDirent',
3230
+
3231
+ const menuEntryAddProject = {
3232
+ args: [CreateProject],
3233
+ command: 'Chat.handleClick',
3111
3234
  flags: None,
3112
- id: 'delete',
3113
- label: deleteItem()
3235
+ id: 'addProject',
3236
+ label: addProject$1()
3114
3237
  };
3115
- const getMenuEntriesFile = () => {
3116
- return [menuEntryCopyAsE2eTest, menuEntryOpenContainingFolder, menuEntryOpenInIntegratedTerminal, menuEntrySeparator, menuEntryCut, menuEntryCopy, menuEntryPaste, menuEntrySeparator, menuEntryCopyPath, menuEntryCopyRelativePath, menuEntrySeparator, menuEntryRename, menuEntryDelete];
3238
+ const getMenuEntriesChatProjectList = (projectId = '') => {
3239
+ if (!projectId) {
3240
+ return [menuEntryAddProject];
3241
+ }
3242
+ return [{
3243
+ args: [getCreateSessionInProjectInputName(projectId)],
3244
+ command: 'Chat.handleClick',
3245
+ flags: None,
3246
+ id: 'newChat',
3247
+ label: newChat()
3248
+ }, menuEntryAddProject];
3117
3249
  };
3118
- const getMenuEntries = menuId => {
3119
- switch (menuId) {
3250
+
3251
+ const getMenuEntriesProjectAddButton = () => {
3252
+ return [{
3253
+ args: [CreateProject],
3254
+ command: 'Chat.handleClick',
3255
+ flags: None,
3256
+ id: 'addProject',
3257
+ label: addProject()
3258
+ }];
3259
+ };
3260
+
3261
+ const MenuChatList = 2178;
3262
+ const MenuChatHeader = 2179;
3263
+ const MenuChatInput = 2180;
3264
+ const MenuProjectAddButton = 2181;
3265
+ const MenuChatProjectList = 2182;
3266
+ const getMenuEntryIds = () => {
3267
+ return [Chat$1, MenuChatList, MenuChatHeader, MenuChatInput, MenuProjectAddButton, MenuChatProjectList];
3268
+ };
3269
+
3270
+ const getMenuEntries = (menuId, props) => {
3271
+ switch (props.menuId) {
3272
+ case MenuChatHeader:
3273
+ return getMenuEntriesChatHeader();
3274
+ case MenuChatInput:
3275
+ return getMenuEntriesChatInput();
3120
3276
  case MenuChatList:
3121
3277
  return getMenuEntriesChatList();
3278
+ case MenuChatProjectList:
3279
+ return getMenuEntriesChatProjectList(props.projectId);
3280
+ case MenuProjectAddButton:
3281
+ return getMenuEntriesProjectAddButton();
3122
3282
  default:
3123
- return getMenuEntriesFile();
3283
+ return [];
3124
3284
  }
3125
3285
  };
3126
3286
 
@@ -3132,11 +3292,21 @@ const getSelectedSessionId = state => {
3132
3292
  return state.selectedSessionId;
3133
3293
  };
3134
3294
 
3295
+ const handleChatDetailWelcomeContextMenu = async state => {
3296
+ return state;
3297
+ };
3298
+
3135
3299
  const handleChatHeaderContextMenu = async state => {
3136
3300
  return state;
3137
3301
  };
3138
3302
 
3139
- const handleChatInputContextMenu = async state => {
3303
+ const handleChatInputContextMenu = async (state, eventX, eventY) => {
3304
+ const {
3305
+ uid
3306
+ } = state;
3307
+ await showContextMenu2(uid, MenuChatInput, eventX, eventY, {
3308
+ menuId: MenuChatInput
3309
+ });
3140
3310
  return state;
3141
3311
  };
3142
3312
 
@@ -3172,15 +3342,16 @@ const handleChatListContextMenu = async (state, eventX, eventY) => {
3172
3342
  if (!item) {
3173
3343
  return state;
3174
3344
  }
3175
- await showContextMenu2(uid, -1, eventX, eventY, {
3176
- menuId: -1,
3345
+ await showContextMenu2(uid, MenuChatList, eventX, eventY, {
3346
+ menuId: MenuChatList,
3177
3347
  sessionId: item.id
3178
3348
  });
3179
- return state;
3180
- };
3181
-
3182
- const handleChatWelcomeContextMenu = async state => {
3183
- return state;
3349
+ return {
3350
+ ...state,
3351
+ focus: 'list',
3352
+ focused: true,
3353
+ listFocusedIndex: index
3354
+ };
3184
3355
  };
3185
3356
 
3186
3357
  const generateSessionId = () => {
@@ -7051,7 +7222,8 @@ const focusInput = state => {
7051
7222
  return {
7052
7223
  ...state,
7053
7224
  focus: 'composer',
7054
- focused: true
7225
+ focused: true,
7226
+ listFocusedIndex: -1
7055
7227
  };
7056
7228
  };
7057
7229
 
@@ -7776,76 +7948,6 @@ const handleClickSend = async state => {
7776
7948
  return handleSubmit(submitState);
7777
7949
  };
7778
7950
 
7779
- const Composer = 'composer';
7780
- const Search = 'search';
7781
- const ComposerDropTarget = 'composer-drop-target';
7782
- const AddContext = 'add-context';
7783
- const Dictate = 'dictate';
7784
- const Send = 'send';
7785
- const Back = 'back';
7786
- const Model = 'model';
7787
- const ModelPickerToggle = 'model-picker-toggle';
7788
- const ModelPickerSearch = 'model-picker-search';
7789
- const ModelPickerSettings = 'model-picker-settings';
7790
- const RunMode = 'runMode';
7791
- const ToggleChatFocus = 'toggle-chat-focus';
7792
- const ToggleSearch = 'toggle-search';
7793
- const CreateProject = 'create-project';
7794
- const CreateSession = 'create-session';
7795
- const CreateSessionInProjectPrefix = 'create-session-in-project:';
7796
- const SessionDebug = 'session-debug';
7797
- const Settings = 'settings';
7798
- const Login = 'login';
7799
- const Logout = 'logout';
7800
- const CloseChat = 'close-chat';
7801
- const SessionDelete = 'SessionDelete';
7802
- const ProjectPrefix = 'project:';
7803
- const SessionPrefix = 'session:';
7804
- const RenamePrefix = 'session-rename:';
7805
- const ModelPickerItemPrefix = 'model-picker-item:';
7806
- const getProjectInputName = projectId => {
7807
- return `${ProjectPrefix}${projectId}`;
7808
- };
7809
- const getCreateSessionInProjectInputName = projectId => {
7810
- return `${CreateSessionInProjectPrefix}${projectId}`;
7811
- };
7812
- const isCreateSessionInProjectInputName = name => {
7813
- return name.startsWith(CreateSessionInProjectPrefix);
7814
- };
7815
- const getProjectIdFromCreateSessionInProjectInputName = name => {
7816
- return name.slice(CreateSessionInProjectPrefix.length);
7817
- };
7818
- const isProjectInputName = name => {
7819
- return name.startsWith(ProjectPrefix);
7820
- };
7821
- const getProjectIdFromInputName = name => {
7822
- return name.slice(ProjectPrefix.length);
7823
- };
7824
- const getSessionInputName = sessionId => {
7825
- return `${SessionPrefix}${sessionId}`;
7826
- };
7827
- const isSessionInputName = name => {
7828
- return name.startsWith(SessionPrefix);
7829
- };
7830
- const getSessionIdFromInputName = name => {
7831
- return name.slice(SessionPrefix.length);
7832
- };
7833
- const isRenameInputName = name => {
7834
- return name.startsWith(RenamePrefix);
7835
- };
7836
- const getRenameIdFromInputName = name => {
7837
- return name.slice(RenamePrefix.length);
7838
- };
7839
- const getModelPickerItemInputName = modelId => {
7840
- return `${ModelPickerItemPrefix}${modelId}`;
7841
- };
7842
- const isModelPickerItemInputName = name => {
7843
- return name.startsWith(ModelPickerItemPrefix);
7844
- };
7845
- const getModelIdFromModelPickerItemInputName = name => {
7846
- return name.slice(ModelPickerItemPrefix.length);
7847
- };
7848
-
7849
7951
  const OpenApiApiKeyInput = 'open-api-api-key';
7850
7952
  const SaveOpenApiApiKey = 'save-openapi-api-key';
7851
7953
  const OpenOpenApiApiKeySettings = 'open-openapi-api-key-settings';
@@ -7954,11 +8056,34 @@ const selectListIndex = async (state, index) => {
7954
8056
  return state;
7955
8057
  }
7956
8058
  const session = visibleSessions[index];
7957
- return selectSession(state, session.id);
8059
+ const nextState = await selectSession(state, session.id);
8060
+ return {
8061
+ ...nextState,
8062
+ focus: 'list',
8063
+ focused: true,
8064
+ listFocusedIndex: index
8065
+ };
7958
8066
  };
7959
8067
 
7960
8068
  const handleClickList = async (state, eventX, eventY) => {
7961
8069
  const index = getListIndex(state, eventX, eventY);
8070
+ if (index === -1) {
8071
+ return {
8072
+ ...state,
8073
+ focus: 'list',
8074
+ focused: true,
8075
+ listFocusedIndex: -1
8076
+ };
8077
+ }
8078
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
8079
+ if (index >= visibleSessions.length) {
8080
+ return {
8081
+ ...state,
8082
+ focus: 'list',
8083
+ focused: true,
8084
+ listFocusedIndex: -1
8085
+ };
8086
+ }
7962
8087
  return selectListIndex(state, index);
7963
8088
  };
7964
8089
 
@@ -8241,21 +8366,37 @@ const handleInputFocus = async (state, name) => {
8241
8366
  return {
8242
8367
  ...state,
8243
8368
  focus: 'send-button',
8244
- focused: true
8369
+ focused: true,
8370
+ listFocusedIndex: -1
8371
+ };
8372
+ }
8373
+ if (name === ChatList$1) {
8374
+ return {
8375
+ ...state,
8376
+ focus: 'list',
8377
+ focused: true,
8378
+ listFocusedIndex: -1
8245
8379
  };
8246
8380
  }
8247
8381
  if (isSessionInputName(name) || name === SessionDelete) {
8382
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
8383
+ const sessionId = isSessionInputName(name) ? getSessionIdFromInputName(name) : '';
8384
+ const focusedIndex = sessionId === '' ? -1 : visibleSessions.findIndex(session => {
8385
+ return session.id === sessionId;
8386
+ });
8248
8387
  return {
8249
8388
  ...state,
8250
8389
  focus: 'list',
8251
- focused: true
8390
+ focused: true,
8391
+ listFocusedIndex: focusedIndex
8252
8392
  };
8253
8393
  }
8254
8394
  if (name === CreateSession || name === SessionDebug || name === Settings || name === CloseChat || name === Back) {
8255
8395
  return {
8256
8396
  ...state,
8257
8397
  focus: 'header',
8258
- focused: true
8398
+ focused: true,
8399
+ listFocusedIndex: -1
8259
8400
  };
8260
8401
  }
8261
8402
  return {
@@ -8308,6 +8449,18 @@ const handleKeyDown = async (state, key, shiftKey) => {
8308
8449
  sessions,
8309
8450
  viewMode
8310
8451
  } = state;
8452
+ if (state.focus === 'list' && viewMode === 'list') {
8453
+ switch (key) {
8454
+ case 'ArrowDown':
8455
+ return chatListFocusNext(state);
8456
+ case 'ArrowUp':
8457
+ return chatListFocusPrevious(state);
8458
+ case 'End':
8459
+ return chatListFocusLast(state);
8460
+ case 'Home':
8461
+ return chatListFocusFirst(state);
8462
+ }
8463
+ }
8311
8464
  if (key !== 'Enter' || shiftKey) {
8312
8465
  return state;
8313
8466
  }
@@ -8356,7 +8509,63 @@ const handleNewline = async state => {
8356
8509
  return handleInput(state, Composer, `${composerValue}\n`);
8357
8510
  };
8358
8511
 
8359
- const handleProjectListContextMenu = async state => {
8512
+ const handleProjectAddButtonContextMenu = async (state, button, x, y) => {
8513
+ const {
8514
+ uid
8515
+ } = state;
8516
+ await showContextMenu2(uid, MenuProjectAddButton, x, y, {
8517
+ menuId: MenuProjectAddButton
8518
+ });
8519
+ return state;
8520
+ };
8521
+
8522
+ const getProjectIdAtIndex = (state, index) => {
8523
+ const {
8524
+ projectExpandedIds,
8525
+ projects,
8526
+ sessions
8527
+ } = state;
8528
+ const blankProjectId = projects.find(project => project.name === '_blank')?.id || projects[0]?.id || '';
8529
+ let currentIndex = 0;
8530
+ for (const project of projects) {
8531
+ if (currentIndex === index) {
8532
+ return project.id;
8533
+ }
8534
+ currentIndex++;
8535
+ if (projectExpandedIds.includes(project.id)) {
8536
+ for (const session of sessions) {
8537
+ const sessionProjectId = session.projectId || blankProjectId;
8538
+ if (sessionProjectId !== project.id) {
8539
+ continue;
8540
+ }
8541
+ if (currentIndex === index) {
8542
+ return project.id;
8543
+ }
8544
+ currentIndex++;
8545
+ }
8546
+ }
8547
+ }
8548
+ return '';
8549
+ };
8550
+ const handleProjectListContextMenu = async (state, button, x, y) => {
8551
+ const {
8552
+ headerHeight,
8553
+ listItemHeight,
8554
+ projectListScrollTop,
8555
+ uid
8556
+ } = state;
8557
+ const index = Math.floor((y - headerHeight + projectListScrollTop) / listItemHeight);
8558
+ if (index < 0) {
8559
+ return state;
8560
+ }
8561
+ const projectId = getProjectIdAtIndex(state, index);
8562
+ if (!projectId) {
8563
+ return state;
8564
+ }
8565
+ await showContextMenu2(uid, MenuChatProjectList, x, y, {
8566
+ menuId: MenuChatProjectList,
8567
+ projectId
8568
+ });
8360
8569
  return state;
8361
8570
  };
8362
8571
 
@@ -9103,15 +9312,39 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
9103
9312
  border-color: darkcyan;
9104
9313
  }
9105
9314
 
9315
+ .ChatModelPicker{
9316
+ border: 1px solid white;
9317
+ }
9318
+
9106
9319
  .ChatListItem{
9107
9320
  display:flex;
9108
9321
  align-items:center;
9322
+ box-shadow: inset 0 0 0 1px transparent;
9323
+ }
9324
+
9325
+ .ChatListItemFocused{
9326
+ background: var(--vscode-list-activeSelectionBackground);
9327
+ box-shadow: inset 0 0 0 1px var(--vscode-focusBorder);
9328
+ color: var(--vscode-list-activeSelectionForeground);
9109
9329
  }
9110
9330
 
9111
9331
  .ChatMessageContent p + p{
9112
9332
  margin-top: 0.75em;
9113
9333
  }
9114
9334
 
9335
+ .MissingApiKeyForm{
9336
+ padding-top: 10px;
9337
+ }
9338
+
9339
+ a.Button{
9340
+ text-decoration: none;
9341
+ }
9342
+
9343
+ .ChatHeaderLabel{
9344
+ margin: 0;
9345
+ font-size: 14px;
9346
+ }
9347
+
9115
9348
  .ChatListItemStatusRow{
9116
9349
  width: 16px;
9117
9350
  min-width: 16px;
@@ -9134,6 +9367,8 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
9134
9367
 
9135
9368
  .ChatListItemStatusFinished{
9136
9369
  color: var(--vscode-testing-iconPassed);
9370
+ }
9371
+
9137
9372
  .ChatListItem .SessionArchiveButton{
9138
9373
  opacity: 0;
9139
9374
  }
@@ -9142,6 +9377,13 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
9142
9377
  .ChatListItem:focus-within .SessionArchiveButton{
9143
9378
  opacity: 1;
9144
9379
  }
9380
+
9381
+ .ChatHeaderLabel{
9382
+ white-space: nowrap;
9383
+ overflow: hidden;
9384
+ text-overflow: ellipsis;
9385
+ }
9386
+
9145
9387
  `;
9146
9388
  return `${baseCss}
9147
9389
 
@@ -9176,7 +9418,11 @@ const renderCss = (oldState, newState) => {
9176
9418
  return [SetCss, uid, css];
9177
9419
  };
9178
9420
 
9179
- const getFocusSelector = focus => {
9421
+ const getFocusSelector = state => {
9422
+ const {
9423
+ focus,
9424
+ listFocusedIndex
9425
+ } = state;
9180
9426
  switch (focus) {
9181
9427
  case 'composer':
9182
9428
  case 'input':
@@ -9184,7 +9430,17 @@ const getFocusSelector = focus => {
9184
9430
  case 'header':
9185
9431
  return '[name="create-session"]';
9186
9432
  case 'list':
9187
- return '[name^="session:"]';
9433
+ {
9434
+ if (listFocusedIndex === -1) {
9435
+ return `[name="${ChatList$1}"]`;
9436
+ }
9437
+ const visibleSessions = getVisibleSessions(state.sessions, state.selectedProjectId);
9438
+ const session = visibleSessions[listFocusedIndex];
9439
+ if (!session) {
9440
+ return `[name="${ChatList$1}"]`;
9441
+ }
9442
+ return `[name="${getSessionInputName(session.id)}"]`;
9443
+ }
9188
9444
  case 'send-button':
9189
9445
  return '[name="send"]';
9190
9446
  default:
@@ -9192,7 +9448,7 @@ const getFocusSelector = focus => {
9192
9448
  }
9193
9449
  };
9194
9450
  const renderFocus = (oldState, newState) => {
9195
- const selector = getFocusSelector(newState.focus);
9451
+ const selector = getFocusSelector(newState);
9196
9452
  return [FocusSelector, selector];
9197
9453
  };
9198
9454
 
@@ -9225,6 +9481,15 @@ const ChatTodoListItemInProgress = 'ChatTodoListItemInProgress';
9225
9481
  const ChatTodoListItemCompleted = 'ChatTodoListItemCompleted';
9226
9482
  const Chat = 'Chat';
9227
9483
  const ChatHeader = 'ChatHeader';
9484
+ const ChatHeaderLabel = 'ChatHeaderLabel';
9485
+ const MaskIconDebugPause = 'MaskIconDebugPause';
9486
+ const MaskIconAccount = 'MaskIconAccount';
9487
+ const MaskIconAdd = 'MaskIconAdd';
9488
+ const MaskIconClose = 'MaskIconClose';
9489
+ const MaskIconLayoutPanelLeft = 'MaskIconLayoutPanelLeft';
9490
+ const MaskIconSearch = 'MaskIconSearch';
9491
+ const MaskIconSettingsGear = 'MaskIconSettingsGear';
9492
+ const MaskIconSignOut = 'MaskIconSignOut';
9228
9493
  const Button = 'Button';
9229
9494
  const ButtonPrimary = 'ButtonPrimary';
9230
9495
  const ButtonSecondary = 'ButtonSecondary';
@@ -9241,6 +9506,7 @@ const LabelDetail = 'LabelDetail';
9241
9506
  const ChatList = 'ChatList';
9242
9507
  const ChatListEmpty = 'ChatListEmpty';
9243
9508
  const ChatListItem = 'ChatListItem';
9509
+ const ChatListItemFocused = 'ChatListItemFocused';
9244
9510
  const ChatListItemStatusRow = 'ChatListItemStatusRow';
9245
9511
  const ChatListItemStatusIcon = 'ChatListItemStatusIcon';
9246
9512
  const ChatListItemStatusStopped = 'ChatListItemStatusStopped';
@@ -9266,7 +9532,9 @@ const MarkdownQuote = 'MarkdownQuote';
9266
9532
  const MarkdownMathBlock = 'MarkdownMathBlock';
9267
9533
  const MarkdownTable = 'MarkdownTable';
9268
9534
  const ChatTableWrapper = 'ChatTableWrapper';
9535
+ const MaskIcon = 'MaskIcon';
9269
9536
  const Message = 'Message';
9537
+ const MissingApiKeyForm = 'MissingApiKeyForm';
9270
9538
  const ChatMessageContent = 'ChatMessageContent';
9271
9539
  const ChatToolCalls = 'ChatToolCalls';
9272
9540
  const ChatToolCallsLabel = 'ChatToolCallsLabel';
@@ -9330,7 +9598,6 @@ const HandleDrop = 29;
9330
9598
  const HandleDragEnterChatView = 30;
9331
9599
  const HandleDragOverChatView = 31;
9332
9600
  const HandleProjectListScroll = 32;
9333
- const HandleProjectListContextMenu = 33;
9334
9601
  const HandleClickDictationButton = 34;
9335
9602
  const HandleMissingApiKeySubmit = 35;
9336
9603
  const HandleRunModeChange = 36;
@@ -9339,6 +9606,8 @@ const HandleChatWelcomeContextMenu = 39;
9339
9606
  const HandleChatHeaderContextMenu = 40;
9340
9607
  const HandleChatInputContextMenu = 41;
9341
9608
  const HandleContextMenuChatSendAreaBottom = 42;
9609
+ const HandleProjectAddButtonContextMenu = 43;
9610
+ const HandleProjectListContextMenu = 44;
9342
9611
 
9343
9612
  const getModelLabel = model => {
9344
9613
  if (model.provider === 'openRouter') {
@@ -9381,6 +9650,7 @@ const getChatModelPickerVirtualDom = (models, selectedModelId, modelPickerOpen,
9381
9650
  }, {
9382
9651
  childCount: 0,
9383
9652
  className: InputBox,
9653
+ inputType: 'search',
9384
9654
  name: ModelPickerSearch,
9385
9655
  onInput: HandleInput,
9386
9656
  placeholder: 'Search models',
@@ -9400,13 +9670,13 @@ const getChatModelPickerVirtualDom = (models, selectedModelId, modelPickerOpen,
9400
9670
  }, {
9401
9671
  childCount: visibleModels.length,
9402
9672
  className: ChatModelPickerList,
9403
- type: Div
9673
+ type: Ul
9404
9674
  }, ...visibleModels.flatMap(model => [{
9405
9675
  childCount: 1,
9406
9676
  className: `${ChatModelPickerItem}${model.id === selectedModelId ? ` ${ChatModelPickerItemSelected}` : ''}`,
9407
9677
  name: getModelPickerItemInputName(model.id),
9408
9678
  onClick: HandleClick,
9409
- type: Button$1
9679
+ type: Li
9410
9680
  }, text(getModelLabel(model))])] : [])];
9411
9681
  };
9412
9682
 
@@ -9481,7 +9751,8 @@ const getSendButtonDom = (isSendDisabled, voiceDictationEnabled) => {
9481
9751
  type: Button$1
9482
9752
  }, {
9483
9753
  childCount: 0,
9484
- className: 'MaskIcon MaskIconSend',
9754
+ className: 'MaskIcon MaskIconArrowUp',
9755
+ role: 'none',
9485
9756
  type: Div
9486
9757
  }];
9487
9758
  };
@@ -9497,6 +9768,20 @@ const getAddContextButtonDom = () => {
9497
9768
  type: Text
9498
9769
  }];
9499
9770
  };
9771
+ const getBackToChatsButtonDom = () => {
9772
+ return [{
9773
+ childCount: 1,
9774
+ className: mergeClassNames(Button, ButtonSecondary),
9775
+ inputType: 'button',
9776
+ name: Back,
9777
+ onClick: HandleClickBack,
9778
+ title: backToChatList(),
9779
+ type: Button$1
9780
+ }, {
9781
+ text: backToChatList(),
9782
+ type: Text
9783
+ }];
9784
+ };
9500
9785
 
9501
9786
  const clampToPercentage = (tokensUsed, tokensMax) => {
9502
9787
  if (tokensMax <= 0) {
@@ -9533,20 +9818,20 @@ const getUsageOverviewDom = (tokensUsed, tokensMax) => {
9533
9818
  }, text(usageLabel)];
9534
9819
  };
9535
9820
 
9821
+ const getTodoItemClassName = status => {
9822
+ if (status === 'completed') {
9823
+ return `${ChatTodoListItem} ${ChatTodoListItemCompleted} completed`;
9824
+ }
9825
+ if (status === 'inProgress') {
9826
+ return `${ChatTodoListItem} ${ChatTodoListItemInProgress} inProgress`;
9827
+ }
9828
+ return `${ChatTodoListItem} ${ChatTodoListItemTodo} todo`;
9829
+ };
9536
9830
  const getChatSendAreaDom = (composerValue, modelPickerOpen, modelPickerSearchValue, models, newChatModelPickerEnabled, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, runMode, todoListToolEnabled, todoListItems, voiceDictationEnabled = false) => {
9537
9831
  const isSendDisabled = composerValue.trim() === '';
9538
9832
  const controlsCount = 2 + (usageOverviewEnabled ? 1 : 0) + (showRunMode ? 1 : 0) + (addContextButtonEnabled ? 1 : 0);
9539
9833
  const hasTodoList = todoListToolEnabled && todoListItems.length > 0;
9540
9834
  const todoHeaderText = `Todos (${todoListItems.filter(item => item.status === 'completed').length}/${todoListItems.length})`;
9541
- const getTodoItemClassName = status => {
9542
- if (status === 'completed') {
9543
- return `${ChatTodoListItem} ${ChatTodoListItemCompleted} completed`;
9544
- }
9545
- if (status === 'inProgress') {
9546
- return `${ChatTodoListItem} ${ChatTodoListItemInProgress} inProgress`;
9547
- }
9548
- return `${ChatTodoListItem} ${ChatTodoListItemTodo} todo`;
9549
- };
9550
9835
  return [{
9551
9836
  childCount: 1,
9552
9837
  className: ChatSendArea,
@@ -9592,61 +9877,50 @@ const getChatSendAreaDom = (composerValue, modelPickerOpen, modelPickerSearchVal
9592
9877
  }, ...(newChatModelPickerEnabled ? getChatModelPickerVirtualDom(models, selectedModelId, modelPickerOpen, modelPickerSearchValue) : getChatSelectVirtualDom(models, selectedModelId)), ...(showRunMode ? getRunModeSelectVirtualDom(runMode) : []), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...(addContextButtonEnabled ? getAddContextButtonDom() : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
9593
9878
  };
9594
9879
 
9880
+ const getBoldInlineNodeDom = (inlineNode, useChatMathWorker, renderInlineNodeDom) => {
9881
+ return [{
9882
+ childCount: inlineNode.children.length,
9883
+ type: Strong
9884
+ }, ...inlineNode.children.flatMap(child => renderInlineNodeDom(child, useChatMathWorker))];
9885
+ };
9886
+
9595
9887
  const getImageAltText = alt => {
9596
9888
  if (!alt.trim()) {
9597
9889
  return 'image could not be loaded';
9598
9890
  }
9599
9891
  return `${alt} (image could not be loaded)`;
9600
9892
  };
9893
+
9894
+ const getImageInlineNodeDom = inlineNode => {
9895
+ return [{
9896
+ alt: getImageAltText(inlineNode.alt),
9897
+ childCount: 0,
9898
+ className: ImageElement,
9899
+ src: inlineNode.src,
9900
+ type: Img
9901
+ }];
9902
+ };
9903
+
9904
+ const getInlineCodeInlineNodeDom = inlineNode => {
9905
+ return [{
9906
+ childCount: 1,
9907
+ type: Code
9908
+ }, text(inlineNode.text)];
9909
+ };
9910
+
9911
+ const getItalicInlineNodeDom = (inlineNode, useChatMathWorker, renderInlineNodeDom) => {
9912
+ return [{
9913
+ childCount: inlineNode.children.length,
9914
+ type: Em
9915
+ }, ...inlineNode.children.flatMap(child => renderInlineNodeDom(child, useChatMathWorker))];
9916
+ };
9917
+
9601
9918
  const isFileReferenceUri = href => {
9602
9919
  const normalized = href.trim().toLowerCase();
9603
9920
  return normalized.startsWith('file://') || normalized.startsWith('vscode-references://');
9604
9921
  };
9605
- const getInlineNodeDom = (inlineNode, useChatMathWorker = false) => {
9606
- if (inlineNode.type === 'text') {
9607
- return [text(inlineNode.text)];
9608
- }
9609
- if (inlineNode.type === 'image') {
9610
- return [{
9611
- alt: getImageAltText(inlineNode.alt),
9612
- childCount: 0,
9613
- className: ImageElement,
9614
- src: inlineNode.src,
9615
- type: Img
9616
- }];
9617
- }
9618
- if (inlineNode.type === 'bold') {
9619
- return [{
9620
- childCount: inlineNode.children.length,
9621
- type: Strong
9622
- }, ...inlineNode.children.flatMap(child => getInlineNodeDom(child, useChatMathWorker))];
9623
- }
9624
- if (inlineNode.type === 'italic') {
9625
- return [{
9626
- childCount: inlineNode.children.length,
9627
- type: Em
9628
- }, ...inlineNode.children.flatMap(child => getInlineNodeDom(child, useChatMathWorker))];
9629
- }
9630
- if (inlineNode.type === 'strikethrough') {
9631
- return [{
9632
- childCount: inlineNode.children.length,
9633
- className: StrikeThrough,
9634
- type: Span
9635
- }, ...inlineNode.children.flatMap(child => getInlineNodeDom(child, useChatMathWorker))];
9636
- }
9637
- if (inlineNode.type === 'inline-code') {
9638
- return [{
9639
- childCount: 1,
9640
- type: Code
9641
- }, text(inlineNode.text)];
9642
- }
9643
- if (inlineNode.type === 'math-inline') {
9644
- const fallback = inlineNode.displayMode ? `$$${inlineNode.text}$$` : `$${inlineNode.text}$`;
9645
- return [text(fallback)];
9646
- }
9647
- if (inlineNode.type === 'math-inline-dom') {
9648
- return inlineNode.dom;
9649
- }
9922
+
9923
+ const getLinkInlineNodeDom = inlineNode => {
9650
9924
  if (isFileReferenceUri(inlineNode.href)) {
9651
9925
  return [{
9652
9926
  childCount: 1,
@@ -9669,6 +9943,48 @@ const getInlineNodeDom = (inlineNode, useChatMathWorker = false) => {
9669
9943
  }, text(inlineNode.text)];
9670
9944
  };
9671
9945
 
9946
+ const getMathInlineNodeDom = inlineNode => {
9947
+ const fallback = inlineNode.displayMode ? `$$${inlineNode.text}$$` : `$${inlineNode.text}$`;
9948
+ return [text(fallback)];
9949
+ };
9950
+
9951
+ const getStrikethroughInlineNodeDom = (inlineNode, useChatMathWorker, renderInlineNodeDom) => {
9952
+ return [{
9953
+ childCount: inlineNode.children.length,
9954
+ className: StrikeThrough,
9955
+ type: Span
9956
+ }, ...inlineNode.children.flatMap(child => renderInlineNodeDom(child, useChatMathWorker))];
9957
+ };
9958
+
9959
+ const getTextInlineNodeDom = inlineNode => {
9960
+ return [text(inlineNode.text)];
9961
+ };
9962
+
9963
+ const getInlineNodeDom = (inlineNode, useChatMathWorker = false) => {
9964
+ switch (inlineNode.type) {
9965
+ case 'bold':
9966
+ return getBoldInlineNodeDom(inlineNode, useChatMathWorker, getInlineNodeDom);
9967
+ case 'image':
9968
+ return getImageInlineNodeDom(inlineNode);
9969
+ case 'inline-code':
9970
+ return getInlineCodeInlineNodeDom(inlineNode);
9971
+ case 'italic':
9972
+ return getItalicInlineNodeDom(inlineNode, useChatMathWorker, getInlineNodeDom);
9973
+ case 'link':
9974
+ return getLinkInlineNodeDom(inlineNode);
9975
+ case 'math-inline':
9976
+ return getMathInlineNodeDom(inlineNode);
9977
+ case 'math-inline-dom':
9978
+ return inlineNode.dom;
9979
+ case 'strikethrough':
9980
+ return getStrikethroughInlineNodeDom(inlineNode, useChatMathWorker, getInlineNodeDom);
9981
+ case 'text':
9982
+ return getTextInlineNodeDom(inlineNode);
9983
+ }
9984
+ const exhaustiveCheck = inlineNode;
9985
+ return exhaustiveCheck;
9986
+ };
9987
+
9672
9988
  const jsRules = [{
9673
9989
  className: TokenComment,
9674
9990
  regex: /\/\/[^\n]*/
@@ -9995,12 +10311,42 @@ const getMessageContentDom = (nodes, useChatMathWorker = false) => {
9995
10311
  return nodes.flatMap(node => getMessageNodeDom(node, useChatMathWorker));
9996
10312
  };
9997
10313
 
10314
+ const getMissingApiActionsDom = ({
10315
+ getApiKeyText,
10316
+ openSettingsButtonName,
10317
+ openSettingsUrl,
10318
+ saveButtonDisabled = false,
10319
+ saveButtonName,
10320
+ saveButtonText = save()
10321
+ }) => {
10322
+ return [{
10323
+ childCount: 2,
10324
+ className: Actions,
10325
+ type: Div
10326
+ }, {
10327
+ childCount: 1,
10328
+ className: mergeClassNames(Button, ButtonPrimary),
10329
+ disabled: saveButtonDisabled,
10330
+ inputType: 'submit',
10331
+ name: saveButtonName,
10332
+ type: Button$1
10333
+ }, text(saveButtonText), {
10334
+ childCount: 1,
10335
+ className: mergeClassNames(Button, ButtonSecondary),
10336
+ href: openSettingsUrl,
10337
+ name: openSettingsButtonName,
10338
+ rel: 'noopener noreferrer',
10339
+ target: '_blank',
10340
+ type: A
10341
+ }, text(getApiKeyText)];
10342
+ };
9998
10343
  const getMissingApiKeyDom = ({
9999
10344
  getApiKeyText,
10000
10345
  inputName,
10001
10346
  inputPattern,
10002
10347
  inputRequired = false,
10003
10348
  openSettingsButtonName,
10349
+ openSettingsUrl,
10004
10350
  placeholder,
10005
10351
  saveButtonDisabled = false,
10006
10352
  saveButtonName,
@@ -10008,10 +10354,14 @@ const getMissingApiKeyDom = ({
10008
10354
  }) => {
10009
10355
  return [{
10010
10356
  childCount: 2,
10357
+ className: MissingApiKeyForm,
10011
10358
  method: 'GET',
10012
10359
  onSubmit: HandleMissingApiKeySubmit,
10013
10360
  type: Form
10014
10361
  }, {
10362
+ autocapitalize: 'off',
10363
+ autocomplete: 'off',
10364
+ autocorrect: 'off',
10015
10365
  childCount: 0,
10016
10366
  className: InputBox,
10017
10367
  name: inputName,
@@ -10021,26 +10371,16 @@ const getMissingApiKeyDom = ({
10021
10371
  } : {}),
10022
10372
  placeholder,
10023
10373
  required: inputRequired,
10374
+ spellcheck: false,
10024
10375
  type: Input
10025
- }, {
10026
- childCount: 2,
10027
- className: Actions,
10028
- type: Div
10029
- }, {
10030
- childCount: 1,
10031
- className: mergeClassNames(Button, ButtonPrimary),
10032
- disabled: saveButtonDisabled,
10033
- inputType: 'submit',
10034
- name: saveButtonName,
10035
- type: Button$1
10036
- }, text(saveButtonText), {
10037
- childCount: 1,
10038
- className: mergeClassNames(Button, ButtonSecondary),
10039
- inputType: 'button',
10040
- name: openSettingsButtonName,
10041
- onClick: HandleClick,
10042
- type: Button$1
10043
- }, text(getApiKeyText)];
10376
+ }, ...getMissingApiActionsDom({
10377
+ getApiKeyText,
10378
+ openSettingsButtonName,
10379
+ openSettingsUrl,
10380
+ saveButtonDisabled,
10381
+ saveButtonName,
10382
+ saveButtonText
10383
+ })];
10044
10384
  };
10045
10385
 
10046
10386
  const getMissingOpenApiApiKeyDom = () => {
@@ -10050,6 +10390,7 @@ const getMissingOpenApiApiKeyDom = () => {
10050
10390
  inputPattern: '^sk-.+',
10051
10391
  inputRequired: true,
10052
10392
  openSettingsButtonName: OpenOpenApiApiKeyWebsite,
10393
+ openSettingsUrl: 'https://platform.openai.com/api-keys',
10053
10394
  placeholder: openApiApiKeyPlaceholder(),
10054
10395
  saveButtonName: SaveOpenApiApiKey
10055
10396
  });
@@ -10061,6 +10402,7 @@ const getMissingOpenRouterApiKeyDom = (openRouterApiKeyState = 'idle') => {
10061
10402
  getApiKeyText: getOpenRouterApiKey(),
10062
10403
  inputName: OpenRouterApiKeyInput,
10063
10404
  openSettingsButtonName: OpenOpenRouterApiKeySettings,
10405
+ openSettingsUrl: 'https://openrouter.ai/settings/keys',
10064
10406
  placeholder: openRouterApiKeyPlaceholder(),
10065
10407
  saveButtonDisabled: isSaving,
10066
10408
  saveButtonName: SaveOpenRouterApiKey,
@@ -10945,6 +11287,7 @@ const getProjectSessionDom = (session, selectedSessionId) => {
10945
11287
  className: ProjectSessionItemLabel,
10946
11288
  name: getSessionInputName(session.id),
10947
11289
  onClick: HandleClick,
11290
+ onContextMenu: HandleProjectListContextMenu,
10948
11291
  tabIndex: 0,
10949
11292
  type: Div
10950
11293
  }, text(session.title)];
@@ -10965,6 +11308,7 @@ const getProjectGroupDom = (project, sessions, projectExpandedIds, selectedProje
10965
11308
  className: ProjectListItemLabel,
10966
11309
  name: getProjectInputName(project.id),
10967
11310
  onClick: HandleClick,
11311
+ onContextMenu: HandleProjectListContextMenu,
10968
11312
  tabIndex: 0,
10969
11313
  type: Div
10970
11314
  }, {
@@ -10989,7 +11333,7 @@ const getProjectGroupDom = (project, sessions, projectExpandedIds, selectedProje
10989
11333
  type: Button$1
10990
11334
  }, text('+'), ...(expanded ? sessions.flatMap(session => getProjectSessionDom(session, selectedSessionId)) : [])];
10991
11335
  };
10992
- const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop) => {
11336
+ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop, showBackToChatsButton = false) => {
10993
11337
  const blankProjectId = projects.find(project => project.name === '_blank')?.id || projects[0]?.id || '';
10994
11338
  const projectGroups = projects.map(project => {
10995
11339
  const projectSessions = sessions.filter(session => {
@@ -10999,13 +11343,12 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
10999
11343
  return getProjectGroupDom(project, projectSessions, projectExpandedIds, selectedProjectId, selectedSessionId);
11000
11344
  });
11001
11345
  return [{
11002
- childCount: 2,
11346
+ childCount: 2 + (showBackToChatsButton ? 1 : 0),
11003
11347
  className: ProjectSidebar,
11004
11348
  type: Div
11005
11349
  }, {
11006
11350
  childCount: projects.length,
11007
11351
  className: ProjectList,
11008
- onContextMenu: HandleProjectListContextMenu,
11009
11352
  onScroll: HandleProjectListScroll,
11010
11353
  scrollTop: projectListScrollTop,
11011
11354
  type: Div
@@ -11014,9 +11357,10 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
11014
11357
  className: ProjectAddButton,
11015
11358
  name: CreateProject,
11016
11359
  onClick: HandleClick,
11360
+ onContextMenu: HandleProjectAddButtonContextMenu,
11017
11361
  tabIndex: 0,
11018
11362
  type: Button$1
11019
- }, text('+ Add Project')];
11363
+ }, text('+ Add Project'), ...(showBackToChatsButton ? getBackToChatsButtonDom() : [])];
11020
11364
  };
11021
11365
 
11022
11366
  const getChatModeChatFocusVirtualDom = ({
@@ -11066,7 +11410,7 @@ const getChatModeChatFocusVirtualDom = ({
11066
11410
  onDragEnter: HandleDragEnterChatView,
11067
11411
  onDragOver: HandleDragOverChatView,
11068
11412
  type: Div
11069
- }, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, modelPickerOpen, modelPickerSearchValue, models, newChatModelPickerEnabled, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, runMode, todoListToolEnabled, todoListItems, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
11413
+ }, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop, true), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, modelPickerOpen, modelPickerSearchValue, models, newChatModelPickerEnabled, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, runMode, todoListToolEnabled, todoListItems, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
11070
11414
  childCount: 1,
11071
11415
  className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
11072
11416
  name: ComposerDropTarget,
@@ -11117,44 +11461,44 @@ const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'si
11117
11461
  const isSigningIn = authStatus === 'signing-in';
11118
11462
  const authAction = authEnabled && authStatus !== 'signed-in' ? {
11119
11463
  disabled: isSigningIn,
11120
- icon: 'MaskIcon MaskIconAccount',
11464
+ icon: mergeClassNames(MaskIcon, MaskIconAccount),
11121
11465
  name: Login,
11122
11466
  onClick: HandleClick,
11123
11467
  title: isSigningIn ? loggingInToBackend() : loginToBackend()
11124
11468
  } : authEnabled ? {
11125
11469
  disabled: false,
11126
- icon: 'MaskIcon MaskIconSignOut',
11470
+ icon: mergeClassNames(MaskIcon, MaskIconSignOut),
11127
11471
  name: Logout,
11128
11472
  onClick: HandleClick,
11129
11473
  title: logoutFromBackend()
11130
11474
  } : undefined;
11131
11475
  const items = [{
11132
- icon: 'MaskIcon MaskIconLayoutPanelLeft',
11476
+ icon: mergeClassNames(MaskIcon, MaskIconLayoutPanelLeft),
11133
11477
  name: ToggleChatFocus,
11134
11478
  onClick: HandleClick,
11135
11479
  title: toggleTitle
11136
11480
  }, ...(searchEnabled ? [{
11137
- icon: 'MaskIcon MaskIconSearch',
11481
+ icon: mergeClassNames(MaskIcon, MaskIconSearch),
11138
11482
  name: ToggleSearch,
11139
11483
  onClick: HandleClick,
11140
11484
  title: search()
11141
11485
  }] : []), {
11142
- icon: 'MaskIcon MaskIconDebugPause',
11486
+ icon: mergeClassNames(MaskIcon, MaskIconDebugPause),
11143
11487
  name: SessionDebug,
11144
11488
  onClick: HandleClickSessionDebug,
11145
11489
  title: debug()
11146
11490
  }, {
11147
- icon: 'MaskIcon MaskIconAdd',
11491
+ icon: mergeClassNames(MaskIcon, MaskIconAdd),
11148
11492
  name: CreateSession,
11149
11493
  onClick: HandleClickNew,
11150
11494
  title: newChat()
11151
11495
  }, {
11152
- icon: 'MaskIcon MaskIconSettingsGear',
11496
+ icon: mergeClassNames(MaskIcon, MaskIconSettingsGear),
11153
11497
  name: Settings,
11154
11498
  onClick: HandleClickSettings,
11155
11499
  title: settings()
11156
11500
  }, ...(authAction ? [authAction] : []), {
11157
- icon: 'MaskIcon MaskIconClose',
11501
+ icon: mergeClassNames(MaskIcon, MaskIconClose),
11158
11502
  name: CloseChat,
11159
11503
  onClick: HandleClickClose,
11160
11504
  title: closeChat()
@@ -11180,8 +11524,8 @@ const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, a
11180
11524
  type: Div
11181
11525
  }, ...getBackButtonVirtualDom(), {
11182
11526
  childCount: 1,
11183
- className: Label,
11184
- type: Span
11527
+ className: ChatHeaderLabel,
11528
+ type: H2
11185
11529
  }, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail', authEnabled, authStatus), ...(hasAuthError ? [{
11186
11530
  childCount: 1,
11187
11531
  className: ChatAuthError,
@@ -11258,8 +11602,8 @@ const getChatHeaderListModeDom = (authEnabled = false, authStatus = 'signed-out'
11258
11602
  type: Div
11259
11603
  }, {
11260
11604
  childCount: 1,
11261
- className: Label,
11262
- type: Span
11605
+ className: ChatHeaderLabel,
11606
+ type: H2
11263
11607
  }, text(chats()), ...getChatHeaderActionsDom('list', authEnabled, authStatus, searchEnabled), ...(hasSearchField ? [{
11264
11608
  childCount: 1,
11265
11609
  className: SearchFieldContainer,
@@ -11303,8 +11647,8 @@ const getSessionStatusClassName = session => {
11303
11647
  }
11304
11648
  return ChatListItemStatusStopped;
11305
11649
  };
11306
- const getSessionDom = session => {
11307
- const sessionClassName = ChatListItem;
11650
+ const getSessionDom = (session, focused = false) => {
11651
+ const sessionClassName = focused ? mergeClassNames(ChatListItem, ChatListItemFocused) : ChatListItem;
11308
11652
  const sessionStatusClassName = getSessionStatusClassName(session);
11309
11653
  return [{
11310
11654
  childCount: 3,
@@ -11323,6 +11667,8 @@ const getSessionDom = session => {
11323
11667
  className: ChatListItemLabel,
11324
11668
  name: getSessionInputName(session.id),
11325
11669
  onContextMenu: HandleListContextMenu,
11670
+ onFocus: HandleFocus,
11671
+ tabIndex: 0,
11326
11672
  type: Div
11327
11673
  }, text(session.title), {
11328
11674
  childCount: 1,
@@ -11344,18 +11690,22 @@ const getSessionDom = session => {
11344
11690
  }];
11345
11691
  };
11346
11692
 
11347
- const getChatListDom = (sessions, selectedSessionId, chatListScrollTop = 0) => {
11693
+ const getChatListDom = (sessions, selectedSessionId, listFocusedIndex, chatListScrollTop = 0) => {
11348
11694
  if (sessions.length === 0) {
11349
11695
  return getEmptyChatSessionsDom();
11350
11696
  }
11351
11697
  return [{
11352
11698
  childCount: sessions.length,
11353
11699
  className: ChatList,
11700
+ name: ChatList$1,
11354
11701
  onClick: HandleClickList,
11702
+ onContextMenu: HandleListContextMenu,
11703
+ onFocus: HandleFocus,
11355
11704
  onScroll: HandleChatListScroll,
11356
11705
  scrollTop: chatListScrollTop,
11706
+ tabIndex: 0,
11357
11707
  type: Ul
11358
- }, ...sessions.flatMap(getSessionDom)];
11708
+ }, ...sessions.flatMap((session, index) => getSessionDom(session, index === listFocusedIndex))];
11359
11709
  };
11360
11710
 
11361
11711
  const getChatModeListVirtualDom = ({
@@ -11371,6 +11721,7 @@ const getChatModeListVirtualDom = ({
11371
11721
  composerHeight = 28,
11372
11722
  composerLineHeight = 20,
11373
11723
  composerValue,
11724
+ listFocusedIndex = -1,
11374
11725
  modelPickerOpen = false,
11375
11726
  modelPickerSearchValue = '',
11376
11727
  models,
@@ -11399,7 +11750,7 @@ const getChatModeListVirtualDom = ({
11399
11750
  onDragEnter: HandleDragEnterChatView,
11400
11751
  onDragOver: HandleDragOverChatView,
11401
11752
  type: Div
11402
- }, ...getChatHeaderListModeDom(authEnabled, authStatus, authErrorMessage, searchEnabled, searchFieldVisible, searchValue), ...getChatListDom(visibleSessions, selectedSessionId, chatListScrollTop), ...getChatSendAreaDom(composerValue, modelPickerOpen, modelPickerSearchValue, models, newChatModelPickerEnabled, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, runMode, todoListToolEnabled, todoListItems, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
11753
+ }, ...getChatHeaderListModeDom(authEnabled, authStatus, authErrorMessage, searchEnabled, searchFieldVisible, searchValue), ...getChatListDom(visibleSessions, selectedSessionId, listFocusedIndex, chatListScrollTop), ...getChatSendAreaDom(composerValue, modelPickerOpen, modelPickerSearchValue, models, newChatModelPickerEnabled, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, runMode, todoListToolEnabled, todoListItems, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
11403
11754
  childCount: 1,
11404
11755
  className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
11405
11756
  name: ComposerDropTarget,
@@ -11506,6 +11857,7 @@ const getChatVirtualDom = options => {
11506
11857
  composerHeight,
11507
11858
  composerLineHeight,
11508
11859
  composerValue,
11860
+ listFocusedIndex = -1,
11509
11861
  messagesScrollTop,
11510
11862
  modelPickerOpen = false,
11511
11863
  modelPickerSearchValue = '',
@@ -11626,6 +11978,7 @@ const getChatVirtualDom = options => {
11626
11978
  composerHeight,
11627
11979
  composerLineHeight,
11628
11980
  composerValue,
11981
+ listFocusedIndex,
11629
11982
  modelPickerOpen,
11630
11983
  modelPickerSearchValue,
11631
11984
  models,
@@ -11665,6 +12018,7 @@ const renderItems = (oldState, newState) => {
11665
12018
  composerLineHeight,
11666
12019
  composerValue,
11667
12020
  initial,
12021
+ listFocusedIndex,
11668
12022
  messagesScrollTop,
11669
12023
  modelPickerOpen,
11670
12024
  modelPickerSearchValue,
@@ -11711,6 +12065,7 @@ const renderItems = (oldState, newState) => {
11711
12065
  composerHeight,
11712
12066
  composerLineHeight,
11713
12067
  composerValue,
12068
+ listFocusedIndex,
11714
12069
  messagesScrollTop,
11715
12070
  modelPickerOpen,
11716
12071
  modelPickerSearchValue,
@@ -11961,6 +12316,10 @@ const renderEventListeners = () => {
11961
12316
  }, {
11962
12317
  name: HandleProjectListScroll,
11963
12318
  params: ['handleProjectListScroll', 'event.target.scrollTop']
12319
+ }, {
12320
+ name: HandleProjectAddButtonContextMenu,
12321
+ params: ['handleProjectAddButtonContextMenu'],
12322
+ preventDefault: true
11964
12323
  }, {
11965
12324
  name: HandleProjectListContextMenu,
11966
12325
  params: ['handleProjectListContextMenu'],
@@ -11971,7 +12330,8 @@ const renderEventListeners = () => {
11971
12330
  preventDefault: true
11972
12331
  }, {
11973
12332
  name: HandleChatWelcomeContextMenu,
11974
- params: ['handleChatWelcomeContextMenu']
12333
+ params: ['handleChatDetailWelcomeContextMenu'],
12334
+ preventDefault: true
11975
12335
  }, {
11976
12336
  name: HandleChatHeaderContextMenu,
11977
12337
  params: ['handleChatHeaderContextMenu'],
@@ -12025,11 +12385,18 @@ const reset = async state => {
12025
12385
  };
12026
12386
  };
12027
12387
 
12028
- const resize = (state, dimensions) => {
12029
- return {
12388
+ const resize = async (state, dimensions, getComposerHeightFn = getComposerHeight) => {
12389
+ const nextState = {
12030
12390
  ...state,
12031
12391
  ...dimensions
12032
12392
  };
12393
+ if (dimensions.width !== undefined && dimensions.width !== state.width && nextState.composerValue) {
12394
+ return {
12395
+ ...nextState,
12396
+ composerHeight: await getComposerHeightFn(nextState, nextState.composerValue, nextState.width)
12397
+ };
12398
+ }
12399
+ return nextState;
12033
12400
  };
12034
12401
 
12035
12402
  const saveState = state => {
@@ -12233,6 +12600,10 @@ const useMockApi = (state, value, mockApiCommandId = defaultMockApiCommandId) =>
12233
12600
  };
12234
12601
 
12235
12602
  const commandMap = {
12603
+ 'Chat.chatListFocusFirst': wrapCommand(chatListFocusFirst),
12604
+ 'Chat.chatListFocusLast': wrapCommand(chatListFocusLast),
12605
+ 'Chat.chatListFocusNext': wrapCommand(chatListFocusNext),
12606
+ 'Chat.chatListFocusPrevious': wrapCommand(chatListFocusPrevious),
12236
12607
  'Chat.clearInput': wrapCommand(clearInput),
12237
12608
  'Chat.copyInput': wrapCommand(copyInput),
12238
12609
  'Chat.create': create,
@@ -12247,11 +12618,11 @@ const commandMap = {
12247
12618
  'Chat.getMenuEntryIds': getMenuEntryIds,
12248
12619
  'Chat.getQuickPickMenuEntries': getQuickPickMenuEntries,
12249
12620
  'Chat.getSelectedSessionId': wrapGetter(getSelectedSessionId),
12621
+ 'Chat.handleChatDetailWelcomeContextMenu': wrapCommand(handleChatDetailWelcomeContextMenu),
12250
12622
  'Chat.handleChatHeaderContextMenu': wrapCommand(handleChatHeaderContextMenu),
12251
12623
  'Chat.handleChatInputContextMenu': wrapCommand(handleChatInputContextMenu),
12252
12624
  'Chat.handleChatListContextMenu': wrapCommand(handleChatListContextMenu),
12253
12625
  'Chat.handleChatListScroll': wrapCommand(handleChatListScroll),
12254
- 'Chat.handleChatWelcomeContextMenu': wrapCommand(handleChatWelcomeContextMenu),
12255
12626
  'Chat.handleClick': wrapCommand(handleClick),
12256
12627
  'Chat.handleClickBack': wrapCommand(handleClickBack),
12257
12628
  'Chat.handleClickClose': handleClickClose,
@@ -12275,6 +12646,7 @@ const commandMap = {
12275
12646
  'Chat.handleMessagesScroll': wrapCommand(handleMessagesScroll),
12276
12647
  'Chat.handleMissingApiKeySubmit': wrapCommand(handleMissingApiKeySubmit),
12277
12648
  'Chat.handleModelChange': wrapCommand(handleModelChange),
12649
+ 'Chat.handleProjectAddButtonContextMenu': wrapCommand(handleProjectAddButtonContextMenu),
12278
12650
  'Chat.handleProjectListContextMenu': wrapCommand(handleProjectListContextMenu),
12279
12651
  'Chat.handleProjectListScroll': wrapCommand(handleProjectListScroll),
12280
12652
  'Chat.handleRunModeChange': wrapCommand(handleRunModeChange),