@lvce-editor/chat-view 7.10.0 → 7.11.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.
@@ -2283,7 +2283,7 @@ const getVisibleModels = (models, modelPickerSearchValue) => {
2283
2283
  };
2284
2284
 
2285
2285
  const reasoningEfforts = ['extra-high', 'high', 'medium', 'low'];
2286
- const defaultReasoningEffort = 'high';
2286
+ const defaultReasoningEffort = 'medium';
2287
2287
  const isReasoningEffort = value => {
2288
2288
  return reasoningEfforts.includes(value);
2289
2289
  };
@@ -4999,8 +4999,22 @@ const getBackendErrorMessage = errorResult => {
4999
4999
  }
5000
5000
  return backendCompletionFailedMessage;
5001
5001
  }
5002
+ case 'invalid-response':
5003
+ {
5004
+ const errorMessage = errorResult.errorMessage?.trim();
5005
+ if (errorMessage) {
5006
+ return `Backend completion request failed. ${errorMessage}`;
5007
+ }
5008
+ return 'Backend completion request failed. Unexpected backend response format.';
5009
+ }
5002
5010
  case 'request-failed':
5003
- return backendCompletionFailedMessage;
5011
+ {
5012
+ const errorMessage = errorResult.errorMessage?.trim();
5013
+ if (errorMessage) {
5014
+ return `Backend completion request failed. ${errorMessage}`;
5015
+ }
5016
+ return backendCompletionFailedMessage;
5017
+ }
5004
5018
  }
5005
5019
  };
5006
5020
 
@@ -7173,6 +7187,7 @@ const isOpenRouterModel = (selectedModelId, models) => {
7173
7187
  };
7174
7188
 
7175
7189
  let errorResponse;
7190
+ let successResponse;
7176
7191
  const setHttpErrorResponse = (statusCode, body) => {
7177
7192
  errorResponse = {
7178
7193
  body,
@@ -7180,11 +7195,22 @@ const setHttpErrorResponse = (statusCode, body) => {
7180
7195
  type: 'http-error'
7181
7196
  };
7182
7197
  };
7198
+ const setResponse = body => {
7199
+ successResponse = {
7200
+ body,
7201
+ type: 'success'
7202
+ };
7203
+ };
7183
7204
  const takeErrorResponse = () => {
7184
7205
  const response = errorResponse;
7185
7206
  errorResponse = undefined;
7186
7207
  return response;
7187
7208
  };
7209
+ const takeResponse = () => {
7210
+ const response = successResponse;
7211
+ successResponse = undefined;
7212
+ return response;
7213
+ };
7188
7214
 
7189
7215
  /* eslint-disable prefer-destructuring */
7190
7216
 
@@ -7230,6 +7256,109 @@ const getBackendStatusCodeFromBody = body => {
7230
7256
  }
7231
7257
  return undefined;
7232
7258
  };
