@lvce-editor/chat-view 2.7.0 → 2.8.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.
@@ -1078,6 +1078,7 @@ const {
1078
1078
  set: set$3
1079
1079
  } = create$2(6002);
1080
1080
 
1081
+ const Div$1 = 4;
1081
1082
  const Ol$1 = 49;
1082
1083
 
1083
1084
  const ClientX = 'event.clientX';
@@ -1512,6 +1513,7 @@ const createDefaultState = () => {
1512
1513
  useMockApi: false,
1513
1514
  viewMode: 'list',
1514
1515
  warningCount: 0,
1516
+ webSearchEnabled: true,
1515
1517
  width: 0,
1516
1518
  x: 0,
1517
1519
  y: 0
@@ -3286,7 +3288,8 @@ const getOpenAiTools = tools => {
3286
3288
  };
3287
3289
  });
3288
3290
  };
3289
- const getOpenAiParams = (input, modelId, stream, includeObfuscation, tools, previousResponseId) => {
3291
+ const getOpenAiParams = (input, modelId, stream, includeObfuscation, tools, webSearchEnabled, previousResponseId) => {
3292
+ const openAiTools = getOpenAiTools(tools);
3290
3293
  return {
3291
3294
  input,
3292
3295
  model: modelId,
@@ -3302,7 +3305,9 @@ const getOpenAiParams = (input, modelId, stream, includeObfuscation, tools, prev
3302
3305
  previous_response_id: previousResponseId
3303
3306
  } : {}),
3304
3307
  tool_choice: 'auto',
3305
- tools: getOpenAiTools(tools)
3308
+ tools: webSearchEnabled ? [...openAiTools, {
3309
+ type: 'web_search'
3310
+ }] : openAiTools
3306
3311
  };
3307
3312
  };
3308
3313
  const getStreamChunkText = content => {
@@ -3320,6 +3325,47 @@ const getStreamChunkText = content => {
3320
3325
  return typeof text === 'string' ? text : '';
3321
3326
  }).join('');
3322
3327
  };
