@lvce-editor/chat-view 6.67.0 → 6.69.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.
@@ -1214,6 +1214,7 @@ const Home = 12;
1214
1214
  const UpArrow = 14;
1215
1215
  const DownArrow = 16;
1216
1216
  const KeyN = 42;
1217
+ const KeyV = 50;
1217
1218
 
1218
1219
  const CtrlCmd = 1 << 11 >>> 0;
1219
1220
  const Shift = 1 << 10 >>> 0;
@@ -1856,6 +1857,7 @@ const Paste = 'Paste';
1856
1857
  const Rename = 'Rename';
1857
1858
  const Archive = 'Archive';
1858
1859
  const AddProjectChat = 'Add Project';
1860
+ const RemoveProject = 'Remove Project';
1859
1861
  const Settings$1 = 'Settings';
1860
1862
  const LoginToBackend = 'Login to backend';
1861
1863
  const LogoutFromBackend = 'Logout from backend';
@@ -1915,6 +1917,9 @@ const newChat = () => {
1915
1917
  const addProject = () => {
1916
1918
  return i18nString(AddProjectChat);
1917
1919
  };
1920
+ const removeProject = () => {
1921
+ return i18nString(RemoveProject);
1922
+ };
1918
1923
  const debug = () => {
1919
1924
  return i18nString(Debug);
1920
1925
  };
@@ -2872,10 +2877,7 @@ const RenderIncremental = 11;
2872
2877
  const RenderScrollTop = 12;
2873
2878
 
2874
2879
  const diffValue = (oldState, newState) => {
2875
- if (oldState.composerValue === newState.composerValue) {
2876
- return true;
2877
- }
2878
- return newState.inputSource !== 'script';
2880
+ return oldState.composerValue === newState.composerValue || newState.inputSource !== 'script';
2879
2881
  };
2880
2882
 
2881
2883
  const modules = [isEqual, diffValue, diffSelection, diffFocus, isEqual$1, diffFocus, diffScrollTop];
@@ -2897,8 +2899,7 @@ const diff2 = uid => {
2897
2899
  newState,
2898
2900
  oldState
2899
2901
  } = get$1(uid);
2900
- const result = diff(oldState, newState);
2901
- return result;
2902
+ return diff(oldState, newState);
2902
2903
  };
2903
2904
 
