@lvce-editor/chat-view 7.7.0 → 7.10.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 +322 -77
- package/package.json +1 -1
|
@@ -1290,6 +1290,9 @@ const {
|
|
|
1290
1290
|
const openExternal = async url => {
|
|
1291
1291
|
return invoke$1('Open.openExternal', url);
|
|
1292
1292
|
};
|
|
1293
|
+
const openUrl = async (url, platform) => {
|
|
1294
|
+
return invoke$1('Open.openUrl', url, platform);
|
|
1295
|
+
};
|
|
1293
1296
|
|
|
1294
1297
|
const {
|
|
1295
1298
|
invoke,
|
|
@@ -2402,6 +2405,7 @@ const createDefaultState = () => {
|
|
|
2402
2405
|
gitBranchPickerVisible: false,
|
|
2403
2406
|
headerHeight: 50,
|
|
2404
2407
|
height: 0,
|
|
2408
|
+
useOwnBackend: false,
|
|
2405
2409
|
...responsivePickerState,
|
|
2406
2410
|
initial: true,
|
|
2407
2411
|
inputSource: 'script',
|
|
@@ -4361,8 +4365,24 @@ const getBackendAuthUrl = (backendUrl, path) => {
|
|
|
4361
4365
|
return `${trimTrailingSlashes(backendUrl)}${path}`;
|
|
4362
4366
|
};
|
|
4363
4367
|
|
|
4364
|
-
const
|
|
4365
|
-
|
|
4368
|
+
const getCurrentHref = async () => {
|
|
4369
|
+
try {
|
|
4370
|
+
return await invoke('Layout.getHref');
|
|
4371
|
+
} catch {
|
|
4372
|
+
// ignore
|
|
4373
|
+
}
|
|
4374
|
+
if (!globalThis.location || typeof globalThis.location.href !== 'string' || !globalThis.location.href) {
|
|
4375
|
+
return '';
|
|
4376
|
+
}
|
|
4377
|
+
return globalThis.location.href;
|
|
4378
|
+
};
|
|
4379
|
+
const getBackendLoginUrl = async backendUrl => {
|
|
4380
|
+
const loginUrl = new URL(getBackendAuthUrl(backendUrl, '/login'));
|
|
4381
|
+
const redirectUri = await getCurrentHref();
|
|
4382
|
+
if (redirectUri) {
|
|
4383
|
+
loginUrl.searchParams.set('redirect_uri', redirectUri);
|
|
4384
|
+
}
|
|
4385
|
+
return loginUrl.toString();
|
|
4366
4386
|
};
|
|
4367
4387
|
|
|
4368
4388
|
const getLoggedOutBackendAuthState = (authErrorMessage = '') => {
|
|
@@ -4397,16 +4417,59 @@ const logoutFromBackend = async backendUrl => {
|
|
|
4397
4417
|
}
|
|
4398
4418
|
};
|
|
4399
4419
|
|
|
4420
|
+
let nextLoginResponse;
|
|
4421
|
+
let nextRefreshResponse;
|
|
4422
|
+
const setNextLoginResponse = response => {
|
|
4423
|
+
nextLoginResponse = response;
|
|
4424
|
+
};
|
|
4425
|
+
const setNextRefreshResponse = response => {
|
|
4426
|
+
nextRefreshResponse = response;
|
|
4427
|
+
};
|
|
4428
|
+
const hasPendingMockLoginResponse = () => {
|
|
4429
|
+
return !!nextLoginResponse;
|
|
4430
|
+
};
|
|
4431
|
+
const hasPendingMockRefreshResponse = () => {
|
|
4432
|
+
return !!nextRefreshResponse;
|
|
4433
|
+
};
|
|
4434
|
+
const consumeNextLoginResponse = async () => {
|
|
4435
|
+
if (!nextLoginResponse) {
|
|
4436
|
+
return undefined;
|
|
4437
|
+
}
|
|
4438
|
+
const response = nextLoginResponse;
|
|
4439
|
+
nextLoginResponse = undefined;
|
|
4440
|
+
if (response.delay > 0) {
|
|
4441
|
+
await new Promise(resolve => setTimeout(resolve, response.delay));
|
|
4442
|
+
}
|
|
4443
|
+
if (response.type === 'error') {
|
|
4444
|
+
throw new Error(response.message);
|
|
4445
|
+
}
|
|
4446
|
+
return response.response;
|
|
4447
|
+
};
|
|
4448
|
+
const consumeNextRefreshResponse = async () => {
|
|
4449
|
+
if (!nextRefreshResponse) {
|
|
4450
|
+
return undefined;
|
|
4451
|
+
}
|
|
4452
|
+
const response = nextRefreshResponse;
|
|
4453
|
+
nextRefreshResponse = undefined;
|
|
4454
|
+
if (response.delay > 0) {
|
|
4455
|
+
await new Promise(resolve => setTimeout(resolve, response.delay));
|
|
4456
|
+
}
|
|
4457
|
+
if (response.type === 'error') {
|
|
4458
|
+
throw new Error(response.message);
|
|
4459
|
+
}
|
|
4460
|
+
return response.response;
|
|
4461
|
+
};
|
|
4462
|
+
|
|
4400
4463
|
const getBackendRefreshUrl = backendUrl => {
|
|
4401
4464
|
return getBackendAuthUrl(backendUrl, '/auth/refresh');
|
|
4402
4465
|
};
|
|
4403
4466
|
|
|
4404
|
-
const isObject$
|
|
4467
|
+
const isObject$3 = value => {
|
|
4405
4468
|
return !!value && typeof value === 'object';
|
|
4406
4469
|
};
|
|
4407
4470
|
|
|
4408
4471
|
const isBackendAuthResponse = value => {
|
|
4409
|
-
return isObject$
|
|
4472
|
+
return isObject$3(value);
|
|
4410
4473
|
};
|
|
4411
4474
|
|
|
4412
4475
|
const getNumber = (value, fallback = 0) => {
|
|
@@ -4440,6 +4503,10 @@ const syncBackendAuth = async backendUrl => {
|
|
|
4440
4503
|
return getLoggedOutBackendAuthState('Backend URL is missing.');
|
|
4441
4504
|
}
|
|
4442
4505
|
try {
|
|
4506
|
+
if (hasPendingMockRefreshResponse()) {
|
|
4507
|
+
const mockResponse = await consumeNextRefreshResponse();
|
|
4508
|
+
return parseBackendAuthResponse(mockResponse);
|
|
4509
|
+
}
|
|
4443
4510
|
const response = await fetch(getBackendRefreshUrl(backendUrl), {
|
|
4444
4511
|
credentials: 'include',
|
|
4445
4512
|
headers: {
|
|
@@ -4494,28 +4561,6 @@ const waitForBackendLogin = async (backendUrl, timeoutMs = 30_000, pollIntervalM
|
|
|
4494
4561
|
return getLoggedOutBackendAuthState(lastErrorMessage);
|
|
4495
4562
|
};
|
|
4496
4563
|
|
|
4497
|
-
let nextLoginResponse;
|
|
4498
|
-
const setNextLoginResponse = response => {
|
|
4499
|
-
nextLoginResponse = response;
|
|
4500
|
-
};
|
|
4501
|
-
const hasPendingMockLoginResponse = () => {
|
|
4502
|
-
return !!nextLoginResponse;
|
|
4503
|
-
};
|
|
4504
|
-
const consumeNextLoginResponse = async () => {
|
|
4505
|
-
if (!nextLoginResponse) {
|
|
4506
|
-
return undefined;
|
|
4507
|
-
}
|
|
4508
|
-
const response = nextLoginResponse;
|
|
4509
|
-
nextLoginResponse = undefined;
|
|
4510
|
-
if (response.delay > 0) {
|
|
4511
|
-
await new Promise(resolve => setTimeout(resolve, response.delay));
|
|
4512
|
-
}
|
|
4513
|
-
if (response.type === 'error') {
|
|
4514
|
-
throw new Error(response.message);
|
|
4515
|
-
}
|
|
4516
|
-
return response.response;
|
|
4517
|
-
};
|
|
4518
|
-
|
|
4519
4564
|
const isLoginResponse = value => {
|
|
4520
4565
|
if (!value || typeof value !== 'object') {
|
|
4521
4566
|
return false;
|
|
@@ -4570,7 +4615,8 @@ const handleClickLogin = async state => {
|
|
|
4570
4615
|
}
|
|
4571
4616
|
return getLoggedInState(signingInState, response);
|
|
4572
4617
|
}
|
|
4573
|
-
await
|
|
4618
|
+
const url = await getBackendLoginUrl(state.backendUrl);
|
|
4619
|
+
await openUrl(url, state.platform);
|
|
4574
4620
|
const authState = await waitForBackendLogin(state.backendUrl);
|
|
4575
4621
|
return {
|
|
4576
4622
|
...signingInState,
|
|
@@ -4936,6 +4982,28 @@ const getBasicChatTools = async (agentMode = defaultAgentMode, questionToolEnabl
|
|
|
4936
4982
|
}
|
|
4937
4983
|
};
|
|
4938
4984
|
|
|
4985
|
+
const getBackendErrorMessage = errorResult => {
|
|
4986
|
+
switch (errorResult.details) {
|
|
4987
|
+
case 'http-error':
|
|
4988
|
+
{
|
|
4989
|
+
const errorMessage = errorResult.errorMessage?.trim();
|
|
4990
|
+
if (typeof errorResult.statusCode === 'number') {
|
|
4991
|
+
const prefix = `Backend completion request failed (status ${errorResult.statusCode}).`;
|
|
4992
|
+
if (!errorMessage) {
|
|
4993
|
+
return prefix;
|
|
4994
|
+
}
|
|
4995
|
+
return `${prefix} ${errorMessage}`;
|
|
4996
|
+
}
|
|
4997
|
+
if (errorMessage) {
|
|
4998
|
+
return `Backend completion request failed. ${errorMessage}`;
|
|
4999
|
+
}
|
|
5000
|
+
return backendCompletionFailedMessage;
|
|
5001
|
+
}
|
|
5002
|
+
case 'request-failed':
|
|
5003
|
+
return backendCompletionFailedMessage;
|
|
5004
|
+
}
|
|
5005
|
+
};
|
|
5006
|
+
|
|
4939
5007
|
const getAttachmentTextPart = attachment => {
|
|
4940
5008
|
switch (attachment.displayType) {
|
|
4941
5009
|
case 'file':
|
|
@@ -5019,7 +5087,7 @@ const reset$1 = () => {
|
|
|
5019
5087
|
finished = false;
|
|
5020
5088
|
errorResult = undefined;
|
|
5021
5089
|
};
|
|
5022
|
-
const setHttpErrorResponse = (statusCode, body) => {
|
|
5090
|
+
const setHttpErrorResponse$1 = (statusCode, body) => {
|
|
5023
5091
|
const rawError = body && typeof body === 'object' ? Reflect.get(body, 'error') : undefined;
|
|
5024
5092
|
const errorCode = rawError && typeof rawError === 'object' ? Reflect.get(rawError, 'code') : undefined;
|
|
5025
5093
|
const errorMessage = rawError && typeof rawError === 'object' ? Reflect.get(rawError, 'message') : undefined;
|
|
@@ -5048,7 +5116,7 @@ const setRequestFailedResponse = (isOffline = false) => {
|
|
|
5048
5116
|
type: 'error'
|
|
5049
5117
|
};
|
|
5050
5118
|
};
|
|
5051
|
-
const takeErrorResponse = () => {
|
|
5119
|
+
const takeErrorResponse$1 = () => {
|
|
5052
5120
|
const error = errorResult;
|
|
5053
5121
|
errorResult = undefined;
|
|
5054
5122
|
return error;
|
|
@@ -5180,7 +5248,7 @@ const emitToolCalls = async (toolCallAccumulator, onToolCallsChunk) => {
|
|
|
5180
5248
|
await onToolCallsChunk(toolCalls);
|
|
5181
5249
|
};
|
|
5182
5250
|
const getMockOpenApiAssistantText = async (stream, onTextChunk, onToolCallsChunk, onDataEvent, onEventStreamFinished) => {
|
|
5183
|
-
const error = takeErrorResponse();
|
|
5251
|
+
const error = takeErrorResponse$1();
|
|
5184
5252
|
if (error) {
|
|
5185
5253
|
return error;
|
|
5186
5254
|
}
|
|
@@ -7104,38 +7172,151 @@ const isOpenRouterModel = (selectedModelId, models) => {
|
|
|
7104
7172
|
return selectedModelId.toLowerCase().startsWith('openrouter/');
|
|
7105
7173
|
};
|
|
7106
7174
|
|
|
7175
|
+
let errorResponse;
|
|
7176
|
+
const setHttpErrorResponse = (statusCode, body) => {
|
|
7177
|
+
errorResponse = {
|
|
7178
|
+
body,
|
|
7179
|
+
statusCode,
|
|
7180
|
+
type: 'http-error'
|
|
7181
|
+
};
|
|
7182
|
+
};
|
|
7183
|
+
const takeErrorResponse = () => {
|
|
7184
|
+
const response = errorResponse;
|
|
7185
|
+
errorResponse = undefined;
|
|
7186
|
+
return response;
|
|
7187
|
+
};
|
|
7188
|
+
|
|
7107
7189
|
/* eslint-disable prefer-destructuring */
|
|
7108
7190
|
|
|
7109
7191
|
const trailingSlashesRegex = /\/+$/;
|
|
7110
|
-
const
|
|
7192
|
+
const getBackendResponsesEndpoint = backendUrl => {
|
|
7111
7193
|
const trimmedBackendUrl = backendUrl.replace(trailingSlashesRegex, '');
|
|
7112
|
-
return `${trimmedBackendUrl}/v1/
|
|
7113
|
-
};
|
|
7114
|
-
const getEffectiveBackendModelId = selectedModelId => {
|
|
7115
|
-
const separatorIndex = selectedModelId.indexOf('/');
|
|
7116
|
-
if (separatorIndex === -1) {
|
|
7117
|
-
return selectedModelId;
|
|
7118
|
-
}
|
|
7119
|
-
return selectedModelId.slice(separatorIndex + 1);
|
|
7194
|
+
return `${trimmedBackendUrl}/v1/responses`;
|
|
7120
7195
|
};
|
|
7121
7196
|
const hasImageAttachments = messages => {
|
|
7122
7197
|
return messages.some(message => message.attachments?.some(attachment => attachment.displayType === 'image'));
|
|
7123
7198
|
};
|
|
7124
|
-
const
|
|
7199
|
+
const isObject$2 = value => {
|
|
7200
|
+
return !!value && typeof value === 'object';
|
|
7201
|
+
};
|
|
7202
|
+
const getBackendErrorMessageFromBody = body => {
|
|
7203
|
+
if (!isObject$2(body)) {
|
|
7204
|
+
return undefined;
|
|
7205
|
+
}
|
|
7206
|
+
const directMessage = Reflect.get(body, 'message');
|
|
7207
|
+
if (typeof directMessage === 'string' && directMessage) {
|
|
7208
|
+
return directMessage;
|
|
7209
|
+
}
|
|
7210
|
+
const directError = Reflect.get(body, 'error');
|
|
7211
|
+
if (typeof directError === 'string' && directError) {
|
|
7212
|
+
return directError;
|
|
7213
|
+
}
|
|
7214
|
+
if (!isObject$2(directError)) {
|
|
7215
|
+
return undefined;
|
|
7216
|
+
}
|
|
7217
|
+
const nestedMessage = Reflect.get(directError, 'message');
|
|
7218
|
+
if (typeof nestedMessage === 'string' && nestedMessage) {
|
|
7219
|
+
return nestedMessage;
|
|
7220
|
+
}
|
|
7221
|
+
return undefined;
|
|
7222
|
+
};
|
|
7223
|
+
const getBackendStatusCodeFromBody = body => {
|
|
7224
|
+
if (!isObject$2(body)) {
|
|
7225
|
+
return undefined;
|
|
7226
|
+
}
|
|
7227
|
+
const statusCode = Reflect.get(body, 'statusCode');
|
|
7228
|
+
if (typeof statusCode === 'number') {
|
|
7229
|
+
return statusCode;
|
|
7230
|
+
}
|
|
7231
|
+
return undefined;
|
|
7232
|
+
};
|
|
7233
|
+
const getBackendResponseOutputText = body => {
|
|
7234
|
+
if (!isObject$2(body)) {
|
|
7235
|
+
return '';
|
|
7236
|
+
}
|
|
7237
|
+
const outputText = Reflect.get(body, 'output_text');
|
|
7238
|
+
if (typeof outputText === 'string' && outputText) {
|
|
7239
|
+
return outputText;
|
|
7240
|
+
}
|
|
7241
|
+
const text = Reflect.get(body, 'text');
|
|
7242
|
+
if (typeof text === 'string' && text) {
|
|
7243
|
+
return text;
|
|
7244
|
+
}
|
|
7245
|
+
const message = Reflect.get(body, 'message');
|
|
7246
|
+
if (isObject$2(message)) {
|
|
7247
|
+
const content = Reflect.get(message, 'content');
|
|
7248
|
+
if (typeof content === 'string' && content) {
|
|
7249
|
+
return content;
|
|
7250
|
+
}
|
|
7251
|
+
}
|
|
7252
|
+
const choices = Reflect.get(body, 'choices');
|
|
7253
|
+
if (Array.isArray(choices)) {
|
|
7254
|
+
const firstChoice = choices[0];
|
|
7255
|
+
if (isObject$2(firstChoice)) {
|
|
7256
|
+
const firstMessage = Reflect.get(firstChoice, 'message');
|
|
7257
|
+
if (isObject$2(firstMessage)) {
|
|
7258
|
+
const content = Reflect.get(firstMessage, 'content');
|
|
7259
|
+
if (typeof content === 'string' && content) {
|
|
7260
|
+
return content;
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7264
|
+
}
|
|
7265
|
+
const output = Reflect.get(body, 'output');
|
|
7266
|
+
if (!Array.isArray(output)) {
|
|
7267
|
+
return '';
|
|
7268
|
+
}
|
|
7269
|
+
const chunks = [];
|
|
7270
|
+
for (const outputItem of output) {
|
|
7271
|
+
if (!isObject$2(outputItem)) {
|
|
7272
|
+
continue;
|
|
7273
|
+
}
|
|
7274
|
+
if (Reflect.get(outputItem, 'type') !== 'message') {
|
|
7275
|
+
continue;
|
|
7276
|
+
}
|
|
7277
|
+
const content = Reflect.get(outputItem, 'content');
|
|
7278
|
+
if (!Array.isArray(content)) {
|
|
7279
|
+
continue;
|
|
7280
|
+
}
|
|
7281
|
+
for (const part of content) {
|
|
7282
|
+
if (!isObject$2(part)) {
|
|
7283
|
+
continue;
|
|
7284
|
+
}
|
|
7285
|
+
const type = Reflect.get(part, 'type');
|
|
7286
|
+
const text = Reflect.get(part, 'text');
|
|
7287
|
+
if ((type === 'output_text' || type === 'text') && typeof text === 'string' && text) {
|
|
7288
|
+
chunks.push(text);
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
return chunks.join('');
|
|
7293
|
+
};
|
|
7294
|
+
const getBackendResponsesBody = (messages, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, reasoningEffort, supportsReasoningEffort = false) => {
|
|
7295
|
+
const input = messages.map(message => ({
|
|
7296
|
+
content: getChatMessageOpenAiContent(message),
|
|
7297
|
+
role: message.role
|
|
7298
|
+
}));
|
|
7299
|
+
return getOpenAiParams(input, modelId, false, false, tools, webSearchEnabled, maxToolCalls, systemPrompt, undefined, reasoningEffort, supportsReasoningEffort);
|
|
7300
|
+
};
|
|
7301
|
+
const getBackendAssistantText = async (messages, modelId, backendUrl, authAccessToken, systemPrompt, agentMode = defaultAgentMode, questionToolEnabled = false, toolEnablement, maxToolCalls = defaultMaxToolCalls, webSearchEnabled = false, reasoningEffort, supportsReasoningEffort = false) => {
|
|
7302
|
+
const mockError = takeErrorResponse();
|
|
7303
|
+
if (mockError) {
|
|
7304
|
+
const errorMessage = getBackendErrorMessageFromBody(mockError.body);
|
|
7305
|
+
return getBackendErrorMessage({
|
|
7306
|
+
details: 'http-error',
|
|
7307
|
+
...(typeof mockError.statusCode === 'number' ? {
|
|
7308
|
+
statusCode: mockError.statusCode
|
|
7309
|
+
} : {}),
|
|
7310
|
+
...(errorMessage ? {
|
|
7311
|
+
errorMessage
|
|
7312
|
+
} : {})
|
|
7313
|
+
});
|
|
7314
|
+
}
|
|
7125
7315
|
let response;
|
|
7126
7316
|
try {
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
content: systemPrompt,
|
|
7131
|
-
role: 'system'
|
|
7132
|
-
}] : []), ...messages.map(message => ({
|
|
7133
|
-
content: message.text,
|
|
7134
|
-
role: message.role
|
|
7135
|
-
}))],
|
|
7136
|
-
model: getEffectiveBackendModelId(selectedModelId),
|
|
7137
|
-
stream: false
|
|
7138
|
-
}),
|
|
7317
|
+
const tools = await getBasicChatTools(agentMode, questionToolEnabled, toolEnablement);
|
|
7318
|
+
response = await fetch(getBackendResponsesEndpoint(backendUrl), {
|
|
7319
|
+
body: JSON.stringify(getBackendResponsesBody(messages, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, reasoningEffort, supportsReasoningEffort)),
|
|
7139
7320
|
headers: {
|
|
7140
7321
|
Authorization: `Bearer ${authAccessToken}`,
|
|
7141
7322
|
'Content-Type': 'application/json',
|
|
@@ -7144,20 +7325,37 @@ const getBackendAssistantText = async (messages, selectedModelId, backendUrl, au
|
|
|
7144
7325
|
method: 'POST'
|
|
7145
7326
|
});
|
|
7146
7327
|
} catch {
|
|
7147
|
-
return
|
|
7328
|
+
return getBackendErrorMessage({
|
|
7329
|
+
details: 'request-failed'
|
|
7330
|
+
});
|
|
7148
7331
|
}
|
|
7149
7332
|
if (!response.ok) {
|
|
7333
|
+
const payload = await response.json().catch(() => undefined);
|
|
7334
|
+
const errorMessage = getBackendErrorMessageFromBody(payload);
|
|
7335
|
+
const statusCode = response.status || getBackendStatusCodeFromBody(payload);
|
|
7336
|
+
return getBackendErrorMessage({
|
|
7337
|
+
details: 'http-error',
|
|
7338
|
+
...(typeof statusCode === 'number' ? {
|
|
7339
|
+
statusCode
|
|
7340
|
+
} : {}),
|
|
7341
|
+
...(errorMessage ? {
|
|
7342
|
+
errorMessage
|
|
7343
|
+
} : {})
|
|
7344
|
+
});
|
|
7345
|
+
}
|
|
7346
|
+
let json;
|
|
7347
|
+
try {
|
|
7348
|
+
json = await response.json();
|
|
7349
|
+
} catch {
|
|
7150
7350
|
return backendCompletionFailedMessage;
|
|
7151
7351
|
}
|
|
7152
|
-
const
|
|
7153
|
-
const content = json.choices?.[0]?.message?.content;
|
|
7352
|
+
const content = getBackendResponseOutputText(json);
|
|
7154
7353
|
return typeof content === 'string' && content ? content : backendCompletionFailedMessage;
|
|
7155
7354
|
};
|
|
7156
7355
|
const getAiResponse = async ({
|
|
7157
7356
|
agentMode = defaultAgentMode,
|
|
7158
7357
|
assetDir,
|
|
7159
7358
|
authAccessToken,
|
|
7160
|
-
authEnabled = false,
|
|
7161
7359
|
backendUrl = '',
|
|
7162
7360
|
maxToolCalls = defaultMaxToolCalls,
|
|
7163
7361
|
messageId,
|
|
@@ -7188,12 +7386,13 @@ const getAiResponse = async ({
|
|
|
7188
7386
|
useChatNetworkWorkerForRequests = false,
|
|
7189
7387
|
useChatToolWorker = true,
|
|
7190
7388
|
useMockApi,
|
|
7389
|
+
useOwnBackend = false,
|
|
7191
7390
|
userText,
|
|
7192
7391
|
webSearchEnabled = false,
|
|
7193
7392
|
workspaceUri
|
|
7194
7393
|
}) => {
|
|
7195
7394
|
useChatCoordinatorWorker = false; // TODO enable this
|
|
7196
|
-
if (useChatCoordinatorWorker && !
|
|
7395
|
+
if (useChatCoordinatorWorker && !useOwnBackend) {
|
|
7197
7396
|
try {
|
|
7198
7397
|
const result = await getAiResponse$1({
|
|
7199
7398
|
agentMode,
|
|
@@ -7251,20 +7450,20 @@ const getAiResponse = async ({
|
|
|
7251
7450
|
const selectedModel = models.find(model => model.id === selectedModelId);
|
|
7252
7451
|
const supportsImages = selectedModel?.supportsImages ?? false;
|
|
7253
7452
|
const supportsReasoningEffort = selectedModel?.supportsReasoningEffort ?? false;
|
|
7453
|
+
const safeMaxToolCalls = Math.max(1, maxToolCalls);
|
|
7254
7454
|
if (hasImageAttachments(messages) && !supportsImages) {
|
|
7255
7455
|
text = getImageNotSupportedMessage(selectedModel?.name);
|
|
7256
7456
|
}
|
|
7257
|
-
if (!text &&
|
|
7457
|
+
if (!text && useOwnBackend) {
|
|
7258
7458
|
if (!backendUrl) {
|
|
7259
7459
|
text = backendUrlRequiredMessage;
|
|
7260
7460
|
} else if (authAccessToken) {
|
|
7261
|
-
text = await getBackendAssistantText(messages, selectedModelId, backendUrl, authAccessToken, systemPrompt);
|
|
7461
|
+
text = await getBackendAssistantText(messages, getOpenApiModelId(selectedModelId), backendUrl, authAccessToken, systemPrompt, agentMode, questionToolEnabled, toolEnablement, safeMaxToolCalls, agentMode === 'plan' ? false : webSearchEnabled, reasoningEffort, supportsReasoningEffort);
|
|
7262
7462
|
} else {
|
|
7263
7463
|
text = backendAccessTokenRequiredMessage;
|
|
7264
7464
|
}
|
|
7265
7465
|
}
|
|
7266
7466
|
if (!text && usesOpenApiModel) {
|
|
7267
|
-
const safeMaxToolCalls = Math.max(1, maxToolCalls);
|
|
7268
7467
|
if (useMockApi) {
|
|
7269
7468
|
const openAiInput = messages.map(message => ({
|
|
7270
7469
|
content: getChatMessageOpenAiContent(message),
|
|
@@ -7582,6 +7781,7 @@ const handleClickSaveOpenApiApiKey = async state => {
|
|
|
7582
7781
|
useChatCoordinatorWorker: updatedState.useChatCoordinatorWorker,
|
|
7583
7782
|
useChatNetworkWorkerForRequests: updatedState.useChatNetworkWorkerForRequests,
|
|
7584
7783
|
useMockApi: updatedState.useMockApi,
|
|
7784
|
+
useOwnBackend: updatedState.useOwnBackend,
|
|
7585
7785
|
userText: previousUserMessage.text
|
|
7586
7786
|
});
|
|
7587
7787
|
const parsedMessages = await parseAndStoreMessageContent(updatedState.parsedMessages, assistantMessage);
|
|
@@ -7670,6 +7870,7 @@ const handleClickSaveOpenRouterApiKey = async state => {
|
|
|
7670
7870
|
useChatCoordinatorWorker: updatedState.useChatCoordinatorWorker,
|
|
7671
7871
|
useChatNetworkWorkerForRequests: updatedState.useChatNetworkWorkerForRequests,
|
|
7672
7872
|
useMockApi: updatedState.useMockApi,
|
|
7873
|
+
useOwnBackend: updatedState.useOwnBackend,
|
|
7673
7874
|
userText: previousUserMessage.text
|
|
7674
7875
|
});
|
|
7675
7876
|
const parsedMessages = await parseAndStoreMessageContent(updatedState.parsedMessages, assistantMessage);
|
|
@@ -7781,7 +7982,6 @@ Assistant: ${assistantText}`;
|
|
|
7781
7982
|
const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
7782
7983
|
const {
|
|
7783
7984
|
authAccessToken,
|
|
7784
|
-
authEnabled,
|
|
7785
7985
|
backendUrl,
|
|
7786
7986
|
models,
|
|
7787
7987
|
openApiApiBaseUrl,
|
|
@@ -7789,21 +7989,28 @@ const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
|
7789
7989
|
openRouterApiBaseUrl,
|
|
7790
7990
|
openRouterApiKey,
|
|
7791
7991
|
selectedModelId,
|
|
7792
|
-
useMockApi
|
|
7992
|
+
useMockApi,
|
|
7993
|
+
useOwnBackend
|
|
7793
7994
|
} = state;
|
|
7794
7995
|
if (useMockApi) {
|
|
7795
7996
|
return '';
|
|
7796
7997
|
}
|
|
7797
7998
|
const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
|
|
7798
7999
|
const usesOpenRouterModel = isOpenRouterModel(selectedModelId, models);
|
|
7799
|
-
if (
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
8000
|
+
if (useOwnBackend) {
|
|
8001
|
+
if (!backendUrl || !authAccessToken) {
|
|
8002
|
+
return '';
|
|
8003
|
+
}
|
|
8004
|
+
} else {
|
|
8005
|
+
if (usesOpenApiModel && !openApiApiKey) {
|
|
8006
|
+
return '';
|
|
8007
|
+
}
|
|
8008
|
+
if (usesOpenRouterModel && !openRouterApiKey) {
|
|
8009
|
+
return '';
|
|
8010
|
+
}
|
|
8011
|
+
if (!usesOpenApiModel && !usesOpenRouterModel) {
|
|
8012
|
+
return '';
|
|
8013
|
+
}
|
|
7807
8014
|
}
|
|
7808
8015
|
const titlePrompt = getTitlePrompt(userText, assistantText);
|
|
7809
8016
|
const promptMessage = {
|
|
@@ -7818,7 +8025,6 @@ const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
|
7818
8025
|
const titleResponse = await getAiResponse({
|
|
7819
8026
|
assetDir: state.assetDir,
|
|
7820
8027
|
authAccessToken,
|
|
7821
|
-
authEnabled,
|
|
7822
8028
|
backendUrl,
|
|
7823
8029
|
maxToolCalls: state.maxToolCalls,
|
|
7824
8030
|
messages: [promptMessage],
|
|
@@ -7839,6 +8045,7 @@ const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
|
7839
8045
|
useChatNetworkWorkerForRequests: state.useChatNetworkWorkerForRequests,
|
|
7840
8046
|
useChatToolWorker: state.useChatToolWorker,
|
|
7841
8047
|
useMockApi,
|
|
8048
|
+
useOwnBackend,
|
|
7842
8049
|
userText: titlePrompt,
|
|
7843
8050
|
webSearchEnabled: false
|
|
7844
8051
|
});
|
|
@@ -8279,7 +8486,8 @@ const withProvisionedBackgroundSession = async (state, session) => {
|
|
|
8279
8486
|
};
|
|
8280
8487
|
};
|
|
8281
8488
|
const handleSubmit = async state => {
|
|
8282
|
-
const
|
|
8489
|
+
const shouldSyncBackendAuth = (state.authEnabled || state.useOwnBackend) && !!state.backendUrl;
|
|
8490
|
+
const authState = shouldSyncBackendAuth ? await syncBackendAuth(state.backendUrl) : undefined;
|
|
8283
8491
|
const effectiveState = authState ? {
|
|
8284
8492
|
...state,
|
|
8285
8493
|
...authState
|
|
@@ -8315,6 +8523,7 @@ const handleSubmit = async state => {
|
|
|
8315
8523
|
useChatNetworkWorkerForRequests,
|
|
8316
8524
|
useChatToolWorker,
|
|
8317
8525
|
useMockApi,
|
|
8526
|
+
useOwnBackend,
|
|
8318
8527
|
viewMode,
|
|
8319
8528
|
webSearchEnabled
|
|
8320
8529
|
} = effectiveState;
|
|
@@ -8532,6 +8741,7 @@ const handleSubmit = async state => {
|
|
|
8532
8741
|
useChatNetworkWorkerForRequests,
|
|
8533
8742
|
useChatToolWorker,
|
|
8534
8743
|
useMockApi,
|
|
8744
|
+
useOwnBackend,
|
|
8535
8745
|
userText,
|
|
8536
8746
|
webSearchEnabled,
|
|
8537
8747
|
workspaceUri
|
|
@@ -10318,6 +10528,15 @@ const loadUseChatToolWorker = async () => {
|
|
|
10318
10528
|
}
|
|
10319
10529
|
};
|
|
10320
10530
|
|
|
10531
|
+
const loadUseOwnBackend = async () => {
|
|
10532
|
+
try {
|
|
10533
|
+
const savedUseOwnBackend = await get('chat.useOwnBackend');
|
|
10534
|
+
return typeof savedUseOwnBackend === 'boolean' ? savedUseOwnBackend : false;
|
|
10535
|
+
} catch {
|
|
10536
|
+
return false;
|
|
10537
|
+
}
|
|
10538
|
+
};
|
|
10539
|
+
|
|
10321
10540
|
const loadVoiceDictationEnabled = async () => {
|
|
10322
10541
|
try {
|
|
10323
10542
|
const savedVoiceDictationEnabled = await get('chatView.voiceDictationEnabled');
|
|
@@ -10328,7 +10547,7 @@ const loadVoiceDictationEnabled = async () => {
|
|
|
10328
10547
|
};
|
|
10329
10548
|
|
|
10330
10549
|
const loadPreferences = async () => {
|
|
10331
|
-
const [aiSessionTitleGenerationEnabled, authEnabled, backendUrl, chatHistoryEnabled, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, reasoningPickerEnabled, scrollDownButtonEnabled, searchEnabled, streamingEnabled, todoListToolEnabled, toolEnablement, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatNetworkWorkerForRequests, useChatToolWorker, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadAuthEnabled(), loadBackendUrl(), loadChatHistoryEnabled(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadReasoningPickerEnabled(), loadScrollDownButtonEnabled(), loadSearchEnabled(), loadStreamingEnabled(), loadTodoListToolEnabled(), loadToolEnablement(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadVoiceDictationEnabled()]);
|
|
10550
|
+
const [aiSessionTitleGenerationEnabled, authEnabled, backendUrl, chatHistoryEnabled, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, reasoningPickerEnabled, scrollDownButtonEnabled, searchEnabled, streamingEnabled, todoListToolEnabled, toolEnablement, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatNetworkWorkerForRequests, useChatToolWorker, useOwnBackend, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadAuthEnabled(), loadBackendUrl(), loadChatHistoryEnabled(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadReasoningPickerEnabled(), loadScrollDownButtonEnabled(), loadSearchEnabled(), loadStreamingEnabled(), loadTodoListToolEnabled(), loadToolEnablement(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadUseOwnBackend(), loadVoiceDictationEnabled()]);
|
|
10332
10551
|
return {
|
|
10333
10552
|
aiSessionTitleGenerationEnabled,
|
|
10334
10553
|
authEnabled,
|
|
@@ -10349,6 +10568,7 @@ const loadPreferences = async () => {
|
|
|
10349
10568
|
useChatMathWorker,
|
|
10350
10569
|
useChatNetworkWorkerForRequests,
|
|
10351
10570
|
useChatToolWorker,
|
|
10571
|
+
useOwnBackend,
|
|
10352
10572
|
voiceDictationEnabled
|
|
10353
10573
|
};
|
|
10354
10574
|
};
|
|
@@ -10420,9 +10640,10 @@ const loadContent = async (state, savedState) => {
|
|
|
10420
10640
|
useChatMathWorker,
|
|
10421
10641
|
useChatNetworkWorkerForRequests,
|
|
10422
10642
|
useChatToolWorker,
|
|
10643
|
+
useOwnBackend,
|
|
10423
10644
|
voiceDictationEnabled
|
|
10424
10645
|
} = await loadPreferences();
|
|
10425
|
-
const authState = authEnabled
|
|
10646
|
+
const authState = authEnabled || useOwnBackend ? backendUrl ? await syncBackendAuth(backendUrl) : getLoggedOutBackendAuthState() : getLoggedOutBackendAuthState();
|
|
10426
10647
|
const legacySavedSessions = getSavedSessions(savedState);
|
|
10427
10648
|
const storedSessions = await listChatSessions();
|
|
10428
10649
|
let sessions = storedSessions;
|
|
@@ -10530,6 +10751,7 @@ const loadContent = async (state, savedState) => {
|
|
|
10530
10751
|
useChatMathWorker,
|
|
10531
10752
|
useChatNetworkWorkerForRequests,
|
|
10532
10753
|
useChatToolWorker,
|
|
10754
|
+
useOwnBackend,
|
|
10533
10755
|
userName: authState.userName,
|
|
10534
10756
|
userState: authState.userState,
|
|
10535
10757
|
userSubscriptionPlan: authState.userSubscriptionPlan,
|
|
@@ -10555,15 +10777,19 @@ const getDelay = payload => {
|
|
|
10555
10777
|
};
|
|
10556
10778
|
const mockBackendAuthResponse = (state, payload) => {
|
|
10557
10779
|
const delay = getDelay(payload);
|
|
10780
|
+
const setNextResponse = payload.request === 'refresh' ? setNextRefreshResponse : setNextLoginResponse;
|
|
10558
10781
|
if (payload.type === 'error') {
|
|
10559
|
-
|
|
10782
|
+
setNextResponse({
|
|
10560
10783
|
delay,
|
|
10784
|
+
...(payload.errorName ? {
|
|
10785
|
+
errorName: payload.errorName
|
|
10786
|
+
} : {}),
|
|
10561
10787
|
message: payload.message || 'Backend authentication failed.',
|
|
10562
10788
|
type: 'error'
|
|
10563
10789
|
});
|
|
10564
10790
|
return state;
|
|
10565
10791
|
}
|
|
10566
|
-
|
|
10792
|
+
setNextResponse({
|
|
10567
10793
|
delay,
|
|
10568
10794
|
response: payload,
|
|
10569
10795
|
type: 'success'
|
|
@@ -10571,6 +10797,11 @@ const mockBackendAuthResponse = (state, payload) => {
|
|
|
10571
10797
|
return state;
|
|
10572
10798
|
};
|
|
10573
10799
|
|
|
10800
|
+
const mockBackendSetHttpErrorResponse = (state, statusCode, body) => {
|
|
10801
|
+
setHttpErrorResponse(statusCode, body);
|
|
10802
|
+
return state;
|
|
10803
|
+
};
|
|
10804
|
+
|
|
10574
10805
|
const mockOpenApiRequestGetAll = _state => {
|
|
10575
10806
|
return getAll();
|
|
10576
10807
|
};
|
|
@@ -10581,7 +10812,7 @@ const mockOpenApiRequestReset = state => {
|
|
|
10581
10812
|
};
|
|
10582
10813
|
|
|
10583
10814
|
const mockOpenApiSetHttpErrorResponse = (state, statusCode, body) => {
|
|
10584
|
-
setHttpErrorResponse(statusCode, body);
|
|
10815
|
+
setHttpErrorResponse$1(statusCode, body);
|
|
10585
10816
|
return state;
|
|
10586
10817
|
};
|
|
10587
10818
|
|
|
@@ -15544,6 +15775,18 @@ const setUseChatNetworkWorkerForRequests = async (state, useChatNetworkWorkerFor
|
|
|
15544
15775
|
};
|
|
15545
15776
|
};
|
|
15546
15777
|
|
|
15778
|
+
const setUseOwnBackend = async (state, useOwnBackend, persist = true) => {
|
|
15779
|
+
if (persist) {
|
|
15780
|
+
await update({
|
|
15781
|
+
'chat.useOwnBackend': useOwnBackend
|
|
15782
|
+
});
|
|
15783
|
+
}
|
|
15784
|
+
return {
|
|
15785
|
+
...state,
|
|
15786
|
+
useOwnBackend
|
|
15787
|
+
};
|
|
15788
|
+
};
|
|
15789
|
+
|
|
15547
15790
|
const defaultMockApiCommandId = 'ChatE2e.mockApi';
|
|
15548
15791
|
const useMockApi = (state, value, mockApiCommandId = defaultMockApiCommandId) => {
|
|
15549
15792
|
if (!value) {
|
|
@@ -15644,6 +15887,7 @@ const commandMap = {
|
|
|
15644
15887
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
15645
15888
|
'Chat.loadContent2': wrapCommand(loadContent),
|
|
15646
15889
|
'Chat.mockBackendAuthResponse': wrapCommand(mockBackendAuthResponse),
|
|
15890
|
+
'Chat.mockBackendSetHttpErrorResponse': wrapCommand(mockBackendSetHttpErrorResponse),
|
|
15647
15891
|
'Chat.mockOpenApiRequestGetAll': wrapGetter(mockOpenApiRequestGetAll),
|
|
15648
15892
|
'Chat.mockOpenApiRequestReset': wrapCommand(mockOpenApiRequestReset),
|
|
15649
15893
|
'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
|
|
@@ -15689,6 +15933,7 @@ const commandMap = {
|
|
|
15689
15933
|
'Chat.setUseChatCoordinatorWorker': wrapCommand(setUseChatCoordinatorWorker),
|
|
15690
15934
|
'Chat.setUseChatMathWorker': wrapCommand(setUseChatMathWorker),
|
|
15691
15935
|
'Chat.setUseChatNetworkWorkerForRequests': wrapCommand(setUseChatNetworkWorkerForRequests),
|
|
15936
|
+
'Chat.setUseOwnBackend': wrapCommand(setUseOwnBackend),
|
|
15692
15937
|
'Chat.showComposerAttachmentPreviewOverlay': wrapCommand(showComposerAttachmentPreviewOverlay),
|
|
15693
15938
|
'Chat.terminate': terminate,
|
|
15694
15939
|
'Chat.useMockApi': wrapCommand(useMockApi)
|