3328
+ const getShortToolErrorMessage = error => {
3329
+ const trimmed = error.trim().replace(/^Error:\s*/, '');
3330
+ const firstLine = trimmed.split('\n')[0];
3331
+ if (firstLine.length <= 80) {
3332
+ return firstLine;
3333
+ }
3334
+ return `${firstLine.slice(0, 77)}...`;
3335
+ };
3336
+ const getToolCallExecutionStatus = content => {
3337
+ let parsed;
3338
+ try {
3339
+ parsed = JSON.parse(content);
3340
+ } catch {
3341
+ return {
3342
+ errorMessage: 'Invalid tool output',
3343
+ status: 'error'
3344
+ };
3345
+ }
3346
+ if (!parsed || typeof parsed !== 'object') {
3347
+ return {
3348
+ errorMessage: 'Invalid tool output',
3349
+ status: 'error'
3350
+ };
3351
+ }
3352
+ const rawError = Reflect.get(parsed, 'error');
3353
+ if (typeof rawError !== 'string' || !rawError.trim()) {
3354
+ return {
3355
+ status: 'success'
3356
+ };
3357
+ }
3358
+ const errorMessage = getShortToolErrorMessage(rawError);
3359
+ if (/not[\s_-]?found|enoent/i.test(errorMessage)) {
3360
+ return {
3361
+ status: 'not-found'
3362
+ };
3363
+ }
3364
+ return {
3365
+ errorMessage,
3366
+ status: 'error'
3367
+ };
3368
+ };
3323
3369
  const getResponseOutputText = parsed => {
3324
3370
  if (!parsed || typeof parsed !== 'object') {
3325
3371
  return '';
@@ -3457,12 +3503,29 @@ const updateToolCallAccumulator = (accumulator, chunk) => {
3457
3503
  };
3458
3504
  };
3459
3505
  const getResponseFunctionCallsFromStreamingAccumulator = toolCallAccumulator => {
3460
- return Object.entries(toolCallAccumulator).toSorted((a, b) => Number(a[0]) - Number(b[0])).map(entry => entry[1]).filter(toolCall => typeof toolCall.id === 'string' && !!toolCall.id && !!toolCall.name).map(toolCall => ({
3506
+ return Object.entries(toolCallAccumulator).toSorted((a, b) => a[0].localeCompare(b[0])).map(entry => entry[1]).filter(toolCall => typeof toolCall.id === 'string' && !!toolCall.id && !!toolCall.name).map(toolCall => ({
3461
3507
  arguments: toolCall.arguments,
3462
3508
  callId: toolCall.id,
3463
3509
  name: toolCall.name
3464
3510
  }));
3465
3511
  };
3512
+ const getStreamingToolCallKey = value => {
3513
+ if (!value || typeof value !== 'object') {
3514
+ return undefined;
3515
+ }
3516
+ const outputIndex = Reflect.get(value, 'output_index');
3517
+ if (typeof outputIndex === 'number') {
3518
+ return String(outputIndex);
3519
+ }
3520
+ if (typeof outputIndex === 'string' && outputIndex) {
3521
+ return outputIndex;
3522
+ }
3523
+ const itemId = Reflect.get(value, 'item_id');
3524
+ if (typeof itemId === 'string' && itemId) {
3525
+ return itemId;
3526
+ }
3527
+ return undefined;
3528
+ };
3466
3529
  const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDataEvent) => {
3467
3530
  if (!response.body) {
3468
3531
  return {
@@ -3482,7 +3545,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3482
3545
  if (!onToolCallsChunk) {
3483
3546
  return;
3484
3547
  }
3485
- const toolCalls = Object.entries(toolCallAccumulator).toSorted((a, b) => Number(a[0]) - Number(b[0])).map(entry => entry[1]).filter(toolCall => !!toolCall.name);
3548
+ const toolCalls = Object.entries(toolCallAccumulator).toSorted((a, b) => a[0].localeCompare(b[0])).map(entry => entry[1]).filter(toolCall => !!toolCall.name);
3486
3549
  if (toolCalls.length === 0) {
3487
3550
  return;
3488
3551
  }
@@ -3530,9 +3593,9 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3530
3593
  return;
3531
3594
  }
3532
3595
  if (eventType === 'response.output_item.added') {
3533
- const outputIndex = Reflect.get(parsed, 'output_index');
3596
+ const toolCallKey = getStreamingToolCallKey(parsed);
3534
3597
  const item = Reflect.get(parsed, 'item');
3535
- if (typeof outputIndex !== 'number' || !item || typeof item !== 'object') {
3598
+ if (!toolCallKey || !item || typeof item !== 'object') {
3536
3599
  return;
3537
3600
  }
3538
3601
  const itemType = Reflect.get(item, 'type');
@@ -3551,15 +3614,15 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3551
3614
  };
3552
3615
  toolCallAccumulator = {
3553
3616
  ...toolCallAccumulator,
3554
- [outputIndex]: next
3617
+ [toolCallKey]: next
3555
3618
  };
3556
3619
  await emitToolCallAccumulator();
3557
3620
  return;
3558
3621
  }
3559
3622
  if (eventType === 'response.output_item.done') {
3560
- const outputIndex = Reflect.get(parsed, 'output_index');
3623
+ const toolCallKey = getStreamingToolCallKey(parsed);
3561
3624
  const item = Reflect.get(parsed, 'item');
3562
- if (typeof outputIndex !== 'number' || !item || typeof item !== 'object') {
3625
+ if (!toolCallKey || !item || typeof item !== 'object') {
3563
3626
  return;
3564
3627
  }
3565
3628
  const itemType = Reflect.get(item, 'type');
@@ -3569,13 +3632,13 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3569
3632
  const callId = Reflect.get(item, 'call_id');
3570
3633
  const name = Reflect.get(item, 'name');
3571
3634
  const rawArguments = Reflect.get(item, 'arguments');
3572
- const current = toolCallAccumulator[outputIndex] || {
3635
+ const current = toolCallAccumulator[toolCallKey] || {
3573
3636
  arguments: '',
3574
3637
  name: ''
3575
3638
  };
3576
3639
  toolCallAccumulator = {
3577
3640
  ...toolCallAccumulator,
3578
- [outputIndex]: {
3641
+ [toolCallKey]: {
3579
3642
  arguments: typeof rawArguments === 'string' ? rawArguments : current.arguments,
3580
3643
  ...(typeof callId === 'string' ? {
3581
3644
  id: callId
@@ -3589,11 +3652,11 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3589
3652
  return;
3590
3653
  }
3591
3654
  if (eventType === 'response.function_call_arguments.delta' || eventType === 'response.function_call_arguments.done') {
3592
- const outputIndex = Reflect.get(parsed, 'output_index');
3593
- if (typeof outputIndex !== 'number') {
3655
+ const toolCallKey = getStreamingToolCallKey(parsed);
3656
+ if (!toolCallKey) {
3594
3657
  return;
3595
3658
  }
3596
- const current = toolCallAccumulator[outputIndex] || {
3659
+ const current = toolCallAccumulator[toolCallKey] || {
3597
3660
  arguments: '',
3598
3661
  name: ''
3599
3662
  };
@@ -3612,7 +3675,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3612
3675
  };
3613
3676
  toolCallAccumulator = {
3614
3677
  ...toolCallAccumulator,
3615
- [outputIndex]: next
3678
+ [toolCallKey]: next
3616
3679
  };
3617
3680
  await emitToolCallAccumulator();
3618
3681
  return;
@@ -3746,7 +3809,8 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3746
3809
  onEventStreamFinished,
3747
3810
  onTextChunk,
3748
3811
  onToolCallsChunk,
3749
- stream
3812
+ stream,
3813
+ webSearchEnabled = false
3750
3814
  } = options ?? {
3751
3815
  stream: false
3752
3816
  };
@@ -3761,7 +3825,7 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3761
3825
  let response;
3762
3826
  try {
3763
3827
  response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl), {
3764
- body: JSON.stringify(getOpenAiParams(openAiInput, modelId, stream, includeObfuscation, tools, previousResponseId)),
3828
+ body: JSON.stringify(getOpenAiParams(openAiInput, modelId, stream, includeObfuscation, tools, webSearchEnabled, previousResponseId)),
3765
3829
  headers: {
3766
3830
  Authorization: `Bearer ${openApiApiKey}`,
3767
3831
  'Content-Type': 'application/json',
@@ -3804,6 +3868,37 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3804
3868
  if (streamResult.responseId) {
3805
3869
  previousResponseId = streamResult.responseId;
3806
3870
  }
3871
+ if (streamResult.responseFunctionCalls.length > 0) {
3872
+ openAiInput.length = 0;
3873
+ const executedToolCalls = [];
3874
+ for (const toolCall of streamResult.responseFunctionCalls) {
3875
+ const content = await executeChatTool(toolCall.name, toolCall.arguments, {
3876
+ assetDir,
3877
+ platform
3878
+ });
3879
+ const executionStatus = getToolCallExecutionStatus(content);
3880
+ executedToolCalls.push({
3881
+ arguments: toolCall.arguments,
3882
+ ...(executionStatus.errorMessage ? {
3883
+ errorMessage: executionStatus.errorMessage
3884
+ } : {}),
3885
+ id: toolCall.callId,
3886
+ name: toolCall.name,
3887
+ ...(executionStatus.status ? {
3888
+ status: executionStatus.status
3889
+ } : {})
3890
+ });
3891
+ openAiInput.push({
3892
+ call_id: toolCall.callId,
3893
+ output: content,
3894
+ type: 'function_call_output'
3895
+ });
3896
+ }
3897
+ if (onToolCallsChunk && executedToolCalls.length > 0) {
3898
+ await onToolCallsChunk(executedToolCalls);
3899
+ }
3900
+ continue;
3901
+ }
3807
3902
  if (onEventStreamFinished) {
3808
3903
  await onEventStreamFinished();
3809
3904
  }
@@ -3834,17 +3929,33 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3834
3929
  const responseFunctionCalls = getResponseFunctionCalls(parsed);
3835
3930
  if (responseFunctionCalls.length > 0) {
3836
3931
  openAiInput.length = 0;
3932
+ const executedToolCalls = [];
3837
3933
  for (const toolCall of responseFunctionCalls) {
3838
3934
  const content = await executeChatTool(toolCall.name, toolCall.arguments, {
3839
3935
  assetDir,
3840
3936
  platform
3841
3937
  });
3938
+ const executionStatus = getToolCallExecutionStatus(content);
3939
+ executedToolCalls.push({
3940
+ arguments: toolCall.arguments,
3941
+ ...(executionStatus.errorMessage ? {
3942
+ errorMessage: executionStatus.errorMessage
3943
+ } : {}),
3944
+ id: toolCall.callId,
3945
+ name: toolCall.name,
3946
+ ...(executionStatus.status ? {
3947
+ status: executionStatus.status
3948
+ } : {})
3949
+ });
3842
3950
  openAiInput.push({
3843
3951
  call_id: toolCall.callId,
3844
3952
  output: content,
3845
3953
  type: 'function_call_output'
3846
3954
  });
3847
3955
  }
3956
+ if (onToolCallsChunk && executedToolCalls.length > 0) {
3957
+ await onToolCallsChunk(executedToolCalls);
3958
+ }
3848
3959
  continue;
3849
3960
  }
3850
3961
  const outputText = getResponseOutputText(parsed);
@@ -3873,6 +3984,7 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3873
3984
  const toolCalls = Reflect.get(message, 'tool_calls');
3874
3985
  if (Array.isArray(toolCalls) && toolCalls.length > 0) {
3875
3986
  openAiInput.length = 0;
3987
+ const executedToolCalls = [];
3876
3988
  for (const toolCall of toolCalls) {
3877
3989
  if (!toolCall || typeof toolCall !== 'object') {
3878
3990
  continue;
@@ -3888,12 +4000,29 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3888
4000
  assetDir,
3889
4001
  platform
3890
4002
  }) : '{}';
4003
+ if (typeof name === 'string') {
4004
+ const executionStatus = getToolCallExecutionStatus(content);
4005
+ executedToolCalls.push({
4006
+ arguments: typeof rawArguments === 'string' ? rawArguments : '',
4007
+ ...(executionStatus.errorMessage ? {
4008
+ errorMessage: executionStatus.errorMessage
4009
+ } : {}),
4010
+ id,
4011
+ name,
4012
+ ...(executionStatus.status ? {
4013
+ status: executionStatus.status
4014
+ } : {})
4015
+ });
4016
+ }
3891
4017
  openAiInput.push({
3892
4018
  call_id: id,
3893
4019
  output: content,
3894
4020
  type: 'function_call_output'
3895
4021
  });
3896
4022
  }
4023
+ if (onToolCallsChunk && executedToolCalls.length > 0) {
4024
+ await onToolCallsChunk(executedToolCalls);
4025
+ }
3897
4026
  continue;
3898
4027
  }
3899
4028
  const content = Reflect.get(message, 'content');
@@ -4283,7 +4412,8 @@ const getAiResponse = async ({
4283
4412
  selectedModelId,
4284
4413
  streamingEnabled = false,
4285
4414
  useMockApi,
4286
- userText
4415
+ userText,
4416
+ webSearchEnabled = false
4287
4417
  }) => {
4288
4418
  let text = '';
4289
4419
  const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
@@ -4314,7 +4444,8 @@ const getAiResponse = async ({
4314
4444
  ...(onToolCallsChunk ? {
4315
4445
  onToolCallsChunk
4316
4446
  } : {}),
4317
- stream: streamingEnabled
4447
+ stream: streamingEnabled,
4448
+ webSearchEnabled
4318
4449
  });
4319
4450
  if (result.type === 'success') {
4320
4451
  const {
@@ -4703,7 +4834,8 @@ const handleSubmit = async state => {
4703
4834
  sessions,
4704
4835
  streamingEnabled,
4705
4836
  useMockApi,
4706
- viewMode
4837
+ viewMode,
4838
+ webSearchEnabled
4707
4839
  } = state;
4708
4840
  const userText = composerValue.trim();
4709
4841
  if (!userText) {
@@ -4847,7 +4979,8 @@ const handleSubmit = async state => {
4847
4979
  selectedModelId,
4848
4980
  streamingEnabled,
4849
4981
  useMockApi,
4850
- userText
4982
+ userText,
4983
+ webSearchEnabled
4851
4984
  });
4852
4985
  const {
4853
4986
  latestState
@@ -5168,6 +5301,11 @@ const handleKeyDown = async (state, key, shiftKey) => {
5168
5301
  return handleSubmit(submitState);
5169
5302
  };
5170
5303
 
5304
+ const handleMessagesContextMenu = async state => {
5305
+ await invoke('ContextMenu.show', 1234);
5306
+ return state;
5307
+ };
5308
+
5171
5309
  const handleModelChange = async (state, value) => {
5172
5310
  return {
5173
5311
  ...state,
@@ -5510,6 +5648,34 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
5510
5648
  --ChatMessageFontSize: ${chatMessageFontSize}px;
5511
5649
  --ChatMessageLineHeight: ${chatMessageLineHeight}px;
5512
5650
  --ChatMessageFontFamily: ${chatMessageFontFamily};
5651
+ }
5652
+
5653
+ .ChatToolCalls {
5654
+ position: relative;
5655
+ border: 1px solid var(--vscode-editorWidget-border);
5656
+ border-radius: 4px;
5657
+ margin-bottom: 8px;
5658
+ padding: 10px 8px 6px;
5659
+ background: var(--vscode-editorWidget-background);
5660
+ }
5661
+
5662
+ .ChatToolCallsLabel {
5663
+ position: absolute;
5664
+ top: -8px;
5665
+ left: 8px;
5666
+ padding: 0 4px;
5667
+ border-radius: 3px;
5668
+ background: var(--vscode-editor-background);
5669
+ color: var(--vscode-descriptionForeground);
5670
+ font-size: 10px;
5671
+ line-height: 14px;
5672
+ text-transform: lowercase;
5673
+ letter-spacing: 0.02em;
5674
+ }
5675
+
5676
+ .ChatToolCallReadFileLink {
5677
+ color: var(--vscode-textLink-foreground);
5678
+ text-decoration: underline;
5513
5679
  }`;
5514
5680
  };
5515
5681
 
@@ -5577,6 +5743,9 @@ const ChatListItemLabel = 'ChatListItemLabel';
5577
5743
  const Markdown = 'Markdown';
5578
5744
  const Message = 'Message';
5579
5745
  const ChatMessageContent = 'ChatMessageContent';
5746
+ const ChatToolCalls = 'ChatToolCalls';
5747
+ const ChatToolCallsLabel = 'ChatToolCallsLabel';
5748
+ const ChatToolCallReadFileLink = 'ChatToolCallReadFileLink';
5580
5749
  const ChatOrderedList = 'ChatOrderedList';
5581
5750
  const ChatOrderedListItem = 'ChatOrderedListItem';
5582
5751
  const MessageUser = 'MessageUser';
@@ -5607,6 +5776,7 @@ const HandleChatListScroll = 21;
5607
5776
  const HandleMessagesScroll = 22;
5608
5777
  const HandleClickSessionDebug = 23;
5609
5778
  const HandleClickReadFile = 24;
5779
+ const HandleMessagesContextMenu = 25;
5610
5780
 
5611
5781
  const getModelLabel = model => {
5612
5782
  if (model.provider === 'openRouter') {
@@ -5921,8 +6091,10 @@ const getToolCallArgumentPreview = rawArguments => {
5921
6091
  return rawArguments;
5922
6092
  };
5923
6093
 
6094
+ const RE_QUERY_OR_HASH = /[?#].*$/;
6095
+ const RE_TRAILING_SLASH = /\/$/;
5924
6096
  const getFileNameFromUri = uri => {
5925
- const stripped = uri.replace(/[?#].*$/, '').replace(/\/$/, '');
6097
+ const stripped = uri.replace(RE_QUERY_OR_HASH, '').replace(RE_TRAILING_SLASH, '');
5926
6098
  const slashIndex = Math.max(stripped.lastIndexOf('/'), stripped.lastIndexOf('\\\\'));
5927
6099
  const fileName = slashIndex === -1 ? stripped : stripped.slice(slashIndex + 1);
5928
6100
  return fileName || uri;
@@ -5946,42 +6118,68 @@ const getReadFileTarget = rawArguments => {
5946
6118
  if (!title) {
5947
6119
  return undefined;
5948
6120
  }
5949
- const clickableUri = uriValue || (pathValue.startsWith('file://') ? pathValue : '');
6121
+ // `read_file` tool calls usually provide a relative `path`; pass it through so UI clicks can open the file.
6122
+ const clickableUri = uriValue || pathValue;
5950
6123
  return {
5951
6124
  clickableUri,
5952
6125
  title
5953
6126
  };
5954
6127
  };
5955
6128
 
6129
+ const getToolCallStatusLabel$1 = toolCall => {
6130
+ if (toolCall.status === 'not-found') {
6131
+ return ' (not-found)';
6132
+ }
6133
+ if (toolCall.status === 'error') {
6134
+ if (toolCall.errorMessage) {
6135
+ return ` (error: ${toolCall.errorMessage})`;
6136
+ }
6137
+ return ' (error)';
6138
+ }
6139
+ return '';
6140
+ };
6141
+
5956
6142
  const getToolCallReadFileVirtualDom = toolCall => {
5957
6143
  const target = getReadFileTarget(toolCall.arguments);
5958
6144
  if (!target) {
5959
6145
  return [];
5960
6146
  }
5961
6147
  const fileName = getFileNameFromUri(target.title);
5962
- const clickableProps = target.clickableUri ? {
6148
+ const toolNameLabel = `${toolCall.name} `;
6149
+ const statusLabel = getToolCallStatusLabel$1(toolCall);
6150
+ const fileNameClickableProps = target.clickableUri ? {
5963
6151
  'data-uri': target.clickableUri,
5964
6152
  onClick: HandleClickReadFile
5965
6153
  } : {};
5966
6154
  return [{
5967
- childCount: 2,
6155
+ childCount: statusLabel ? 4 : 3,
5968
6156
  className: ChatOrderedListItem,
5969
- ...clickableProps,
5970
6157
  title: target.title,
5971
6158
  type: Li
5972
6159
  }, {
5973
6160
  childCount: 0,
5974
6161
  className: FileIcon,
5975
- ...clickableProps,
5976
6162
  type: Div
5977
- }, {
6163
+ }, text(toolNameLabel), {
5978
6164
  childCount: 1,
5979
- ...clickableProps,
5980
- style: 'color: var(--vscode-textLink-foreground); text-decoration: underline;',
6165
+ className: ChatToolCallReadFileLink,
6166
+ ...fileNameClickableProps,
5981
6167
  type: Span
5982
- }, text(fileName)];
6168
+ }, text(fileName), ...(statusLabel ? [text(statusLabel)] : [])];
5983
6169
  };
5984
6170
 
6171
+ const getToolCallStatusLabel = toolCall => {
6172
+ if (toolCall.status === 'not-found') {
6173
+ return ' (not-found)';
6174
+ }
6175
+ if (toolCall.status === 'error') {
6176
+ if (toolCall.errorMessage) {
6177
+ return ` (error: ${toolCall.errorMessage})`;
6178
+ }
6179
+ return ' (error)';
6180
+ }
6181
+ return '';
6182
+ };
5985
6183
  const getToolCallDom = toolCall => {
5986
6184
  if (toolCall.name === 'read_file') {
5987
6185
  const virtualDom = getToolCallReadFileVirtualDom(toolCall);
@@ -5990,7 +6188,7 @@ const getToolCallDom = toolCall => {
5990
6188
  }
5991
6189
  }
5992
6190
  const argumentPreview = getToolCallArgumentPreview(toolCall.arguments);
5993
- const label = `${toolCall.name} ${argumentPreview}`;
6191
+ const label = `${toolCall.name} ${argumentPreview}${getToolCallStatusLabel(toolCall)}`;
5994
6192
  return [{
5995
6193
  childCount: 1,
5996
6194
  className: ChatOrderedListItem,
@@ -6003,6 +6201,14 @@ const getToolCallsDom = message => {
6003
6201
  return [];
6004
6202
  }
6005
6203
  return [{
6204
+ childCount: 2,
6205
+ className: ChatToolCalls,
6206
+ type: Div$1
6207
+ }, {
6208
+ childCount: 1,
6209
+ className: ChatToolCallsLabel,
6210
+ type: Div$1
6211
+ }, text('tools'), {
6006
6212
  childCount: message.toolCalls.length,
6007
6213
  className: ChatOrderedList,
6008
6214
  type: Ol$1
@@ -6126,6 +6332,7 @@ const getMessagesDom = (messages, openRouterApiKeyInput, openApiApiKeyInput = ''
6126
6332
  return [{
6127
6333
  childCount: messages.length,
6128
6334
  className: 'ChatMessages',
6335
+ onContextMenu: HandleMessagesContextMenu,
6129
6336
  onScroll: HandleMessagesScroll,
6130
6337
  scrollTop: messagesScrollTop,
6131
6338
  type: Div
@@ -6376,6 +6583,10 @@ const renderEventListeners = () => {
6376
6583
  }, {
6377
6584
  name: HandleMessagesScroll,
6378
6585
  params: ['handleMessagesScroll', 'event.target.scrollTop']
6586
+ }, {
6587
+ name: HandleMessagesContextMenu,
6588
+ params: ['handleMessagesContextMenu'],
6589
+ preventDefault: true
6379
6590
  }, {
6380
6591
  name: HandleFocus,
6381
6592
  params: ['handleInputFocus', TargetName]
@@ -6519,6 +6730,7 @@ const commandMap = {
6519
6730
  'Chat.handleInput': wrapCommand(handleInput),
6520
6731
  'Chat.handleInputFocus': wrapCommand(handleInputFocus),
6521
6732
  'Chat.handleKeyDown': wrapCommand(handleKeyDown),
6733
+ 'Chat.handleMessagesContextMenu': wrapCommand(handleMessagesContextMenu),
6522
6734
  'Chat.handleMessagesScroll': wrapCommand(handleMessagesScroll),
6523
6735
  'Chat.handleModelChange': wrapCommand(handleModelChange),
6524
6736
  'Chat.handleSubmit': wrapCommand(handleSubmit),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",