7259
+ const getBackendResponseId = body => {
7260
+ if (!isObject$2(body)) {
7261
+ return undefined;
7262
+ }
7263
+ const id = Reflect.get(body, 'id');
7264
+ return typeof id === 'string' && id ? id : undefined;
7265
+ };
7266
+ const getBackendResponseStatus = body => {
7267
+ if (!isObject$2(body)) {
7268
+ return undefined;
7269
+ }
7270
+ const status = Reflect.get(body, 'status');
7271
+ return typeof status === 'string' && status ? status : undefined;
7272
+ };
7273
+ const getBackendIncompleteMessage = body => {
7274
+ if (!isObject$2(body)) {
7275
+ return undefined;
7276
+ }
7277
+ const incompleteDetails = Reflect.get(body, 'incomplete_details');
7278
+ if (!isObject$2(incompleteDetails)) {
7279
+ return undefined;
7280
+ }
7281
+ const reason = Reflect.get(incompleteDetails, 'reason');
7282
+ if (typeof reason === 'string' && reason) {
7283
+ return `Backend response was incomplete (${reason}).`;
7284
+ }
7285
+ return undefined;
7286
+ };
7287
+ const getBackendResponseFunctionCalls = body => {
7288
+ if (!isObject$2(body)) {
7289
+ return [];
7290
+ }
7291
+ const output = Reflect.get(body, 'output');
7292
+ if (!Array.isArray(output)) {
7293
+ return [];
7294
+ }
7295
+ const calls = [];
7296
+ for (const outputItem of output) {
7297
+ if (!isObject$2(outputItem)) {
7298
+ continue;
7299
+ }
7300
+ if (Reflect.get(outputItem, 'type') !== 'function_call') {
7301
+ continue;
7302
+ }
7303
+ const callId = Reflect.get(outputItem, 'call_id');
7304
+ const name = Reflect.get(outputItem, 'name');
7305
+ const rawArguments = Reflect.get(outputItem, 'arguments');
7306
+ if (typeof callId !== 'string' || !callId || typeof name !== 'string' || !name) {
7307
+ continue;
7308
+ }
7309
+ calls.push({
7310
+ arguments: typeof rawArguments === 'string' ? rawArguments : '',
7311
+ callId,
7312
+ name
7313
+ });
7314
+ }
7315
+ return calls;
7316
+ };
7317
+ const getErrorMessage = error => {
7318
+ if (error instanceof Error) {
7319
+ return error.message;
7320
+ }
7321
+ return typeof error === 'string' && error ? error : undefined;
7322
+ };
7323
+ const getBackendInvalidResponseDetails = body => {
7324
+ const errorMessage = getBackendErrorMessageFromBody(body);
7325
+ if (errorMessage) {
7326
+ return errorMessage;
7327
+ }
7328
+ const incompleteMessage = getBackendIncompleteMessage(body);
7329
+ if (incompleteMessage) {
7330
+ return incompleteMessage;
7331
+ }
7332
+ const status = getBackendResponseStatus(body);
7333
+ if (status && status !== 'completed') {
7334
+ return `Backend response status was "${status}".`;
7335
+ }
7336
+ if (isObject$2(body) && Array.isArray(Reflect.get(body, 'output'))) {
7337
+ return 'Unexpected backend response format: no assistant text or tool calls were returned.';
7338
+ }
7339
+ return 'Unexpected backend response format.';
7340
+ };
7341
+ const toExecutedToolCall = (toolCall, content) => {
7342
+ const executionStatus = getToolCallExecutionStatus(content);
7343
+ const toolCallResult = getToolCallResult(toolCall.name, content);
7344
+ return {
7345
+ arguments: toolCall.arguments,
7346
+ ...(executionStatus.errorMessage ? {
7347
+ errorMessage: executionStatus.errorMessage
7348
+ } : {}),
7349
+ ...(executionStatus.errorStack ? {
7350
+ errorStack: executionStatus.errorStack
7351
+ } : {}),
7352
+ id: toolCall.callId,
7353
+ name: toolCall.name,
7354
+ ...(toolCallResult ? {
7355
+ result: toolCallResult
7356
+ } : {}),
7357
+ ...(executionStatus.status ? {
7358
+ status: executionStatus.status
7359
+ } : {})
7360
+ };
7361
+ };
7233
7362
  const getBackendResponseOutputText = body => {
7234
7363
  if (!isObject$2(body)) {
7235
7364
  return '';
@@ -7291,14 +7420,29 @@ const getBackendResponseOutputText = body => {
7291
7420
  }
7292
7421
  return chunks.join('');
7293
7422
  };
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);
7423
+ const getBackendResponsesBody = (input, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, previousResponseId, reasoningEffort, supportsReasoningEffort = false) => {
7424
+ return getOpenAiParams(input, modelId, false, false, tools, webSearchEnabled, maxToolCalls, systemPrompt, previousResponseId, reasoningEffort, supportsReasoningEffort);
7300
7425
  };
7301
- const getBackendAssistantText = async (messages, modelId, backendUrl, authAccessToken, systemPrompt, agentMode = defaultAgentMode, questionToolEnabled = false, toolEnablement, maxToolCalls = defaultMaxToolCalls, webSearchEnabled = false, reasoningEffort, supportsReasoningEffort = false) => {
7426
+ const getBackendAssistantText = async ({
7427
+ agentMode = defaultAgentMode,
7428
+ assetDir,
7429
+ authAccessToken,
7430
+ backendUrl,
7431
+ maxToolCalls = defaultMaxToolCalls,
7432
+ messages,
7433
+ modelId,
7434
+ onToolCallsChunk,
7435
+ platform,
7436
+ questionToolEnabled = false,
7437
+ reasoningEffort,
7438
+ sessionId,
7439
+ supportsReasoningEffort = false,
7440
+ systemPrompt,
7441
+ toolEnablement,
7442
+ useChatToolWorker,
7443
+ webSearchEnabled = false,
7444
+ workspaceUri
7445
+ }) => {
7302
7446
  const mockError = takeErrorResponse();
7303
7447
  if (mockError) {
7304
7448
  const errorMessage = getBackendErrorMessageFromBody(mockError.body);
@@ -7312,45 +7456,115 @@ const getBackendAssistantText = async (messages, modelId, backendUrl, authAccess
7312
7456
  } : {})
7313
7457
  });
