@lvce-editor/chat-view 6.5.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 +399 -49
- 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
|
}
|
|
@@ -7649,7 +7871,8 @@ const handleClickDictationButton = async state => {
|
|
|
7649
7871
|
|
|
7650
7872
|
const handleClickNew = async state => {
|
|
7651
7873
|
const newState = await createSession(state);
|
|
7652
|
-
|
|
7874
|
+
const clearedState = await clearInput(newState);
|
|
7875
|
+
return focusInput(clearedState);
|
|
7653
7876
|
};
|
|
7654
7877
|
|
|
7655
7878
|
const handleClickReadFile = async uri => {
|
|
@@ -7964,12 +8187,12 @@ const initialize = async () => {
|
|
|
7964
8187
|
set$4(rpc);
|
|
7965
8188
|
};
|
|
7966
8189
|
|
|
7967
|
-
const isObject = value => {
|
|
8190
|
+
const isObject$1 = value => {
|
|
7968
8191
|
return typeof value === 'object' && value !== null;
|
|
7969
8192
|
};
|
|
7970
8193
|
|
|
7971
8194
|
const getSavedChatListScrollTop = savedState => {
|
|
7972
|
-
if (!isObject(savedState)) {
|
|
8195
|
+
if (!isObject$1(savedState)) {
|
|
7973
8196
|
return undefined;
|
|
7974
8197
|
}
|
|
7975
8198
|
const {
|
|
@@ -7982,7 +8205,7 @@ const getSavedChatListScrollTop = savedState => {
|
|
|
7982
8205
|
};
|
|
7983
8206
|
|
|
7984
8207
|
const getSavedMessagesScrollTop = savedState => {
|
|
7985
|
-
if (!isObject(savedState)) {
|
|
8208
|
+
if (!isObject$1(savedState)) {
|
|
7986
8209
|
return undefined;
|
|
7987
8210
|
}
|
|
7988
8211
|
const {
|
|
@@ -7995,7 +8218,7 @@ const getSavedMessagesScrollTop = savedState => {
|
|
|
7995
8218
|
};
|
|
7996
8219
|
|
|
7997
8220
|
const getSavedSelectedModelId = savedState => {
|
|
7998
|
-
if (!isObject(savedState)) {
|
|
8221
|
+
if (!isObject$1(savedState)) {
|
|
7999
8222
|
return undefined;
|
|
8000
8223
|
}
|
|
8001
8224
|
const {
|
|
@@ -8008,7 +8231,7 @@ const getSavedSelectedModelId = savedState => {
|
|
|
8008
8231
|
};
|
|
8009
8232
|
|
|
8010
8233
|
const getSavedSelectedSessionId = savedState => {
|
|
8011
|
-
if (!isObject(savedState)) {
|
|
8234
|
+
if (!isObject$1(savedState)) {
|
|
8012
8235
|
return undefined;
|
|
8013
8236
|
}
|
|
8014
8237
|
const {
|
|
@@ -8021,7 +8244,7 @@ const getSavedSelectedSessionId = savedState => {
|
|
|
8021
8244
|
};
|
|
8022
8245
|
|
|
8023
8246
|
const getSavedSessions = savedState => {
|
|
8024
|
-
if (!isObject(savedState)) {
|
|
8247
|
+
if (!isObject$1(savedState)) {
|
|
8025
8248
|
return undefined;
|
|
8026
8249
|
}
|
|
8027
8250
|
const {
|
|
@@ -8034,7 +8257,7 @@ const getSavedSessions = savedState => {
|
|
|
8034
8257
|
};
|
|
8035
8258
|
|
|
8036
8259
|
const getSavedViewMode = savedState => {
|
|
8037
|
-
if (!isObject(savedState)) {
|
|
8260
|
+
if (!isObject$1(savedState)) {
|
|
8038
8261
|
return undefined;
|
|
8039
8262
|
}
|
|
8040
8263
|
const {
|
|
@@ -8055,6 +8278,42 @@ const loadAiSessionTitleGenerationEnabled = async () => {
|
|
|
8055
8278
|
}
|
|
8056
8279
|
};
|
|
8057
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
|
+
|
|
8058
8317
|
const loadComposerDropEnabled = async () => {
|
|
8059
8318
|
try {
|
|
8060
8319
|
const savedComposerDropEnabled = await get('chatView.composerDropEnabled');
|
|
@@ -8163,9 +8422,13 @@ const loadVoiceDictationEnabled = async () => {
|
|
|
8163
8422
|
};
|
|
8164
8423
|
|
|
8165
8424
|
const loadPreferences = async () => {
|
|
8166
|
-
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()]);
|
|
8167
8426
|
return {
|
|
8168
8427
|
aiSessionTitleGenerationEnabled,
|
|
8428
|
+
authAccessToken,
|
|
8429
|
+
authEnabled,
|
|
8430
|
+
authRefreshToken,
|
|
8431
|
+
backendUrl,
|
|
8169
8432
|
composerDropEnabled,
|
|
8170
8433
|
emitStreamingFunctionCallEvents,
|
|
8171
8434
|
openApiApiKey,
|
|
@@ -8211,7 +8474,7 @@ const toSummarySession = session => {
|
|
|
8211
8474
|
};
|
|
8212
8475
|
};
|
|
8213
8476
|
const getSavedSelectedProjectId = savedState => {
|
|
8214
|
-
if (!isObject(savedState)) {
|
|
8477
|
+
if (!isObject$1(savedState)) {
|
|
8215
8478
|
return undefined;
|
|
8216
8479
|
}
|
|
8217
8480
|
const {
|
|
@@ -8223,7 +8486,7 @@ const getSavedSelectedProjectId = savedState => {
|
|
|
8223
8486
|
return selectedProjectId;
|
|
8224
8487
|
};
|
|
8225
8488
|
const getSavedProjects = savedState => {
|
|
8226
|
-
if (!isObject(savedState)) {
|
|
8489
|
+
if (!isObject$1(savedState)) {
|
|
8227
8490
|
return undefined;
|
|
8228
8491
|
}
|
|
8229
8492
|
const {
|
|
@@ -8233,7 +8496,7 @@ const getSavedProjects = savedState => {
|
|
|
8233
8496
|
return undefined;
|
|
8234
8497
|
}
|
|
8235
8498
|
const validProjects = projects.filter(project => {
|
|
8236
|
-
if (!isObject(project)) {
|
|
8499
|
+
if (!isObject$1(project)) {
|
|
8237
8500
|
return false;
|
|
8238
8501
|
}
|
|
8239
8502
|
return typeof project.id === 'string' && typeof project.name === 'string' && typeof project.uri === 'string';
|
|
@@ -8250,7 +8513,7 @@ const ensureBlankProject = (projects, fallbackBlankProject) => {
|
|
|
8250
8513
|
return [fallbackBlankProject, ...projects];
|
|
8251
8514
|
};
|
|
8252
8515
|
const getSavedProjectListScrollTop = savedState => {
|
|
8253
|
-
if (!isObject(savedState)) {
|
|
8516
|
+
if (!isObject$1(savedState)) {
|
|
8254
8517
|
return undefined;
|
|
8255
8518
|
}
|
|
8256
8519
|
const {
|
|
@@ -8262,7 +8525,7 @@ const getSavedProjectListScrollTop = savedState => {
|
|
|
8262
8525
|
return projectListScrollTop;
|
|
8263
8526
|
};
|
|
8264
8527
|
const getSavedProjectExpandedIds = savedState => {
|
|
8265
|
-
if (!isObject(savedState)) {
|
|
8528
|
+
if (!isObject$1(savedState)) {
|
|
8266
8529
|
return undefined;
|
|
8267
8530
|
}
|
|
8268
8531
|
const {
|
|
@@ -8278,7 +8541,7 @@ const getSavedProjectExpandedIds = savedState => {
|
|
|
8278
8541
|
return ids;
|
|
8279
8542
|
};
|
|
8280
8543
|
const getSavedLastNormalViewMode = savedState => {
|
|
8281
|
-
if (!isObject(savedState)) {
|
|
8544
|
+
if (!isObject$1(savedState)) {
|
|
8282
8545
|
return undefined;
|
|
8283
8546
|
}
|
|
8284
8547
|
const {
|
|
@@ -8290,7 +8553,7 @@ const getSavedLastNormalViewMode = savedState => {
|
|
|
8290
8553
|
return lastNormalViewMode;
|
|
8291
8554
|
};
|
|
8292
8555
|
const getSavedComposerValue = savedState => {
|
|
8293
|
-
if (!isObject(savedState)) {
|
|
8556
|
+
if (!isObject$1(savedState)) {
|
|
8294
8557
|
return undefined;
|
|
8295
8558
|
}
|
|
8296
8559
|
const {
|
|
@@ -8307,6 +8570,10 @@ const loadContent = async (state, savedState) => {
|
|
|
8307
8570
|
const savedComposerValue = getSavedComposerValue(savedState);
|
|
8308
8571
|
const {
|
|
8309
8572
|
aiSessionTitleGenerationEnabled,
|
|
8573
|
+
authAccessToken,
|
|
8574
|
+
authEnabled,
|
|
8575
|
+
authRefreshToken,
|
|
8576
|
+
backendUrl,
|
|
8310
8577
|
composerDropEnabled,
|
|
8311
8578
|
emitStreamingFunctionCallEvents,
|
|
8312
8579
|
openApiApiKey,
|
|
@@ -8368,6 +8635,11 @@ const loadContent = async (state, savedState) => {
|
|
|
8368
8635
|
return {
|
|
8369
8636
|
...state,
|
|
8370
8637
|
aiSessionTitleGenerationEnabled,
|
|
8638
|
+
authAccessToken,
|
|
8639
|
+
authEnabled,
|
|
8640
|
+
authRefreshToken,
|
|
8641
|
+
authStatus: authAccessToken ? 'signed-in' : 'signed-out',
|
|
8642
|
+
backendUrl,
|
|
8371
8643
|
chatListScrollTop,
|
|
8372
8644
|
composerDropActive: false,
|
|
8373
8645
|
composerDropEnabled,
|
|
@@ -8399,6 +8671,36 @@ const loadContent = async (state, savedState) => {
|
|
|
8399
8671
|
};
|
|
8400
8672
|
};
|
|
8401
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
|
+
|
|
8402
8704
|
const mockOpenApiRequestGetAll = _state => {
|
|
8403
8705
|
return getAll();
|
|
8404
8706
|
};
|
|
@@ -8799,6 +9101,7 @@ const renderFocusContext = (oldState, newState) => {
|
|
|
8799
9101
|
const Actions = 'Actions';
|
|
8800
9102
|
const ChatActions = 'ChatActions';
|
|
8801
9103
|
const ChatName = 'ChatName';
|
|
9104
|
+
const ChatAuthError = 'ChatAuthError';
|
|
8802
9105
|
const ChatSendArea = 'ChatSendArea';
|
|
8803
9106
|
const ChatViewDropOverlay = 'ChatViewDropOverlay';
|
|
8804
9107
|
const ChatViewDropOverlayActive = 'ChatViewDropOverlayActive';
|
|
@@ -8813,6 +9116,7 @@ const ButtonSecondary = 'ButtonSecondary';
|
|
|
8813
9116
|
const Empty = '';
|
|
8814
9117
|
const FileIcon = 'FileIcon';
|
|
8815
9118
|
const IconButton = 'IconButton';
|
|
9119
|
+
const IconButtonDisabled = 'IconButtonDisabled';
|
|
8816
9120
|
const ImageElement = 'ImageElement';
|
|
8817
9121
|
const InputBox = 'InputBox';
|
|
8818
9122
|
const Label = 'Label';
|
|
@@ -10185,7 +10489,7 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
|
|
|
10185
10489
|
}, text('+ Add Project')];
|
|
10186
10490
|
};
|
|
10187
10491
|
|
|
10188
|
-
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 = '') => {
|
|
10189
10493
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
10190
10494
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
10191
10495
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
@@ -10228,7 +10532,8 @@ const getBackButtonVirtualDom = () => {
|
|
|
10228
10532
|
const getHeaderActionVirtualDom = item => {
|
|
10229
10533
|
return [{
|
|
10230
10534
|
childCount: 1,
|
|
10231
|
-
className: IconButton,
|
|
10535
|
+
className: mergeClassNames(IconButton, item.disabled ? IconButtonDisabled : ''),
|
|
10536
|
+
disabled: item.disabled,
|
|
10232
10537
|
name: item.name,
|
|
10233
10538
|
onClick: item.onClick,
|
|
10234
10539
|
title: item.title,
|
|
@@ -10240,8 +10545,22 @@ const getHeaderActionVirtualDom = item => {
|
|
|
10240
10545
|
}];
|
|
10241
10546
|
};
|
|
10242
10547
|
|
|
10243
|
-
const getChatHeaderActionsDom = viewMode => {
|
|
10548
|
+
const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'signed-out') => {
|
|
10244
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;
|
|
10245
10564
|
const items = [{
|
|
10246
10565
|
icon: 'MaskIcon MaskIconLayoutPanelLeft',
|
|
10247
10566
|
name: ToggleChatFocus,
|
|
@@ -10262,7 +10581,7 @@ const getChatHeaderActionsDom = viewMode => {
|
|
|
10262
10581
|
name: Settings,
|
|
10263
10582
|
onClick: HandleClickSettings,
|
|
10264
10583
|
title: settings()
|
|
10265
|
-
}, {
|
|
10584
|
+
}, ...(authAction ? [authAction] : []), {
|
|
10266
10585
|
icon: 'MaskIcon MaskIconClose',
|
|
10267
10586
|
name: CloseChat,
|
|
10268
10587
|
onClick: HandleClickClose,
|
|
@@ -10275,9 +10594,10 @@ const getChatHeaderActionsDom = viewMode => {
|
|
|
10275
10594
|
}, ...items.flatMap(getHeaderActionVirtualDom)];
|
|
10276
10595
|
};
|
|
10277
10596
|
|
|
10278
|
-
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
10597
|
+
const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
|
|
10598
|
+
const hasAuthError = authEnabled && !!authErrorMessage;
|
|
10279
10599
|
return [{
|
|
10280
|
-
childCount: 2,
|
|
10600
|
+
childCount: hasAuthError ? 3 : 2,
|
|
10281
10601
|
className: ChatHeader,
|
|
10282
10602
|
type: Div
|
|
10283
10603
|
}, {
|
|
@@ -10288,10 +10608,14 @@ const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
|
10288
10608
|
childCount: 1,
|
|
10289
10609
|
className: Label,
|
|
10290
10610
|
type: Span
|
|
10291
|
-
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail')
|
|
10611
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail', authEnabled, authStatus), ...(hasAuthError ? [{
|
|
10612
|
+
childCount: 1,
|
|
10613
|
+
className: ChatAuthError,
|
|
10614
|
+
type: Span
|
|
10615
|
+
}, text(authErrorMessage)] : [])];
|
|
10292
10616
|
};
|
|
10293
10617
|
|
|
10294
|
-
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 = '') => {
|
|
10295
10619
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
10296
10620
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
10297
10621
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
@@ -10302,7 +10626,7 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
|
|
|
10302
10626
|
onDragEnter: HandleDragEnterChatView,
|
|
10303
10627
|
onDragOver: HandleDragOverChatView,
|
|
10304
10628
|
type: Div
|
|
10305
|
-
}, ...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 ? [{
|
|
10306
10630
|
childCount: 1,
|
|
10307
10631
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10308
10632
|
name: ComposerDropTarget,
|
|
@@ -10316,16 +10640,21 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
|
|
|
10316
10640
|
}] : [])];
|
|
10317
10641
|
};
|
|
10318
10642
|
|
|
10319
|
-
const getChatHeaderListModeDom = () => {
|
|
10643
|
+
const getChatHeaderListModeDom = (authEnabled = false, authStatus = 'signed-out', authErrorMessage = '') => {
|
|
10644
|
+
const hasAuthError = authEnabled && !!authErrorMessage;
|
|
10320
10645
|
return [{
|
|
10321
|
-
childCount: 2,
|
|
10646
|
+
childCount: hasAuthError ? 3 : 2,
|
|
10322
10647
|
className: ChatHeader,
|
|
10323
10648
|
type: Div
|
|
10324
10649
|
}, {
|
|
10325
10650
|
childCount: 1,
|
|
10326
10651
|
className: Label,
|
|
10327
10652
|
type: Span
|
|
10328
|
-
}, text(chats()), ...getChatHeaderActionsDom('list')
|
|
10653
|
+
}, text(chats()), ...getChatHeaderActionsDom('list', authEnabled, authStatus), ...(hasAuthError ? [{
|
|
10654
|
+
childCount: 1,
|
|
10655
|
+
className: ChatAuthError,
|
|
10656
|
+
type: Span
|
|
10657
|
+
}, text(authErrorMessage)] : [])];
|
|
10329
10658
|
};
|
|
10330
10659
|
|
|
10331
10660
|
const getEmptyChatSessionsDom = () => {
|
|
@@ -10383,7 +10712,7 @@ const getChatListDom = (sessions, selectedSessionId, chatListScrollTop = 0) => {
|
|
|
10383
10712
|
}, ...sessions.flatMap(getSessionDom)];
|
|
10384
10713
|
};
|
|
10385
10714
|
|
|
10386
|
-
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 = '') => {
|
|
10387
10716
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
10388
10717
|
return [{
|
|
10389
10718
|
childCount: isDropOverlayVisible ? 4 : 3,
|
|
@@ -10391,7 +10720,7 @@ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, m
|
|
|
10391
10720
|
onDragEnter: HandleDragEnterChatView,
|
|
10392
10721
|
onDragOver: HandleDragOverChatView,
|
|
10393
10722
|
type: Div
|
|
10394
|
-
}, ...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 ? [{
|
|
10395
10724
|
childCount: 1,
|
|
10396
10725
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10397
10726
|
name: ComposerDropTarget,
|
|
@@ -10428,15 +10757,15 @@ const getFallbackParsedMessages = sessions => {
|
|
|
10428
10757
|
}
|
|
10429
10758
|
return parsedMessages;
|
|
10430
10759
|
};
|
|
10431
|
-
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 = '') => {
|
|
10432
10761
|
const effectiveParsedMessages = parsedMessages || getFallbackParsedMessages(sessions);
|
|
10433
10762
|
switch (viewMode) {
|
|
10434
10763
|
case 'chat-focus':
|
|
10435
|
-
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);
|
|
10436
10765
|
case 'detail':
|
|
10437
|
-
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);
|
|
10438
10767
|
case 'list':
|
|
10439
|
-
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);
|
|
10440
10769
|
default:
|
|
10441
10770
|
return getChatModeUnsupportedVirtualDom();
|
|
10442
10771
|
}
|
|
@@ -10444,6 +10773,9 @@ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRoute
|
|
|
10444
10773
|
|
|
10445
10774
|
const renderItems = (oldState, newState) => {
|
|
10446
10775
|
const {
|
|
10776
|
+
authEnabled,
|
|
10777
|
+
authErrorMessage,
|
|
10778
|
+
authStatus,
|
|
10447
10779
|
chatListScrollTop,
|
|
10448
10780
|
composerDropActive,
|
|
10449
10781
|
composerDropEnabled,
|
|
@@ -10477,7 +10809,7 @@ const renderItems = (oldState, newState) => {
|
|
|
10477
10809
|
if (initial) {
|
|
10478
10810
|
return [SetDom2, uid, []];
|
|
10479
10811
|
}
|
|
10480
|
-
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);
|
|
10481
10813
|
return [SetDom2, uid, dom];
|
|
10482
10814
|
};
|
|
10483
10815
|
|
|
@@ -10776,6 +11108,20 @@ const saveState = state => {
|
|
|
10776
11108
|
};
|
|
10777
11109
|
};
|
|
10778
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
|
+
|
|
10779
11125
|
const dummySessions = [{
|
|
10780
11126
|
id: 'session-a',
|
|
10781
11127
|
messages: [],
|
|
@@ -10869,6 +11215,7 @@ const commandMap = {
|
|
|
10869
11215
|
'Chat.deleteSessionAtIndex': wrapCommand(deleteSessionAtIndex),
|
|
10870
11216
|
'Chat.diff2': diff2,
|
|
10871
11217
|
'Chat.enterNewLine': wrapCommand(handleNewline),
|
|
11218
|
+
'Chat.getAuthState': wrapGetter(getAuthState),
|
|
10872
11219
|
'Chat.getCommandIds': getCommandIds,
|
|
10873
11220
|
'Chat.getKeyBindings': getKeyBindings,
|
|
10874
11221
|
'Chat.getMenuEntries': getMenuEntries,
|
|
@@ -10904,6 +11251,7 @@ const commandMap = {
|
|
|
10904
11251
|
'Chat.initialize': initialize,
|
|
10905
11252
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
10906
11253
|
'Chat.loadContent2': wrapCommand(loadContent),
|
|
11254
|
+
'Chat.mockBackendAuthResponse': wrapCommand(mockBackendAuthResponse),
|
|
10907
11255
|
'Chat.mockOpenApiRequestGetAll': wrapGetter(mockOpenApiRequestGetAll),
|
|
10908
11256
|
'Chat.mockOpenApiRequestReset': wrapCommand(mockOpenApiRequestReset),
|
|
10909
11257
|
'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
|
|
@@ -10919,6 +11267,8 @@ const commandMap = {
|
|
|
10919
11267
|
'Chat.reset': wrapCommand(reset),
|
|
10920
11268
|
'Chat.resize': wrapCommand(resize),
|
|
10921
11269
|
'Chat.saveState': wrapGetter(saveState),
|
|
11270
|
+
'Chat.setAuthEnabled': wrapCommand(setAuthEnabled),
|
|
11271
|
+
'Chat.setBackendUrl': wrapCommand(setBackendUrl),
|
|
10922
11272
|
'Chat.setChatList': wrapCommand(setChatList),
|
|
10923
11273
|
'Chat.setEmitStreamingFunctionCallEvents': wrapCommand(setEmitStreamingFunctionCallEvents),
|
|
10924
11274
|
'Chat.setOpenRouterApiKey': wrapCommand(setOpenRouterApiKey),
|