@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.
- package/dist/chatViewWorkerMain.js +397 -48
- package/package.json +1 -1
|
@@ -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),
|