@lvce-editor/chat-view 7.1.0 → 7.2.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,20 +1118,13 @@ const create$2 = rpcId => {
1118
1118
  };
1119
1119
 
1120
1120
  const {
1121
- invoke: invoke$9,
1121
+ invoke: invoke$8,
1122
1122
  set: set$c
1123
1123
  } = create$2(6008);
1124
1124
 
1125
1125
  const {
1126
- invoke: invoke$8,
1127
1126
  set: set$b
1128
1127
  } = create$2(6007);
1129
- const getMathBlockDom = async node => {
1130
- return invoke$8('ChatMath.getMathBlockDom', node);
1131
- };
1132
- const getMathInlineDom = async node => {
1133
- return invoke$8('ChatMath.getMathInlineDom', node);
1134
- };
1135
1128
 
1136
1129
  const {
1137
1130
  invoke: invoke$7,
@@ -1185,7 +1178,7 @@ const Br = 55;
1185
1178
  const Tfoot = 59;
1186
1179
  const Ul = 60;
1187
1180
  const TextArea = 62;
1188
- const Select$1 = 63;
1181
+ const Select = 63;
1189
1182
  const Option = 64;
1190
1183
  const Code = 65;
1191
1184
  const Label$1 = 66;
@@ -2470,7 +2463,6 @@ const createDefaultState = () => {
2470
2463
  usageOverviewEnabled: false,
2471
2464
  useChatCoordinatorWorker: false,
2472
2465
  useChatMathWorker: true,
2473
- useChatMessageParsingWorker: false,
2474
2466
  useChatNetworkWorkerForRequests: false,
2475
2467
  useChatToolWorker: true,
2476
2468
  useMockApi: false,
@@ -3521,9 +3513,6 @@ const isRenameInputName = name => {
3521
3513
  const getRenameIdFromInputName = name => {
3522
3514
  return name.slice(RenamePrefix.length);
3523
3515
  };
3524
- const getModelPickerItemInputName = modelId => {
3525
- return `${ModelPickerItemPrefix}${modelId}`;
3526
- };
3527
3516
  const getGitBranchPickerItemInputName = branchName => {
3528
3517
  return `${GitBranchPickerItemPrefix}${branchName}`;
3529
3518
  };
@@ -4591,7 +4580,7 @@ const handleClickOpenRouterApiKeyWebsite = async state => {
4591
4580
  };
4592
4581
 
4593
4582
  const getAiResponse$1 = async options => {
4594
- return invoke$9('ChatCoordinator.getAiResponse', options);
4583
+ return invoke$8('ChatCoordinator.getAiResponse', options);
4595
4584
  };
4596
4585
 
4597
4586
  const execute = async (name, rawArguments, options) => {
@@ -7212,1477 +7201,47 @@ const getAiResponse = async ({
7212
7201
  } else {
7213
7202
  text = getOpenRouterErrorMessage(result);
7214
7203
  }
7215
- } else if (openRouterApiKey) {
7216
- const result = await getOpenRouterAssistantText(messages, modelId, openRouterApiKey, openRouterApiBaseUrl, assetDir, platform, useChatNetworkWorkerForRequests, useChatToolWorker, questionToolEnabled, systemPrompt, workspaceUri, agentMode, toolEnablement);
7217
- if (result.type === 'success') {
7218
- const {
7219
- text: assistantText
7220
- } = result;
7221
- text = assistantText;
7222
- } else {
7223
- text = getOpenRouterErrorMessage(result);
7224
- }
7225
- } else {
7226
- text = openRouterApiKeyRequiredMessage;
7227
- }
7228
- }
7229
- if (!text && !usesOpenApiModel && !usesOpenRouterModel) {
7230
- text = await getMockAiResponse(userText, mockAiResponseDelay);
7231
- }
7232
- const assistantTime = new Date().toLocaleTimeString([], {
7233
- hour: '2-digit',
7234
- minute: '2-digit'
7235
- });
7236
- const message = {
7237
- id: messageId || crypto.randomUUID(),
7238
- role: 'assistant',
7239
- text,
7240
- time: assistantTime
7241
- };
7242
- return message;
7243
- };
7244
-
7245
- const parseMessageContents = async rawMessages => {
7246
- return invoke$7('ChatMessageParsing.parseMessageContents', rawMessages);
7247
- };
7248
-
7249
- const Actions = 'Actions';
7250
- const Button = 'Button';
7251
- const ButtonPrimary = 'ButtonPrimary';
7252
- const ButtonSecondary = 'ButtonSecondary';
7253
- const Chat = 'Chat';
7254
- const ChatActions = 'ChatActions';
7255
- const ChatAuthError = 'ChatAuthError';
7256
- const ChatFocus = 'ChatFocus';
7257
- const ChatFocusActions = 'ChatFocusActions';
7258
- const ChatFocusHeader = 'ChatFocusHeader';
7259
- const ChatFocusMainArea = 'ChatFocusMainArea';
7260
- const ChatFocusProject = 'ChatFocusProject';
7261
- const ChatGitBranchPicker = 'ChatGitBranchPicker';
7262
- const ChatGitBranchPickerErrorMessage = 'ChatGitBranchPickerErrorMessage';
7263
- const ChatGitBranchPickerMessage = 'ChatGitBranchPickerMessage';
7264
- const ChatHeader = 'ChatHeader';
7265
- const ChatHeaderAuth = 'ChatHeaderAuth';
7266
- const ChatHeaderAuthName = 'ChatHeaderAuthName';
7267
- const ChatHeaderLabel = 'ChatHeaderLabel';
7268
- const ChatInputBox = 'ChatInputBox';
7269
- const ChatList = 'ChatList';
7270
- const ChatListEmpty = 'ChatListEmpty';
7271
- const ChatListItem = 'ChatListItem';
7272
- const ChatListItemFocused = 'ChatListItemFocused';
7273
- const ChatListItemLabel = 'ChatListItemLabel';
7274
- const ChatListItemStatusFinished = 'ChatListItemStatusFinished';
7275
- const ChatListItemStatusIcon = 'ChatListItemStatusIcon';
7276
- const ChatListItemStatusInProgress = 'ChatListItemStatusInProgress';
7277
- const ChatListItemStatusRow = 'ChatListItemStatusRow';
7278
- const ChatListItemStatusStopped = 'ChatListItemStatusStopped';
7279
- const ChatMessageContent = 'ChatMessageContent';
7280
- const ChatImageMessageContent = 'ChatImageMessageContent';
7281
- const ChatMessageLink = 'ChatMessageLink';
7282
- const ChatModelPicker = 'ChatModelPicker';
7283
- const ChatModelPickerContainer = 'ChatModelPickerContainer';
7284
- const ChatModelPickerHeader = 'ChatModelPickerHeader';
7285
- const ChatModelPickerItem = 'ChatModelPickerItem';
7286
- const ChatModelPickerItemLabel = 'ChatModelPickerItemLabel';
7287
- const ChatModelPickerItemSelected = 'ChatModelPickerItemSelected';
7288
- const ChatModelPickerItemUsageCost = 'ChatModelPickerItemUsageCost';
7289
- const ChatModelPickerList = 'ChatModelPickerList';
7290
- const ChatName = 'ChatName';
7291
- const ChatOverlays = 'ChatOverlays';
7292
- const ChatOrderedList = 'ChatOrderedList';
7293
- const ChatOrderedListItem = 'ChatOrderedListItem';
7294
- const ChatOrderedListItemContent = 'ChatOrderedListItemContent';
7295
- const ChatOrderedListItemPrefix = 'ChatOrderedListItemPrefix';
7296
- const ChatOrderedListMarker = 'ChatOrderedListMarker';
7297
- const ChatComposerAttachment = 'ChatComposerAttachment';
7298
- const ChatComposerAttachmentImage = 'ChatComposerAttachmentImage';
7299
- const ChatComposerAttachmentInvalidImage = 'ChatComposerAttachmentInvalidImage';
7300
- const ChatComposerAttachmentLabel = 'ChatComposerAttachmentLabel';
7301
- const ChatComposerAttachmentPreview = 'ChatComposerAttachmentPreview';
7302
- const ChatComposerAttachmentPreviewOverlay = 'ChatComposerAttachmentPreviewOverlay';
7303
- const ChatComposerAttachmentPreviewOverlayError = 'ChatComposerAttachmentPreviewOverlayError';
7304
- const ChatComposerAttachmentPreviewOverlayImage = 'ChatComposerAttachmentPreviewOverlayImage';
7305
- const ChatComposerAttachmentRemoveButton = 'ChatComposerAttachmentRemoveButton';
7306
- const ChatComposerAttachments = 'ChatComposerAttachments';
7307
- const ChatComposerAttachmentTextFile = 'ChatComposerAttachmentTextFile';
7308
- const ChatAttachment = 'ChatAttachment';
7309
- const ChatAttachmentImage = 'ChatAttachmentImage';
7310
- const ChatAttachmentInvalidImage = 'ChatAttachmentInvalidImage';
7311
- const ChatAttachmentLabel = 'ChatAttachmentLabel';
7312
- const ChatAttachmentPreview = 'ChatAttachmentPreview';
7313
- const ChatAttachments = 'ChatAttachments';
7314
- const ChatAttachmentTextFile = 'ChatAttachmentTextFile';
7315
- const ChatMessageImage = 'ChatMessageImage';
7316
- const ChatSendArea = 'ChatSendArea';
7317
- const ChatSendAreaBottom = 'ChatSendAreaBottom';
7318
- const ChatSendAreaContent = 'ChatSendAreaContent';
7319
- const ChatSendAreaPrimaryControls = 'ChatSendAreaPrimaryControls';
7320
- const ChatTableWrapper = 'ChatTableWrapper';
7321
- const ChatTodoList = 'ChatTodoList';
7322
- const ChatTodoListHeader = 'ChatTodoListHeader';
7323
- const ChatTodoListItem = 'ChatTodoListItem';
7324
- const ChatTodoListItemCompleted = 'ChatTodoListItemCompleted';
7325
- const ChatTodoListItemInProgress = 'ChatTodoListItemInProgress';
7326
- const ChatTodoListItems = 'ChatTodoListItems';
7327
- const ChatTodoListItemTodo = 'ChatTodoListItemTodo';
7328
- const ChatToolCallFileName = 'ChatToolCallFileName';
7329
- const ChatToolCallQuestionOption = 'ChatToolCallQuestionOption';
7330
- const ChatToolCallQuestionOptions = 'ChatToolCallQuestionOptions';
7331
- const ChatToolCallQuestionText = 'ChatToolCallQuestionText';
7332
- const ChatToolCallReadFileLink = 'ChatToolCallReadFileLink';
7333
- const ChatToolCallRenderHtmlBody = 'ChatToolCallRenderHtmlBody';
7334
- const ChatToolCallRenderHtmlContent = 'ChatToolCallRenderHtmlContent';
7335
- const ChatToolCallRenderHtmlLabel = 'ChatToolCallRenderHtmlLabel';
7336
- const ChatToolCalls = 'ChatToolCalls';
7337
- const ChatToolCallsLabel = 'ChatToolCallsLabel';
7338
- const ChatUnorderedList = 'ChatUnorderedList';
7339
- const ChatUnorderedListItem = 'ChatUnorderedListItem';
7340
- const ChatViewDropOverlay = 'ChatViewDropOverlay';
7341
- const ChatViewDropOverlayActive = 'ChatViewDropOverlayActive';
7342
- const ChatWelcomeMessage = 'ChatWelcomeMessage';
7343
- const CustomSelectContainer = 'CustomSelectContainer';
7344
- const CustomSelectPopOver = 'CustomSelectPopOver';
7345
- const Deletion = 'Deletion';
7346
- const Empty = '';
7347
- const FileIcon = 'FileIcon';
7348
- const IconButton = 'IconButton';
7349
- const IconButtonDisabled = 'IconButtonDisabled';
7350
- const ImageElement = 'ImageElement';
7351
- const ImageErrorMessage = 'ImageErrorMessage';
7352
- const InputBox = 'InputBox';
7353
- const InputInvalid = 'InputInvalid';
7354
- const Insertion = 'Insertion';
7355
- const Label = 'Label';
7356
- const LabelDetail = 'LabelDetail';
7357
- const Markdown = 'Markdown';
7358
- const MarkdownMathBlock = 'MarkdownMathBlock';
7359
- const MarkdownQuote = 'MarkdownQuote';
7360
- const MarkdownTable = 'MarkdownTable';
7361
- const MaskIcon = 'MaskIcon';
7362
- const MaskIconAdd = 'MaskIconAdd';
7363
- const MaskIconArrowLeft = 'MaskIconArrowLeft';
7364
- const MaskIconChevronDown = 'MaskIconChevronDown';
7365
- const MaskIconChevronRight = 'MaskIconChevronRight';
7366
- const MaskIconChevronUp = 'MaskIconChevronUp';
7367
- const MaskIconClose = 'MaskIconClose';
7368
- const MaskIconDebugPause = 'MaskIconDebugPause';
7369
- const MaskIconLayoutPanelLeft = 'MaskIconLayoutPanelLeft';
7370
- const MaskIconSearch = 'MaskIconSearch';
7371
- const MaskIconSettingsGear = 'MaskIconSettingsGear';
7372
- const Message = 'Message';
7373
- const MessageAssistant = 'MessageAssistant';
7374
- const MessageUser = 'MessageUser';
7375
- const MissingApiKeyForm = 'MissingApiKeyForm';
7376
- const MultiLineInputBox = 'MultilineInputBox';
7377
- const ProjectAddButton = 'ProjectAddButton';
7378
- const ProjectList = 'ProjectList';
7379
- const ProjectListChevron = 'ProjectListChevron';
7380
- const ProjectListGroup = 'ProjectListGroup';
7381
- const ProjectListItem = 'ProjectListItem';
7382
- const ProjectListItemActions = 'ProjectListItemActions';
7383
- const ProjectListItemAddChatButton = 'ProjectListItemAddChatButton';
7384
- const ProjectListItemLabel = 'ProjectListItemLabel';
7385
- const ProjectListItemSelected = 'ProjectListItemSelected';
7386
- const ProjectSessionItem = 'ProjectSessionItem';
7387
- const ProjectSessionItemLabel = 'ProjectSessionItemLabel';
7388
- const ProjectSessionItemSelected = 'ProjectSessionItemSelected';
7389
- const ProjectSidebar = 'ProjectSidebar';
7390
- const SearchFieldContainer = 'SearchFieldContainer';
7391
- const RunModePickerContainer = 'RunModePickerContainer';
7392
- const RunModePickerPopOver = 'RunModePickerPopOver';
7393
- const Select = 'Select';
7394
- const SelectLabel = 'SelectLabel';
7395
- const SendButtonDisabled = 'SendButtonDisabled';
7396
- const SessionArchiveButton = 'SessionArchiveButton';
7397
- const StrikeThrough = 'StrikeThrough';
7398
- const TokenAttribute = 'TokenAttribute';
7399
- const TokenComment = 'TokenComment';
7400
- const TokenKeyword = 'TokenKeyword';
7401
- const TokenNumber = 'TokenNumber';
7402
- const TokenProperty = 'TokenProperty';
7403
- const TokenString = 'TokenString';
7404
- const TokenTag = 'TokenTag';
7405
- const TokenUsageOverview = 'TokenUsageOverview';
7406
- const TokenUsageRing = 'TokenUsageRing';
7407
- const TokenUsageRingInner = 'TokenUsageRingInner';
7408
- const TokenValue = 'TokenValue';
7409
- const ToolCallName = 'ToolCallName';
7410
- const Viewlet = 'Viewlet';
7411
-
7412
- const jsRules = [{
7413
- className: TokenComment,
7414
- regex: /\/\/[^\n]*/
7415
- }, {
7416
- className: TokenComment,
7417
- regex: /\/\*[\s\S]*?\*\//
7418
- }, {
7419
- className: TokenString,
7420
- regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
7421
- }, {
7422
- className: TokenString,
7423
- regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
7424
- }, {
7425
- className: TokenString,
7426
- regex: /`[^`\\]*(?:\\.[^`\\]*)*`/
7427
- }, {
7428
- className: TokenNumber,
7429
- regex: /\b\d+\.?\d*\b/
7430
- }, {
7431
- className: TokenKeyword,
7432
- regex: /\b(?:const|let|var|function|return|if|else|for|while|class|new|typeof|instanceof|import|export|from|default|async|await|try|catch|finally|throw|this|true|false|null|undefined)\b/
7433
- }];
7434
- const tsRules = [{
7435
- className: TokenComment,
7436
- regex: /\/\/[^\n]*/
7437
- }, {
7438
- className: TokenComment,
7439
- regex: /\/\*[\s\S]*?\*\//
7440
- }, {
7441
- className: TokenString,
7442
- regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
7443
- }, {
7444
- className: TokenString,
7445
- regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
7446
- }, {
7447
- className: TokenString,
7448
- regex: /`[^`\\]*(?:\\.[^`\\]*)*`/
7449
- }, {
7450
- className: TokenNumber,
7451
- regex: /\b\d+\.?\d*\b/
7452
- }, {
7453
- className: TokenKeyword,
7454
- regex: /\b(?:abstract|any|as|asserts|async|await|boolean|class|const|constructor|declare|default|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|infer|instanceof|interface|is|keyof|let|module|namespace|never|new|null|number|object|override|private|protected|public|readonly|return|satisfies|set|static|string|super|switch|symbol|this|throw|true|try|type|typeof|undefined|unknown|var|void|while)\b/
7455
- }];
7456
- const htmlRules = [{
7457
- className: TokenComment,
7458
- regex: /<!--[\s\S]*?-->/
7459
- }, {
7460
- className: TokenTag,
7461
- regex: /<\/[a-zA-Z][a-zA-Z0-9-]*\s*>/
7462
- }, {
7463
- className: TokenTag,
7464
- regex: /<[a-zA-Z][a-zA-Z0-9-]*/
7465
- }, {
7466
- className: TokenTag,
7467
- regex: /\/?>/
7468
- }, {
7469
- className: TokenString,
7470
- regex: /"[^"]*"/
7471
- }, {
7472
- className: TokenString,
7473
- regex: /'[^']*'/
7474
- }, {
7475
- className: TokenAttribute,
7476
- regex: /[a-zA-Z-]+(?=\s*=)/
7477
- }];
7478
- const cssRules = [{
7479
- className: TokenComment,
7480
- regex: /\/\*[\s\S]*?\*\//
7481
- }, {
7482
- className: TokenString,
7483
- regex: /"[^"]*"/
7484
- }, {
7485
- className: TokenString,
7486
- regex: /'[^']*'/
7487
- }, {
7488
- className: TokenValue,
7489
- regex: /#[0-9a-fA-F]{3,8}/
7490
- }, {
7491
- className: TokenValue,
7492
- regex: /\b\d+(?:\.\d+)?(?:px|em|rem|%|vh|vw|pt|s|ms|fr)?\b/
7493
- }, {
7494
- className: TokenProperty,
7495
- regex: /[a-zA-Z-]+(?=\s*:)/
7496
- }];
7497
- const pythonRules = [{
7498
- className: TokenComment,
7499
- regex: /#[^\n]*/
7500
- }, {
7501
- className: TokenString,
7502
- regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
7503
- }, {
7504
- className: TokenString,
7505
- regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
7506
- }, {
7507
- className: TokenNumber,
7508
- regex: /\b\d+\.?\d*\b/
7509
- }, {
7510
- className: TokenKeyword,
7511
- regex: /\b(?:def|class|return|if|elif|else|for|while|in|import|from|as|with|try|except|finally|raise|lambda|yield|pass|break|continue|True|False|None|and|or|not|is)\b/
7512
- }];
7513
- const jsonRules = [{
7514
- className: TokenProperty,
7515
- regex: /"[^"\\]*(?:\\.[^"\\]*)*"(?=\s*:)/
7516
- }, {
7517
- className: TokenString,
7518
- regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
7519
- }, {
7520
- className: TokenNumber,
7521
- regex: /-?\b\d+\.?\d*(?:[eE][+-]?\d+)?\b/
7522
- }, {
7523
- className: TokenKeyword,
7524
- regex: /\b(?:true|false|null)\b/
7525
- }];
7526
- const tokenize = (code, rules) => {
7527
- const tokens = [];
7528
- let pos = 0;
7529
- while (pos < code.length) {
7530
- let matched = false;
7531
- for (const rule of rules) {
7532
- const match = rule.regex.exec(code.slice(pos));
7533
- if (match && match.index === 0) {
7534
- tokens.push({
7535
- className: rule.className,
7536
- text: match[0]
7537
- });
7538
- pos += match[0].length;
7539
- matched = true;
7540
- break;
7541
- }
7542
- }
7543
- if (!matched) {
7544
- const last = tokens.at(-1);
7545
- if (last && last.className === '') {
7546
- tokens.pop();
7547
- tokens.push({
7548
- className: '',
7549
- text: last.text + code[pos]
7550
- });
7551
- } else {
7552
- tokens.push({
7553
- className: '',
7554
- text: code[pos]
7555
- });
7556
- }
7557
- pos++;
7558
- }
7559
- }
7560
- return tokens;
7561
- };
7562
- const highlightCode = (code, language) => {
7563
- if (!language) {
7564
- return [{
7565
- className: '',
7566
- text: code
7567
- }];
7568
- }
7569
- const normalized = language.toLowerCase();
7570
- if (normalized === 'html') {
7571
- return tokenize(code, htmlRules);
7572
- }
7573
- if (normalized === 'css') {
7574
- return tokenize(code, cssRules);
7575
- }
7576
- if (normalized === 'js' || normalized === 'javascript') {
7577
- return tokenize(code, jsRules);
7578
- }
7579
- if (normalized === 'ts' || normalized === 'typescript') {
7580
- return tokenize(code, tsRules);
7581
- }
7582
- if (normalized === 'py' || normalized === 'python') {
7583
- return tokenize(code, pythonRules);
7584
- }
7585
- if (normalized === 'json') {
7586
- return tokenize(code, jsonRules);
7587
- }
7588
- return [{
7589
- className: '',
7590
- text: code
7591
- }];
7592
- };
7593
-
7594
- const isAlphaNumeric = value => {
7595
- if (!value) {
7596
- return false;
7597
- }
7598
- const code = value.codePointAt(0) ?? 0;
7599
- if (code >= 48 && code <= 57) {
7600
- return true;
7601
- }
7602
- if (code >= 65 && code <= 90) {
7603
- return true;
7604
- }
7605
- return code >= 97 && code <= 122;
7606
- };
7607
- const sanitizeLinkUrl = url => {
7608
- const trimmedUrl = url.trim();
7609
- const normalized = url.trim().toLowerCase();
7610
- if (normalized.startsWith('http://') || normalized.startsWith('https://') || normalized.startsWith('file://') || normalized.startsWith('vscode-references://')) {
7611
- return trimmedUrl;
7612
- }
7613
- if (!trimmedUrl || trimmedUrl.startsWith('#') || trimmedUrl.startsWith('?') || trimmedUrl.startsWith('/') || trimmedUrl.startsWith('\\')) {
7614
- return '#';
7615
- }
7616
- if (trimmedUrl.includes('://') || trimmedUrl.includes(':')) {
7617
- return '#';
7618
- }
7619
- if (isPathTraversalAttempt(trimmedUrl)) {
7620
- return '#';
7621
- }
7622
- const normalizedPath = normalizeRelativePath(trimmedUrl);
7623
- if (normalizedPath === '.') {
7624
- return '#';
7625
- }
7626
- return `file:///workspace/${normalizedPath}`;
7627
- };
7628
- const sanitizeImageUrl = url => {
7629
- const normalized = url.trim().toLowerCase();
7630
- if (normalized.startsWith('http://') || normalized.startsWith('https://')) {
7631
- return url;
7632
- }
7633
- return '#';
7634
- };
7635
- const isOpenBracket = value => {
7636
- return value === '(' || value === '[' || value === '{';
7637
- };
7638
- const isCloseBracket = value => {
7639
- return value === ')' || value === ']' || value === '}';
7640
- };
7641
- const findRawUrlEnd = (value, start) => {
7642
- let index = start;
7643
- while (index < value.length) {
7644
- const current = value[index];
7645
- if (current === ' ' || current === '\n' || current === '\r' || current === '\t' || current === '"' || current === "'" || current === '`' || current === '<' || current === '>') {
7646
- break;
7647
- }
7648
- index++;
7649
- }
7650
- return index;
7651
- };
7652
- const trimRawUrlEnd = url => {
7653
- let end = url.length;
7654
- while (end > 0) {
7655
- const current = url[end - 1];
7656
- if (current === '.' || current === ',' || current === ':' || current === ';' || current === '!' || current === '?') {
7657
- end--;
7658
- continue;
7659
- }
7660
- if (isCloseBracket(current)) {
7661
- const inner = url.slice(0, end - 1);
7662
- let openCount = 0;
7663
- let closeCount = 0;
7664
- for (let i = 0; i < inner.length; i++) {
7665
- if (isOpenBracket(inner[i])) {
7666
- openCount++;
7667
- } else if (isCloseBracket(inner[i])) {
7668
- closeCount++;
7669
- }
7670
- }
7671
- if (closeCount >= openCount) {
7672
- end--;
7673
- continue;
7674
- }
7675
- }
7676
- break;
7677
- }
7678
- return url.slice(0, end);
7679
- };
7680
- const parseRawLinkToken = (value, start) => {
7681
- if (!value.startsWith('https://', start) && !value.startsWith('http://', start)) {
7682
- return undefined;
7683
- }
7684
- if (start >= 2 && value[start - 1] === '(' && value[start - 2] === ']') {
7685
- return undefined;
7686
- }
7687
- const end = findRawUrlEnd(value, start);
7688
- const rawUrl = value.slice(start, end);
7689
- const href = trimRawUrlEnd(rawUrl);
7690
- if (!href) {
7691
- return undefined;
7692
- }
7693
- return {
7694
- length: href.length,
7695
- node: {
7696
- href: sanitizeLinkUrl(href),
7697
- text: href,
7698
- type: 'link'
7699
- }
7700
- };
7701
- };
7702
- const parseLinkToken = (value, start) => {
7703
- if (value[start] !== '[') {
7704
- return undefined;
7705
- }
7706
- const textEnd = value.indexOf(']', start + 1);
7707
- if (textEnd === -1) {
7708
- return undefined;
7709
- }
7710
- if (value[textEnd + 1] !== '(') {
7711
- return undefined;
7712
- }
7713
- let depth = 1;
7714
- let index = textEnd + 2;
7715
- while (index < value.length) {
7716
- const current = value[index];
7717
- if (current === '\n') {
7718
- return undefined;
7719
- }
7720
- if (current === '(') {
7721
- depth++;
7722
- } else if (current === ')') {
7723
- depth--;
7724
- if (depth === 0) {
7725
- const text = value.slice(start + 1, textEnd);
7726
- const href = value.slice(textEnd + 2, index);
7727
- if (!text || !href) {
7728
- return undefined;
7729
- }
7730
- return {
7731
- length: index - start + 1,
7732
- node: {
7733
- href: sanitizeLinkUrl(href),
7734
- text,
7735
- type: 'link'
7736
- }
7737
- };
7738
- }
7739
- }
7740
- index++;
7741
- }
7742
- return undefined;
7743
- };
7744
- const parseImageToken = (value, start) => {
7745
- if (value[start] !== '!' || value[start + 1] !== '[') {
7746
- return undefined;
7747
- }
7748
- const textEnd = value.indexOf(']', start + 2);
7749
- if (textEnd === -1) {
7750
- return undefined;
7751
- }
7752
- if (value[textEnd + 1] !== '(') {
7753
- return undefined;
7754
- }
7755
- let depth = 1;
7756
- let index = textEnd + 2;
7757
- while (index < value.length) {
7758
- const current = value[index];
7759
- if (current === '\n') {
7760
- return undefined;
7761
- }
7762
- if (current === '(') {
7763
- depth++;
7764
- } else if (current === ')') {
7765
- depth--;
7766
- if (depth === 0) {
7767
- const alt = value.slice(start + 2, textEnd);
7768
- const src = value.slice(textEnd + 2, index);
7769
- if (!src) {
7770
- return undefined;
7771
- }
7772
- return {
7773
- length: index - start + 1,
7774
- node: {
7775
- alt,
7776
- src: sanitizeImageUrl(src),
7777
- type: 'image'
7778
- }
7779
- };
7780
- }
7781
- }
7782
- index++;
7783
- }
7784
- return undefined;
7785
- };
7786
- const parseBoldToken = (value, start) => {
7787
- if (value[start] !== '*' || value[start + 1] !== '*') {
7788
- return undefined;
7789
- }
7790
- const end = value.indexOf('**', start + 2);
7791
- if (end === -1) {
7792
- return undefined;
7793
- }
7794
- const text = value.slice(start + 2, end);
7795
- if (!text || text.includes('\n')) {
7796
- return undefined;
7797
- }
7798
- return {
7799
- length: end - start + 2,
7800
- node: {
7801
- children: parseInlineNodes(text),
7802
- type: 'bold'
7803
- }
7804
- };
7805
- };
7806
- const parseBoldItalicToken = (value, start) => {
7807
- if (value[start] !== '*' || value[start + 1] !== '*' || value[start + 2] !== '*') {
7808
- return undefined;
7809
- }
7810
- const end = value.indexOf('***', start + 3);
7811
- if (end === -1) {
7812
- return undefined;
7813
- }
7814
- const text = value.slice(start + 3, end);
7815
- if (!text || text.includes('\n')) {
7816
- return undefined;
7817
- }
7818
- return {
7819
- length: end - start + 3,
7820
- node: {
7821
- children: [{
7822
- children: parseInlineNodes(text),
7823
- type: 'italic'
7824
- }],
7825
- type: 'bold'
7826
- }
7827
- };
7828
- };
7829
- const findItalicEnd = (value, start) => {
7830
- let index = start + 1;
7831
- while (index < value.length) {
7832
- if (value[index] !== '*') {
7833
- index++;
7834
- continue;
7835
- }
7836
- if (value[index + 1] !== '*') {
7837
- return index;
7838
- }
7839
- const boldEnd = value.indexOf('**', index + 2);
7840
- if (boldEnd === -1) {
7841
- return -1;
7842
- }
7843
- index = boldEnd + 2;
7844
- }
7845
- return -1;
7846
- };
7847
- const parseItalicToken = (value, start) => {
7848
- if (value[start] !== '*' || value[start + 1] === '*') {
7849
- return undefined;
7850
- }
7851
- const end = findItalicEnd(value, start);
7852
- if (end === -1) {
7853
- return undefined;
7854
- }
7855
- const text = value.slice(start + 1, end);
7856
- if (!text) {
7857
- return undefined;
7858
- }
7859
- return {
7860
- length: end - start + 1,
7861
- node: {
7862
- children: parseInlineNodes(text),
7863
- type: 'italic'
7864
- }
7865
- };
7866
- };
7867
- const parseStrikethroughToken = (value, start) => {
7868
- if (value[start] !== '~' || value[start + 1] !== '~') {
7869
- return undefined;
7870
- }
7871
- const end = value.indexOf('~~', start + 2);
7872
- if (end === -1) {
7873
- return undefined;
7874
- }
7875
- const text = value.slice(start + 2, end);
7876
- if (!text || text.includes('\n')) {
7877
- return undefined;
7878
- }
7879
- return {
7880
- length: end - start + 2,
7881
- node: {
7882
- children: parseInlineNodes(text),
7883
- type: 'strikethrough'
7884
- }
7885
- };
7886
- };
7887
- const parseInlineCodeToken = (value, start) => {
7888
- if (value[start] !== '`') {
7889
- return undefined;
7890
- }
7891
- const end = value.indexOf('`', start + 1);
7892
- if (end === -1) {
7893
- return undefined;
7894
- }
7895
- const codeText = value.slice(start + 1, end);
7896
- if (!codeText || codeText.includes('\n')) {
7897
- return undefined;
7898
- }
7899
- return {
7900
- length: end - start + 1,
7901
- node: {
7902
- text: codeText,
7903
- type: 'inline-code'
7904
- }
7905
- };
7906
- };
7907
- const parseMathToken = (value, start) => {
7908
- if (value[start] !== '$') {
7909
- return undefined;
7910
- }
7911
- const delimiterLength = value[start + 1] === '$' ? 2 : 1;
7912
- const previous = value[start - 1];
7913
- if (isAlphaNumeric(previous)) {
7914
- return undefined;
7915
- }
7916
- const next = value[start + delimiterLength];
7917
- if (!next || next === '.') {
7918
- return undefined;
7919
- }
7920
- if (next === '(' && (value[start + delimiterLength + 1] === '"' || value[start + delimiterLength + 1] === "'")) {
7921
- return undefined;
7922
- }
7923
- let index = start + delimiterLength;
7924
- while (index < value.length) {
7925
- if (value[index] === '\n') {
7926
- return undefined;
7927
- }
7928
- const isClosed = delimiterLength === 2 ? value.startsWith('$$', index) : value[index] === '$';
7929
- if (isClosed) {
7930
- const body = value.slice(start + delimiterLength, index);
7931
- const following = value[index + delimiterLength];
7932
- if (!body || isAlphaNumeric(following)) {
7933
- return undefined;
7934
- }
7935
- return {
7936
- length: index - start + delimiterLength,
7937
- node: {
7938
- displayMode: delimiterLength === 2,
7939
- text: body.trim(),
7940
- type: 'math-inline'
7941
- }
7942
- };
7943
- }
7944
- if (value[index] === '\\') {
7945
- index += 2;
7946
- continue;
7947
- }
7948
- index++;
7949
- }
7950
- return undefined;
7951
- };
7952
- const parseInlineToken = (value, start) => {
7953
- return parseImageToken(value, start) || parseLinkToken(value, start) || parseRawLinkToken(value, start) || parseBoldItalicToken(value, start) || parseBoldToken(value, start) || parseItalicToken(value, start) || parseLinkToken(value, start) || parseBoldItalicToken(value, start) || parseBoldToken(value, start) || parseItalicToken(value, start) || parseStrikethroughToken(value, start) || parseInlineCodeToken(value, start) || parseMathToken(value, start);
7954
- };
7955
- const parseInlineNodes = value => {
7956
- const nodes = [];
7957
- let textStart = 0;
7958
- let index = 0;
7959
- const pushText = end => {
7960
- if (end <= textStart) {
7961
- return;
7962
- }
7963
- nodes.push({
7964
- text: value.slice(textStart, end),
7965
- type: 'text'
7966
- });
7967
- };
7968
- while (index < value.length) {
7969
- const parsed = parseInlineToken(value, index);
7970
- if (!parsed) {
7971
- index++;
7972
- continue;
7973
- }
7974
- pushText(index);
7975
- nodes.push(parsed.node);
7976
- index += parsed.length;
7977
- textStart = index;
7978
- }
7979
- pushText(value.length);
7980
- if (nodes.length === 0) {
7981
- return [{
7982
- text: value,
7983
- type: 'text'
7984
- }];
7985
- }
7986
- return nodes;
7987
- };
7988
-
7989
- const markdownMathBlockDelimiter = '$$';
7990
- const escapedNewlineRegex = /\\r\\n|\\n/g;
7991
- const lineBreakRegex = /\r?\n/;
7992
- const tableDelimiterRegex = /\|\s*[-:]{3,}/;
7993
- const inlineTableCellRegex = /\|\s+\|/g;
7994
- const normalizeEscapedNewlines = value => {
7995
- if (value.includes('\\n')) {
7996
- return value.replaceAll(escapedNewlineRegex, '\n');
7997
- }
7998
- return value;
7999
- };
8000
- const normalizeInlineTables = value => {
8001
- return value.split(lineBreakRegex).map(line => {
8002
- if (!line.includes('|')) {
8003
- return line;
8004
- }
8005
- if (!tableDelimiterRegex.test(line)) {
8006
- return line;
8007
- }
8008
- return line.replaceAll(inlineTableCellRegex, '|\n|');
8009
- }).join('\n');
8010
- };
8011
- const parseHeadingLine = line => {
8012
- const trimmedStart = line.trimStart();
8013
- let index = 0;
8014
- while (index < trimmedStart.length && trimmedStart[index] === '#') {
8015
- index++;
8016
- }
8017
- if (index === 0 || index > 6) {
8018
- return undefined;
8019
- }
8020
- if (trimmedStart[index] !== ' ') {
8021
- return undefined;
8022
- }
8023
- const text = trimmedStart.slice(index).trimStart();
8024
- return {
8025
- level: index,
8026
- text
8027
- };
8028
- };
8029
- const parseOrderedListItemLine = line => {
8030
- let indentation = 0;
8031
- while (indentation < line.length && line[indentation] === ' ') {
8032
- indentation++;
8033
- }
8034
- let index = indentation;
8035
- const firstDigit = index;
8036
- while (index < line.length && line[index] >= '0' && line[index] <= '9') {
8037
- index++;
8038
- }
8039
- if (index === firstDigit || line[index] !== '.') {
8040
- return undefined;
8041
- }
8042
- index++;
8043
- if (line[index] !== ' ') {
8044
- return undefined;
8045
- }
8046
- while (index < line.length && line[index] === ' ') {
8047
- index++;
8048
- }
8049
- return {
8050
- indentation,
8051
- text: line.slice(index)
8052
- };
8053
- };
8054
- const parseUnorderedListItemLine = line => {
8055
- let indentation = 0;
8056
- while (indentation < line.length && line[indentation] === ' ') {
8057
- indentation++;
8058
- }
8059
- const marker = line[indentation];
8060
- if (marker !== '-' && marker !== '*') {
8061
- return undefined;
8062
- }
8063
- let index = indentation + 1;
8064
- if (line[index] !== ' ') {
8065
- return undefined;
8066
- }
8067
- while (index < line.length && line[index] === ' ') {
8068
- index++;
8069
- }
8070
- return {
8071
- indentation,
8072
- text: line.slice(index)
8073
- };
8074
- };
8075
- const parseBlockQuoteLine = line => {
8076
- const trimmedStart = line.trimStart();
8077
- if (!trimmedStart.startsWith('>')) {
8078
- return undefined;
8079
- }
8080
- const content = trimmedStart.slice(1);
8081
- if (!content) {
8082
- return '';
8083
- }
8084
- if (content.startsWith(' ')) {
8085
- return content.slice(1);
8086
- }
8087
- return content;
8088
- };
8089
- const isThematicBreakLine = line => {
8090
- const trimmedStart = line.trimStart();
8091
- const leadingSpaces = line.length - trimmedStart.length;
8092
- if (leadingSpaces > 3) {
8093
- return false;
8094
- }
8095
- const trimmed = trimmedStart.trimEnd();
8096
- if (!trimmed) {
8097
- return false;
8098
- }
8099
- const marker = trimmed[0];
8100
- if (marker !== '-' && marker !== '_' && marker !== '*') {
8101
- return false;
8102
- }
8103
- let markerCount = 0;
8104
- for (let i = 0; i < trimmed.length; i++) {
8105
- const char = trimmed[i];
8106
- if (char === marker) {
8107
- markerCount++;
8108
- continue;
8109
- }
8110
- if (char !== ' ') {
8111
- return false;
8112
- }
8113
- }
8114
- return markerCount >= 3;
8115
- };
8116
- const isTableRow = line => {
8117
- const trimmed = line.trim();
8118
- if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) {
8119
- return false;
8120
- }
8121
- return trimmed.length > 2;
8122
- };
8123
- const getTableCells = line => {
8124
- const trimmed = line.trim();
8125
- return trimmed.slice(1, -1).split('|').map(part => part.trim());
8126
- };
8127
- const scanBlockTokens = rawMessage => {
8128
- const normalizedMessage = normalizeInlineTables(normalizeEscapedNewlines(rawMessage));
8129
- const lines = normalizedMessage.split(lineBreakRegex);
8130
- const tokens = [];
8131
- for (let i = 0; i < lines.length; i++) {
8132
- const line = lines[i];
8133
- const trimmed = line.trim();
8134
- if (!trimmed) {
8135
- tokens.push({
8136
- type: 'blank-line'
8137
- });
8138
- continue;
8139
- }
8140
- const blockQuoteLine = parseBlockQuoteLine(line);
8141
- if (blockQuoteLine !== undefined) {
8142
- tokens.push({
8143
- text: blockQuoteLine,
8144
- type: 'blockquote-line'
8145
- });
8146
- continue;
8147
- }
8148
- if (trimmed.startsWith('```')) {
8149
- const language = trimmed.slice(3).trim();
8150
- const codeLines = [];
8151
- i++;
8152
- while (i < lines.length && !lines[i].trim().startsWith('```')) {
8153
- codeLines.push(lines[i]);
8154
- i++;
8155
- }
8156
- if (language) {
8157
- tokens.push({
8158
- language,
8159
- text: codeLines.join('\n'),
8160
- type: 'code-block'
8161
- });
8162
- } else {
8163
- tokens.push({
8164
- text: codeLines.join('\n'),
8165
- type: 'code-block'
8166
- });
8167
- }
8168
- continue;
8169
- }
8170
- if (trimmed === markdownMathBlockDelimiter) {
8171
- const endIndex = lines.findIndex((candidate, index) => {
8172
- if (index <= i) {
8173
- return false;
8174
- }
8175
- return candidate.trim() === markdownMathBlockDelimiter;
8176
- });
8177
- if (endIndex !== -1) {
8178
- tokens.push({
8179
- text: lines.slice(i + 1, endIndex).join('\n').trim(),
8180
- type: 'math-block'
8181
- });
8182
- i = endIndex;
8183
- continue;
8184
- }
8185
- }
8186
- const heading = parseHeadingLine(line);
8187
- if (heading) {
8188
- tokens.push({
8189
- level: heading.level,
8190
- text: heading.text,
8191
- type: 'heading-line'
8192
- });
8193
- continue;
8194
- }
8195
- if (isThematicBreakLine(line)) {
8196
- tokens.push({
8197
- type: 'thematic-break'
8198
- });
8199
- continue;
8200
- }
8201
- const ordered = parseOrderedListItemLine(line);
8202
- if (ordered) {
8203
- tokens.push({
8204
- indentation: ordered.indentation,
8205
- text: ordered.text,
8206
- type: 'ordered-list-item-line'
8207
- });
8208
- continue;
8209
- }
8210
- const unordered = parseUnorderedListItemLine(line);
8211
- if (unordered) {
8212
- tokens.push({
8213
- indentation: unordered.indentation,
8214
- text: unordered.text,
8215
- type: 'unordered-list-item-line'
8216
- });
8217
- continue;
8218
- }
8219
- if (isTableRow(line)) {
8220
- tokens.push({
8221
- cells: getTableCells(line),
8222
- line,
8223
- type: 'table-row-line'
8224
- });
8225
- continue;
8226
- }
8227
- tokens.push({
8228
- text: line,
8229
- type: 'paragraph-line'
8230
- });
8231
- }
8232
- return tokens;
8233
- };
8234
-
8235
- const isTableSeparatorCell = value => {
8236
- if (!value) {
8237
- return false;
8238
- }
8239
- let index = 0;
8240
- if (value[index] === ':') {
8241
- index++;
8242
- }
8243
- let dashCount = 0;
8244
- while (index < value.length && value[index] === '-') {
8245
- dashCount++;
8246
- index++;
8247
- }
8248
- if (dashCount < 3) {
8249
- return false;
8250
- }
8251
- if (index < value.length && value[index] === ':') {
8252
- index++;
8253
- }
8254
- return index === value.length;
8255
- };
8256
- const isTableSeparatorToken = (token, expectedColumns) => {
8257
- if (!token || token.type !== 'table-row-line') {
8258
- return false;
8259
- }
8260
- if (token.cells.length !== expectedColumns) {
8261
- return false;
8262
- }
8263
- return token.cells.every(isTableSeparatorCell);
8264
- };
8265
- const toTableCell = value => {
8266
- return {
8267
- children: parseInlineNodes(value),
8268
- type: 'table-cell'
8269
- };
8270
- };
8271
- const toTableRow = token => {
8272
- return {
8273
- cells: token.cells.map(toTableCell),
8274
- type: 'table-row'
8275
- };
8276
- };
8277
- const getEmptyTextNode = () => {
8278
- return [{
8279
- children: [{
8280
- text: '',
8281
- type: 'text'
8282
- }],
8283
- type: 'text'
8284
- }];
8285
- };
8286
- const parseBlockTokens = tokens => {
8287
- if (tokens.length === 0) {
8288
- return getEmptyTextNode();
8289
- }
8290
- const nodes = [];
8291
- let paragraphLines = [];
8292
- let listItems = [];
8293
- let listType = '';
8294
- let orderedListPathStack = [];
8295
- let canContinueOrderedListItemParagraph = false;
8296
- const createListItem = (text, index) => {
8297
- return {
8298
- children: parseInlineNodes(text),
8299
- ...(index === undefined ? {} : {
8300
- index
8301
- }),
8302
- type: 'list-item'
8303
- };
8304
- };
8305
- const getListItemAtPath = (items, path) => {
8306
- let currentItems = items;
8307
- let currentItem;
8308
- for (const index of path) {
8309
- currentItem = currentItems[index];
8310
- if (!currentItem) {
8311
- return undefined;
8312
- }
8313
- currentItems = currentItem.nestedItems || [];
8314
- }
8315
- return currentItem;
8316
- };
8317
- const appendNestedItemAtPath = (items, path, item, nestedListType) => {
8318
- if (path.length === 0) {
8319
- return [...items, item];
8320
- }
8321
- const [index, ...rest] = path;
8322
- const current = items[index];
8323
- if (!current) {
8324
- return [...items];
8325
- }
8326
- const nextNestedItems = rest.length > 0 ? appendNestedItemAtPath(current.nestedItems || [], rest, item, nestedListType) : [...(current.nestedItems || []), item];
8327
- const nextItem = {
8328
- ...current,
8329
- nestedItems: nextNestedItems,
8330
- nestedListType
8331
- };
8332
- return [...items.slice(0, index), nextItem, ...items.slice(index + 1)];
8333
- };
8334
- const appendInlineChildrenAtPath = (items, path, children) => {
8335
- if (path.length === 0) {
8336
- return [...items];
8337
- }
8338
- const [index, ...rest] = path;
8339
- const current = items[index];
8340
- if (!current) {
8341
- return [...items];
8342
- }
8343
- const lineBreakNode = {
8344
- text: '\n',
8345
- type: 'text'
8346
- };
8347
- const nextChildren = [...current.children, lineBreakNode, ...children];
8348
- const nextItem = rest.length > 0 ? {
8349
- ...current,
8350
- nestedItems: appendInlineChildrenAtPath(current.nestedItems || [], rest, children)
8351
- } : {
8352
- ...current,
8353
- children: nextChildren
8354
- };
8355
- return [...items.slice(0, index), nextItem, ...items.slice(index + 1)];
8356
- };
8357
- const flushParagraph = () => {
8358
- if (paragraphLines.length === 0) {
8359
- return;
8360
- }
8361
- nodes.push({
8362
- children: parseInlineNodes(paragraphLines.join('\n')),
8363
- type: 'text'
8364
- });
8365
- paragraphLines = [];
8366
- };
8367
- const flushList = () => {
8368
- if (listItems.length === 0) {
8369
- return;
8370
- }
8371
- nodes.push({
8372
- items: listItems,
8373
- type: listType || 'ordered-list'
8374
- });
8375
- listItems = [];
8376
- listType = '';
8377
- orderedListPathStack = [];
8378
- canContinueOrderedListItemParagraph = false;
8379
- };
8380
- for (let i = 0; i < tokens.length; i++) {
8381
- const token = tokens[i];
8382
- if (token.type === 'blank-line') {
8383
- flushParagraph();
8384
- canContinueOrderedListItemParagraph = false;
8385
- continue;
8386
- }
8387
- if (token.type === 'code-block') {
8388
- flushList();
8389
- flushParagraph();
8390
- if (token.language) {
8391
- nodes.push({
8392
- codeTokens: highlightCode(token.text, token.language),
8393
- language: token.language,
8394
- text: token.text,
8395
- type: 'code-block'
8396
- });
8397
- } else {
8398
- nodes.push({
8399
- codeTokens: highlightCode(token.text, undefined),
8400
- text: token.text,
8401
- type: 'code-block'
8402
- });
8403
- }
8404
- continue;
8405
- }
8406
- if (token.type === 'math-block') {
8407
- flushList();
8408
- flushParagraph();
8409
- nodes.push({
8410
- text: token.text,
8411
- type: 'math-block'
8412
- });
8413
- continue;
8414
- }
8415
- if (token.type === 'thematic-break') {
8416
- flushList();
8417
- flushParagraph();
8418
- nodes.push({
8419
- type: 'thematic-break'
8420
- });
8421
- continue;
8422
- }
8423
- if (token.type === 'blockquote-line') {
8424
- flushList();
8425
- flushParagraph();
8426
- const lines = [];
8427
- while (i < tokens.length && tokens[i].type === 'blockquote-line') {
8428
- const quoteToken = tokens[i];
8429
- if (quoteToken.type === 'blockquote-line') {
8430
- lines.push(quoteToken.text);
8431
- }
8432
- i++;
8433
- }
8434
- i--;
8435
- nodes.push({
8436
- children: parseBlockTokens(scanBlockTokens(lines.join('\n'))),
8437
- type: 'blockquote'
8438
- });
8439
- continue;
8440
- }
8441
- if (token.type === 'table-row-line') {
8442
- const expectedColumns = token.cells.length;
8443
- if (isTableSeparatorToken(tokens[i + 1], expectedColumns)) {
8444
- flushList();
8445
- flushParagraph();
8446
- const rows = [];
8447
- i += 2;
8448
- while (i < tokens.length && tokens[i].type === 'table-row-line') {
8449
- const rowToken = tokens[i];
8450
- if (rowToken.type !== 'table-row-line') {
8451
- break;
8452
- }
8453
- if (rowToken.cells.length === expectedColumns) {
8454
- rows.push(toTableRow(rowToken));
8455
- }
8456
- i++;
8457
- }
8458
- i--;
8459
- nodes.push({
8460
- headers: token.cells.map(toTableCell),
8461
- rows,
8462
- type: 'table'
8463
- });
8464
- continue;
8465
- }
8466
- flushList();
8467
- paragraphLines.push(token.line);
8468
- continue;
8469
- }
8470
- if (token.type === 'ordered-list-item-line') {
8471
- if (listType === 'ordered-list' && listItems.length > 0 && token.indentation > 0 && orderedListPathStack.length > 0) {
8472
- const parentEntry = orderedListPathStack.toReversed().find(entry => entry.indentation < token.indentation);
8473
- if (parentEntry) {
8474
- const parentItem = getListItemAtPath(listItems, parentEntry.path);
8475
- if (parentItem) {
8476
- const nextIndex = parentItem.nestedItems?.length || 0;
8477
- const nextItem = createListItem(token.text, nextIndex + 1);
8478
- listItems = appendNestedItemAtPath(listItems, parentEntry.path, nextItem, 'ordered-list');
8479
- const nextPath = [...parentEntry.path, nextIndex];
8480
- orderedListPathStack = [...orderedListPathStack.filter(entry => entry.indentation < token.indentation), {
8481
- indentation: token.indentation,
8482
- path: nextPath
8483
- }];
8484
- canContinueOrderedListItemParagraph = true;
8485
- continue;
8486
- }
8487
- }
8488
- }
8489
- if (listType && listType !== 'ordered-list') {
8490
- flushList();
8491
- }
8492
- flushParagraph();
8493
- listType = 'ordered-list';
8494
- const nextIndex = listItems.length;
8495
- const nextItem = createListItem(token.text, nextIndex + 1);
8496
- listItems.push(nextItem);
8497
- orderedListPathStack = [...orderedListPathStack.filter(entry => entry.indentation < token.indentation), {
8498
- indentation: token.indentation,
8499
- path: [nextIndex]
8500
- }];
8501
- canContinueOrderedListItemParagraph = true;
8502
- continue;
8503
- }
8504
- if (token.type === 'unordered-list-item-line') {
8505
- if (listType === 'ordered-list' && listItems.length > 0 && token.indentation > 0 && orderedListPathStack.length > 0) {
8506
- const parentEntry = orderedListPathStack.toReversed().find(entry => entry.indentation < token.indentation);
8507
- if (parentEntry) {
8508
- const nextItem = createListItem(token.text);
8509
- listItems = appendNestedItemAtPath(listItems, parentEntry.path, nextItem, 'unordered-list');
8510
- canContinueOrderedListItemParagraph = false;
8511
- continue;
8512
- }
8513
- }
8514
- if (listType && listType !== 'unordered-list') {
8515
- flushList();
8516
- }
8517
- flushParagraph();
8518
- listType = 'unordered-list';
8519
- listItems.push(createListItem(token.text));
8520
- canContinueOrderedListItemParagraph = false;
8521
- continue;
8522
- }
8523
- if (token.type === 'heading-line') {
8524
- flushList();
8525
- flushParagraph();
8526
- nodes.push({
8527
- children: parseInlineNodes(token.text),
8528
- level: token.level,
8529
- type: 'heading'
8530
- });
8531
- continue;
8532
- }
8533
- if (token.type === 'paragraph-line' && listType === 'ordered-list' && listItems.length > 0 && canContinueOrderedListItemParagraph) {
8534
- const currentPath = orderedListPathStack.at(-1)?.path;
8535
- if (currentPath) {
8536
- listItems = appendInlineChildrenAtPath(listItems, currentPath, parseInlineNodes(token.text));
8537
- continue;
8538
- }
8539
- }
8540
- flushList();
8541
- paragraphLines.push(token.text);
8542
- canContinueOrderedListItemParagraph = false;
8543
- }
8544
- flushList();
8545
- flushParagraph();
8546
- return nodes.length === 0 ? getEmptyTextNode() : nodes;
8547
- };
8548
-
8549
- const parseMessageContent = async rawMessage => {
8550
- return parseBlockTokens(scanBlockTokens(rawMessage));
8551
- };
8552
-
8553
- const emptyMessageContent = [{
8554
- children: [{
8555
- text: '',
8556
- type: 'text'
8557
- }],
8558
- type: 'text'
8559
- }];
8560
- const parseMathInline = async children => {
8561
- const nextChildren = [];
8562
- for (const child of children) {
8563
- if (child.type === 'math-inline') {
8564
- const dom = await getMathInlineDom(child);
8565
- nextChildren.push({
8566
- dom,
8567
- type: 'math-inline-dom'
8568
- });
8569
- continue;
8570
- }
8571
- if (child.type === 'bold') {
8572
- nextChildren.push({
8573
- ...child,
8574
- children: await parseMathInline(child.children)
8575
- });
8576
- continue;
8577
- }
8578
- if (child.type === 'italic') {
8579
- nextChildren.push({
8580
- ...child,
8581
- children: await parseMathInline(child.children)
8582
- });
8583
- continue;
8584
- }
8585
- if (child.type === 'strikethrough') {
8586
- nextChildren.push({
8587
- ...child,
8588
- children: await parseMathInline(child.children)
8589
- });
8590
- continue;
8591
- }
8592
- nextChildren.push(child);
8593
- }
8594
- return nextChildren;
8595
- };
8596
- const parseMathListItem = async item => {
8597
- const children = await parseMathInline(item.children);
8598
- if (!item.nestedItems) {
8599
- return {
8600
- ...item,
8601
- children
8602
- };
8603
- }
8604
- const nestedItems = [];
8605
- for (const nestedItem of item.nestedItems) {
8606
- nestedItems.push(await parseMathListItem(nestedItem));
8607
- }
8608
- return {
8609
- ...item,
8610
- children,
8611
- nestedItems
8612
- };
8613
- };
8614
- const parseMathTableCell = async cell => {
8615
- return {
8616
- ...cell,
8617
- children: await parseMathInline(cell.children)
8618
- };
8619
- };
8620
- const parseMathNode = async node => {
8621
- if (node.type === 'math-block') {
8622
- const dom = await getMathBlockDom(node);
8623
- return {
8624
- dom,
8625
- type: 'math-block-dom'
8626
- };
8627
- }
8628
- if (node.type === 'text' || node.type === 'heading') {
8629
- return {
8630
- ...node,
8631
- children: await parseMathInline(node.children)
8632
- };
8633
- }
8634
- if (node.type === 'blockquote') {
8635
- const children = [];
8636
- for (const child of node.children) {
8637
- children.push(await parseMathNode(child));
8638
- }
8639
- return {
8640
- ...node,
8641
- children
8642
- };
8643
- }
8644
- if (node.type === 'ordered-list' || node.type === 'unordered-list') {
8645
- const items = [];
8646
- for (const item of node.items) {
8647
- items.push(await parseMathListItem(item));
8648
- }
8649
- return {
8650
- ...node,
8651
- items
8652
- };
8653
- }
8654
- if (node.type === 'table') {
8655
- const headers = [];
8656
- for (const header of node.headers) {
8657
- headers.push(await parseMathTableCell(header));
8658
- }
8659
- const rows = [];
8660
- for (const row of node.rows) {
8661
- const cells = [];
8662
- for (const cell of row.cells) {
8663
- cells.push(await parseMathTableCell(cell));
7204
+ } else if (openRouterApiKey) {
7205
+ const result = await getOpenRouterAssistantText(messages, modelId, openRouterApiKey, openRouterApiBaseUrl, assetDir, platform, useChatNetworkWorkerForRequests, useChatToolWorker, questionToolEnabled, systemPrompt, workspaceUri, agentMode, toolEnablement);
7206
+ if (result.type === 'success') {
7207
+ const {
7208
+ text: assistantText
7209
+ } = result;
7210
+ text = assistantText;
7211
+ } else {
7212
+ text = getOpenRouterErrorMessage(result);
8664
7213
  }
8665
- rows.push({
8666
- ...row,
8667
- cells
8668
- });
7214
+ } else {
7215
+ text = openRouterApiKeyRequiredMessage;
8669
7216
  }
8670
- return {
8671
- ...node,
8672
- headers,
8673
- rows
8674
- };
8675
7217
  }
8676
- return node;
8677
- };
8678
- const parseMessage = async rawMessage => {
8679
- const parsedContent = await parseMessageContent(rawMessage);
8680
- const nextParsedContent = [];
8681
- for (const node of parsedContent) {
8682
- nextParsedContent.push(await parseMathNode(node));
7218
+ if (!text && !usesOpenApiModel && !usesOpenRouterModel) {
7219
+ text = await getMockAiResponse(userText, mockAiResponseDelay);
8683
7220
  }
8684
- return nextParsedContent;
7221
+ const assistantTime = new Date().toLocaleTimeString([], {
7222
+ hour: '2-digit',
7223
+ minute: '2-digit'
7224
+ });
7225
+ const message = {
7226
+ id: messageId || crypto.randomUUID(),
7227
+ role: 'assistant',
7228
+ text,
7229
+ time: assistantTime
7230
+ };
7231
+ return message;
7232
+ };
7233
+
7234
+ const parseMessageContents = async rawMessages => {
7235
+ return invoke$7('ChatMessageParsing.parseMessageContents', rawMessages);
8685
7236
  };
7237
+
7238
+ const emptyMessageContent = [{
7239
+ children: [{
7240
+ text: '',
7241
+ type: 'text'
7242
+ }],
7243
+ type: 'text'
7244
+ }];
8686
7245
  const getParsedMessageContent = (parsedMessages, messageId) => {
8687
7246
  const parsedMessage = parsedMessages.find(item => item.id === messageId);
8688
7247
  return parsedMessage?.parsedContent;
@@ -8714,26 +7273,10 @@ const copyParsedMessageContent = (parsedMessages, sourceMessageId, targetMessage
8714
7273
  return setParsedMessageContent(parsedMessages, targetMessageId, parsedMessage.text, parsedMessage.parsedContent);
8715
7274
  };
8716
7275
  const parseAndStoreMessageContent = async (parsedMessages, message) => {
8717
- const existingParsedMessage = parsedMessages.find(item => item.id === message.id);
8718
- if (existingParsedMessage && existingParsedMessage.text === message.text) {
8719
- return parsedMessages;
8720
- }
8721
- await Promise.resolve();
8722
- const parsedContent = message.text === '' ? emptyMessageContent : await parseMessage(message.text);
8723
- return setParsedMessageContent(parsedMessages, message.id, message.text, parsedContent);
8724
- };
8725
- const parseAndStoreMessageContentWithWorkerPreference = async (parsedMessages, message, useChatMessageParsingWorker) => {
8726
- if (useChatMessageParsingWorker) {
8727
- return parseAndStoreMessagesContentInWorker(parsedMessages, [message]);
8728
- }
8729
- return parseAndStoreMessageContent(parsedMessages, message);
7276
+ return parseAndStoreMessagesContentInWorker(parsedMessages, [message]);
8730
7277
  };
8731
7278
  const parseAndStoreMessagesContent = async (parsedMessages, messages) => {
8732
- let nextParsedMessages = parsedMessages;
8733
- for (const message of messages) {
8734
- nextParsedMessages = await parseAndStoreMessageContent(nextParsedMessages, message);
8735
- }
8736
- return nextParsedMessages;
7279
+ return parseAndStoreMessagesContentInWorker(parsedMessages, messages);
8737
7280
  };
8738
7281
  const getMessagesNeedingParsing = (parsedMessages, messages) => {
8739
7282
  return messages.filter(message => {
@@ -8754,12 +7297,6 @@ const parseAndStoreMessagesContentInWorker = async (parsedMessages, messages) =>
8754
7297
  }
8755
7298
  return nextParsedMessages;
8756
7299
  };
8757
- const parseAndStoreMessagesContentWithWorkerPreference = async (parsedMessages, messages, useChatMessageParsingWorker) => {
8758
- if (useChatMessageParsingWorker) {
8759
- return parseAndStoreMessagesContentInWorker(parsedMessages, messages);
8760
- }
8761
- return parseAndStoreMessagesContent(parsedMessages, messages);
8762
- };
8763
7300
  const getEmptyMessageContent = () => {
8764
7301
  return emptyMessageContent;
8765
7302
  };
@@ -9271,7 +7808,7 @@ const handleToolCallsChunkFunction = async (uid, assistantMessageId, toolCalls,
9271
7808
  };
9272
7809
  };
9273
7810
 
9274
- const updateMessageTextInSelectedSession = async (sessions, parsedMessages, selectedSessionId, messageId, text, inProgress, useChatMessageParsingWorker) => {
7811
+ const updateMessageTextInSelectedSession = async (sessions, parsedMessages, selectedSessionId, messageId, text, inProgress) => {
9275
7812
  let updatedMessage;
9276
7813
  const updatedSessions = sessions.map(session => {
9277
7814
  if (session.id !== selectedSessionId) {
@@ -9294,7 +7831,7 @@ const updateMessageTextInSelectedSession = async (sessions, parsedMessages, sele
9294
7831
  });
9295
7832
  let nextParsedMessages = parsedMessages;
9296
7833
  if (updatedMessage) {
9297
- nextParsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, updatedMessage, useChatMessageParsingWorker);
7834
+ nextParsedMessages = await parseAndStoreMessageContent(parsedMessages, updatedMessage);
9298
7835
  }
9299
7836
  return {
9300
7837
  parsedMessages: nextParsedMessages,
@@ -9317,7 +7854,7 @@ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTex
9317
7854
  };
9318
7855
  }
9319
7856
  const updatedText = assistantMessage.text + chunk;
9320
- const updated = await updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.parsedMessages, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true, handleTextChunkState.latestState.useChatMessageParsingWorker);
7857
+ const updated = await updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.parsedMessages, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
9321
7858
  const nextState = {
9322
7859
  ...handleTextChunkState.latestState,
9323
7860
  ...(handleTextChunkState.latestState.messagesAutoScrollEnabled ? {
@@ -9516,7 +8053,6 @@ const handleSubmit = async state => {
9516
8053
  streamingEnabled,
9517
8054
  toolEnablement,
9518
8055
  useChatCoordinatorWorker,
9519
- useChatMessageParsingWorker,
9520
8056
  useChatNetworkWorkerForRequests,
9521
8057
  useChatToolWorker,
9522
8058
  useMockApi,
@@ -9562,8 +8098,8 @@ const handleSubmit = async state => {
9562
8098
  let {
9563
8099
  parsedMessages
9564
8100
  } = effectiveState;
9565
- parsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, userMessage, useChatMessageParsingWorker);
9566
- parsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, inProgressAssistantMessage, useChatMessageParsingWorker);
8101
+ parsedMessages = await parseAndStoreMessageContent(parsedMessages, userMessage);
8102
+ parsedMessages = await parseAndStoreMessageContent(parsedMessages, inProgressAssistantMessage);
9567
8103
  let workingSessions = sessions;
9568
8104
  if (viewMode === 'detail') {
9569
8105
  const loadedSession = await getChatSession(selectedSessionId);
@@ -9738,11 +8274,11 @@ const handleSubmit = async state => {
9738
8274
  let finalParsedMessages = latestState.parsedMessages;
9739
8275
  let updatedSessions;
9740
8276
  if (streamingEnabled) {
9741
- const updated = await updateMessageTextInSelectedSession(latestState.sessions, finalParsedMessages, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false, latestState.useChatMessageParsingWorker);
8277
+ const updated = await updateMessageTextInSelectedSession(latestState.sessions, finalParsedMessages, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false);
9742
8278
  updatedSessions = updated.sessions;
9743
8279
  finalParsedMessages = updated.parsedMessages;
9744
8280
  } else {
9745
- finalParsedMessages = await parseAndStoreMessageContentWithWorkerPreference(finalParsedMessages, assistantMessage, latestState.useChatMessageParsingWorker);
8281
+ finalParsedMessages = await parseAndStoreMessageContent(finalParsedMessages, assistantMessage);
9746
8282
  updatedSessions = appendMessageToSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessage);
9747
8283
  }
9748
8284
  if (aiSessionTitleGenerationEnabled && createsNewSession) {
@@ -11388,15 +9924,6 @@ const loadUseChatMathWorker = async () => {
11388
9924
  }
11389
9925
  };
11390
9926
 
11391
- const loadUseChatMessageParsingWorker = async () => {
11392
- try {
11393
- const savedUseChatMessageParsingWorker = await get('chatView.useChatMessageParsingWorker');
11394
- return typeof savedUseChatMessageParsingWorker === 'boolean' ? savedUseChatMessageParsingWorker : false;
11395
- } catch {
11396
- return false;
11397
- }
11398
- };
11399
-
11400
9927
  const loadUseChatNetworkWorkerForRequests = async () => {
11401
9928
  try {
11402
9929
  const savedUseChatNetworkWorkerForRequests = await get('chatView.useChatNetworkWorkerForRequests');
@@ -11425,7 +9952,7 @@ const loadVoiceDictationEnabled = async () => {
11425
9952
  };
11426
9953
 
11427
9954
  const loadPreferences = async () => {
11428
- const [aiSessionTitleGenerationEnabled, authEnabled, backendUrl, chatHistoryEnabled, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, reasoningPickerEnabled, scrollDownButtonEnabled, searchEnabled, streamingEnabled, todoListToolEnabled, toolEnablement, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatMessageParsingWorker, useChatNetworkWorkerForRequests, useChatToolWorker, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadAuthEnabled(), loadBackendUrl(), loadChatHistoryEnabled(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadReasoningPickerEnabled(), loadScrollDownButtonEnabled(), loadSearchEnabled(), loadStreamingEnabled(), loadTodoListToolEnabled(), loadToolEnablement(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatMessageParsingWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadVoiceDictationEnabled()]);
9955
+ 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()]);
11429
9956
  return {
11430
9957
  aiSessionTitleGenerationEnabled,
11431
9958
  authEnabled,
@@ -11444,7 +9971,6 @@ const loadPreferences = async () => {
11444
9971
  toolEnablement,
11445
9972
  useChatCoordinatorWorker,
11446
9973
  useChatMathWorker,
11447
- useChatMessageParsingWorker,
11448
9974
  useChatNetworkWorkerForRequests,
11449
9975
  useChatToolWorker,
11450
9976
  voiceDictationEnabled
@@ -11516,12 +10042,10 @@ const loadContent = async (state, savedState) => {
11516
10042
  toolEnablement,
11517
10043
  useChatCoordinatorWorker,
11518
10044
  useChatMathWorker,
11519
- // useChatMessageParsingWorker,
11520
10045
  useChatNetworkWorkerForRequests,
11521
10046
  useChatToolWorker,
11522
10047
  voiceDictationEnabled
11523
10048
  } = await loadPreferences();
11524
- const useChatMessageParsingWorker = true;
11525
10049
  const authState = authEnabled && backendUrl ? await syncBackendAuth(backendUrl) : getLoggedOutBackendAuthState();
11526
10050
  const legacySavedSessions = getSavedSessions(savedState);
11527
10051
  const storedSessions = await listChatSessions();
@@ -11567,7 +10091,7 @@ const loadContent = async (state, savedState) => {
11567
10091
  parsedMessages
11568
10092
  } = state;
11569
10093
  for (const session of sessions) {
11570
- parsedMessages = await parseAndStoreMessagesContentWithWorkerPreference(parsedMessages, session.messages, useChatMessageParsingWorker);
10094
+ parsedMessages = await parseAndStoreMessagesContent(parsedMessages, session.messages);
11571
10095
  }
11572
10096
  const preferredViewMode = savedViewMode || state.viewMode;
11573
10097
  const savedLastNormalViewMode = getSavedLastNormalViewMode(savedState);
@@ -11625,7 +10149,6 @@ const loadContent = async (state, savedState) => {
11625
10149
  toolEnablement,
11626
10150
  useChatCoordinatorWorker,
11627
10151
  useChatMathWorker,
11628
- useChatMessageParsingWorker,
11629
10152
  useChatNetworkWorkerForRequests,
11630
10153
  useChatToolWorker,
11631
10154
  userName: authState.userName,
@@ -11750,7 +10273,7 @@ const openMockSession = async (state, mockSessionId, mockChatMessages, options)
11750
10273
  if (!mockSessionId) {
11751
10274
  return state;
11752
10275
  }
11753
- const parsedMessages = await parseAndStoreMessagesContentWithWorkerPreference(state.parsedMessages, mockChatMessages, state.useChatMessageParsingWorker);
10276
+ const parsedMessages = await parseAndStoreMessagesContent(state.parsedMessages, mockChatMessages);
11754
10277
  const existingSession = currentSessions.find(session => session.id === mockSessionId);
11755
10278
  const sessions = existingSession ? currentSessions.map(session => {
11756
10279
  if (session.id !== mockSessionId) {
@@ -12003,12 +10526,16 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
12003
10526
  color: var(--vscode-errorForeground, var(--vscode-foreground));
12004
10527
  }
12005
10528
 
12006
- .CustomSelectContainer{
10529
+ .ChatSelect{
12007
10530
  position: relative;
12008
10531
  min-width: 0;
12009
10532
 
12010
10533
  }
12011
10534
 
10535
+ .ChatModelPickerItem{
10536
+ display: flex;
10537
+ }
10538
+
12012
10539
  .ChatGitBranchPickerMessage{
12013
10540
  padding: 6px 8px;
12014
10541
  }
@@ -12136,6 +10663,11 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
12136
10663
  flex: 1;
12137
10664
  min-height: 0;
12138
10665
  }
10666
+
10667
+ .ChatModelPickerList {
10668
+ display: flex;
10669
+ contain: content;
10670
+ }
12139
10671
  `;
12140
10672
  return `${baseCss}
12141
10673
 
@@ -12228,6 +10760,160 @@ const renderFocusContext = (oldState, newState) => {
12228
10760
  return [SetFocusContext, newState.uid, FocusChatInput];
12229
10761
  };
12230
10762
 
10763
+ const Actions = 'Actions';
10764
+ const Button = 'Button';
10765
+ const ButtonPrimary = 'ButtonPrimary';
10766
+ const ButtonSecondary = 'ButtonSecondary';
10767
+ const Chat = 'Chat';
10768
+ const ChatActions = 'ChatActions';
10769
+ const ChatAuthError = 'ChatAuthError';
10770
+ const ChatFocus = 'ChatFocus';
10771
+ const ChatFocusActions = 'ChatFocusActions';
10772
+ const ChatFocusHeader = 'ChatFocusHeader';
10773
+ const ChatFocusMainArea = 'ChatFocusMainArea';
10774
+ const ChatFocusProject = 'ChatFocusProject';
10775
+ const ChatGitBranchPicker = 'ChatGitBranchPicker';
10776
+ const ChatGitBranchPickerErrorMessage = 'ChatGitBranchPickerErrorMessage';
10777
+ const ChatGitBranchPickerMessage = 'ChatGitBranchPickerMessage';
10778
+ const ChatHeader = 'ChatHeader';
10779
+ const ChatHeaderAuth = 'ChatHeaderAuth';
10780
+ const ChatHeaderAuthName = 'ChatHeaderAuthName';
10781
+ const ChatHeaderLabel = 'ChatHeaderLabel';
10782
+ const ChatInputBox = 'ChatInputBox';
10783
+ const ChatList = 'ChatList';
10784
+ const ChatListEmpty = 'ChatListEmpty';
10785
+ const ChatListItem = 'ChatListItem';
10786
+ const ChatListItemFocused = 'ChatListItemFocused';
10787
+ const ChatListItemLabel = 'ChatListItemLabel';
10788
+ const ChatListItemStatusFinished = 'ChatListItemStatusFinished';
10789
+ const ChatListItemStatusIcon = 'ChatListItemStatusIcon';
10790
+ const ChatListItemStatusInProgress = 'ChatListItemStatusInProgress';
10791
+ const ChatListItemStatusRow = 'ChatListItemStatusRow';
10792
+ const ChatListItemStatusStopped = 'ChatListItemStatusStopped';
10793
+ const ChatMessageContent = 'ChatMessageContent';
10794
+ const ChatImageMessageContent = 'ChatImageMessageContent';
10795
+ const ChatMessageLink = 'ChatMessageLink';
10796
+ const ChatModelPicker = 'ChatModelPicker';
10797
+ const ChatModelPickerContainer = 'ChatModelPickerContainer';
10798
+ const ChatModelPickerHeader = 'ChatModelPickerHeader';
10799
+ const ChatModelPickerItem = 'ChatModelPickerItem';
10800
+ const ChatModelPickerItemLabel = 'ChatModelPickerItemLabel';
10801
+ const ChatModelPickerItemSelected = 'ChatModelPickerItemSelected';
10802
+ const ChatModelPickerItemUsageCost = 'ChatModelPickerItemUsageCost';
10803
+ const ChatModelPickerList = 'ChatModelPickerList';
10804
+ const ChatName = 'ChatName';
10805
+ const ChatOverlays = 'ChatOverlays';
10806
+ const ChatOrderedList = 'ChatOrderedList';
10807
+ const ChatOrderedListItem = 'ChatOrderedListItem';
10808
+ const ChatOrderedListItemContent = 'ChatOrderedListItemContent';
10809
+ const ChatOrderedListItemPrefix = 'ChatOrderedListItemPrefix';
10810
+ const ChatOrderedListMarker = 'ChatOrderedListMarker';
10811
+ const ChatComposerAttachment = 'ChatComposerAttachment';
10812
+ const ChatComposerAttachmentImage = 'ChatComposerAttachmentImage';
10813
+ const ChatComposerAttachmentInvalidImage = 'ChatComposerAttachmentInvalidImage';
10814
+ const ChatComposerAttachmentLabel = 'ChatComposerAttachmentLabel';
10815
+ const ChatComposerAttachmentPreview = 'ChatComposerAttachmentPreview';
10816
+ const ChatComposerAttachmentPreviewOverlay = 'ChatComposerAttachmentPreviewOverlay';
10817
+ const ChatComposerAttachmentPreviewOverlayError = 'ChatComposerAttachmentPreviewOverlayError';
10818
+ const ChatComposerAttachmentPreviewOverlayImage = 'ChatComposerAttachmentPreviewOverlayImage';
10819
+ const ChatComposerAttachmentRemoveButton = 'ChatComposerAttachmentRemoveButton';
10820
+ const ChatComposerAttachments = 'ChatComposerAttachments';
10821
+ const ChatComposerAttachmentTextFile = 'ChatComposerAttachmentTextFile';
10822
+ const ChatAttachment = 'ChatAttachment';
10823
+ const ChatAttachmentImage = 'ChatAttachmentImage';
10824
+ const ChatAttachmentInvalidImage = 'ChatAttachmentInvalidImage';
10825
+ const ChatAttachmentLabel = 'ChatAttachmentLabel';
10826
+ const ChatAttachmentPreview = 'ChatAttachmentPreview';
10827
+ const ChatAttachments = 'ChatAttachments';
10828
+ const ChatAttachmentTextFile = 'ChatAttachmentTextFile';
10829
+ const ChatMessageImage = 'ChatMessageImage';
10830
+ const ChatSendArea = 'ChatSendArea';
10831
+ const ChatSendAreaBottom = 'ChatSendAreaBottom';
10832
+ const ChatSendAreaContent = 'ChatSendAreaContent';
10833
+ const ChatSendAreaPrimaryControls = 'ChatSendAreaPrimaryControls';
10834
+ const ChatSelect = 'ChatSelect';
10835
+ const ChatTableWrapper = 'ChatTableWrapper';
10836
+ const ChatTodoList = 'ChatTodoList';
10837
+ const ChatTodoListHeader = 'ChatTodoListHeader';
10838
+ const ChatTodoListItem = 'ChatTodoListItem';
10839
+ const ChatTodoListItemCompleted = 'ChatTodoListItemCompleted';
10840
+ const ChatTodoListItemInProgress = 'ChatTodoListItemInProgress';
10841
+ const ChatTodoListItems = 'ChatTodoListItems';
10842
+ const ChatTodoListItemTodo = 'ChatTodoListItemTodo';
10843
+ const ChatToolCallFileName = 'ChatToolCallFileName';
10844
+ const ChatToolCallQuestionOption = 'ChatToolCallQuestionOption';
10845
+ const ChatToolCallQuestionOptions = 'ChatToolCallQuestionOptions';
10846
+ const ChatToolCallQuestionText = 'ChatToolCallQuestionText';
10847
+ const ChatToolCallReadFileLink = 'ChatToolCallReadFileLink';
10848
+ const ChatToolCallRenderHtmlBody = 'ChatToolCallRenderHtmlBody';
10849
+ const ChatToolCallRenderHtmlContent = 'ChatToolCallRenderHtmlContent';
10850
+ const ChatToolCallRenderHtmlLabel = 'ChatToolCallRenderHtmlLabel';
10851
+ const ChatToolCalls = 'ChatToolCalls';
10852
+ const ChatToolCallsLabel = 'ChatToolCallsLabel';
10853
+ const ChatUnorderedList = 'ChatUnorderedList';
10854
+ const ChatUnorderedListItem = 'ChatUnorderedListItem';
10855
+ const ChatViewDropOverlay = 'ChatViewDropOverlay';
10856
+ const ChatViewDropOverlayActive = 'ChatViewDropOverlayActive';
10857
+ const ChatWelcomeMessage = 'ChatWelcomeMessage';
10858
+ const CustomSelectPopOver = 'CustomSelectPopOver';
10859
+ const Deletion = 'Deletion';
10860
+ const Empty = '';
10861
+ const FileIcon = 'FileIcon';
10862
+ const IconButton = 'IconButton';
10863
+ const IconButtonDisabled = 'IconButtonDisabled';
10864
+ const ImageElement = 'ImageElement';
10865
+ const ImageErrorMessage = 'ImageErrorMessage';
10866
+ const InputBox = 'InputBox';
10867
+ const InputInvalid = 'InputInvalid';
10868
+ const Insertion = 'Insertion';
10869
+ const Label = 'Label';
10870
+ const LabelDetail = 'LabelDetail';
10871
+ const Markdown = 'Markdown';
10872
+ const MarkdownMathBlock = 'MarkdownMathBlock';
10873
+ const MarkdownQuote = 'MarkdownQuote';
10874
+ const MarkdownTable = 'MarkdownTable';
10875
+ const MaskIcon = 'MaskIcon';
10876
+ const MaskIconAdd = 'MaskIconAdd';
10877
+ const MaskIconArrowLeft = 'MaskIconArrowLeft';
10878
+ const MaskIconChevronDown = 'MaskIconChevronDown';
10879
+ const MaskIconChevronRight = 'MaskIconChevronRight';
10880
+ const MaskIconChevronUp = 'MaskIconChevronUp';
10881
+ const MaskIconClose = 'MaskIconClose';
10882
+ const MaskIconDebugPause = 'MaskIconDebugPause';
10883
+ const MaskIconLayoutPanelLeft = 'MaskIconLayoutPanelLeft';
10884
+ const MaskIconSearch = 'MaskIconSearch';
10885
+ const MaskIconSettingsGear = 'MaskIconSettingsGear';
10886
+ const Message = 'Message';
10887
+ const MessageAssistant = 'MessageAssistant';
10888
+ const MessageUser = 'MessageUser';
10889
+ const MissingApiKeyForm = 'MissingApiKeyForm';
10890
+ const MultiLineInputBox = 'MultilineInputBox';
10891
+ const ProjectAddButton = 'ProjectAddButton';
10892
+ const ProjectList = 'ProjectList';
10893
+ const ProjectListChevron = 'ProjectListChevron';
10894
+ const ProjectListGroup = 'ProjectListGroup';
10895
+ const ProjectListItem = 'ProjectListItem';
10896
+ const ProjectListItemActions = 'ProjectListItemActions';
10897
+ const ProjectListItemAddChatButton = 'ProjectListItemAddChatButton';
10898
+ const ProjectListItemLabel = 'ProjectListItemLabel';
10899
+ const ProjectListItemSelected = 'ProjectListItemSelected';
10900
+ const ProjectSessionItem = 'ProjectSessionItem';
10901
+ const ProjectSessionItemLabel = 'ProjectSessionItemLabel';
10902
+ const ProjectSessionItemSelected = 'ProjectSessionItemSelected';
10903
+ const ProjectSidebar = 'ProjectSidebar';
10904
+ const SearchFieldContainer = 'SearchFieldContainer';
10905
+ const RunModePickerContainer = 'RunModePickerContainer';
10906
+ const RunModePickerPopOver = 'RunModePickerPopOver';
10907
+ const SelectLabel = 'SelectLabel';
10908
+ const SendButtonDisabled = 'SendButtonDisabled';
10909
+ const SessionArchiveButton = 'SessionArchiveButton';
10910
+ const StrikeThrough = 'StrikeThrough';
10911
+ const TokenUsageOverview = 'TokenUsageOverview';
10912
+ const TokenUsageRing = 'TokenUsageRing';
10913
+ const TokenUsageRingInner = 'TokenUsageRingInner';
10914
+ const ToolCallName = 'ToolCallName';
10915
+ const Viewlet = 'Viewlet';
10916
+
12231
10917
  const HandleListContextMenu = 2;
12232
10918
  const HandleFocus = 3;
12233
10919
  const HandleInput = 4;
@@ -12297,13 +10983,22 @@ const getAddContextButtonDom = () => {
12297
10983
  };
12298
10984
 
12299
10985
  const getCustomSelectToggleVirtualDom = (label, name, open, onClick, title = label, ariaLabel = title) => {
10986
+ const getChevronDom = expanded => {
10987
+ return {
10988
+ childCount: 0,
10989
+ className: mergeClassNames(MaskIcon, expanded ? MaskIconChevronUp : MaskIconChevronDown),
10990
+ name,
10991
+ role: None$1,
10992
+ type: Div
10993
+ };
10994
+ };
12300
10995
  return [{
12301
10996
  'aria-expanded': open ? 'true' : 'false',
12302
10997
  'aria-haspopup': 'true',
12303
10998
  'aria-label': ariaLabel,
12304
10999
  ariaLabel,
12305
11000
  childCount: 2,
12306
- className: Select,
11001
+ className: ChatSelect,
12307
11002
  inputType: 'button',
12308
11003
  name,
12309
11004
  onClick,
@@ -12315,21 +11010,11 @@ const getCustomSelectToggleVirtualDom = (label, name, open, onClick, title = lab
12315
11010
  name,
12316
11011
  role: None$1,
12317
11012
  type: Span
12318
- }, text(label), {
12319
- childCount: 0,
12320
- className: mergeClassNames(MaskIcon, open ? MaskIconChevronUp : MaskIconChevronDown),
12321
- name,
12322
- role: None$1,
12323
- type: Div
12324
- }];
11013
+ }, text(label), getChevronDom(open)];
12325
11014
  };
12326
11015
 
12327
- const getCustomSelectPickerToggleVirtualDom = (label, name, open, onClick, title = label, ariaLabel = title, containerChildCount = 1) => {
12328
- return [{
12329
- childCount: containerChildCount,
12330
- className: CustomSelectContainer,
12331
- type: Div
12332
- }, ...getCustomSelectToggleVirtualDom(label, name, open, onClick, title, ariaLabel)];
11016
+ const getCustomSelectPickerToggleVirtualDom = (label, name, open, onClick, title = label, ariaLabel = title) => {
11017
+ return getCustomSelectToggleVirtualDom(label, name, open, onClick, title, ariaLabel);
12333
11018
  };
12334
11019
 
12335
11020
  const getAgentModePickerVirtualDom = (selectedAgentMode, agentModePickerOpen) => {
@@ -12421,7 +11106,7 @@ const getGitBranchPickerVirtualDom = (gitBranches, gitBranchPickerOpen, gitBranc
12421
11106
  const messageDom = getBranchPickerMessageDom(gitBranches, gitBranchPickerErrorMessage);
12422
11107
  const showMessage = messageDom.length > 0;
12423
11108
  const popOverHeight = gitBranches.length * itemHeight + (showMessage ? messageHeight : 0);
12424
- return [...getCustomSelectPickerToggleVirtualDom(label, GitBranchPickerToggle, gitBranchPickerOpen, HandleClickGitBranchPickerToggle, 'Switch branch', 'Switch branch', gitBranchPickerOpen ? 2 : 1), ...(gitBranchPickerOpen ? [{
11109
+ return [...getCustomSelectPickerToggleVirtualDom(label, GitBranchPickerToggle, gitBranchPickerOpen, HandleClickGitBranchPickerToggle, 'Switch branch', 'Switch branch'), ...(gitBranchPickerOpen ? [{
12425
11110
  childCount: (showMessage ? 1 : 0) + 1,
12426
11111
  className: mergeClassNames(ChatModelPicker, CustomSelectPopOver, ChatGitBranchPicker),
12427
11112
  style: `height: ${popOverHeight}px;`,
@@ -12442,7 +11127,7 @@ const getReasoningEffortOptionsVirtualDom = selectedReasoningEffort => {
12442
11127
  });
12443
11128
  };
12444
11129
  const getReasoningEffortPickerVirtualDom = (selectedReasoningEffort, reasoningEffortPickerOpen) => {
12445
- return [...getCustomSelectPickerToggleVirtualDom(getReasoningEffortLabel(selectedReasoningEffort), ReasoningEffortPickerToggle, reasoningEffortPickerOpen, HandleClickReasoningEffortPickerToggle, 'Reasoning', 'Reasoning', reasoningEffortPickerOpen ? 2 : 1), ...(reasoningEffortPickerOpen ? [{
11130
+ return [...getCustomSelectPickerToggleVirtualDom(getReasoningEffortLabel(selectedReasoningEffort), ReasoningEffortPickerToggle, reasoningEffortPickerOpen, HandleClickReasoningEffortPickerToggle, 'Reasoning', 'Reasoning'), ...(reasoningEffortPickerOpen ? [{
12446
11131
  childCount: 1,
12447
11132
  className: mergeClassNames(ChatModelPicker, CustomSelectPopOver),
12448
11133
  style: `height: ${reasoningEffortPickerHeight}px;`,
@@ -12853,7 +11538,23 @@ const getUsageCostLabel = model => {
12853
11538
  };
12854
11539
 
12855
11540
  const getChatModelListItemVirtualDom = (model, selectedModelId) => {
12856
- return getCustomSelectOptionVirtualDom(getModelPickerItemInputName(model.id), getModelLabel(model), model.id === selectedModelId, getUsageCostLabel(model));
11541
+ const detail = getUsageCostLabel(model);
11542
+ const hasDetail = detail !== '';
11543
+ const className = mergeClassNames(ChatModelPickerItem, model.id === selectedModelId ? ChatModelPickerItemSelected : '');
11544
+ return [{
11545
+ childCount: hasDetail ? 2 : 1,
11546
+ className,
11547
+ 'data-id': model.id,
11548
+ type: Li
11549
+ }, {
11550
+ childCount: 1,
11551
+ className: ChatModelPickerItemLabel,
11552
+ type: Span
11553
+ }, text(getModelLabel(model)), ...(hasDetail ? [{
11554
+ childCount: 1,
11555
+ className: ChatModelPickerItemUsageCost,
11556
+ type: Span
11557
+ }, text(detail)] : [])];
12857
11558
  };
12858
11559
 
12859
11560
  const parentNode$2 = {
@@ -13116,19 +11817,7 @@ const getBlockQuoteDom = (node, useChatMathWorker, getMessageNodeDom) => {
13116
11817
  }, ...node.children.flatMap(child => getMessageNodeDom(child, useChatMathWorker))];
13117
11818
  };
13118
11819
 
13119
- const getTokenDom = token => {
13120
- if (!token.className) {
13121
- return [text(token.text)];
13122
- }
13123
- return [{
13124
- childCount: 1,
13125
- className: token.className,
13126
- type: Span
13127
- }, text(token.text)];
13128
- };
13129
-
13130
11820
  const getCodeBlockDom = node => {
13131
- const tokenDom = node.codeTokens.flatMap(getTokenDom);
13132
11821
  const languageAttribute = node.language ? {
13133
11822
  'data-lang': node.language
13134
11823
  } : {};
@@ -13137,10 +11826,10 @@ const getCodeBlockDom = node => {
13137
11826
  type: Pre,
13138
11827
  ...languageAttribute
13139
11828
  }, {
13140
- childCount: node.codeTokens.length,
11829
+ childCount: 1,
13141
11830
  type: Code,
13142
11831
  ...languageAttribute
13143
- }, ...tokenDom];
11832
+ }, text(node.text)];
13144
11833
  };
13145
11834
 
13146
11835
  const getHeadingElementType = level => {
@@ -14050,7 +12739,7 @@ const getElementType = tagName => {
14050
12739
  case 'section':
14051
12740
  return Section;
14052
12741
  case 'select':
14053
- return Select$1;
12742
+ return Select;
14054
12743
  case 'span':
14055
12744
  return Span;
14056
12745
  case 'strong':
@@ -15048,7 +13737,7 @@ const getSessionDom = (session, focused = false) => {
15048
13737
  type: Div
15049
13738
  }, {
15050
13739
  childCount: 0,
15051
- className: `${ChatListItemStatusIcon} codicon codicon-circle-filled ${sessionStatusClassName}`,
13740
+ className: `${ChatListItemStatusIcon} ${sessionStatusClassName}`,
15052
13741
  type: Div
15053
13742
  }, {
15054
13743
  childCount: 1,
@@ -16195,18 +14884,6 @@ const setUseChatMathWorker = async (state, useChatMathWorker, persist = true) =>
16195
14884
  };
16196
14885
  };
16197
14886
 
16198
- const setUseChatMessageParsingWorker = async (state, useChatMessageParsingWorker, persist = true) => {
16199
- if (persist) {
16200
- await update({
16201
- 'chatView.useChatMessageParsingWorker': useChatMessageParsingWorker
16202
- });
16203
- }
16204
- return {
16205
- ...state,
16206
- useChatMessageParsingWorker
16207
- };
16208
- };
16209
-
16210
14887
  const setUseChatNetworkWorkerForRequests = async (state, useChatNetworkWorkerForRequests, persist = true) => {
16211
14888
  if (persist) {
16212
14889
  await update({
@@ -16358,7 +15035,6 @@ const commandMap = {
16358
15035
  'Chat.setToolEnablement': wrapCommand(setToolEnablement),
16359
15036
  'Chat.setUseChatCoordinatorWorker': wrapCommand(setUseChatCoordinatorWorker),
16360
15037
  'Chat.setUseChatMathWorker': wrapCommand(setUseChatMathWorker),
16361
- 'Chat.setUseChatMessageParsingWorker': wrapCommand(setUseChatMessageParsingWorker),
16362
15038
  'Chat.setUseChatNetworkWorkerForRequests': wrapCommand(setUseChatNetworkWorkerForRequests),
16363
15039
  'Chat.showComposerAttachmentPreviewOverlay': wrapCommand(showComposerAttachmentPreviewOverlay),
16364
15040
  'Chat.terminate': terminate,