@lvce-editor/chat-view 6.9.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 +695 -460
- package/package.json +1 -1
|
@@ -1269,15 +1269,9 @@ const sendMessagePortToChatNetworkWorker = async port => {
|
|
|
1269
1269
|
const sendMessagePortToChatToolWorker = async port => {
|
|
1270
1270
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatToolWorker', port, 'HandleMessagePort.handleMessagePort');
|
|
1271
1271
|
};
|
|
1272
|
-
const writeFile = async (uri, text) => {
|
|
1273
|
-
await invoke$1('FileSystem.writeFile', uri, text);
|
|
1274
|
-
};
|
|
1275
1272
|
const activateByEvent$1 = (event, assetDir, platform) => {
|
|
1276
1273
|
return invoke$1('ExtensionHostManagement.activateByEvent', event, assetDir, platform);
|
|
1277
1274
|
};
|
|
1278
|
-
const getWorkspacePath = () => {
|
|
1279
|
-
return invoke$1('Workspace.getPath');
|
|
1280
|
-
};
|
|
1281
1275
|
const getPreference = async key => {
|
|
1282
1276
|
return await invoke$1('Preferences.get', key);
|
|
1283
1277
|
};
|
|
@@ -1670,6 +1664,10 @@ const createDefaultState = () => {
|
|
|
1670
1664
|
chatMessageFontFamily: 'system-ui',
|
|
1671
1665
|
chatMessageFontSize,
|
|
1672
1666
|
chatMessageLineHeight,
|
|
1667
|
+
chatSendAreaPaddingBottom: 10,
|
|
1668
|
+
chatSendAreaPaddingLeft: 8,
|
|
1669
|
+
chatSendAreaPaddingRight: 8,
|
|
1670
|
+
chatSendAreaPaddingTop: 10,
|
|
1673
1671
|
composerDropActive: false,
|
|
1674
1672
|
composerDropEnabled: true,
|
|
1675
1673
|
composerFontFamily: 'system-ui',
|
|
@@ -1716,6 +1714,7 @@ const createDefaultState = () => {
|
|
|
1716
1714
|
}],
|
|
1717
1715
|
questionToolEnabled: false,
|
|
1718
1716
|
renamingSessionId: '',
|
|
1717
|
+
runMode: 'local',
|
|
1719
1718
|
selectedModelId: defaultModelId,
|
|
1720
1719
|
selectedProjectId: defaultProjectId,
|
|
1721
1720
|
selectedSessionId: defaultSessionId,
|
|
@@ -1725,7 +1724,12 @@ const createDefaultState = () => {
|
|
|
1725
1724
|
projectId: defaultProjectId,
|
|
1726
1725
|
title: defaultSessionTitle()
|
|
1727
1726
|
}],
|
|
1727
|
+
showRunMode: false,
|
|
1728
1728
|
streamingEnabled: true,
|
|
1729
|
+
textAreaPaddingBottom: 0,
|
|
1730
|
+
textAreaPaddingLeft: 12,
|
|
1731
|
+
textAreaPaddingRight: 12,
|
|
1732
|
+
textAreaPaddingTop: 0,
|
|
1729
1733
|
tokensMax: 0,
|
|
1730
1734
|
tokensUsed: 0,
|
|
1731
1735
|
uid: 0,
|
|
@@ -2519,7 +2523,7 @@ const getRenderHtmlCss = (sessions, selectedSessionId) => {
|
|
|
2519
2523
|
const isEqual$1 = (oldState, newState) => {
|
|
2520
2524
|
const oldRenderHtmlCss = getRenderHtmlCss(oldState.sessions, oldState.selectedSessionId);
|
|
2521
2525
|
const newRenderHtmlCss = getRenderHtmlCss(newState.sessions, newState.selectedSessionId);
|
|
2522
|
-
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;
|
|
2523
2527
|
};
|
|
2524
2528
|
|
|
2525
2529
|
const diffFocus = (oldState, newState) => {
|
|
@@ -2541,7 +2545,7 @@ const isEqualProjectExpandedIds = (a, b) => {
|
|
|
2541
2545
|
return true;
|
|
2542
2546
|
};
|
|
2543
2547
|
const isEqual = (oldState, newState) => {
|
|
2544
|
-
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;
|
|
2545
2549
|
};
|
|
2546
2550
|
|
|
2547
2551
|
const diffScrollTop = (oldState, newState) => {
|
|
@@ -3132,12 +3136,14 @@ const selectProject = async (state, projectId) => {
|
|
|
3132
3136
|
};
|
|
3133
3137
|
};
|
|
3134
3138
|
|
|
3139
|
+
const fileSchemeRegex = /^file:\/\//;
|
|
3140
|
+
const trailingSlashesRegex$4 = /\/+$/;
|
|
3135
3141
|
const getProjectName = (uri, fallbackIndex) => {
|
|
3136
3142
|
if (!uri) {
|
|
3137
3143
|
return `Project ${fallbackIndex}`;
|
|
3138
3144
|
}
|
|
3139
|
-
const withoutScheme = uri.replace(
|
|
3140
|
-
const normalized = withoutScheme.replace(
|
|
3145
|
+
const withoutScheme = uri.replace(fileSchemeRegex, '');
|
|
3146
|
+
const normalized = withoutScheme.replace(trailingSlashesRegex$4, '');
|
|
3141
3147
|
const lastSegment = normalized.split('/').pop();
|
|
3142
3148
|
if (!lastSegment) {
|
|
3143
3149
|
return `Project ${fallbackIndex}`;
|
|
@@ -3200,6 +3206,7 @@ const update = async settings => {
|
|
|
3200
3206
|
await invoke$1('Preferences.update', settings);
|
|
3201
3207
|
};
|
|
3202
3208
|
|
|
3209
|
+
const trailingSlashesRegex$3 = /\/+$/;
|
|
3203
3210
|
const isLoginResponse = value => {
|
|
3204
3211
|
if (!value || typeof value !== 'object') {
|
|
3205
3212
|
return false;
|
|
@@ -3207,7 +3214,7 @@ const isLoginResponse = value => {
|
|
|
3207
3214
|
return true;
|
|
3208
3215
|
};
|
|
3209
3216
|
const trimTrailingSlashes = value => {
|
|
3210
|
-
return value.replace(
|
|
3217
|
+
return value.replace(trailingSlashesRegex$3, '');
|
|
3211
3218
|
};
|
|
3212
3219
|
const handleClickLogin = async state => {
|
|
3213
3220
|
if (!state.backendUrl) {
|
|
@@ -3349,240 +3356,6 @@ const getTools = async () => {
|
|
|
3349
3356
|
return invoke$3('ChatTool.getTools');
|
|
3350
3357
|
};
|
|
3351
3358
|
|
|
3352
|
-
const executeAskQuestionTool = args => {
|
|
3353
|
-
const normalized = args && typeof args === 'object' ? args : {};
|
|
3354
|
-
const question = Reflect.get(normalized, 'question');
|
|
3355
|
-
const answers = Reflect.get(normalized, 'answers');
|
|
3356
|
-
return JSON.stringify({
|
|
3357
|
-
answers: Array.isArray(answers) ? answers.filter(answer => typeof answer === 'string') : [],
|
|
3358
|
-
ok: true,
|
|
3359
|
-
question: typeof question === 'string' ? question : ''
|
|
3360
|
-
});
|
|
3361
|
-
};
|
|
3362
|
-
|
|
3363
|
-
const getToolErrorPayload = error => {
|
|
3364
|
-
const rawStack = error && typeof error === 'object' ? Reflect.get(error, 'stack') : undefined;
|
|
3365
|
-
return {
|
|
3366
|
-
error: String(error),
|
|
3367
|
-
...(typeof rawStack === 'string' && rawStack.trim() ? {
|
|
3368
|
-
errorStack: rawStack,
|
|
3369
|
-
stack: rawStack
|
|
3370
|
-
} : {})
|
|
3371
|
-
};
|
|
3372
|
-
};
|
|
3373
|
-
|
|
3374
|
-
const executeGetWorkspaceUriTool = async (_args, _options) => {
|
|
3375
|
-
try {
|
|
3376
|
-
const workspaceUri = await getWorkspacePath();
|
|
3377
|
-
return JSON.stringify({
|
|
3378
|
-
workspaceUri
|
|
3379
|
-
});
|
|
3380
|
-
} catch (error) {
|
|
3381
|
-
return JSON.stringify(getToolErrorPayload(error));
|
|
3382
|
-
}
|
|
3383
|
-
};
|
|
3384
|
-
|
|
3385
|
-
const isAbsoluteUri$1 = value => {
|
|
3386
|
-
return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value);
|
|
3387
|
-
};
|
|
3388
|
-
const executeListFilesTool = async (args, _options) => {
|
|
3389
|
-
const uri = typeof args.uri === 'string' ? args.uri : '';
|
|
3390
|
-
if (!uri || !isAbsoluteUri$1(uri)) {
|
|
3391
|
-
return JSON.stringify({
|
|
3392
|
-
error: 'Invalid argument: uri must be an absolute URI.'
|
|
3393
|
-
});
|
|
3394
|
-
}
|
|
3395
|
-
try {
|
|
3396
|
-
const entries = await invoke$1('FileSystem.readDirWithFileTypes', uri);
|
|
3397
|
-
return JSON.stringify({
|
|
3398
|
-
entries,
|
|
3399
|
-
uri
|
|
3400
|
-
});
|
|
3401
|
-
} catch (error) {
|
|
3402
|
-
return JSON.stringify({
|
|
3403
|
-
...getToolErrorPayload(error),
|
|
3404
|
-
uri
|
|
3405
|
-
});
|
|
3406
|
-
}
|
|
3407
|
-
};
|
|
3408
|
-
|
|
3409
|
-
const isPathTraversalAttempt = path => {
|
|
3410
|
-
if (!path) {
|
|
3411
|
-
return false;
|
|
3412
|
-
}
|
|
3413
|
-
if (path.startsWith('/') || path.startsWith('\\')) {
|
|
3414
|
-
return true;
|
|
3415
|
-
}
|
|
3416
|
-
if (path.startsWith('file://')) {
|
|
3417
|
-
return true;
|
|
3418
|
-
}
|
|
3419
|
-
if (/^[a-zA-Z]:[\\/]/.test(path)) {
|
|
3420
|
-
return true;
|
|
3421
|
-
}
|
|
3422
|
-
const segments = path.split(/[\\/]/);
|
|
3423
|
-
return segments.includes('..');
|
|
3424
|
-
};
|
|
3425
|
-
|
|
3426
|
-
const normalizeRelativePath = path => {
|
|
3427
|
-
const segments = path.split(/[\\/]/).filter(segment => segment && segment !== '.');
|
|
3428
|
-
if (segments.length === 0) {
|
|
3429
|
-
return '.';
|
|
3430
|
-
}
|
|
3431
|
-
return segments.join('/');
|
|
3432
|
-
};
|
|
3433
|
-
|
|
3434
|
-
const isAbsoluteUri = value => {
|
|
3435
|
-
return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value);
|
|
3436
|
-
};
|
|
3437
|
-
const executeReadFileTool = async (args, _options) => {
|
|
3438
|
-
const uri = typeof args.uri === 'string' ? args.uri : '';
|
|
3439
|
-
if (uri) {
|
|
3440
|
-
if (!isAbsoluteUri(uri)) {
|
|
3441
|
-
return JSON.stringify({
|
|
3442
|
-
error: 'Invalid argument: uri must be an absolute URI.'
|
|
3443
|
-
});
|
|
3444
|
-
}
|
|
3445
|
-
try {
|
|
3446
|
-
const content = await readFile(uri);
|
|
3447
|
-
return JSON.stringify({
|
|
3448
|
-
content,
|
|
3449
|
-
uri
|
|
3450
|
-
});
|
|
3451
|
-
} catch (error) {
|
|
3452
|
-
return JSON.stringify({
|
|
3453
|
-
...getToolErrorPayload(error),
|
|
3454
|
-
uri
|
|
3455
|
-
});
|
|
3456
|
-
}
|
|
3457
|
-
}
|
|
3458
|
-
const filePath = typeof args.path === 'string' ? args.path : '';
|
|
3459
|
-
if (!filePath || isPathTraversalAttempt(filePath)) {
|
|
3460
|
-
return JSON.stringify({
|
|
3461
|
-
error: 'Access denied: path must be relative and stay within the open workspace folder.'
|
|
3462
|
-
});
|
|
3463
|
-
}
|
|
3464
|
-
const normalizedPath = normalizeRelativePath(filePath);
|
|
3465
|
-
try {
|
|
3466
|
-
const content = await readFile(normalizedPath);
|
|
3467
|
-
return JSON.stringify({
|
|
3468
|
-
content,
|
|
3469
|
-
path: normalizedPath
|
|
3470
|
-
});
|
|
3471
|
-
} catch (error) {
|
|
3472
|
-
return JSON.stringify({
|
|
3473
|
-
...getToolErrorPayload(error),
|
|
3474
|
-
path: normalizedPath
|
|
3475
|
-
});
|
|
3476
|
-
}
|
|
3477
|
-
};
|
|
3478
|
-
|
|
3479
|
-
const maxPayloadLength = 40_000;
|
|
3480
|
-
const executeRenderHtmlTool = async (args, _options) => {
|
|
3481
|
-
const html = typeof args.html === 'string' ? args.html : '';
|
|
3482
|
-
const css = typeof args.css === 'string' ? args.css : '';
|
|
3483
|
-
const title = typeof args.title === 'string' ? args.title : '';
|
|
3484
|
-
if (!html) {
|
|
3485
|
-
return JSON.stringify({
|
|
3486
|
-
error: 'Missing required argument: html'
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
|
-
if (html.length > maxPayloadLength || css.length > maxPayloadLength) {
|
|
3490
|
-
return JSON.stringify({
|
|
3491
|
-
error: 'Payload too large: keep html/css under 40,000 characters each.'
|
|
3492
|
-
});
|
|
3493
|
-
}
|
|
3494
|
-
return JSON.stringify({
|
|
3495
|
-
css,
|
|
3496
|
-
html,
|
|
3497
|
-
ok: true,
|
|
3498
|
-
title
|
|
3499
|
-
});
|
|
3500
|
-
};
|
|
3501
|
-
|
|
3502
|
-
const toLines = value => {
|
|
3503
|
-
if (!value) {
|
|
3504
|
-
return [];
|
|
3505
|
-
}
|
|
3506
|
-
const split = value.split('\n').map(line => line.endsWith('\r') ? line.slice(0, -1) : line);
|
|
3507
|
-
if (split.length > 0 && split.at(-1) === '') {
|
|
3508
|
-
split.pop();
|
|
3509
|
-
}
|
|
3510
|
-
return split;
|
|
3511
|
-
};
|
|
3512
|
-
const getLineCounts = (before, after) => {
|
|
3513
|
-
const beforeLines = toLines(before);
|
|
3514
|
-
const afterLines = toLines(after);
|
|
3515
|
-
let start = 0;
|
|
3516
|
-
while (start < beforeLines.length && start < afterLines.length && beforeLines[start] === afterLines[start]) {
|
|
3517
|
-
start++;
|
|
3518
|
-
}
|
|
3519
|
-
let beforeEnd = beforeLines.length - 1;
|
|
3520
|
-
let afterEnd = afterLines.length - 1;
|
|
3521
|
-
while (beforeEnd >= start && afterEnd >= start && beforeLines[beforeEnd] === afterLines[afterEnd]) {
|
|
3522
|
-
beforeEnd--;
|
|
3523
|
-
afterEnd--;
|
|
3524
|
-
}
|
|
3525
|
-
return {
|
|
3526
|
-
linesAdded: Math.max(0, afterEnd - start + 1),
|
|
3527
|
-
linesDeleted: Math.max(0, beforeEnd - start + 1)
|
|
3528
|
-
};
|
|
3529
|
-
};
|
|
3530
|
-
const isFileNotFoundError = error => {
|
|
3531
|
-
const message = String(error).toLowerCase();
|
|
3532
|
-
return message.includes('enoent') || message.includes('not found');
|
|
3533
|
-
};
|
|
3534
|
-
const executeWriteFileTool = async (args, _options) => {
|
|
3535
|
-
const filePath = typeof args.path === 'string' ? args.path : '';
|
|
3536
|
-
const content = typeof args.content === 'string' ? args.content : '';
|
|
3537
|
-
if (!filePath || isPathTraversalAttempt(filePath)) {
|
|
3538
|
-
return JSON.stringify({
|
|
3539
|
-
error: 'Access denied: path must be relative and stay within the open workspace folder.'
|
|
3540
|
-
});
|
|
3541
|
-
}
|
|
3542
|
-
const normalizedPath = normalizeRelativePath(filePath);
|
|
3543
|
-
try {
|
|
3544
|
-
let previousContent = '';
|
|
3545
|
-
try {
|
|
3546
|
-
previousContent = await readFile(normalizedPath);
|
|
3547
|
-
} catch (error) {
|
|
3548
|
-
if (!isFileNotFoundError(error)) {
|
|
3549
|
-
throw error;
|
|
3550
|
-
}
|
|
3551
|
-
}
|
|
3552
|
-
await writeFile(normalizedPath, content);
|
|
3553
|
-
const {
|
|
3554
|
-
linesAdded,
|
|
3555
|
-
linesDeleted
|
|
3556
|
-
} = getLineCounts(previousContent, content);
|
|
3557
|
-
return JSON.stringify({
|
|
3558
|
-
linesAdded,
|
|
3559
|
-
linesDeleted,
|
|
3560
|
-
ok: true,
|
|
3561
|
-
path: normalizedPath
|
|
3562
|
-
});
|
|
3563
|
-
} catch (error) {
|
|
3564
|
-
return JSON.stringify({
|
|
3565
|
-
...getToolErrorPayload(error),
|
|
3566
|
-
path: normalizedPath
|
|
3567
|
-
});
|
|
3568
|
-
}
|
|
3569
|
-
};
|
|
3570
|
-
|
|
3571
|
-
const parseToolArguments = rawArguments => {
|
|
3572
|
-
if (typeof rawArguments !== 'string') {
|
|
3573
|
-
return {};
|
|
3574
|
-
}
|
|
3575
|
-
try {
|
|
3576
|
-
const parsed = JSON.parse(rawArguments);
|
|
3577
|
-
if (!parsed || typeof parsed !== 'object') {
|
|
3578
|
-
return {};
|
|
3579
|
-
}
|
|
3580
|
-
return parsed;
|
|
3581
|
-
} catch {
|
|
3582
|
-
return {};
|
|
3583
|
-
}
|
|
3584
|
-
};
|
|
3585
|
-
|
|
3586
3359
|
const stringifyToolOutput = output => {
|
|
3587
3360
|
if (typeof output === 'string') {
|
|
3588
3361
|
return output;
|
|
@@ -3590,35 +3363,14 @@ const stringifyToolOutput = output => {
|
|
|
3590
3363
|
return JSON.stringify(output) ?? 'null';
|
|
3591
3364
|
};
|
|
3592
3365
|
const executeChatTool = async (name, rawArguments, options) => {
|
|
3593
|
-
if (options.useChatToolWorker) {
|
|
3594
|
-
|
|
3595
|
-
assetDir: options.assetDir,
|
|
3596
|
-
platform: options.platform
|
|
3597
|
-
});
|
|
3598
|
-
return stringifyToolOutput(workerOutput);
|
|
3366
|
+
if (!options.useChatToolWorker) {
|
|
3367
|
+
throw new Error('Chat tools must be executed in a web worker environment. Please set useChatToolWorker to true in the options.');
|
|
3599
3368
|
}
|
|
3600
|
-
const
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
}
|
|
3604
|
-
if (name === 'write_file') {
|
|
3605
|
-
return executeWriteFileTool(args);
|
|
3606
|
-
}
|
|
3607
|
-
if (name === 'list_files') {
|
|
3608
|
-
return executeListFilesTool(args);
|
|
3609
|
-
}
|
|
3610
|
-
if (name === 'getWorkspaceUri') {
|
|
3611
|
-
return executeGetWorkspaceUriTool();
|
|
3612
|
-
}
|
|
3613
|
-
if (name === 'render_html') {
|
|
3614
|
-
return executeRenderHtmlTool(args);
|
|
3615
|
-
}
|
|
3616
|
-
if (name === 'ask_question') {
|
|
3617
|
-
return executeAskQuestionTool(args);
|
|
3618
|
-
}
|
|
3619
|
-
return JSON.stringify({
|
|
3620
|
-
error: `Unknown tool: ${name}`
|
|
3369
|
+
const workerOutput = await execute(name, rawArguments, {
|
|
3370
|
+
assetDir: options.assetDir,
|
|
3371
|
+
platform: options.platform
|
|
3621
3372
|
});
|
|
3373
|
+
return stringifyToolOutput(workerOutput);
|
|
3622
3374
|
};
|
|
3623
3375
|
|
|
3624
3376
|
const getReadFileTool = () => {
|
|
@@ -4262,6 +4014,8 @@ const getTextContent = content => {
|
|
|
4262
4014
|
|
|
4263
4015
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
4264
4016
|
|
|
4017
|
+
const errorPrefixRegex = /^Error:\s*/;
|
|
4018
|
+
const notFoundErrorRegex = /not[\s_-]?found|enoent/i;
|
|
4265
4019
|
const getOpenAiTools = tools => {
|
|
4266
4020
|
return tools.map(tool => {
|
|
4267
4021
|
if (!tool || typeof tool !== 'object') {
|
|
@@ -4327,7 +4081,7 @@ const getStreamChunkText = content => {
|
|
|
4327
4081
|
}).join('');
|
|
4328
4082
|
};
|
|
4329
4083
|
const getShortToolErrorMessage = error => {
|
|
4330
|
-
const trimmed = error.trim().replace(
|
|
4084
|
+
const trimmed = error.trim().replace(errorPrefixRegex, '');
|
|
4331
4085
|
const firstLine = trimmed.split('\n')[0];
|
|
4332
4086
|
if (firstLine.length <= 80) {
|
|
4333
4087
|
return firstLine;
|
|
@@ -4359,7 +4113,7 @@ const getToolCallExecutionStatus = content => {
|
|
|
4359
4113
|
const rawStack = Reflect.get(parsed, 'errorStack') ?? Reflect.get(parsed, 'stack');
|
|
4360
4114
|
const errorStack = typeof rawStack === 'string' && rawStack.trim() ? rawStack : undefined;
|
|
4361
4115
|
const errorMessage = getShortToolErrorMessage(rawError);
|
|
4362
|
-
if (
|
|
4116
|
+
if (notFoundErrorRegex.test(errorMessage)) {
|
|
4363
4117
|
return {
|
|
4364
4118
|
...(errorStack ? {
|
|
4365
4119
|
errorStack
|
|
@@ -5347,13 +5101,15 @@ const getOpenApiModelId = selectedModelId => {
|
|
|
5347
5101
|
return selectedModelId;
|
|
5348
5102
|
};
|
|
5349
5103
|
|
|
5104
|
+
const trailingSlashesRegex$2 = /\/+$/;
|
|
5350
5105
|
const getOpenRouterApiEndpoint = openRouterApiBaseUrl => {
|
|
5351
|
-
const trimmedBaseUrl = openRouterApiBaseUrl.replace(
|
|
5106
|
+
const trimmedBaseUrl = openRouterApiBaseUrl.replace(trailingSlashesRegex$2, '');
|
|
5352
5107
|
return `${trimmedBaseUrl}/chat/completions`;
|
|
5353
5108
|
};
|
|
5354
5109
|
|
|
5110
|
+
const trailingSlashesRegex$1 = /\/+$/;
|
|
5355
5111
|
const getOpenRouterKeyEndpoint = openRouterApiBaseUrl => {
|
|
5356
|
-
const trimmedBaseUrl = openRouterApiBaseUrl.replace(
|
|
5112
|
+
const trimmedBaseUrl = openRouterApiBaseUrl.replace(trailingSlashesRegex$1, '');
|
|
5357
5113
|
return `${trimmedBaseUrl}/auth/key`;
|
|
5358
5114
|
};
|
|
5359
5115
|
|
|
@@ -5739,8 +5495,9 @@ const getAll = () => {
|
|
|
5739
5495
|
|
|
5740
5496
|
/* eslint-disable prefer-destructuring */
|
|
5741
5497
|
|
|
5498
|
+
const trailingSlashesRegex = /\/+$/;
|
|
5742
5499
|
const getBackendCompletionsEndpoint = backendUrl => {
|
|
5743
|
-
const trimmedBackendUrl = backendUrl.replace(
|
|
5500
|
+
const trimmedBackendUrl = backendUrl.replace(trailingSlashesRegex, '');
|
|
5744
5501
|
return `${trimmedBackendUrl}/v1/chat/completions`;
|
|
5745
5502
|
};
|
|
5746
5503
|
const getEffectiveBackendModelId = selectedModelId => {
|
|
@@ -6515,21 +6272,25 @@ const parseInlineNodes = value => {
|
|
|
6515
6272
|
};
|
|
6516
6273
|
|
|
6517
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;
|
|
6518
6279
|
const normalizeEscapedNewlines = value => {
|
|
6519
6280
|
if (value.includes('\\n')) {
|
|
6520
|
-
return value.replaceAll(
|
|
6281
|
+
return value.replaceAll(escapedNewlineRegex, '\n');
|
|
6521
6282
|
}
|
|
6522
6283
|
return value;
|
|
6523
6284
|
};
|
|
6524
6285
|
const normalizeInlineTables = value => {
|
|
6525
|
-
return value.split(
|
|
6286
|
+
return value.split(lineBreakRegex).map(line => {
|
|
6526
6287
|
if (!line.includes('|')) {
|
|
6527
6288
|
return line;
|
|
6528
6289
|
}
|
|
6529
|
-
if (
|
|
6290
|
+
if (!tableDelimiterRegex.test(line)) {
|
|
6530
6291
|
return line;
|
|
6531
6292
|
}
|
|
6532
|
-
return line.replaceAll(
|
|
6293
|
+
return line.replaceAll(inlineTableCellRegex, '|\n|');
|
|
6533
6294
|
}).join('\n');
|
|
6534
6295
|
};
|
|
6535
6296
|
const parseHeadingLine = line => {
|
|
@@ -6608,6 +6369,33 @@ const parseBlockQuoteLine = line => {
|
|
|
6608
6369
|
}
|
|
6609
6370
|
return content;
|
|
6610
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
|
+
};
|
|
6611
6399
|
const isTableRow = line => {
|
|
6612
6400
|
const trimmed = line.trim();
|
|
6613
6401
|
if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) {
|
|
@@ -6621,7 +6409,7 @@ const getTableCells = line => {
|
|
|
6621
6409
|
};
|
|
6622
6410
|
const scanBlockTokens = rawMessage => {
|
|
6623
6411
|
const normalizedMessage = normalizeInlineTables(normalizeEscapedNewlines(rawMessage));
|
|
6624
|
-
const lines = normalizedMessage.split(
|
|
6412
|
+
const lines = normalizedMessage.split(lineBreakRegex);
|
|
6625
6413
|
const tokens = [];
|
|
6626
6414
|
for (let i = 0; i < lines.length; i++) {
|
|
6627
6415
|
const line = lines[i];
|
|
@@ -6687,6 +6475,12 @@ const scanBlockTokens = rawMessage => {
|
|
|
6687
6475
|
});
|
|
6688
6476
|
continue;
|
|
6689
6477
|
}
|
|
6478
|
+
if (isThematicBreakLine(line)) {
|
|
6479
|
+
tokens.push({
|
|
6480
|
+
type: 'thematic-break'
|
|
6481
|
+
});
|
|
6482
|
+
continue;
|
|
6483
|
+
}
|
|
6690
6484
|
const ordered = parseOrderedListItemLine(line);
|
|
6691
6485
|
if (ordered) {
|
|
6692
6486
|
tokens.push({
|
|
@@ -6832,6 +6626,14 @@ const parseBlockTokens = tokens => {
|
|
|
6832
6626
|
});
|
|
6833
6627
|
continue;
|
|
6834
6628
|
}
|
|
6629
|
+
if (token.type === 'thematic-break') {
|
|
6630
|
+
flushList();
|
|
6631
|
+
flushParagraph();
|
|
6632
|
+
nodes.push({
|
|
6633
|
+
type: 'thematic-break'
|
|
6634
|
+
});
|
|
6635
|
+
continue;
|
|
6636
|
+
}
|
|
6835
6637
|
if (token.type === 'blockquote-line') {
|
|
6836
6638
|
flushList();
|
|
6837
6639
|
flushParagraph();
|
|
@@ -7205,12 +7007,16 @@ const executeSlashCommand = async (state, command) => {
|
|
|
7205
7007
|
});
|
|
7206
7008
|
};
|
|
7207
7009
|
|
|
7010
|
+
const defaultSessionTitleRegex = /^Chat \d+$/;
|
|
7208
7011
|
const isDefaultSessionTitle = title => {
|
|
7209
|
-
return
|
|
7012
|
+
return defaultSessionTitleRegex.test(title);
|
|
7210
7013
|
};
|
|
7211
7014
|
|
|
7015
|
+
const titlePrefixRegex = /^title:\s*/i;
|
|
7016
|
+
const wrappedQuotesAndWhitespaceRegex = /^['"`\s]+|['"`\s]+$/g;
|
|
7017
|
+
const consecutiveWhitespaceRegex = /\s+/g;
|
|
7212
7018
|
const sanitizeGeneratedTitle = value => {
|
|
7213
|
-
return value.replace(
|
|
7019
|
+
return value.replace(titlePrefixRegex, '').replaceAll(wrappedQuotesAndWhitespaceRegex, '').replaceAll(consecutiveWhitespaceRegex, ' ').trim().slice(0, 80);
|
|
7214
7020
|
};
|
|
7215
7021
|
|
|
7216
7022
|
const getAiSessionTitle = async (state, userText, assistantText) => {
|
|
@@ -7281,14 +7087,43 @@ Assistant: ${assistantText}`;
|
|
|
7281
7087
|
return title && !isDefaultSessionTitle(title) ? title : '';
|
|
7282
7088
|
};
|
|
7283
7089
|
|
|
7090
|
+
const windowsAbsolutePathRegex = /^[a-zA-Z]:[\\/]/;
|
|
7091
|
+
const pathSeparatorRegex$1 = /[\\/]/;
|
|
7092
|
+
const isPathTraversalAttempt = path => {
|
|
7093
|
+
if (!path) {
|
|
7094
|
+
return false;
|
|
7095
|
+
}
|
|
7096
|
+
if (path.startsWith('/') || path.startsWith('\\')) {
|
|
7097
|
+
return true;
|
|
7098
|
+
}
|
|
7099
|
+
if (path.startsWith('file://')) {
|
|
7100
|
+
return true;
|
|
7101
|
+
}
|
|
7102
|
+
if (windowsAbsolutePathRegex.test(path)) {
|
|
7103
|
+
return true;
|
|
7104
|
+
}
|
|
7105
|
+
const segments = path.split(pathSeparatorRegex$1);
|
|
7106
|
+
return segments.includes('..');
|
|
7107
|
+
};
|
|
7108
|
+
|
|
7109
|
+
const pathSeparatorRegex = /[\\/]/;
|
|
7110
|
+
const normalizeRelativePath = path => {
|
|
7111
|
+
const segments = path.split(pathSeparatorRegex).filter(segment => segment && segment !== '.');
|
|
7112
|
+
if (segments.length === 0) {
|
|
7113
|
+
return '.';
|
|
7114
|
+
}
|
|
7115
|
+
return segments.join('/');
|
|
7116
|
+
};
|
|
7117
|
+
|
|
7284
7118
|
const mentionRegex = /(^|\s)@([^\s]+)/g;
|
|
7119
|
+
const trailingPunctuationRegex = /[),.;:!?]+$/g;
|
|
7285
7120
|
const maxMentionCount = 5;
|
|
7286
7121
|
const parseMentionedPaths = value => {
|
|
7287
7122
|
const matches = value.matchAll(mentionRegex);
|
|
7288
7123
|
const paths = [];
|
|
7289
7124
|
for (const match of matches) {
|
|
7290
7125
|
const rawPath = match[2] || '';
|
|
7291
|
-
const cleanedPath = rawPath.replaceAll(
|
|
7126
|
+
const cleanedPath = rawPath.replaceAll(trailingPunctuationRegex, '');
|
|
7292
7127
|
if (!cleanedPath || isPathTraversalAttempt(cleanedPath)) {
|
|
7293
7128
|
continue;
|
|
7294
7129
|
}
|
|
@@ -7816,6 +7651,7 @@ const Dictate = 'dictate';
|
|
|
7816
7651
|
const Send = 'send';
|
|
7817
7652
|
const Back = 'back';
|
|
7818
7653
|
const Model = 'model';
|
|
7654
|
+
const RunMode = 'runMode';
|
|
7819
7655
|
const ToggleChatFocus = 'toggle-chat-focus';
|
|
7820
7656
|
const CreateProject = 'create-project';
|
|
7821
7657
|
const CreateSession = 'create-session';
|
|
@@ -8333,6 +8169,19 @@ const handleProjectListContextMenu = async state => {
|
|
|
8333
8169
|
return state;
|
|
8334
8170
|
};
|
|
8335
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
|
+
|
|
8336
8185
|
const handleChatListScroll = async (state, chatListScrollTop) => {
|
|
8337
8186
|
if (state.chatListScrollTop === chatListScrollTop) {
|
|
8338
8187
|
return state;
|
|
@@ -8976,15 +8825,31 @@ const registerMockResponse = (state, mockResponse) => {
|
|
|
8976
8825
|
return state;
|
|
8977
8826
|
};
|
|
8978
8827
|
|
|
8979
|
-
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) => {
|
|
8980
8829
|
const baseCss = `:root {
|
|
8981
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;
|
|
8982
8841
|
--ChatListItemHeight: ${listItemHeight}px;
|
|
8983
8842
|
--ChatMessageFontSize: ${chatMessageFontSize}px;
|
|
8984
8843
|
--ChatMessageLineHeight: ${chatMessageLineHeight}px;
|
|
8985
8844
|
--ChatMessageFontFamily: ${chatMessageFontFamily};
|
|
8986
8845
|
}
|
|
8987
8846
|
|
|
8847
|
+
|
|
8848
|
+
.ChatSendArea{
|
|
8849
|
+
height: var(--ChatSendAreaHeight);
|
|
8850
|
+
padding: var(--ChatSendAreaPaddingTop) var(--ChatSendAreaPaddingRight) var(--ChatSendAreaPaddingBottom) var(--ChatSendAreaPaddingLeft);
|
|
8851
|
+
}
|
|
8852
|
+
|
|
8988
8853
|
.Viewlet.Chat.ChatFocus {
|
|
8989
8854
|
background: linear-gradient(180deg, var(--ColorViewBackground, #1d2229) 0%, #1f252d 100%);
|
|
8990
8855
|
display: grid;
|
|
@@ -8996,6 +8861,11 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
8996
8861
|
grid-column: 1 / 3;
|
|
8997
8862
|
}
|
|
8998
8863
|
|
|
8864
|
+
.ChatHeader .Label {
|
|
8865
|
+
text-decoration: underline;
|
|
8866
|
+
text-underline-offset: 5px;
|
|
8867
|
+
}
|
|
8868
|
+
|
|
8999
8869
|
.Chat.ChatFocus .ProjectSidebar {
|
|
9000
8870
|
background: color-mix(in srgb, var(--ColorSideBarBackground, #232b35) 88%, #1f2b38 12%);
|
|
9001
8871
|
border-right: 1px solid var(--ColorBorder, #3a3d41);
|
|
@@ -9180,7 +9050,9 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
9180
9050
|
.ChatList,
|
|
9181
9051
|
.ChatListEmpty,
|
|
9182
9052
|
.ChatMessages {
|
|
9053
|
+
margin: 0;
|
|
9183
9054
|
min-height: 0;
|
|
9055
|
+
padding: 0;
|
|
9184
9056
|
}
|
|
9185
9057
|
|
|
9186
9058
|
.Chat.ChatFocus .ChatList,
|
|
@@ -9196,6 +9068,32 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
9196
9068
|
.Chat.ChatFocus .ChatSendArea {
|
|
9197
9069
|
grid-column: 2;
|
|
9198
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;
|
|
9199
9097
|
}
|
|
9200
9098
|
|
|
9201
9099
|
.MarkdownMathInline {
|
|
@@ -9216,6 +9114,16 @@ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessage
|
|
|
9216
9114
|
overflow-y: hidden;
|
|
9217
9115
|
}
|
|
9218
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
|
+
|
|
9219
9127
|
.StrikeThrough {
|
|
9220
9128
|
text-decoration: line-through;
|
|
9221
9129
|
}
|
|
@@ -9284,14 +9192,22 @@ const renderCss = (oldState, newState) => {
|
|
|
9284
9192
|
chatMessageFontFamily,
|
|
9285
9193
|
chatMessageFontSize,
|
|
9286
9194
|
chatMessageLineHeight,
|
|
9195
|
+
chatSendAreaPaddingBottom,
|
|
9196
|
+
chatSendAreaPaddingLeft,
|
|
9197
|
+
chatSendAreaPaddingRight,
|
|
9198
|
+
chatSendAreaPaddingTop,
|
|
9287
9199
|
composerHeight,
|
|
9288
9200
|
listItemHeight,
|
|
9289
9201
|
selectedSessionId,
|
|
9290
9202
|
sessions,
|
|
9203
|
+
textAreaPaddingBottom,
|
|
9204
|
+
textAreaPaddingLeft,
|
|
9205
|
+
textAreaPaddingRight,
|
|
9206
|
+
textAreaPaddingTop,
|
|
9291
9207
|
uid
|
|
9292
9208
|
} = newState;
|
|
9293
9209
|
const renderHtmlCss = getRenderHtmlCss(sessions, selectedSessionId);
|
|
9294
|
-
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);
|
|
9295
9211
|
return [SetCss, uid, css];
|
|
9296
9212
|
};
|
|
9297
9213
|
|
|
@@ -9429,6 +9345,7 @@ const HandleProjectListScroll = 32;
|
|
|
9429
9345
|
const HandleProjectListContextMenu = 33;
|
|
9430
9346
|
const HandleClickDictationButton = 34;
|
|
9431
9347
|
const HandleMissingApiKeySubmit = 35;
|
|
9348
|
+
const HandleRunModeChange = 36;
|
|
9432
9349
|
|
|
9433
9350
|
const getModelLabel = model => {
|
|
9434
9351
|
if (model.provider === 'openRouter') {
|
|
@@ -9462,6 +9379,28 @@ const getChatSelectVirtualDom = (models, selectedModelId) => {
|
|
|
9462
9379
|
}, ...modelOptions];
|
|
9463
9380
|
};
|
|
9464
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
|
+
|
|
9465
9404
|
const getSendButtonClassName = isSendDisabled => {
|
|
9466
9405
|
return isSendDisabled ? `${IconButton} ${SendButtonDisabled}` : `${IconButton}`;
|
|
9467
9406
|
};
|
|
@@ -9529,9 +9468,9 @@ const getUsageOverviewDom = (tokensUsed, tokensMax) => {
|
|
|
9529
9468
|
}, text(usageLabel)];
|
|
9530
9469
|
};
|
|
9531
9470
|
|
|
9532
|
-
const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, voiceDictationEnabled = false) => {
|
|
9471
|
+
const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, showRunMode, runMode, voiceDictationEnabled = false) => {
|
|
9533
9472
|
const isSendDisabled = composerValue.trim() === '';
|
|
9534
|
-
const controlsCount = usageOverviewEnabled ?
|
|
9473
|
+
const controlsCount = 2 + (usageOverviewEnabled ? 1 : 0) + (showRunMode ? 1 : 0);
|
|
9535
9474
|
return [{
|
|
9536
9475
|
childCount: 1,
|
|
9537
9476
|
className: ChatSendArea,
|
|
@@ -9554,7 +9493,7 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOvervie
|
|
|
9554
9493
|
childCount: voiceDictationEnabled ? controlsCount + 1 : controlsCount,
|
|
9555
9494
|
className: ChatSendAreaBottom,
|
|
9556
9495
|
type: Div
|
|
9557
|
-
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
9496
|
+
}, ...getChatSelectVirtualDom(models, selectedModelId), ...(showRunMode ? getRunModeSelectVirtualDom(runMode) : []), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
9558
9497
|
};
|
|
9559
9498
|
|
|
9560
9499
|
const getImageAltText = alt => {
|
|
@@ -9919,6 +9858,12 @@ const getMessageNodeDom = (node, useChatMathWorker = false) => {
|
|
|
9919
9858
|
if (node.type === 'math-block-dom') {
|
|
9920
9859
|
return node.dom;
|
|
9921
9860
|
}
|
|
9861
|
+
if (node.type === 'thematic-break') {
|
|
9862
|
+
return [{
|
|
9863
|
+
childCount: 0,
|
|
9864
|
+
type: Hr
|
|
9865
|
+
}];
|
|
9866
|
+
}
|
|
9922
9867
|
if (node.type === 'heading') {
|
|
9923
9868
|
return getHeadingDom(node, useChatMathWorker);
|
|
9924
9869
|
}
|
|
@@ -10053,57 +9998,123 @@ const getOpenRouterTooManyRequestsDom = () => {
|
|
|
10053
9998
|
})];
|
|
10054
9999
|
};
|
|
10055
10000
|
|
|
10056
|
-
const
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
const stripped = uri.replace(RE_QUERY_OR_HASH, '').replace(RE_TRAILING_SLASH, '');
|
|
10060
|
-
const slashIndex = Math.max(stripped.lastIndexOf('/'), stripped.lastIndexOf('\\\\'));
|
|
10061
|
-
const fileName = slashIndex === -1 ? stripped : stripped.slice(slashIndex + 1);
|
|
10062
|
-
return fileName || uri;
|
|
10063
|
-
};
|
|
10064
|
-
|
|
10065
|
-
const isCompleteJson = value => {
|
|
10066
|
-
const trimmed = value.trim();
|
|
10067
|
-
if (!trimmed) {
|
|
10068
|
-
return false;
|
|
10001
|
+
const getToolCallStatusLabel = toolCall => {
|
|
10002
|
+
if (toolCall.status === 'not-found') {
|
|
10003
|
+
return ' (not-found)';
|
|
10069
10004
|
}
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
for (const char of trimmed) {
|
|
10074
|
-
if (inString) {
|
|
10075
|
-
if (escaped) {
|
|
10076
|
-
escaped = false;
|
|
10077
|
-
continue;
|
|
10078
|
-
}
|
|
10079
|
-
if (char === '\\') {
|
|
10080
|
-
escaped = true;
|
|
10081
|
-
continue;
|
|
10082
|
-
}
|
|
10083
|
-
if (char === '"') {
|
|
10084
|
-
inString = false;
|
|
10085
|
-
}
|
|
10086
|
-
continue;
|
|
10087
|
-
}
|
|
10088
|
-
if (char === '"') {
|
|
10089
|
-
inString = true;
|
|
10090
|
-
continue;
|
|
10091
|
-
}
|
|
10092
|
-
if (char === '{' || char === '[') {
|
|
10093
|
-
depth += 1;
|
|
10094
|
-
continue;
|
|
10095
|
-
}
|
|
10096
|
-
if (char === '}' || char === ']') {
|
|
10097
|
-
depth -= 1;
|
|
10098
|
-
if (depth < 0) {
|
|
10099
|
-
return false;
|
|
10100
|
-
}
|
|
10005
|
+
if (toolCall.status === 'error') {
|
|
10006
|
+
if (toolCall.errorMessage) {
|
|
10007
|
+
return ` (error: ${toolCall.errorMessage})`;
|
|
10101
10008
|
}
|
|
10009
|
+
return ' (error)';
|
|
10102
10010
|
}
|
|
10103
|
-
return
|
|
10011
|
+
return '';
|
|
10104
10012
|
};
|
|
10105
|
-
|
|
10106
|
-
|
|
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
|
+
|
|
10067
|
+
const RE_QUERY_OR_HASH = /[?#].*$/;
|
|
10068
|
+
const RE_TRAILING_SLASH = /\/$/;
|
|
10069
|
+
const getFileNameFromUri = uri => {
|
|
10070
|
+
const stripped = uri.replace(RE_QUERY_OR_HASH, '').replace(RE_TRAILING_SLASH, '');
|
|
10071
|
+
const slashIndex = Math.max(stripped.lastIndexOf('/'), stripped.lastIndexOf('\\\\'));
|
|
10072
|
+
const fileName = slashIndex === -1 ? stripped : stripped.slice(slashIndex + 1);
|
|
10073
|
+
return fileName || uri;
|
|
10074
|
+
};
|
|
10075
|
+
|
|
10076
|
+
const isCompleteJson = value => {
|
|
10077
|
+
const trimmed = value.trim();
|
|
10078
|
+
if (!trimmed) {
|
|
10079
|
+
return false;
|
|
10080
|
+
}
|
|
10081
|
+
let depth = 0;
|
|
10082
|
+
let inString = false;
|
|
10083
|
+
let escaped = false;
|
|
10084
|
+
for (const char of trimmed) {
|
|
10085
|
+
if (inString) {
|
|
10086
|
+
if (escaped) {
|
|
10087
|
+
escaped = false;
|
|
10088
|
+
continue;
|
|
10089
|
+
}
|
|
10090
|
+
if (char === '\\') {
|
|
10091
|
+
escaped = true;
|
|
10092
|
+
continue;
|
|
10093
|
+
}
|
|
10094
|
+
if (char === '"') {
|
|
10095
|
+
inString = false;
|
|
10096
|
+
}
|
|
10097
|
+
continue;
|
|
10098
|
+
}
|
|
10099
|
+
if (char === '"') {
|
|
10100
|
+
inString = true;
|
|
10101
|
+
continue;
|
|
10102
|
+
}
|
|
10103
|
+
if (char === '{' || char === '[') {
|
|
10104
|
+
depth += 1;
|
|
10105
|
+
continue;
|
|
10106
|
+
}
|
|
10107
|
+
if (char === '}' || char === ']') {
|
|
10108
|
+
depth -= 1;
|
|
10109
|
+
if (depth < 0) {
|
|
10110
|
+
return false;
|
|
10111
|
+
}
|
|
10112
|
+
}
|
|
10113
|
+
}
|
|
10114
|
+
return depth === 0 && !inString && !escaped;
|
|
10115
|
+
};
|
|
10116
|
+
const getReadFileTarget = rawArguments => {
|
|
10117
|
+
// Tool arguments stream in chunks, so skip parsing until a full JSON payload is available.
|
|
10107
10118
|
if (!isCompleteJson(rawArguments)) {
|
|
10108
10119
|
return undefined;
|
|
10109
10120
|
}
|
|
@@ -10132,6 +10143,58 @@ const getReadFileTarget = rawArguments => {
|
|
|
10132
10143
|
};
|
|
10133
10144
|
};
|
|
10134
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
|
+
|
|
10135
10198
|
const getToolCallArgumentPreview = rawArguments => {
|
|
10136
10199
|
if (!rawArguments.trim()) {
|
|
10137
10200
|
return '""';
|
|
@@ -10159,69 +10222,33 @@ const getToolCallArgumentPreview = rawArguments => {
|
|
|
10159
10222
|
return rawArguments;
|
|
10160
10223
|
};
|
|
10161
10224
|
|
|
10162
|
-
const
|
|
10163
|
-
if (
|
|
10164
|
-
return '
|
|
10165
|
-
}
|
|
10166
|
-
if (toolCall.status === 'error') {
|
|
10167
|
-
if (toolCall.errorMessage) {
|
|
10168
|
-
return ` (error: ${toolCall.errorMessage})`;
|
|
10169
|
-
}
|
|
10170
|
-
return ' (error)';
|
|
10225
|
+
const getToolCallDisplayName = name => {
|
|
10226
|
+
if (name === 'getWorkspaceUri') {
|
|
10227
|
+
return 'get_workspace_uri';
|
|
10171
10228
|
}
|
|
10172
|
-
return
|
|
10229
|
+
return name;
|
|
10173
10230
|
};
|
|
10174
10231
|
|
|
10175
|
-
const
|
|
10176
|
-
let parsed;
|
|
10232
|
+
const hasIncompleteJsonArguments = rawArguments => {
|
|
10177
10233
|
try {
|
|
10178
|
-
|
|
10234
|
+
JSON.parse(rawArguments);
|
|
10235
|
+
return false;
|
|
10179
10236
|
} catch {
|
|
10180
|
-
return
|
|
10181
|
-
answers: [],
|
|
10182
|
-
question: ''
|
|
10183
|
-
};
|
|
10184
|
-
}
|
|
10185
|
-
if (!parsed || typeof parsed !== 'object') {
|
|
10186
|
-
return {
|
|
10187
|
-
answers: [],
|
|
10188
|
-
question: ''
|
|
10189
|
-
};
|
|
10237
|
+
return true;
|
|
10190
10238
|
}
|
|
10191
|
-
const question = Reflect.get(parsed, 'question');
|
|
10192
|
-
const rawAnswers = Reflect.get(parsed, 'answers');
|
|
10193
|
-
const rawChoices = Reflect.get(parsed, 'choices');
|
|
10194
|
-
const rawOptions = Reflect.get(parsed, 'options');
|
|
10195
|
-
const arrayValue = Array.isArray(rawAnswers) ? rawAnswers : Array.isArray(rawChoices) ? rawChoices : Array.isArray(rawOptions) ? rawOptions : [];
|
|
10196
|
-
const answers = arrayValue.filter(value => typeof value === 'string');
|
|
10197
|
-
return {
|
|
10198
|
-
answers,
|
|
10199
|
-
question: typeof question === 'string' ? question : ''
|
|
10200
|
-
};
|
|
10201
10239
|
};
|
|
10202
|
-
|
|
10203
|
-
|
|
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);
|
|
10204
10247
|
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
return
|
|
10209
|
-
childCount,
|
|
10210
|
-
className: ChatOrderedListItem,
|
|
10211
|
-
type: Li
|
|
10212
|
-
}, {
|
|
10213
|
-
childCount: 1,
|
|
10214
|
-
className: ChatToolCallQuestionText,
|
|
10215
|
-
type: Div
|
|
10216
|
-
}, text(`ask_question: ${questionLabel}${statusLabel}`), {
|
|
10217
|
-
childCount: answers.length,
|
|
10218
|
-
className: ChatToolCallQuestionOptions,
|
|
10219
|
-
type: Div
|
|
10220
|
-
}, ...answers.flatMap(answer => [{
|
|
10221
|
-
childCount: 1,
|
|
10222
|
-
className: ChatToolCallQuestionOption,
|
|
10223
|
-
type: Span
|
|
10224
|
-
}, text(answer.trim() ? answer : '(empty answer)')])];
|
|
10248
|
+
if (argumentPreview === '{}') {
|
|
10249
|
+
return `${displayName}${statusLabel}`;
|
|
10250
|
+
}
|
|
10251
|
+
return `${displayName} ${argumentPreview}${statusLabel}`;
|
|
10225
10252
|
};
|
|
10226
10253
|
|
|
10227
10254
|
const getToolCallReadFileVirtualDom = toolCall => {
|
|
@@ -10256,16 +10283,24 @@ const getToolCallReadFileVirtualDom = toolCall => {
|
|
|
10256
10283
|
const maxHtmlLength = 40_000;
|
|
10257
10284
|
const tokenRegex = /<!--[\s\S]*?-->|<\/?[a-zA-Z][\w:-]*(?:\s[^<>]*?)?>|[^<]+/g;
|
|
10258
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:-]*)/;
|
|
10259
10294
|
const inlineTags = new Set(['a', 'abbr', 'b', 'code', 'em', 'i', 'label', 'small', 'span', 'strong', 'sub', 'sup', 'u']);
|
|
10260
10295
|
const voidElements = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
|
|
10261
10296
|
const sanitizeHtml = value => {
|
|
10262
|
-
return value.slice(0, maxHtmlLength).replaceAll(
|
|
10297
|
+
return value.slice(0, maxHtmlLength).replaceAll(scriptTagRegex, '').replaceAll(styleTagRegex, '').replaceAll(headTagRegex, '').replaceAll(metaTagRegex, '').replaceAll(linkTagRegex, '');
|
|
10263
10298
|
};
|
|
10264
10299
|
const decodeEntities = value => {
|
|
10265
10300
|
return value.replaceAll(' ', ' ').replaceAll('"', '"').replaceAll(''', "'").replaceAll('<', '<').replaceAll('>', '>').replaceAll('&', '&');
|
|
10266
10301
|
};
|
|
10267
10302
|
const parseAttributes = token => {
|
|
10268
|
-
const withoutTag = token.replace(
|
|
10303
|
+
const withoutTag = token.replace(tagPrefixRegex, '').replace(tagSuffixRegex, '').trim();
|
|
10269
10304
|
if (!withoutTag) {
|
|
10270
10305
|
return Object.create(null);
|
|
10271
10306
|
}
|
|
@@ -10312,7 +10347,7 @@ const parseHtml = value => {
|
|
|
10312
10347
|
continue;
|
|
10313
10348
|
}
|
|
10314
10349
|
if (token.startsWith('<')) {
|
|
10315
|
-
const openTagNameMatch =
|
|
10350
|
+
const openTagNameMatch = openTagNameRegex.exec(token);
|
|
10316
10351
|
if (!openTagNameMatch) {
|
|
10317
10352
|
continue;
|
|
10318
10353
|
}
|
|
@@ -10556,55 +10591,6 @@ const getToolCallRenderHtmlVirtualDom = toolCall => {
|
|
|
10556
10591
|
}, ...parsedHtml.virtualDom];
|
|
10557
10592
|
};
|
|
10558
10593
|
|
|
10559
|
-
const getToolCallDisplayName = name => {
|
|
10560
|
-
if (name === 'getWorkspaceUri') {
|
|
10561
|
-
return 'get_workspace_uri';
|
|
10562
|
-
}
|
|
10563
|
-
return name;
|
|
10564
|
-
};
|
|
10565
|
-
const hasIncompleteJsonArguments = rawArguments => {
|
|
10566
|
-
try {
|
|
10567
|
-
JSON.parse(rawArguments);
|
|
10568
|
-
return false;
|
|
10569
|
-
} catch {
|
|
10570
|
-
return true;
|
|
10571
|
-
}
|
|
10572
|
-
};
|
|
10573
|
-
const getToolCallLabel = toolCall => {
|
|
10574
|
-
const displayName = getToolCallDisplayName(toolCall.name);
|
|
10575
|
-
if (toolCall.name === 'write_file' && !toolCall.status && hasIncompleteJsonArguments(toolCall.arguments)) {
|
|
10576
|
-
return `${displayName} (in progress)`;
|
|
10577
|
-
}
|
|
10578
|
-
const argumentPreview = getToolCallArgumentPreview(toolCall.arguments);
|
|
10579
|
-
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10580
|
-
if (argumentPreview === '{}') {
|
|
10581
|
-
return `${displayName}${statusLabel}`;
|
|
10582
|
-
}
|
|
10583
|
-
return `${displayName} ${argumentPreview}${statusLabel}`;
|
|
10584
|
-
};
|
|
10585
|
-
const getToolCallGetWorkspaceUriVirtualDom = toolCall => {
|
|
10586
|
-
if (!toolCall.result) {
|
|
10587
|
-
return [];
|
|
10588
|
-
}
|
|
10589
|
-
const statusLabel = getToolCallStatusLabel(toolCall);
|
|
10590
|
-
const fileName = getFileNameFromUri(toolCall.result);
|
|
10591
|
-
return [{
|
|
10592
|
-
childCount: statusLabel ? 4 : 3,
|
|
10593
|
-
className: ChatOrderedListItem,
|
|
10594
|
-
title: toolCall.result,
|
|
10595
|
-
type: Li
|
|
10596
|
-
}, {
|
|
10597
|
-
childCount: 0,
|
|
10598
|
-
className: FileIcon,
|
|
10599
|
-
type: Div
|
|
10600
|
-
}, text('get_workspace_uri '), {
|
|
10601
|
-
childCount: 1,
|
|
10602
|
-
className: ChatToolCallReadFileLink,
|
|
10603
|
-
'data-uri': toolCall.result,
|
|
10604
|
-
onClick: HandleClickReadFile,
|
|
10605
|
-
type: Span
|
|
10606
|
-
}, text(fileName), ...(statusLabel ? [text(statusLabel)] : [])];
|
|
10607
|
-
};
|
|
10608
10594
|
const parseWriteFileLineCounts = rawResult => {
|
|
10609
10595
|
if (!rawResult) {
|
|
10610
10596
|
return {
|
|
@@ -10634,6 +10620,7 @@ const parseWriteFileLineCounts = rawResult => {
|
|
|
10634
10620
|
linesDeleted: typeof linesDeleted === 'number' ? Math.max(0, linesDeleted) : 0
|
|
10635
10621
|
};
|
|
10636
10622
|
};
|
|
10623
|
+
|
|
10637
10624
|
const getToolCallWriteFileVirtualDom = toolCall => {
|
|
10638
10625
|
const target = getReadFileTarget(toolCall.arguments);
|
|
10639
10626
|
if (!target) {
|
|
@@ -10673,6 +10660,7 @@ const getToolCallWriteFileVirtualDom = toolCall => {
|
|
|
10673
10660
|
type: Span
|
|
10674
10661
|
}, text(` -${linesDeleted}`), ...(statusLabel ? [text(statusLabel)] : [])];
|
|
10675
10662
|
};
|
|
10663
|
+
|
|
10676
10664
|
const getToolCallDom = toolCall => {
|
|
10677
10665
|
if (toolCall.name === 'getWorkspaceUri') {
|
|
10678
10666
|
const virtualDom = getToolCallGetWorkspaceUriVirtualDom(toolCall);
|
|
@@ -10692,6 +10680,12 @@ const getToolCallDom = toolCall => {
|
|
|
10692
10680
|
return virtualDom;
|
|
10693
10681
|
}
|
|
10694
10682
|
}
|
|
10683
|
+
if (toolCall.name === 'edit_file') {
|
|
10684
|
+
const virtualDom = getToolCallEditFileVirtualDom(toolCall);
|
|
10685
|
+
if (virtualDom.length > 0) {
|
|
10686
|
+
return virtualDom;
|
|
10687
|
+
}
|
|
10688
|
+
}
|
|
10695
10689
|
if (toolCall.name === 'render_html') {
|
|
10696
10690
|
const virtualDom = getToolCallRenderHtmlVirtualDom(toolCall);
|
|
10697
10691
|
if (virtualDom.length > 0) {
|
|
@@ -10801,9 +10795,9 @@ const getDisplayMessages = (messages, parsedMessages) => {
|
|
|
10801
10795
|
}
|
|
10802
10796
|
return displayMessages;
|
|
10803
10797
|
};
|
|
10804
|
-
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) => {
|
|
10805
10799
|
if (messages.length === 0) {
|
|
10806
|
-
return getEmptyMessagesDom();
|
|
10800
|
+
return hideWelcomeMessage ? [] : getEmptyMessagesDom();
|
|
10807
10801
|
}
|
|
10808
10802
|
const displayMessages = getDisplayMessages(messages, parsedMessages);
|
|
10809
10803
|
return [{
|
|
@@ -10901,7 +10895,38 @@ const getProjectListDom = (projects, sessions, projectExpandedIds, selectedProje
|
|
|
10901
10895
|
}, text('+ Add Project')];
|
|
10902
10896
|
};
|
|
10903
10897
|
|
|
10904
|
-
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
|
+
}) => {
|
|
10905
10930
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
10906
10931
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
10907
10932
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
@@ -10911,7 +10936,7 @@ const getChatModeChatFocusVirtualDom = (sessions, selectedSessionId, composerVal
|
|
|
10911
10936
|
onDragEnter: HandleDragEnterChatView,
|
|
10912
10937
|
onDragOver: HandleDragOverChatView,
|
|
10913
10938
|
type: Div
|
|
10914
|
-
}, ...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 ? [{
|
|
10915
10940
|
childCount: 1,
|
|
10916
10941
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
10917
10942
|
name: ComposerDropTarget,
|
|
@@ -11027,7 +11052,34 @@ const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, a
|
|
|
11027
11052
|
}, text(authErrorMessage)] : [])];
|
|
11028
11053
|
};
|
|
11029
11054
|
|
|
11030
|
-
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
|
+
}) => {
|
|
11031
11083
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
11032
11084
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
11033
11085
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
@@ -11038,7 +11090,7 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
|
|
|
11038
11090
|
onDragEnter: HandleDragEnterChatView,
|
|
11039
11091
|
onDragOver: HandleDragOverChatView,
|
|
11040
11092
|
type: Div
|
|
11041
|
-
}, ...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 ? [{
|
|
11042
11094
|
childCount: 1,
|
|
11043
11095
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
11044
11096
|
name: ComposerDropTarget,
|
|
@@ -11086,7 +11138,7 @@ const getSessionDom = session => {
|
|
|
11086
11138
|
return [{
|
|
11087
11139
|
childCount: 2,
|
|
11088
11140
|
className: sessionClassName,
|
|
11089
|
-
type:
|
|
11141
|
+
type: Li
|
|
11090
11142
|
}, {
|
|
11091
11143
|
childCount: 1,
|
|
11092
11144
|
className: ChatListItemLabel,
|
|
@@ -11120,11 +11172,33 @@ const getChatListDom = (sessions, selectedSessionId, chatListScrollTop = 0) => {
|
|
|
11120
11172
|
onClick: HandleClickList,
|
|
11121
11173
|
onScroll: HandleChatListScroll,
|
|
11122
11174
|
scrollTop: chatListScrollTop,
|
|
11123
|
-
type:
|
|
11175
|
+
type: Ul
|
|
11124
11176
|
}, ...sessions.flatMap(getSessionDom)];
|
|
11125
11177
|
};
|
|
11126
11178
|
|
|
11127
|
-
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
|
+
}) => {
|
|
11128
11202
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
11129
11203
|
return [{
|
|
11130
11204
|
childCount: isDropOverlayVisible ? 4 : 3,
|
|
@@ -11132,7 +11206,7 @@ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, m
|
|
|
11132
11206
|
onDragEnter: HandleDragEnterChatView,
|
|
11133
11207
|
onDragOver: HandleDragOverChatView,
|
|
11134
11208
|
type: Div
|
|
11135
|
-
}, ...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 ? [{
|
|
11136
11210
|
childCount: 1,
|
|
11137
11211
|
className: mergeClassNames(ChatViewDropOverlay, ChatViewDropOverlayActive),
|
|
11138
11212
|
name: ComposerDropTarget,
|
|
@@ -11169,15 +11243,129 @@ const getFallbackParsedMessages = sessions => {
|
|
|
11169
11243
|
}
|
|
11170
11244
|
return parsedMessages;
|
|
11171
11245
|
};
|
|
11172
|
-
const getChatVirtualDom =
|
|
11173
|
-
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);
|
|
11174
11282
|
switch (viewMode) {
|
|
11175
11283
|
case 'chat-focus':
|
|
11176
|
-
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
|
+
});
|
|
11177
11316
|
case 'detail':
|
|
11178
|
-
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
|
+
});
|
|
11179
11345
|
case 'list':
|
|
11180
|
-
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
|
+
});
|
|
11181
11369
|
default:
|
|
11182
11370
|
return getChatModeUnsupportedVirtualDom();
|
|
11183
11371
|
}
|
|
@@ -11206,10 +11394,12 @@ const renderItems = (oldState, newState) => {
|
|
|
11206
11394
|
projectExpandedIds,
|
|
11207
11395
|
projectListScrollTop,
|
|
11208
11396
|
projects,
|
|
11397
|
+
runMode,
|
|
11209
11398
|
selectedModelId,
|
|
11210
11399
|
selectedProjectId,
|
|
11211
11400
|
selectedSessionId,
|
|
11212
11401
|
sessions,
|
|
11402
|
+
showRunMode,
|
|
11213
11403
|
tokensMax,
|
|
11214
11404
|
tokensUsed,
|
|
11215
11405
|
uid,
|
|
@@ -11221,7 +11411,40 @@ const renderItems = (oldState, newState) => {
|
|
|
11221
11411
|
if (initial) {
|
|
11222
11412
|
return [SetDom2, uid, []];
|
|
11223
11413
|
}
|
|
11224
|
-
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
|
+
});
|
|
11225
11448
|
return [SetDom2, uid, dom];
|
|
11226
11449
|
};
|
|
11227
11450
|
|
|
@@ -11425,6 +11648,9 @@ const renderEventListeners = () => {
|
|
|
11425
11648
|
}, {
|
|
11426
11649
|
name: HandleModelChange,
|
|
11427
11650
|
params: ['handleModelChange', TargetValue]
|
|
11651
|
+
}, {
|
|
11652
|
+
name: HandleRunModeChange,
|
|
11653
|
+
params: ['handleRunModeChange', TargetValue]
|
|
11428
11654
|
}, {
|
|
11429
11655
|
name: HandleChatListScroll,
|
|
11430
11656
|
params: ['handleChatListScroll', 'event.target.scrollTop']
|
|
@@ -11570,6 +11796,13 @@ const setQuestionToolEnabled = (state, questionToolEnabled) => {
|
|
|
11570
11796
|
};
|
|
11571
11797
|
};
|
|
11572
11798
|
|
|
11799
|
+
const setShowRunMode = (state, showRunMode) => {
|
|
11800
|
+
return {
|
|
11801
|
+
...state,
|
|
11802
|
+
showRunMode
|
|
11803
|
+
};
|
|
11804
|
+
};
|
|
11805
|
+
|
|
11573
11806
|
const setStreamingEnabled = (state, streamingEnabled) => {
|
|
11574
11807
|
return {
|
|
11575
11808
|
...state,
|
|
@@ -11666,6 +11899,7 @@ const commandMap = {
|
|
|
11666
11899
|
'Chat.handleModelChange': wrapCommand(handleModelChange),
|
|
11667
11900
|
'Chat.handleProjectListContextMenu': wrapCommand(handleProjectListContextMenu),
|
|
11668
11901
|
'Chat.handleProjectListScroll': wrapCommand(handleProjectListScroll),
|
|
11902
|
+
'Chat.handleRunModeChange': wrapCommand(handleRunModeChange),
|
|
11669
11903
|
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
11670
11904
|
'Chat.initialize': initialize,
|
|
11671
11905
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
@@ -11692,6 +11926,7 @@ const commandMap = {
|
|
|
11692
11926
|
'Chat.setEmitStreamingFunctionCallEvents': wrapCommand(setEmitStreamingFunctionCallEvents),
|
|
11693
11927
|
'Chat.setOpenRouterApiKey': wrapCommand(setOpenRouterApiKey),
|
|
11694
11928
|
'Chat.setQuestionToolEnabled': wrapCommand(setQuestionToolEnabled),
|
|
11929
|
+
'Chat.setShowRunMode': wrapCommand(setShowRunMode),
|
|
11695
11930
|
'Chat.setStreamingEnabled': wrapCommand(setStreamingEnabled),
|
|
11696
11931
|
'Chat.setUseChatCoordinatorWorker': wrapCommand(setUseChatCoordinatorWorker),
|
|
11697
11932
|
'Chat.setUseChatMathWorker': wrapCommand(setUseChatMathWorker),
|