@lvce-editor/chat-view 6.69.0 → 7.0.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 +1068 -233
- package/package.json +1 -1
|
@@ -1775,6 +1775,17 @@ const clearInput = async state => {
|
|
|
1775
1775
|
};
|
|
1776
1776
|
};
|
|
1777
1777
|
|
|
1778
|
+
const closeGitBranchPicker = state => {
|
|
1779
|
+
if (!state.gitBranchPickerOpen && !state.gitBranchPickerErrorMessage) {
|
|
1780
|
+
return state;
|
|
1781
|
+
}
|
|
1782
|
+
return {
|
|
1783
|
+
...state,
|
|
1784
|
+
gitBranchPickerErrorMessage: '',
|
|
1785
|
+
gitBranchPickerOpen: false
|
|
1786
|
+
};
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1778
1789
|
const clampSelectionIndex = (value, max) => {
|
|
1779
1790
|
if (!Number.isFinite(value)) {
|
|
1780
1791
|
return 0;
|
|
@@ -1852,6 +1863,7 @@ const BackToChatList = 'Back to chat list';
|
|
|
1852
1863
|
const Search$1 = 'Search';
|
|
1853
1864
|
const ScrollDown$1 = 'Scroll down';
|
|
1854
1865
|
const SearchModels = 'Search models';
|
|
1866
|
+
const PickModel = 'Pick Model';
|
|
1855
1867
|
const SearchChats = 'Search chats';
|
|
1856
1868
|
const Paste = 'Paste';
|
|
1857
1869
|
const Rename = 'Rename';
|
|
@@ -1859,9 +1871,13 @@ const Archive = 'Archive';
|
|
|
1859
1871
|
const AddProjectChat = 'Add Project';
|
|
1860
1872
|
const RemoveProject = 'Remove Project';
|
|
1861
1873
|
const Settings$1 = 'Settings';
|
|
1874
|
+
const Login$1 = 'Login';
|
|
1875
|
+
const Logout$1 = 'Logout';
|
|
1862
1876
|
const LoginToBackend = 'Login to backend';
|
|
1863
1877
|
const LogoutFromBackend = 'Logout from backend';
|
|
1864
1878
|
const LoggingInToBackend = 'Logging in to backend';
|
|
1879
|
+
const LoggingOutFromBackend = 'Logging out from backend';
|
|
1880
|
+
const SignedIn = 'Signed in';
|
|
1865
1881
|
const SwitchToChatFocusMode = 'Switch to chat focus mode';
|
|
1866
1882
|
const SwitchToNormalChatMode = 'Switch to normal chat mode';
|
|
1867
1883
|
const CloseChat$1 = 'Close Chat';
|
|
@@ -1941,18 +1957,33 @@ const scrollDown = () => {
|
|
|
1941
1957
|
const searchModels = () => {
|
|
1942
1958
|
return i18nString(SearchModels);
|
|
1943
1959
|
};
|
|
1960
|
+
const pickModel = modelName => {
|
|
1961
|
+
return `${i18nString(PickModel)}, ${modelName}`;
|
|
1962
|
+
};
|
|
1944
1963
|
const searchChats = () => {
|
|
1945
1964
|
return i18nString(SearchChats);
|
|
1946
1965
|
};
|
|
1966
|
+
const login = () => {
|
|
1967
|
+
return i18nString(Login$1);
|
|
1968
|
+
};
|
|
1969
|
+
const logout = () => {
|
|
1970
|
+
return i18nString(Logout$1);
|
|
1971
|
+
};
|
|
1947
1972
|
const loginToBackend = () => {
|
|
1948
1973
|
return i18nString(LoginToBackend);
|
|
1949
1974
|
};
|
|
1950
|
-
const logoutFromBackend = () => {
|
|
1975
|
+
const logoutFromBackend$1 = () => {
|
|
1951
1976
|
return i18nString(LogoutFromBackend);
|
|
1952
1977
|
};
|
|
1953
1978
|
const loggingInToBackend = () => {
|
|
1954
1979
|
return i18nString(LoggingInToBackend);
|
|
1955
1980
|
};
|
|
1981
|
+
const loggingOutFromBackend = () => {
|
|
1982
|
+
return i18nString(LoggingOutFromBackend);
|
|
1983
|
+
};
|
|
1984
|
+
const signedIn = () => {
|
|
1985
|
+
return i18nString(SignedIn);
|
|
1986
|
+
};
|
|
1956
1987
|
const chatFocusMode = () => {
|
|
1957
1988
|
return i18nString(SwitchToChatFocusMode);
|
|
1958
1989
|
};
|
|
@@ -2324,8 +2355,6 @@ const createDefaultState = () => {
|
|
|
2324
2355
|
authAccessToken: '',
|
|
2325
2356
|
authEnabled: false,
|
|
2326
2357
|
authErrorMessage: '',
|
|
2327
|
-
authRefreshToken: '',
|
|
2328
|
-
authStatus: 'signed-out',
|
|
2329
2358
|
backendUrl: '',
|
|
2330
2359
|
chatFocusContentMaxWidth: 700,
|
|
2331
2360
|
chatHistoryEnabled: true,
|
|
@@ -2357,6 +2386,10 @@ const createDefaultState = () => {
|
|
|
2357
2386
|
errorCount: 0,
|
|
2358
2387
|
focus: 'composer',
|
|
2359
2388
|
focused: false,
|
|
2389
|
+
gitBranches: [],
|
|
2390
|
+
gitBranchPickerErrorMessage: '',
|
|
2391
|
+
gitBranchPickerOpen: false,
|
|
2392
|
+
gitBranchPickerVisible: false,
|
|
2360
2393
|
headerHeight: 50,
|
|
2361
2394
|
height: 0,
|
|
2362
2395
|
...responsivePickerState,
|
|
@@ -2443,6 +2476,7 @@ const createDefaultState = () => {
|
|
|
2443
2476
|
useChatToolWorker: true,
|
|
2444
2477
|
useMockApi: false,
|
|
2445
2478
|
userName: '',
|
|
2479
|
+
userState: 'loggedOut',
|
|
2446
2480
|
userSubscriptionPlan: '',
|
|
2447
2481
|
userUsedTokens: 0,
|
|
2448
2482
|
viewMode: 'list',
|
|
@@ -2829,7 +2863,24 @@ const isEqualComposerAttachments = (a, b) => {
|
|
|
2829
2863
|
}
|
|
2830
2864
|
return true;
|
|
2831
2865
|
};
|
|
2866
|
+
const isEqualGitBranches = (a, b) => {
|
|
2867
|
+
if (a === b) {
|
|
2868
|
+
return true;
|
|
2869
|
+
}
|
|
2870
|
+
if (a.length !== b.length) {
|
|
2871
|
+
return false;
|
|
2872
|
+
}
|
|
2873
|
+
for (let i = 0; i < a.length; i++) {
|
|
2874
|
+
if (a[i].current !== b[i].current || a[i].name !== b[i].name) {
|
|
2875
|
+
return false;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
return true;
|
|
2879
|
+
};
|
|
2832
2880
|
const isEqualProjectExpandedIds = (a, b) => {
|
|
2881
|
+
if (a === b) {
|
|
2882
|
+
return true;
|
|
2883
|
+
}
|
|
2833
2884
|
if (a.length !== b.length) {
|
|
2834
2885
|
return false;
|
|
2835
2886
|
}
|
|
@@ -2840,6 +2891,20 @@ const isEqualProjectExpandedIds = (a, b) => {
|
|
|
2840
2891
|
}
|
|
2841
2892
|
return true;
|
|
2842
2893
|
};
|
|
2894
|
+
const isEqualProjects = (a, b) => {
|
|
2895
|
+
if (a === b) {
|
|
2896
|
+
return true;
|
|
2897
|
+
}
|
|
2898
|
+
if (a.length !== b.length) {
|
|
2899
|
+
return false;
|
|
2900
|
+
}
|
|
2901
|
+
for (let i = 0; i < a.length; i++) {
|
|
2902
|
+
if (a[i].id !== b[i].id || a[i].name !== b[i].name || a[i].uri !== b[i].uri) {
|
|
2903
|
+
return false;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
return true;
|
|
2907
|
+
};
|
|
2843
2908
|
const isEqualVisibleModels = (a, b) => {
|
|
2844
2909
|
if (a === b) {
|
|
2845
2910
|
return true;
|
|
@@ -2856,7 +2921,7 @@ const isEqualVisibleModels = (a, b) => {
|
|
|
2856
2921
|
};
|
|
2857
2922
|
|
|
2858
2923
|
const isEqual = (oldState, newState) => {
|
|
2859
|
-
return oldState.addContextButtonEnabled === newState.addContextButtonEnabled && oldState.agentMode === newState.agentMode && oldState.agentModePickerOpen === newState.agentModePickerOpen && oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage &&
|
|
2924
|
+
return oldState.addContextButtonEnabled === newState.addContextButtonEnabled && oldState.agentMode === newState.agentMode && oldState.agentModePickerOpen === newState.agentModePickerOpen && oldState.authEnabled === newState.authEnabled && oldState.authErrorMessage === newState.authErrorMessage && isEqualComposerAttachments(oldState.composerAttachments, newState.composerAttachments) && oldState.composerDropActive === newState.composerDropActive && oldState.composerDropEnabled === newState.composerDropEnabled && oldState.composerValue === newState.composerValue && oldState.gitBranchPickerErrorMessage === newState.gitBranchPickerErrorMessage && oldState.gitBranchPickerOpen === newState.gitBranchPickerOpen && oldState.gitBranchPickerVisible === newState.gitBranchPickerVisible && isEqualGitBranches(oldState.gitBranches, newState.gitBranches) && oldState.hasSpaceForAgentModePicker === newState.hasSpaceForAgentModePicker && oldState.hasSpaceForRunModePicker === newState.hasSpaceForRunModePicker && oldState.initial === newState.initial && oldState.modelPickerOpen === newState.modelPickerOpen && oldState.modelPickerSearchValue === newState.modelPickerSearchValue && isEqualVisibleModels(oldState.visibleModels, newState.visibleModels) && oldState.listFocusedIndex === newState.listFocusedIndex && oldState.openApiApiKeyInput === newState.openApiApiKeyInput && oldState.openRouterApiKeyInput === newState.openRouterApiKeyInput && isEqualProjectExpandedIds(oldState.projectExpandedIds, newState.projectExpandedIds) && isEqualProjects(oldState.projects, newState.projects) && oldState.reasoningEffort === newState.reasoningEffort && oldState.reasoningEffortPickerOpen === newState.reasoningEffortPickerOpen && oldState.reasoningPickerEnabled === newState.reasoningPickerEnabled && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedProjectId === newState.selectedProjectId && oldState.selectedSessionId === newState.selectedSessionId && oldState.searchEnabled === newState.searchEnabled && oldState.searchFieldVisible === newState.searchFieldVisible && oldState.searchValue === newState.searchValue && oldState.showRunMode === newState.showRunMode && oldState.runMode === newState.runMode && oldState.runModePickerOpen === newState.runModePickerOpen && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.useChatMathWorker === newState.useChatMathWorker && oldState.userName === newState.userName && oldState.userState === newState.userState && oldState.viewMode === newState.viewMode && oldState.voiceDictationEnabled === newState.voiceDictationEnabled;
|
|
2860
2925
|
};
|
|
2861
2926
|
|
|
2862
2927
|
const diffScrollTop = (oldState, newState) => {
|
|
@@ -2877,6 +2942,12 @@ const RenderIncremental = 11;
|
|
|
2877
2942
|
const RenderScrollTop = 12;
|
|
2878
2943
|
|
|
2879
2944
|
const diffValue = (oldState, newState) => {
|
|
2945
|
+
if (oldState.openApiApiKeyInput !== newState.openApiApiKeyInput) {
|
|
2946
|
+
return false;
|
|
2947
|
+
}
|
|
2948
|
+
if (oldState.openRouterApiKeyInput !== newState.openRouterApiKeyInput) {
|
|
2949
|
+
return false;
|
|
2950
|
+
}
|
|
2880
2951
|
return oldState.composerValue === newState.composerValue || newState.inputSource !== 'script';
|
|
2881
2952
|
};
|
|
2882
2953
|
|
|
@@ -2907,10 +2978,9 @@ const getAuthState = state => {
|
|
|
2907
2978
|
authAccessToken,
|
|
2908
2979
|
authEnabled,
|
|
2909
2980
|
authErrorMessage,
|
|
2910
|
-
authRefreshToken,
|
|
2911
|
-
authStatus,
|
|
2912
2981
|
backendUrl,
|
|
2913
2982
|
userName,
|
|
2983
|
+
userState,
|
|
2914
2984
|
userSubscriptionPlan,
|
|
2915
2985
|
userUsedTokens
|
|
2916
2986
|
} = state;
|
|
@@ -2918,10 +2988,9 @@ const getAuthState = state => {
|
|
|
2918
2988
|
authAccessToken,
|
|
2919
2989
|
authEnabled,
|
|
2920
2990
|
authErrorMessage,
|
|
2921
|
-
authRefreshToken,
|
|
2922
|
-
authStatus,
|
|
2923
2991
|
backendUrl,
|
|
2924
2992
|
userName,
|
|
2993
|
+
userState,
|
|
2925
2994
|
userSubscriptionPlan,
|
|
2926
2995
|
userUsedTokens
|
|
2927
2996
|
};
|
|
@@ -3387,9 +3456,11 @@ const ComposerAttachmentPreviewOverlay = 'composer-attachment-preview-overlay';
|
|
|
3387
3456
|
const AddContext = 'add-context';
|
|
3388
3457
|
const Dictate = 'dictate';
|
|
3389
3458
|
const CreatePullRequest$1 = 'create-pull-request';
|
|
3459
|
+
const GitBranchPickerToggle = 'git-branch-picker-toggle';
|
|
3460
|
+
const GitBranchPickerItemPrefix = 'git-branch-picker-item:';
|
|
3390
3461
|
const FocusAddAction = 'focus-add-action';
|
|
3391
|
-
const FocusOpenInVsCode = 'focus-open-in-vscode';
|
|
3392
3462
|
const FocusCommit = 'focus-commit';
|
|
3463
|
+
const FocusOpenInVsCode = 'focus-open-in-vscode';
|
|
3393
3464
|
const FocusOpenTerminal = 'focus-open-terminal';
|
|
3394
3465
|
const FocusShowDiff = 'focus-show-diff';
|
|
3395
3466
|
const Send = 'send';
|
|
@@ -3458,6 +3529,15 @@ const getRenameIdFromInputName = name => {
|
|
|
3458
3529
|
const getModelPickerItemInputName = modelId => {
|
|
3459
3530
|
return `${ModelPickerItemPrefix}${modelId}`;
|
|
3460
3531
|
};
|
|
3532
|
+
const getGitBranchPickerItemInputName = branchName => {
|
|
3533
|
+
return `${GitBranchPickerItemPrefix}${branchName}`;
|
|
3534
|
+
};
|
|
3535
|
+
const isGitBranchPickerItemInputName = name => {
|
|
3536
|
+
return name.startsWith(GitBranchPickerItemPrefix);
|
|
3537
|
+
};
|
|
3538
|
+
const getGitBranchFromGitBranchPickerItemInputName = name => {
|
|
3539
|
+
return name.slice(GitBranchPickerItemPrefix.length);
|
|
3540
|
+
};
|
|
3461
3541
|
const getComposerAttachmentInputName = attachmentId => {
|
|
3462
3542
|
return `${ComposerAttachmentPrefix}${attachmentId}`;
|
|
3463
3543
|
};
|
|
@@ -3818,6 +3898,236 @@ const openFolder = async () => {
|
|
|
3818
3898
|
}
|
|
3819
3899
|
};
|
|
3820
3900
|
|
|
3901
|
+
// cspell:ignore gitdir worktrees
|
|
3902
|
+
const FileTypeFile = 1;
|
|
3903
|
+
const FileTypeDirectory = 2;
|
|
3904
|
+
const slashAtEndRegex = /\/$/;
|
|
3905
|
+
const gitDirPointerRegex = /^gitdir:\s*(.+)$/m;
|
|
3906
|
+
const headRefRegex = /^ref:\s+refs\/heads\/(.+)$/m;
|
|
3907
|
+
const toGitUri = (baseUri, ...segments) => {
|
|
3908
|
+
const url = new URL(baseUri.endsWith('/') ? baseUri : `${baseUri}/`);
|
|
3909
|
+
for (const segment of segments) {
|
|
3910
|
+
url.pathname = `${url.pathname.replace(slashAtEndRegex, '')}/${segment.split('/').map(part => encodeURIComponent(part)).join('/')}`;
|
|
3911
|
+
}
|
|
3912
|
+
return url.toString();
|
|
3913
|
+
};
|
|
3914
|
+
const decodeFileContent = content => {
|
|
3915
|
+
if (typeof content === 'string') {
|
|
3916
|
+
return content;
|
|
3917
|
+
}
|
|
3918
|
+
if (content instanceof Uint8Array) {
|
|
3919
|
+
return new TextDecoder().decode(content);
|
|
3920
|
+
}
|
|
3921
|
+
if (Array.isArray(content)) {
|
|
3922
|
+
return new TextDecoder().decode(new Uint8Array(content));
|
|
3923
|
+
}
|
|
3924
|
+
return '';
|
|
3925
|
+
};
|
|
3926
|
+
const toFileSystemPath = uri => {
|
|
3927
|
+
if (!uri.startsWith('file://')) {
|
|
3928
|
+
return uri;
|
|
3929
|
+
}
|
|
3930
|
+
return decodeURIComponent(new URL(uri).pathname);
|
|
3931
|
+
};
|
|
3932
|
+
const getRelativePath = (fromPath, toPath) => {
|
|
3933
|
+
if (!fromPath.startsWith('/') || !toPath.startsWith('/')) {
|
|
3934
|
+
return toPath;
|
|
3935
|
+
}
|
|
3936
|
+
const fromParts = fromPath.split('/').filter(Boolean);
|
|
3937
|
+
const toParts = toPath.split('/').filter(Boolean);
|
|
3938
|
+
let commonPrefixLength = 0;
|
|
3939
|
+
while (commonPrefixLength < fromParts.length && commonPrefixLength < toParts.length && fromParts[commonPrefixLength] === toParts[commonPrefixLength]) {
|
|
3940
|
+
commonPrefixLength++;
|
|
3941
|
+
}
|
|
3942
|
+
const parentSegments = fromParts.slice(commonPrefixLength).map(() => '..');
|
|
3943
|
+
const childSegments = toParts.slice(commonPrefixLength);
|
|
3944
|
+
return [...parentSegments, ...childSegments].join('/') || '.';
|
|
3945
|
+
};
|
|
3946
|
+
const toFileSystemTarget = (workspaceUri, uri) => {
|
|
3947
|
+
const workspacePath = toFileSystemPath(workspaceUri);
|
|
3948
|
+
const fileSystemPath = toFileSystemPath(uri);
|
|
3949
|
+
if (!workspaceUri.startsWith('file://') || !uri.startsWith('file://')) {
|
|
3950
|
+
return fileSystemPath;
|
|
3951
|
+
}
|
|
3952
|
+
return getRelativePath(workspacePath, fileSystemPath);
|
|
3953
|
+
};
|
|
3954
|
+
const parseEntries = value => {
|
|
3955
|
+
if (!Array.isArray(value)) {
|
|
3956
|
+
return [];
|
|
3957
|
+
}
|
|
3958
|
+
return value.map(entry => {
|
|
3959
|
+
if (Array.isArray(entry) && typeof entry[0] === 'string' && typeof entry[1] === 'number') {
|
|
3960
|
+
return {
|
|
3961
|
+
name: entry[0],
|
|
3962
|
+
type: entry[1]
|
|
3963
|
+
};
|
|
3964
|
+
}
|
|
3965
|
+
if (entry && typeof entry === 'object' && typeof Reflect.get(entry, 'name') === 'string' && typeof Reflect.get(entry, 'type') === 'number') {
|
|
3966
|
+
return {
|
|
3967
|
+
name: Reflect.get(entry, 'name'),
|
|
3968
|
+
type: Reflect.get(entry, 'type')
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3971
|
+
return undefined;
|
|
3972
|
+
}).filter(entry => !!entry);
|
|
3973
|
+
};
|
|
3974
|
+
const readDir = async (workspaceUri, uri) => {
|
|
3975
|
+
const result = await invoke('FileSystem.readDirWithFileTypes', toFileSystemTarget(workspaceUri, uri));
|
|
3976
|
+
return parseEntries(result);
|
|
3977
|
+
};
|
|
3978
|
+
const readTextFile = async (workspaceUri, uri) => {
|
|
3979
|
+
const result = await invoke('FileSystem.readFile', toFileSystemTarget(workspaceUri, uri));
|
|
3980
|
+
return decodeFileContent(result);
|
|
3981
|
+
};
|
|
3982
|
+
const getGitDirUri = async workspaceUri => {
|
|
3983
|
+
const gitUri = toGitUri(workspaceUri, '.git');
|
|
3984
|
+
try {
|
|
3985
|
+
await readTextFile(workspaceUri, toGitUri(gitUri, 'HEAD'));
|
|
3986
|
+
return gitUri;
|
|
3987
|
+
} catch {
|
|
3988
|
+
// Fall through to support worktrees/submodules where .git is a pointer file.
|
|
3989
|
+
}
|
|
3990
|
+
const gitPointer = await readTextFile(workspaceUri, gitUri);
|
|
3991
|
+
const match = gitDirPointerRegex.exec(gitPointer);
|
|
3992
|
+
if (!match) {
|
|
3993
|
+
return '';
|
|
3994
|
+
}
|
|
3995
|
+
return new URL(match[1].trim(), workspaceUri.endsWith('/') ? workspaceUri : `${workspaceUri}/`).toString();
|
|
3996
|
+
};
|
|
3997
|
+
const collectBranchNames = async (workspaceUri, refsHeadsUri, prefix, branches) => {
|
|
3998
|
+
const entries = await readDir(workspaceUri, refsHeadsUri);
|
|
3999
|
+
for (const entry of entries) {
|
|
4000
|
+
if (entry.type === FileTypeDirectory) {
|
|
4001
|
+
await collectBranchNames(workspaceUri, toGitUri(refsHeadsUri, entry.name), `${prefix}${entry.name}/`, branches);
|
|
4002
|
+
continue;
|
|
4003
|
+
}
|
|
4004
|
+
if (entry.type === FileTypeFile) {
|
|
4005
|
+
branches.add(`${prefix}${entry.name}`);
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
};
|
|
4009
|
+
const parseCurrentBranch = headContent => {
|
|
4010
|
+
const match = headRefRegex.exec(headContent.trim());
|
|
4011
|
+
if (match) {
|
|
4012
|
+
return match[1].trim();
|
|
4013
|
+
}
|
|
4014
|
+
return '';
|
|
4015
|
+
};
|
|
4016
|
+
const hasGitRepository = async workspaceUri => {
|
|
4017
|
+
try {
|
|
4018
|
+
return Boolean(await getGitDirUri(workspaceUri));
|
|
4019
|
+
} catch {
|
|
4020
|
+
return false;
|
|
4021
|
+
}
|
|
4022
|
+
};
|
|
4023
|
+
const getGitBranches = async workspaceUri => {
|
|
4024
|
+
const gitDirUri = await getGitDirUri(workspaceUri);
|
|
4025
|
+
if (!gitDirUri) {
|
|
4026
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
4027
|
+
throw new globalThis.Error('Git repository not found.');
|
|
4028
|
+
}
|
|
4029
|
+
const branches = new Set();
|
|
4030
|
+
let currentBranch = '';
|
|
4031
|
+
try {
|
|
4032
|
+
const headContent = await readTextFile(workspaceUri, toGitUri(gitDirUri, 'HEAD'));
|
|
4033
|
+
currentBranch = parseCurrentBranch(headContent);
|
|
4034
|
+
if (currentBranch) {
|
|
4035
|
+
branches.add(currentBranch);
|
|
4036
|
+
}
|
|
4037
|
+
} catch {
|
|
4038
|
+
// Keep trying to discover branches from refs even if HEAD cannot be read.
|
|
4039
|
+
}
|
|
4040
|
+
try {
|
|
4041
|
+
await collectBranchNames(workspaceUri, toGitUri(gitDirUri, 'refs', 'heads'), '', branches);
|
|
4042
|
+
} catch {
|
|
4043
|
+
// Repositories without local refs should still open and surface any current branch we found.
|
|
4044
|
+
}
|
|
4045
|
+
if (branches.size === 0) {
|
|
4046
|
+
// eslint-disable-next-line @typescript-eslint/only-throw-error
|
|
4047
|
+
throw new globalThis.Error('No local git branches found.');
|
|
4048
|
+
}
|
|
4049
|
+
return [...branches].toSorted((a, b) => a.localeCompare(b)).map(name => ({
|
|
4050
|
+
current: name === currentBranch,
|
|
4051
|
+
name
|
|
4052
|
+
}));
|
|
4053
|
+
};
|
|
4054
|
+
|
|
4055
|
+
const getSelectedSession = (sessions, selectedSessionId) => {
|
|
4056
|
+
return sessions.find(session => session.id === selectedSessionId);
|
|
4057
|
+
};
|
|
4058
|
+
|
|
4059
|
+
const getProjectUri$1 = (state, projectId) => {
|
|
4060
|
+
return state.projects.find(project => project.id === projectId)?.uri || '';
|
|
4061
|
+
};
|
|
4062
|
+
const getWorkspaceUri$1 = (state, session) => {
|
|
4063
|
+
if (session?.workspaceUri) {
|
|
4064
|
+
return session.workspaceUri;
|
|
4065
|
+
}
|
|
4066
|
+
return getProjectUri$1(state, session?.projectId || state.selectedProjectId);
|
|
4067
|
+
};
|
|
4068
|
+
|
|
4069
|
+
const withHiddenBranchPicker = state => {
|
|
4070
|
+
return {
|
|
4071
|
+
...state,
|
|
4072
|
+
gitBranches: [],
|
|
4073
|
+
gitBranchPickerErrorMessage: '',
|
|
4074
|
+
gitBranchPickerOpen: false,
|
|
4075
|
+
gitBranchPickerVisible: false
|
|
4076
|
+
};
|
|
4077
|
+
};
|
|
4078
|
+
const refreshGitBranchPickerVisibility = async state => {
|
|
4079
|
+
if (state.viewMode !== 'chat-focus') {
|
|
4080
|
+
return {
|
|
4081
|
+
...state,
|
|
4082
|
+
gitBranchPickerErrorMessage: '',
|
|
4083
|
+
gitBranchPickerOpen: false
|
|
4084
|
+
};
|
|
4085
|
+
}
|
|
4086
|
+
const selectedSession = getSelectedSession(state.sessions, state.selectedSessionId);
|
|
4087
|
+
const fallbackBranchName = selectedSession?.branchName || '';
|
|
4088
|
+
const workspaceUri = getWorkspaceUri$1(state, selectedSession);
|
|
4089
|
+
if (!workspaceUri) {
|
|
4090
|
+
return withHiddenBranchPicker(state);
|
|
4091
|
+
}
|
|
4092
|
+
const visible = await hasGitRepository(workspaceUri);
|
|
4093
|
+
if (!visible) {
|
|
4094
|
+
if (fallbackBranchName) {
|
|
4095
|
+
return {
|
|
4096
|
+
...state,
|
|
4097
|
+
gitBranches: [{
|
|
4098
|
+
current: true,
|
|
4099
|
+
name: fallbackBranchName
|
|
4100
|
+
}],
|
|
4101
|
+
gitBranchPickerVisible: true
|
|
4102
|
+
};
|
|
4103
|
+
}
|
|
4104
|
+
return withHiddenBranchPicker(state);
|
|
4105
|
+
}
|
|
4106
|
+
try {
|
|
4107
|
+
const gitBranches = await getGitBranches(workspaceUri);
|
|
4108
|
+
return {
|
|
4109
|
+
...state,
|
|
4110
|
+
gitBranches,
|
|
4111
|
+
gitBranchPickerVisible: true
|
|
4112
|
+
};
|
|
4113
|
+
} catch {
|
|
4114
|
+
if (fallbackBranchName) {
|
|
4115
|
+
return {
|
|
4116
|
+
...state,
|
|
4117
|
+
gitBranches: [{
|
|
4118
|
+
current: true,
|
|
4119
|
+
name: fallbackBranchName
|
|
4120
|
+
}],
|
|
4121
|
+
gitBranchPickerVisible: true
|
|
4122
|
+
};
|
|
4123
|
+
}
|
|
4124
|
+
return {
|
|
4125
|
+
...state,
|
|
4126
|
+
gitBranchPickerVisible: true
|
|
4127
|
+
};
|
|
4128
|
+
}
|
|
4129
|
+
};
|
|
4130
|
+
|
|
3821
4131
|
const selectProject = async (state, projectId) => {
|
|
3822
4132
|
const {
|
|
3823
4133
|
selectedProjectId,
|
|
@@ -3831,14 +4141,14 @@ const selectProject = async (state, projectId) => {
|
|
|
3831
4141
|
}
|
|
3832
4142
|
const visibleSessions = getVisibleSessions(sessions, projectId);
|
|
3833
4143
|
if (visibleSessions.length === 0) {
|
|
3834
|
-
return {
|
|
4144
|
+
return refreshGitBranchPickerVisibility({
|
|
3835
4145
|
...state,
|
|
3836
4146
|
composerAttachments: [],
|
|
3837
4147
|
composerAttachmentsHeight: 0,
|
|
3838
4148
|
selectedProjectId: projectId,
|
|
3839
4149
|
selectedSessionId: '',
|
|
3840
4150
|
viewMode: viewMode === 'chat-focus' ? 'chat-focus' : 'list'
|
|
3841
|
-
};
|
|
4151
|
+
});
|
|
3842
4152
|
}
|
|
3843
4153
|
const currentSessionVisible = visibleSessions.some(session => session.id === selectedSessionId);
|
|
3844
4154
|
const nextSelectedSessionId = currentSessionVisible ? selectedSessionId : visibleSessions[0].id;
|
|
@@ -3850,7 +4160,7 @@ const selectProject = async (state, projectId) => {
|
|
|
3850
4160
|
}
|
|
3851
4161
|
return loadedSession;
|
|
3852
4162
|
});
|
|
3853
|
-
return {
|
|
4163
|
+
return refreshGitBranchPickerVisibility({
|
|
3854
4164
|
...state,
|
|
3855
4165
|
composerAttachments,
|
|
3856
4166
|
composerAttachmentsHeight: getComposerAttachmentsHeight(composerAttachments, width),
|
|
@@ -3858,7 +4168,7 @@ const selectProject = async (state, projectId) => {
|
|
|
3858
4168
|
selectedSessionId: nextSelectedSessionId,
|
|
3859
4169
|
sessions: hydratedSessions,
|
|
3860
4170
|
viewMode: viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
3861
|
-
};
|
|
4171
|
+
});
|
|
3862
4172
|
};
|
|
3863
4173
|
|
|
3864
4174
|
const fileSchemeRegex = /^file:\/\//;
|
|
@@ -3993,6 +4303,148 @@ const handleClickCreatePullRequest = async state => {
|
|
|
3993
4303
|
};
|
|
3994
4304
|
};
|
|
3995
4305
|
|
|
4306
|
+
const trailingSlashesRegex$3 = /\/+$/;
|
|
4307
|
+
const trimTrailingSlashes = value => {
|
|
4308
|
+
return value.replace(trailingSlashesRegex$3, '');
|
|
4309
|
+
};
|
|
4310
|
+
|
|
4311
|
+
const getBackendAuthUrl = (backendUrl, path) => {
|
|
4312
|
+
return `${trimTrailingSlashes(backendUrl)}${path}`;
|
|
4313
|
+
};
|
|
4314
|
+
|
|
4315
|
+
const getBackendLoginUrl = backendUrl => {
|
|
4316
|
+
return getBackendAuthUrl(backendUrl, '/auth/login');
|
|
4317
|
+
};
|
|
4318
|
+
|
|
4319
|
+
const getLoggedOutBackendAuthState = (authErrorMessage = '') => {
|
|
4320
|
+
return {
|
|
4321
|
+
authAccessToken: '',
|
|
4322
|
+
authErrorMessage,
|
|
4323
|
+
userName: '',
|
|
4324
|
+
userState: 'loggedOut',
|
|
4325
|
+
userSubscriptionPlan: '',
|
|
4326
|
+
userUsedTokens: 0
|
|
4327
|
+
};
|
|
4328
|
+
};
|
|
4329
|
+
|
|
4330
|
+
const getBackendLogoutUrl = backendUrl => {
|
|
4331
|
+
return getBackendAuthUrl(backendUrl, '/auth/logout');
|
|
4332
|
+
};
|
|
4333
|
+
|
|
4334
|
+
const logoutFromBackend = async backendUrl => {
|
|
4335
|
+
if (!backendUrl) {
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
try {
|
|
4339
|
+
await fetch(getBackendLogoutUrl(backendUrl), {
|
|
4340
|
+
credentials: 'include',
|
|
4341
|
+
headers: {
|
|
4342
|
+
Accept: 'application/json'
|
|
4343
|
+
},
|
|
4344
|
+
method: 'POST'
|
|
4345
|
+
});
|
|
4346
|
+
} catch {
|
|
4347
|
+
// Ignore logout failures and still clear local auth state.
|
|
4348
|
+
}
|
|
4349
|
+
};
|
|
4350
|
+
|
|
4351
|
+
const getBackendRefreshUrl = backendUrl => {
|
|
4352
|
+
return getBackendAuthUrl(backendUrl, '/auth/refresh');
|
|
4353
|
+
};
|
|
4354
|
+
|
|
4355
|
+
const isObject$2 = value => {
|
|
4356
|
+
return !!value && typeof value === 'object';
|
|
4357
|
+
};
|
|
4358
|
+
|
|
4359
|
+
const isBackendAuthResponse = value => {
|
|
4360
|
+
return isObject$2(value);
|
|
4361
|
+
};
|
|
4362
|
+
|
|
4363
|
+
const getNumber = (value, fallback = 0) => {
|
|
4364
|
+
return typeof value === 'number' ? value : fallback;
|
|
4365
|
+
};
|
|
4366
|
+
|
|
4367
|
+
const getString = (value, fallback = '') => {
|
|
4368
|
+
return typeof value === 'string' ? value : fallback;
|
|
4369
|
+
};
|
|
4370
|
+
|
|
4371
|
+
const toBackendAuthState = value => {
|
|
4372
|
+
return {
|
|
4373
|
+
authAccessToken: getString(value.accessToken),
|
|
4374
|
+
authErrorMessage: getString(value.error),
|
|
4375
|
+
userName: getString(value.userName),
|
|
4376
|
+
userState: value.accessToken ? 'loggedIn' : 'loggedOut',
|
|
4377
|
+
userSubscriptionPlan: getString(value.subscriptionPlan),
|
|
4378
|
+
userUsedTokens: getNumber(value.usedTokens)
|
|
4379
|
+
};
|
|
4380
|
+
};
|
|
4381
|
+
|
|
4382
|
+
const parseBackendAuthResponse = value => {
|
|
4383
|
+
if (!isBackendAuthResponse(value)) {
|
|
4384
|
+
return getLoggedOutBackendAuthState('Backend returned an invalid authentication response.');
|
|
4385
|
+
}
|
|
4386
|
+
return toBackendAuthState(value);
|
|
4387
|
+
};
|
|
4388
|
+
|
|
4389
|
+
const syncBackendAuth = async backendUrl => {
|
|
4390
|
+
if (!backendUrl) {
|
|
4391
|
+
return getLoggedOutBackendAuthState('Backend URL is missing.');
|
|
4392
|
+
}
|
|
4393
|
+
try {
|
|
4394
|
+
const response = await fetch(getBackendRefreshUrl(backendUrl), {
|
|
4395
|
+
credentials: 'include',
|
|
4396
|
+
headers: {
|
|
4397
|
+
Accept: 'application/json'
|
|
4398
|
+
},
|
|
4399
|
+
method: 'POST'
|
|
4400
|
+
});
|
|
4401
|
+
if (response.status === 401 || response.status === 403) {
|
|
4402
|
+
return getLoggedOutBackendAuthState();
|
|
4403
|
+
}
|
|
4404
|
+
let payload = undefined;
|
|
4405
|
+
try {
|
|
4406
|
+
payload = await response.json();
|
|
4407
|
+
} catch {
|
|
4408
|
+
payload = undefined;
|
|
4409
|
+
}
|
|
4410
|
+
if (!response.ok) {
|
|
4411
|
+
const parsed = parseBackendAuthResponse(payload);
|
|
4412
|
+
return getLoggedOutBackendAuthState(parsed.authErrorMessage || 'Backend authentication failed.');
|
|
4413
|
+
}
|
|
4414
|
+
const parsed = parseBackendAuthResponse(payload);
|
|
4415
|
+
if (parsed.authErrorMessage) {
|
|
4416
|
+
return getLoggedOutBackendAuthState(parsed.authErrorMessage);
|
|
4417
|
+
}
|
|
4418
|
+
if (!parsed.authAccessToken) {
|
|
4419
|
+
return getLoggedOutBackendAuthState();
|
|
4420
|
+
}
|
|
4421
|
+
return parsed;
|
|
4422
|
+
} catch (error) {
|
|
4423
|
+
const authErrorMessage = error instanceof Error && error.message ? error.message : 'Backend authentication failed.';
|
|
4424
|
+
return getLoggedOutBackendAuthState(authErrorMessage);
|
|
4425
|
+
}
|
|
4426
|
+
};
|
|
4427
|
+
|
|
4428
|
+
const delay = async ms => {
|
|
4429
|
+
await new Promise(resolve => setTimeout(resolve, ms));
|
|
4430
|
+
};
|
|
4431
|
+
|
|
4432
|
+
const waitForBackendLogin = async (backendUrl, timeoutMs = 30_000, pollIntervalMs = 1000) => {
|
|
4433
|
+
const deadline = Date.now() + timeoutMs;
|
|
4434
|
+
let lastErrorMessage = '';
|
|
4435
|
+
while (Date.now() < deadline) {
|
|
4436
|
+
const authState = await syncBackendAuth(backendUrl);
|
|
4437
|
+
if (authState.userState === 'loggedIn') {
|
|
4438
|
+
return authState;
|
|
4439
|
+
}
|
|
4440
|
+
if (authState.authErrorMessage) {
|
|
4441
|
+
lastErrorMessage = authState.authErrorMessage;
|
|
4442
|
+
}
|
|
4443
|
+
await delay(pollIntervalMs);
|
|
4444
|
+
}
|
|
4445
|
+
return getLoggedOutBackendAuthState(lastErrorMessage);
|
|
4446
|
+
};
|
|
4447
|
+
|
|
3996
4448
|
let nextLoginResponse;
|
|
3997
4449
|
const setNextLoginResponse = response => {
|
|
3998
4450
|
nextLoginResponse = response;
|
|
@@ -4016,35 +4468,36 @@ const consumeNextLoginResponse = async () => {
|
|
|
4016
4468
|
return response.response;
|
|
4017
4469
|
};
|
|
4018
4470
|
|
|
4019
|
-
const get = async key => {
|
|
4020
|
-
return getPreference(key);
|
|
4021
|
-
};
|
|
4022
|
-
const update = async settings => {
|
|
4023
|
-
await invoke('Preferences.update', settings);
|
|
4024
|
-
};
|
|
4025
|
-
|
|
4026
|
-
const trailingSlashesRegex$3 = /\/+$/;
|
|
4027
4471
|
const isLoginResponse = value => {
|
|
4028
4472
|
if (!value || typeof value !== 'object') {
|
|
4029
4473
|
return false;
|
|
4030
4474
|
}
|
|
4031
4475
|
return true;
|
|
4032
4476
|
};
|
|
4033
|
-
const
|
|
4034
|
-
|
|
4477
|
+
const getLoggedInState = (state, response) => {
|
|
4478
|
+
const accessToken = typeof response.accessToken === 'string' ? response.accessToken : '';
|
|
4479
|
+
return {
|
|
4480
|
+
...state,
|
|
4481
|
+
authAccessToken: accessToken,
|
|
4482
|
+
authErrorMessage: '',
|
|
4483
|
+
userName: typeof response.userName === 'string' ? response.userName : state.userName,
|
|
4484
|
+
userState: accessToken ? 'loggedIn' : 'loggedOut',
|
|
4485
|
+
userSubscriptionPlan: typeof response.subscriptionPlan === 'string' ? response.subscriptionPlan : state.userSubscriptionPlan,
|
|
4486
|
+
userUsedTokens: typeof response.usedTokens === 'number' ? response.usedTokens : state.userUsedTokens
|
|
4487
|
+
};
|
|
4035
4488
|
};
|
|
4036
4489
|
const handleClickLogin = async state => {
|
|
4037
4490
|
if (!state.backendUrl) {
|
|
4038
4491
|
return {
|
|
4039
4492
|
...state,
|
|
4040
4493
|
authErrorMessage: 'Backend URL is missing.',
|
|
4041
|
-
|
|
4494
|
+
userState: 'loggedOut'
|
|
4042
4495
|
};
|
|
4043
4496
|
}
|
|
4044
4497
|
const signingInState = {
|
|
4045
4498
|
...state,
|
|
4046
4499
|
authErrorMessage: '',
|
|
4047
|
-
|
|
4500
|
+
userState: 'loggingIn'
|
|
4048
4501
|
};
|
|
4049
4502
|
if (state.uid) {
|
|
4050
4503
|
set(state.uid, state, signingInState);
|
|
@@ -4053,69 +4506,53 @@ const handleClickLogin = async state => {
|
|
|
4053
4506
|
let usedMockResponse = false;
|
|
4054
4507
|
try {
|
|
4055
4508
|
usedMockResponse = hasPendingMockLoginResponse();
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4509
|
+
if (usedMockResponse) {
|
|
4510
|
+
const response = await consumeNextLoginResponse();
|
|
4511
|
+
if (!isLoginResponse(response)) {
|
|
4512
|
+
return {
|
|
4513
|
+
...signingInState,
|
|
4514
|
+
authErrorMessage: 'Backend returned an invalid login response.',
|
|
4515
|
+
userState: 'loggedOut'
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4518
|
+
if (typeof response.error === 'string' && response.error) {
|
|
4519
|
+
return {
|
|
4520
|
+
...signingInState,
|
|
4521
|
+
authErrorMessage: response.error,
|
|
4522
|
+
userState: 'loggedOut'
|
|
4523
|
+
};
|
|
4524
|
+
}
|
|
4525
|
+
return getLoggedInState(signingInState, response);
|
|
4070
4526
|
}
|
|
4071
|
-
|
|
4072
|
-
const
|
|
4073
|
-
await update({
|
|
4074
|
-
'secrets.chatBackendAccessToken': accessToken,
|
|
4075
|
-
'secrets.chatBackendRefreshToken': refreshToken
|
|
4076
|
-
});
|
|
4527
|
+
await invoke('Main.openUri', getBackendLoginUrl(state.backendUrl));
|
|
4528
|
+
const authState = await waitForBackendLogin(state.backendUrl);
|
|
4077
4529
|
return {
|
|
4078
4530
|
...signingInState,
|
|
4079
|
-
|
|
4080
|
-
authErrorMessage: '',
|
|
4081
|
-
authRefreshToken: refreshToken,
|
|
4082
|
-
authStatus: accessToken ? 'signed-in' : 'signed-out',
|
|
4083
|
-
userName: typeof response.userName === 'string' ? response.userName : state.userName,
|
|
4084
|
-
userSubscriptionPlan: typeof response.subscriptionPlan === 'string' ? response.subscriptionPlan : state.userSubscriptionPlan,
|
|
4085
|
-
userUsedTokens: typeof response.usedTokens === 'number' ? response.usedTokens : state.userUsedTokens
|
|
4531
|
+
...authState
|
|
4086
4532
|
};
|
|
4087
4533
|
} catch (error) {
|
|
4088
4534
|
const errorMessage = error instanceof Error && error.message ? error.message : 'Backend authentication failed.';
|
|
4089
|
-
if (!usedMockResponse) {
|
|
4090
|
-
await invoke('Main.openUri', `${trimTrailingSlashes(state.backendUrl)}/auth/login`);
|
|
4091
|
-
}
|
|
4092
4535
|
return {
|
|
4093
4536
|
...signingInState,
|
|
4094
|
-
|
|
4095
|
-
authStatus: 'signed-out'
|
|
4537
|
+
...getLoggedOutBackendAuthState(errorMessage)
|
|
4096
4538
|
};
|
|
4097
4539
|
}
|
|
4098
4540
|
};
|
|
4099
4541
|
|
|
4100
4542
|
const handleClickLogout = async state => {
|
|
4101
|
-
|
|
4102
|
-
await invoke('Auth.logout', state.backendUrl);
|
|
4103
|
-
} catch {
|
|
4104
|
-
// Ignore logout bridge errors and still clear local auth state.
|
|
4105
|
-
}
|
|
4106
|
-
await update({
|
|
4107
|
-
'secrets.chatBackendAccessToken': '',
|
|
4108
|
-
'secrets.chatBackendRefreshToken': ''
|
|
4109
|
-
});
|
|
4110
|
-
return {
|
|
4543
|
+
const loggingOutState = {
|
|
4111
4544
|
...state,
|
|
4112
|
-
authAccessToken: '',
|
|
4113
4545
|
authErrorMessage: '',
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4546
|
+
userState: 'loggingOut'
|
|
4547
|
+
};
|
|
4548
|
+
if (state.uid) {
|
|
4549
|
+
set(state.uid, state, loggingOutState);
|
|
4550
|
+
await invoke('Chat.rerender');
|
|
4551
|
+
}
|
|
4552
|
+
await logoutFromBackend(state.backendUrl);
|
|
4553
|
+
return {
|
|
4554
|
+
...loggingOutState,
|
|
4555
|
+
...getLoggedOutBackendAuthState()
|
|
4119
4556
|
};
|
|
4120
4557
|
};
|
|
4121
4558
|
|
|
@@ -4440,10 +4877,6 @@ const getClientRequestIdHeader = () => {
|
|
|
4440
4877
|
};
|
|
4441
4878
|
};
|
|
4442
4879
|
|
|
4443
|
-
const delay = async ms => {
|
|
4444
|
-
await new Promise(resolve => setTimeout(resolve, ms));
|
|
4445
|
-
};
|
|
4446
|
-
|
|
4447
4880
|
const getMockAiResponse = async (userMessage, delayInMs) => {
|
|
4448
4881
|
await delay(delayInMs);
|
|
4449
4882
|
return `Mock AI response: I received "${userMessage}".`;
|
|
@@ -6830,7 +7263,12 @@ const ChatFocusActions = 'ChatFocusActions';
|
|
|
6830
7263
|
const ChatFocusHeader = 'ChatFocusHeader';
|
|
6831
7264
|
const ChatFocusMainArea = 'ChatFocusMainArea';
|
|
6832
7265
|
const ChatFocusProject = 'ChatFocusProject';
|
|
7266
|
+
const ChatGitBranchPicker = 'ChatGitBranchPicker';
|
|
7267
|
+
const ChatGitBranchPickerErrorMessage = 'ChatGitBranchPickerErrorMessage';
|
|
7268
|
+
const ChatGitBranchPickerMessage = 'ChatGitBranchPickerMessage';
|
|
6833
7269
|
const ChatHeader = 'ChatHeader';
|
|
7270
|
+
const ChatHeaderAuth = 'ChatHeaderAuth';
|
|
7271
|
+
const ChatHeaderAuthName = 'ChatHeaderAuthName';
|
|
6834
7272
|
const ChatHeaderLabel = 'ChatHeaderLabel';
|
|
6835
7273
|
const ChatInputBox = 'ChatInputBox';
|
|
6836
7274
|
const ChatList = 'ChatList';
|
|
@@ -6844,6 +7282,7 @@ const ChatListItemStatusInProgress = 'ChatListItemStatusInProgress';
|
|
|
6844
7282
|
const ChatListItemStatusRow = 'ChatListItemStatusRow';
|
|
6845
7283
|
const ChatListItemStatusStopped = 'ChatListItemStatusStopped';
|
|
6846
7284
|
const ChatMessageContent = 'ChatMessageContent';
|
|
7285
|
+
const ChatImageMessageContent = 'ChatImageMessageContent';
|
|
6847
7286
|
const ChatMessageLink = 'ChatMessageLink';
|
|
6848
7287
|
const ChatModelPicker = 'ChatModelPicker';
|
|
6849
7288
|
const ChatModelPickerContainer = 'ChatModelPickerContainer';
|
|
@@ -6878,6 +7317,7 @@ const ChatAttachmentLabel = 'ChatAttachmentLabel';
|
|
|
6878
7317
|
const ChatAttachmentPreview = 'ChatAttachmentPreview';
|
|
6879
7318
|
const ChatAttachments = 'ChatAttachments';
|
|
6880
7319
|
const ChatAttachmentTextFile = 'ChatAttachmentTextFile';
|
|
7320
|
+
const ChatMessageImage = 'ChatMessageImage';
|
|
6881
7321
|
const ChatSendArea = 'ChatSendArea';
|
|
6882
7322
|
const ChatSendAreaBottom = 'ChatSendAreaBottom';
|
|
6883
7323
|
const ChatSendAreaContent = 'ChatSendAreaContent';
|
|
@@ -6915,6 +7355,7 @@ const IconButtonDisabled = 'IconButtonDisabled';
|
|
|
6915
7355
|
const ImageElement = 'ImageElement';
|
|
6916
7356
|
const ImageErrorMessage = 'ImageErrorMessage';
|
|
6917
7357
|
const InputBox = 'InputBox';
|
|
7358
|
+
const InputInvalid = 'InputInvalid';
|
|
6918
7359
|
const Insertion = 'Insertion';
|
|
6919
7360
|
const Label = 'Label';
|
|
6920
7361
|
const LabelDetail = 'LabelDetail';
|
|
@@ -6923,7 +7364,6 @@ const MarkdownMathBlock = 'MarkdownMathBlock';
|
|
|
6923
7364
|
const MarkdownQuote = 'MarkdownQuote';
|
|
6924
7365
|
const MarkdownTable = 'MarkdownTable';
|
|
6925
7366
|
const MaskIcon = 'MaskIcon';
|
|
6926
|
-
const MaskIconAccount = 'MaskIconAccount';
|
|
6927
7367
|
const MaskIconAdd = 'MaskIconAdd';
|
|
6928
7368
|
const MaskIconArrowLeft = 'MaskIconArrowLeft';
|
|
6929
7369
|
const MaskIconChevronDown = 'MaskIconChevronDown';
|
|
@@ -6934,7 +7374,6 @@ const MaskIconDebugPause = 'MaskIconDebugPause';
|
|
|
6934
7374
|
const MaskIconLayoutPanelLeft = 'MaskIconLayoutPanelLeft';
|
|
6935
7375
|
const MaskIconSearch = 'MaskIconSearch';
|
|
6936
7376
|
const MaskIconSettingsGear = 'MaskIconSettingsGear';
|
|
6937
|
-
const MaskIconSignOut = 'MaskIconSignOut';
|
|
6938
7377
|
const Message = 'Message';
|
|
6939
7378
|
const MessageAssistant = 'MessageAssistant';
|
|
6940
7379
|
const MessageUser = 'MessageUser';
|
|
@@ -6997,6 +7436,28 @@ const jsRules = [{
|
|
|
6997
7436
|
className: TokenKeyword,
|
|
6998
7437
|
regex: /\b(?:const|let|var|function|return|if|else|for|while|class|new|typeof|instanceof|import|export|from|default|async|await|try|catch|finally|throw|this|true|false|null|undefined)\b/
|
|
6999
7438
|
}];
|
|
7439
|
+
const tsRules = [{
|
|
7440
|
+
className: TokenComment,
|
|
7441
|
+
regex: /\/\/[^\n]*/
|
|
7442
|
+
}, {
|
|
7443
|
+
className: TokenComment,
|
|
7444
|
+
regex: /\/\*[\s\S]*?\*\//
|
|
7445
|
+
}, {
|
|
7446
|
+
className: TokenString,
|
|
7447
|
+
regex: /"[^"\\]*(?:\\.[^"\\]*)*"/
|
|
7448
|
+
}, {
|
|
7449
|
+
className: TokenString,
|
|
7450
|
+
regex: /'[^'\\]*(?:\\.[^'\\]*)*'/
|
|
7451
|
+
}, {
|
|
7452
|
+
className: TokenString,
|
|
7453
|
+
regex: /`[^`\\]*(?:\\.[^`\\]*)*`/
|
|
7454
|
+
}, {
|
|
7455
|
+
className: TokenNumber,
|
|
7456
|
+
regex: /\b\d+\.?\d*\b/
|
|
7457
|
+
}, {
|
|
7458
|
+
className: TokenKeyword,
|
|
7459
|
+
regex: /\b(?:abstract|any|as|asserts|async|await|boolean|class|const|constructor|declare|default|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|infer|instanceof|interface|is|keyof|let|module|namespace|never|new|null|number|object|override|private|protected|public|readonly|return|satisfies|set|static|string|super|switch|symbol|this|throw|true|try|type|typeof|undefined|unknown|var|void|while)\b/
|
|
7460
|
+
}];
|
|
7000
7461
|
const htmlRules = [{
|
|
7001
7462
|
className: TokenComment,
|
|
7002
7463
|
regex: /<!--[\s\S]*?-->/
|
|
@@ -7120,6 +7581,9 @@ const highlightCode = (code, language) => {
|
|
|
7120
7581
|
if (normalized === 'js' || normalized === 'javascript') {
|
|
7121
7582
|
return tokenize(code, jsRules);
|
|
7122
7583
|
}
|
|
7584
|
+
if (normalized === 'ts' || normalized === 'typescript') {
|
|
7585
|
+
return tokenize(code, tsRules);
|
|
7586
|
+
}
|
|
7123
7587
|
if (normalized === 'py' || normalized === 'python') {
|
|
7124
7588
|
return tokenize(code, pythonRules);
|
|
7125
7589
|
}
|
|
@@ -8263,6 +8727,12 @@ const parseAndStoreMessageContent = async (parsedMessages, message) => {
|
|
|
8263
8727
|
const parsedContent = message.text === '' ? emptyMessageContent : await parseMessage(message.text);
|
|
8264
8728
|
return setParsedMessageContent(parsedMessages, message.id, message.text, parsedContent);
|
|
8265
8729
|
};
|
|
8730
|
+
const parseAndStoreMessageContentWithWorkerPreference = async (parsedMessages, message, useChatMessageParsingWorker) => {
|
|
8731
|
+
if (useChatMessageParsingWorker) {
|
|
8732
|
+
return parseAndStoreMessagesContentInWorker(parsedMessages, [message]);
|
|
8733
|
+
}
|
|
8734
|
+
return parseAndStoreMessageContent(parsedMessages, message);
|
|
8735
|
+
};
|
|
8266
8736
|
const parseAndStoreMessagesContent = async (parsedMessages, messages) => {
|
|
8267
8737
|
let nextParsedMessages = parsedMessages;
|
|
8268
8738
|
for (const message of messages) {
|
|
@@ -8295,8 +8765,15 @@ const parseAndStoreMessagesContentWithWorkerPreference = async (parsedMessages,
|
|
|
8295
8765
|
}
|
|
8296
8766
|
return parseAndStoreMessagesContent(parsedMessages, messages);
|
|
8297
8767
|
};
|
|
8298
|
-
const getEmptyMessageContent = () => {
|
|
8299
|
-
return emptyMessageContent;
|
|
8768
|
+
const getEmptyMessageContent = () => {
|
|
8769
|
+
return emptyMessageContent;
|
|
8770
|
+
};
|
|
8771
|
+
|
|
8772
|
+
const get = async key => {
|
|
8773
|
+
return getPreference(key);
|
|
8774
|
+
};
|
|
8775
|
+
const update = async settings => {
|
|
8776
|
+
await invoke('Preferences.update', settings);
|
|
8300
8777
|
};
|
|
8301
8778
|
|
|
8302
8779
|
const setOpenApiApiKey = async (state, openApiApiKey, persist = true) => {
|
|
@@ -8713,10 +9190,6 @@ const getNextHandleTextChunkState = (latestState, parsedMessages, sessions) => {
|
|
|
8713
9190
|
};
|
|
8714
9191
|
};
|
|
8715
9192
|
|
|
8716
|
-
const getSelectedSession = (sessions, selectedSessionId) => {
|
|
8717
|
-
return sessions.find(session => session.id === selectedSessionId);
|
|
8718
|
-
};
|
|
8719
|
-
|
|
8720
9193
|
const setAndRerenderHandleTextChunkState = async (uid, previousState, nextState) => {
|
|
8721
9194
|
set(uid, previousState, nextState);
|
|
8722
9195
|
// @ts-ignore
|
|
@@ -8803,7 +9276,7 @@ const handleToolCallsChunkFunction = async (uid, assistantMessageId, toolCalls,
|
|
|
8803
9276
|
};
|
|
8804
9277
|
};
|
|
8805
9278
|
|
|
8806
|
-
const updateMessageTextInSelectedSession = async (sessions, parsedMessages, selectedSessionId, messageId, text, inProgress) => {
|
|
9279
|
+
const updateMessageTextInSelectedSession = async (sessions, parsedMessages, selectedSessionId, messageId, text, inProgress, useChatMessageParsingWorker) => {
|
|
8807
9280
|
let updatedMessage;
|
|
8808
9281
|
const updatedSessions = sessions.map(session => {
|
|
8809
9282
|
if (session.id !== selectedSessionId) {
|
|
@@ -8826,7 +9299,7 @@ const updateMessageTextInSelectedSession = async (sessions, parsedMessages, sele
|
|
|
8826
9299
|
});
|
|
8827
9300
|
let nextParsedMessages = parsedMessages;
|
|
8828
9301
|
if (updatedMessage) {
|
|
8829
|
-
nextParsedMessages = await
|
|
9302
|
+
nextParsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, updatedMessage, useChatMessageParsingWorker);
|
|
8830
9303
|
}
|
|
8831
9304
|
return {
|
|
8832
9305
|
parsedMessages: nextParsedMessages,
|
|
@@ -8849,7 +9322,7 @@ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTex
|
|
|
8849
9322
|
};
|
|
8850
9323
|
}
|
|
8851
9324
|
const updatedText = assistantMessage.text + chunk;
|
|
8852
|
-
const updated = await updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.parsedMessages, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
|
|
9325
|
+
const updated = await updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.parsedMessages, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true, handleTextChunkState.latestState.useChatMessageParsingWorker);
|
|
8853
9326
|
const nextState = {
|
|
8854
9327
|
...handleTextChunkState.latestState,
|
|
8855
9328
|
...(handleTextChunkState.latestState.messagesAutoScrollEnabled ? {
|
|
@@ -9015,6 +9488,11 @@ const withProvisionedBackgroundSession = async (state, session) => {
|
|
|
9015
9488
|
};
|
|
9016
9489
|
};
|
|
9017
9490
|
const handleSubmit = async state => {
|
|
9491
|
+
const authState = state.authEnabled && state.backendUrl ? await syncBackendAuth(state.backendUrl) : undefined;
|
|
9492
|
+
const effectiveState = authState ? {
|
|
9493
|
+
...state,
|
|
9494
|
+
...authState
|
|
9495
|
+
} : state;
|
|
9018
9496
|
const {
|
|
9019
9497
|
agentMode,
|
|
9020
9498
|
aiSessionTitleGenerationEnabled,
|
|
@@ -9043,27 +9521,28 @@ const handleSubmit = async state => {
|
|
|
9043
9521
|
streamingEnabled,
|
|
9044
9522
|
toolEnablement,
|
|
9045
9523
|
useChatCoordinatorWorker,
|
|
9524
|
+
useChatMessageParsingWorker,
|
|
9046
9525
|
useChatNetworkWorkerForRequests,
|
|
9047
9526
|
useChatToolWorker,
|
|
9048
9527
|
useMockApi,
|
|
9049
9528
|
viewMode,
|
|
9050
9529
|
webSearchEnabled
|
|
9051
|
-
} =
|
|
9530
|
+
} = effectiveState;
|
|
9052
9531
|
const userText = composerValue.trim();
|
|
9053
9532
|
if (!userText) {
|
|
9054
|
-
return
|
|
9533
|
+
return effectiveState;
|
|
9055
9534
|
}
|
|
9056
9535
|
const slashCommand = getSlashCommand(userText);
|
|
9057
9536
|
if (slashCommand) {
|
|
9058
|
-
return executeSlashCommand(
|
|
9537
|
+
return executeSlashCommand(effectiveState, slashCommand);
|
|
9059
9538
|
}
|
|
9060
9539
|
const userTime = new Date().toLocaleTimeString([], {
|
|
9061
9540
|
hour: '2-digit',
|
|
9062
9541
|
minute: '2-digit'
|
|
9063
9542
|
});
|
|
9064
9543
|
const userMessageId = crypto.randomUUID();
|
|
9065
|
-
const composerAttachments =
|
|
9066
|
-
await clearComposerAttachments(
|
|
9544
|
+
const composerAttachments = effectiveState.composerAttachments.length > 0 ? effectiveState.composerAttachments : await getComposerAttachments(effectiveState.selectedSessionId);
|
|
9545
|
+
await clearComposerAttachments(effectiveState.selectedSessionId, composerAttachments.map(attachment => attachment.attachmentId));
|
|
9067
9546
|
const userMessage = {
|
|
9068
9547
|
...(composerAttachments.length > 0 ? {
|
|
9069
9548
|
attachments: composerAttachments
|
|
@@ -9087,9 +9566,9 @@ const handleSubmit = async state => {
|
|
|
9087
9566
|
};
|
|
9088
9567
|
let {
|
|
9089
9568
|
parsedMessages
|
|
9090
|
-
} =
|
|
9091
|
-
parsedMessages = await
|
|
9092
|
-
parsedMessages = await
|
|
9569
|
+
} = effectiveState;
|
|
9570
|
+
parsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, userMessage, useChatMessageParsingWorker);
|
|
9571
|
+
parsedMessages = await parseAndStoreMessageContentWithWorkerPreference(parsedMessages, inProgressAssistantMessage, useChatMessageParsingWorker);
|
|
9093
9572
|
let workingSessions = sessions;
|
|
9094
9573
|
if (viewMode === 'detail') {
|
|
9095
9574
|
const loadedSession = await getChatSession(selectedSessionId);
|
|
@@ -9121,10 +9600,10 @@ const handleSubmit = async state => {
|
|
|
9121
9600
|
const provisionedSession = await withProvisionedBackgroundSession(state, newSession);
|
|
9122
9601
|
await saveChatSession(provisionedSession);
|
|
9123
9602
|
optimisticState = withUpdatedMessageScrollTop(focusInput({
|
|
9124
|
-
...
|
|
9603
|
+
...effectiveState,
|
|
9125
9604
|
composerAttachments: [],
|
|
9126
9605
|
composerAttachmentsHeight: 0,
|
|
9127
|
-
composerHeight: getMinComposerHeightForState(
|
|
9606
|
+
composerHeight: getMinComposerHeightForState(effectiveState),
|
|
9128
9607
|
composerSelectionEnd: 0,
|
|
9129
9608
|
composerSelectionStart: 0,
|
|
9130
9609
|
composerValue: '',
|
|
@@ -9160,10 +9639,10 @@ const handleSubmit = async state => {
|
|
|
9160
9639
|
await saveChatSession(selectedSession);
|
|
9161
9640
|
}
|
|
9162
9641
|
optimisticState = withUpdatedMessageScrollTop(focusInput({
|
|
9163
|
-
...
|
|
9642
|
+
...effectiveState,
|
|
9164
9643
|
composerAttachments: [],
|
|
9165
9644
|
composerAttachmentsHeight: 0,
|
|
9166
|
-
composerHeight: getMinComposerHeightForState(
|
|
9645
|
+
composerHeight: getMinComposerHeightForState(effectiveState),
|
|
9167
9646
|
composerSelectionEnd: 0,
|
|
9168
9647
|
composerSelectionStart: 0,
|
|
9169
9648
|
composerValue: '',
|
|
@@ -9175,7 +9654,7 @@ const handleSubmit = async state => {
|
|
|
9175
9654
|
}));
|
|
9176
9655
|
optimisticState = withUpdatedChatInputHistory(optimisticState, userText);
|
|
9177
9656
|
}
|
|
9178
|
-
set(
|
|
9657
|
+
set(effectiveState.uid, effectiveState, optimisticState);
|
|
9179
9658
|
// @ts-ignore
|
|
9180
9659
|
await invoke('Chat.rerender');
|
|
9181
9660
|
let handleTextChunkState = {
|
|
@@ -9264,11 +9743,11 @@ const handleSubmit = async state => {
|
|
|
9264
9743
|
let finalParsedMessages = latestState.parsedMessages;
|
|
9265
9744
|
let updatedSessions;
|
|
9266
9745
|
if (streamingEnabled) {
|
|
9267
|
-
const updated = await updateMessageTextInSelectedSession(latestState.sessions, finalParsedMessages, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false);
|
|
9746
|
+
const updated = await updateMessageTextInSelectedSession(latestState.sessions, finalParsedMessages, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false, latestState.useChatMessageParsingWorker);
|
|
9268
9747
|
updatedSessions = updated.sessions;
|
|
9269
9748
|
finalParsedMessages = updated.parsedMessages;
|
|
9270
9749
|
} else {
|
|
9271
|
-
finalParsedMessages = await
|
|
9750
|
+
finalParsedMessages = await parseAndStoreMessageContentWithWorkerPreference(finalParsedMessages, assistantMessage, latestState.useChatMessageParsingWorker);
|
|
9272
9751
|
updatedSessions = appendMessageToSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessage);
|
|
9273
9752
|
}
|
|
9274
9753
|
if (aiSessionTitleGenerationEnabled && createsNewSession) {
|
|
@@ -9297,6 +9776,84 @@ const handleClickSend = async state => {
|
|
|
9297
9776
|
return handleSubmit(state);
|
|
9298
9777
|
};
|
|
9299
9778
|
|
|
9779
|
+
const SwitchGitBranch = 'Chat.switchGitBranch';
|
|
9780
|
+
const switchGitBranch = async ({
|
|
9781
|
+
assetDir,
|
|
9782
|
+
branchName,
|
|
9783
|
+
platform,
|
|
9784
|
+
workspaceUri
|
|
9785
|
+
}) => {
|
|
9786
|
+
await executeProvider({
|
|
9787
|
+
assetDir,
|
|
9788
|
+
event: `onCommand:${SwitchGitBranch}`,
|
|
9789
|
+
method: CommandExecute,
|
|
9790
|
+
noProviderFoundMessage: 'No git branch switch command found',
|
|
9791
|
+
params: [SwitchGitBranch, {
|
|
9792
|
+
branchName,
|
|
9793
|
+
workspaceUri
|
|
9794
|
+
}],
|
|
9795
|
+
platform
|
|
9796
|
+
});
|
|
9797
|
+
};
|
|
9798
|
+
|
|
9799
|
+
const getGitBranchSwitchErrorMessage = (branchName, error) => {
|
|
9800
|
+
if (error instanceof Error && error.message) {
|
|
9801
|
+
return `Failed to switch to branch "${branchName}". ${error.message}`;
|
|
9802
|
+
}
|
|
9803
|
+
return `Failed to switch to branch "${branchName}".`;
|
|
9804
|
+
};
|
|
9805
|
+
const handleGitBranchChange = async (state, branchName) => {
|
|
9806
|
+
if (!branchName) {
|
|
9807
|
+
return state;
|
|
9808
|
+
}
|
|
9809
|
+
const selectedSession = getSelectedSession(state.sessions, state.selectedSessionId);
|
|
9810
|
+
const workspaceUri = getWorkspaceUri$1(state, selectedSession);
|
|
9811
|
+
if (!workspaceUri) {
|
|
9812
|
+
return {
|
|
9813
|
+
...state,
|
|
9814
|
+
gitBranchPickerErrorMessage: 'No workspace is selected.',
|
|
9815
|
+
gitBranchPickerOpen: true
|
|
9816
|
+
};
|
|
9817
|
+
}
|
|
9818
|
+
try {
|
|
9819
|
+
await switchGitBranch({
|
|
9820
|
+
assetDir: state.assetDir,
|
|
9821
|
+
branchName,
|
|
9822
|
+
platform: state.platform,
|
|
9823
|
+
workspaceUri
|
|
9824
|
+
});
|
|
9825
|
+
const updatedSessions = state.sessions.map(session => {
|
|
9826
|
+
if (session.id !== state.selectedSessionId) {
|
|
9827
|
+
return session;
|
|
9828
|
+
}
|
|
9829
|
+
return {
|
|
9830
|
+
...session,
|
|
9831
|
+
branchName
|
|
9832
|
+
};
|
|
9833
|
+
});
|
|
9834
|
+
const updatedSelectedSession = updatedSessions.find(session => session.id === state.selectedSessionId);
|
|
9835
|
+
if (updatedSelectedSession) {
|
|
9836
|
+
await saveChatSession(updatedSelectedSession);
|
|
9837
|
+
}
|
|
9838
|
+
return {
|
|
9839
|
+
...state,
|
|
9840
|
+
gitBranches: state.gitBranches.map(branch => ({
|
|
9841
|
+
...branch,
|
|
9842
|
+
current: branch.name === branchName
|
|
9843
|
+
})),
|
|
9844
|
+
gitBranchPickerErrorMessage: '',
|
|
9845
|
+
gitBranchPickerOpen: false,
|
|
9846
|
+
sessions: updatedSessions
|
|
9847
|
+
};
|
|
9848
|
+
} catch (error) {
|
|
9849
|
+
return {
|
|
9850
|
+
...state,
|
|
9851
|
+
gitBranchPickerErrorMessage: getGitBranchSwitchErrorMessage(branchName, error),
|
|
9852
|
+
gitBranchPickerOpen: true
|
|
9853
|
+
};
|
|
9854
|
+
}
|
|
9855
|
+
};
|
|
9856
|
+
|
|
9300
9857
|
const setReasoningEffort = (state, reasoningEffort) => {
|
|
9301
9858
|
return {
|
|
9302
9859
|
...state,
|
|
@@ -9427,7 +9984,7 @@ const selectSession = async (state, id) => {
|
|
|
9427
9984
|
}
|
|
9428
9985
|
return loadedSession;
|
|
9429
9986
|
});
|
|
9430
|
-
return {
|
|
9987
|
+
return refreshGitBranchPickerVisibility({
|
|
9431
9988
|
...state,
|
|
9432
9989
|
composerAttachments,
|
|
9433
9990
|
composerAttachmentsHeight: getComposerAttachmentsHeight(composerAttachments, width),
|
|
@@ -9436,7 +9993,7 @@ const selectSession = async (state, id) => {
|
|
|
9436
9993
|
selectedSessionId: id,
|
|
9437
9994
|
sessions: hydratedSessions,
|
|
9438
9995
|
viewMode: viewMode === 'chat-focus' ? 'chat-focus' : 'detail'
|
|
9439
|
-
};
|
|
9996
|
+
});
|
|
9440
9997
|
};
|
|
9441
9998
|
|
|
9442
9999
|
const startRename = (state, id) => {
|
|
@@ -9466,15 +10023,17 @@ const toggleChatFocusMode = async state => {
|
|
|
9466
10023
|
if (viewMode === 'chat-focus') {
|
|
9467
10024
|
return {
|
|
9468
10025
|
...state,
|
|
10026
|
+
gitBranchPickerErrorMessage: '',
|
|
10027
|
+
gitBranchPickerOpen: false,
|
|
9469
10028
|
viewMode: lastNormalViewMode
|
|
9470
10029
|
};
|
|
9471
10030
|
}
|
|
9472
10031
|
if (viewMode === 'list' || viewMode === 'detail') {
|
|
9473
|
-
return {
|
|
10032
|
+
return refreshGitBranchPickerVisibility({
|
|
9474
10033
|
...state,
|
|
9475
10034
|
lastNormalViewMode: viewMode,
|
|
9476
10035
|
viewMode: 'chat-focus'
|
|
9477
|
-
};
|
|
10036
|
+
});
|
|
9478
10037
|
}
|
|
9479
10038
|
return state;
|
|
9480
10039
|
};
|
|
@@ -9604,6 +10163,11 @@ const handleClick = async (state, name, id = '', eventX = 0, eventY = 0) => {
|
|
|
9604
10163
|
visibleModels: state.models
|
|
9605
10164
|
};
|
|
9606
10165
|
}
|
|
10166
|
+
case isGitBranchPickerItemInputName(name):
|
|
10167
|
+
{
|
|
10168
|
+
const branchName = getGitBranchFromGitBranchPickerItemInputName(name);
|
|
10169
|
+
return handleGitBranchChange(state, branchName);
|
|
10170
|
+
}
|
|
9607
10171
|
case isAgentModePickerItemInputName(name):
|
|
9608
10172
|
{
|
|
9609
10173
|
const agentMode = getAgentModeFromAgentModePickerItemInputName(name);
|
|
@@ -9728,6 +10292,71 @@ const handleClickFileName = async (state, uri) => {
|
|
|
9728
10292
|
return state;
|
|
9729
10293
|
};
|
|
9730
10294
|
|
|
10295
|
+
const getBranchPickerErrorMessage = error => {
|
|
10296
|
+
if (error instanceof Error && error.message) {
|
|
10297
|
+
return error.message;
|
|
10298
|
+
}
|
|
10299
|
+
return 'Failed to load git branches.';
|
|
10300
|
+
};
|
|
10301
|
+
const openGitBranchPicker = async state => {
|
|
10302
|
+
const visibleState = await refreshGitBranchPickerVisibility(state);
|
|
10303
|
+
const selectedSession = getSelectedSession(visibleState.sessions, visibleState.selectedSessionId);
|
|
10304
|
+
const fallbackBranchName = selectedSession?.branchName || '';
|
|
10305
|
+
if (visibleState.viewMode !== 'chat-focus' || !visibleState.gitBranchPickerVisible && !fallbackBranchName) {
|
|
10306
|
+
return {
|
|
10307
|
+
...visibleState,
|
|
10308
|
+
gitBranchPickerOpen: false
|
|
10309
|
+
};
|
|
10310
|
+
}
|
|
10311
|
+
const workspaceUri = getWorkspaceUri$1(visibleState, selectedSession);
|
|
10312
|
+
if (!workspaceUri) {
|
|
10313
|
+
return {
|
|
10314
|
+
...visibleState,
|
|
10315
|
+
gitBranches: [],
|
|
10316
|
+
gitBranchPickerErrorMessage: 'No workspace is selected.',
|
|
10317
|
+
gitBranchPickerOpen: true
|
|
10318
|
+
};
|
|
10319
|
+
}
|
|
10320
|
+
try {
|
|
10321
|
+
const gitBranches = await getGitBranches(workspaceUri);
|
|
10322
|
+
return {
|
|
10323
|
+
...visibleState,
|
|
10324
|
+
agentModePickerOpen: false,
|
|
10325
|
+
gitBranches,
|
|
10326
|
+
gitBranchPickerErrorMessage: '',
|
|
10327
|
+
gitBranchPickerOpen: true,
|
|
10328
|
+
modelPickerOpen: false,
|
|
10329
|
+
modelPickerSearchValue: '',
|
|
10330
|
+
reasoningEffortPickerOpen: false,
|
|
10331
|
+
runModePickerOpen: false,
|
|
10332
|
+
visibleModels: visibleState.models
|
|
10333
|
+
};
|
|
10334
|
+
} catch (error) {
|
|
10335
|
+
return {
|
|
10336
|
+
...visibleState,
|
|
10337
|
+
agentModePickerOpen: false,
|
|
10338
|
+
gitBranches: fallbackBranchName ? [{
|
|
10339
|
+
current: true,
|
|
10340
|
+
name: fallbackBranchName
|
|
10341
|
+
}] : [],
|
|
10342
|
+
gitBranchPickerErrorMessage: getBranchPickerErrorMessage(error),
|
|
10343
|
+
gitBranchPickerOpen: true,
|
|
10344
|
+
modelPickerOpen: false,
|
|
10345
|
+
modelPickerSearchValue: '',
|
|
10346
|
+
reasoningEffortPickerOpen: false,
|
|
10347
|
+
runModePickerOpen: false,
|
|
10348
|
+
visibleModels: visibleState.models
|
|
10349
|
+
};
|
|
10350
|
+
}
|
|
10351
|
+
};
|
|
10352
|
+
|
|
10353
|
+
const handleClickGitBranchPickerToggle = async state => {
|
|
10354
|
+
if (state.gitBranchPickerOpen) {
|
|
10355
|
+
return closeGitBranchPicker(state);
|
|
10356
|
+
}
|
|
10357
|
+
return openGitBranchPicker(state);
|
|
10358
|
+
};
|
|
10359
|
+
|
|
9731
10360
|
const handleClickModelPickerList = async (state, eventY) => {
|
|
9732
10361
|
const {
|
|
9733
10362
|
height,
|
|
@@ -10590,19 +11219,6 @@ const getSavedSessions = savedState => {
|
|
|
10590
11219
|
return sessions;
|
|
10591
11220
|
};
|
|
10592
11221
|
|
|
10593
|
-
const getSavedSystemPrompt = savedState => {
|
|
10594
|
-
if (!isObject$1(savedState)) {
|
|
10595
|
-
return undefined;
|
|
10596
|
-
}
|
|
10597
|
-
const {
|
|
10598
|
-
systemPrompt
|
|
10599
|
-
} = savedState;
|
|
10600
|
-
if (typeof systemPrompt !== 'string') {
|
|
10601
|
-
return undefined;
|
|
10602
|
-
}
|
|
10603
|
-
return systemPrompt;
|
|
10604
|
-
};
|
|
10605
|
-
|
|
10606
11222
|
const getSavedViewMode = savedState => {
|
|
10607
11223
|
if (!isObject$1(savedState)) {
|
|
10608
11224
|
return undefined;
|
|
@@ -10634,24 +11250,6 @@ const loadAuthEnabled = async () => {
|
|
|
10634
11250
|
}
|
|
10635
11251
|
};
|
|
10636
11252
|
|
|
10637
|
-
const loadBackendAccessToken = async () => {
|
|
10638
|
-
try {
|
|
10639
|
-
const savedAccessToken = await get('secrets.chatBackendAccessToken');
|
|
10640
|
-
return typeof savedAccessToken === 'string' ? savedAccessToken : '';
|
|
10641
|
-
} catch {
|
|
10642
|
-
return '';
|
|
10643
|
-
}
|
|
10644
|
-
};
|
|
10645
|
-
|
|
10646
|
-
const loadBackendRefreshToken = async () => {
|
|
10647
|
-
try {
|
|
10648
|
-
const savedRefreshToken = await get('secrets.chatBackendRefreshToken');
|
|
10649
|
-
return typeof savedRefreshToken === 'string' ? savedRefreshToken : '';
|
|
10650
|
-
} catch {
|
|
10651
|
-
return '';
|
|
10652
|
-
}
|
|
10653
|
-
};
|
|
10654
|
-
|
|
10655
11253
|
const loadBackendUrl = async () => {
|
|
10656
11254
|
try {
|
|
10657
11255
|
const savedBackendUrl = await get('chat.backendUrl');
|
|
@@ -10832,12 +11430,10 @@ const loadVoiceDictationEnabled = async () => {
|
|
|
10832
11430
|
};
|
|
10833
11431
|
|
|
10834
11432
|
const loadPreferences = async () => {
|
|
10835
|
-
const [aiSessionTitleGenerationEnabled,
|
|
11433
|
+
const [aiSessionTitleGenerationEnabled, authEnabled, backendUrl, chatHistoryEnabled, composerDropEnabled, openApiApiKey, openRouterApiKey, emitStreamingFunctionCallEvents, reasoningPickerEnabled, scrollDownButtonEnabled, searchEnabled, streamingEnabled, todoListToolEnabled, toolEnablement, passIncludeObfuscation, useChatCoordinatorWorker, useChatMathWorker, useChatMessageParsingWorker, useChatNetworkWorkerForRequests, useChatToolWorker, voiceDictationEnabled] = await Promise.all([loadAiSessionTitleGenerationEnabled(), loadAuthEnabled(), loadBackendUrl(), loadChatHistoryEnabled(), loadComposerDropEnabled(), loadOpenApiApiKey(), loadOpenRouterApiKey(), loadEmitStreamingFunctionCallEvents(), loadReasoningPickerEnabled(), loadScrollDownButtonEnabled(), loadSearchEnabled(), loadStreamingEnabled(), loadTodoListToolEnabled(), loadToolEnablement(), loadPassIncludeObfuscation(), loadUseChatCoordinatorWorker(), loadUseChatMathWorker(), loadUseChatMessageParsingWorker(), loadUseChatNetworkWorkerForRequests(), loadUseChatToolWorker(), loadVoiceDictationEnabled()]);
|
|
10836
11434
|
return {
|
|
10837
11435
|
aiSessionTitleGenerationEnabled,
|
|
10838
|
-
authAccessToken,
|
|
10839
11436
|
authEnabled,
|
|
10840
|
-
authRefreshToken,
|
|
10841
11437
|
backendUrl,
|
|
10842
11438
|
chatHistoryEnabled,
|
|
10843
11439
|
composerDropEnabled,
|
|
@@ -10909,9 +11505,7 @@ const loadContent = async (state, savedState) => {
|
|
|
10909
11505
|
const [composerSelectionStart, composerSelectionEnd] = savedComposerSelection ?? [state.composerSelectionStart, state.composerSelectionEnd];
|
|
10910
11506
|
const {
|
|
10911
11507
|
aiSessionTitleGenerationEnabled,
|
|
10912
|
-
authAccessToken,
|
|
10913
11508
|
authEnabled,
|
|
10914
|
-
authRefreshToken,
|
|
10915
11509
|
backendUrl,
|
|
10916
11510
|
chatHistoryEnabled,
|
|
10917
11511
|
composerDropEnabled,
|
|
@@ -10927,11 +11521,13 @@ const loadContent = async (state, savedState) => {
|
|
|
10927
11521
|
toolEnablement,
|
|
10928
11522
|
useChatCoordinatorWorker,
|
|
10929
11523
|
useChatMathWorker,
|
|
10930
|
-
useChatMessageParsingWorker,
|
|
11524
|
+
// useChatMessageParsingWorker,
|
|
10931
11525
|
useChatNetworkWorkerForRequests,
|
|
10932
11526
|
useChatToolWorker,
|
|
10933
11527
|
voiceDictationEnabled
|
|
10934
11528
|
} = await loadPreferences();
|
|
11529
|
+
const useChatMessageParsingWorker = true;
|
|
11530
|
+
const authState = authEnabled && backendUrl ? await syncBackendAuth(backendUrl) : getLoggedOutBackendAuthState();
|
|
10935
11531
|
const legacySavedSessions = getSavedSessions(savedState);
|
|
10936
11532
|
const storedSessions = await listChatSessions();
|
|
10937
11533
|
let sessions = storedSessions;
|
|
@@ -10967,7 +11563,6 @@ const loadContent = async (state, savedState) => {
|
|
|
10967
11563
|
const projectExpandedIds = (savedProjectExpandedIds || state.projectExpandedIds).filter(id => projects.some(project => project.id === id));
|
|
10968
11564
|
const reasoningEffort = getSavedReasoningEffort(savedState) ?? state.reasoningEffort;
|
|
10969
11565
|
const selectedModelId = state.models.some(model => model.id === preferredModelId) ? preferredModelId : state.models[0]?.id || '';
|
|
10970
|
-
const systemPrompt = getSavedSystemPrompt(savedState) ?? state.systemPrompt;
|
|
10971
11566
|
const visibleModels = getVisibleModels(state.models, '');
|
|
10972
11567
|
const visibleSessions = getVisibleSessions(sessions, selectedProjectId);
|
|
10973
11568
|
const selectedSessionId = visibleSessions.some(session => session.id === preferredSessionId) ? preferredSessionId : visibleSessions[0]?.id || '';
|
|
@@ -10983,15 +11578,14 @@ const loadContent = async (state, savedState) => {
|
|
|
10983
11578
|
const savedLastNormalViewMode = getSavedLastNormalViewMode(savedState);
|
|
10984
11579
|
const lastNormalViewMode = savedLastNormalViewMode || (preferredViewMode === 'detail' ? 'detail' : state.lastNormalViewMode);
|
|
10985
11580
|
const viewMode = sessions.length === 0 || !selectedSessionId ? 'list' : preferredViewMode;
|
|
10986
|
-
|
|
11581
|
+
const nextState = {
|
|
10987
11582
|
...state,
|
|
10988
11583
|
agentMode,
|
|
10989
11584
|
agentModePickerOpen: false,
|
|
10990
11585
|
aiSessionTitleGenerationEnabled,
|
|
10991
|
-
authAccessToken,
|
|
11586
|
+
authAccessToken: authState.authAccessToken,
|
|
10992
11587
|
authEnabled,
|
|
10993
|
-
|
|
10994
|
-
authStatus: authAccessToken ? 'signed-in' : 'signed-out',
|
|
11588
|
+
authErrorMessage: authState.authErrorMessage,
|
|
10995
11589
|
backendUrl,
|
|
10996
11590
|
chatHistoryEnabled,
|
|
10997
11591
|
chatListScrollTop,
|
|
@@ -11032,7 +11626,6 @@ const loadContent = async (state, savedState) => {
|
|
|
11032
11626
|
selectedSessionId,
|
|
11033
11627
|
sessions,
|
|
11034
11628
|
streamingEnabled,
|
|
11035
|
-
systemPrompt,
|
|
11036
11629
|
todoListToolEnabled,
|
|
11037
11630
|
toolEnablement,
|
|
11038
11631
|
useChatCoordinatorWorker,
|
|
@@ -11040,10 +11633,15 @@ const loadContent = async (state, savedState) => {
|
|
|
11040
11633
|
useChatMessageParsingWorker,
|
|
11041
11634
|
useChatNetworkWorkerForRequests,
|
|
11042
11635
|
useChatToolWorker,
|
|
11636
|
+
userName: authState.userName,
|
|
11637
|
+
userState: authState.userState,
|
|
11638
|
+
userSubscriptionPlan: authState.userSubscriptionPlan,
|
|
11639
|
+
userUsedTokens: authState.userUsedTokens,
|
|
11043
11640
|
viewMode,
|
|
11044
11641
|
visibleModels,
|
|
11045
11642
|
voiceDictationEnabled
|
|
11046
11643
|
};
|
|
11644
|
+
return refreshGitBranchPickerVisibility(nextState);
|
|
11047
11645
|
};
|
|
11048
11646
|
|
|
11049
11647
|
const isObject = value => {
|
|
@@ -11133,7 +11731,24 @@ const openMockProject = async (state, projectId, projectName, projectUri) => {
|
|
|
11133
11731
|
};
|
|
11134
11732
|
};
|
|
11135
11733
|
|
|
11136
|
-
const
|
|
11734
|
+
const applySessionOptions = (session, options) => {
|
|
11735
|
+
if (!options) {
|
|
11736
|
+
return session;
|
|
11737
|
+
}
|
|
11738
|
+
return {
|
|
11739
|
+
...session,
|
|
11740
|
+
...(options.branchName ? {
|
|
11741
|
+
branchName: options.branchName
|
|
11742
|
+
} : {}),
|
|
11743
|
+
...(options.projectId ? {
|
|
11744
|
+
projectId: options.projectId
|
|
11745
|
+
} : {}),
|
|
11746
|
+
...(options.workspaceUri ? {
|
|
11747
|
+
workspaceUri: options.workspaceUri
|
|
11748
|
+
} : {})
|
|
11749
|
+
};
|
|
11750
|
+
};
|
|
11751
|
+
const openMockSession = async (state, mockSessionId, mockChatMessages, options) => {
|
|
11137
11752
|
const {
|
|
11138
11753
|
sessions: currentSessions
|
|
11139
11754
|
} = state;
|
|
@@ -11146,20 +11761,20 @@ const openMockSession = async (state, mockSessionId, mockChatMessages) => {
|
|
|
11146
11761
|
if (session.id !== mockSessionId) {
|
|
11147
11762
|
return session;
|
|
11148
11763
|
}
|
|
11149
|
-
return {
|
|
11764
|
+
return applySessionOptions({
|
|
11150
11765
|
...session,
|
|
11151
11766
|
messages: mockChatMessages
|
|
11152
|
-
};
|
|
11153
|
-
}) : [...currentSessions, {
|
|
11767
|
+
}, options);
|
|
11768
|
+
}) : [...currentSessions, applySessionOptions({
|
|
11154
11769
|
id: mockSessionId,
|
|
11155
11770
|
messages: mockChatMessages,
|
|
11156
11771
|
title: mockSessionId
|
|
11157
|
-
}];
|
|
11772
|
+
}, options)];
|
|
11158
11773
|
const selectedSession = sessions.find(session => session.id === mockSessionId);
|
|
11159
11774
|
if (selectedSession) {
|
|
11160
11775
|
await saveChatSession(selectedSession);
|
|
11161
11776
|
}
|
|
11162
|
-
return {
|
|
11777
|
+
return refreshGitBranchPickerVisibility({
|
|
11163
11778
|
...state,
|
|
11164
11779
|
composerAttachments: [],
|
|
11165
11780
|
composerAttachmentsHeight: 0,
|
|
@@ -11168,7 +11783,7 @@ const openMockSession = async (state, mockSessionId, mockChatMessages) => {
|
|
|
11168
11783
|
selectedSessionId: mockSessionId,
|
|
11169
11784
|
sessions,
|
|
11170
11785
|
viewMode: 'detail'
|
|
11171
|
-
};
|
|
11786
|
+
});
|
|
11172
11787
|
};
|
|
11173
11788
|
|
|
11174
11789
|
const pasteInput = async state => {
|
|
@@ -11281,6 +11896,10 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
|
|
|
11281
11896
|
color: var(--vscode-errorForeground, var(--vscode-foreground));
|
|
11282
11897
|
}
|
|
11283
11898
|
|
|
11899
|
+
.InputInvalid{
|
|
11900
|
+
border-color: var(--vscode-inputValidation-errorBorder, var(--vscode-errorForeground));
|
|
11901
|
+
}
|
|
11902
|
+
|
|
11284
11903
|
.ChatComposerAttachmentTextFile{
|
|
11285
11904
|
border-color: var(--vscode-charts-green, var(--vscode-widget-border, var(--vscode-panel-border)));
|
|
11286
11905
|
}
|
|
@@ -11335,6 +11954,23 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
|
|
|
11335
11954
|
border-color: var(--vscode-charts-green, var(--vscode-widget-border, var(--vscode-panel-border)));
|
|
11336
11955
|
}
|
|
11337
11956
|
|
|
11957
|
+
.ChatImageMessageContent{
|
|
11958
|
+
padding: 6px;
|
|
11959
|
+
border: 1px solid var(--vscode-widget-border, var(--vscode-panel-border));
|
|
11960
|
+
border-radius: 12px;
|
|
11961
|
+
background: var(--vscode-editorWidget-background, var(--vscode-editor-background));
|
|
11962
|
+
overflow: hidden;
|
|
11963
|
+
}
|
|
11964
|
+
|
|
11965
|
+
.ChatMessageImage{
|
|
11966
|
+
display: block;
|
|
11967
|
+
max-width: min(320px, 100%);
|
|
11968
|
+
max-height: min(320px, calc(100vh - 220px));
|
|
11969
|
+
border-radius: 8px;
|
|
11970
|
+
object-fit: contain;
|
|
11971
|
+
background: color-mix(in srgb, var(--vscode-editor-background) 88%, black);
|
|
11972
|
+
}
|
|
11973
|
+
|
|
11338
11974
|
.Chat{
|
|
11339
11975
|
position: relative;
|
|
11340
11976
|
}
|
|
@@ -11378,6 +12014,14 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
|
|
|
11378
12014
|
|
|
11379
12015
|
}
|
|
11380
12016
|
|
|
12017
|
+
.ChatGitBranchPickerMessage{
|
|
12018
|
+
padding: 6px 8px;
|
|
12019
|
+
}
|
|
12020
|
+
|
|
12021
|
+
.ChatGitBranchPickerErrorMessage{
|
|
12022
|
+
color: var(--vscode-errorForeground, var(--vscode-foreground));
|
|
12023
|
+
}
|
|
12024
|
+
|
|
11381
12025
|
.RunModePickerContainer{
|
|
11382
12026
|
display: flex;
|
|
11383
12027
|
justify-content: flex-end;
|
|
@@ -11482,13 +12126,10 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
|
|
|
11482
12126
|
.ChatFocus .ChatMessages > .Message > .ChatMessageContent{
|
|
11483
12127
|
max-inline-size: 100%;
|
|
11484
12128
|
}
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
12129
|
.Viewlet.Chat.ChatFocus{
|
|
11488
12130
|
display: flex !important;
|
|
11489
12131
|
min-width: 0;
|
|
11490
12132
|
}
|
|
11491
|
-
|
|
11492
12133
|
.ChatFocusMainArea{
|
|
11493
12134
|
display: flex;
|
|
11494
12135
|
flex: 1;
|
|
@@ -11500,7 +12141,6 @@ const getCss = (composerHeight, composerAttachmentsHeight, modelPickerHeight, li
|
|
|
11500
12141
|
flex: 1;
|
|
11501
12142
|
min-height: 0;
|
|
11502
12143
|
}
|
|
11503
|
-
|
|
11504
12144
|
`;
|
|
11505
12145
|
return `${baseCss}
|
|
11506
12146
|
|
|
@@ -11645,7 +12285,8 @@ const HandlePointerUpModelPickerList = 55;
|
|
|
11645
12285
|
const HandleClickReasoningEffortPickerToggle = 56;
|
|
11646
12286
|
const HandleClickAgentModePickerToggle = 57;
|
|
11647
12287
|
const HandleContextMenuChatImageAttachment = 58;
|
|
11648
|
-
const
|
|
12288
|
+
const HandleClickGitBranchPickerToggle = 59;
|
|
12289
|
+
const HandleErrorComposerAttachmentPreviewOverlay = 60;
|
|
11649
12290
|
|
|
11650
12291
|
const getAddContextButtonDom = () => {
|
|
11651
12292
|
return [{
|
|
@@ -11660,10 +12301,12 @@ const getAddContextButtonDom = () => {
|
|
|
11660
12301
|
}];
|
|
11661
12302
|
};
|
|
11662
12303
|
|
|
11663
|
-
const getCustomSelectToggleVirtualDom = (label, name, open, onClick, title = label) => {
|
|
12304
|
+
const getCustomSelectToggleVirtualDom = (label, name, open, onClick, title = label, ariaLabel = title) => {
|
|
11664
12305
|
return [{
|
|
11665
12306
|
'aria-expanded': open ? 'true' : 'false',
|
|
11666
12307
|
'aria-haspopup': 'true',
|
|
12308
|
+
'aria-label': ariaLabel,
|
|
12309
|
+
ariaLabel,
|
|
11667
12310
|
childCount: 2,
|
|
11668
12311
|
className: Select,
|
|
11669
12312
|
inputType: 'button',
|
|
@@ -11686,12 +12329,12 @@ const getCustomSelectToggleVirtualDom = (label, name, open, onClick, title = lab
|
|
|
11686
12329
|
}];
|
|
11687
12330
|
};
|
|
11688
12331
|
|
|
11689
|
-
const getCustomSelectPickerToggleVirtualDom = (label, name, open, onClick, title = label, containerChildCount = 1) => {
|
|
12332
|
+
const getCustomSelectPickerToggleVirtualDom = (label, name, open, onClick, title = label, ariaLabel = title, containerChildCount = 1) => {
|
|
11690
12333
|
return [{
|
|
11691
12334
|
childCount: containerChildCount,
|
|
11692
12335
|
className: CustomSelectContainer,
|
|
11693
12336
|
type: Div
|
|
11694
|
-
}, ...getCustomSelectToggleVirtualDom(label, name, open, onClick, title)];
|
|
12337
|
+
}, ...getCustomSelectToggleVirtualDom(label, name, open, onClick, title, ariaLabel)];
|
|
11695
12338
|
};
|
|
11696
12339
|
|
|
11697
12340
|
const getAgentModePickerVirtualDom = (selectedAgentMode, agentModePickerOpen) => {
|
|
@@ -11701,7 +12344,8 @@ const getAgentModePickerVirtualDom = (selectedAgentMode, agentModePickerOpen) =>
|
|
|
11701
12344
|
const getChatModelPickerToggleVirtualDom = (models, selectedModelId, modelPickerOpen) => {
|
|
11702
12345
|
const selectedModel = models.find(model => model.id === selectedModelId);
|
|
11703
12346
|
const selectedModelLabel = selectedModel ? selectedModel.name : selectedModelId;
|
|
11704
|
-
|
|
12347
|
+
const pickModelLabel = pickModel(selectedModelLabel);
|
|
12348
|
+
return getCustomSelectPickerToggleVirtualDom(selectedModelLabel, ModelPickerToggle, modelPickerOpen, HandleClickModelPickerToggle, pickModelLabel, pickModelLabel);
|
|
11705
12349
|
};
|
|
11706
12350
|
|
|
11707
12351
|
const getCreatePullRequestButtonDom = () => {
|
|
@@ -11745,6 +12389,55 @@ const getCustomSelectOptionVirtualDom = (name, label, selected, detail = '') =>
|
|
|
11745
12389
|
}, text(detail)] : [])];
|
|
11746
12390
|
};
|
|
11747
12391
|
|
|
12392
|
+
const itemHeight = 28;
|
|
12393
|
+
const messageHeight = 32;
|
|
12394
|
+
const getCurrentBranchLabel = (gitBranches, fallbackBranchName) => {
|
|
12395
|
+
const currentBranch = gitBranches.find(branch => branch.current);
|
|
12396
|
+
if (currentBranch) {
|
|
12397
|
+
return currentBranch.name;
|
|
12398
|
+
}
|
|
12399
|
+
if (fallbackBranchName) {
|
|
12400
|
+
return fallbackBranchName;
|
|
12401
|
+
}
|
|
12402
|
+
return 'Branch';
|
|
12403
|
+
};
|
|
12404
|
+
const getBranchOptionsVirtualDom = gitBranches => {
|
|
12405
|
+
return gitBranches.flatMap(branch => {
|
|
12406
|
+
return getCustomSelectOptionVirtualDom(getGitBranchPickerItemInputName(branch.name), branch.name, branch.current, branch.current ? 'current' : '');
|
|
12407
|
+
});
|
|
12408
|
+
};
|
|
12409
|
+
const getBranchPickerMessageDom = (gitBranches, errorMessage) => {
|
|
12410
|
+
const message = errorMessage || (gitBranches.length === 0 ? 'No local git branches found.' : '');
|
|
12411
|
+
if (!message) {
|
|
12412
|
+
return [];
|
|
12413
|
+
}
|
|
12414
|
+
return [{
|
|
12415
|
+
childCount: 1,
|
|
12416
|
+
className: mergeClassNames(ChatGitBranchPickerMessage, errorMessage ? ChatGitBranchPickerErrorMessage : Empty),
|
|
12417
|
+
type: Div
|
|
12418
|
+
}, {
|
|
12419
|
+
text: message,
|
|
12420
|
+
type: Text
|
|
12421
|
+
}];
|
|
12422
|
+
};
|
|
12423
|
+
const getGitBranchPickerVirtualDom = (gitBranches, gitBranchPickerOpen, gitBranchPickerErrorMessage, fallbackBranchName) => {
|
|
12424
|
+
const label = getCurrentBranchLabel(gitBranches, fallbackBranchName);
|
|
12425
|
+
const branchOptions = getBranchOptionsVirtualDom(gitBranches);
|
|
12426
|
+
const messageDom = getBranchPickerMessageDom(gitBranches, gitBranchPickerErrorMessage);
|
|
12427
|
+
const showMessage = messageDom.length > 0;
|
|
12428
|
+
const popOverHeight = gitBranches.length * itemHeight + (showMessage ? messageHeight : 0);
|
|
12429
|
+
return [...getCustomSelectPickerToggleVirtualDom(label, GitBranchPickerToggle, gitBranchPickerOpen, HandleClickGitBranchPickerToggle, 'Switch branch', 'Switch branch', gitBranchPickerOpen ? 2 : 1), ...(gitBranchPickerOpen ? [{
|
|
12430
|
+
childCount: (showMessage ? 1 : 0) + 1,
|
|
12431
|
+
className: mergeClassNames(ChatModelPicker, CustomSelectPopOver, ChatGitBranchPicker),
|
|
12432
|
+
style: `height: ${popOverHeight}px;`,
|
|
12433
|
+
type: Div
|
|
12434
|
+
}, ...messageDom, {
|
|
12435
|
+
childCount: branchOptions.length / 4,
|
|
12436
|
+
className: ChatModelPickerList,
|
|
12437
|
+
type: Ul
|
|
12438
|
+
}, ...branchOptions] : [])];
|
|
12439
|
+
};
|
|
12440
|
+
|
|
11748
12441
|
const reasoningEffortPickerHeight = reasoningEfforts.length * 28;
|
|
11749
12442
|
const getReasoningEffortOptionsVirtualDom = selectedReasoningEffort => {
|
|
11750
12443
|
return reasoningEfforts.flatMap(reasoningEffort => {
|
|
@@ -11754,7 +12447,7 @@ const getReasoningEffortOptionsVirtualDom = selectedReasoningEffort => {
|
|
|
11754
12447
|
});
|
|
11755
12448
|
};
|
|
11756
12449
|
const getReasoningEffortPickerVirtualDom = (selectedReasoningEffort, reasoningEffortPickerOpen) => {
|
|
11757
|
-
return [...getCustomSelectPickerToggleVirtualDom(getReasoningEffortLabel(selectedReasoningEffort), ReasoningEffortPickerToggle, reasoningEffortPickerOpen, HandleClickReasoningEffortPickerToggle, 'Reasoning', reasoningEffortPickerOpen ? 2 : 1), ...(reasoningEffortPickerOpen ? [{
|
|
12450
|
+
return [...getCustomSelectPickerToggleVirtualDom(getReasoningEffortLabel(selectedReasoningEffort), ReasoningEffortPickerToggle, reasoningEffortPickerOpen, HandleClickReasoningEffortPickerToggle, 'Reasoning', 'Reasoning', reasoningEffortPickerOpen ? 2 : 1), ...(reasoningEffortPickerOpen ? [{
|
|
11758
12451
|
childCount: 1,
|
|
11759
12452
|
className: mergeClassNames(ChatModelPicker, CustomSelectPopOver),
|
|
11760
12453
|
style: `height: ${reasoningEffortPickerHeight}px;`,
|
|
@@ -11921,6 +12614,7 @@ const getComposerAttachmentClassName = displayType => {
|
|
|
11921
12614
|
};
|
|
11922
12615
|
const getComposerAttachmentRemoveButtonDom = attachment => {
|
|
11923
12616
|
return [{
|
|
12617
|
+
'aria-label': removeAttachment(),
|
|
11924
12618
|
buttonType: 'button',
|
|
11925
12619
|
childCount: 1,
|
|
11926
12620
|
className: ChatComposerAttachmentRemoveButton,
|
|
@@ -11992,12 +12686,13 @@ const getComposerTextAreaDom = () => {
|
|
|
11992
12686
|
type: TextArea
|
|
11993
12687
|
};
|
|
11994
12688
|
};
|
|
11995
|
-
const getChatSendAreaDom = (composerValue, composerAttachments, agentMode, agentModePickerOpen, hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton = false, voiceDictationEnabled = false, scrollDownButtonEnabled = false, messagesAutoScrollEnabled = true) => {
|
|
12689
|
+
const getChatSendAreaDom = (composerValue, composerAttachments, agentMode, agentModePickerOpen, gitBranchPickerVisible, gitBranchPickerOpen, gitBranchPickerErrorMessage, gitBranches, fallbackBranchName, hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton = false, voiceDictationEnabled = false, scrollDownButtonEnabled = false, messagesAutoScrollEnabled = true) => {
|
|
11996
12690
|
const isSendDisabled = composerValue.trim() === '';
|
|
11997
12691
|
const showAgentModePicker = hasSpaceForAgentModePicker;
|
|
12692
|
+
const showGitBranchPicker = gitBranchPickerVisible || Boolean(fallbackBranchName);
|
|
11998
12693
|
const showResponsiveRunModePicker = showRunMode && hasSpaceForRunModePicker;
|
|
11999
12694
|
const showScrollDownButton = scrollDownButtonEnabled && !messagesAutoScrollEnabled;
|
|
12000
|
-
const bottomControlsCount = 2 + (usageOverviewEnabled ? 1 : 0) + (addContextButtonEnabled ? 1 : 0) + (showCreatePullRequestButton ? 1 : 0) + (voiceDictationEnabled ? 1 : 0) + (showScrollDownButton ? 1 : 0);
|
|
12695
|
+
const bottomControlsCount = 2 + (usageOverviewEnabled ? 1 : 0) + (addContextButtonEnabled ? 1 : 0) + (showCreatePullRequestButton ? 1 : 0) + (showGitBranchPicker ? 1 : 0) + (voiceDictationEnabled ? 1 : 0) + (showScrollDownButton ? 1 : 0);
|
|
12001
12696
|
const primaryControlsCount = 1 + (showAgentModePicker ? 1 : 0) + (reasoningPickerEnabled ? 1 : 0) + (showResponsiveRunModePicker ? 1 : 0);
|
|
12002
12697
|
const hasTodoList = todoListToolEnabled && todoListItems.length > 0;
|
|
12003
12698
|
const hasComposerAttachments = composerAttachments.length > 0;
|
|
@@ -12021,7 +12716,62 @@ const getChatSendAreaDom = (composerValue, composerAttachments, agentMode, agent
|
|
|
12021
12716
|
className: ChatSendAreaPrimaryControls,
|
|
12022
12717
|
role: 'toolbar',
|
|
12023
12718
|
type: Div
|
|
12024
|
-
}, ...(showAgentModePicker ? getAgentModePickerVirtualDom(agentMode, agentModePickerOpen) : []), ...getChatModelPickerToggleVirtualDom(models, selectedModelId, modelPickerOpen), ...(reasoningPickerEnabled ? getReasoningEffortPickerVirtualDom(reasoningEffort, reasoningEffortPickerOpen) : []), ...(showResponsiveRunModePicker ? getRunModePickerVirtualDom(runMode, runModePickerOpen) : []), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...(addContextButtonEnabled ? getAddContextButtonDom() : []), ...(showCreatePullRequestButton ? getCreatePullRequestButtonDom() : []), ...(showScrollDownButton ? getScrollDownButtonDom() : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
12719
|
+
}, ...(showAgentModePicker ? getAgentModePickerVirtualDom(agentMode, agentModePickerOpen) : []), ...getChatModelPickerToggleVirtualDom(models, selectedModelId, modelPickerOpen), ...(reasoningPickerEnabled ? getReasoningEffortPickerVirtualDom(reasoningEffort, reasoningEffortPickerOpen) : []), ...(showResponsiveRunModePicker ? getRunModePickerVirtualDom(runMode, runModePickerOpen) : []), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...(addContextButtonEnabled ? getAddContextButtonDom() : []), ...(showCreatePullRequestButton ? getCreatePullRequestButtonDom() : []), ...(showGitBranchPicker ? getGitBranchPickerVirtualDom(gitBranches, gitBranchPickerOpen, gitBranchPickerErrorMessage, fallbackBranchName) : []), ...(showScrollDownButton ? getScrollDownButtonDom() : []), ...getSendButtonDom(isSendDisabled, voiceDictationEnabled)];
|
|
12720
|
+
};
|
|
12721
|
+
|
|
12722
|
+
const authContainerStyle = 'align-items:center;display:flex;gap:8px;min-width:0;';
|
|
12723
|
+
const authNameStyle = 'max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
|
|
12724
|
+
const authButtonStyle = 'white-space:nowrap;';
|
|
12725
|
+
const getButtonLabel = (userState, isAuthenticated) => {
|
|
12726
|
+
if (userState === 'loggingIn') {
|
|
12727
|
+
return loggingInToBackend();
|
|
12728
|
+
}
|
|
12729
|
+
if (userState === 'loggingOut') {
|
|
12730
|
+
return loggingOutFromBackend();
|
|
12731
|
+
}
|
|
12732
|
+
return isAuthenticated ? logout() : login();
|
|
12733
|
+
};
|
|
12734
|
+
const getButtonTitle = (userState, isAuthenticated) => {
|
|
12735
|
+
if (userState === 'loggingIn') {
|
|
12736
|
+
return loggingInToBackend();
|
|
12737
|
+
}
|
|
12738
|
+
if (userState === 'loggingOut') {
|
|
12739
|
+
return loggingOutFromBackend();
|
|
12740
|
+
}
|
|
12741
|
+
return isAuthenticated ? logoutFromBackend$1() : loginToBackend();
|
|
12742
|
+
};
|
|
12743
|
+
const getChatHeaderAuthDom = (authEnabled = false, userState = 'loggedOut', userName = '') => {
|
|
12744
|
+
if (!authEnabled) {
|
|
12745
|
+
return [];
|
|
12746
|
+
}
|
|
12747
|
+
const isAuthenticated = userState === 'loggedIn' || userState === 'loggingOut';
|
|
12748
|
+
const buttonName = isAuthenticated ? Logout : Login;
|
|
12749
|
+
const buttonLabel = getButtonLabel(userState, isAuthenticated);
|
|
12750
|
+
const buttonTitle = getButtonTitle(userState, isAuthenticated);
|
|
12751
|
+
const isPending = userState === 'loggingIn' || userState === 'loggingOut';
|
|
12752
|
+
const displayName = userName || signedIn();
|
|
12753
|
+
return [{
|
|
12754
|
+
childCount: isAuthenticated ? 2 : 1,
|
|
12755
|
+
className: ChatHeaderAuth,
|
|
12756
|
+
style: authContainerStyle,
|
|
12757
|
+
type: Div
|
|
12758
|
+
}, ...(isAuthenticated ? [{
|
|
12759
|
+
childCount: 1,
|
|
12760
|
+
className: ChatHeaderAuthName,
|
|
12761
|
+
style: authNameStyle,
|
|
12762
|
+
title: displayName,
|
|
12763
|
+
type: Span
|
|
12764
|
+
}, text(displayName)] : []), {
|
|
12765
|
+
childCount: 1,
|
|
12766
|
+
className: mergeClassNames(Button, ButtonSecondary),
|
|
12767
|
+
disabled: isPending,
|
|
12768
|
+
inputType: 'button',
|
|
12769
|
+
name: buttonName,
|
|
12770
|
+
onClick: HandleClick,
|
|
12771
|
+
style: authButtonStyle,
|
|
12772
|
+
title: buttonTitle,
|
|
12773
|
+
type: Button$1
|
|
12774
|
+
}, text(buttonLabel)];
|
|
12025
12775
|
};
|
|
12026
12776
|
|
|
12027
12777
|
const focusHeaderStyle = 'align-items:center;border-bottom:1px solid var(--vscode-panel-border, transparent);display:flex;gap:12px;justify-content:space-between;padding:8px 12px;';
|
|
@@ -12042,15 +12792,15 @@ const getFocusHeaderActionButtonDom = (label, name) => {
|
|
|
12042
12792
|
type: Button$1
|
|
12043
12793
|
}, text(label)];
|
|
12044
12794
|
};
|
|
12045
|
-
const getChatHeaderDomFocusMode = (selectedSessionTitle, selectedProjectName) => {
|
|
12795
|
+
const getChatHeaderDomFocusMode = (selectedSessionTitle, selectedProjectName, authEnabled = false, userState = 'loggedOut', userName = '') => {
|
|
12046
12796
|
const items = [[addAction(), FocusAddAction], [openInVsCode(), FocusOpenInVsCode], [commit(), FocusCommit], [openTerminal(), FocusOpenTerminal], [showDiff(), FocusShowDiff]];
|
|
12047
12797
|
const hasProjectName = !!selectedProjectName;
|
|
12048
12798
|
return [{
|
|
12049
|
-
childCount: 2,
|
|
12799
|
+
childCount: 2 + (authEnabled ? 1 : 0),
|
|
12050
12800
|
className: ChatFocusHeader,
|
|
12051
12801
|
style: focusHeaderStyle,
|
|
12052
12802
|
type: Header
|
|
12053
|
-
}, {
|
|
12803
|
+
}, ...getChatHeaderAuthDom(authEnabled, userState, userName), {
|
|
12054
12804
|
childCount: hasProjectName ? 2 : 1,
|
|
12055
12805
|
className: ChatName,
|
|
12056
12806
|
style: focusHeaderMetaStyle,
|
|
@@ -12633,6 +13383,7 @@ const getMissingApiActionsDom = ({
|
|
|
12633
13383
|
};
|
|
12634
13384
|
const getMissingApiKeyDom = ({
|
|
12635
13385
|
getApiKeyText,
|
|
13386
|
+
inputClassName,
|
|
12636
13387
|
inputName,
|
|
12637
13388
|
inputPattern,
|
|
12638
13389
|
inputRequired = false,
|
|
@@ -12655,7 +13406,7 @@ const getMissingApiKeyDom = ({
|
|
|
12655
13406
|
autocomplete: 'off',
|
|
12656
13407
|
autocorrect: 'off',
|
|
12657
13408
|
childCount: 0,
|
|
12658
|
-
className: InputBox,
|
|
13409
|
+
className: inputClassName ? mergeClassNames(InputBox, inputClassName) : InputBox,
|
|
12659
13410
|
name: inputName,
|
|
12660
13411
|
onInput: HandleInput,
|
|
12661
13412
|
...(inputPattern ? {
|
|
@@ -12675,13 +13426,17 @@ const getMissingApiKeyDom = ({
|
|
|
12675
13426
|
})];
|
|
12676
13427
|
};
|
|
12677
13428
|
|
|
12678
|
-
const getMissingOpenApiApiKeyDom = (openApiApiKeyState = 'idle', openSettingsUrl = 'https://platform.openai.com/api-keys', inputPattern = '^sk-.+') => {
|
|
13429
|
+
const getMissingOpenApiApiKeyDom = (openApiApiKeyInput = '', openApiApiKeyState = 'idle', openSettingsUrl = 'https://platform.openai.com/api-keys', inputPattern = '^sk-.+') => {
|
|
12679
13430
|
const isSaving = openApiApiKeyState === 'saving';
|
|
13431
|
+
const isInvalid = openApiApiKeyInput !== '' && !new RegExp(inputPattern).test(openApiApiKeyInput);
|
|
12680
13432
|
return getMissingApiKeyDom({
|
|
12681
13433
|
getApiKeyText: getOpenApiApiKey(),
|
|
13434
|
+
...(isInvalid ? {
|
|
13435
|
+
inputClassName: InputInvalid
|
|
13436
|
+
} : {}),
|
|
12682
13437
|
inputName: OpenApiApiKeyInput,
|
|
12683
13438
|
inputPattern,
|
|
12684
|
-
inputRequired:
|
|
13439
|
+
inputRequired: false,
|
|
12685
13440
|
onSubmit: HandleMissingOpenAiApiKeyFormSubmit,
|
|
12686
13441
|
openSettingsButtonName: OpenOpenApiApiKeyWebsite,
|
|
12687
13442
|
openSettingsUrl,
|
|
@@ -13671,14 +14426,27 @@ const getChatAttachmentsDom = attachments => {
|
|
|
13671
14426
|
}];
|
|
13672
14427
|
})];
|
|
13673
14428
|
};
|
|
13674
|
-
const
|
|
14429
|
+
const getStandaloneImageAttachmentDom = attachment => {
|
|
14430
|
+
if (!attachment.previewSrc) {
|
|
14431
|
+
return getChatAttachmentsDom([attachment]);
|
|
14432
|
+
}
|
|
14433
|
+
return [{
|
|
14434
|
+
alt: attachment.name,
|
|
14435
|
+
childCount: 0,
|
|
14436
|
+
className: ChatMessageImage,
|
|
14437
|
+
src: attachment.previewSrc,
|
|
14438
|
+
type: Img
|
|
14439
|
+
}];
|
|
14440
|
+
};
|
|
14441
|
+
const getChatMessageDom = (message, parsedMessageContent, _openRouterApiKeyInput, openApiApiKeyInput = '', openApiApiKeyState = 'idle', openApiApiKeysSettingsUrl = 'https://platform.openai.com/api-keys', openApiApiKeyInputPattern = '^sk-.+', openRouterApiKeyState = 'idle', useChatMathWorker = false, standaloneImageAttachment) => {
|
|
13675
14442
|
const roleClassName = message.role === 'user' ? MessageUser : MessageAssistant;
|
|
13676
14443
|
const isOpenApiApiKeyMissingMessage = message.role === 'assistant' && message.text === openApiApiKeyRequiredMessage;
|
|
13677
14444
|
const isOpenRouterApiKeyMissingMessage = message.role === 'assistant' && message.text === openRouterApiKeyRequiredMessage;
|
|
13678
14445
|
const isOpenRouterRequestFailedMessage = message.role === 'assistant' && message.text === openRouterRequestFailedMessage;
|
|
13679
14446
|
const isOpenRouterTooManyRequestsMessage = message.role === 'assistant' && message.text.startsWith(openRouterTooManyRequestsMessage);
|
|
13680
|
-
const
|
|
13681
|
-
const
|
|
14447
|
+
const isStandaloneImageMessage = !!standaloneImageAttachment;
|
|
14448
|
+
const messageDom = isStandaloneImageMessage ? getStandaloneImageAttachmentDom(standaloneImageAttachment) : getMessageContentDom(parsedMessageContent, useChatMathWorker);
|
|
14449
|
+
const attachmentsDom = !isStandaloneImageMessage && message.role === 'user' ? getChatAttachmentsDom(message.attachments ?? []) : [];
|
|
13682
14450
|
const toolCallsDom = getToolCallsDom(message);
|
|
13683
14451
|
const toolCallsChildCount = toolCallsDom.length > 0 ? 1 : 0;
|
|
13684
14452
|
const messageDomChildCount = getTopLevelNodeCount(messageDom);
|
|
@@ -13690,9 +14458,9 @@ const getChatMessageDom = (message, parsedMessageContent, _openRouterApiKeyInput
|
|
|
13690
14458
|
type: Div
|
|
13691
14459
|
}, {
|
|
13692
14460
|
childCount: extraChildCount,
|
|
13693
|
-
className: ChatMessageContent,
|
|
14461
|
+
className: isStandaloneImageMessage ? mergeClassNames(ChatMessageContent, ChatImageMessageContent) : ChatMessageContent,
|
|
13694
14462
|
type: Div
|
|
13695
|
-
}, ...toolCallsDom, ...messageDom, ...attachmentsDom, ...(isOpenApiApiKeyMissingMessage ? getMissingOpenApiApiKeyDom(openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern) : []), ...(isOpenRouterApiKeyMissingMessage ? getMissingOpenRouterApiKeyDom(openRouterApiKeyState) : []), ...(isOpenRouterRequestFailedMessage ? getOpenRouterRequestFailedDom() : []), ...(isOpenRouterTooManyRequestsMessage ? getOpenRouterTooManyRequestsDom() : [])];
|
|
14463
|
+
}, ...toolCallsDom, ...messageDom, ...attachmentsDom, ...(isOpenApiApiKeyMissingMessage ? getMissingOpenApiApiKeyDom(openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern) : []), ...(isOpenRouterApiKeyMissingMessage ? getMissingOpenRouterApiKeyDom(openRouterApiKeyState) : []), ...(isOpenRouterRequestFailedMessage ? getOpenRouterRequestFailedDom() : []), ...(isOpenRouterTooManyRequestsMessage ? getOpenRouterTooManyRequestsDom() : [])];
|
|
13696
14464
|
};
|
|
13697
14465
|
|
|
13698
14466
|
const parentNode$1 = {
|
|
@@ -13708,6 +14476,22 @@ const getEmptyMessagesDom = () => {
|
|
|
13708
14476
|
const hasMessageText = message => {
|
|
13709
14477
|
return message.text.trim().length > 0;
|
|
13710
14478
|
};
|
|
14479
|
+
const isImageAttachment = attachment => {
|
|
14480
|
+
return attachment.displayType === 'image';
|
|
14481
|
+
};
|
|
14482
|
+
const withAttachments = (message, attachments) => {
|
|
14483
|
+
const {
|
|
14484
|
+
attachments: _attachments,
|
|
14485
|
+
...messageWithoutAttachments
|
|
14486
|
+
} = message;
|
|
14487
|
+
if (attachments.length === 0) {
|
|
14488
|
+
return messageWithoutAttachments;
|
|
14489
|
+
}
|
|
14490
|
+
return {
|
|
14491
|
+
...messageWithoutAttachments,
|
|
14492
|
+
attachments
|
|
14493
|
+
};
|
|
14494
|
+
};
|
|
13711
14495
|
const getDisplayMessages = (messages, parsedMessages) => {
|
|
13712
14496
|
const displayMessages = [];
|
|
13713
14497
|
for (const message of messages) {
|
|
@@ -13715,6 +14499,30 @@ const getDisplayMessages = (messages, parsedMessages) => {
|
|
|
13715
14499
|
if (!parsedContent) {
|
|
13716
14500
|
continue;
|
|
13717
14501
|
}
|
|
14502
|
+
if (message.role === 'user') {
|
|
14503
|
+
const attachments = message.attachments ?? [];
|
|
14504
|
+
const imageAttachments = attachments.filter(isImageAttachment);
|
|
14505
|
+
if (imageAttachments.length > 0) {
|
|
14506
|
+
const nonImageAttachments = attachments.filter(attachment => !isImageAttachment(attachment));
|
|
14507
|
+
if (hasMessageText(message) || nonImageAttachments.length > 0) {
|
|
14508
|
+
displayMessages.push({
|
|
14509
|
+
message: withAttachments(message, nonImageAttachments),
|
|
14510
|
+
parsedContent: hasMessageText(message) ? parsedContent : getEmptyMessageContent()
|
|
14511
|
+
});
|
|
14512
|
+
}
|
|
14513
|
+
for (const attachment of imageAttachments) {
|
|
14514
|
+
displayMessages.push({
|
|
14515
|
+
message: {
|
|
14516
|
+
...withAttachments(message, [attachment]),
|
|
14517
|
+
text: ''
|
|
14518
|
+
},
|
|
14519
|
+
parsedContent: getEmptyMessageContent(),
|
|
14520
|
+
standaloneImageAttachment: attachment
|
|
14521
|
+
});
|
|
14522
|
+
}
|
|
14523
|
+
continue;
|
|
14524
|
+
}
|
|
14525
|
+
}
|
|
13718
14526
|
if (message.role !== 'assistant' || !message.toolCalls || message.toolCalls.length === 0) {
|
|
13719
14527
|
displayMessages.push({
|
|
13720
14528
|
message,
|
|
@@ -13770,7 +14578,7 @@ const getMessagesDom = (messages, parsedMessages, openRouterApiKeyInput, openApi
|
|
|
13770
14578
|
role: 'log',
|
|
13771
14579
|
scrollTop: messagesScrollTop,
|
|
13772
14580
|
type: Div
|
|
13773
|
-
}, ...displayMessages.flatMap(item => getChatMessageDom(item.message, item.parsedContent, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, useChatMathWorker))];
|
|
14581
|
+
}, ...displayMessages.flatMap(item => getChatMessageDom(item.message, item.parsedContent, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, useChatMathWorker, item.standaloneImageAttachment))];
|
|
13774
14582
|
};
|
|
13775
14583
|
|
|
13776
14584
|
const arrowLeft$1 = {
|
|
@@ -13884,7 +14692,6 @@ const getChatModeChatFocusVirtualDom = ({
|
|
|
13884
14692
|
agentModePickerOpen = false,
|
|
13885
14693
|
authEnabled = false,
|
|
13886
14694
|
authErrorMessage = '',
|
|
13887
|
-
authStatus = 'signed-out',
|
|
13888
14695
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
13889
14696
|
composerAttachmentPreviewOverlayError = false,
|
|
13890
14697
|
composerAttachments,
|
|
@@ -13895,6 +14702,10 @@ const getChatModeChatFocusVirtualDom = ({
|
|
|
13895
14702
|
composerHeight = 28,
|
|
13896
14703
|
composerLineHeight = 20,
|
|
13897
14704
|
composerValue,
|
|
14705
|
+
gitBranches,
|
|
14706
|
+
gitBranchPickerErrorMessage,
|
|
14707
|
+
gitBranchPickerOpen,
|
|
14708
|
+
gitBranchPickerVisible,
|
|
13898
14709
|
hasSpaceForAgentModePicker,
|
|
13899
14710
|
hasSpaceForRunModePicker,
|
|
13900
14711
|
messagesAutoScrollEnabled,
|
|
@@ -13929,14 +14740,15 @@ const getChatModeChatFocusVirtualDom = ({
|
|
|
13929
14740
|
tokensUsed,
|
|
13930
14741
|
usageOverviewEnabled,
|
|
13931
14742
|
useChatMathWorker = false,
|
|
14743
|
+
userName = '',
|
|
14744
|
+
userState = 'loggedOut',
|
|
13932
14745
|
visibleModels = models,
|
|
13933
14746
|
voiceDictationEnabled = false
|
|
13934
14747
|
}) => {
|
|
13935
14748
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
13936
|
-
const selectedProject = projects.find(project => project.id === selectedProjectId);
|
|
13937
|
-
const messages = selectedSession ? selectedSession.messages : [];
|
|
13938
14749
|
const selectedSessionTitle = selectedSession?.title || chatTitle();
|
|
13939
|
-
const selectedProjectName =
|
|
14750
|
+
const selectedProjectName = projects.find(project => project.id === selectedProjectId)?.name || '';
|
|
14751
|
+
const messages = selectedSession ? selectedSession.messages : [];
|
|
13940
14752
|
const showCreatePullRequestButton = canCreatePullRequest(selectedSession);
|
|
13941
14753
|
const isDropOverlayVisible = composerDropEnabled && composerDropActive;
|
|
13942
14754
|
const isComposerAttachmentPreviewOverlayVisible = !!composerAttachmentPreviewOverlayAttachmentId;
|
|
@@ -13955,7 +14767,7 @@ const getChatModeChatFocusVirtualDom = ({
|
|
|
13955
14767
|
childCount: 3,
|
|
13956
14768
|
className: ChatFocusMainArea,
|
|
13957
14769
|
type: Div
|
|
13958
|
-
}, ...getChatHeaderDomFocusMode(selectedSessionTitle, selectedProjectName), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton, voiceDictationEnabled, scrollDownButtonEnabled, messagesAutoScrollEnabled), ...getChatOverlaysVirtualDom({
|
|
14770
|
+
}, ...getChatHeaderDomFocusMode(selectedSessionTitle, selectedProjectName, authEnabled, userState, userName), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, messagesScrollTop, useChatMathWorker, true), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, gitBranchPickerVisible, gitBranchPickerOpen, gitBranchPickerErrorMessage, gitBranches, selectedSession?.branchName || '', hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton, voiceDictationEnabled, scrollDownButtonEnabled, messagesAutoScrollEnabled), ...getChatOverlaysVirtualDom({
|
|
13959
14771
|
agentMode,
|
|
13960
14772
|
agentModePickerVisible: isAgentModePickerVisible,
|
|
13961
14773
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
@@ -14008,31 +14820,8 @@ const getHeaderActionVirtualDom = item => {
|
|
|
14008
14820
|
}];
|
|
14009
14821
|
};
|
|
14010
14822
|
|
|
14011
|
-
const
|
|
14012
|
-
const isSigningIn = authStatus === 'signing-in';
|
|
14013
|
-
if (!authEnabled) {
|
|
14014
|
-
return undefined;
|
|
14015
|
-
}
|
|
14016
|
-
if (authStatus !== 'signed-in') {
|
|
14017
|
-
return {
|
|
14018
|
-
disabled: isSigningIn,
|
|
14019
|
-
icon: mergeClassNames(MaskIcon, MaskIconAccount),
|
|
14020
|
-
name: Login,
|
|
14021
|
-
onClick: HandleClick,
|
|
14022
|
-
title: isSigningIn ? loggingInToBackend() : loginToBackend()
|
|
14023
|
-
};
|
|
14024
|
-
}
|
|
14025
|
-
return {
|
|
14026
|
-
disabled: false,
|
|
14027
|
-
icon: mergeClassNames(MaskIcon, MaskIconSignOut),
|
|
14028
|
-
name: Logout,
|
|
14029
|
-
onClick: HandleClick,
|
|
14030
|
-
title: logoutFromBackend()
|
|
14031
|
-
};
|
|
14032
|
-
};
|
|
14033
|
-
const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'signed-out', searchEnabled = false) => {
|
|
14823
|
+
const getChatHeaderActionsDom = (viewMode, searchEnabled = false) => {
|
|
14034
14824
|
const toggleTitle = viewMode === 'chat-focus' ? normalChatMode() : chatFocusMode();
|
|
14035
|
-
const authAction = getAuthAction(authEnabled, authStatus);
|
|
14036
14825
|
const items = [{
|
|
14037
14826
|
icon: mergeClassNames(MaskIcon, MaskIconLayoutPanelLeft),
|
|
14038
14827
|
name: ToggleChatFocus,
|
|
@@ -14058,7 +14847,7 @@ const getChatHeaderActionsDom = (viewMode, authEnabled = false, authStatus = 'si
|
|
|
14058
14847
|
name: Settings,
|
|
14059
14848
|
onClick: HandleClickSettings,
|
|
14060
14849
|
title: settings()
|
|
14061
|
-
},
|
|
14850
|
+
}, {
|
|
14062
14851
|
icon: mergeClassNames(MaskIcon, MaskIconClose),
|
|
14063
14852
|
name: CloseChat,
|
|
14064
14853
|
onClick: HandleClickClose,
|
|
@@ -14083,14 +14872,14 @@ const getAuthErrorDom = (hasAuthError, authErrorMessage) => {
|
|
|
14083
14872
|
type: Span
|
|
14084
14873
|
}, text(authErrorMessage)];
|
|
14085
14874
|
};
|
|
14086
|
-
const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false,
|
|
14875
|
+
const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, userState = 'loggedOut', userName = '', authErrorMessage = '') => {
|
|
14087
14876
|
const hasAuthError = authEnabled && !!authErrorMessage;
|
|
14088
14877
|
return [{
|
|
14089
|
-
childCount: hasAuthError ?
|
|
14878
|
+
childCount: 2 + (authEnabled ? 1 : 0) + (hasAuthError ? 1 : 0),
|
|
14090
14879
|
className: ChatHeader,
|
|
14091
14880
|
onContextMenu: HandleChatHeaderContextMenu,
|
|
14092
14881
|
type: Header
|
|
14093
|
-
}, {
|
|
14882
|
+
}, ...getChatHeaderAuthDom(authEnabled, userState, userName), {
|
|
14094
14883
|
childCount: 2,
|
|
14095
14884
|
className: ChatName,
|
|
14096
14885
|
type: Div
|
|
@@ -14098,7 +14887,7 @@ const getChatHeaderDomDetailMode = (selectedSessionTitle, authEnabled = false, a
|
|
|
14098
14887
|
childCount: 1,
|
|
14099
14888
|
className: ChatHeaderLabel,
|
|
14100
14889
|
type: H2
|
|
14101
|
-
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail'
|
|
14890
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom('detail'), ...getAuthErrorDom(hasAuthError, authErrorMessage)];
|
|
14102
14891
|
};
|
|
14103
14892
|
|
|
14104
14893
|
const getChatModeDetailVirtualDom = ({
|
|
@@ -14107,7 +14896,6 @@ const getChatModeDetailVirtualDom = ({
|
|
|
14107
14896
|
agentModePickerOpen = false,
|
|
14108
14897
|
authEnabled = false,
|
|
14109
14898
|
authErrorMessage = '',
|
|
14110
|
-
authStatus = 'signed-out',
|
|
14111
14899
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14112
14900
|
composerAttachmentPreviewOverlayError = false,
|
|
14113
14901
|
composerAttachments,
|
|
@@ -14148,6 +14936,8 @@ const getChatModeDetailVirtualDom = ({
|
|
|
14148
14936
|
tokensUsed,
|
|
14149
14937
|
usageOverviewEnabled,
|
|
14150
14938
|
useChatMathWorker = false,
|
|
14939
|
+
userName = '',
|
|
14940
|
+
userState = 'loggedOut',
|
|
14151
14941
|
visibleModels = models,
|
|
14152
14942
|
voiceDictationEnabled = false
|
|
14153
14943
|
}) => {
|
|
@@ -14168,7 +14958,7 @@ const getChatModeDetailVirtualDom = ({
|
|
|
14168
14958
|
onDragEnter: HandleDragEnterChatView,
|
|
14169
14959
|
onDragOver: HandleDragOverChatView,
|
|
14170
14960
|
type: Div
|
|
14171
|
-
}, ...getChatHeaderDomDetailMode(selectedSessionTitle, authEnabled,
|
|
14961
|
+
}, ...getChatHeaderDomDetailMode(selectedSessionTitle, authEnabled, userState, userName, authErrorMessage), ...getMessagesDom(messages, parsedMessages, openRouterApiKeyInput, openApiApiKeyInput, openApiApiKeyState, openApiApiKeysSettingsUrl, openApiApiKeyInputPattern, openRouterApiKeyState, messagesScrollTop, useChatMathWorker), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, false, false, '', [], '', hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, showCreatePullRequestButton, voiceDictationEnabled, scrollDownButtonEnabled, messagesAutoScrollEnabled), ...getChatOverlaysVirtualDom({
|
|
14172
14962
|
agentMode,
|
|
14173
14963
|
agentModePickerVisible: isAgentModePickerVisible,
|
|
14174
14964
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
@@ -14204,20 +14994,20 @@ const getChatSearchDom = (hasSearchField, searchValue) => {
|
|
|
14204
14994
|
value: searchValue
|
|
14205
14995
|
}];
|
|
14206
14996
|
};
|
|
14207
|
-
const getChatHeaderListModeDom = (authEnabled = false,
|
|
14997
|
+
const getChatHeaderListModeDom = (authEnabled = false, userState = 'loggedOut', userName = '', authErrorMessage = '', searchEnabled = false, searchFieldVisible = false, searchValue = '') => {
|
|
14208
14998
|
const hasAuthError = authEnabled && !!authErrorMessage;
|
|
14209
14999
|
const hasSearchField = searchEnabled && searchFieldVisible;
|
|
14210
|
-
const headerChildCount = 2 + (hasAuthError ? 1 : 0) + (hasSearchField ? 1 : 0);
|
|
15000
|
+
const headerChildCount = 2 + (authEnabled ? 1 : 0) + (hasAuthError ? 1 : 0) + (hasSearchField ? 1 : 0);
|
|
14211
15001
|
return [{
|
|
14212
15002
|
childCount: headerChildCount,
|
|
14213
15003
|
className: ChatHeader,
|
|
14214
15004
|
onContextMenu: HandleChatHeaderContextMenu,
|
|
14215
15005
|
type: Header
|
|
14216
|
-
}, {
|
|
15006
|
+
}, ...getChatHeaderAuthDom(authEnabled, userState, userName), {
|
|
14217
15007
|
childCount: 1,
|
|
14218
15008
|
className: ChatHeaderLabel,
|
|
14219
15009
|
type: H2
|
|
14220
|
-
}, text(chats()), ...getChatHeaderActionsDom('list',
|
|
15010
|
+
}, text(chats()), ...getChatHeaderActionsDom('list', searchEnabled), ...getChatSearchDom(hasSearchField, searchValue), ...(hasAuthError ? [{
|
|
14221
15011
|
childCount: 1,
|
|
14222
15012
|
className: ChatAuthError,
|
|
14223
15013
|
type: Span
|
|
@@ -14317,7 +15107,6 @@ const getChatModeListVirtualDom = ({
|
|
|
14317
15107
|
agentModePickerOpen = false,
|
|
14318
15108
|
authEnabled = false,
|
|
14319
15109
|
authErrorMessage = '',
|
|
14320
|
-
authStatus = 'signed-out',
|
|
14321
15110
|
chatListScrollTop = 0,
|
|
14322
15111
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14323
15112
|
composerAttachmentPreviewOverlayError = false,
|
|
@@ -14352,6 +15141,8 @@ const getChatModeListVirtualDom = ({
|
|
|
14352
15141
|
tokensMax,
|
|
14353
15142
|
tokensUsed,
|
|
14354
15143
|
usageOverviewEnabled,
|
|
15144
|
+
userName = '',
|
|
15145
|
+
userState = 'loggedOut',
|
|
14355
15146
|
visibleModels = models,
|
|
14356
15147
|
voiceDictationEnabled = false
|
|
14357
15148
|
}) => {
|
|
@@ -14370,7 +15161,7 @@ const getChatModeListVirtualDom = ({
|
|
|
14370
15161
|
onDragEnter: HandleDragEnterChatView,
|
|
14371
15162
|
onDragOver: HandleDragOverChatView,
|
|
14372
15163
|
type: Div
|
|
14373
|
-
}, ...getChatHeaderListModeDom(authEnabled,
|
|
15164
|
+
}, ...getChatHeaderListModeDom(authEnabled, userState, userName, authErrorMessage, searchEnabled, searchFieldVisible, searchValue), ...getChatListDom(visibleSessions, selectedSessionId, listFocusedIndex, chatListScrollTop), ...getChatSendAreaDom(composerValue, composerAttachments, agentMode, agentModePickerOpen, false, false, '', [], '', hasSpaceForAgentModePicker, modelPickerOpen, models, selectedModelId, reasoningPickerEnabled, reasoningEffort, reasoningEffortPickerOpen, usageOverviewEnabled, tokensUsed, tokensMax, addContextButtonEnabled, showRunMode, hasSpaceForRunModePicker, runMode, runModePickerOpen, todoListToolEnabled, todoListItems, false, voiceDictationEnabled), ...getChatOverlaysVirtualDom({
|
|
14374
15165
|
agentMode,
|
|
14375
15166
|
agentModePickerVisible: isAgentModePickerVisible,
|
|
14376
15167
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
@@ -14473,7 +15264,6 @@ const getChatVirtualDom = options => {
|
|
|
14473
15264
|
agentModePickerOpen = false,
|
|
14474
15265
|
authEnabled = false,
|
|
14475
15266
|
authErrorMessage = '',
|
|
14476
|
-
authStatus = 'signed-out',
|
|
14477
15267
|
chatListScrollTop,
|
|
14478
15268
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14479
15269
|
composerAttachmentPreviewOverlayError = false,
|
|
@@ -14485,6 +15275,10 @@ const getChatVirtualDom = options => {
|
|
|
14485
15275
|
composerHeight,
|
|
14486
15276
|
composerLineHeight,
|
|
14487
15277
|
composerValue,
|
|
15278
|
+
gitBranches = [],
|
|
15279
|
+
gitBranchPickerErrorMessage = '',
|
|
15280
|
+
gitBranchPickerOpen = false,
|
|
15281
|
+
gitBranchPickerVisible = false,
|
|
14488
15282
|
hasSpaceForAgentModePicker,
|
|
14489
15283
|
hasSpaceForRunModePicker,
|
|
14490
15284
|
listFocusedIndex = -1,
|
|
@@ -14522,6 +15316,8 @@ const getChatVirtualDom = options => {
|
|
|
14522
15316
|
tokensUsed,
|
|
14523
15317
|
usageOverviewEnabled,
|
|
14524
15318
|
useChatMathWorker = false,
|
|
15319
|
+
userName = '',
|
|
15320
|
+
userState = 'loggedOut',
|
|
14525
15321
|
viewMode,
|
|
14526
15322
|
visibleModels = models,
|
|
14527
15323
|
voiceDictationEnabled = false
|
|
@@ -14536,7 +15332,6 @@ const getChatVirtualDom = options => {
|
|
|
14536
15332
|
agentModePickerOpen,
|
|
14537
15333
|
authEnabled,
|
|
14538
15334
|
authErrorMessage,
|
|
14539
|
-
authStatus,
|
|
14540
15335
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14541
15336
|
composerAttachmentPreviewOverlayError,
|
|
14542
15337
|
composerAttachments,
|
|
@@ -14547,6 +15342,10 @@ const getChatVirtualDom = options => {
|
|
|
14547
15342
|
composerHeight,
|
|
14548
15343
|
composerLineHeight,
|
|
14549
15344
|
composerValue,
|
|
15345
|
+
gitBranches,
|
|
15346
|
+
gitBranchPickerErrorMessage,
|
|
15347
|
+
gitBranchPickerOpen,
|
|
15348
|
+
gitBranchPickerVisible,
|
|
14550
15349
|
hasSpaceForAgentModePicker,
|
|
14551
15350
|
hasSpaceForRunModePicker,
|
|
14552
15351
|
messagesAutoScrollEnabled,
|
|
@@ -14581,6 +15380,8 @@ const getChatVirtualDom = options => {
|
|
|
14581
15380
|
tokensUsed,
|
|
14582
15381
|
usageOverviewEnabled,
|
|
14583
15382
|
useChatMathWorker,
|
|
15383
|
+
userName,
|
|
15384
|
+
userState,
|
|
14584
15385
|
visibleModels,
|
|
14585
15386
|
voiceDictationEnabled
|
|
14586
15387
|
});
|
|
@@ -14591,7 +15392,6 @@ const getChatVirtualDom = options => {
|
|
|
14591
15392
|
agentModePickerOpen,
|
|
14592
15393
|
authEnabled,
|
|
14593
15394
|
authErrorMessage,
|
|
14594
|
-
authStatus,
|
|
14595
15395
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14596
15396
|
composerAttachmentPreviewOverlayError,
|
|
14597
15397
|
composerAttachments,
|
|
@@ -14632,6 +15432,8 @@ const getChatVirtualDom = options => {
|
|
|
14632
15432
|
tokensUsed,
|
|
14633
15433
|
usageOverviewEnabled,
|
|
14634
15434
|
useChatMathWorker,
|
|
15435
|
+
userName,
|
|
15436
|
+
userState,
|
|
14635
15437
|
visibleModels,
|
|
14636
15438
|
voiceDictationEnabled
|
|
14637
15439
|
});
|
|
@@ -14642,7 +15444,6 @@ const getChatVirtualDom = options => {
|
|
|
14642
15444
|
agentModePickerOpen,
|
|
14643
15445
|
authEnabled,
|
|
14644
15446
|
authErrorMessage,
|
|
14645
|
-
authStatus,
|
|
14646
15447
|
chatListScrollTop,
|
|
14647
15448
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14648
15449
|
composerAttachmentPreviewOverlayError,
|
|
@@ -14677,6 +15478,8 @@ const getChatVirtualDom = options => {
|
|
|
14677
15478
|
tokensMax,
|
|
14678
15479
|
tokensUsed,
|
|
14679
15480
|
usageOverviewEnabled,
|
|
15481
|
+
userName,
|
|
15482
|
+
userState,
|
|
14680
15483
|
visibleModels,
|
|
14681
15484
|
voiceDictationEnabled
|
|
14682
15485
|
});
|
|
@@ -14692,7 +15495,6 @@ const renderItems = (oldState, newState) => {
|
|
|
14692
15495
|
agentModePickerOpen,
|
|
14693
15496
|
authEnabled,
|
|
14694
15497
|
authErrorMessage,
|
|
14695
|
-
authStatus,
|
|
14696
15498
|
chatListScrollTop,
|
|
14697
15499
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14698
15500
|
composerAttachmentPreviewOverlayError,
|
|
@@ -14704,6 +15506,10 @@ const renderItems = (oldState, newState) => {
|
|
|
14704
15506
|
composerHeight,
|
|
14705
15507
|
composerLineHeight,
|
|
14706
15508
|
composerValue,
|
|
15509
|
+
gitBranches,
|
|
15510
|
+
gitBranchPickerErrorMessage,
|
|
15511
|
+
gitBranchPickerOpen,
|
|
15512
|
+
gitBranchPickerVisible,
|
|
14707
15513
|
hasSpaceForAgentModePicker,
|
|
14708
15514
|
hasSpaceForRunModePicker,
|
|
14709
15515
|
initial,
|
|
@@ -14743,6 +15549,8 @@ const renderItems = (oldState, newState) => {
|
|
|
14743
15549
|
uid,
|
|
14744
15550
|
usageOverviewEnabled,
|
|
14745
15551
|
useChatMathWorker,
|
|
15552
|
+
userName,
|
|
15553
|
+
userState,
|
|
14746
15554
|
viewMode,
|
|
14747
15555
|
visibleModels,
|
|
14748
15556
|
voiceDictationEnabled
|
|
@@ -14756,7 +15564,6 @@ const renderItems = (oldState, newState) => {
|
|
|
14756
15564
|
agentModePickerOpen,
|
|
14757
15565
|
authEnabled,
|
|
14758
15566
|
authErrorMessage,
|
|
14759
|
-
authStatus,
|
|
14760
15567
|
chatListScrollTop,
|
|
14761
15568
|
composerAttachmentPreviewOverlayAttachmentId,
|
|
14762
15569
|
composerAttachmentPreviewOverlayError,
|
|
@@ -14768,6 +15575,10 @@ const renderItems = (oldState, newState) => {
|
|
|
14768
15575
|
composerHeight,
|
|
14769
15576
|
composerLineHeight,
|
|
14770
15577
|
composerValue,
|
|
15578
|
+
gitBranches,
|
|
15579
|
+
gitBranchPickerErrorMessage,
|
|
15580
|
+
gitBranchPickerOpen,
|
|
15581
|
+
gitBranchPickerVisible,
|
|
14771
15582
|
hasSpaceForAgentModePicker,
|
|
14772
15583
|
hasSpaceForRunModePicker,
|
|
14773
15584
|
listFocusedIndex,
|
|
@@ -14805,6 +15616,8 @@ const renderItems = (oldState, newState) => {
|
|
|
14805
15616
|
tokensUsed,
|
|
14806
15617
|
usageOverviewEnabled,
|
|
14807
15618
|
useChatMathWorker,
|
|
15619
|
+
userName,
|
|
15620
|
+
userState,
|
|
14808
15621
|
viewMode,
|
|
14809
15622
|
visibleModels,
|
|
14810
15623
|
voiceDictationEnabled
|
|
@@ -14851,8 +15664,16 @@ const renderSelection = (oldState, newState) => {
|
|
|
14851
15664
|
const renderValue = (oldState, newState) => {
|
|
14852
15665
|
const {
|
|
14853
15666
|
composerValue,
|
|
15667
|
+
openApiApiKeyInput,
|
|
15668
|
+
openRouterApiKeyInput,
|
|
14854
15669
|
uid
|
|
14855
15670
|
} = newState;
|
|
15671
|
+
if (oldState.openApiApiKeyInput !== openApiApiKeyInput) {
|
|
15672
|
+
return [SetValueByName, uid, OpenApiApiKeyInput, openApiApiKeyInput];
|
|
15673
|
+
}
|
|
15674
|
+
if (oldState.openRouterApiKeyInput !== openRouterApiKeyInput) {
|
|
15675
|
+
return [SetValueByName, uid, OpenRouterApiKeyInput, openRouterApiKeyInput];
|
|
15676
|
+
}
|
|
14856
15677
|
return [SetValueByName, uid, Composer, composerValue];
|
|
14857
15678
|
};
|
|
14858
15679
|
|
|
@@ -14946,6 +15767,9 @@ const renderEventListeners = () => {
|
|
|
14946
15767
|
}, {
|
|
14947
15768
|
name: HandleClickAgentModePickerToggle,
|
|
14948
15769
|
params: ['openAgentModePicker']
|
|
15770
|
+
}, {
|
|
15771
|
+
name: HandleClickGitBranchPickerToggle,
|
|
15772
|
+
params: ['handleClickGitBranchPickerToggle']
|
|
14949
15773
|
}, {
|
|
14950
15774
|
name: HandleClickModelPickerOverlay,
|
|
14951
15775
|
params: ['handleClickModelPickerOverlay', DefaultPrevented]
|
|
@@ -15104,6 +15928,10 @@ const reset = async state => {
|
|
|
15104
15928
|
composerSelectionEnd: 0,
|
|
15105
15929
|
composerSelectionStart: 0,
|
|
15106
15930
|
composerValue: '',
|
|
15931
|
+
gitBranches: [],
|
|
15932
|
+
gitBranchPickerErrorMessage: '',
|
|
15933
|
+
gitBranchPickerOpen: false,
|
|
15934
|
+
gitBranchPickerVisible: false,
|
|
15107
15935
|
mockAiResponseDelay: 0,
|
|
15108
15936
|
modelPickerHeight: getModelPickerHeight(state.modelPickerHeaderHeight, state.models.length),
|
|
15109
15937
|
modelPickerListScrollTop: 0,
|
|
@@ -15183,7 +16011,6 @@ const saveState = state => {
|
|
|
15183
16011
|
selectedModelId,
|
|
15184
16012
|
selectedProjectId,
|
|
15185
16013
|
selectedSessionId,
|
|
15186
|
-
systemPrompt,
|
|
15187
16014
|
viewMode
|
|
15188
16015
|
} = state;
|
|
15189
16016
|
return {
|
|
@@ -15206,7 +16033,6 @@ const saveState = state => {
|
|
|
15206
16033
|
selectedModelId,
|
|
15207
16034
|
selectedProjectId,
|
|
15208
16035
|
selectedSessionId,
|
|
15209
|
-
systemPrompt,
|
|
15210
16036
|
viewMode
|
|
15211
16037
|
};
|
|
15212
16038
|
};
|
|
@@ -15221,7 +16047,13 @@ const setAddContextButtonEnabled = (state, addContextButtonEnabled) => {
|
|
|
15221
16047
|
const setAuthEnabled = (state, authEnabled) => {
|
|
15222
16048
|
return {
|
|
15223
16049
|
...state,
|
|
15224
|
-
authEnabled
|
|
16050
|
+
authAccessToken: authEnabled ? state.authAccessToken : '',
|
|
16051
|
+
authEnabled,
|
|
16052
|
+
authErrorMessage: authEnabled ? state.authErrorMessage : '',
|
|
16053
|
+
userName: authEnabled ? state.userName : '',
|
|
16054
|
+
userState: authEnabled ? state.userState : 'loggedOut',
|
|
16055
|
+
userSubscriptionPlan: authEnabled ? state.userSubscriptionPlan : '',
|
|
16056
|
+
userUsedTokens: authEnabled ? state.userUsedTokens : 0
|
|
15225
16057
|
};
|
|
15226
16058
|
};
|
|
15227
16059
|
|
|
@@ -15415,6 +16247,7 @@ const commandMap = {
|
|
|
15415
16247
|
'Chat.chatListFocusNext': wrapCommand(chatListFocusNext),
|
|
15416
16248
|
'Chat.chatListFocusPrevious': wrapCommand(chatListFocusPrevious),
|
|
15417
16249
|
'Chat.clearInput': wrapCommand(clearInput),
|
|
16250
|
+
'Chat.closeGitBranchPicker': wrapCommand(closeGitBranchPicker),
|
|
15418
16251
|
'Chat.copyInput': wrapCommand(copyInput),
|
|
15419
16252
|
'Chat.create': create,
|
|
15420
16253
|
'Chat.cutInput': wrapCommand(cutInput),
|
|
@@ -15443,6 +16276,7 @@ const commandMap = {
|
|
|
15443
16276
|
'Chat.handleClickDelete': wrapCommand(handleClickDelete),
|
|
15444
16277
|
'Chat.handleClickDictationButton': wrapCommand(handleClickDictationButton),
|
|
15445
16278
|
'Chat.handleClickFileName': wrapCommand(handleClickFileName),
|
|
16279
|
+
'Chat.handleClickGitBranchPickerToggle': wrapCommand(handleClickGitBranchPickerToggle),
|
|
15446
16280
|
'Chat.handleClickList': wrapCommand(handleClickList),
|
|
15447
16281
|
'Chat.handleClickModelPickerList': wrapCommand(handleClickModelPickerList),
|
|
15448
16282
|
'Chat.handleClickModelPickerListIndex': wrapCommand(handleClickModelPickerListIndex),
|
|
@@ -15494,6 +16328,7 @@ const commandMap = {
|
|
|
15494
16328
|
'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
|
|
15495
16329
|
'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
|
|
15496
16330
|
'Chat.openAgentModePicker': wrapCommand(openAgentModePicker),
|
|
16331
|
+
'Chat.openGitBranchPicker': wrapCommand(openGitBranchPicker),
|
|
15497
16332
|
'Chat.openMockProject': wrapCommand(openMockProject),
|
|
15498
16333
|
'Chat.openMockSession': wrapCommand(openMockSession),
|
|
15499
16334
|
'Chat.openModelPicker': wrapCommand(openModelPicker),
|