7314
7458
  }
7315
- let response;
7316
- try {
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)),
7320
- headers: {
7321
- Authorization: `Bearer ${authAccessToken}`,
7322
- 'Content-Type': 'application/json',
7323
- ...getClientRequestIdHeader()
7324
- },
7325
- method: 'POST'
7326
- });
7327
- } catch {
7328
- return getBackendErrorMessage({
7329
- details: 'request-failed'
7330
- });
7331
- }
7332
- if (!response.ok) {
7333
- const payload = await response.json().catch(() => undefined);
7334
- const errorMessage = getBackendErrorMessageFromBody(payload);
7335
- const statusCode = response.status || getBackendStatusCodeFromBody(payload);
7459
+ const mockResponse = takeResponse();
7460
+ const tools = await getBasicChatTools(agentMode, questionToolEnabled, toolEnablement);
7461
+ const input = messages.map(message => ({
7462
+ content: getChatMessageOpenAiContent(message),
7463
+ role: message.role
7464
+ }));
7465
+ let previousResponseId;
7466
+ const maxToolIterations = Math.max(0, maxToolCalls - 1);
7467
+ for (let index = 0; index <= maxToolIterations; index++) {
7468
+ let json;
7469
+ if (index === 0 && mockResponse) {
7470
+ json = mockResponse.body;
7471
+ } else {
7472
+ let response;
7473
+ try {
7474
+ response = await fetch(getBackendResponsesEndpoint(backendUrl), {
7475
+ body: JSON.stringify(getBackendResponsesBody(input, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, previousResponseId, reasoningEffort, supportsReasoningEffort)),
7476
+ headers: {
7477
+ Authorization: `Bearer ${authAccessToken}`,
7478
+ 'Content-Type': 'application/json',
7479
+ ...getClientRequestIdHeader()
7480
+ },
7481
+ method: 'POST'
7482
+ });
7483
+ } catch (error) {
7484
+ const errorMessage = getErrorMessage(error);
7485
+ return getBackendErrorMessage({
7486
+ details: 'request-failed',
7487
+ ...(errorMessage ? {
7488
+ errorMessage
7489
+ } : {})
7490
+ });
7491
+ }
7492
+ if (!response.ok) {
7493
+ const payload = await response.json().catch(() => undefined);
7494
+ const errorMessage = getBackendErrorMessageFromBody(payload);
7495
+ const statusCode = response.status || getBackendStatusCodeFromBody(payload);
7496
+ return getBackendErrorMessage({
7497
+ details: 'http-error',
7498
+ ...(typeof statusCode === 'number' ? {
7499
+ statusCode
7500
+ } : {}),
7501
+ ...(errorMessage ? {
7502
+ errorMessage
7503
+ } : {})
7504
+ });
7505
+ }
7506
+ try {
7507
+ json = await response.json();
7508
+ } catch {
7509
+ return getBackendErrorMessage({
7510
+ details: 'invalid-response',
7511
+ errorMessage: 'Backend returned invalid JSON.'
7512
+ });
7513
+ }
7514
+ }
7515
+ const responseFunctionCalls = getBackendResponseFunctionCalls(json);
7516
+ if (responseFunctionCalls.length > 0) {
7517
+ const responseId = getBackendResponseId(json);
7518
+ if (!responseId) {
7519
+ return getBackendErrorMessage({
7520
+ details: 'invalid-response',
7521
+ errorMessage: 'Unexpected backend response format: tool calls were returned without a response id.'
7522
+ });
7523
+ }
7524
+ previousResponseId = responseId;
7525
+ input.length = 0;
7526
+ const executedToolCalls = [];
7527
+ for (const toolCall of responseFunctionCalls) {
7528
+ const content = await executeChatTool(toolCall.name, toolCall.arguments, {
7529
+ assetDir,
7530
+ platform,
7531
+ ...(sessionId ? {
7532
+ sessionId
7533
+ } : {}),
7534
+ toolCallId: toolCall.callId,
7535
+ ...(toolEnablement ? {
7536
+ toolEnablement
7537
+ } : {}),
7538
+ useChatToolWorker,
7539
+ ...(workspaceUri ? {
7540
+ workspaceUri
7541
+ } : {})
7542
+ });
7543
+ executedToolCalls.push(toExecutedToolCall(toolCall, content));
7544
+ input.push({
7545
+ call_id: toolCall.callId,
7546
+ output: content,
7547
+ type: 'function_call_output'
7548
+ });
7549
+ }
7550
+ if (onToolCallsChunk && executedToolCalls.length > 0) {
7551
+ await onToolCallsChunk(executedToolCalls);
7552
+ }
7553
+ continue;
7554
+ }
7555
+ const content = getBackendResponseOutputText(json);
7556
+ if (content) {
7557
+ return content;
7558
+ }
7336
7559
  return getBackendErrorMessage({
7337
- details: 'http-error',
7338
- ...(typeof statusCode === 'number' ? {
7339
- statusCode
7340
- } : {}),
7341
- ...(errorMessage ? {
7342
- errorMessage
7343
- } : {})
7560
+ details: 'invalid-response',
7561
+ errorMessage: getBackendInvalidResponseDetails(json)
7344
7562
  });
7345
7563
  }
7346
- let json;
7347
- try {
7348
- json = await response.json();
7349
- } catch {
7350
- return backendCompletionFailedMessage;
7351
- }
7352
- const content = getBackendResponseOutputText(json);
7353
- return typeof content === 'string' && content ? content : backendCompletionFailedMessage;
7564
+ return getBackendErrorMessage({
7565
+ details: 'invalid-response',
7566
+ errorMessage: `Backend request ended after ${maxToolCalls} tool-call rounds without a final assistant response. This usually means the model got stuck in a tool loop.`
7567
+ });
7354
7568
  };