2904
2905
  const getAuthState = state => {
@@ -3256,6 +3257,10 @@ const getKeyBindings = () => {
3256
3257
  command: 'Chat.chatInputHistoryDown',
3257
3258
  key: DownArrow,
3258
3259
  when: FocusChatInput
3260
+ }, {
3261
+ command: 'Chat.pasteInput',
3262
+ key: CtrlCmd | KeyV,
3263
+ when: FocusChatInput
3259
3264
  }, {
3260
3265
  command: 'Chat.chatInputHistoryUp',
3261
3266
  key: UpArrow,
@@ -3412,6 +3417,7 @@ const Login = 'login';
3412
3417
  const Logout = 'logout';
3413
3418
  const CloseChat = 'close-chat';
3414
3419
  const SessionDelete = 'SessionDelete';
3420
+ const ProjectDelete = 'ProjectDelete';
3415
3421
  const ProjectPrefix = 'project:';
3416
3422
  const SessionPrefix = 'session:';
3417
3423
  const RenamePrefix = 'session-rename:';
@@ -3520,17 +3526,27 @@ const menuEntryAddProject = {
3520
3526
  id: 'addProject',
3521
3527
  label: addProject()
3522
3528
  };
3523
- const getMenuEntriesChatProjectList = (projectId = '') => {
3529
+ const getMenuEntriesChatProjectList = (projectId = '', canRemoveProject = true) => {
3524
3530
  if (!projectId) {
3525
3531
  return [menuEntryAddProject];
3526
3532
  }
3527
- return [{
3533
+ const entries = [{
3528
3534
  args: [getCreateSessionInProjectInputName(projectId)],
3529
3535
  command: 'Chat.handleClick',
3530
3536
  flags: None,
3531
3537
  id: 'newChat',
3532
3538
  label: newChat()
3533
3539
  }, menuEntryAddProject];
3540
+ if (canRemoveProject) {
3541
+ entries.push({
3542
+ args: [ProjectDelete, projectId],
3543
+ command: 'Chat.handleClick',
3544
+ flags: None,
3545
+ id: 'removeProject',
3546
+ label: removeProject()
3547
+ });
3548
+ }
3549
+ return entries;
3534
3550
  };
3535
3551
 
3536
3552
  const getMenuEntriesProjectAddButton = () => {
@@ -3564,7 +3580,7 @@ const getMenuEntries = (menuId, props) => {
3564
3580
  case MenuChatList:
3565
3581
  return getMenuEntriesChatList();
3566
3582
  case MenuChatProjectList:
3567
- return getMenuEntriesChatProjectList(props.projectId);
3583
+ return getMenuEntriesChatProjectList(props.projectId, props.canRemoveProject);
3568
3584
  case MenuProjectAddButton:
3569
3585
  return getMenuEntriesProjectAddButton();
3570
3586
  default:
@@ -3665,6 +3681,15 @@ const handleChatListContextMenu = async (state, eventX, eventY) => {
3665
3681
  };
3666
3682
  };
3667
3683
 
3684
+ const focusInput = state => {
3685
+ return {
3686
+ ...state,
3687
+ focus: 'composer',
3688
+ focused: true,
3689
+ listFocusedIndex: -1
3690
+ };
3691
+ };
3692
+
3668
3693
  const generateSessionId = () => {
3669
3694
  return crypto.randomUUID();
3670
3695
  };
@@ -3680,7 +3705,7 @@ const createSession = async (state, projectIdOverride = '') => {
3680
3705
  title: `Chat ${state.sessions.length + 1}`
3681
3706
  };
3682
3707
  await saveChatSession(session);
3683
- return {
3708
+ return focusInput({
3684
3709
  ...state,
3685
3710
  composerAttachments: [],
3686
3711
  composerAttachmentsHeight: 0,
@@ -3689,6 +3714,84 @@ const createSession = async (state, projectIdOverride = '') => {
3689
3714
  selectedProjectId: projectId,
3690
3715
  selectedSessionId: id,
3691
3716
  sessions: [...state.sessions, session]
3717
+ });
3718
+ };
3719
+
3720
+ const getBlankProjectId = (state, removedProjectId) => {
3721
+ return state.projects.find(project => project.id !== removedProjectId && project.name === '_blank')?.id || '';
3722
+ };
3723
+ const getNextViewMode = (state, hasSelectedSession) => {
3724
+ if (state.viewMode === 'chat-focus') {
3725
+ return 'chat-focus';
3726
+ }
3727
+ if (!hasSelectedSession) {
3728
+ return 'list';
3729
+ }
3730
+ return state.viewMode === 'detail' ? 'detail' : 'list';
3731
+ };
3732
+ const ensureExpandedProject = (state, projectExpandedIds, selectedProjectId, visibleSessions) => {
3733
+ if (state.viewMode !== 'chat-focus' || !selectedProjectId || visibleSessions.length === 0 || projectExpandedIds.includes(selectedProjectId)) {
3734
+ return projectExpandedIds;
3735
+ }
3736
+ return [...projectExpandedIds, selectedProjectId];
3737
+ };
3738
+ const deleteProject = async (state, projectId) => {
3739
+ const project = state.projects.find(candidate => candidate.id === projectId);
3740
+ if (!project || project.name === '_blank') {
3741
+ return state;
3742
+ }
3743
+ const blankProjectId = getBlankProjectId(state, projectId);
3744
+ if (!blankProjectId) {
3745
+ return state;
3746
+ }
3747
+ const projects = state.projects.filter(candidate => candidate.id !== projectId);
3748
+ const sessions = await Promise.all(state.sessions.map(async session => {
3749
+ if (session.projectId !== projectId) {
3750
+ return session;
3751
+ }
3752
+ const updatedSession = {
3753
+ ...session,
3754
+ projectId: blankProjectId
3755
+ };
3756
+ await saveChatSession(updatedSession);
3757
+ return updatedSession;
3758
+ }));
3759
+ const selectedProjectId = !state.selectedProjectId || state.selectedProjectId === projectId || !projects.some(candidate => candidate.id === state.selectedProjectId) ? blankProjectId : state.selectedProjectId;
3760
+ const projectExpandedIds = state.projectExpandedIds.filter(expandedProjectId => expandedProjectId !== projectId && projects.some(candidate => candidate.id === expandedProjectId));
3761
+ const visibleSessions = getVisibleSessions(sessions, selectedProjectId);
3762
+ const nextProjectExpandedIds = ensureExpandedProject(state, projectExpandedIds, selectedProjectId, visibleSessions);
3763
+ if (visibleSessions.length === 0) {
3764
+ return {
3765
+ ...state,
3766
+ composerAttachments: [],
3767
+ composerAttachmentsHeight: 0,
3768
+ projectExpandedIds: nextProjectExpandedIds,
3769
+ projects,
3770
+ selectedProjectId,
3771
+ selectedSessionId: '',
3772
+ sessions,
3773
+ viewMode: getNextViewMode(state, false)
3774
+ };
3775
+ }
3776
+ const selectedSessionId = visibleSessions.some(session => session.id === state.selectedSessionId) ? state.selectedSessionId : visibleSessions[0].id;
3777
+ const loadedSession = await getChatSession(selectedSessionId);
3778
+ const composerAttachments = await getComposerAttachments(selectedSessionId);
3779
+ const hydratedSessions = sessions.map(session => {
3780
+ if (session.id !== selectedSessionId || !loadedSession) {
3781
+ return session;
3782
+ }
3783
+ return loadedSession;
3784
+ });
3785
+ return {
3786
+ ...state,
3787
+ composerAttachments,
3788
+ composerAttachmentsHeight: getComposerAttachmentsHeight(composerAttachments, state.width),
3789
+ projectExpandedIds: nextProjectExpandedIds,
3790
+ projects,
3791
+ selectedProjectId,
3792
+ selectedSessionId,
3793
+ sessions: hydratedSessions,
3794
+ viewMode: getNextViewMode(state, true)
3692
3795
  };
3693
3796
  };
3694
3797
 
@@ -3832,8 +3935,7 @@ const executeProvider = async ({
3832
3935
  }) => {
3833
3936
  await activateByEvent(event, assetDir, platform);
3834
3937
  // @ts-ignore
3835
- const result = invoke$2(method, ...params);
3836
- return result;
3938
+ return invoke$2(method, ...params);
3837
3939
  };
3838
3940
 
3839
3941
  const CommandExecute = 'ExtensionHostCommand.executeCommand';
@@ -6726,6 +6828,7 @@ const ChatAuthError = 'ChatAuthError';
6726
6828
  const ChatFocus = 'ChatFocus';
6727
6829
  const ChatFocusActions = 'ChatFocusActions';
6728
6830
  const ChatFocusHeader = 'ChatFocusHeader';
6831
+ const ChatFocusMainArea = 'ChatFocusMainArea';
6729
6832
  const ChatFocusProject = 'ChatFocusProject';
6730
6833
  const ChatHeader = 'ChatHeader';
6731
6834
  const ChatHeaderLabel = 'ChatHeaderLabel';
@@ -6768,6 +6871,13 @@ const ChatComposerAttachmentPreviewOverlayImage = 'ChatComposerAttachmentPreview
6768
6871
  const ChatComposerAttachmentRemoveButton = 'ChatComposerAttachmentRemoveButton';
6769
6872
  const ChatComposerAttachments = 'ChatComposerAttachments';
6770
6873
  const ChatComposerAttachmentTextFile = 'ChatComposerAttachmentTextFile';
6874
+ const ChatAttachment = 'ChatAttachment';
6875
+ const ChatAttachmentImage = 'ChatAttachmentImage';
6876
+ const ChatAttachmentInvalidImage = 'ChatAttachmentInvalidImage';
6877
+ const ChatAttachmentLabel = 'ChatAttachmentLabel';
6878
+ const ChatAttachmentPreview = 'ChatAttachmentPreview';
6879
+ const ChatAttachments = 'ChatAttachments';
6880
+ const ChatAttachmentTextFile = 'ChatAttachmentTextFile';
6771
6881
  const ChatSendArea = 'ChatSendArea';
6772
6882
  const ChatSendAreaBottom = 'ChatSendAreaBottom';
6773
6883
  const ChatSendAreaContent = 'ChatSendAreaContent';
@@ -6817,6 +6927,7 @@ const MaskIconAccount = 'MaskIconAccount';
6817
6927
  const MaskIconAdd = 'MaskIconAdd';
6818
6928
  const MaskIconArrowLeft = 'MaskIconArrowLeft';
6819
6929
  const MaskIconChevronDown = 'MaskIconChevronDown';
6930
+ const MaskIconChevronRight = 'MaskIconChevronRight';
6820
6931
  const MaskIconChevronUp = 'MaskIconChevronUp';
6821
6932
  const MaskIconClose = 'MaskIconClose';
6822
6933
  const MaskIconDebugPause = 'MaskIconDebugPause';
@@ -8416,15 +8527,6 @@ const getSlashCommandHandler = command => {
8416
8527
  return slashCommandRegistry[command];
8417
8528
  };
8418
8529
 
8419
- const focusInput = state => {
8420
- return {
8421
- ...state,
8422
- focus: 'composer',
8423
- focused: true,
8424
- listFocusedIndex: -1
8425
- };
8426
- };
8427
-
8428
8530
  const withClearedComposer = state => {
8429
8531
  return focusInput({
8430
8532
  ...state,
@@ -9556,6 +9658,8 @@ const handleClick = async (state, name, id = '', eventX = 0, eventY = 0) => {
9556
9658
  }
9557
9659
  case name === SessionDelete:
9558
9660
  return deleteSession(state, id);
9661
+ case name === ProjectDelete:
9662
+ return deleteProject(state, id);
9559
9663
  case name === Send:
9560
9664
  return handleClickSend(state);
9561
9665
  case name === ScrollDown:
@@ -9871,15 +9975,6 @@ const handleSearchValueChange = (state, newValue) => {
9871
9975
  };
9872
9976
 
9873
9977
  const handleInput = async (state, name, value, inputSource = 'user') => {
9874
- const {
9875
- chatInputHistoryDraft,
9876
- chatInputHistoryIndex,
9877
- composerAttachments,
9878
- modelPickerHeaderHeight,
9879
- models,
9880
- selectedSessionId,
9881
- width
9882
- } = state;
9883
9978
  if (name === OpenApiApiKeyInput) {
9884
9979
  return {
9885
9980
  ...state,
@@ -9896,10 +9991,10 @@ const handleInput = async (state, name, value, inputSource = 'user') => {
9896
9991
  return handleSearchValueChange(state, value);
9897
9992
  }
9898
9993
  if (name === ModelPickerSearch) {
9899
- const visibleModels = getVisibleModels(models, value);
9994
+ const visibleModels = getVisibleModels(state.models, value);
9900
9995
  return {
9901
9996
  ...state,
9902
- modelPickerHeight: getModelPickerHeight(modelPickerHeaderHeight, visibleModels.length),
9997
+ modelPickerHeight: getModelPickerHeight(state.modelPickerHeaderHeight, visibleModels.length),
9903
9998
  modelPickerListScrollTop: 0,
9904
9999
  modelPickerSearchValue: value,
9905
10000
  visibleModels
@@ -9908,19 +10003,20 @@ const handleInput = async (state, name, value, inputSource = 'user') => {
9908
10003
  if (name !== Composer) {
9909
10004
  return state;
9910
10005
  }
9911
- if (selectedSessionId) {
10006
+ if (state.selectedSessionId) {
9912
10007
  await appendChatViewEvent({
9913
- sessionId: selectedSessionId,
10008
+ sessionId: state.selectedSessionId,
9914
10009
  timestamp: new Date().toISOString(),
9915
10010
  type: 'handle-input',
9916
10011
  value
9917
10012
  });
9918
10013
  }
9919
10014
  const composerHeight = await getComposerHeight(state, value);
9920
- const composerAttachmentsHeight = getComposerAttachmentsHeight(composerAttachments, width);
10015
+ const composerAttachmentsHeight = getComposerAttachmentsHeight(state.composerAttachments, state.width);
10016
+ const chatInputHistoryDraft = state.chatInputHistoryIndex === -1 ? value : state.chatInputHistoryDraft;
9921
10017
  return {
9922
10018
  ...state,
9923
- chatInputHistoryDraft: chatInputHistoryIndex === -1 ? value : chatInputHistoryDraft,
10019
+ chatInputHistoryDraft,
9924
10020
  composerAttachmentsHeight,
9925
10021
  composerHeight,
9926
10022
  composerSelectionEnd: value.length,
@@ -9977,6 +10073,18 @@ const handleInputFocus = async (state, name) => {
9977
10073
  };
9978
10074
  };
9979
10075
 
10076
+ const getSubmittedRenameState = (state, sessions) => {
10077
+ return {
10078
+ ...state,
10079
+ composerHeight: getMinComposerHeightForState(state),
10080
+ composerSelectionEnd: 0,
10081
+ composerSelectionStart: 0,
10082
+ composerValue: '',
10083
+ inputSource: 'script',
10084
+ renamingSessionId: '',
10085
+ sessions
10086
+ };
10087
+ };
9980
10088
  const submitRename = async state => {
9981
10089
  const {
9982
10090
  composerValue,
@@ -9990,29 +10098,24 @@ const submitRename = async state => {
9990
10098
  renamingSessionId: ''
9991
10099
  };
9992
10100
  }
10101
+ const promptedTitle = sanitizeGeneratedTitle(await invoke('Main.prompt', title));
10102
+ if (!promptedTitle) {
10103
+ return getSubmittedRenameState(state, sessions);
10104
+ }
9993
10105
  const updatedSessions = sessions.map(session => {
9994
10106
  if (session.id !== renamingSessionId) {
9995
10107
  return session;
9996
10108
  }
9997
10109
  return {
9998
10110
  ...session,
9999
- title
10111
+ title: promptedTitle
10000
10112
  };
10001
10113
  });
10002
10114
  const renamedSession = updatedSessions.find(session => session.id === renamingSessionId);
10003
10115
  if (renamedSession) {
10004
10116
  await saveChatSession(renamedSession);
10005
10117
  }
10006
- return {
10007
- ...state,
10008
- composerHeight: getMinComposerHeightForState(state),
10009
- composerSelectionEnd: 0,
10010
- composerSelectionStart: 0,
10011
- composerValue: '',
10012
- inputSource: 'script',
10013
- renamingSessionId: '',
10014
- sessions: updatedSessions
10015
- };
10118
+ return getSubmittedRenameState(state, updatedSessions);
10016
10119
  };
10017
10120
 
10018
10121
  const handleKeyDown = async (state, key, shiftKey) => {
@@ -10142,7 +10245,7 @@ const handleProjectAddButtonContextMenu = async (state, button, x, y) => {
10142
10245
  return state;
10143
10246
  };
10144
10247
 
10145
- const getProjectIdAtIndex = (state, index) => {
10248
+ const getProjectAtIndex = (state, index) => {
10146
10249
  const {
10147
10250
  projectExpandedIds,
10148
10251
  projects,
@@ -10152,7 +10255,7 @@ const getProjectIdAtIndex = (state, index) => {
10152
10255
  let currentIndex = 0;
10153
10256
  for (const project of projects) {
10154
10257
  if (currentIndex === index) {
10155
- return project.id;
10258
+ return project;
10156
10259
  }
10157
10260
  currentIndex++;
10158
10261
  if (projectExpandedIds.includes(project.id)) {
@@ -10162,13 +10265,13 @@ const getProjectIdAtIndex = (state, index) => {
10162
10265
  continue;
10163
10266
  }
10164
10267
  if (currentIndex === index) {
10165
- return project.id;
10268
+ return project;
10166
10269
  }
10167
10270
  currentIndex++;
10168
10271
  }
10169
10272
  }
10170
10273
  }
10171
- return '';
10274
+ return undefined;
10172
10275
  };
10173
10276
  const handleProjectListContextMenu = async (state, button, x, y) => {
10174
10277
  const {
@@ -10181,13 +10284,14 @@ const handleProjectListContextMenu = async (state, button, x, y) => {
10181
10284
  if (index < 0) {
10182
10285
  return state;
10183
10286
  }
10184
- const projectId = getProjectIdAtIndex(state, index);
10185
- if (!projectId) {
10287
+ const project = getProjectAtIndex(state, index);
10288
+ if (!project) {
10186
10289
  return state;
10187
10290
  }
10188
10291
  await showContextMenu2(uid, MenuChatProjectList, x, y, {
10292
+ canRemoveProject: project.name !== '_blank',
10189
10293
  menuId: MenuChatProjectList,
10190
- projectId
10294
+ projectId: project.id
10191
10295
  });
10192
10296
  return state;
10193
10297
  };
@@ -11006,6 +11110,29 @@ const mockOpenApiStreamReset = state => {
11006
11110
  return state;
11007
11111
  };
11008
11112
 
11113
+ const openMockProject = async (state, projectId, projectName, projectUri) => {
11114
+ if (!projectId || !projectName) {
11115
+ return state;
11116
+ }
11117
+ const project = {
11118
+ id: projectId,
11119
+ name: projectName,
11120
+ uri: projectUri
11121
+ };
11122
+ const projects = state.projects.some(candidate => candidate.id === projectId) ? state.projects.map(candidate => {
11123
+ if (candidate.id !== projectId) {
11124
+ return candidate;
11125
+ }
11126
+ return project;
11127
+ }) : [...state.projects, project];
11128
+ return {
11129
+ ...state,
11130
+ projectExpandedIds: state.projectExpandedIds.includes(projectId) ? state.projectExpandedIds : [...state.projectExpandedIds, projectId],
11131
+ projects,
11132
+ selectedProjectId: projectId
11133
+ };
11134
+ };
11135
+
11009
11136
  const openMockSession = async (state, mockSessionId, mockChatMessages) => {
11010
11137
  const {
11011
11138
  sessions: currentSessions
@@ -11158,6 +11285,56 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
11158
11285
  border-color: var(--vscode-charts-green, var(--vscode-widget-border, var(--vscode-panel-border)));
11159
11286
  }
11160
11287
 
11288
+ .ChatAttachments{
11289
+ display: flex;
11290
+ flex-wrap: wrap;
11291
+ gap: 8px;
11292
+ margin-top: 8px;
11293
+ }
11294
+
11295
+ .ChatAttachment{
11296
+ align-items: center;
11297
+ display: inline-flex;
11298
+ gap: 6px;
11299
+ max-width: 100%;
11300
+ min-width: 0;
11301
+ overflow: hidden;
11302
+ border-radius: 999px;
11303
+ border: 1px solid var(--vscode-widget-border, var(--vscode-panel-border));
11304
+ padding: 4px 10px;
11305
+ background: var(--vscode-badge-background, color-mix(in srgb, var(--vscode-editor-background) 88%, white));
11306
+ color: var(--vscode-badge-foreground, var(--vscode-foreground));
11307
+ font-size: 12px;
11308
+ }
11309
+
11310
+ .ChatAttachmentLabel{
11311
+ min-width: 0;
11312
+ overflow: hidden;
11313
+ text-overflow: ellipsis;
11314
+ white-space: nowrap;
11315
+ }
11316
+
11317
+ .ChatAttachmentPreview{
11318
+ width: 20px;
11319
+ height: 20px;
11320
+ flex: none;
11321
+ border-radius: 4px;
11322
+ object-fit: cover;
11323
+ }
11324
+
11325
+ .ChatAttachmentImage{
11326
+ border-color: var(--vscode-charts-blue);
11327
+ }
11328
+
11329
+ .ChatAttachmentInvalidImage{
11330
+ border-color: var(--vscode-inputValidation-errorBorder, var(--vscode-errorForeground));
11331
+ color: var(--vscode-errorForeground, var(--vscode-foreground));
11332
+ }
11333
+
11334
+ .ChatAttachmentTextFile{
11335
+ border-color: var(--vscode-charts-green, var(--vscode-widget-border, var(--vscode-panel-border)));
11336
+ }
11337
+
11161
11338
  .Chat{
11162
11339
  position: relative;
11163
11340
  }
@@ -11232,6 +11409,13 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
11232
11409
  color: var(--vscode-textLink-foreground);
11233
11410
  }
11234
11411
 
11412
+ .ProjectListChevron{
11413
+ display: inline-block;
11414
+ flex: none;
11415
+ height: 16px;
11416
+ width: 16px;
11417
+ }
11418
+
11235
11419
  .ChatOrderedListItem{
11236
11420
  align-items: flex-start;
11237
11421
  display: flex;
@@ -11286,6 +11470,10 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
11286
11470
  justify-content: flex-start;
11287
11471
  }
11288
11472
 
11473
+ .ChatMessages > .MessageUser .ChatAttachments{
11474
+ justify-content: flex-end;
11475
+ }
11476
+
11289
11477
  .ChatFocus .ChatMessages > .Message{
11290
11478
  inline-size: fit-content;
11291
11479
  max-inline-size: min(100%, var(--ChatFocusContentMaxWidth));
@@ -11295,6 +11483,24 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
11295
11483
  max-inline-size: 100%;
11296
11484
  }
11297
11485
 
11486
+
11487
+ .Viewlet.Chat.ChatFocus{
11488
+ display: flex !important;
11489
+ min-width: 0;
11490
+ }
11491
+
11492
+ .ChatFocusMainArea{
11493
+ display: flex;
11494
+ flex: 1;
11495
+ flex-direction: column;
11496
+ min-width: 0;
11497
+ }
11498
+
11499
+ .ChatFocusMainArea > .ChatMessages{
11500
+ flex: 1;
11501
+ min-height: 0;
11502
+ }
11503
+
11298
11504
  `;
11299
11505
  return `${baseCss}
11300
11506
 
@@ -11869,6 +12075,10 @@ const getChatHeaderDomFocusMode = (selectedSessionTitle, selectedProjectName) =>
11869
12075
  }, ...items.flatMap(([label, name]) => getFocusHeaderActionButtonDom(label, name))];
11870
12076
  };
11871
12077
 
12078
+ const getAgentModeOptionsVirtualDom = selectedAgentMode => {
12079
+ return agentModes.flatMap(agentMode => getCustomSelectOptionVirtualDom(getAgentModePickerItemInputName(agentMode), getAgentModeLabel(agentMode), agentMode === selectedAgentMode));
12080
+ };
12081
+
11872
12082
  const getCustomSelectPopOverVirtualDom = (optionCount, height, optionNodes, containerClassName = '', popOverClassName = '') => {
11873
12083
  return [{
11874
12084
  childCount: 1,
@@ -11889,9 +12099,6 @@ const getCustomSelectPopOverVirtualDom = (optionCount, height, optionNodes, cont
11889
12099
  };
11890
12100
 
11891
12101
  const agentModePickerHeight = agentModes.length * 28;
11892
- const getAgentModeOptionsVirtualDom = selectedAgentMode => {
11893
- return agentModes.flatMap(agentMode => getCustomSelectOptionVirtualDom(getAgentModePickerItemInputName(agentMode), getAgentModeLabel(agentMode), agentMode === selectedAgentMode));
11894
- };
11895
12102
  const getAgentModePickerPopOverVirtualDom = selectedAgentMode => {
11896
12103
  return getCustomSelectPopOverVirtualDom(agentModes.length, agentModePickerHeight, getAgentModeOptionsVirtualDom(selectedAgentMode));
11897
12104
  };
@@ -12177,12 +12384,17 @@ const getTokenDom = token => {
12177
12384
 
12178
12385
  const getCodeBlockDom = node => {
12179
12386
  const tokenDom = node.codeTokens.flatMap(getTokenDom);
12387
+ const languageAttribute = node.language ? {
12388
+ 'data-lang': node.language
12389
+ } : {};
12180
12390
  return [{
12181
12391
  childCount: 1,
12182
- type: Pre
12392
+ type: Pre,
12393
+ ...languageAttribute
12183
12394
  }, {
12184
12395
  childCount: node.codeTokens.length,
12185
- type: Code
12396
+ type: Code,
12397
+ ...languageAttribute
12186
12398
  }, ...tokenDom];
12187
12399
  };
12188
12400
 
@@ -12675,11 +12887,22 @@ const getReadFileTarget = rawArguments => {
12675
12887
  };
12676
12888
  };
12677
12889
 
12678
- const getToolCallFileNameDom = (fileName, fileNameClickableProps = {}) => {
12890
+ const getToolCallFileNameDom = (fileName, {
12891
+ clickableProps = {},
12892
+ title
12893
+ } = {}) => {
12679
12894
  return [{
12895
+ childCount: 1,
12896
+ className: ChatToolCallReadFileLink,
12897
+ ...(title === undefined ? {} : {
12898
+ title
12899
+ }),
12900
+ ...clickableProps,
12901
+ type: Span
12902
+ }, {
12680
12903
  childCount: 1,
12681
12904
  className: ChatToolCallFileName,
12682
- ...fileNameClickableProps,
12905
+ ...clickableProps,
12683
12906
  type: Span
12684
12907
  }, text(fileName)];
12685
12908
  };
@@ -12708,75 +12931,9 @@ const getToolCallCreateDirectoryVirtualDom = toolCall => {
12708
12931
  childCount: 1,
12709
12932
  className: ToolCallName,
12710
12933
  type: Span
12711
- }, text('create_directory '), {
12712
- childCount: 1,
12713
- className: ChatToolCallReadFileLink,
12714
- ...fileNameClickableProps,
12715
- type: Span
12716
- }, ...getToolCallFileNameDom(directoryName, fileNameClickableProps), ...(statusLabel ? [text(statusLabel)] : [])];
12717
- };
12718
-
12719
- const getToolCallEditFileVirtualDom = toolCall => {
12720
- const target = getReadFileTarget(toolCall.arguments);
12721
- if (!target) {
12722
- return [];
12723
- }
12724
- const fileName = getFileNameFromUri(target.title);
12725
- const fileNameClickableProps = target.clickableUri ? {
12726
- 'data-uri': target.clickableUri,
12727
- onClick: HandleClickFileName
12728
- } : {};
12729
- return [{
12730
- childCount: 3,
12731
- className: ChatOrderedListItem,
12732
- title: target.title,
12733
- type: Li
12734
- }, {
12735
- childCount: 0,
12736
- className: FileIcon,
12737
- type: Div
12738
- }, {
12739
- childCount: 1,
12740
- className: ToolCallName,
12741
- type: Span
12742
- }, text('edit_file '), {
12743
- childCount: 1,
12744
- className: ChatToolCallReadFileLink,
12745
- title: target.clickableUri,
12746
- ...fileNameClickableProps,
12747
- type: Span
12748
- }, ...getToolCallFileNameDom(fileName, fileNameClickableProps)];
12749
- };
12750
-
12751
- const getToolCallGetWorkspaceUriVirtualDom = toolCall => {
12752
- if (!toolCall.result) {
12753
- return [];
12754
- }
12755
- const statusLabel = getToolCallStatusLabel(toolCall);
12756
- const fileName = getFileNameFromUri(toolCall.result);
12757
- const fileNameClickableProps = {
12758
- 'data-uri': toolCall.result,
12759
- onClick: HandleClickFileName
12760
- };
12761
- return [{
12762
- childCount: statusLabel ? 4 : 3,
12763
- className: ChatOrderedListItem,
12764
- title: toolCall.result,
12765
- type: Li
12766
- }, {
12767
- childCount: 0,
12768
- className: FileIcon,
12769
- type: Div
12770
- }, {
12771
- childCount: 1,
12772
- className: ToolCallName,
12773
- type: Span
12774
- }, text('get_workspace_uri '), {
12775
- childCount: 1,
12776
- className: ChatToolCallReadFileLink,
12777
- ...fileNameClickableProps,
12778
- type: Span
12779
- }, ...getToolCallFileNameDom(fileName, fileNameClickableProps), ...(statusLabel ? [text(statusLabel)] : [])];
12934
+ }, text('create_directory '), ...getToolCallFileNameDom(directoryName, {
12935
+ clickableProps: fileNameClickableProps
12936
+ }), ...(statusLabel ? [text(statusLabel)] : [])];
12780
12937
  };
12781
12938
 
12782
12939
  const getToolCallArgumentPreview = rawArguments => {
@@ -12853,6 +13010,85 @@ const getToolCallLabel = toolCall => {
12853
13010
  return `${displayName} ${argumentPreview}${statusLabel}`;
12854
13011
  };
12855
13012
 
13013
+ const RE_TOOL_NAME_PREFIX = /^([^ :]+)/;
13014
+ const getToolCallDefaultDom = toolCall => {
13015
+ const label = getToolCallLabel(toolCall);
13016
+ const match = RE_TOOL_NAME_PREFIX.exec(label);
13017
+ const toolNamePrefix = match ? match[1] : label;
13018
+ const suffix = label.slice(toolNamePrefix.length);
13019
+ const hasSuffix = suffix.length > 0;
13020
+ const hoverTitle = hasSuffix && toolCall.arguments.trim() ? toolCall.arguments : undefined;
13021
+ return [{
13022
+ childCount: hasSuffix ? 2 : 1,
13023
+ className: ChatOrderedListItem,
13024
+ ...(hoverTitle ? {
13025
+ title: hoverTitle
13026
+ } : {}),
13027
+ type: Li
13028
+ }, {
13029
+ childCount: 1,
13030
+ className: ToolCallName,
13031
+ type: Span
13032
+ }, text(toolNamePrefix), ...(hasSuffix ? [text(suffix)] : [])];
13033
+ };
13034
+
13035
+ const getToolCallEditFileVirtualDom = toolCall => {
13036
+ const target = getReadFileTarget(toolCall.arguments);
13037
+ if (!target) {
13038
+ return [];
13039
+ }
13040
+ const fileName = getFileNameFromUri(target.title);
13041
+ const fileNameClickableProps = target.clickableUri ? {
13042
+ 'data-uri': target.clickableUri,
13043
+ onClick: HandleClickFileName
13044
+ } : {};
13045
+ return [{
13046
+ childCount: 3,
13047
+ className: ChatOrderedListItem,
13048
+ title: target.title,
13049
+ type: Li
13050
+ }, {
13051
+ childCount: 0,
13052
+ className: FileIcon,
13053
+ type: Div
13054
+ }, {
13055
+ childCount: 1,
13056
+ className: ToolCallName,
13057
+ type: Span
13058
+ }, text('edit_file '), ...getToolCallFileNameDom(fileName, {
13059
+ clickableProps: fileNameClickableProps,
13060
+ title: target.clickableUri
13061
+ })];
13062
+ };
13063
+
13064
+ const getToolCallGetWorkspaceUriVirtualDom = toolCall => {
13065
+ if (!toolCall.result) {
13066
+ return [];
13067
+ }
13068
+ const statusLabel = getToolCallStatusLabel(toolCall);
13069
+ const fileName = getFileNameFromUri(toolCall.result);
13070
+ const fileNameClickableProps = {
13071
+ 'data-uri': toolCall.result,
13072
+ onClick: HandleClickFileName
13073
+ };
13074
+ return [{
13075
+ childCount: statusLabel ? 4 : 3,
13076
+ className: ChatOrderedListItem,
13077
+ title: toolCall.result,
13078
+ type: Li
13079
+ }, {
13080
+ childCount: 0,
13081
+ className: FileIcon,
13082
+ type: Div
13083
+ }, {
13084
+ childCount: 1,
13085
+ className: ToolCallName,
13086
+ type: Span
13087
+ }, text('get_workspace_uri '), ...getToolCallFileNameDom(fileName, {
13088
+ clickableProps: fileNameClickableProps
13089
+ }), ...(statusLabel ? [text(statusLabel)] : [])];
13090
+ };
13091
+
12856
13092
  const getToolCallReadFileVirtualDom = toolCall => {
12857
13093
  const target = getReadFileTarget(toolCall.arguments);
12858
13094
  if (!target) {
@@ -12878,12 +13114,9 @@ const getToolCallReadFileVirtualDom = toolCall => {
12878
13114
  childCount: 1,
12879
13115
  className: ToolCallName,
12880
13116
  type: Span
12881
- }, text(toolNameLabel), {
12882
- childCount: 1,
12883
- className: ChatToolCallReadFileLink,
12884
- ...fileNameClickableProps,
12885
- type: Span
12886
- }, ...getToolCallFileNameDom(fileName, fileNameClickableProps), ...(statusLabel ? [text(statusLabel)] : [])];
13117
+ }, text(toolNameLabel), ...getToolCallFileNameDom(fileName, {
13118
+ clickableProps: fileNameClickableProps
13119
+ }), ...(statusLabel ? [text(statusLabel)] : [])];
12887
13120
  };
12888
13121
 
12889
13122
  const maxHtmlLength = 40_000;
@@ -13260,12 +13493,9 @@ const getToolCallWriteFileVirtualDom = toolCall => {
13260
13493
  childCount: 1,
13261
13494
  className: ToolCallName,
13262
13495
  type: Span
13263
- }, text('write_file '), {
13264
- childCount: 1,
13265
- className: ChatToolCallReadFileLink,
13266
- ...fileNameClickableProps,
13267
- type: Span
13268
- }, ...getToolCallFileNameDom(fileName, fileNameClickableProps), ...(showDiffStats ? [{
13496
+ }, text('write_file '), ...getToolCallFileNameDom(fileName, {
13497
+ clickableProps: fileNameClickableProps
13498
+ }), ...(showDiffStats ? [{
13269
13499
  childCount: 1,
13270
13500
  className: Insertion,
13271
13501
  type: Span
@@ -13276,7 +13506,6 @@ const getToolCallWriteFileVirtualDom = toolCall => {
13276
13506
  }, text(` -${linesDeleted}`)] : []), ...(statusLabel ? [text(statusLabel)] : [])];
13277
13507
  };
13278
13508
 
13279
- const RE_TOOL_NAME_PREFIX = /^([^ :]+)/;
13280
13509
  const getToolCallDom = toolCall => {
13281
13510
  if (toolCall.name === 'getWorkspaceUri') {
13282
13511
  const virtualDom = getToolCallGetWorkspaceUriVirtualDom(toolCall);
@@ -13320,24 +13549,7 @@ const getToolCallDom = toolCall => {
13320
13549
  return virtualDom;
13321
13550
  }
13322
13551
  }
13323
- const label = getToolCallLabel(toolCall);
13324
- const match = RE_TOOL_NAME_PREFIX.exec(label);
13325
- const toolNamePrefix = match ? match[1] : label;
13326
- const suffix = label.slice(toolNamePrefix.length);
13327
- const hasSuffix = suffix.length > 0;
13328
- const hoverTitle = hasSuffix && toolCall.arguments.trim() ? toolCall.arguments : undefined;
13329
- return [{
13330
- childCount: hasSuffix ? 2 : 1,
13331
- className: ChatOrderedListItem,
13332
- ...(hoverTitle ? {
13333
- title: hoverTitle
13334
- } : {}),
13335
- type: Li
13336
- }, {
13337
- childCount: 1,
13338
- className: ToolCallName,
13339
- type: Span
13340
- }, text(toolNamePrefix), ...(hasSuffix ? [text(suffix)] : [])];
13552
+ return getToolCallDefaultDom(toolCall);
13341
13553
  };
13342
13554
 
13343
13555
  const withOrderedListMarker = (virtualDom, index) => {
@@ -13395,6 +13607,70 @@ const getTopLevelNodeCount = nodes => {
13395
13607
  return topLevelCount;
13396
13608
  };
13397
13609
 
13610
+ const getChatAttachmentLabel = displayType => {
13611
+ switch (displayType) {
13612
+ case 'file':
13613
+ return 'File';
13614
+ case 'image':
13615
+ return 'Image';
13616
+ case 'invalid-image':
13617
+ return 'Invalid image';
13618
+ case 'text-file':
13619
+ return 'Text file';
13620
+ default:
13621
+ return displayType;
13622
+ }
13623
+ };
13624
+ const getChatAttachmentClassName = displayType => {
13625
+ switch (displayType) {
13626
+ case 'file':
13627
+ return ChatAttachment;
13628
+ case 'image':
13629
+ return ChatAttachmentImage;
13630
+ case 'invalid-image':
13631
+ return ChatAttachmentInvalidImage;
13632
+ case 'text-file':
13633
+ return ChatAttachmentTextFile;
13634
+ default:
13635
+ return ChatAttachment;
13636
+ }
13637
+ };
13638
+ const getChatAttachmentPreviewDom = attachment => {
13639
+ if (!attachment.previewSrc) {
13640
+ return [];
13641
+ }
13642
+ return [{
13643
+ alt: `Attachment preview for ${attachment.name}`,
13644
+ childCount: 0,
13645
+ className: ChatAttachmentPreview,
13646
+ src: attachment.previewSrc,
13647
+ type: Img
13648
+ }];
13649
+ };
13650
+ const getChatAttachmentsDom = attachments => {
13651
+ if (attachments.length === 0) {
13652
+ return [];
13653
+ }
13654
+ return [{
13655
+ childCount: attachments.length,
13656
+ className: ChatAttachments,
13657
+ type: Div
13658
+ }, ...attachments.flatMap(attachment => {
13659
+ const previewDom = getChatAttachmentPreviewDom(attachment);
13660
+ return [{
13661
+ childCount: 1 + previewDom.length,
13662
+ className: mergeClassNames(ChatAttachment, getChatAttachmentClassName(attachment.displayType)),
13663
+ type: Div
13664
+ }, ...previewDom, {
13665
+ childCount: 1,
13666
+ className: ChatAttachmentLabel,
13667
+ type: Span
13668
+ }, {
13669
+ text: `${getChatAttachmentLabel(attachment.displayType)} · ${attachment.name}`,
13670
+ type: Text
13671
+ }];
13672
+ })];
13673
+ };
13398
13674
  const getChatMessageDom = (message, parsedMessageContent, _openRouterApiKeyInput, _openApiApiKeyInput = '', openApiApiKeyState = 'idle', openApiApiKeysSettingsUrl = 'https://platform.openai.com/api-keys', openApiApiKeyInputPattern = '^sk-.+', openRouterApiKeyState = 'idle', useChatMathWorker = false) => {
13399
13675
  const roleClassName = message.role === 'user' ? MessageUser : MessageAssistant;
13400
13676
  const isOpenApiApiKeyMissingMessage = message.role === 'assistant' && message.text === openApiApiKeyRequiredMessage;
@@ -13402,10 +13678,12 @@ const getChatMessageDom = (message, parsedMessageContent, _openRouterApiKeyInput
13402
13678
  const isOpenRouterRequestFailedMessage = message.role === 'assistant' && message.text === openRouterRequestFailedMessage;
13403
13679
  const isOpenRouterTooManyRequestsMessage = message.role === 'assistant' && message.text.startsWith(openRouterTooManyRequestsMessage);
13404
13680
  const messageDom = getMessageContentDom(parsedMessageContent, useChatMathWorker);
13681
+ const attachmentsDom = message.role === 'user' ? getChatAttachmentsDom(message.attachments ?? []) : [];
13405
13682
  const toolCallsDom = getToolCallsDom(message);
13406
13683
  const toolCallsChildCount = toolCallsDom.length > 0 ? 1 : 0;
13407
13684
  const messageDomChildCount = getTopLevelNodeCount(messageDom);
13408
- const extraChildCount = isOpenApiApiKeyMissingMessage || isOpenRouterApiKeyMissingMessage || isOpenRouterRequestFailedMessage || isOpenRouterTooManyRequestsMessage ? messageDomChildCount + 1 + toolCallsChildCount : messageDomChildCount + toolCallsChildCount;
13685
+ const attachmentsChildCount = attachmentsDom.length > 0 ? 1 : 0;
13686
+ const extraChildCount = isOpenApiApiKeyMissingMessage || isOpenRouterApiKeyMissingMessage || isOpenRouterRequestFailedMessage || isOpenRouterTooManyRequestsMessage ? messageDomChildCount + 1 + toolCallsChildCount + attachmentsChildCount : messageDomChildCount + toolCallsChildCount + attachmentsChildCount;
13409
13687
  return [{
13410
13688
  childCount: 1,
13411
13689
  className: mergeClassNames(Message, roleClassName),
@@ -13414,7 +13692,7 @@ const getChatMessageDom = (message, parsedMessageContent, _openRouterApiKeyInput
13414
13692
  childCount: extraChildCount,
13415
13693
  className: ChatMessageContent,
13416
13694
  type: Div
13417
- }, ...toolCallsDom, ...messageDom, ...(isOpenApiApiKeyMissingMessage ? getMissingOpenApiApiKeyDom(openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern) : []), ...(isOpenRouterApiKeyMissingMessage ? getMissingOpenRouterApiKeyDom(openRouterApiKeyState) : []), ...(isOpenRouterRequestFailedMessage ? getOpenRouterRequestFailedDom() : []), ...(isOpenRouterTooManyRequestsMessage ? getOpenRouterTooManyRequestsDom() : [])];
13695
+ }, ...toolCallsDom, ...messageDom, ...attachmentsDom, ...(isOpenApiApiKeyMissingMessage ? getMissingOpenApiApiKeyDom(openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern) : []), ...(isOpenRouterApiKeyMissingMessage ? getMissingOpenRouterApiKeyDom(openRouterApiKeyState) : []), ...(isOpenRouterRequestFailedMessage ? getOpenRouterRequestFailedDom() : []), ...(isOpenRouterTooManyRequestsMessage ? getOpenRouterTooManyRequestsDom() : [])];
13418
13696
  };
13419
13697
 
13420
13698
  const parentNode$1 = {
@@ -13470,7 +13748,18 @@ const getDisplayMessages = (messages, parsedMessages) => {
13470
13748
  };
13471
13749
  const getMessagesDom = (messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput = '', openApiApiKeyState = 'idle', openApiApiKeysSettingsUrl = 'https://platform.openai.com/api-keys', openApiApiKeyInputPattern = '^sk-.+', openRouterApiKeyState = 'idle', messagesScrollTop = 0, useChatMathWorker = false, hideWelcomeMessage = false) => {
13472
13750
  if (messages.length === 0) {
13473
- return hideWelcomeMessage ? [] : getEmptyMessagesDom();
13751
+ if (!hideWelcomeMessage) {
13752
+ return getEmptyMessagesDom();
13753
+ }
13754
+ return [{
13755
+ childCount: 0,
13756
+ className: 'ChatMessages',
13757
+ onContextMenu: HandleMessagesContextMenu,
13758
+ onScroll: HandleMessagesScroll,
13759
+ role: 'log',
13760
+ scrollTop: messagesScrollTop,
13761
+ type: Div
13762
+ }];
13474
13763
  }
13475
13764
  const displayMessages = getDisplayMessages(messages, parsedMessages);
13476
13765
  return [{
@@ -13537,10 +13826,10 @@ const getProjectGroupDom = (project, sessions, projectExpandedIds, selectedProje
13537
13826
  tabIndex: 0,
13538
13827
  type: Div
13539
13828
  }, {
13540
- childCount: 1,
13541
- className: ProjectListChevron,
13542
- type: Span
13543
- }, text(expanded ? '▾' : '▸'), {
13829
+ childCount: 0,
13830
+ className: mergeClassNames(ProjectListChevron, MaskIcon, expanded ? MaskIconChevronDown : MaskIconChevronRight),
13831
+ type: Div
13832
+ }, {
13544
13833
  childCount: 0,
13545
13834
  className: 'MaskIcon MaskIconFolder',
13546
13835
  type: Div
@@ -13655,14 +13944,18 @@ const getChatModeChatFocusVirtualDom = ({
13655
13944
  const isNewModelPickerVisible = modelPickerOpen;
13656
13945
  const isRunModePickerVisible = showRunMode && hasSpaceForRunModePicker && runModePickerOpen;
13657
13946
  const hasVisibleOverlays = isDropOverlayVisible || isComposerAttachmentPreviewOverlayVisible || isAgentModePickerVisible || isNewModelPickerVisible || isRunModePickerVisible;
13658
- const chatRootChildCount = 4 + (hasVisibleOverlays ? 1 : 0);
13947
+ const chatRootChildCount = 2 + (hasVisibleOverlays ? 1 : 0);
13659
13948
  return [{
13660
13949
  childCount: chatRootChildCount,
13661
13950
  className: mergeClassNames(Viewlet, Chat, ChatFocus),
13662
13951
  onDragEnter: HandleDragEnterChatView,
13663
13952
  onDragOver: HandleDragOverChatView,
13664
13953
  type: Div
13665
- }, ...getChatHeaderDomFocusMode(selectedSessionTitle, selectedProjectName), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop, true), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton, voiceDictationEnabled, scrollDownButtonEnabled, messagesAutoScrollEnabled), ...getChatOverlaysVirtualDom({
13954
+ }, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop, true), {
13955
+ childCount: 3,
13956
+ className: ChatFocusMainArea,
13957
+ type: Div
13958
+ }, ...getChatHeaderDomFocusMode(selectedSessionTitle, selectedProjectName), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton, voiceDictationEnabled, scrollDownButtonEnabled, messagesAutoScrollEnabled), ...getChatOverlaysVirtualDom({
13666
13959
  agentMode,
13667
13960
  agentModePickerVisible: isAgentModePickerVisible,
13668
13961
  composerAttachmentPreviewOverlayAttachmentId,
@@ -13715,22 +14008,31 @@ const getHeaderActionVirtualDom = item => {
13715
14008
  }];
13716
14009
  };
13717
14010
 
13718
- const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'signed-out', searchEnabled = false) => {
13719
- const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
14011
+ const getAuthAction = (authEnabled, authStatus) => {
13720
14012
  const isSigningIn = authStatus === 'signing-in';
13721
- const authAction = authEnabled && authStatus !== 'signed-in' ? {
13722
- disabled: isSigningIn,
13723
- icon: mergeClassNames(MaskIcon, MaskIconAccount),
13724
- name: Login,
13725
- onClick: HandleClick,
13726
- title: isSigningIn ? loggingInToBackend() : loginToBackend()
13727
- } : authEnabled ? {
14013
+ if (!authEnabled) {
14014
+ return undefined;
14015
+ }
14016
+ if (authStatus !== 'signed-in') {
14017
+ return {
14018
+ disabled: isSigningIn,
14019
+ icon: mergeClassNames(MaskIcon, MaskIconAccount),
14020
+ name: Login,
14021
+ onClick: HandleClick,
14022
+ title: isSigningIn ? loggingInToBackend() : loginToBackend()
14023
+ };
14024
+ }
14025
+ return {
13728
14026
  disabled: false,
13729
14027
  icon: mergeClassNames(MaskIcon, MaskIconSignOut),
13730
14028
  name: Logout,
13731
14029
  onClick: HandleClick,
13732
14030
  title: logoutFromBackend()
13733
- } : undefined;
14031
+ };
14032
+ };
14033
+ const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'signed-out', searchEnabled = false) => {
14034
+ const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
14035
+ const authAction = getAuthAction(authEnabled, authStatus);
13734
14036
  const items = [{
13735
14037
  icon: mergeClassNames(MaskIcon, MaskIconLayoutPanelLeft),
13736
14038
  name: ToggleChatFocus,
@@ -15192,6 +15494,7 @@ const commandMap = {
15192
15494
  'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
15193
15495
  'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
15194
15496
  'Chat.openAgentModePicker': wrapCommand(openAgentModePicker),
15497
+ 'Chat.openMockProject': wrapCommand(openMockProject),
15195
15498
  'Chat.openMockSession': wrapCommand(openMockSession),
15196
15499
  'Chat.openModelPicker': wrapCommand(openModelPicker),
15197
15500
  'Chat.openReasoningEffortPicker': wrapCommand(openReasoningEffortPicker),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "6.67.0",
3
+ "version": "6.69.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",