@lvce-editor/chat-view 3.2.0 → 3.4.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.
@@ -1118,6 +1118,9 @@ const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
1118
1118
  const command = 'HandleMessagePort.handleMessagePort2';
1119
1119
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
1120
1120
  };
1121
+ const sendMessagePortToChatNetworkWorker = async port => {
1122
+ await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatNetworkWorker', port, 'HandleMessagePort.handleMessagePort');
1123
+ };
1121
1124
  const activateByEvent$1 = (event, assetDir, platform) => {
1122
1125
  return invoke('ExtensionHostManagement.activateByEvent', event, assetDir, platform);
1123
1126
  };
@@ -1275,6 +1278,9 @@ const getComposerHeight = async (state, value, width = state.width) => {
1275
1278
  composerLineHeight,
1276
1279
  maxComposerRows
1277
1280
  } = state;
1281
+ if (value === '') {
1282
+ return composerLineHeight;
1283
+ }
1278
1284
  const minimumHeight = getMinComposerHeight(composerLineHeight);
1279
1285
  const maximumHeight = getMaxComposerHeight(composerLineHeight, maxComposerRows);
1280
1286
  const content = value || ' ';
@@ -1463,6 +1469,7 @@ const createDefaultState = () => {
1463
1469
  const composerFontSize = 13;
1464
1470
  const composerLineHeight = 20;
1465
1471
  return {
1472
+ aiSessionTitleGenerationEnabled: false,
1466
1473
  assetDir: '',
1467
1474
  chatListScrollTop: 0,
1468
1475
  chatMessageFontFamily: 'system-ui',
@@ -5015,6 +5022,10 @@ const handleToolCallsChunkFunction = async (uid, assistantMessageId, toolCalls,
5015
5022
  };
5016
5023
  };
5017
5024
 
5025
+ const slashCommandRegex = /^\/(clear|export|help|new)(?:\s+.*)?$/;
5026
+ const mentionRegex = /(^|\s)@([^\s]+)/g;
5027
+ const maxMentionCount = 5;
5028
+ const maxMentionTextLength = 8000;
5018
5029
  const appendMessageToSelectedSession = (sessions, selectedSessionId, message) => {
5019
5030
  return sessions.map(session => {
5020
5031
  if (session.id !== selectedSessionId) {
@@ -5068,8 +5079,208 @@ const isStreamingFunctionCallEvent = parsed => {
5068
5079
  const getSseEventType = value => {
5069
5080
  return value && typeof value === 'object' && Reflect.get(value, 'type') === 'response.completed' ? 'sse-response-completed' : 'sse-response-part';
5070
5081
  };
5082
+ const getCommandHelpText = () => {
5083
+ return ['Available commands:', '/new - Create and switch to a new chat session.', '/clear - Clear messages in the selected chat session.', '/export - Export current chat session as Markdown.', '/help - Show this help.'].join('\n');
5084
+ };
5085
+ const withClearedComposer = state => {
5086
+ return focusInput({
5087
+ ...state,
5088
+ composerHeight: getMinComposerHeightForState(state),
5089
+ composerValue: '',
5090
+ inputSource: 'script'
5091
+ });
5092
+ };
5093
+ const toMarkdownTranscript = session => {
5094
+ const lines = [`# ${session.title}`, ''];
5095
+ for (const message of session.messages) {
5096
+ const role = message.role === 'assistant' ? 'Assistant' : 'User';
5097
+ lines.push(`## ${role}`);
5098
+ lines.push(message.text || '(empty)');
5099
+ lines.push('');
5100
+ }
5101
+ return lines.join('\n').trim();
5102
+ };
5103
+ const executeSlashCommand = async (state, command) => {
5104
+ if (command === 'new') {
5105
+ const nextState = await createSession(state);
5106
+ return withClearedComposer({
5107
+ ...nextState,
5108
+ viewMode: 'detail'
5109
+ });
5110
+ }
5111
+ const selectedSession = state.sessions.find(session => session.id === state.selectedSessionId);
5112
+ if (!selectedSession) {
5113
+ return withClearedComposer(state);
5114
+ }
5115
+ if (command === 'clear') {
5116
+ const updatedSessions = state.sessions.map(session => {
5117
+ if (session.id !== state.selectedSessionId) {
5118
+ return session;
5119
+ }
5120
+ return {
5121
+ ...session,
5122
+ messages: []
5123
+ };
5124
+ });
5125
+ const updatedSelectedSession = updatedSessions.find(session => session.id === state.selectedSessionId);
5126
+ if (updatedSelectedSession) {
5127
+ await saveChatSession(updatedSelectedSession);
5128
+ }
5129
+ return withClearedComposer({
5130
+ ...state,
5131
+ sessions: updatedSessions
5132
+ });
5133
+ }
5134
+ const assistantText = command === 'help' ? getCommandHelpText() : ['```md', toMarkdownTranscript(selectedSession), '```'].join('\n');
5135
+ const assistantMessage = {
5136
+ id: crypto.randomUUID(),
5137
+ role: 'assistant',
5138
+ text: assistantText,
5139
+ time: new Date().toLocaleTimeString([], {
5140
+ hour: '2-digit',
5141
+ minute: '2-digit'
5142
+ })
5143
+ };
5144
+ const updatedSessions = appendMessageToSelectedSession(state.sessions, state.selectedSessionId, assistantMessage);
5145
+ const updatedSelectedSession = updatedSessions.find(session => session.id === state.selectedSessionId);
5146
+ if (updatedSelectedSession) {
5147
+ await saveChatSession(updatedSelectedSession);
5148
+ }
5149
+ return withClearedComposer({
5150
+ ...state,
5151
+ sessions: updatedSessions
5152
+ });
5153
+ };
5154
+ const getSlashCommand = value => {
5155
+ const trimmed = value.trim();
5156
+ const match = trimmed.match(slashCommandRegex);
5157
+ if (!match) {
5158
+ return undefined;
5159
+ }
5160
+ return match[1];
5161
+ };
5162
+ const parseMentionedPaths = value => {
5163
+ const matches = value.matchAll(mentionRegex);
5164
+ const paths = [];
5165
+ for (const match of matches) {
5166
+ const rawPath = match[2] || '';
5167
+ const cleanedPath = rawPath.replaceAll(/[),.;:!?]+$/g, '');
5168
+ if (!cleanedPath || isPathTraversalAttempt(cleanedPath)) {
5169
+ continue;
5170
+ }
5171
+ const normalizedPath = normalizeRelativePath(cleanedPath);
5172
+ if (paths.includes(normalizedPath)) {
5173
+ continue;
5174
+ }
5175
+ paths.push(normalizedPath);
5176
+ if (paths.length >= maxMentionCount) {
5177
+ break;
5178
+ }
5179
+ }
5180
+ return paths;
5181
+ };
5182
+ const getMentionContextMessage = async value => {
5183
+ const paths = parseMentionedPaths(value);
5184
+ if (paths.length === 0) {
5185
+ return undefined;
5186
+ }
5187
+ const sections = [];
5188
+ for (const path of paths) {
5189
+ try {
5190
+ const fileContent = await readFile(path);
5191
+ const truncatedContent = fileContent.length > maxMentionTextLength ? `${fileContent.slice(0, maxMentionTextLength)}\n... [truncated]` : fileContent;
5192
+ sections.push([`File: ${path}`, '```text', truncatedContent, '```'].join('\n'));
5193
+ } catch (error) {
5194
+ sections.push([`File: ${path}`, `Error: ${String(error)}`].join('\n'));
5195
+ }
5196
+ }
5197
+ return {
5198
+ id: crypto.randomUUID(),
5199
+ role: 'user',
5200
+ text: ['Referenced file context:', ...sections].join('\n\n'),
5201
+ time: new Date().toLocaleTimeString([], {
5202
+ hour: '2-digit',
5203
+ minute: '2-digit'
5204
+ })
5205
+ };
5206
+ };
5207
+ const isDefaultSessionTitle = title => {
5208
+ return /^Chat \d+$/.test(title);
5209
+ };
5210
+ const sanitizeGeneratedTitle = value => {
5211
+ return value.replace(/^title:\s*/i, '').replaceAll(/^['"`\s]+|['"`\s]+$/g, '').replaceAll(/\s+/g, ' ').trim().slice(0, 80);
5212
+ };
5213
+ const updateSessionTitle = (sessions, selectedSessionId, title) => {
5214
+ return sessions.map(session => {
5215
+ if (session.id !== selectedSessionId) {
5216
+ return session;
5217
+ }
5218
+ return {
5219
+ ...session,
5220
+ title
5221
+ };
5222
+ });
5223
+ };
5224
+ const getAiSessionTitle = async (state, userText, assistantText) => {
5225
+ const {
5226
+ models,
5227
+ openApiApiBaseUrl,
5228
+ openApiApiKey,
5229
+ openRouterApiBaseUrl,
5230
+ openRouterApiKey,
5231
+ selectedModelId,
5232
+ useMockApi
5233
+ } = state;
5234
+ if (useMockApi) {
5235
+ return '';
5236
+ }
5237
+ const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
5238
+ const usesOpenRouterModel = isOpenRouterModel(selectedModelId, models);
5239
+ if (usesOpenApiModel && !openApiApiKey) {
5240
+ return '';
5241
+ }
5242
+ if (usesOpenRouterModel && !openRouterApiKey) {
5243
+ return '';
5244
+ }
5245
+ if (!usesOpenApiModel && !usesOpenRouterModel) {
5246
+ return '';
5247
+ }
5248
+ const titlePrompt = `Create a concise title (max 6 words) for this conversation. Respond only with the title, no punctuation at the end.
5249
+ User: ${userText}
5250
+ Assistant: ${assistantText}`;
5251
+ const promptMessage = {
5252
+ id: crypto.randomUUID(),
5253
+ role: 'user',
5254
+ text: titlePrompt,
5255
+ time: new Date().toLocaleTimeString([], {
5256
+ hour: '2-digit',
5257
+ minute: '2-digit'
5258
+ })
5259
+ };
5260
+ const titleResponse = await getAiResponse({
5261
+ assetDir: state.assetDir,
5262
+ messages: [promptMessage],
5263
+ mockAiResponseDelay: state.mockAiResponseDelay,
5264
+ mockApiCommandId: state.mockApiCommandId,
5265
+ models,
5266
+ openApiApiBaseUrl,
5267
+ openApiApiKey,
5268
+ openRouterApiBaseUrl,
5269
+ openRouterApiKey,
5270
+ passIncludeObfuscation: state.passIncludeObfuscation,
5271
+ platform: state.platform,
5272
+ selectedModelId,
5273
+ streamingEnabled: false,
5274
+ useMockApi,
5275
+ userText: titlePrompt,
5276
+ webSearchEnabled: false
5277
+ });
5278
+ const title = sanitizeGeneratedTitle(titleResponse.text);
5279
+ return title && !isDefaultSessionTitle(title) ? title : '';
5280
+ };
5071
5281
  const handleSubmit = async state => {
5072
5282
  const {
5283
+ aiSessionTitleGenerationEnabled,
5073
5284
  assetDir,
5074
5285
  composerValue,
5075
5286
  emitStreamingFunctionCallEvents,
@@ -5095,6 +5306,10 @@ const handleSubmit = async state => {
5095
5306
  if (!userText) {
5096
5307
  return state;
5097
5308
  }
5309
+ const slashCommand = getSlashCommand(userText);
5310
+ if (slashCommand) {
5311
+ return executeSlashCommand(state, slashCommand);
5312
+ }
5098
5313
  const userTime = new Date().toLocaleTimeString([], {
5099
5314
  hour: '2-digit',
5100
5315
  minute: '2-digit'
@@ -5131,6 +5346,7 @@ const handleSubmit = async state => {
5131
5346
  }
5132
5347
  }
5133
5348
  let optimisticState;
5349
+ const createsNewSession = viewMode === 'list';
5134
5350
  if (viewMode === 'list') {
5135
5351
  const newSessionId = generateSessionId();
5136
5352
  await appendChatViewEvent({
@@ -5188,13 +5404,15 @@ const handleSubmit = async state => {
5188
5404
  };
5189
5405
  const selectedOptimisticSession = optimisticState.sessions.find(session => session.id === optimisticState.selectedSessionId);
5190
5406
  const messages = (selectedOptimisticSession?.messages ?? []).filter(message => !message.inProgress);
5407
+ const mentionContextMessage = await getMentionContextMessage(userText);
5408
+ const messagesWithMentionContext = mentionContextMessage ? [...messages, mentionContextMessage] : messages;
5191
5409
  const handleTextChunkFunctionRef = streamingEnabled ? async chunk => {
5192
5410
  handleTextChunkState = await handleTextChunkFunction(state.uid, assistantMessageId, chunk, handleTextChunkState);
5193
5411
  } : undefined;
5194
5412
  const assistantMessage = await getAiResponse({
5195
5413
  assetDir,
5196
5414
  messageId: assistantMessageId,
5197
- messages,
5415
+ messages: messagesWithMentionContext,
5198
5416
  mockAiResponseDelay,
5199
5417
  mockApiCommandId,
5200
5418
  models,
@@ -5239,7 +5457,16 @@ const handleSubmit = async state => {
5239
5457
  const {
5240
5458
  latestState
5241
5459
  } = handleTextChunkState;
5242
- const updatedSessions = streamingEnabled ? updateMessageTextInSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false) : appendMessageToSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessage);
5460
+ let updatedSessions = streamingEnabled ? updateMessageTextInSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false) : appendMessageToSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessage);
5461
+ if (aiSessionTitleGenerationEnabled && createsNewSession) {
5462
+ const selectedSession = updatedSessions.find(session => session.id === latestState.selectedSessionId);
5463
+ if (selectedSession && isDefaultSessionTitle(selectedSession.title)) {
5464
+ const generatedTitle = await getAiSessionTitle(latestState, userText, assistantMessage.text);
5465
+ if (generatedTitle) {
5466
+ updatedSessions = updateSessionTitle(updatedSessions, latestState.selectedSessionId, generatedTitle);
5467
+ }
5468
+ }
5469
+ }
5243
5470
  const selectedSession = updatedSessions.find(session => session.id === latestState.selectedSessionId);
5244
5471
  if (selectedSession) {
5245
5472
  await saveChatSession(selectedSession);
@@ -5441,6 +5668,9 @@ const handleClickSettings = async () => {
5441
5668
  };
5442
5669
 
5443
5670
  const handleInput = async (state, name, value, inputSource = 'user') => {
5671
+ const {
5672
+ selectedSessionId
5673
+ } = state;
5444
5674
  if (name === OpenApiApiKeyInput) {
5445
5675
  return {
5446
5676
  ...state,
@@ -5456,9 +5686,9 @@ const handleInput = async (state, name, value, inputSource = 'user') => {
5456
5686
  if (name !== Composer) {
5457
5687
  return state;
5458
5688
  }
5459
- if (state.selectedSessionId) {
5689
+ if (selectedSessionId) {
5460
5690
  await appendChatViewEvent({
5461
- sessionId: state.selectedSessionId,
5691
+ sessionId: selectedSessionId,
5462
5692
  timestamp: new Date().toISOString(),
5463
5693
  type: 'handle-input',
5464
5694
  value
@@ -5705,6 +5935,15 @@ const getSavedViewMode = savedState => {
5705
5935
  return viewMode;
5706
5936
  };
5707
5937
 
5938
+ const loadAiSessionTitleGenerationEnabled = async () => {
5939
+ try {
5940
+ const savedAiSessionTitleGenerationEnabled = await get('chatView.aiSessionTitleGenerationEnabled');
5941
+ return typeof savedAiSessionTitleGenerationEnabled === 'boolean' ? savedAiSessionTitleGenerationEnabled : false;
5942
+ } catch {
5943
+ return false;
5944
+ }
5945
+ };
5946
+
5708
5947
  const loadEmitStreamingFunctionCallEvents = async () => {
5709
5948
  try {
5710
5949
  const savedEmitStreamingFunctionCallEvents = await get('chatView.emitStreamingFunctionCallEvents');
@@ -5759,12 +5998,9 @@ const loadStreamingEnabled = async () => {
5759
5998
  };
5760
5999
 
5761
6000
  const loadPreferences = async () => {
5762
- const openApiApiKey = await loadOpenApiApiKey();
5763
- const openRouterApiKey = await loadOpenRouterApiKey();
5764
- const emitStreamingFunctionCallEvents = await loadEmitStreamingFunctionCallEvents();
5765
- const streamingEnabled = await loadStreamingEnabled();
5766
- const passIncludeObfuscation = await loadPassIncludeObfuscation();
6001
+ const [aiSessionTitleGenerationEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, streamingEnabled, passIncludeObfuscation] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadStreamingEnabled(), loadPassIncludeObfuscation()]);
5767
6002
  return {
6003
+ aiSessionTitleGenerationEnabled,
5768
6004
  emitStreamingFunctionCallEvents,
5769
6005
  openApiApiKey,
5770
6006
  openRouterApiKey,
@@ -5800,6 +6036,7 @@ const loadContent = async (state, savedState) => {
5800
6036
  const savedSelectedModelId = getSavedSelectedModelId(savedState);
5801
6037
  const savedViewMode = getSavedViewMode(savedState);
5802
6038
  const {
6039
+ aiSessionTitleGenerationEnabled,
5803
6040
  emitStreamingFunctionCallEvents,
5804
6041
  openApiApiKey,
5805
6042
  openRouterApiKey,
@@ -5832,6 +6069,7 @@ const loadContent = async (state, savedState) => {
5832
6069
  const viewMode = sessions.length === 0 || !selectedSessionId ? 'list' : preferredViewMode === 'detail' ? 'detail' : 'list';
5833
6070
  return {
5834
6071
  ...state,
6072
+ aiSessionTitleGenerationEnabled,
5835
6073
  chatListScrollTop,
5836
6074
  emitStreamingFunctionCallEvents,
5837
6075
  initial: false,
@@ -5903,6 +6141,13 @@ const openMockSession = async (state, mockSessionId, mockChatMessages) => {
5903
6141
  };
5904
6142
  };
5905
6143
 
6144
+ const registerMockResponse = (state, mockResponse) => {
6145
+ reset$1();
6146
+ pushChunk(mockResponse.text);
6147
+ finish();
6148
+ return state;
6149
+ };
6150
+
5906
6151
  const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily, renderHtmlCss) => {
5907
6152
  const baseCss = `:root {
5908
6153
  --ChatInputBoxHeight: ${composerHeight}px;
@@ -5968,6 +6213,17 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
5968
6213
  cursor: pointer;
5969
6214
  }
5970
6215
 
6216
+ .ChatOrderedList,
6217
+ .ChatUnorderedList {
6218
+ margin: 6px 0;
6219
+ padding-inline-start: 20px;
6220
+ }
6221
+
6222
+ .ChatOrderedListItem,
6223
+ .ChatUnorderedListItem {
6224
+ margin: 2px 0;
6225
+ }
6226
+
5971
6227
  .MarkdownTable {
5972
6228
  width: 100%;
5973
6229
  margin: 6px 0;
@@ -6072,6 +6328,8 @@ const ChatToolCallRenderHtmlBody = 'ChatToolCallRenderHtmlBody';
6072
6328
  const ChatMessageLink = 'ChatMessageLink';
6073
6329
  const ChatOrderedList = 'ChatOrderedList';
6074
6330
  const ChatOrderedListItem = 'ChatOrderedListItem';
6331
+ const ChatUnorderedList = 'ChatUnorderedList';
6332
+ const ChatUnorderedListItem = 'ChatUnorderedListItem';
6075
6333
  const MessageUser = 'MessageUser';
6076
6334
  const MessageAssistant = 'MessageAssistant';
6077
6335
  const MultilineInputBox = 'MultilineInputBox';
@@ -6331,6 +6589,13 @@ const getOrderedListItemDom = item => {
6331
6589
  type: Li
6332
6590
  }, ...item.children.flatMap(getInlineNodeDom)];
6333
6591
  };
6592
+ const getUnorderedListItemDom = item => {
6593
+ return [{
6594
+ childCount: item.children.length,
6595
+ className: ChatUnorderedListItem,
6596
+ type: Li
6597
+ }, ...item.children.flatMap(getInlineNodeDom)];
6598
+ };
6334
6599
  const getTableHeadCellDom = cell => {
6335
6600
  return [{
6336
6601
  childCount: cell.children.length,
@@ -6365,6 +6630,28 @@ const getTableDom = node => {
6365
6630
  type: TBody
6366
6631
  }, ...node.rows.flatMap(getTableRowDom)];
6367
6632
  };
6633
+ const getHeadingElementType = level => {
6634
+ switch (level) {
6635
+ case 1:
6636
+ return H1;
6637
+ case 2:
6638
+ return H2;
6639
+ case 3:
6640
+ return H3;
6641
+ case 4:
6642
+ return H4;
6643
+ case 5:
6644
+ return H5;
6645
+ case 6:
6646
+ return H6;
6647
+ }
6648
+ };
6649
+ const getHeadingDom = node => {
6650
+ return [{
6651
+ childCount: node.children.length,
6652
+ type: getHeadingElementType(node.level)
6653
+ }, ...node.children.flatMap(getInlineNodeDom)];
6654
+ };
6368
6655
  const getMessageNodeDom = node => {
6369
6656
  if (node.type === 'text') {
6370
6657
  return [{
@@ -6379,11 +6666,21 @@ const getMessageNodeDom = node => {
6379
6666
  if (node.type === 'code-block') {
6380
6667
  return getCodeBlockDom(node);
6381
6668
  }
6669
+ if (node.type === 'heading') {
6670
+ return getHeadingDom(node);
6671
+ }
6672
+ if (node.type === 'ordered-list') {
6673
+ return [{
6674
+ childCount: node.items.length,
6675
+ className: ChatOrderedList,
6676
+ type: Ol
6677
+ }, ...node.items.flatMap(getOrderedListItemDom)];
6678
+ }
6382
6679
  return [{
6383
6680
  childCount: node.items.length,
6384
- className: ChatOrderedList,
6385
- type: Ol
6386
- }, ...node.items.flatMap(getOrderedListItemDom)];
6681
+ className: ChatUnorderedList,
6682
+ type: Ul
6683
+ }, ...node.items.flatMap(getUnorderedListItemDom)];
6387
6684
  };
6388
6685
 
6389
6686
  const getMessageContentDom = nodes => {
@@ -6929,9 +7226,11 @@ const getToolCallsDom = message => {
6929
7226
  };
6930
7227
 
6931
7228
  const orderedListItemRegex = /^\s*\d+\.\s+(.*)$/;
7229
+ const unorderedListItemRegex = /^\s*[-*]\s+(.*)$/;
6932
7230
  const markdownInlineRegex = /\[([^\]]+)\]\(([^)]+)\)|\*\*([^*]+)\*\*/g;
6933
7231
  const markdownTableSeparatorCellRegex = /^:?-{3,}:?$/;
6934
7232
  const fencedCodeBlockRegex = /^```/;
7233
+ const markdownHeadingRegex = /^\s*(#{1,6})\s+(.*)$/;
6935
7234
  const normalizeInlineTables = value => {
6936
7235
  return value.split(/\r?\n/).map(line => {
6937
7236
  if (!line.includes('|')) {
@@ -7034,6 +7333,7 @@ const parseMessageContent = rawMessage => {
7034
7333
  const nodes = [];
7035
7334
  let paragraphLines = [];
7036
7335
  let listItems = [];
7336
+ let listType = '';
7037
7337
  const flushParagraph = () => {
7038
7338
  if (paragraphLines.length === 0) {
7039
7339
  return;
@@ -7050,9 +7350,10 @@ const parseMessageContent = rawMessage => {
7050
7350
  }
7051
7351
  nodes.push({
7052
7352
  items: listItems,
7053
- type: 'list'
7353
+ type: listType || 'ordered-list'
7054
7354
  });
7055
7355
  listItems = [];
7356
+ listType = '';
7056
7357
  };
7057
7358
  for (let i = 0; i < lines.length; i++) {
7058
7359
  const line = lines[i];
@@ -7099,15 +7400,43 @@ const parseMessageContent = rawMessage => {
7099
7400
  continue;
7100
7401
  }
7101
7402
  }
7102
- const match = line.match(orderedListItemRegex);
7103
- if (match) {
7403
+ const orderedMatch = line.match(orderedListItemRegex);
7404
+ if (orderedMatch) {
7405
+ if (listType && listType !== 'ordered-list') {
7406
+ flushList();
7407
+ }
7104
7408
  flushParagraph();
7409
+ listType = 'ordered-list';
7105
7410
  listItems.push({
7106
- children: parseInlineNodes(match[1]),
7411
+ children: parseInlineNodes(orderedMatch[1]),
7107
7412
  type: 'list-item'
7108
7413
  });
7109
7414
  continue;
7110
7415
  }
7416
+ const unorderedMatch = line.match(unorderedListItemRegex);
7417
+ if (unorderedMatch) {
7418
+ if (listType && listType !== 'unordered-list') {
7419
+ flushList();
7420
+ }
7421
+ flushParagraph();
7422
+ listType = 'unordered-list';
7423
+ listItems.push({
7424
+ children: parseInlineNodes(unorderedMatch[1]),
7425
+ type: 'list-item'
7426
+ });
7427
+ continue;
7428
+ }
7429
+ const headingMatch = line.match(markdownHeadingRegex);
7430
+ if (headingMatch) {
7431
+ flushList();
7432
+ flushParagraph();
7433
+ nodes.push({
7434
+ children: parseInlineNodes(headingMatch[2]),
7435
+ level: headingMatch[1].length,
7436
+ type: 'heading'
7437
+ });
7438
+ continue;
7439
+ }
7111
7440
  flushList();
7112
7441
  paragraphLines.push(line);
7113
7442
  }
@@ -7561,6 +7890,7 @@ const commandMap = {
7561
7890
  'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
7562
7891
  'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
7563
7892
  'Chat.openMockSession': wrapCommand(openMockSession),
7893
+ 'Chat.registerMockResponse': wrapCommand(registerMockResponse),
7564
7894
  'Chat.render2': render2,
7565
7895
  'Chat.renderEventListeners': renderEventListeners,
7566
7896
  'Chat.rerender': wrapCommand(rerender),
@@ -7576,7 +7906,7 @@ const commandMap = {
7576
7906
  };
7577
7907
 
7578
7908
  const send = port => {
7579
- return invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatNetworkWorker', port, 'HandleMessagePort.handleMessagePort');
7909
+ return sendMessagePortToChatNetworkWorker(port);
7580
7910
  };
7581
7911
  const initializeChatNetworkWorker = async () => {
7582
7912
  const rpc = await create$4({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",