@lvce-editor/chat-view 6.10.0 → 6.12.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.
- package/dist/chatViewWorkerMain.js +614 -176
- package/package.json +1 -1
|
@@ -1664,6 +1664,10 @@ const createDefaultState = () => {
|
|
|
1664
1664
|
chatMessageFontFamily: 'system-ui',
|
|
1665
1665
|
chatMessageFontSize,
|
|
1666
1666
|
chatMessageLineHeight,
|
|
1667
|
+
chatSendAreaPaddingBottom: 10,
|
|
1668
|
+
chatSendAreaPaddingLeft: 8,
|
|
1669
|
+
chatSendAreaPaddingRight: 8,
|
|
1670
|
+
chatSendAreaPaddingTop: 10,
|
|
1667
1671
|
composerDropActive: false,
|
|
1668
1672
|
composerDropEnabled: true,
|
|
1669
1673
|
composerFontFamily: 'system-ui',
|
|
@@ -1710,6 +1714,7 @@ const createDefaultState = () => {
|
|
|
1710
1714
|
}],
|
|
1711
1715
|
questionToolEnabled: false,
|
|
1712
1716
|
renamingSessionId: '',
|
|
1717
|
+
runMode: 'local',
|
|
1713
1718
|
selectedModelId: defaultModelId,
|
|
1714
1719
|
selectedProjectId: defaultProjectId,
|
|
1715
1720
|
selectedSessionId: defaultSessionId,
|
|
@@ -1719,7 +1724,12 @@ const createDefaultState = () => {
|
|
|
1719
1724
|
projectId: defaultProjectId,
|
|
1720
1725
|
title: defaultSessionTitle()
|
|
1721
1726
|
}],
|
|
1727
|
+
showRunMode: false,
|
|
1722
1728
|
streamingEnabled: true,
|
|
1729
|
+
textAreaPaddingBottom: 0,
|
|
1730
|
+
textAreaPaddingLeft: 12,
|
|
1731
|
+
textAreaPaddingRight: 12,
|
|
1732
|
+
textAreaPaddingTop: 0,
|
|
1723
1733
|
tokensMax: 0,
|
|
1724
1734
|
tokensUsed: 0,
|
|
1725
1735
|
uid: 0,
|
|
@@ -2513,7 +2523,7 @@ const getRenderHtmlCss = (sessions, selectedSessionId) => {
|
|
|
2513
2523
|
const isEqual$1 = (oldState, newState) => {
|
|
2514
2524
|
const oldRenderHtmlCss = getRenderHtmlCss(oldState.sessions, oldState.selectedSessionId);
|
|
2515
2525
|
const newRenderHtmlCss = getRenderHtmlCss(newState.sessions, newState.selectedSessionId);
|
|
2516
|
-
return oldState.initial === newState.initial && oldState.chatMessageFontFamily === newState.chatMessageFontFamily && oldState.chatMessageFontSize === newState.chatMessageFontSize && oldState.chatMessageLineHeight === newState.chatMessageLineHeight && oldState.composerHeight === newState.composerHeight && oldState.composerLineHeight === newState.composerLineHeight && oldState.composerFontFamily === newState.composerFontFamily && oldState.composerFontSize === newState.composerFontSize && oldState.listItemHeight === newState.listItemHeight && oldRenderHtmlCss === newRenderHtmlCss;
|
|
2526
|
+
return oldState.initial === newState.initial && oldState.chatMessageFontFamily === newState.chatMessageFontFamily && oldState.chatMessageFontSize === newState.chatMessageFontSize && oldState.chatMessageLineHeight === newState.chatMessageLineHeight && oldState.chatSendAreaPaddingTop === newState.chatSendAreaPaddingTop && oldState.chatSendAreaPaddingLeft === newState.chatSendAreaPaddingLeft && oldState.chatSendAreaPaddingRight === newState.chatSendAreaPaddingRight && oldState.chatSendAreaPaddingBottom === newState.chatSendAreaPaddingBottom && oldState.composerHeight === newState.composerHeight && oldState.composerLineHeight === newState.composerLineHeight && oldState.composerFontFamily === newState.composerFontFamily && oldState.composerFontSize === newState.composerFontSize && oldState.listItemHeight === newState.listItemHeight && oldState.textAreaPaddingTop === newState.textAreaPaddingTop && oldState.textAreaPaddingLeft === newState.textAreaPaddingLeft && oldState.textAreaPaddingRight === newState.textAreaPaddingRight && oldState.textAreaPaddingBottom === newState.textAreaPaddingBottom && oldRenderHtmlCss === newRenderHtmlCss;
|
|
2517
2527
|
};
|
|
2518
2528
|
|
|
2519
2529
|
const diffFocus = (oldState, newState) => {
|
|
@@ -2535,7 +2545,7 @@ const isEqualProjectExpandedIds = (a, b) => {
|
|
|
2535
2545
|
return true;
|
|
2536
2546
|
};
|
|
2537
2547
|
const isEqual = (oldState, newState) => {
|
|
2538
|
-
return oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage && oldState.authStatus === newState.authStatus && oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && oldState.projectListScrollTop === newState.projectListScrollTop && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
|
|
2548
|
+
return oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage && oldState.authStatus === newState.authStatus && oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && oldState.projectListScrollTop === newState.projectListScrollTop && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.showRunMode === newState.showRunMode && oldState.runMode === newState.runMode && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
|
|
2539
2549
|
};
|
|
2540
2550
|
|
|
2541
2551
|
const diffScrollTop = (oldState, newState) => {
|
|
@@ -3126,12 +3136,14 @@ const selectProject = async (state, projectId) => {
|
|
|
3126
3136
|
};
|
|
3127
3137
|
};
|
|
3128
3138
|
|
|
3139
|
+
const fileSchemeRegex = /^file:\/\//;
|
|
3140
|
+
const trailingSlashesRegex$4 = /\/+$/;
|
|
3129
3141
|
const getProjectName = (uri, fallbackIndex) => {
|
|
3130
3142
|
if (!uri) {
|
|
3131
3143
|
return `Project ${fallbackIndex}`;
|
|
3132
3144
|
}
|
|
3133
|
-
const withoutScheme = uri.replace(
|
|
3134
|
-
const normalized = withoutScheme.replace(
|
|
3145
|
+
const withoutScheme = uri.replace(fileSchemeRegex, '');
|
|
3146
|
+
const normalized = withoutScheme.replace(trailingSlashesRegex$4, '');
|
|
3135
3147
|
const lastSegment = normalized.split('/').pop();
|
|
3136
3148
|
if (!lastSegment) {
|
|
3137
3149
|
return `Project ${fallbackIndex}`;
|
|
@@ -3194,6 +3206,7 @@ const update = async settings => {
|
|
|
3194
3206
|
await invoke$1('Preferences.update', settings);
|
|
3195
3207
|
};
|
|
3196
3208
|
|
|
3209
|
+
const trailingSlashesRegex$3 = /\/+$/;
|
|
3197
3210
|
const isLoginResponse = value => {
|
|
3198
3211
|
if (!value || typeof value !== 'object') {
|
|
3199
3212
|
return false;
|
|
@@ -3201,7 +3214,7 @@ const isLoginResponse = value => {
|
|
|
3201
3214
|
return true;
|
|
3202
3215
|
};
|
|
3203
3216
|
const trimTrailingSlashes = value => {
|
|
3204
|
-
return value.replace(
|
|
3217
|
+
return value.replace(trailingSlashesRegex$3, '');
|
|
3205
3218
|
};
|
|
3206
3219
|
const handleClickLogin = async state => {
|
|
3207
3220
|
if (!state.backendUrl) {
|
|
@@ -4001,6 +4014,8 @@ const getTextContent = content => {
|
|
|
4001
4014
|
|
|
4002
4015
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
4003
4016
|
|
|
4017
|
+
const errorPrefixRegex = /^Error:\s*/;
|
|
4018
|
+
const notFoundErrorRegex = /not[\s_-]?found|enoent/i;
|
|
4004
4019
|
const getOpenAiTools = tools => {
|
|
4005
4020
|
return tools.map(tool => {
|
|
4006
4021
|
if (!tool || typeof tool !== 'object') {
|
|
@@ -4066,7 +4081,7 @@ const getStreamChunkText = content => {
|
|
|
4066
4081
|
}).join('');
|
|
4067
4082
|
};
|
|
4068
4083
|
const getShortToolErrorMessage = error => {
|
|
4069
|
-
const trimmed = error.trim().replace(
|
|
4084
|
+
const trimmed = error.trim().replace(errorPrefixRegex, '');
|
|
4070
4085
|
const firstLine = trimmed.split('\n')[0];
|
|
4071
4086
|
if (firstLine.length <= 80) {
|
|
4072
4087
|
return firstLine;
|
|
@@ -4098,7 +4113,7 @@ const getToolCallExecutionStatus = content => {
|
|
|
4098
4113
|
const rawStack = Reflect.get(parsed, 'errorStack') ?? Reflect.get(parsed, 'stack');
|
|
4099
4114
|
const errorStack = typeof rawStack === 'string' && rawStack.trim() ? rawStack : undefined;
|
|
4100
4115
|
const errorMessage = getShortToolErrorMessage(rawError);
|
|
4101
|
-
if (
|
|
4116
|
+
if (notFoundErrorRegex.test(errorMessage)) {
|
|
4102
4117
|
return {
|
|
4103
4118
|
...(errorStack ? {
|
|
4104
4119
|
errorStack
|
|
@@ -5086,13 +5101,15 @@ const getOpenApiModelId = selectedModelId => {
|
|
|
5086
5101
|
return selectedModelId;
|
|
5087
5102
|
};
|
|
5088
5103
|
|
|
5104
|
+
const trailingSlashesRegex$2 = /\/+$/;
|
|
5089
5105
|
const getOpenRouterApiEndpoint = openRouterApiBaseUrl => {
|
|
5090
|
-
const trimmedBaseUrl = openRouterApiBaseUrl.replace(
|
|
5106
|
+
const trimmedBaseUrl = openRouterApiBaseUrl.replace(trailingSlashesRegex$2, '');
|
|
5091
5107
|
return `${trimmedBaseUrl}/chat/completions`;
|
|
5092
5108
|
};
|
|
5093
5109
|
|
|
5110
|
+
const trailingSlashesRegex$1 = /\/+$/;
|
|
5094
5111
|
const getOpenRouterKeyEndpoint = openRouterApiBaseUrl => {
|
|
5095
|
-
const trimmedBaseUrl = openRouterApiBaseUrl.replace(
|
|
5112
|
+
const trimmedBaseUrl = openRouterApiBaseUrl.replace(trailingSlashesRegex$1, '');
|
|
5096
5113
|
return `${trimmedBaseUrl}/auth/key`;
|
|
5097
5114
|
};
|
|
5098
5115
|
|
|
@@ -5478,8 +5495,9 @@ const getAll = () => {
|
|
|
5478
5495
|
|
|
5479
5496
|
/* eslint-disable prefer-destructuring */
|
|
5480
5497
|
|
|
5498
|
+
const trailingSlashesRegex = /\/+$/;
|
|
5481
5499
|
const getBackendCompletionsEndpoint = backendUrl => {
|
|
5482
|
-
const trimmedBackendUrl = backendUrl.replace(
|
|
5500
|
+
const trimmedBackendUrl = backendUrl.replace(trailingSlashesRegex, '');
|
|
5483
5501
|
return `${trimmedBackendUrl}/v1/chat/completions`;
|
|
5484
5502
|
};
|
|
5485
5503
|
const getEffectiveBackendModelId = selectedModelId => {
|
|
@@ -6254,21 +6272,25 @@ const parseInlineNodes = value => {
|
|
|
6254
6272
|
};
|
|
6255
6273
|
|
|
6256
6274
|
const markdownMathBlockDelimiter = '$$';
|
|
6275
|
+
const escapedNewlineRegex = /\\r\\n|\\n/g;
|
|
6276
|
+
const lineBreakRegex = /\r?\n/;
|
|
6277
|
+
const tableDelimiterRegex = /\|\s*[-:]{3,}/;
|
|
6278
|
+
const inlineTableCellRegex = /\|\s+\|/g;
|
|
6257
6279
|
const normalizeEscapedNewlines = value => {
|
|
6258
6280
|
if (value.includes('\\n')) {
|
|
6259
|
-
return value.replaceAll(
|
|
6281
|
+
return value.replaceAll(escapedNewlineRegex, '\n');
|
|
6260
6282
|
}
|
|
6261
6283
|
return value;
|
|
6262
6284
|
};
|
|
6263
6285
|
const normalizeInlineTables = value => {
|
|
6264
|
-
return value.split(
|
|
6286
|
+
return value.split(lineBreakRegex).map(line => {
|
|
6265
6287
|
if (!line.includes('|')) {
|
|
6266
6288
|
return line;
|
|
6267
6289
|
}
|
|
6268
|
-
if (
|
|
6290
|
+
if (!tableDelimiterRegex.test(line)) {
|
|
6269
6291
|
return line;
|
|
6270
6292
|
}
|
|
6271
|
-
return line.replaceAll(
|
|
6293
|
+
return line.replaceAll(inlineTableCellRegex, '|\n|');
|
|
6272
6294
|
}).join('\n');
|
|
6273
6295
|
};
|
|
6274
6296
|
const parseHeadingLine = line => {
|
|
@@ -6347,6 +6369,33 @@ const parseBlockQuoteLine = line => {
|
|
|
6347
6369
|
}
|
|
6348
6370
|
return content;
|
|
6349
6371
|
};
|
|
6372
|
+
const isThematicBreakLine = line => {
|
|
6373
|
+
const trimmedStart = line.trimStart();
|
|
6374
|
+
const leadingSpaces = line.length - trimmedStart.length;
|
|
6375
|
+
if (leadingSpaces > 3) {
|
|
6376
|
+
return false;
|
|
6377
|
+
}
|
|
6378
|
+
const trimmed = trimmedStart.trimEnd();
|
|
6379
|
+
if (!trimmed) {
|
|
6380
|
+
return false;
|
|
6381
|
+
}
|
|
6382
|
+
const marker = trimmed[0];
|
|
6383
|
+
if (marker !== '-' && marker !== '_' && marker !== '*') {
|
|
6384
|
+
return false;
|
|
6385
|
+
}
|
|
6386
|
+
let markerCount = 0;
|
|
6387
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
6388
|
+
const char = trimmed[i];
|
|
6389
|
+
if (char === marker) {
|
|
6390
|
+
markerCount++;
|
|
6391
|
+
continue;
|
|
6392
|
+
}
|
|
6393
|
+
if (char !== ' ') {
|
|
6394
|
+
return false;
|
|
6395
|
+
}
|
|
6396
|
+
}
|
|
6397
|
+
return markerCount >= 3;
|
|
6398
|
+
};
|
|
6350
6399
|
const isTableRow = line => {
|
|
6351
6400
|
const trimmed = line.trim();
|
|
6352
6401
|
if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) {
|
|
@@ -6360,7 +6409,7 @@ const getTableCells = line => {
|
|
|
6360
6409
|
};
|
|
6361
6410
|
const scanBlockTokens = rawMessage => {
|
|
6362
6411
|
const normalizedMessage = normalizeInlineTables(normalizeEscapedNewlines(rawMessage));
|
|
6363
|
-
const lines = normalizedMessage.split(
|
|
6412
|
+
const lines = normalizedMessage.split(lineBreakRegex);
|
|
6364
6413
|
const tokens = [];
|
|
6365
6414
|
for (let i = 0; i < lines.length; i++) {
|
|
6366
6415
|
const line = lines[i];
|
|
@@ -6426,6 +6475,12 @@ const scanBlockTokens = rawMessage => {
|
|
|
6426
6475
|
});
|
|
6427
6476
|
continue;
|
|
6428
6477
|
}
|
|
6478
|
+
if (isThematicBreakLine(line)) {
|
|
6479
|
+
tokens.push({
|
|
6480
|
+
type: 'thematic-break'
|
|
6481
|
+
});
|
|
6482
|
+
continue;
|
|
6483
|
+
}
|
|
6429
6484
|
const ordered = parseOrderedListItemLine(line);
|
|
6430
6485
|
if (ordered) {
|
|
6431
6486
|
tokens.push({
|
|
@@ -6571,6 +6626,14 @@ const parseBlockTokens = tokens => {
|
|
|
6571
6626
|
});
|
|
6572
6627
|
continue;
|
|
6573
6628
|
}
|
|
6629
|
+
if (token.type === 'thematic-break') {
|
|
6630
|
+
flushList();
|
|
6631
|
+
flushParagraph();
|
|
6632
|
+
nodes.push({
|
|
6633
|
+
type: 'thematic-break'
|
|
6634
|
+
});
|
|
6635
|
+
continue;
|
|
6636
|
+
}
|
|
6574
6637
|
if (token.type === 'blockquote-line') {
|
|
6575
6638
|
flushList();
|
|
6576
6639
|
flushParagraph();
|
|
@@ -6944,12 +7007,16 @@ const executeSlashCommand = async (state, command) => {
|
|
|
6944
7007
|
});
|
|
6945
7008
|
};
|
|
6946
7009
|
|
|
7010
|
+
const defaultSessionTitleRegex = /^Chat \d+$/;
|
|
6947
7011
|
const isDefaultSessionTitle = title => {
|
|
6948
|
-
return
|
|
7012
|
+
return defaultSessionTitleRegex.test(title);
|
|
6949
7013
|
};
|
|
6950
7014
|
|
|
7015
|
+
const titlePrefixRegex = /^title:\s*/i;
|
|
7016
|
+
const wrappedQuotesAndWhitespaceRegex = /^['"`\s]+|['"`\s]+$/g;
|
|
7017
|
+
const consecutiveWhitespaceRegex = /\s+/g;
|
|
6951
7018
|
const sanitizeGeneratedTitle = value => {
|
|
6952
|
-
return value.replace(
|
|
7019
|
+
return value.replace(titlePrefixRegex, '').replaceAll(wrappedQuotesAndWhitespaceRegex, '').replaceAll(consecutiveWhitespaceRegex, ' ').trim().slice(0, 80);
|
|
6953
7020
|
};
|
|
6954
7021
|
|
|
6955
7022
|
const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
@@ -7020,6 +7087,8 @@ Assistant: ${assistantText}`;
|
|
|
7020
7087
|
return title && !isDefaultSessionTitle(title) ? title : '';
|
|
7021
7088
|
};
|
|
7022
7089
|
|
|
7090
|
+
const windowsAbsolutePathRegex = /^[a-zA-Z]:[\\/]/;
|
|
7091
|
+
const pathSeparatorRegex$1 = /[\\/]/;
|
|
7023
7092
|
const isPathTraversalAttempt = path => {
|
|
7024
7093
|
if (!path) {
|
|
7025
7094
|
return false;
|
|
@@ -7030,15 +7099,16 @@ const isPathTraversalAttempt = path => {
|
|
|
7030
7099
|
if (path.startsWith('file://')) {
|
|
7031
7100
|
return true;
|
|
7032
7101
|
}
|
|
7033
|
-
if (
|
|
7102
|
+
if (windowsAbsolutePathRegex.test(path)) {
|
|
7034
7103
|
return true;
|
|
7035
7104
|
}
|
|
7036
|
-
const segments = path.split(
|
|
7105
|
+
const segments = path.split(pathSeparatorRegex$1);
|
|
7037
7106
|
return segments.includes('..');
|
|
7038
7107
|
};
|
|
7039
7108
|
|
|
7109
|
+
const pathSeparatorRegex = /[\\/]/;
|
|
7040
7110
|
const normalizeRelativePath = path => {
|
|
7041
|
-
const segments = path.split(
|
|
7111
|
+
const segments = path.split(pathSeparatorRegex).filter(segment => segment && segment !== '.');
|
|
7042
7112
|
if (segments.length === 0) {
|
|
7043
7113
|
return '.';
|
|
7044
7114
|
}
|
|
@@ -7046,13 +7116,14 @@ const normalizeRelativePath = path => {
|
|
|
7046
7116
|
};
|
|
7047
7117
|
|
|
7048
7118
|
const mentionRegex = /(^|\s)@([^\s]+)/g;
|
|
7119
|
+
const trailingPunctuationRegex = /[),.;:!?]+$/g;
|
|
7049
7120
|
const maxMentionCount = 5;
|
|
7050
7121
|
const parseMentionedPaths = value => {
|
|
7051
7122
|
const matches = value.matchAll(mentionRegex);
|
|
7052
7123
|
const paths = [];
|
|
7053
7124
|
for (const match of matches) {
|
|
7054
7125
|
const rawPath = match[2] || '';
|
|
7055
|
-
const cleanedPath = rawPath.replaceAll(
|
|
7126
|
+
const cleanedPath = rawPath.replaceAll(trailingPunctuationRegex, '');
|
|
7056
7127
|
if (!cleanedPath || isPathTraversalAttempt(cleanedPath)) {
|
|
7057
7128
|
continue;
|
|
7058
7129
|
}
|
|
@@ -7580,6 +7651,7 @@ const Dictate = 'dictate';
|
|
|
7580
7651
|
const Send = 'send';
|
|
7581
7652
|
const Back = 'back';
|
|
7582
7653
|
const Model = 'model';
|
|
7654
|
+
const RunMode = 'runMode';
|
|
7583
7655
|
const ToggleChatFocus = 'toggle-chat-focus';
|
|
7584
7656
|
const CreateProject = 'create-project';
|
|
7585
7657
|
const CreateSession = 'create-session';
|
|
@@ -8097,6 +8169,19 @@ const handleProjectListContextMenu = async state => {
|
|
|
8097
8169
|
return state;
|
|
8098
8170
|
};
|
|
8099
8171
|
|
|
8172
|
+
const isRunMode = value => {
|
|
8173
|
+
return value === 'local' || value === 'background' || value === 'cloud';
|
|
8174
|
+
};
|
|
8175
|
+
const handleRunModeChange = async (state, value) => {
|
|
8176
|
+
if (!isRunMode(value)) {
|
|
8177
|
+
return state;
|
|
8178
|
+
}
|
|
8179
|
+
return {
|
|
8180
|
+
...state,
|
|
8181
|
+
runMode: value
|
|
8182
|
+
};
|
|
8183
|
+
};
|
|
8184
|
+
|
|
8100
8185
|
const handleChatListScroll = async (state, chatListScrollTop) => {
|
|
8101
8186
|
if (state.chatListScrollTop === chatListScrollTop) {
|
|
8102
8187
|
return state;
|
|
@@ -8740,15 +8825,31 @@ const registerMockResponse = (state, mockResponse) => {
|
|
|
8740
8825
|
return state;
|
|
8741
8826
|
};
|
|
8742
8827
|
|
|
8743
|
-
const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily, renderHtmlCss) => {
|
|
8828
|
+
const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily, textAreaPaddingTop, textAreaPaddingLeft, textAreaPaddingRight, textAreaPaddingBottom, chatSendAreaPaddingTop, chatSendAreaPaddingLeft, chatSendAreaPaddingRight, chatSendAreaPaddingBottom, renderHtmlCss) => {
|
|
8744
8829
|
const baseCss = `:root {
|
|
8745
8830
|
--ChatInputBoxHeight: ${composerHeight}px;
|
|
8831
|
+
--ChatTextAreaHeight: ${composerHeight}px;
|
|
8832
|
+
--ChatSendAreaHeight: ${composerHeight + 62}px;
|
|
8833
|
+
--ChatTextAreaPaddingTop: ${textAreaPaddingTop}px;
|
|
8834
|
+
--ChatTextAreaPaddingLeft: ${textAreaPaddingLeft}px;
|
|
8835
|
+
--ChatTextAreaPaddingRight: ${textAreaPaddingRight}px;
|
|
8836
|
+
--ChatTextAreaPaddingBottom: ${textAreaPaddingBottom}px;
|
|
8837
|
+
--ChatSendAreaPaddingTop: ${chatSendAreaPaddingTop}px;
|
|
8838
|
+
--ChatSendAreaPaddingLeft: ${chatSendAreaPaddingLeft}px;
|
|
8839
|
+
--ChatSendAreaPaddingRight: ${chatSendAreaPaddingRight}px;
|
|
8840
|
+
--ChatSendAreaPaddingBottom: ${chatSendAreaPaddingBottom}px;
|
|
8746
8841
|
--ChatListItemHeight: ${listItemHeight}px;
|
|
8747
8842
|
--ChatMessageFontSize: ${chatMessageFontSize}px;
|
|
8748
8843
|
--ChatMessageLineHeight: ${chatMessageLineHeight}px;
|
|
8749
8844
|
--ChatMessageFontFamily: ${chatMessageFontFamily};
|
|
8750
8845
|
}
|
|
8751
8846
|
|
|
8847
|
+
|
|
8848
|
+
.ChatSendArea{
|
|
8849
|
+
height: var(--ChatSendAreaHeight);
|
|
8850
|
+
padding: var(--ChatSendAreaPaddingTop) var(--ChatSendAreaPaddingRight) var(--ChatSendAreaPaddingBottom) var(--ChatSendAreaPaddingLeft);
|
|
8851
|
+
}
|
|
8852
|
+
|
|
8752
8853
|
.Viewlet.Chat.ChatFocus {
|
|
8753
8854
|
background: linear-gradient(180deg, var(--ColorViewBackground, #1d2229) 0%, #1f252d 100%);
|
|
8754
8855
|
display: grid;
|
|
@@ -8760,6 +8861,11 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
8760
8861
|
grid-column: 1 / 3;
|
|
8761
8862
|
}
|
|
8762
8863
|
|
|
8864
|
+
.ChatHeader .Label {
|
|
8865
|
+
text-decoration: underline;
|
|
8866
|
+
text-underline-offset: 5px;
|
|
8867
|
+
}
|
|
8868
|
+
|
|
8763
8869
|
.Chat.ChatFocus .ProjectSidebar {
|
|
8764
8870
|
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 88%, #1f2b38 12%);
|
|
8765
8871
|
border-right: 1px solid var(--ColorBorder, #3a3d41);
|
|
@@ -8944,7 +9050,9 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
8944
9050
|
.ChatList,
|
|
8945
9051
|
.ChatListEmpty,
|
|
8946
9052
|
.ChatMessages {
|
|
9053
|
+
margin: 0;
|
|
8947
9054
|
min-height: 0;
|
|
9055
|
+
padding: 0;
|
|
8948
9056
|
}
|
|
8949
9057
|
|
|
8950
9058
|
.Chat.ChatFocus .ChatList,
|
|
@@ -8960,6 +9068,32 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
8960
9068
|
.Chat.ChatFocus .ChatSendArea {
|
|
8961
9069
|
grid-column: 2;
|
|
8962
9070
|
grid-row: 3;
|
|
9071
|
+
height: var(--ChatSendAreaHeight);
|
|
9072
|
+
min-height: var(--ChatSendAreaHeight);
|
|
9073
|
+
}
|
|
9074
|
+
|
|
9075
|
+
.Chat .MultilineInputBox {
|
|
9076
|
+
height: var(--ChatTextAreaHeight);
|
|
9077
|
+
min-height: var(--ChatTextAreaHeight);
|
|
9078
|
+
padding: var(--ChatTextAreaPaddingTop) var(--ChatTextAreaPaddingRight) var(--ChatTextAreaPaddingBottom) var(--ChatTextAreaPaddingLeft);
|
|
9079
|
+
}
|
|
9080
|
+
|
|
9081
|
+
.Select {
|
|
9082
|
+
-moz-appearance: none;
|
|
9083
|
+
-webkit-appearance: none;
|
|
9084
|
+
appearance: none;
|
|
9085
|
+
background-image:
|
|
9086
|
+
linear-gradient(45deg, transparent 50%, color-mix(in srgb, var(--ColorForeground, #d5dbe3) 84%, transparent) 50%),
|
|
9087
|
+
linear-gradient(135deg, color-mix(in srgb, var(--ColorForeground, #d5dbe3) 84%, transparent) 50%, transparent 50%);
|
|
9088
|
+
background-position:
|
|
9089
|
+
calc(100% - 10px) 50%,
|
|
9090
|
+
calc(100% - 6px) 50%;
|
|
9091
|
+
background-repeat: no-repeat;
|
|
9092
|
+
background-size:
|
|
9093
|
+
4px 4px,
|
|
9094
|
+
4px 4px;
|
|
9095
|
+
max-width: 60px;
|
|
9096
|
+
padding-right: 16px;
|
|
8963
9097
|
}
|
|
8964
9098
|
|
|
8965
9099
|
.MarkdownMathInline {
|
|
@@ -8980,6 +9114,16 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
8980
9114
|
overflow-y: hidden;
|
|
8981
9115
|
}
|
|
8982
9116
|
|
|
9117
|
+
.ChatMessageContent hr,
|
|
9118
|
+
.ChatToolCallRenderHtmlBody hr {
|
|
9119
|
+
border: 0;
|
|
9120
|
+
border-top: 1px solid color-mix(in srgb, var(--ColorBorder, #3a3d41) 78%, transparent);
|
|
9121
|
+
display: block;
|
|
9122
|
+
height: 0;
|
|
9123
|
+
margin: 12px 0;
|
|
9124
|
+
width: 100%;
|
|
9125
|
+
}
|
|
9126
|
+
|
|
8983
9127
|
.StrikeThrough {
|
|
8984
9128
|
text-decoration: line-through;
|
|
8985
9129
|
}
|
|
@@ -9048,14 +9192,22 @@ const renderCss = (oldState, newState) => {
|
|
|
9048
9192
|
chatMessageFontFamily,
|
|
9049
9193
|
chatMessageFontSize,
|
|
9050
9194
|
chatMessageLineHeight,
|
|
9195
|
+
chatSendAreaPaddingBottom,
|
|
9196
|
+
chatSendAreaPaddingLeft,
|
|
9197
|
+
chatSendAreaPaddingRight,
|
|
9198
|
+
chatSendAreaPaddingTop,
|
|
9051
9199
|
composerHeight,
|
|
9052
9200
|
listItemHeight,
|
|
9053
9201
|
selectedSessionId,
|
|
9054
9202
|
sessions,
|
|
9203
|
+
textAreaPaddingBottom,
|
|
9204
|
+
textAreaPaddingLeft,
|
|
9205
|
+
textAreaPaddingRight,
|
|
9206
|
+
textAreaPaddingTop,
|
|
9055
9207
|
uid
|
|
9056
9208
|
} = newState;
|
|
9057
9209
|
const renderHtmlCss = getRenderHtmlCss(sessions, selectedSessionId);
|
|
9058
|
-
const css = getCss(composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily, renderHtmlCss);
|
|
9210
|
+
const css = getCss(composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily, textAreaPaddingTop, textAreaPaddingLeft, textAreaPaddingRight, textAreaPaddingBottom, chatSendAreaPaddingTop, chatSendAreaPaddingLeft, chatSendAreaPaddingRight, chatSendAreaPaddingBottom, renderHtmlCss);
|
|
9059
9211
|
return [SetCss, uid, css];
|
|
9060
9212
|
};
|
|
9061
9213
|
|
|
@@ -9193,6 +9345,7 @@ const HandleProjectListScroll = 32;
|
|
|
9193
9345
|
const HandleProjectListContextMenu = 33;
|
|
9194
9346
|
const HandleClickDictationButton = 34;
|
|
9195
9347
|
const HandleMissingApiKeySubmit = 35;
|
|
9348
|
+
const HandleRunModeChange = 36;
|
|
9196
9349
|
|
|
9197
9350
|
const getModelLabel = model => {
|
|
9198
9351
|
if (model.provider === 'openRouter') {
|
|
@@ -9226,6 +9379,28 @@ const getChatSelectVirtualDom = (models, selectedModelId) => {
|
|
|
9226
9379
|
}, ...modelOptions];
|
|
9227
9380
|
};
|
|
9228
9381
|
|
|
9382
|
+
const getRunModeOptionDom = (runMode, selectedRunMode) => {
|
|
9383
|
+
return [{
|
|
9384
|
+
childCount: 1,
|
|
9385
|
+
selected: runMode === selectedRunMode,
|
|
9386
|
+
type: Option$1,
|
|
9387
|
+
value: runMode
|
|
9388
|
+
}, text(runMode)];
|
|
9389
|
+
};
|
|
9390
|
+
|
|
9391
|
+
const runModes = ['local', 'background', 'cloud'];
|
|
9392
|
+
const getRunModeSelectVirtualDom = selectedRunMode => {
|
|
9393
|
+
const runModeOptions = runModes.flatMap(runMode => getRunModeOptionDom(runMode, selectedRunMode));
|
|
9394
|
+
return [{
|
|
9395
|
+
childCount: runModes.length,
|
|
9396
|
+
className: Select,
|
|
9397
|
+
name: RunMode,
|
|
9398
|
+
onInput: HandleRunModeChange,
|
|
9399
|
+
type: Select$1,
|
|
9400
|
+
value: selectedRunMode
|
|
9401
|
+
}, ...runModeOptions];
|
|
9402
|
+
};
|
|
9403
|
+
|
|
9229
9404
|
const getSendButtonClassName = isSendDisabled => {
|
|
9230
9405
|
return isSendDisabled ? `${IconButton} ${SendButtonDisabled}` : `${IconButton}`;
|
|
9231
9406
|
};
|
|
@@ -9293,9 +9468,9 @@ const getUsageOverviewDom = (tokensUsed, tokensMax) => {
|
|
|
9293
9468
|
}, text(usageLabel)];
|
|
9294
9469
|
};
|
|
9295
9470
|
|
|
9296
|
-
const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled = false) => {
|
|
9471
|
+
const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, showRunMode, runMode, voiceDictationEnabled = false) => {
|
|
9297
9472
|
const isSendDisabled = composerValue.trim() === '';
|
|
9298
|
-
const controlsCount = usageOverviewEnabled ?
|
|
9473
|
+
const controlsCount = 2 + (usageOverviewEnabled ? 1 : 0) + (showRunMode ? 1 : 0);
|
|
9299
9474
|
return [{
|
|
9300
9475
|
childCount: 1,
|
|
9301
9476
|
className: ChatSendArea,
|
|
@@ -9318,7 +9493,7 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOvervie
|
|
|
9318
9493
|
childCount: voiceDictationEnabled ? controlsCount + 1 : controlsCount,
|
|
9319
9494
|
className: ChatSendAreaBottom,
|
|
9320
9495
|
type: Div
|
|
9321
|
-
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
9496
|
+
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(showRunMode ? getRunModeSelectVirtualDom(runMode) : []), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
9322
9497
|
};
|
|
9323
9498
|
|
|
9324
9499
|
const getImageAltText = alt => {
|
|
@@ -9683,6 +9858,12 @@ const getMessageNodeDom = (node, useChatMathWorker = false) => {
|
|
|
9683
9858
|
if (node.type === 'math-block-dom') {
|
|
9684
9859
|
return node.dom;
|
|
9685
9860
|
}
|
|
9861
|
+
if (node.type === 'thematic-break') {
|
|
9862
|
+
return [{
|
|
9863
|
+
childCount: 0,
|
|
9864
|
+
type: Hr
|
|
9865
|
+
}];
|
|
9866
|
+
}
|
|
9686
9867
|
if (node.type === 'heading') {
|
|
9687
9868
|
return getHeadingDom(node, useChatMathWorker);
|
|
9688
9869
|
}
|
|
@@ -9817,6 +9998,72 @@ const getOpenRouterTooManyRequestsDom = () => {
|
|
|
9817
9998
|
})];
|
|
9818
9999
|
};
|
|
9819
10000
|
|
|
10001
|
+
const getToolCallStatusLabel = toolCall => {
|
|
10002
|
+
if (toolCall.status === 'not-found') {
|
|
10003
|
+
return ' (not-found)';
|
|
10004
|
+
}
|
|
10005
|
+
if (toolCall.status === 'error') {
|
|
10006
|
+
if (toolCall.errorMessage) {
|
|
10007
|
+
return ` (error: ${toolCall.errorMessage})`;
|
|
10008
|
+
}
|
|
10009
|
+
return ' (error)';
|
|
10010
|
+
}
|
|
10011
|
+
return '';
|
|
10012
|
+
};
|
|
10013
|
+
|
|
10014
|
+
const parseAskQuestionArguments = rawArguments => {
|
|
10015
|
+
let parsed;
|
|
10016
|
+
try {
|
|
10017
|
+
parsed = JSON.parse(rawArguments);
|
|
10018
|
+
} catch {
|
|
10019
|
+
return {
|
|
10020
|
+
answers: [],
|
|
10021
|
+
question: ''
|
|
10022
|
+
};
|
|
10023
|
+
}
|
|
10024
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
10025
|
+
return {
|
|
10026
|
+
answers: [],
|
|
10027
|
+
question: ''
|
|
10028
|
+
};
|
|
10029
|
+
}
|
|
10030
|
+
const question = Reflect.get(parsed, 'question');
|
|
10031
|
+
const rawAnswers = Reflect.get(parsed, 'answers');
|
|
10032
|
+
const rawChoices = Reflect.get(parsed, 'choices');
|
|
10033
|
+
const rawOptions = Reflect.get(parsed, 'options');
|
|
10034
|
+
const arrayValue = Array.isArray(rawAnswers) ? rawAnswers : Array.isArray(rawChoices) ? rawChoices : Array.isArray(rawOptions) ? rawOptions : [];
|
|
10035
|
+
const answers = arrayValue.filter(value => typeof value === 'string');
|
|
10036
|
+
return {
|
|
10037
|
+
answers,
|
|
10038
|
+
question: typeof question === 'string' ? question : ''
|
|
10039
|
+
};
|
|
10040
|
+
};
|
|
10041
|
+
|
|
10042
|
+
const getToolCallAskQuestionVirtualDom = toolCall => {
|
|
10043
|
+
const parsed = parseAskQuestionArguments(toolCall.arguments);
|
|
10044
|
+
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10045
|
+
const questionLabel = parsed.question.trim() ? parsed.question : '(empty question)';
|
|
10046
|
+
const answers = parsed.answers.length > 0 ? parsed.answers : ['(no answers)'];
|
|
10047
|
+
const childCount = 2;
|
|
10048
|
+
return [{
|
|
10049
|
+
childCount,
|
|
10050
|
+
className: ChatOrderedListItem,
|
|
10051
|
+
type: Li
|
|
10052
|
+
}, {
|
|
10053
|
+
childCount: 1,
|
|
10054
|
+
className: ChatToolCallQuestionText,
|
|
10055
|
+
type: Div
|
|
10056
|
+
}, text(`ask_question: ${questionLabel}${statusLabel}`), {
|
|
10057
|
+
childCount: answers.length,
|
|
10058
|
+
className: ChatToolCallQuestionOptions,
|
|
10059
|
+
type: Div
|
|
10060
|
+
}, ...answers.flatMap(answer => [{
|
|
10061
|
+
childCount: 1,
|
|
10062
|
+
className: ChatToolCallQuestionOption,
|
|
10063
|
+
type: Span
|
|
10064
|
+
}, text(answer.trim() ? answer : '(empty answer)')])];
|
|
10065
|
+
};
|
|
10066
|
+
|
|
9820
10067
|
const RE_QUERY_OR_HASH = /[?#].*$/;
|
|
9821
10068
|
const RE_TRAILING_SLASH = /\/$/;
|
|
9822
10069
|
const getFileNameFromUri = uri => {
|
|
@@ -9896,6 +10143,58 @@ const getReadFileTarget = rawArguments => {
|
|
|
9896
10143
|
};
|
|
9897
10144
|
};
|
|
9898
10145
|
|
|
10146
|
+
const getToolCallEditFileVirtualDom = toolCall => {
|
|
10147
|
+
const target = getReadFileTarget(toolCall.arguments);
|
|
10148
|
+
if (!target) {
|
|
10149
|
+
return [];
|
|
10150
|
+
}
|
|
10151
|
+
const fileName = getFileNameFromUri(target.title);
|
|
10152
|
+
const fileNameClickableProps = target.clickableUri ? {
|
|
10153
|
+
'data-uri': target.clickableUri,
|
|
10154
|
+
onClick: HandleClickReadFile
|
|
10155
|
+
} : {};
|
|
10156
|
+
return [{
|
|
10157
|
+
childCount: 3,
|
|
10158
|
+
className: ChatOrderedListItem,
|
|
10159
|
+
title: target.title,
|
|
10160
|
+
type: Li
|
|
10161
|
+
}, {
|
|
10162
|
+
childCount: 0,
|
|
10163
|
+
className: FileIcon,
|
|
10164
|
+
type: Div
|
|
10165
|
+
}, text('edit_file '), {
|
|
10166
|
+
childCount: 1,
|
|
10167
|
+
className: ChatToolCallReadFileLink,
|
|
10168
|
+
title: target.clickableUri,
|
|
10169
|
+
...fileNameClickableProps,
|
|
10170
|
+
type: Span
|
|
10171
|
+
}, text(fileName)];
|
|
10172
|
+
};
|
|
10173
|
+
|
|
10174
|
+
const getToolCallGetWorkspaceUriVirtualDom = toolCall => {
|
|
10175
|
+
if (!toolCall.result) {
|
|
10176
|
+
return [];
|
|
10177
|
+
}
|
|
10178
|
+
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10179
|
+
const fileName = getFileNameFromUri(toolCall.result);
|
|
10180
|
+
return [{
|
|
10181
|
+
childCount: statusLabel ? 4 : 3,
|
|
10182
|
+
className: ChatOrderedListItem,
|
|
10183
|
+
title: toolCall.result,
|
|
10184
|
+
type: Li
|
|
10185
|
+
}, {
|
|
10186
|
+
childCount: 0,
|
|
10187
|
+
className: FileIcon,
|
|
10188
|
+
type: Div
|
|
10189
|
+
}, text('get_workspace_uri '), {
|
|
10190
|
+
childCount: 1,
|
|
10191
|
+
className: ChatToolCallReadFileLink,
|
|
10192
|
+
'data-uri': toolCall.result,
|
|
10193
|
+
onClick: HandleClickReadFile,
|
|
10194
|
+
type: Span
|
|
10195
|
+
}, text(fileName), ...(statusLabel ? [text(statusLabel)] : [])];
|
|
10196
|
+
};
|
|
10197
|
+
|
|
9899
10198
|
const getToolCallArgumentPreview = rawArguments => {
|
|
9900
10199
|
if (!rawArguments.trim()) {
|
|
9901
10200
|
return '""';
|
|
@@ -9923,69 +10222,33 @@ const getToolCallArgumentPreview = rawArguments => {
|
|
|
9923
10222
|
return rawArguments;
|
|
9924
10223
|
};
|
|
9925
10224
|
|
|
9926
|
-
const
|
|
9927
|
-
if (
|
|
9928
|
-
return '
|
|
9929
|
-
}
|
|
9930
|
-
if (toolCall.status === 'error') {
|
|
9931
|
-
if (toolCall.errorMessage) {
|
|
9932
|
-
return ` (error: ${toolCall.errorMessage})`;
|
|
9933
|
-
}
|
|
9934
|
-
return ' (error)';
|
|
10225
|
+
const getToolCallDisplayName = name => {
|
|
10226
|
+
if (name === 'getWorkspaceUri') {
|
|
10227
|
+
return 'get_workspace_uri';
|
|
9935
10228
|
}
|
|
9936
|
-
return
|
|
10229
|
+
return name;
|
|
9937
10230
|
};
|
|
9938
10231
|
|
|
9939
|
-
const
|
|
9940
|
-
let parsed;
|
|
10232
|
+
const hasIncompleteJsonArguments = rawArguments => {
|
|
9941
10233
|
try {
|
|
9942
|
-
|
|
10234
|
+
JSON.parse(rawArguments);
|
|
10235
|
+
return false;
|
|
9943
10236
|
} catch {
|
|
9944
|
-
return
|
|
9945
|
-
answers: [],
|
|
9946
|
-
question: ''
|
|
9947
|
-
};
|
|
9948
|
-
}
|
|
9949
|
-
if (!parsed || typeof parsed !== 'object') {
|
|
9950
|
-
return {
|
|
9951
|
-
answers: [],
|
|
9952
|
-
question: ''
|
|
9953
|
-
};
|
|
10237
|
+
return true;
|
|
9954
10238
|
}
|
|
9955
|
-
const question = Reflect.get(parsed, 'question');
|
|
9956
|
-
const rawAnswers = Reflect.get(parsed, 'answers');
|
|
9957
|
-
const rawChoices = Reflect.get(parsed, 'choices');
|
|
9958
|
-
const rawOptions = Reflect.get(parsed, 'options');
|
|
9959
|
-
const arrayValue = Array.isArray(rawAnswers) ? rawAnswers : Array.isArray(rawChoices) ? rawChoices : Array.isArray(rawOptions) ? rawOptions : [];
|
|
9960
|
-
const answers = arrayValue.filter(value => typeof value === 'string');
|
|
9961
|
-
return {
|
|
9962
|
-
answers,
|
|
9963
|
-
question: typeof question === 'string' ? question : ''
|
|
9964
|
-
};
|
|
9965
10239
|
};
|
|
9966
|
-
|
|
9967
|
-
|
|
10240
|
+
|
|
10241
|
+
const getToolCallLabel = toolCall => {
|
|
10242
|
+
const displayName = getToolCallDisplayName(toolCall.name);
|
|
10243
|
+
if (toolCall.name === 'write_file' && !toolCall.status && hasIncompleteJsonArguments(toolCall.arguments)) {
|
|
10244
|
+
return `${displayName} (in progress)`;
|
|
10245
|
+
}
|
|
10246
|
+
const argumentPreview = getToolCallArgumentPreview(toolCall.arguments);
|
|
9968
10247
|
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
return
|
|
9973
|
-
childCount,
|
|
9974
|
-
className: ChatOrderedListItem,
|
|
9975
|
-
type: Li
|
|
9976
|
-
}, {
|
|
9977
|
-
childCount: 1,
|
|
9978
|
-
className: ChatToolCallQuestionText,
|
|
9979
|
-
type: Div
|
|
9980
|
-
}, text(`ask_question: ${questionLabel}${statusLabel}`), {
|
|
9981
|
-
childCount: answers.length,
|
|
9982
|
-
className: ChatToolCallQuestionOptions,
|
|
9983
|
-
type: Div
|
|
9984
|
-
}, ...answers.flatMap(answer => [{
|
|
9985
|
-
childCount: 1,
|
|
9986
|
-
className: ChatToolCallQuestionOption,
|
|
9987
|
-
type: Span
|
|
9988
|
-
}, text(answer.trim() ? answer : '(empty answer)')])];
|
|
10248
|
+
if (argumentPreview === '{}') {
|
|
10249
|
+
return `${displayName}${statusLabel}`;
|
|
10250
|
+
}
|
|
10251
|
+
return `${displayName} ${argumentPreview}${statusLabel}`;
|
|
9989
10252
|
};
|
|
9990
10253
|
|
|
9991
10254
|
const getToolCallReadFileVirtualDom = toolCall => {
|
|
@@ -10020,16 +10283,24 @@ const getToolCallReadFileVirtualDom = toolCall => {
|
|
|
10020
10283
|
const maxHtmlLength = 40_000;
|
|
10021
10284
|
const tokenRegex = /<!--[\s\S]*?-->|<\/?[a-zA-Z][\w:-]*(?:\s[^<>]*?)?>|[^<]+/g;
|
|
10022
10285
|
const attributeRegex = /([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
|
|
10286
|
+
const scriptTagRegex = /<script\b[\s\S]*?<\/script>/gi;
|
|
10287
|
+
const styleTagRegex = /<style\b[\s\S]*?<\/style>/gi;
|
|
10288
|
+
const headTagRegex = /<head\b[\s\S]*?<\/head>/gi;
|
|
10289
|
+
const metaTagRegex = /<meta\b[^>]*>/gi;
|
|
10290
|
+
const linkTagRegex = /<link\b[^>]*>/gi;
|
|
10291
|
+
const tagPrefixRegex = /^<\/?\s*[a-zA-Z][\w:-]*/;
|
|
10292
|
+
const tagSuffixRegex = /\/?\s*>$/;
|
|
10293
|
+
const openTagNameRegex = /^<\s*([a-zA-Z][\w:-]*)/;
|
|
10023
10294
|
const inlineTags = new Set(['a', 'abbr', 'b', 'code', 'em', 'i', 'label', 'small', 'span', 'strong', 'sub', 'sup', 'u']);
|
|
10024
10295
|
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
|
|
10025
10296
|
const sanitizeHtml = value => {
|
|
10026
|
-
return value.slice(0, maxHtmlLength).replaceAll(
|
|
10297
|
+
return value.slice(0, maxHtmlLength).replaceAll(scriptTagRegex, '').replaceAll(styleTagRegex, '').replaceAll(headTagRegex, '').replaceAll(metaTagRegex, '').replaceAll(linkTagRegex, '');
|
|
10027
10298
|
};
|
|
10028
10299
|
const decodeEntities = value => {
|
|
10029
10300
|
return value.replaceAll(' ', ' ').replaceAll('"', '"').replaceAll(''', "'").replaceAll('<', '<').replaceAll('>', '>').replaceAll('&', '&');
|
|
10030
10301
|
};
|
|
10031
10302
|
const parseAttributes = token => {
|
|
10032
|
-
const withoutTag = token.replace(
|
|
10303
|
+
const withoutTag = token.replace(tagPrefixRegex, '').replace(tagSuffixRegex, '').trim();
|
|
10033
10304
|
if (!withoutTag) {
|
|
10034
10305
|
return Object.create(null);
|
|
10035
10306
|
}
|
|
@@ -10076,7 +10347,7 @@ const parseHtml = value => {
|
|
|
10076
10347
|
continue;
|
|
10077
10348
|
}
|
|
10078
10349
|
if (token.startsWith('<')) {
|
|
10079
|
-
const openTagNameMatch =
|
|
10350
|
+
const openTagNameMatch = openTagNameRegex.exec(token);
|
|
10080
10351
|
if (!openTagNameMatch) {
|
|
10081
10352
|
continue;
|
|
10082
10353
|
}
|
|
@@ -10320,55 +10591,6 @@ const getToolCallRenderHtmlVirtualDom = toolCall => {
|
|
|
10320
10591
|
}, ...parsedHtml.virtualDom];
|
|
10321
10592
|
};
|
|
10322
10593
|
|
|
10323
|
-
const getToolCallDisplayName = name => {
|
|
10324
|
-
if (name === 'getWorkspaceUri') {
|
|
10325
|
-
return 'get_workspace_uri';
|
|
10326
|
-
}
|
|
10327
|
-
return name;
|
|
10328
|
-
};
|
|
10329
|
-
const hasIncompleteJsonArguments = rawArguments => {
|
|
10330
|
-
try {
|
|
10331
|
-
JSON.parse(rawArguments);
|
|
10332
|
-
return false;
|
|
10333
|
-
} catch {
|
|
10334
|
-
return true;
|
|
10335
|
-
}
|
|
10336
|
-
};
|
|
10337
|
-
const getToolCallLabel = toolCall => {
|
|
10338
|
-
const displayName = getToolCallDisplayName(toolCall.name);
|
|
10339
|
-
if (toolCall.name === 'write_file' && !toolCall.status && hasIncompleteJsonArguments(toolCall.arguments)) {
|
|
10340
|
-
return `${displayName} (in progress)`;
|
|
10341
|
-
}
|
|
10342
|
-
const argumentPreview = getToolCallArgumentPreview(toolCall.arguments);
|
|
10343
|
-
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10344
|
-
if (argumentPreview === '{}') {
|
|
10345
|
-
return `${displayName}${statusLabel}`;
|
|
10346
|
-
}
|
|
10347
|
-
return `${displayName} ${argumentPreview}${statusLabel}`;
|
|
10348
|
-
};
|
|
10349
|
-
const getToolCallGetWorkspaceUriVirtualDom = toolCall => {
|
|
10350
|
-
if (!toolCall.result) {
|
|
10351
|
-
return [];
|
|
10352
|
-
}
|
|
10353
|
-
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10354
|
-
const fileName = getFileNameFromUri(toolCall.result);
|
|
10355
|
-
return [{
|
|
10356
|
-
childCount: statusLabel ? 4 : 3,
|
|
10357
|
-
className: ChatOrderedListItem,
|
|
10358
|
-
title: toolCall.result,
|
|
10359
|
-
type: Li
|
|
10360
|
-
}, {
|
|
10361
|
-
childCount: 0,
|
|
10362
|
-
className: FileIcon,
|
|
10363
|
-
type: Div
|
|
10364
|
-
}, text('get_workspace_uri '), {
|
|
10365
|
-
childCount: 1,
|
|
10366
|
-
className: ChatToolCallReadFileLink,
|
|
10367
|
-
'data-uri': toolCall.result,
|
|
10368
|
-
onClick: HandleClickReadFile,
|
|
10369
|
-
type: Span
|
|
10370
|
-
}, text(fileName), ...(statusLabel ? [text(statusLabel)] : [])];
|
|
10371
|
-
};
|
|
10372
10594
|
const parseWriteFileLineCounts = rawResult => {
|
|
10373
10595
|
if (!rawResult) {
|
|
10374
10596
|
return {
|
|
@@ -10398,6 +10620,7 @@ const parseWriteFileLineCounts = rawResult => {
|
|
|
10398
10620
|
linesDeleted: typeof linesDeleted === 'number' ? Math.max(0, linesDeleted) : 0
|
|
10399
10621
|
};
|
|
10400
10622
|
};
|
|
10623
|
+
|
|
10401
10624
|
const getToolCallWriteFileVirtualDom = toolCall => {
|
|
10402
10625
|
const target = getReadFileTarget(toolCall.arguments);
|
|
10403
10626
|
if (!target) {
|
|
@@ -10437,33 +10660,7 @@ const getToolCallWriteFileVirtualDom = toolCall => {
|
|
|
10437
10660
|
type: Span
|
|
10438
10661
|
}, text(` -${linesDeleted}`), ...(statusLabel ? [text(statusLabel)] : [])];
|
|
10439
10662
|
};
|
|
10440
|
-
|
|
10441
|
-
const target = getReadFileTarget(toolCall.arguments);
|
|
10442
|
-
if (!target) {
|
|
10443
|
-
return [];
|
|
10444
|
-
}
|
|
10445
|
-
const fileName = getFileNameFromUri(target.title);
|
|
10446
|
-
const fileNameClickableProps = target.clickableUri ? {
|
|
10447
|
-
'data-uri': target.clickableUri,
|
|
10448
|
-
onClick: HandleClickReadFile
|
|
10449
|
-
} : {};
|
|
10450
|
-
return [{
|
|
10451
|
-
childCount: 3,
|
|
10452
|
-
className: ChatOrderedListItem,
|
|
10453
|
-
title: target.title,
|
|
10454
|
-
type: Li
|
|
10455
|
-
}, {
|
|
10456
|
-
childCount: 0,
|
|
10457
|
-
className: FileIcon,
|
|
10458
|
-
type: Div
|
|
10459
|
-
}, text('edit_file '), {
|
|
10460
|
-
childCount: 1,
|
|
10461
|
-
className: ChatToolCallReadFileLink,
|
|
10462
|
-
title: target.clickableUri,
|
|
10463
|
-
...fileNameClickableProps,
|
|
10464
|
-
type: Span
|
|
10465
|
-
}, text(fileName)];
|
|
10466
|
-
};
|
|
10663
|
+
|
|
10467
10664
|
const getToolCallDom = toolCall => {
|
|
10468
10665
|
if (toolCall.name === 'getWorkspaceUri') {
|
|
10469
10666
|
const virtualDom = getToolCallGetWorkspaceUriVirtualDom(toolCall);
|
|
@@ -10598,9 +10795,9 @@ const getDisplayMessages = (messages, parsedMessages) => {
|
|
|
10598
10795
|
}
|
|
10599
10796
|
return displayMessages;
|
|
10600
10797
|
};
|
|
10601
|
-
const getMessagesDom = (messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput = '', openRouterApiKeyState = 'idle', messagesScrollTop = 0, useChatMathWorker = false) => {
|
|
10798
|
+
const getMessagesDom = (messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput = '', openRouterApiKeyState = 'idle', messagesScrollTop = 0, useChatMathWorker = false, hideWelcomeMessage = false) => {
|
|
10602
10799
|
if (messages.length === 0) {
|
|
10603
|
-
return getEmptyMessagesDom();
|
|
10800
|
+
return hideWelcomeMessage ? [] : getEmptyMessagesDom();
|
|
10604
10801
|
}
|
|
10605
10802
|
const displayMessages = getDisplayMessages(messages, parsedMessages);
|
|
10606
10803
|
return [{
|
|
@@ -10698,7 +10895,38 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
|
|
|
10698
10895
|
}, text('+ Add Project')];
|
|
10699
10896
|
};
|
|
10700
10897
|
|
|
10701
|
-
const getChatModeChatFocusVirtualDom = (
|
|
10898
|
+
const getChatModeChatFocusVirtualDom = ({
|
|
10899
|
+
authEnabled = false,
|
|
10900
|
+
authErrorMessage = '',
|
|
10901
|
+
authStatus = 'signed-out',
|
|
10902
|
+
composerDropActive = false,
|
|
10903
|
+
composerDropEnabled = true,
|
|
10904
|
+
composerFontFamily = 'system-ui',
|
|
10905
|
+
composerFontSize = 13,
|
|
10906
|
+
composerHeight = 28,
|
|
10907
|
+
composerLineHeight = 20,
|
|
10908
|
+
composerValue,
|
|
10909
|
+
messagesScrollTop = 0,
|
|
10910
|
+
models,
|
|
10911
|
+
openApiApiKeyInput,
|
|
10912
|
+
openRouterApiKeyInput,
|
|
10913
|
+
openRouterApiKeyState = 'idle',
|
|
10914
|
+
parsedMessages = [],
|
|
10915
|
+
projectExpandedIds = [],
|
|
10916
|
+
projectListScrollTop = 0,
|
|
10917
|
+
projects = [],
|
|
10918
|
+
runMode,
|
|
10919
|
+
selectedModelId,
|
|
10920
|
+
selectedProjectId = '',
|
|
10921
|
+
selectedSessionId,
|
|
10922
|
+
sessions,
|
|
10923
|
+
showRunMode,
|
|
10924
|
+
tokensMax,
|
|
10925
|
+
tokensUsed,
|
|
10926
|
+
usageOverviewEnabled,
|
|
10927
|
+
useChatMathWorker = false,
|
|
10928
|
+
voiceDictationEnabled = false
|
|
10929
|
+
}) => {
|
|
10702
10930
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
10703
10931
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
10704
10932
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
@@ -10708,7 +10936,7 @@ const getChatModeChatFocusVirtualDom = (sessions, selectedSessionId, composerVal
|
|
|
10708
10936
|
onDragEnter: HandleDragEnterChatView,
|
|
10709
10937
|
onDragOver: HandleDragOverChatView,
|
|
10710
10938
|
type: Div
|
|
10711
|
-
}, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
10939
|
+
}, ...getProjectListDom(projects, sessions, projectExpandedIds, selectedProjectId, selectedSessionId, projectListScrollTop), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, showRunMode, runMode, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
10712
10940
|
childCount: 1,
|
|
10713
10941
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10714
10942
|
name: ComposerDropTarget,
|
|
@@ -10824,7 +11052,34 @@ const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, a
|
|
|
10824
11052
|
}, text(authErrorMessage)] : [])];
|
|
10825
11053
|
};
|
|
10826
11054
|
|
|
10827
|
-
const getChatModeDetailVirtualDom = (
|
|
11055
|
+
const getChatModeDetailVirtualDom = ({
|
|
11056
|
+
authEnabled = false,
|
|
11057
|
+
authErrorMessage = '',
|
|
11058
|
+
authStatus = 'signed-out',
|
|
11059
|
+
composerDropActive = false,
|
|
11060
|
+
composerDropEnabled = true,
|
|
11061
|
+
composerFontFamily = 'system-ui',
|
|
11062
|
+
composerFontSize = 13,
|
|
11063
|
+
composerHeight = 28,
|
|
11064
|
+
composerLineHeight = 20,
|
|
11065
|
+
composerValue,
|
|
11066
|
+
messagesScrollTop = 0,
|
|
11067
|
+
models,
|
|
11068
|
+
openApiApiKeyInput,
|
|
11069
|
+
openRouterApiKeyInput,
|
|
11070
|
+
openRouterApiKeyState = 'idle',
|
|
11071
|
+
parsedMessages = [],
|
|
11072
|
+
runMode,
|
|
11073
|
+
selectedModelId,
|
|
11074
|
+
selectedSessionId,
|
|
11075
|
+
sessions,
|
|
11076
|
+
showRunMode,
|
|
11077
|
+
tokensMax,
|
|
11078
|
+
tokensUsed,
|
|
11079
|
+
usageOverviewEnabled,
|
|
11080
|
+
useChatMathWorker = false,
|
|
11081
|
+
voiceDictationEnabled = false
|
|
11082
|
+
}) => {
|
|
10828
11083
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
10829
11084
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
10830
11085
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
@@ -10835,7 +11090,7 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
|
|
|
10835
11090
|
onDragEnter: HandleDragEnterChatView,
|
|
10836
11091
|
onDragOver: HandleDragOverChatView,
|
|
10837
11092
|
type: Div
|
|
10838
|
-
}, ...getChatHeaderDomDetailMode(selectedSessionTitle, authEnabled, authStatus, authErrorMessage), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
11093
|
+
}, ...getChatHeaderDomDetailMode(selectedSessionTitle, authEnabled, authStatus, authErrorMessage), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, showRunMode, runMode, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
10839
11094
|
childCount: 1,
|
|
10840
11095
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10841
11096
|
name: ComposerDropTarget,
|
|
@@ -10883,7 +11138,7 @@ const getSessionDom = session => {
|
|
|
10883
11138
|
return [{
|
|
10884
11139
|
childCount: 2,
|
|
10885
11140
|
className: sessionClassName,
|
|
10886
|
-
type:
|
|
11141
|
+
type: Li
|
|
10887
11142
|
}, {
|
|
10888
11143
|
childCount: 1,
|
|
10889
11144
|
className: ChatListItemLabel,
|
|
@@ -10917,11 +11172,33 @@ const getChatListDom = (sessions, selectedSessionId, chatListScrollTop = 0) => {
|
|
|
10917
11172
|
onClick: HandleClickList,
|
|
10918
11173
|
onScroll: HandleChatListScroll,
|
|
10919
11174
|
scrollTop: chatListScrollTop,
|
|
10920
|
-
type:
|
|
11175
|
+
type: Ul
|
|
10921
11176
|
}, ...sessions.flatMap(getSessionDom)];
|
|
10922
11177
|
};
|
|
10923
11178
|
|
|
10924
|
-
const getChatModeListVirtualDom = (
|
|
11179
|
+
const getChatModeListVirtualDom = ({
|
|
11180
|
+
authEnabled = false,
|
|
11181
|
+
authErrorMessage = '',
|
|
11182
|
+
authStatus = 'signed-out',
|
|
11183
|
+
chatListScrollTop = 0,
|
|
11184
|
+
composerDropActive = false,
|
|
11185
|
+
composerDropEnabled = true,
|
|
11186
|
+
composerFontFamily = 'system-ui',
|
|
11187
|
+
composerFontSize = 13,
|
|
11188
|
+
composerHeight = 28,
|
|
11189
|
+
composerLineHeight = 20,
|
|
11190
|
+
composerValue,
|
|
11191
|
+
models,
|
|
11192
|
+
runMode,
|
|
11193
|
+
selectedModelId,
|
|
11194
|
+
selectedSessionId,
|
|
11195
|
+
sessions,
|
|
11196
|
+
showRunMode,
|
|
11197
|
+
tokensMax,
|
|
11198
|
+
tokensUsed,
|
|
11199
|
+
usageOverviewEnabled,
|
|
11200
|
+
voiceDictationEnabled = false
|
|
11201
|
+
}) => {
|
|
10925
11202
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
10926
11203
|
return [{
|
|
10927
11204
|
childCount: isDropOverlayVisible ? 4 : 3,
|
|
@@ -10929,7 +11206,7 @@ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, m
|
|
|
10929
11206
|
onDragEnter: HandleDragEnterChatView,
|
|
10930
11207
|
onDragOver: HandleDragOverChatView,
|
|
10931
11208
|
type: Div
|
|
10932
|
-
}, ...getChatHeaderListModeDom(authEnabled, authStatus, authErrorMessage), ...getChatListDom(sessions, selectedSessionId, chatListScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
11209
|
+
}, ...getChatHeaderListModeDom(authEnabled, authStatus, authErrorMessage), ...getChatListDom(sessions, selectedSessionId, chatListScrollTop), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, showRunMode, runMode, voiceDictationEnabled), ...(isDropOverlayVisible ? [{
|
|
10933
11210
|
childCount: 1,
|
|
10934
11211
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10935
11212
|
name: ComposerDropTarget,
|
|
@@ -10966,15 +11243,129 @@ const getFallbackParsedMessages = sessions => {
|
|
|
10966
11243
|
}
|
|
10967
11244
|
return parsedMessages;
|
|
10968
11245
|
};
|
|
10969
|
-
const getChatVirtualDom =
|
|
10970
|
-
const
|
|
11246
|
+
const getChatVirtualDom = options => {
|
|
11247
|
+
const {
|
|
11248
|
+
authEnabled = false,
|
|
11249
|
+
authErrorMessage = '',
|
|
11250
|
+
authStatus = 'signed-out',
|
|
11251
|
+
chatListScrollTop,
|
|
11252
|
+
composerDropActive = false,
|
|
11253
|
+
composerDropEnabled = true,
|
|
11254
|
+
composerFontFamily,
|
|
11255
|
+
composerFontSize,
|
|
11256
|
+
composerHeight,
|
|
11257
|
+
composerLineHeight,
|
|
11258
|
+
composerValue,
|
|
11259
|
+
messagesScrollTop,
|
|
11260
|
+
models,
|
|
11261
|
+
openApiApiKeyInput,
|
|
11262
|
+
openRouterApiKeyInput,
|
|
11263
|
+
openRouterApiKeyState,
|
|
11264
|
+
parsedMessages: parsedMessagesInput,
|
|
11265
|
+
projectExpandedIds = [],
|
|
11266
|
+
projectListScrollTop = 0,
|
|
11267
|
+
projects = [],
|
|
11268
|
+
runMode,
|
|
11269
|
+
selectedModelId,
|
|
11270
|
+
selectedProjectId = '',
|
|
11271
|
+
selectedSessionId,
|
|
11272
|
+
sessions,
|
|
11273
|
+
showRunMode,
|
|
11274
|
+
tokensMax,
|
|
11275
|
+
tokensUsed,
|
|
11276
|
+
usageOverviewEnabled,
|
|
11277
|
+
useChatMathWorker = false,
|
|
11278
|
+
viewMode,
|
|
11279
|
+
voiceDictationEnabled = false
|
|
11280
|
+
} = options;
|
|
11281
|
+
const parsedMessages = parsedMessagesInput ?? getFallbackParsedMessages(sessions);
|
|
10971
11282
|
switch (viewMode) {
|
|
10972
11283
|
case 'chat-focus':
|
|
10973
|
-
return getChatModeChatFocusVirtualDom(
|
|
11284
|
+
return getChatModeChatFocusVirtualDom({
|
|
11285
|
+
authEnabled,
|
|
11286
|
+
authErrorMessage,
|
|
11287
|
+
authStatus,
|
|
11288
|
+
composerDropActive,
|
|
11289
|
+
composerDropEnabled,
|
|
11290
|
+
composerFontFamily,
|
|
11291
|
+
composerFontSize,
|
|
11292
|
+
composerHeight,
|
|
11293
|
+
composerLineHeight,
|
|
11294
|
+
composerValue,
|
|
11295
|
+
messagesScrollTop,
|
|
11296
|
+
models,
|
|
11297
|
+
openApiApiKeyInput,
|
|
11298
|
+
openRouterApiKeyInput,
|
|
11299
|
+
openRouterApiKeyState,
|
|
11300
|
+
parsedMessages,
|
|
11301
|
+
projectExpandedIds,
|
|
11302
|
+
projectListScrollTop,
|
|
11303
|
+
projects,
|
|
11304
|
+
runMode,
|
|
11305
|
+
selectedModelId,
|
|
11306
|
+
selectedProjectId,
|
|
11307
|
+
selectedSessionId,
|
|
11308
|
+
sessions,
|
|
11309
|
+
showRunMode,
|
|
11310
|
+
tokensMax,
|
|
11311
|
+
tokensUsed,
|
|
11312
|
+
usageOverviewEnabled,
|
|
11313
|
+
useChatMathWorker,
|
|
11314
|
+
voiceDictationEnabled
|
|
11315
|
+
});
|
|
10974
11316
|
case 'detail':
|
|
10975
|
-
return getChatModeDetailVirtualDom(
|
|
11317
|
+
return getChatModeDetailVirtualDom({
|
|
11318
|
+
authEnabled,
|
|
11319
|
+
authErrorMessage,
|
|
11320
|
+
authStatus,
|
|
11321
|
+
composerDropActive,
|
|
11322
|
+
composerDropEnabled,
|
|
11323
|
+
composerFontFamily,
|
|
11324
|
+
composerFontSize,
|
|
11325
|
+
composerHeight,
|
|
11326
|
+
composerLineHeight,
|
|
11327
|
+
composerValue,
|
|
11328
|
+
messagesScrollTop,
|
|
11329
|
+
models,
|
|
11330
|
+
openApiApiKeyInput,
|
|
11331
|
+
openRouterApiKeyInput,
|
|
11332
|
+
openRouterApiKeyState,
|
|
11333
|
+
parsedMessages,
|
|
11334
|
+
runMode,
|
|
11335
|
+
selectedModelId,
|
|
11336
|
+
selectedSessionId,
|
|
11337
|
+
sessions,
|
|
11338
|
+
showRunMode,
|
|
11339
|
+
tokensMax,
|
|
11340
|
+
tokensUsed,
|
|
11341
|
+
usageOverviewEnabled,
|
|
11342
|
+
useChatMathWorker,
|
|
11343
|
+
voiceDictationEnabled
|
|
11344
|
+
});
|
|
10976
11345
|
case 'list':
|
|
10977
|
-
return getChatModeListVirtualDom(
|
|
11346
|
+
return getChatModeListVirtualDom({
|
|
11347
|
+
authEnabled,
|
|
11348
|
+
authErrorMessage,
|
|
11349
|
+
authStatus,
|
|
11350
|
+
chatListScrollTop,
|
|
11351
|
+
composerDropActive,
|
|
11352
|
+
composerDropEnabled,
|
|
11353
|
+
composerFontFamily,
|
|
11354
|
+
composerFontSize,
|
|
11355
|
+
composerHeight,
|
|
11356
|
+
composerLineHeight,
|
|
11357
|
+
composerValue,
|
|
11358
|
+
models,
|
|
11359
|
+
runMode,
|
|
11360
|
+
selectedModelId,
|
|
11361
|
+
selectedSessionId,
|
|
11362
|
+
sessions,
|
|
11363
|
+
showRunMode,
|
|
11364
|
+
tokensMax,
|
|
11365
|
+
tokensUsed,
|
|
11366
|
+
usageOverviewEnabled,
|
|
11367
|
+
voiceDictationEnabled
|
|
11368
|
+
});
|
|
10978
11369
|
default:
|
|
10979
11370
|
return getChatModeUnsupportedVirtualDom();
|
|
10980
11371
|
}
|
|
@@ -11003,10 +11394,12 @@ const renderItems = (oldState, newState) => {
|
|
|
11003
11394
|
projectExpandedIds,
|
|
11004
11395
|
projectListScrollTop,
|
|
11005
11396
|
projects,
|
|
11397
|
+
runMode,
|
|
11006
11398
|
selectedModelId,
|
|
11007
11399
|
selectedProjectId,
|
|
11008
11400
|
selectedSessionId,
|
|
11009
11401
|
sessions,
|
|
11402
|
+
showRunMode,
|
|
11010
11403
|
tokensMax,
|
|
11011
11404
|
tokensUsed,
|
|
11012
11405
|
uid,
|
|
@@ -11018,7 +11411,40 @@ const renderItems = (oldState, newState) => {
|
|
|
11018
11411
|
if (initial) {
|
|
11019
11412
|
return [SetDom2, uid, []];
|
|
11020
11413
|
}
|
|
11021
|
-
const dom = getChatVirtualDom(
|
|
11414
|
+
const dom = getChatVirtualDom({
|
|
11415
|
+
authEnabled,
|
|
11416
|
+
authErrorMessage,
|
|
11417
|
+
authStatus,
|
|
11418
|
+
chatListScrollTop,
|
|
11419
|
+
composerDropActive,
|
|
11420
|
+
composerDropEnabled,
|
|
11421
|
+
composerFontFamily,
|
|
11422
|
+
composerFontSize,
|
|
11423
|
+
composerHeight,
|
|
11424
|
+
composerLineHeight,
|
|
11425
|
+
composerValue,
|
|
11426
|
+
messagesScrollTop,
|
|
11427
|
+
models,
|
|
11428
|
+
openApiApiKeyInput,
|
|
11429
|
+
openRouterApiKeyInput,
|
|
11430
|
+
openRouterApiKeyState,
|
|
11431
|
+
parsedMessages,
|
|
11432
|
+
projectExpandedIds,
|
|
11433
|
+
projectListScrollTop,
|
|
11434
|
+
projects,
|
|
11435
|
+
runMode,
|
|
11436
|
+
selectedModelId,
|
|
11437
|
+
selectedProjectId,
|
|
11438
|
+
selectedSessionId,
|
|
11439
|
+
sessions,
|
|
11440
|
+
showRunMode,
|
|
11441
|
+
tokensMax,
|
|
11442
|
+
tokensUsed,
|
|
11443
|
+
usageOverviewEnabled,
|
|
11444
|
+
useChatMathWorker,
|
|
11445
|
+
viewMode,
|
|
11446
|
+
voiceDictationEnabled
|
|
11447
|
+
});
|
|
11022
11448
|
return [SetDom2, uid, dom];
|
|
11023
11449
|
};
|
|
11024
11450
|
|
|
@@ -11222,6 +11648,9 @@ const renderEventListeners = () => {
|
|
|
11222
11648
|
}, {
|
|
11223
11649
|
name: HandleModelChange,
|
|
11224
11650
|
params: ['handleModelChange', TargetValue]
|
|
11651
|
+
}, {
|
|
11652
|
+
name: HandleRunModeChange,
|
|
11653
|
+
params: ['handleRunModeChange', TargetValue]
|
|
11225
11654
|
}, {
|
|
11226
11655
|
name: HandleChatListScroll,
|
|
11227
11656
|
params: ['handleChatListScroll', 'event.target.scrollTop']
|
|
@@ -11367,6 +11796,13 @@ const setQuestionToolEnabled = (state, questionToolEnabled) => {
|
|
|
11367
11796
|
};
|
|
11368
11797
|
};
|
|
11369
11798
|
|
|
11799
|
+
const setShowRunMode = (state, showRunMode) => {
|
|
11800
|
+
return {
|
|
11801
|
+
...state,
|
|
11802
|
+
showRunMode
|
|
11803
|
+
};
|
|
11804
|
+
};
|
|
11805
|
+
|
|
11370
11806
|
const setStreamingEnabled = (state, streamingEnabled) => {
|
|
11371
11807
|
return {
|
|
11372
11808
|
...state,
|
|
@@ -11463,6 +11899,7 @@ const commandMap = {
|
|
|
11463
11899
|
'Chat.handleModelChange': wrapCommand(handleModelChange),
|
|
11464
11900
|
'Chat.handleProjectListContextMenu': wrapCommand(handleProjectListContextMenu),
|
|
11465
11901
|
'Chat.handleProjectListScroll': wrapCommand(handleProjectListScroll),
|
|
11902
|
+
'Chat.handleRunModeChange': wrapCommand(handleRunModeChange),
|
|
11466
11903
|
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
11467
11904
|
'Chat.initialize': initialize,
|
|
11468
11905
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
@@ -11489,6 +11926,7 @@ const commandMap = {
|
|
|
11489
11926
|
'Chat.setEmitStreamingFunctionCallEvents': wrapCommand(setEmitStreamingFunctionCallEvents),
|
|
11490
11927
|
'Chat.setOpenRouterApiKey': wrapCommand(setOpenRouterApiKey),
|
|
11491
11928
|
'Chat.setQuestionToolEnabled': wrapCommand(setQuestionToolEnabled),
|
|
11929
|
+
'Chat.setShowRunMode': wrapCommand(setShowRunMode),
|
|
11492
11930
|
'Chat.setStreamingEnabled': wrapCommand(setStreamingEnabled),
|
|
11493
11931
|
'Chat.setUseChatCoordinatorWorker': wrapCommand(setUseChatCoordinatorWorker),
|
|
11494
11932
|
'Chat.setUseChatMathWorker': wrapCommand(setUseChatMathWorker),
|