@lvce-editor/chat-view 6.6.0 → 6.7.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.
@@ -1492,6 +1492,15 @@ const backToChats = () => {
1492
1492
  const settings = () => {
1493
1493
  return i18nString('Settings');
1494
1494
  };
1495
+ const loginToBackend = () => {
1496
+ return i18nString('Login to backend');
1497
+ };
1498
+ const logoutFromBackend = () => {
1499
+ return i18nString('Logout from backend');
1500
+ };
1501
+ const loggingInToBackend = () => {
1502
+ return i18nString('Logging in to backend');
1503
+ };
1495
1504
  const chatFocusMode = () => {
1496
1505
  return i18nString('Switch to chat focus mode');
1497
1506
  };
@@ -1651,6 +1660,12 @@ const createDefaultState = () => {
1651
1660
  return {
1652
1661
  aiSessionTitleGenerationEnabled: false,
1653
1662
  assetDir: '',
1663
+ authAccessToken: '',
1664
+ authEnabled: false,
1665
+ authErrorMessage: '',
1666
+ authRefreshToken: '',
1667
+ authStatus: 'signed-out',
1668
+ backendUrl: '',
1654
1669
  chatListScrollTop: 0,
1655
1670
  chatMessageFontFamily: 'system-ui',
1656
1671
  chatMessageFontSize,
@@ -1719,6 +1734,9 @@ const createDefaultState = () => {
1719
1734
  useChatNetworkWorkerForRequests: false,
1720
1735
  useChatToolWorker: false,
1721
1736
  useMockApi: false,
1737
+ userName: '',
1738
+ userSubscriptionPlan: '',
1739
+ userUsedTokens: 0,
1722
1740
  viewMode: 'list',
1723
1741
  voiceDictationEnabled: false,
1724
1742
  warningCount: 0,
@@ -2522,7 +2540,7 @@ const isEqualProjectExpandedIds = (a, b) => {
2522
2540
  return true;
2523
2541
  };
2524
2542
  const isEqual = (oldState, newState) => {
2525
- return oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && oldState.projectListScrollTop === newState.projectListScrollTop && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
2543
+ return 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 && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && oldState.projectListScrollTop === newState.projectListScrollTop && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
2526
2544
  };
2527
2545
 
2528
2546
  const diffScrollTop = (oldState, newState) => {
@@ -2567,6 +2585,20 @@ const diff2 = uid => {
2567
2585
  return result;
2568
2586
  };
2569
2587
 
2588
+ const getAuthState = state => {
2589
+ return {
2590
+ authAccessToken: state.authAccessToken,
2591
+ authEnabled: state.authEnabled,
2592
+ authErrorMessage: state.authErrorMessage,
2593
+ authRefreshToken: state.authRefreshToken,
2594
+ authStatus: state.authStatus,
2595
+ backendUrl: state.backendUrl,
2596
+ userName: state.userName,
2597
+ userSubscriptionPlan: state.userSubscriptionPlan,
2598
+ userUsedTokens: state.userUsedTokens
2599
+ };
2600
+ };
2601
+
2570
2602
  const mergeClassNames = (...classNames) => {
2571
2603
  return classNames.filter(Boolean).join(' ');
2572
2604
  };
@@ -3138,6 +3170,130 @@ const handleClickCreateProject = async state => {
3138
3170
  };
3139
3171
  };
3140
3172
 
3173
+ let nextLoginResponse;
3174
+ const setNextLoginResponse = response => {
3175
+ nextLoginResponse = response;
3176
+ };
3177
+ const hasPendingMockLoginResponse = () => {
3178
+ return !!nextLoginResponse;
3179
+ };
3180
+ const consumeNextLoginResponse = async () => {
3181
+ if (!nextLoginResponse) {
3182
+ return undefined;
3183
+ }
3184
+ const response = nextLoginResponse;
3185
+ nextLoginResponse = undefined;
3186
+ if (response.delay > 0) {
3187
+ await new Promise(resolve => setTimeout(resolve, response.delay));
3188
+ }
3189
+ if (response.type === 'error') {
3190
+ throw new Error(response.message);
3191
+ }
3192
+ return response.response;
3193
+ };
3194
+
3195
+ const get = async key => {
3196
+ return getPreference(key);
3197
+ };
3198
+ const update = async settings => {
3199
+ await invoke$1('Preferences.update', settings);
3200
+ };
3201
+
3202
+ const isLoginResponse = value => {
3203
+ if (!value || typeof value !== 'object') {
3204
+ return false;
3205
+ }
3206
+ return true;
3207
+ };
3208
+ const trimTrailingSlashes = value => {
3209
+ return value.replace(/\/+$/, '');
3210
+ };
3211
+ const handleClickLogin = async state => {
3212
+ if (!state.backendUrl) {
3213
+ return {
3214
+ ...state,
3215
+ authErrorMessage: 'Backend URL is missing.',
3216
+ authStatus: 'signed-out'
3217
+ };
3218
+ }
3219
+ const signingInState = {
3220
+ ...state,
3221
+ authErrorMessage: '',
3222
+ authStatus: 'signing-in'
3223
+ };
3224
+ if (state.uid) {
3225
+ set$1(state.uid, state, signingInState);
3226
+ await invoke$1('Chat.rerender');
3227
+ }
3228
+ let usedMockResponse = false;
3229
+ try {
3230
+ usedMockResponse = hasPendingMockLoginResponse();
3231
+ const response = usedMockResponse ? await consumeNextLoginResponse() : await invoke$1('Auth.login', state.backendUrl);
3232
+ if (!isLoginResponse(response)) {
3233
+ return {
3234
+ ...signingInState,
3235
+ authErrorMessage: 'Backend returned an invalid login response.',
3236
+ authStatus: 'signed-out'
3237
+ };
3238
+ }
3239
+ if (typeof response.error === 'string' && response.error) {
3240
+ return {
3241
+ ...signingInState,
3242
+ authErrorMessage: response.error,
3243
+ authStatus: 'signed-out'
3244
+ };
3245
+ }
3246
+ const accessToken = typeof response.accessToken === 'string' ? response.accessToken : '';
3247
+ const refreshToken = typeof response.refreshToken === 'string' ? response.refreshToken : '';
3248
+ await update({
3249
+ 'secrets.chatBackendAccessToken': accessToken,
3250
+ 'secrets.chatBackendRefreshToken': refreshToken
3251
+ });
3252
+ return {
3253
+ ...signingInState,
3254
+ authAccessToken: accessToken,
3255
+ authErrorMessage: '',
3256
+ authRefreshToken: refreshToken,
3257
+ authStatus: accessToken ? 'signed-in' : 'signed-out',
3258
+ userName: typeof response.userName === 'string' ? response.userName : state.userName,
3259
+ userSubscriptionPlan: typeof response.subscriptionPlan === 'string' ? response.subscriptionPlan : state.userSubscriptionPlan,
3260
+ userUsedTokens: typeof response.usedTokens === 'number' ? response.usedTokens : state.userUsedTokens
3261
+ };
3262
+ } catch (error) {
3263
+ const errorMessage = error instanceof Error && error.message ? error.message : 'Backend authentication failed.';
3264
+ if (!usedMockResponse) {
3265
+ await invoke$1('Main.openUri', `${trimTrailingSlashes(state.backendUrl)}/auth/login`);
3266
+ }
3267
+ return {
3268
+ ...signingInState,
3269
+ authErrorMessage: errorMessage,
3270
+ authStatus: 'signed-out'
3271
+ };
3272
+ }
3273
+ };
3274
+
3275
+ const handleClickLogout = async state => {
3276
+ try {
3277
+ await invoke$1('Auth.logout', state.backendUrl);
3278
+ } catch {
3279
+ // Ignore logout bridge errors and still clear local auth state.
3280
+ }
3281
+ await update({
3282
+ 'secrets.chatBackendAccessToken': '',
3283
+ 'secrets.chatBackendRefreshToken': ''
3284
+ });
3285
+ return {
3286
+ ...state,
3287
+ authAccessToken: '',
3288
+ authErrorMessage: '',
3289
+ authRefreshToken: '',
3290
+ authStatus: 'signed-out',
3291
+ userName: '',
3292
+ userSubscriptionPlan: '',
3293
+ userUsedTokens: 0
3294
+ };
3295
+ };
3296
+
3141
3297
  const handleClickOpenApiApiKeySettings = async state => {
3142
3298
  await invoke$1('Main.openUri', 'app://settings.json');
3143
3299
  return state;
@@ -3166,6 +3322,9 @@ const openRouterRequestFailedMessage = 'OpenRouter request failed. Possible reas
3166
3322
  const openRouterTooManyRequestsMessage = 'OpenRouter rate limit reached (429). Please try again soon. Helpful tips:';
3167
3323
  const openRouterRequestFailureReasons = ['ContentSecurityPolicyViolation: Check DevTools for details.', 'OpenRouter server offline: Check DevTools for details.', 'Check your internet connection.'];
3168
3324
  const openRouterTooManyRequestsReasons = ['Wait a short time and retry your request.', 'Reduce request frequency to avoid rate limits.', 'Use a different model if this one is saturated.'];
3325
+ const backendUrlRequiredMessage = 'Backend URL is not configured. Configure your backend URL and try again.';
3326
+ const backendAccessTokenRequiredMessage = 'You are not logged in. Click Login to continue.';
3327
+ const backendCompletionFailedMessage = 'Backend completion request failed.';
3169
3328
 
3170
3329
  let rpc;
3171
3330
  const set = value => {
@@ -5463,8 +5622,51 @@ const getAll = () => {
5463
5622
 
5464
5623
  /* eslint-disable prefer-destructuring */
5465
5624
 
5625
+ const getBackendCompletionsEndpoint = backendUrl => {
5626
+ const trimmedBackendUrl = backendUrl.replace(/\/+$/, '');
5627
+ return `${trimmedBackendUrl}/v1/chat/completions`;
5628
+ };
5629
+ const getEffectiveBackendModelId = selectedModelId => {
5630
+ const separatorIndex = selectedModelId.indexOf('/');
5631
+ if (separatorIndex === -1) {
5632
+ return selectedModelId;
5633
+ }
5634
+ return selectedModelId.slice(separatorIndex + 1);
5635
+ };
5636
+ const getBackendAssistantText = async (messages, selectedModelId, backendUrl, authAccessToken) => {
5637
+ let response;
5638
+ try {
5639
+ response = await fetch(getBackendCompletionsEndpoint(backendUrl), {
5640
+ body: JSON.stringify({
5641
+ messages: messages.map(message => ({
5642
+ content: message.text,
5643
+ role: message.role
5644
+ })),
5645
+ model: getEffectiveBackendModelId(selectedModelId),
5646
+ stream: false
5647
+ }),
5648
+ headers: {
5649
+ Authorization: `Bearer ${authAccessToken}`,
5650
+ 'Content-Type': 'application/json',
5651
+ ...getClientRequestIdHeader()
5652
+ },
5653
+ method: 'POST'
5654
+ });
5655
+ } catch {
5656
+ return backendCompletionFailedMessage;
5657
+ }
5658
+ if (!response.ok) {
5659
+ return backendCompletionFailedMessage;
5660
+ }
5661
+ const json = await response.json();
5662
+ const content = json.choices?.[0]?.message?.content;
5663
+ return typeof content === 'string' && content ? content : backendCompletionFailedMessage;
5664
+ };
5466
5665
  const getAiResponse = async ({
5467
5666
  assetDir,
5667
+ authAccessToken,
5668
+ authEnabled = false,
5669
+ backendUrl = '',
5468
5670
  messageId,
5469
5671
  messages,
5470
5672
  mockAiResponseDelay = 800,
@@ -5490,7 +5692,7 @@ const getAiResponse = async ({
5490
5692
  userText,
5491
5693
  webSearchEnabled = false
5492
5694
  }) => {
5493
- if (useChatCoordinatorWorker) {
5695
+ if (useChatCoordinatorWorker && !authEnabled) {
5494
5696
  try {
5495
5697
  const result = await getAiResponse$1({
5496
5698
  assetDir,
@@ -5530,9 +5732,18 @@ const getAiResponse = async ({
5530
5732
  }
5531
5733
  }
5532
5734
  let text = '';
5735
+ if (authEnabled) {
5736
+ if (!backendUrl) {
5737
+ text = backendUrlRequiredMessage;
5738
+ } else if (authAccessToken) {
5739
+ text = await getBackendAssistantText(messages, selectedModelId, backendUrl, authAccessToken);
5740
+ } else {
5741
+ text = backendAccessTokenRequiredMessage;
5742
+ }
5743
+ }
5533
5744
  const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
5534
5745
  const usesOpenRouterModel = isOpenRouterModel(selectedModelId, models);
5535
- if (usesOpenApiModel) {
5746
+ if (!text && usesOpenApiModel) {
5536
5747
  if (useMockApi) {
5537
5748
  const openAiInput = messages.map(message => ({
5538
5749
  content: message.text,
@@ -5610,7 +5821,7 @@ const getAiResponse = async ({
5610
5821
  } else {
5611
5822
  text = openApiApiKeyRequiredMessage;
5612
5823
  }
5613
- } else if (usesOpenRouterModel) {
5824
+ } else if (!text && usesOpenRouterModel) {
5614
5825
  const modelId = getOpenRouterModelId(selectedModelId);
5615
5826
  if (useMockApi) {
5616
5827
  const result = await getMockOpenRouterAssistantText(messages, modelId, openRouterApiBaseUrl, openRouterApiKey, mockApiCommandId, assetDir, platform);
@@ -5652,13 +5863,6 @@ const getAiResponse = async ({
5652
5863
  return message;
5653
5864
  };
5654
5865
 
5655
- const get = async key => {
5656
- return getPreference(key);
5657
- };
5658
- const update = async settings => {
5659
- await invoke$1('Preferences.update', settings);
5660
- };
5661
-
5662
5866
  const setOpenApiApiKey = async (state, openApiApiKey, persist = true) => {
5663
5867
  if (persist) {
5664
5868
  await update({
@@ -6824,6 +7028,9 @@ const sanitizeGeneratedTitle = value => {
6824
7028
 
6825
7029
  const getAiSessionTitle = async (state, userText, assistantText) => {
6826
7030
  const {
7031
+ authAccessToken,
7032
+ authEnabled,
7033
+ backendUrl,
6827
7034
  models,
6828
7035
  openApiApiBaseUrl,
6829
7036
  openApiApiKey,
@@ -6837,13 +7044,13 @@ const getAiSessionTitle = async (state, userText, assistantText) => {
6837
7044
  }
6838
7045
  const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
6839
7046
  const usesOpenRouterModel = isOpenRouterModel(selectedModelId, models);
6840
- if (usesOpenApiModel && !openApiApiKey) {
7047
+ if (!authEnabled && usesOpenApiModel && !openApiApiKey) {
6841
7048
  return '';
6842
7049
  }
6843
- if (usesOpenRouterModel && !openRouterApiKey) {
7050
+ if (!authEnabled && usesOpenRouterModel && !openRouterApiKey) {
6844
7051
  return '';
6845
7052
  }
6846
- if (!usesOpenApiModel && !usesOpenRouterModel) {
7053
+ if (!authEnabled && !usesOpenApiModel && !usesOpenRouterModel) {
6847
7054
  return '';
6848
7055
  }
6849
7056
  const titlePrompt = `Create a concise title (max 6 words) for this conversation. Respond only with the title, no punctuation at the end.
@@ -6860,6 +7067,9 @@ Assistant: ${assistantText}`;
6860
7067
  };
6861
7068
  const titleResponse = await getAiResponse({
6862
7069
  assetDir: state.assetDir,
7070
+ authAccessToken,
7071
+ authEnabled,
7072
+ backendUrl,
6863
7073
  messages: [promptMessage],
6864
7074
  mockAiResponseDelay: state.mockAiResponseDelay,
6865
7075
  mockApiCommandId: state.mockApiCommandId,
@@ -7169,6 +7379,9 @@ const handleSubmit = async state => {
7169
7379
  const {
7170
7380
  aiSessionTitleGenerationEnabled,
7171
7381
  assetDir,
7382
+ authAccessToken,
7383
+ authEnabled,
7384
+ backendUrl,
7172
7385
  composerValue,
7173
7386
  emitStreamingFunctionCallEvents,
7174
7387
  mockAiResponseDelay,
@@ -7308,6 +7521,9 @@ const handleSubmit = async state => {
7308
7521
  } : undefined;
7309
7522
  const assistantMessage = await getAiResponse({
7310
7523
  assetDir,
7524
+ authAccessToken,
7525
+ authEnabled,
7526
+ backendUrl,
7311
7527
  messageId: assistantMessageId,
7312
7528
  messages: messagesWithMentionContext,
7313
7529
  mockAiResponseDelay,
@@ -7415,6 +7631,8 @@ const CreateSession = 'create-session';
7415
7631
  const CreateSessionInProjectPrefix = 'create-session-in-project:';
7416
7632
  const SessionDebug = 'session-debug';
7417
7633
  const Settings = 'settings';
7634
+ const Login = 'login';
7635
+ const Logout = 'logout';
7418
7636
  const CloseChat = 'close-chat';
7419
7637
  const SessionDelete = 'SessionDelete';
7420
7638
  const ProjectPrefix = 'project:';
@@ -7620,6 +7838,10 @@ const handleClick = async (state, name, id = '') => {
7620
7838
  return handleClickOpenApiApiKeySettings(state);
7621
7839
  case name === OpenOpenApiApiKeyWebsite:
7622
7840
  return handleClickOpenApiApiKeyWebsite(state);
7841
+ case name === Login:
7842
+ return handleClickLogin(state);
7843
+ case name === Logout:
7844
+ return handleClickLogout(state);
7623
7845
  default:
7624
7846
  return state;
7625
7847
  }
@@ -7965,12 +8187,12 @@ const initialize = async () => {
7965
8187
  set$4(rpc);
7966
8188
  };
7967
8189
 
7968
- const isObject = value => {
8190
+ const isObject$1 = value => {
7969
8191
  return typeof value === 'object' && value !== null;
7970
8192
  };
7971
8193
 
7972
8194
  const getSavedChatListScrollTop = savedState => {
7973
- if (!isObject(savedState)) {
8195
+ if (!isObject$1(savedState)) {
7974
8196
  return undefined;
7975
8197
  }
7976
8198
  const {
@@ -7983,7 +8205,7 @@ const getSavedChatListScrollTop = savedState => {
7983
8205
  };
7984
8206
 
7985
8207
  const getSavedMessagesScrollTop = savedState => {
7986
- if (!isObject(savedState)) {
8208
+ if (!isObject$1(savedState)) {
7987
8209
  return undefined;
7988
8210
  }
7989
8211
  const {
@@ -7996,7 +8218,7 @@ const getSavedMessagesScrollTop = savedState => {
7996
8218
  };
7997
8219
 
7998
8220
  const getSavedSelectedModelId = savedState => {
7999
- if (!isObject(savedState)) {
8221
+ if (!isObject$1(savedState)) {
8000
8222
  return undefined;
8001
8223
  }
8002
8224
  const {
@@ -8009,7 +8231,7 @@ const getSavedSelectedModelId = savedState => {
8009
8231
  };
8010
8232
 
8011
8233
  const getSavedSelectedSessionId = savedState => {
8012
- if (!isObject(savedState)) {
8234
+ if (!isObject$1(savedState)) {
8013
8235
  return undefined;
8014
8236
  }
8015
8237
  const {
@@ -8022,7 +8244,7 @@ const getSavedSelectedSessionId = savedState => {
8022
8244
  };
8023
8245
 
8024
8246
  const getSavedSessions = savedState => {
8025
- if (!isObject(savedState)) {
8247
+ if (!isObject$1(savedState)) {
8026
8248
  return undefined;
8027
8249
  }
8028
8250
  const {
@@ -8035,7 +8257,7 @@ const getSavedSessions = savedState => {
8035
8257
  };
8036
8258
 
8037
8259
  const getSavedViewMode = savedState => {
8038
- if (!isObject(savedState)) {
8260
+ if (!isObject$1(savedState)) {
8039
8261
  return undefined;
8040
8262
  }
8041
8263
  const {
@@ -8056,6 +8278,42 @@ const loadAiSessionTitleGenerationEnabled = async () => {
8056
8278
  }
8057
8279
  };
8058
8280
 
8281
+ const loadAuthEnabled = async () => {
8282
+ try {
8283
+ const savedAuthEnabled = await get('chat.authEnabled');
8284
+ return typeof savedAuthEnabled === 'boolean' ? savedAuthEnabled : false;
8285
+ } catch {
8286
+ return false;
8287
+ }
8288
+ };
8289
+
8290
+ const loadBackendAccessToken = async () => {
8291
+ try {
8292
+ const savedAccessToken = await get('secrets.chatBackendAccessToken');
8293
+ return typeof savedAccessToken === 'string' ? savedAccessToken : '';
8294
+ } catch {
8295
+ return '';
8296
+ }
8297
+ };
8298
+
8299
+ const loadBackendRefreshToken = async () => {
8300
+ try {
8301
+ const savedRefreshToken = await get('secrets.chatBackendRefreshToken');
8302
+ return typeof savedRefreshToken === 'string' ? savedRefreshToken : '';
8303
+ } catch {
8304
+ return '';
8305
+ }
8306
+ };
8307
+
8308
+ const loadBackendUrl = async () => {
8309
+ try {
8310
+ const savedBackendUrl = await get('chat.backendUrl');
8311
+ return typeof savedBackendUrl === 'string' ? savedBackendUrl : '';
8312
+ } catch {
8313
+ return '';
8314
+ }
8315
+ };
8316
+
8059
8317
  const loadComposerDropEnabled = async () => {
8060
8318
  try {
8061
8319
  const savedComposerDropEnabled = await get('chatView.composerDropEnabled');
@@ -8164,9 +8422,13 @@ const loadVoiceDictationEnabled = async () => {
8164
8422
  };
8165
8423
 
8166
8424
  const loadPreferences = async () => {
8167
- const [aiSessionTitleGenerationEnabled, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, streamingEnabled, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatNetworkWorkerForRequests, useChatToolWorker, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadStreamingEnabled(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadVoiceDictationEnabled()]);
8425
+ const [aiSessionTitleGenerationEnabled, authAccessToken, authEnabled, authRefreshToken, backendUrl, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, streamingEnabled, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatNetworkWorkerForRequests, useChatToolWorker, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadBackendAccessToken(), loadAuthEnabled(), loadBackendRefreshToken(), loadBackendUrl(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadStreamingEnabled(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadVoiceDictationEnabled()]);
8168
8426
  return {
8169
8427
  aiSessionTitleGenerationEnabled,
8428
+ authAccessToken,
8429
+ authEnabled,
8430
+ authRefreshToken,
8431
+ backendUrl,
8170
8432
  composerDropEnabled,
8171
8433
  emitStreamingFunctionCallEvents,
8172
8434
  openApiApiKey,
@@ -8212,7 +8474,7 @@ const toSummarySession = session => {
8212
8474
  };
8213
8475
  };
8214
8476
  const getSavedSelectedProjectId = savedState => {
8215
- if (!isObject(savedState)) {
8477
+ if (!isObject$1(savedState)) {
8216
8478
  return undefined;
8217
8479
  }
8218
8480
  const {
@@ -8224,7 +8486,7 @@ const getSavedSelectedProjectId = savedState => {
8224
8486
  return selectedProjectId;
8225
8487
  };
8226
8488
  const getSavedProjects = savedState => {
8227
- if (!isObject(savedState)) {
8489
+ if (!isObject$1(savedState)) {
8228
8490
  return undefined;
8229
8491
  }
8230
8492
  const {
@@ -8234,7 +8496,7 @@ const getSavedProjects = savedState => {
8234
8496
  return undefined;
8235
8497
  }
8236
8498
  const validProjects = projects.filter(project => {
8237
- if (!isObject(project)) {
8499
+ if (!isObject$1(project)) {
8238
8500
  return false;
8239
8501
  }
8240
8502
  return typeof project.id === 'string' && typeof project.name === 'string' && typeof project.uri === 'string';
@@ -8251,7 +8513,7 @@ const ensureBlankProject = (projects, fallbackBlankProject) => {
8251
8513
  return [fallbackBlankProject, ...projects];
8252
8514
  };
8253
8515
  const getSavedProjectListScrollTop = savedState => {
8254
- if (!isObject(savedState)) {
8516
+ if (!isObject$1(savedState)) {
8255
8517
  return undefined;
8256
8518
  }
8257
8519
  const {
@@ -8263,7 +8525,7 @@ const getSavedProjectListScrollTop = savedState => {
8263
8525
  return projectListScrollTop;
8264
8526
  };
8265
8527
  const getSavedProjectExpandedIds = savedState => {
8266
- if (!isObject(savedState)) {
8528
+ if (!isObject$1(savedState)) {
8267
8529
  return undefined;
8268
8530
  }
8269
8531
  const {
@@ -8279,7 +8541,7 @@ const getSavedProjectExpandedIds = savedState => {
8279
8541
  return ids;
8280
8542
  };
8281
8543
  const getSavedLastNormalViewMode = savedState => {
8282
- if (!isObject(savedState)) {
8544
+ if (!isObject$1(savedState)) {
8283
8545
  return undefined;
8284
8546
  }
8285
8547
  const {
@@ -8291,7 +8553,7 @@ const getSavedLastNormalViewMode = savedState => {
8291
8553
  return lastNormalViewMode;
8292
8554
  };
8293
8555
  const getSavedComposerValue = savedState => {
8294
- if (!isObject(savedState)) {
8556
+ if (!isObject$1(savedState)) {
8295
8557
  return undefined;
8296
8558
  }
8297
8559
  const {
@@ -8308,6 +8570,10 @@ const loadContent = async (state, savedState) => {
8308
8570
  const savedComposerValue = getSavedComposerValue(savedState);
8309
8571
  const {
8310
8572
  aiSessionTitleGenerationEnabled,
8573
+ authAccessToken,
8574
+ authEnabled,
8575
+ authRefreshToken,
8576
+ backendUrl,
8311
8577
  composerDropEnabled,
8312
8578
  emitStreamingFunctionCallEvents,
8313
8579
  openApiApiKey,
@@ -8369,6 +8635,11 @@ const loadContent = async (state, savedState) => {
8369
8635
  return {
8370
8636
  ...state,
8371
8637
  aiSessionTitleGenerationEnabled,
8638
+ authAccessToken,
8639
+ authEnabled,
8640
+ authRefreshToken,
8641
+ authStatus: authAccessToken ? 'signed-in' : 'signed-out',
8642
+ backendUrl,
8372
8643
  chatListScrollTop,
8373
8644
  composerDropActive: false,
8374
8645
  composerDropEnabled,
@@ -8400,6 +8671,36 @@ const loadContent = async (state, savedState) => {
8400
8671
  };
8401
8672
  };
8402
8673
 
8674
+ const isObject = value => {
8675
+ return !!value && typeof value === 'object';
8676
+ };
8677
+ const getDelay = payload => {
8678
+ if (!isObject(payload)) {
8679
+ return 0;
8680
+ }
8681
+ const {
8682
+ delay
8683
+ } = payload;
8684
+ return typeof delay === 'number' && delay > 0 ? delay : 0;
8685
+ };
8686
+ const mockBackendAuthResponse = (state, payload) => {
8687
+ const delay = getDelay(payload);
8688
+ if (payload.type === 'error') {
8689
+ setNextLoginResponse({
8690
+ delay,
8691
+ message: payload.message || 'Backend authentication failed.',
8692
+ type: 'error'
8693
+ });
8694
+ return state;
8695
+ }
8696
+ setNextLoginResponse({
8697
+ delay,
8698
+ response: payload,
8699
+ type: 'success'
8700
+ });
8701
+ return state;
8702
+ };
8703
+
8403
8704
  const mockOpenApiRequestGetAll = _state => {
8404
8705
  return getAll();
8405
8706
  };
@@ -8800,6 +9101,7 @@ const renderFocusContext = (oldState, newState) => {
8800
9101
  const Actions = 'Actions';
8801
9102
  const ChatActions = 'ChatActions';
8802
9103
  const ChatName = 'ChatName';
9104
+ const ChatAuthError = 'ChatAuthError';
8803
9105
  const ChatSendArea = 'ChatSendArea';
8804
9106
  const ChatViewDropOverlay = 'ChatViewDropOverlay';
8805
9107
  const ChatViewDropOverlayActive = 'ChatViewDropOverlayActive';
@@ -8814,6 +9116,7 @@ const ButtonSecondary = 'ButtonSecondary';
8814
9116
  const Empty = '';
8815
9117
  const FileIcon = 'FileIcon';
8816
9118
  const IconButton = 'IconButton';
9119
+ const IconButtonDisabled = 'IconButtonDisabled';
8817
9120
  const ImageElement = 'ImageElement';
8818
9121
  const InputBox = 'InputBox';
8819
9122
  const Label = 'Label';
@@ -10186,7 +10489,7 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
10186
10489
  }, text('+ Add Project')];
10187
10490
  };
10188
10491
 
10189
- const getChatModeChatFocusVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages = []) => {
10492
+ const getChatModeChatFocusVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages = [], authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10190
10493
  const selectedSession = sessions.find(session => session.id === selectedSessionId);
10191
10494
  const messages = selectedSession ? selectedSession.messages : [];
10192
10495
  const isDropOverlayVisible = composerDropEnabled && composerDropActive;
@@ -10229,7 +10532,8 @@ const getBackButtonVirtualDom = () => {
10229
10532
  const getHeaderActionVirtualDom = item => {
10230
10533
  return [{
10231
10534
  childCount: 1,
10232
- className: IconButton,
10535
+ className: mergeClassNames(IconButton, item.disabled ? IconButtonDisabled : ''),
10536
+ disabled: item.disabled,
10233
10537
  name: item.name,
10234
10538
  onClick: item.onClick,
10235
10539
  title: item.title,
@@ -10241,8 +10545,22 @@ const getHeaderActionVirtualDom = item => {
10241
10545
  }];
10242
10546
  };
10243
10547
 
10244
- const getChatHeaderActionsDom = viewMode => {
10548
+ const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'signed-out') => {
10245
10549
  const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
10550
+ const isSigningIn = authStatus === 'signing-in';
10551
+ const authAction = authEnabled && authStatus !== 'signed-in' ? {
10552
+ disabled: isSigningIn,
10553
+ icon: 'MaskIcon MaskIconAccount',
10554
+ name: Login,
10555
+ onClick: HandleClick,
10556
+ title: isSigningIn ? loggingInToBackend() : loginToBackend()
10557
+ } : authEnabled ? {
10558
+ disabled: false,
10559
+ icon: 'MaskIcon MaskIconSignOut',
10560
+ name: Logout,
10561
+ onClick: HandleClick,
10562
+ title: logoutFromBackend()
10563
+ } : undefined;
10246
10564
  const items = [{
10247
10565
  icon: 'MaskIcon MaskIconLayoutPanelLeft',
10248
10566
  name: ToggleChatFocus,
@@ -10263,7 +10581,7 @@ const getChatHeaderActionsDom = viewMode => {
10263
10581
  name: Settings,
10264
10582
  onClick: HandleClickSettings,
10265
10583
  title: settings()
10266
- }, {
10584
+ }, ...(authAction ? [authAction] : []), {
10267
10585
  icon: 'MaskIcon MaskIconClose',
10268
10586
  name: CloseChat,
10269
10587
  onClick: HandleClickClose,
@@ -10276,9 +10594,10 @@ const getChatHeaderActionsDom = viewMode => {
10276
10594
  }, ...items.flatMap(getHeaderActionVirtualDom)];
10277
10595
  };
10278
10596
 
10279
- const getChatHeaderDomDetailMode = selectedSessionTitle => {
10597
+ const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10598
+ const hasAuthError = authEnabled && !!authErrorMessage;
10280
10599
  return [{
10281
- childCount: 2,
10600
+ childCount: hasAuthError ? 3 : 2,
10282
10601
  className: ChatHeader,
10283
10602
  type: Div
10284
10603
  }, {
@@ -10289,10 +10608,14 @@ const getChatHeaderDomDetailMode = selectedSessionTitle => {
10289
10608
  childCount: 1,
10290
10609
  className: Label,
10291
10610
  type: Span
10292
- }, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail')];
10611
+ }, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail', authEnabled, authStatus), ...(hasAuthError ? [{
10612
+ childCount: 1,
10613
+ className: ChatAuthError,
10614
+ type: Span
10615
+ }, text(authErrorMessage)] : [])];
10293
10616
  };
10294
10617
 
10295
- const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages = []) => {
10618
+ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, messagesScrollTop = 0, composerDropActive = false, composerDropEnabled = true, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages = [], authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10296
10619
  const selectedSession = sessions.find(session => session.id === selectedSessionId);
10297
10620
  const selectedSessionTitle = selectedSession?.title || chatTitle();
10298
10621
  const messages = selectedSession ? selectedSession.messages : [];
@@ -10303,7 +10626,7 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
10303
10626
  onDragEnter: HandleDragEnterChatView,
10304
10627
  onDragOver: HandleDragOverChatView,
10305
10628
  type: Div
10306
- }, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
10629
+ }, ...getChatHeaderDomDetailMode(selectedSessionTitle, authEnabled, authStatus, authErrorMessage), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
10307
10630
  childCount: 1,
10308
10631
  className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
10309
10632
  name: ComposerDropTarget,
@@ -10317,16 +10640,21 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
10317
10640
  }] : [])];
10318
10641
  };
10319
10642
 
10320
- const getChatHeaderListModeDom = () => {
10643
+ const getChatHeaderListModeDom = (authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10644
+ const hasAuthError = authEnabled && !!authErrorMessage;
10321
10645
  return [{
10322
- childCount: 2,
10646
+ childCount: hasAuthError ? 3 : 2,
10323
10647
  className: ChatHeader,
10324
10648
  type: Div
10325
10649
  }, {
10326
10650
  childCount: 1,
10327
10651
  className: Label,
10328
10652
  type: Span
10329
- }, text(chats()), ...getChatHeaderActionsDom('list')];
10653
+ }, text(chats()), ...getChatHeaderActionsDom('list', authEnabled, authStatus), ...(hasAuthError ? [{
10654
+ childCount: 1,
10655
+ className: ChatAuthError,
10656
+ type: Span
10657
+ }, text(authErrorMessage)] : [])];
10330
10658
  };
10331
10659
 
10332
10660
  const getEmptyChatSessionsDom = () => {
@@ -10384,7 +10712,7 @@ const getChatListDom = (sessions, selectedSessionId, chatListScrollTop = 0) => {
10384
10712
  }, ...sessions.flatMap(getSessionDom)];
10385
10713
  };
10386
10714
 
10387
- const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, chatListScrollTop = 0, composerDropActive = false, composerDropEnabled = true, voiceDictationEnabled = false) => {
10715
+ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, chatListScrollTop = 0, composerDropActive = false, composerDropEnabled = true, voiceDictationEnabled = false, authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10388
10716
  const isDropOverlayVisible = composerDropEnabled && composerDropActive;
10389
10717
  return [{
10390
10718
  childCount: isDropOverlayVisible ? 4 : 3,
@@ -10392,7 +10720,7 @@ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, m
10392
10720
  onDragEnter: HandleDragEnterChatView,
10393
10721
  onDragOver: HandleDragOverChatView,
10394
10722
  type: Div
10395
- }, ...getChatHeaderListModeDom(), ...getChatListDom(sessions, selectedSessionId, chatListScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
10723
+ }, ...getChatHeaderListModeDom(authEnabled, authStatus, authErrorMessage), ...getChatListDom(sessions, selectedSessionId, chatListScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
10396
10724
  childCount: 1,
10397
10725
  className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
10398
10726
  name: ComposerDropTarget,
@@ -10429,15 +10757,15 @@ const getFallbackParsedMessages = sessions => {
10429
10757
  }
10430
10758
  return parsedMessages;
10431
10759
  };
10432
- const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages) => {
10760
+ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive = false, composerDropEnabled = true, projects = [], projectExpandedIds = [], selectedProjectId = '', projectListScrollTop = 0, voiceDictationEnabled = false, useChatMathWorker = false, parsedMessages, authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
10433
10761
  const effectiveParsedMessages = parsedMessages || getFallbackParsedMessages(sessions);
10434
10762
  switch (viewMode) {
10435
10763
  case 'chat-focus':
10436
- return getChatModeChatFocusVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop, voiceDictationEnabled, useChatMathWorker, effectiveParsedMessages);
10764
+ return getChatModeChatFocusVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop, voiceDictationEnabled, useChatMathWorker, effectiveParsedMessages, authEnabled, authStatus, authErrorMessage);
10437
10765
  case 'detail':
10438
- return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, voiceDictationEnabled, useChatMathWorker, effectiveParsedMessages);
10766
+ return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop, composerDropActive, composerDropEnabled, voiceDictationEnabled, useChatMathWorker, effectiveParsedMessages, authEnabled, authStatus, authErrorMessage);
10439
10767
  case 'list':
10440
- return getChatModeListVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, composerDropActive, composerDropEnabled, voiceDictationEnabled);
10768
+ return getChatModeListVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, composerDropActive, composerDropEnabled, voiceDictationEnabled, authEnabled, authStatus, authErrorMessage);
10441
10769
  default:
10442
10770
  return getChatModeUnsupportedVirtualDom();
10443
10771
  }
@@ -10445,6 +10773,9 @@ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRoute
10445
10773
 
10446
10774
  const renderItems = (oldState, newState) => {
10447
10775
  const {
10776
+ authEnabled,
10777
+ authErrorMessage,
10778
+ authStatus,
10448
10779
  chatListScrollTop,
10449
10780
  composerDropActive,
10450
10781
  composerDropEnabled,
@@ -10478,7 +10809,7 @@ const renderItems = (oldState, newState) => {
10478
10809
  if (initial) {
10479
10810
  return [SetDom2, uid, []];
10480
10811
  }
10481
- const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop, voiceDictationEnabled, useChatMathWorker, parsedMessages);
10812
+ const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop, composerDropActive, composerDropEnabled, projects, projectExpandedIds, selectedProjectId, projectListScrollTop, voiceDictationEnabled, useChatMathWorker, parsedMessages, authEnabled, authStatus, authErrorMessage);
10482
10813
  return [SetDom2, uid, dom];
10483
10814
  };
10484
10815
 
@@ -10777,6 +11108,20 @@ const saveState = state => {
10777
11108
  };
10778
11109
  };
10779
11110
 
11111
+ const setAuthEnabled = (state, authEnabled) => {
11112
+ return {
11113
+ ...state,
11114
+ authEnabled
11115
+ };
11116
+ };
11117
+
11118
+ const setBackendUrl = (state, backendUrl) => {
11119
+ return {
11120
+ ...state,
11121
+ backendUrl
11122
+ };
11123
+ };
11124
+
10780
11125
  const dummySessions = [{
10781
11126
  id: 'session-a',
10782
11127
  messages: [],
@@ -10870,6 +11215,7 @@ const commandMap = {
10870
11215
  'Chat.deleteSessionAtIndex': wrapCommand(deleteSessionAtIndex),
10871
11216
  'Chat.diff2': diff2,
10872
11217
  'Chat.enterNewLine': wrapCommand(handleNewline),
11218
+ 'Chat.getAuthState': wrapGetter(getAuthState),
10873
11219
  'Chat.getCommandIds': getCommandIds,
10874
11220
  'Chat.getKeyBindings': getKeyBindings,
10875
11221
  'Chat.getMenuEntries': getMenuEntries,
@@ -10905,6 +11251,7 @@ const commandMap = {
10905
11251
  'Chat.initialize': initialize,
10906
11252
  'Chat.loadContent': wrapCommand(loadContent),
10907
11253
  'Chat.loadContent2': wrapCommand(loadContent),
11254
+ 'Chat.mockBackendAuthResponse': wrapCommand(mockBackendAuthResponse),
10908
11255
  'Chat.mockOpenApiRequestGetAll': wrapGetter(mockOpenApiRequestGetAll),
10909
11256
  'Chat.mockOpenApiRequestReset': wrapCommand(mockOpenApiRequestReset),
10910
11257
  'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
@@ -10920,6 +11267,8 @@ const commandMap = {
10920
11267
  'Chat.reset': wrapCommand(reset),
10921
11268
  'Chat.resize': wrapCommand(resize),
10922
11269
  'Chat.saveState': wrapGetter(saveState),
11270
+ 'Chat.setAuthEnabled': wrapCommand(setAuthEnabled),
11271
+ 'Chat.setBackendUrl': wrapCommand(setBackendUrl),
10923
11272
  'Chat.setChatList': wrapCommand(setChatList),
10924
11273
  'Chat.setEmitStreamingFunctionCallEvents': wrapCommand(setEmitStreamingFunctionCallEvents),
10925
11274
  'Chat.setOpenRouterApiKey': wrapCommand(setOpenRouterApiKey),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "6.6.0",
3
+ "version": "6.7.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",