7355
7569
  const getAiResponse = async ({
7356
7570
  agentMode = defaultAgentMode,
@@ -7458,7 +7672,30 @@ const getAiResponse = async ({
7458
7672
  if (!backendUrl) {
7459
7673
  text = backendUrlRequiredMessage;
7460
7674
  } else if (authAccessToken) {
7461
- text = await getBackendAssistantText(messages, getOpenApiModelId(selectedModelId), backendUrl, authAccessToken, systemPrompt, agentMode, questionToolEnabled, toolEnablement, safeMaxToolCalls, agentMode === 'plan' ? false : webSearchEnabled, reasoningEffort, supportsReasoningEffort);
7675
+ text = await getBackendAssistantText({
7676
+ agentMode,
7677
+ assetDir,
7678
+ authAccessToken,
7679
+ backendUrl,
7680
+ maxToolCalls: safeMaxToolCalls,
7681
+ messages,
7682
+ modelId: getOpenApiModelId(selectedModelId),
7683
+ onToolCallsChunk,
7684
+ platform,
7685
+ questionToolEnabled,
7686
+ reasoningEffort,
7687
+ supportsReasoningEffort,
7688
+ systemPrompt,
7689
+ toolEnablement,
7690
+ useChatToolWorker,
7691
+ webSearchEnabled: agentMode === 'plan' ? false : webSearchEnabled,
7692
+ ...(sessionId ? {
7693
+ sessionId
7694
+ } : {}),
7695
+ ...(workspaceUri ? {
7696
+ workspaceUri
7697
+ } : {})
7698
+ });
7462
7699
  } else {
7463
7700
  text = backendAccessTokenRequiredMessage;
7464
7701
  }
@@ -10802,6 +11039,11 @@ const mockBackendSetHttpErrorResponse = (state, statusCode, body) => {
10802
11039
  return state;
10803
11040
  };
10804
11041
 
11042
+ const mockBackendSetResponse = (state, body) => {
11043
+ setResponse(body);
11044
+ return state;
11045
+ };
11046
+
10805
11047
  const mockOpenApiRequestGetAll = _state => {
10806
11048
  return getAll();
10807
11049
  };
@@ -15888,6 +16130,7 @@ const commandMap = {
15888
16130
  'Chat.loadContent2': wrapCommand(loadContent),
15889
16131
  'Chat.mockBackendAuthResponse': wrapCommand(mockBackendAuthResponse),
15890
16132
  'Chat.mockBackendSetHttpErrorResponse': wrapCommand(mockBackendSetHttpErrorResponse),
16133
+ 'Chat.mockBackendSetResponse': wrapCommand(mockBackendSetResponse),
15891
16134
  'Chat.mockOpenApiRequestGetAll': wrapGetter(mockOpenApiRequestGetAll),
15892
16135
  'Chat.mockOpenApiRequestReset': wrapCommand(mockOpenApiRequestReset),
15893
16136
  'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "7.10.0",
3
+ "version": "7.11.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",