@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.
@@ -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 getBackendLoginUrl = backendUrl => {
4365
- return getBackendAuthUrl(backendUrl, '/auth/login');
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$2 = value => {
4467
+ const isObject$3 = value => {
4405
4468
  return !!value && typeof value === 'object';
4406
4469
  };
4407
4470
 
4408
4471
  const isBackendAuthResponse = value => {
4409
- return isObject$2(value);
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 invoke('Main.openUri', getBackendLoginUrl(state.backendUrl));
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 getBackendCompletionsEndpoint = backendUrl => {
7192
+ const getBackendResponsesEndpoint = backendUrl => {
7111
7193
  const trimmedBackendUrl = backendUrl.replace(trailingSlashesRegex, '');
7112
- return `${trimmedBackendUrl}/v1/chat/completions`;
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 getBackendAssistantText = async (messages, selectedModelId, backendUrl, authAccessToken, systemPrompt) => {
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
- response = await fetch(getBackendCompletionsEndpoint(backendUrl), {
7128
- body: JSON.stringify({
7129
- messages: [...(systemPrompt ? [{
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 backendCompletionFailedMessage;
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 json = await response.json();
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 && !authEnabled) {
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 && authEnabled) {
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 (!authEnabled && usesOpenApiModel && !openApiApiKey) {
7800
- return '';
7801
- }
7802
- if (!authEnabled && usesOpenRouterModel && !openRouterApiKey) {
7803
- return '';
7804
- }
7805
- if (!authEnabled && !usesOpenApiModel && !usesOpenRouterModel) {
7806
- return '';
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 authState = state.authEnabled && state.backendUrl ? await syncBackendAuth(state.backendUrl) : undefined;
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 && backendUrl ? await syncBackendAuth(backendUrl) : getLoggedOutBackendAuthState();
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
- setNextLoginResponse({
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
- setNextLoginResponse({
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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "7.7.0",
3
+ "version": "7.10.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",