@vantran-se/openchamber-web 1.22.1 → 1.23.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/README.md +2 -3
- package/bin/cli.js +11 -1
- package/bin/cli.test.js +92 -0
- package/bin/lib/cli-startup.js +49 -0
- package/bin/lib/commands-startup.js +41 -6
- package/dist/assets/{CodeMirrorCommentWidgets-C53Q7pbX.js → CodeMirrorCommentWidgets-DFg2wnpo.js} +1 -1
- package/dist/assets/DiffView-3Dn4QHbu.js +4 -0
- package/dist/assets/DirtyBranchSwitchDialog-CwOerqVi.js +1 -0
- package/dist/assets/FilesView-BdTOpew9.js +17 -0
- package/dist/assets/GitView-Dqf9vHJh.js +6 -0
- package/dist/assets/{JsonTreeView-Bl0lp9Rs.js → JsonTreeView-BKdsjg5B.js} +1 -1
- package/dist/assets/LinearIssuesView-CmbeL7I6.js +1 -0
- package/dist/assets/MarkdownImageGallery-_5gEVr0X.js +1 -0
- package/dist/assets/MarkdownRendererImpl-wVZlx4dd.js +12 -0
- package/dist/assets/OnboardingScreen-DdP4_nuc.js +1 -0
- package/dist/assets/{PatchDiff-D6NXAfJk.js → PatchDiff-am3SAss2.js} +1 -1
- package/dist/assets/PierreDiffViewer-DCsydlKs.js +161 -0
- package/dist/assets/PlanView-BoJxdRZe.js +5 -0
- package/dist/assets/SettingsView-CcM8pF5O.js +28 -0
- package/dist/assets/{SettingsWindow-BiWDBRvb.js → SettingsWindow-DVTdDSol.js} +1 -1
- package/dist/assets/SymbolsNerdFontMono-Regular-aK5vsLov.woff2 +0 -0
- package/dist/assets/{ToolOutputDialog-BQexMQIm.js → ToolOutputDialog-BgfTbDZ4.js} +6 -6
- package/dist/assets/ToolPartDiffPreview-C7WLk5i9.js +8 -0
- package/dist/assets/{VirtualizedFileDiff-Dpz2ra8h.js → VirtualizedFileDiff-DcdgkH-x.js} +1 -1
- package/dist/assets/WalkthroughView-BEVUDxuw.js +4 -0
- package/dist/assets/{computeVirtualFileMetrics-DtyozJdt.js → computeVirtualFileMetrics-C8byMnRh.js} +2 -2
- package/dist/assets/contextPanelEmbeddedChat-CirXEPJq.js +1 -0
- package/dist/assets/de-C8jV7J9y.js +10 -0
- package/dist/assets/es-BI6J1M5R.js +16 -0
- package/dist/assets/fr-D6oDFt7E.js +14 -0
- package/dist/assets/ghostty-vt-DdA0Zryv.wasm +0 -0
- package/dist/assets/{index-DmhujXbT.js → index-BB7ryz8y.js} +1 -1
- package/dist/assets/index-BqhiCmYS.js +39 -0
- package/dist/assets/index-FqSOBz0J.css +1 -0
- package/dist/assets/{isDiffPlainText-XyulMHxx.js → isDiffPlainText-45ujMPGb.js} +1 -1
- package/dist/assets/{isFilePlainText-B19Ddps1.js → isFilePlainText-Cc4KFSYi.js} +1 -1
- package/dist/assets/ja-C_4i5EQu.js +16 -0
- package/dist/assets/ko-BFbOTpbq.js +16 -0
- package/dist/assets/{main-B2a_JfKZ.js → main-C9ETLKFc.js} +2 -2
- package/dist/assets/main-CJmb2dF8.js +930 -0
- package/dist/assets/markdownCore-DVuZpnli.js +5 -0
- package/dist/assets/{miniChat-B3CSU_Ps.js → miniChat-B4Ytoq2n.js} +2 -2
- package/dist/assets/{mobile-QNcFIVCW.js → mobile-BUT6-lo1.js} +2 -2
- package/dist/assets/patchFileDiff-8j1apICU.js +13 -0
- package/dist/assets/pl-COFvT56l.js +16 -0
- package/dist/assets/pt-BR-DtVOO2Lj.js +16 -0
- package/dist/assets/renderElectronMiniChatApp-B6vUG-vF.js +2 -0
- package/dist/assets/renderMobileApp-BNgHraq6.js +25 -0
- package/dist/assets/runtimeEndpointReset-B8LYpWvr.js +17 -0
- package/dist/assets/scheduledTasksApi-GC4epIYA.js +1 -0
- package/dist/assets/{shikiHighlight-DE-OwqGw.js → shikiHighlight-BJISeZsQ.js} +1 -1
- package/dist/assets/surface-BvRzS58U.js +1 -0
- package/dist/assets/tr-B8Q0Go2l.js +7 -0
- package/dist/assets/uk-Dk4a-Fn-.js +16 -0
- package/dist/assets/{useAppFontEffects-COAeIX-D.js → useAppFontEffects-DpFNefUA.js} +153 -179
- package/dist/assets/useGitComparison-Dfxaqd0s.js +1 -0
- package/dist/assets/useInlineCommentController-CscsE4t-.js +2 -0
- package/dist/assets/useRootScrollLock-BaCvuRlT.js +1 -0
- package/dist/assets/{vendor-base-ui-BeMD8X_w.js → vendor-base-ui-DdV8vhHn.js} +1 -1
- package/dist/assets/{vendor-codemirror-language-data-BG3v1Ghq.js → vendor-codemirror-language-data-DzlSIu_W.js} +2 -2
- package/dist/assets/vendor-legendapp-list-BuBPBC3R.js +1 -0
- package/dist/assets/vendor-zod-BPAANqvH.js +39 -0
- package/dist/assets/{web-components-BNMwa0qm.js → web-components-CdGfR2XJ.js} +1 -1
- package/dist/assets/zh-CN-B_BXxG1Q.js +16 -0
- package/dist/assets/zh-TW-DLrl1SPZ.js +16 -0
- package/dist/index.html +5 -43
- package/dist/mini-chat.html +4 -4
- package/dist/mobile.html +4 -4
- package/package.json +8 -5
- package/server/index.d.ts +15 -0
- package/server/index.js +82 -13
- package/server/lib/agent-tool/runtime.js +2 -19
- package/server/lib/changelog/update-notes.js +82 -0
- package/server/lib/changelog/update-notes.test.js +59 -0
- package/server/lib/data-dir-migration.js +40 -0
- package/server/lib/data-dir-migration.test.js +59 -0
- package/server/lib/dev-tunnel/DOCUMENTATION.md +13 -4
- package/server/lib/dev-tunnel/runtime.js +4 -4
- package/server/lib/dev-tunnel/tunnel.test.js +20 -0
- package/server/lib/event-stream/runtime.test.js +12 -12
- package/server/lib/fs/DOCUMENTATION.md +5 -0
- package/server/lib/fs/routes.js +63 -21
- package/server/lib/fs/routes.test.js +187 -1
- package/server/lib/git/DOCUMENTATION.md +32 -6
- package/server/lib/git/routes.js +40 -4
- package/server/lib/git/service.js +291 -215
- package/server/lib/git/service.test.js +593 -25
- package/server/lib/inherited-env.js +16 -9
- package/server/lib/inherited-env.test.js +8 -9
- package/server/lib/mcp-reconnect/DOCUMENTATION.md +55 -0
- package/server/lib/mcp-reconnect/runtime.js +122 -0
- package/server/lib/mcp-reconnect/runtime.test.js +140 -0
- package/server/lib/message-queue/DOCUMENTATION.md +161 -0
- package/server/lib/message-queue/runtime.js +870 -0
- package/server/lib/message-queue/runtime.test.js +482 -0
- package/server/lib/network-defaults.js +23 -0
- package/server/lib/network-defaults.test.js +52 -0
- package/server/lib/openchamber-sessions/routes.js +102 -0
- package/server/lib/openchamber-sessions/routes.test.js +88 -0
- package/server/lib/opencode/DOCUMENTATION.md +30 -6
- package/server/lib/opencode/bootstrap-runtime.js +2 -0
- package/server/lib/opencode/config-paths.test.js +116 -0
- package/server/lib/opencode/core-routes.js +1 -0
- package/server/lib/opencode/feature-routes-runtime.js +7 -0
- package/server/lib/opencode/input-history-scope.js +14 -0
- package/server/lib/opencode/managed-plugin-config.js +35 -0
- package/server/lib/opencode/openchamber-routes.js +64 -4
- package/server/lib/opencode/openchamber-routes.test.js +130 -3
- package/server/lib/opencode/plugins.js +2 -2
- package/server/lib/opencode/providers.js +44 -2
- package/server/lib/opencode/providers.test.js +131 -4
- package/server/lib/opencode/routes.js +9 -7
- package/server/lib/opencode/server-startup-runtime.js +1 -1
- package/server/lib/opencode/settings-files.js +214 -0
- package/server/lib/opencode/settings-helpers.js +113 -41
- package/server/lib/opencode/settings-helpers.test.js +342 -0
- package/server/lib/opencode/settings-registry.json +747 -0
- package/server/lib/opencode/settings-runtime.js +141 -20
- package/server/lib/opencode/settings-runtime.test.js +191 -4
- package/server/lib/opencode/shared.js +4 -1
- package/server/lib/opencode/shutdown-runtime.js +2 -0
- package/server/lib/opencode/skill-routes.js +2 -1
- package/server/lib/opencode/snippets.js +1 -2
- package/server/lib/package-manager.js +4 -29
- package/server/lib/package-manager.test.js +2 -2
- package/server/lib/project-context/DOCUMENTATION.md +25 -1
- package/server/lib/project-context/routes.http.test.js +18 -0
- package/server/lib/project-context/routes.js +15 -0
- package/server/lib/project-context/runtime.js +248 -23
- package/server/lib/project-context/runtime.test.js +106 -3
- package/server/lib/projects/DOCUMENTATION.md +76 -0
- package/server/lib/projects/project-config.js +142 -9
- package/server/lib/projects/project-id.js +17 -0
- package/server/lib/projects/project-setup.js +409 -0
- package/server/lib/projects/project-setup.test.js +557 -0
- package/server/lib/projects/routes.js +59 -0
- package/server/lib/quota/DOCUMENTATION.md +40 -2
- package/server/lib/quota/credentials/providers.js +4 -0
- package/server/lib/quota/credentials/store.js +1 -1
- package/server/lib/quota/credentials/store.test.js +4 -4
- package/server/lib/quota/index.js +1 -0
- package/server/lib/quota/providers/cline-pass.js +125 -0
- package/server/lib/quota/providers/cline-pass.test.js +103 -0
- package/server/lib/quota/providers/exe-dev.js +75 -0
- package/server/lib/quota/providers/exe-dev.test.js +47 -0
- package/server/lib/quota/providers/hyper.js +118 -0
- package/server/lib/quota/providers/hyper.test.js +126 -0
- package/server/lib/quota/providers/index.js +22 -0
- package/server/lib/quota/providers/neuralwatt.js +3 -6
- package/server/lib/quota/providers/neuralwatt.test.js +7 -7
- package/server/lib/quota/providers/ollama-cloud.js +31 -0
- package/server/lib/quota/providers/ollama-cloud.test.js +33 -1
- package/server/lib/quota/providers/opencode-go.js +2 -1
- package/server/lib/quota/providers/opencode-go.test.js +31 -2
- package/server/lib/quota/providers/openrouter.js +119 -24
- package/server/lib/quota/providers/openrouter.test.js +330 -0
- package/server/lib/quota/routes.js +2 -0
- package/server/lib/quota/utils/auth.js +1 -1
- package/server/lib/relay/DOCUMENTATION.md +56 -1
- package/server/lib/relay/cross-compat.test.js +26 -0
- package/server/lib/relay/downstream-scheduler.js +154 -0
- package/server/lib/relay/downstream-scheduler.test.js +162 -0
- package/server/lib/relay/e2ee.js +10 -8
- package/server/lib/relay/flow-control.test.js +177 -0
- package/server/lib/relay/host-client.js +37 -8
- package/server/lib/relay/host-client.test.js +9 -1
- package/server/lib/relay/tunnel-codec.js +9 -0
- package/server/lib/relay/tunnel-host.js +69 -18
- package/server/lib/relay/tunnel-host.test.js +9 -1
- package/server/lib/security/request-security.js +21 -6
- package/server/lib/security/request-security.test.js +42 -8
- package/server/lib/session-assist/runtime.js +7 -10
- package/server/lib/session-goal/DOCUMENTATION.md +20 -7
- package/server/lib/session-goal/create.js +3 -1
- package/server/lib/session-goal/runtime.js +81 -20
- package/server/lib/session-goal/runtime.test.js +426 -0
- package/server/lib/skills-catalog/DOCUMENTATION.md +1 -1
- package/server/lib/skills-catalog/install.js +3 -2
- package/server/lib/small-model/DOCUMENTATION.md +7 -2
- package/server/lib/small-model/call.js +17 -6
- package/server/lib/small-model/call.test.js +52 -0
- package/server/lib/small-model/index.js +7 -11
- package/server/lib/small-model/routes.js +2 -1
- package/server/lib/small-model/runtime-providers.js +15 -7
- package/server/lib/small-model/runtime-providers.test.js +7 -1
- package/server/lib/system-prompt/runtime.js +2 -21
- package/server/lib/terminal/DOCUMENTATION.md +14 -10
- package/server/lib/terminal/runtime.js +190 -31
- package/server/lib/terminal/runtime.test.js +571 -37
- package/server/lib/terminal/shells.js +17 -0
- package/server/lib/terminal/shells.test.js +32 -1
- package/server/lib/ui-auth/ui-auth.js +4 -1
- package/server/lib/ui-auth/ui-auth.test.js +16 -0
- package/server/lib/walkthrough/DOCUMENTATION.md +33 -14
- package/server/lib/walkthrough/index.js +1 -0
- package/server/lib/walkthrough/model-settings.js +8 -12
- package/server/lib/walkthrough/prompt.js +3 -1
- package/server/lib/walkthrough/routes.test.js +26 -5
- package/server/lib/walkthrough/sources.js +23 -2
- package/dist/assets/CommitSection-X-f2RgYr.js +0 -1
- package/dist/assets/DiffView-Dh1ey2x9.js +0 -4
- package/dist/assets/FilesView-3ZYP72ki.js +0 -17
- package/dist/assets/GitView-CMuN7z2Z.js +0 -6
- package/dist/assets/LinearIssuesView-CQiUDU8b.js +0 -1
- package/dist/assets/MarkdownImageGallery-bA0PS-tn.js +0 -1
- package/dist/assets/MarkdownRendererImpl-BGQi2PLq.js +0 -12
- package/dist/assets/OnboardingScreen-D3kYJIb6.js +0 -1
- package/dist/assets/PierreDiffViewer-Ct2A13NO.js +0 -157
- package/dist/assets/PlanView-6AUjzNQn.js +0 -5
- package/dist/assets/SettingsView-CHI8fFaK.js +0 -28
- package/dist/assets/ToolPartDiffPreview-DPAATNn6.js +0 -8
- package/dist/assets/WalkthroughView-AX-u2pFg.js +0 -4
- package/dist/assets/contextPanelEmbeddedChat-C9EcRSDF.js +0 -1
- package/dist/assets/de-DqVn5vme.js +0 -9
- package/dist/assets/es-hj43Z53i.js +0 -15
- package/dist/assets/fr-BmkZt2mF.js +0 -13
- package/dist/assets/index-L_ncV-6H.css +0 -1
- package/dist/assets/index-qES19dlJ.js +0 -7
- package/dist/assets/ja-DioMIEGF.js +0 -15
- package/dist/assets/ko-BqPgaQJb.js +0 -15
- package/dist/assets/main-CYgSu6dx.js +0 -928
- package/dist/assets/markdownCore-CWRCqSH2.js +0 -3
- package/dist/assets/patchFileDiff-BpMQZnYu.js +0 -10
- package/dist/assets/pl-slULBF4R.js +0 -15
- package/dist/assets/pt-BR-BqH8fuCH.js +0 -15
- package/dist/assets/renderElectronMiniChatApp-D77bmLqo.js +0 -2
- package/dist/assets/renderMobileApp-BQ3Kdm-d.js +0 -25
- package/dist/assets/runtimeEndpointReset-CRGn1gVj.js +0 -16
- package/dist/assets/scheduledTasksApi-BSRCtP6T.js +0 -1
- package/dist/assets/tr-CjEbw1Aw.js +0 -6
- package/dist/assets/uk-BkkfxbOs.js +0 -15
- package/dist/assets/useInlineCommentController-JsBboQwt.js +0 -2
- package/dist/assets/useRootScrollLock-C0N9mCwz.js +0 -1
- package/dist/assets/vendor-ghostty-web-CrxinGGH.js +0 -13
- package/dist/assets/vendor-legendapp-list-gg7YLRW7.js +0 -1
- package/dist/assets/vendor-zod-BLfBSgBh.js +0 -39
- package/dist/assets/zh-CN-C6FMdVgv.js +0 -15
- package/dist/assets/zh-TW-CdcMjDxv.js +0 -15
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const TERMINAL_SHELL_IDS = ['bash', 'zsh', 'sh', 'fish', 'pwsh', 'powershell', 'cmd', 'dash', 'ksh', 'nu'];
|
|
2
2
|
const TERMINAL_SHELL_ID_SET = new Set(TERMINAL_SHELL_IDS);
|
|
3
|
+
const isString = (value) => String(value) === value;
|
|
3
4
|
|
|
4
5
|
export const normalizeTerminalShell = (value) => {
|
|
5
6
|
if (typeof value !== 'string') return null;
|
|
@@ -24,6 +25,22 @@ export const getTerminalShellLoginArgs = (executable, platform = process.platfor
|
|
|
24
25
|
return null;
|
|
25
26
|
};
|
|
26
27
|
|
|
28
|
+
export const buildTerminalShellLaunch = (executable, { mode = 'interactive', command = null, loginShell = false, platform = process.platform } = {}) => {
|
|
29
|
+
const loginArgs = loginShell ? getTerminalShellLoginArgs(executable, platform) : [];
|
|
30
|
+
if (!loginArgs) throw new Error(`Terminal shell "${shellIdFromPath(executable) ?? executable}" does not support login mode`);
|
|
31
|
+
|
|
32
|
+
if (mode === 'interactive') return { executable, args: loginArgs };
|
|
33
|
+
|
|
34
|
+
const trimmedCommand = isString(command) ? command.trim() : '';
|
|
35
|
+
if (!trimmedCommand) throw new Error('Terminal command is required');
|
|
36
|
+
|
|
37
|
+
const id = shellIdFromPath(executable);
|
|
38
|
+
if (id === 'nu') return { executable, args: [...loginArgs, '-c', trimmedCommand] };
|
|
39
|
+
if (id === 'pwsh' || id === 'powershell') return { executable, args: [...loginArgs, '-Command', trimmedCommand] };
|
|
40
|
+
if (id === 'cmd') return { executable, args: ['/d', '/s', '/c', trimmedCommand] };
|
|
41
|
+
return { executable, args: [...loginArgs, '-i', '-c', trimmedCommand] };
|
|
42
|
+
};
|
|
43
|
+
|
|
27
44
|
export const createTerminalShellResolver = ({ fs, path, searchPathFor, isExecutable, buildAugmentedPath = () => env.PATH || '', platform = process.platform, env = process.env }) => {
|
|
28
45
|
const resolveExecutable = (candidate) => {
|
|
29
46
|
if (!candidate) return null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import * as shells from './shells.js';
|
|
4
|
+
|
|
5
|
+
const { createTerminalShellResolver, getTerminalShellLoginArgs } = shells;
|
|
4
6
|
|
|
5
7
|
const createResolver = ({ platform = 'linux', env = {}, augmentedPath = '/augmented/bin', executables = [] } = {}) => {
|
|
6
8
|
const available = new Set(executables);
|
|
@@ -70,4 +72,33 @@ describe('terminal shell resolver', () => {
|
|
|
70
72
|
expect(getTerminalShellLoginArgs('C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'win32')).toBeNull();
|
|
71
73
|
expect(getTerminalShellLoginArgs('/bin/dash', 'linux')).toBeNull();
|
|
72
74
|
});
|
|
75
|
+
|
|
76
|
+
it('builds interactive shell launches by shell family', () => {
|
|
77
|
+
const buildLaunch = shells.buildTerminalShellLaunch;
|
|
78
|
+
|
|
79
|
+
expect(buildLaunch('/bin/bash', { mode: 'interactive', loginShell: true, platform: 'linux' })).toEqual({ executable: '/bin/bash', args: ['-l'] });
|
|
80
|
+
expect(buildLaunch('/opt/homebrew/bin/fish', { mode: 'interactive', loginShell: true, platform: 'darwin' })).toEqual({ executable: '/opt/homebrew/bin/fish', args: ['--login'] });
|
|
81
|
+
expect(buildLaunch('/usr/bin/nu', { mode: 'interactive', loginShell: true, platform: 'linux' })).toEqual({ executable: '/usr/bin/nu', args: ['--login'] });
|
|
82
|
+
expect(buildLaunch('/usr/bin/pwsh', { mode: 'interactive', loginShell: true, platform: 'linux' })).toEqual({ executable: '/usr/bin/pwsh', args: ['-Login'] });
|
|
83
|
+
expect(buildLaunch('C:\\Windows\\System32\\cmd.exe', { mode: 'interactive', loginShell: false, platform: 'win32' })).toEqual({ executable: 'C:\\Windows\\System32\\cmd.exe', args: [] });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('builds command launches by shell family', () => {
|
|
87
|
+
const buildLaunch = shells.buildTerminalShellLaunch;
|
|
88
|
+
|
|
89
|
+
expect(buildLaunch('/bin/zsh', { mode: 'command', command: 'printf ready', loginShell: true, platform: 'linux' })).toEqual({ executable: '/bin/zsh', args: ['-l', '-i', '-c', 'printf ready'] });
|
|
90
|
+
expect(buildLaunch('/opt/homebrew/bin/fish', { mode: 'command', command: 'echo ready', loginShell: true, platform: 'darwin' })).toEqual({ executable: '/opt/homebrew/bin/fish', args: ['--login', '-i', '-c', 'echo ready'] });
|
|
91
|
+
expect(buildLaunch('/usr/bin/nu', { mode: 'command', command: 'ls', loginShell: true, platform: 'linux' })).toEqual({ executable: '/usr/bin/nu', args: ['--login', '-c', 'ls'] });
|
|
92
|
+
expect(buildLaunch('/usr/bin/pwsh', { mode: 'command', command: 'Get-ChildItem', loginShell: true, platform: 'linux' })).toEqual({ executable: '/usr/bin/pwsh', args: ['-Login', '-Command', 'Get-ChildItem'] });
|
|
93
|
+
expect(buildLaunch('C:\\Program Files\\PowerShell\\7\\pwsh.exe', { mode: 'command', command: 'Get-Date', loginShell: false, platform: 'win32' })).toEqual({ executable: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', args: ['-Command', 'Get-Date'] });
|
|
94
|
+
expect(buildLaunch('C:\\Windows\\System32\\cmd.exe', { mode: 'command', command: 'dir', loginShell: false, platform: 'win32' })).toEqual({ executable: 'C:\\Windows\\System32\\cmd.exe', args: ['/d', '/s', '/c', 'dir'] });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('rejects unsupported login and command combinations', () => {
|
|
98
|
+
const buildLaunch = shells.buildTerminalShellLaunch;
|
|
99
|
+
|
|
100
|
+
expect(() => buildLaunch('/bin/sh', { mode: 'interactive', loginShell: true, platform: 'linux' })).toThrow('does not support login mode');
|
|
101
|
+
expect(() => buildLaunch('/bin/dash', { mode: 'command', command: 'pwd', loginShell: true, platform: 'linux' })).toThrow('does not support login mode');
|
|
102
|
+
expect(() => buildLaunch('/bin/bash', { mode: 'command', command: '', loginShell: false, platform: 'linux' })).toThrow('Terminal command is required');
|
|
103
|
+
});
|
|
73
104
|
});
|
|
@@ -310,6 +310,7 @@ const isUrlAuthWebSocketPath = (pathname) => {
|
|
|
310
310
|
|| pathname === '/api/openchamber/realtime-proxy/ws'
|
|
311
311
|
|| pathname === '/api/terminal/ws'
|
|
312
312
|
|| pathname === '/api/dictation/ws'
|
|
313
|
+
|| pathname === '/api/dev-tunnel'
|
|
313
314
|
|| pathname.startsWith('/api/preview/proxy/');
|
|
314
315
|
};
|
|
315
316
|
|
|
@@ -984,7 +985,9 @@ export const createUiAuth = ({
|
|
|
984
985
|
handlePasskeyList,
|
|
985
986
|
handlePasskeyRevoke,
|
|
986
987
|
handleResetAuth,
|
|
987
|
-
ensureSessionToken:
|
|
988
|
+
ensureSessionToken: (req, _res) => {
|
|
989
|
+
const urlAuth = authenticateUrlAuthToken(req);
|
|
990
|
+
if (urlAuth) return clientSessionToken(urlAuth);
|
|
988
991
|
return resolveAuthenticatedSessionToken(req);
|
|
989
992
|
},
|
|
990
993
|
dispose,
|
|
@@ -221,6 +221,22 @@ describe('ui auth client credential seam', () => {
|
|
|
221
221
|
};
|
|
222
222
|
expect(await auth.ensureSessionToken(dictationWsReq, null)).toBe('client:device-1');
|
|
223
223
|
|
|
224
|
+
const devTunnelWsReq = {
|
|
225
|
+
method: 'GET',
|
|
226
|
+
path: '/api/dev-tunnel',
|
|
227
|
+
url: `/api/dev-tunnel?port=4322&oc_url_token=${encodeURIComponent(urlToken)}`,
|
|
228
|
+
headers: { upgrade: 'websocket' },
|
|
229
|
+
};
|
|
230
|
+
expect(await auth.ensureSessionToken(devTunnelWsReq, null)).toBe('client:device-1');
|
|
231
|
+
|
|
232
|
+
const devTunnelSubpathWsReq = {
|
|
233
|
+
method: 'GET',
|
|
234
|
+
path: '/api/dev-tunnel/private',
|
|
235
|
+
url: `/api/dev-tunnel/private?port=4322&oc_url_token=${encodeURIComponent(urlToken)}`,
|
|
236
|
+
headers: { upgrade: 'websocket' },
|
|
237
|
+
};
|
|
238
|
+
expect(await auth.ensureSessionToken(devTunnelSubpathWsReq, null)).toBe(null);
|
|
239
|
+
|
|
224
240
|
const dictationHttpReq = {
|
|
225
241
|
method: 'GET',
|
|
226
242
|
path: '/api/dictation/ws',
|
|
@@ -52,20 +52,39 @@ written against staged code never silently re-anchors onto an unstaged edit.
|
|
|
52
52
|
| Kind | Sections | Notes |
|
|
53
53
|
|---|---|---|
|
|
54
54
|
| `working-tree` (`all` \| `staged` \| `working`) | `staged`, `working` | Untracked files are fetched individually because `git diff` omits them |
|
|
55
|
-
| `branch` | `branch` | `getRangeDiff`
|
|
56
|
-
| `
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
the current branch's
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
| `branch` | `branch` | `getRangeDiff` with `includeWorkingTree: true` compares the selected merge base with current files, including committed and local work in one net diff |
|
|
56
|
+
| `commit` | `commit` | `getCommitDiff` compares the full selected commit hash with its first parent; root commits compare with an empty tree |
|
|
57
|
+
| `pr` | `pr:<number>` | GitHub's committed pull-request diff, without local working-tree changes |
|
|
58
|
+
|
|
59
|
+
Changes and walkthrough resolve the current branch's base through
|
|
60
|
+
`packages/ui/src/hooks/useBranchComparisonBase.ts`. An explicit choice in Changes
|
|
61
|
+
outranks reflog detection. Both toolbars use
|
|
62
|
+
`packages/ui/src/components/views/git/BranchComparisonSelector.tsx` to select or
|
|
63
|
+
change the base directly. Walkthrough allows selecting Branch before a base is
|
|
64
|
+
known and waits for a valid choice before loading or generating. Opening
|
|
65
|
+
walkthrough from Changes carries the selected base and head; later selections
|
|
66
|
+
in either toolbar update both comparisons.
|
|
67
|
+
|
|
68
|
+
Commit mode uses the shared `CommitComparisonSelector` in both toolbars. It
|
|
69
|
+
lists the latest 50 commits reachable from the checked-out branch, with subject,
|
|
70
|
+
author, date, and short hash. Opening the picker refreshes that list; selecting a
|
|
71
|
+
commit changes the comparison, not the checkout. Changes hands the selected full
|
|
72
|
+
hash to walkthrough. The server accepts full object IDs for commit sources and
|
|
73
|
+
keys their cache entries and generation jobs as `commit:<hash>`, so reviews of
|
|
74
|
+
different commits cannot overwrite each other. Existing source keys keep their
|
|
75
|
+
format. Commit reads have no working-tree freshness dependency, and selecting a
|
|
76
|
+
commit never starts model generation.
|
|
77
|
+
|
|
78
|
+
The Git module owns exact-ref and working-tree comparison semantics. Local and
|
|
79
|
+
remote bases remain distinct, and a checkout during a branch review requires
|
|
80
|
+
the source to be resolved for the new branch rather than including another
|
|
81
|
+
branch's local files.
|
|
82
|
+
|
|
83
|
+
Successful status refreshes invalidate the visible branch comparison even when
|
|
84
|
+
file names and insertion/deletion counts stay the same. Walkthrough refreshes
|
|
85
|
+
its current hunk index while visible; regeneration remains user-initiated. The
|
|
86
|
+
content-addressed cache continues to reuse an old review only when its hunks
|
|
87
|
+
match, and otherwise reports stale anchors and uncovered current hunks.
|
|
69
88
|
|
|
70
89
|
The panel offers the current branch's pull request on its own: it registers with
|
|
71
90
|
the shared GitHub PR status store (`useGitHubPrStatusStore`) rather than waiting
|
|
@@ -474,6 +474,7 @@ async function runGeneration({ directory, source, repoRoot, key, force, explicit
|
|
|
474
474
|
prompt: options.prompt,
|
|
475
475
|
system: options.system,
|
|
476
476
|
directory,
|
|
477
|
+
sessionID: `openchamber-walkthrough-${cacheKey}`,
|
|
477
478
|
model: `${model.providerID}/${model.modelID}`,
|
|
478
479
|
responseSchema: options.responseSchema,
|
|
479
480
|
onOverflow: 'error',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import os from 'os';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import { readMergedSettingsSync } from '../opencode/settings-files.js';
|
|
4
5
|
|
|
5
6
|
// The walkthrough may run on a different model than the rest of the small-model
|
|
6
7
|
// callers. Those callers want cheap and fast; this one needs structured output
|
|
@@ -23,16 +24,11 @@ const SETTINGS_FILE = path.join(
|
|
|
23
24
|
* not use the small model" with nothing to use instead.
|
|
24
25
|
*/
|
|
25
26
|
export function readWalkthroughModelOverride() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} catch {
|
|
34
|
-
// No settings file, unreadable, or malformed all mean the same thing: no
|
|
35
|
-
// override, use the small model.
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
27
|
+
// No settings file, unreadable, or malformed all mean the same thing: no
|
|
28
|
+
// override, use the small model.
|
|
29
|
+
const settings = readMergedSettingsSync({ fs, path, settingsFilePath: SETTINGS_FILE });
|
|
30
|
+
const override = typeof settings.walkthroughModelOverride === 'string'
|
|
31
|
+
? settings.walkthroughModelOverride.trim()
|
|
32
|
+
: '';
|
|
33
|
+
return override || null;
|
|
38
34
|
}
|
|
@@ -86,7 +86,9 @@ export function buildPrompt({ digest, fileCount, hunkCount, source, previousWalk
|
|
|
86
86
|
? `Uncommitted local changes (${source.scope === 'all' ? 'staged and unstaged' : source.scope}).`
|
|
87
87
|
: source.kind === 'branch'
|
|
88
88
|
? `All work on branch "${source.headRef}" that is not in "${source.baseRef}". Changes merged in from ${source.baseRef} are already excluded.`
|
|
89
|
-
:
|
|
89
|
+
: source.kind === 'commit'
|
|
90
|
+
? `Only the changes introduced by commit ${source.hash}, relative to its first parent (or the empty tree for a root commit).`
|
|
91
|
+
: `Pull request #${source.number}.`;
|
|
90
92
|
|
|
91
93
|
const prompt = `Reviewing: ${sourceLine}
|
|
92
94
|
|
|
@@ -15,6 +15,7 @@ describe('walkthrough routes', () => {
|
|
|
15
15
|
let job;
|
|
16
16
|
|
|
17
17
|
let lastArgs;
|
|
18
|
+
let generateCalls = 0;
|
|
18
19
|
|
|
19
20
|
const service = {
|
|
20
21
|
async getWalkthrough(args) {
|
|
@@ -23,6 +24,7 @@ describe('walkthrough routes', () => {
|
|
|
23
24
|
},
|
|
24
25
|
async generateWalkthrough(args) {
|
|
25
26
|
lastArgs = args;
|
|
27
|
+
generateCalls += 1;
|
|
26
28
|
if (job) return job;
|
|
27
29
|
job = new Promise((resolve) => {
|
|
28
30
|
releaseJob = () => resolve({ walkthrough: { title: 'DONE' }, hunks: [], hunkCount: 1 });
|
|
@@ -54,12 +56,27 @@ describe('walkthrough routes', () => {
|
|
|
54
56
|
});
|
|
55
57
|
|
|
56
58
|
afterEach(async () => {
|
|
59
|
+
// A response a failed test never received keeps its keep-alive socket
|
|
60
|
+
// open, and server.close() would wait on it until the hook timeout.
|
|
61
|
+
server.closeAllConnections();
|
|
57
62
|
await new Promise((resolve) => server.close(resolve));
|
|
58
63
|
});
|
|
59
64
|
|
|
65
|
+
// Resolves once the route has asked the service to generate one more time
|
|
66
|
+
// than `seen`. A fixed sleep assumed the request had arrived by then; on a
|
|
67
|
+
// loaded runner it had not, and the step that followed acted on a request
|
|
68
|
+
// the server had not seen yet.
|
|
69
|
+
const untilGenerateCalled = async (seen) => {
|
|
70
|
+
for (let attempt = 0; attempt < 300 && generateCalls <= seen; attempt += 1) {
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
72
|
+
}
|
|
73
|
+
if (generateCalls <= seen) throw new Error('the route never asked the service to generate');
|
|
74
|
+
};
|
|
75
|
+
|
|
60
76
|
it('answers a generation request that nobody interrupted', async () => {
|
|
77
|
+
const seen = generateCalls;
|
|
61
78
|
const pending = generate();
|
|
62
|
-
await
|
|
79
|
+
await untilGenerateCalled(seen);
|
|
63
80
|
releaseJob();
|
|
64
81
|
|
|
65
82
|
const body = await (await pending).json();
|
|
@@ -69,8 +86,9 @@ describe('walkthrough routes', () => {
|
|
|
69
86
|
|
|
70
87
|
it('delivers the result to a client that reconnected after a refresh', async () => {
|
|
71
88
|
const controller = new AbortController();
|
|
89
|
+
const seen = generateCalls;
|
|
72
90
|
generate(controller.signal).catch(() => {});
|
|
73
|
-
await
|
|
91
|
+
await untilGenerateCalled(seen);
|
|
74
92
|
controller.abort();
|
|
75
93
|
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
76
94
|
|
|
@@ -80,8 +98,9 @@ describe('walkthrough routes', () => {
|
|
|
80
98
|
)).json();
|
|
81
99
|
expect(read.generating).toBe(true);
|
|
82
100
|
|
|
101
|
+
const seenBeforeReattach = generateCalls;
|
|
83
102
|
const reattached = generate();
|
|
84
|
-
await
|
|
103
|
+
await untilGenerateCalled(seenBeforeReattach);
|
|
85
104
|
releaseJob();
|
|
86
105
|
|
|
87
106
|
const body = await (await reattached).json();
|
|
@@ -108,12 +127,13 @@ describe('walkthrough routes', () => {
|
|
|
108
127
|
);
|
|
109
128
|
expect(lastArgs.language).toBe('uk');
|
|
110
129
|
|
|
130
|
+
const seen = generateCalls;
|
|
111
131
|
const pending = fetch(`${base}/api/walkthrough/generate`, {
|
|
112
132
|
method: 'POST',
|
|
113
133
|
headers: { 'Content-Type': 'application/json' },
|
|
114
134
|
body: JSON.stringify({ directory: '/repo', source: SOURCE, language: 'ja' }),
|
|
115
135
|
});
|
|
116
|
-
await
|
|
136
|
+
await untilGenerateCalled(seen);
|
|
117
137
|
releaseJob();
|
|
118
138
|
await pending;
|
|
119
139
|
|
|
@@ -129,8 +149,9 @@ describe('walkthrough routes', () => {
|
|
|
129
149
|
});
|
|
130
150
|
|
|
131
151
|
it('cancels through its own endpoint rather than a dropped connection', async () => {
|
|
152
|
+
const seen = generateCalls;
|
|
132
153
|
generate().catch(() => {});
|
|
133
|
-
await
|
|
154
|
+
await untilGenerateCalled(seen);
|
|
134
155
|
|
|
135
156
|
const response = await fetch(`${base}/api/walkthrough/cancel`, {
|
|
136
157
|
method: 'POST',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDiff, getRangeDiff, getUntrackedDiffs, listUntrackedPaths } from '../git/service.js';
|
|
1
|
+
import { getDiff, getRangeDiff, getCommitDiff, getUntrackedDiffs, listUntrackedPaths } from '../git/service.js';
|
|
2
2
|
|
|
3
3
|
// A walkthrough source resolves to one or more diff *sections*. A section is a
|
|
4
4
|
// patch plus the scope its hunk ids live in; keeping staged and working-tree
|
|
@@ -48,6 +48,18 @@ export function parseSource(raw) {
|
|
|
48
48
|
return { kind: 'pr', number };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
if (raw.kind === 'commit') {
|
|
52
|
+
// Sources are content-addressed: accept a full object id, never a moving ref.
|
|
53
|
+
if (!/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i.test(raw.hash)) {
|
|
54
|
+
throw new WalkthroughSourceError('commit sources require a full commit hash');
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return { kind: 'commit', hash: raw.hash.toLowerCase() };
|
|
58
|
+
} catch {
|
|
59
|
+
throw new WalkthroughSourceError('commit sources require a full commit hash');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
throw new WalkthroughSourceError(`Unknown source kind "${String(raw.kind)}"`);
|
|
52
64
|
}
|
|
53
65
|
|
|
@@ -58,6 +70,7 @@ export function parseSource(raw) {
|
|
|
58
70
|
export function sourceKey(source) {
|
|
59
71
|
if (source.kind === 'working-tree') return `working-tree:${source.scope}`;
|
|
60
72
|
if (source.kind === 'branch') return `branch:${source.baseRef}...${source.headRef}`;
|
|
73
|
+
if (source.kind === 'commit') return `commit:${source.hash}`;
|
|
61
74
|
return `pr:${source.number}`;
|
|
62
75
|
}
|
|
63
76
|
|
|
@@ -97,13 +110,21 @@ export async function loadSourceSections(directory, source, { getPullRequestDiff
|
|
|
97
110
|
}
|
|
98
111
|
|
|
99
112
|
if (source.kind === 'branch') {
|
|
100
|
-
const patch = await getRangeDiff(directory, { base: source.baseRef, head: source.headRef });
|
|
113
|
+
const patch = await getRangeDiff(directory, { base: source.baseRef, head: source.headRef, includeWorkingTree: true });
|
|
101
114
|
return {
|
|
102
115
|
sections: patch && patch.trim() ? [{ scope: 'branch', patch }] : [],
|
|
103
116
|
meta: { baseRef: source.baseRef, headRef: source.headRef },
|
|
104
117
|
};
|
|
105
118
|
}
|
|
106
119
|
|
|
120
|
+
if (source.kind === 'commit') {
|
|
121
|
+
const patch = await getCommitDiff(directory, { hash: source.hash });
|
|
122
|
+
return {
|
|
123
|
+
sections: patch.trim() ? [{ scope: 'commit', patch }] : [],
|
|
124
|
+
meta: { hash: source.hash },
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
107
128
|
if (typeof getPullRequestDiff !== 'function') {
|
|
108
129
|
throw new WalkthroughSourceError('Pull request diffs are unavailable', 500);
|
|
109
130
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{R as S,f as oe,j as s}from"./vendor-react-BUCujlKS.js";import{u as Ae}from"./vendor-tanstack-react-virtual-g05Cx3z9.js";import{f as Q,ap as ze,a6 as fe,a7 as me,I as R,a8 as ue,h as Z,B as J,a1 as Ee,h4 as Ie,bG as pe,bH as ge,bI as xe,bJ as be,bK as ye,bL as ve,b5 as Te}from"./useAppFontEffects-COAeIX-D.js";import{u as Ce}from"./index-qES19dlJ.js";const ke={"?":{code:"?",color:"var(--status-info)",description:"Untracked file"},A:{code:"A",color:"var(--status-success)",description:"New file"},D:{code:"D",color:"var(--status-error)",description:"Deleted file"},R:{code:"R",color:"var(--status-info)",description:"Renamed file"},C:{code:"C",color:"var(--status-info)",description:"Copied file"},M:{code:"M",color:"var(--status-warning)",description:"Modified file"}},Me=ke.M;function He(p){const e=p.index?.trim(),t=p.working_dir?.trim();return e&&e!=="?"?e.charAt(0):t?t.charAt(0):e?.charAt(0)||t?.charAt(0)||"M"}function Re(p){const e=He(p);return ke[e]??Me}const $e=S.memo(function(e){const t=oe.c(58),{file:o,actionLabel:x,actionSymbol:b,onAction:m,onViewDiff:f,onRevert:l,isReverting:d,stats:z,rowPaddingClassName:g,indentPx:y,actionAtStart:A,showRevert:$}=e,j=y===void 0?0:y,r=A===void 0?!1:A,w=$===void 0?!0:$;let N;t[0]!==o?(N=Re(o),t[0]=o,t[1]=N):N=t[1];const h=N,{t:E}=Q(),F=h.description,M=z?.insertions??0,C=z?.deletions??0;let D;t[2]!==m||t[3]!==f?(D=U=>{U.key===" "?(U.preventDefault(),m()):U.key==="Enter"&&(U.preventDefault(),f())},t[2]=m,t[3]=f,t[4]=D):D=t[4];const V=D;let I;t[5]!==m?(I=U=>{U.preventDefault(),U.stopPropagation(),m()},t[5]=m,t[6]=I):I=t[6];const u=I;let P;t[7]!==l?(P=U=>{U.preventDefault(),U.stopPropagation(),l()},t[7]=l,t[8]=P):P=t[8];const W=P;let L;t[9]!==x||t[10]!==b||t[11]!==u?(L=s.jsx("button",{type:"button",onClick:u,className:"flex size-5 shrink-0 items-center justify-center rounded typography-micro font-semibold text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]","aria-label":x,title:x,children:b}),t[9]=x,t[10]=b,t[11]=u,t[12]=L):L=t[12];const H=L,X=`group flex items-center gap-2 py-1.5 cursor-pointer ${g??"px-3"}`;let T;t[13]!==j?(T=j>0?{paddingLeft:`${j}px`}:void 0,t[13]=j,t[14]=T):T=t[14];const Y=r?H:null;let K;t[15]!==h.color?(K={color:h.color},t[15]=h.color,t[16]=K):K=t[16];let G;t[17]!==h.code||t[18]!==F||t[19]!==K?(G=s.jsx("span",{className:"typography-micro font-semibold w-4 text-center uppercase",style:K,title:F,"aria-label":F,children:h.code}),t[17]=h.code,t[18]=F,t[19]=K,t[20]=G):G=t[20];let O;t[21]!==o.path?(O=s.jsx(ze,{filePath:o.path,className:"h-3.5 w-3.5 shrink-0"}),t[21]=o.path,t[22]=O):O=t[22];let B;if(t[23]!==o.path){e:{const U=o.path.lastIndexOf("/");if(U===-1){let ne;t[25]===Symbol.for("react.memo_cache_sentinel")?(ne={direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},t[25]=ne):ne=t[25],B=s.jsx("span",{className:"flex-1 min-w-0 truncate typography-ui-label text-foreground",style:ne,title:o.path,children:o.path});break e}const De=o.path.slice(0,U),Ve=o.path.slice(U);let te;t[26]===Symbol.for("react.memo_cache_sentinel")?(te={direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},t[26]=te):te=t[26];let se;t[27]===Symbol.for("react.memo_cache_sentinel")?(se=s.jsx("span",{className:"text-muted-foreground",children:"/"}),t[27]=se):se=t[27];const re=s.jsx("span",{className:"text-foreground",children:Ve.slice(1)});let ie;t[28]!==re?(ie=s.jsxs("span",{className:"flex-shrink-0 typography-ui-label",children:[se,re]}),t[28]=re,t[29]=ie):ie=t[29],B=s.jsxs("span",{className:"flex-1 min-w-0 flex items-baseline overflow-hidden",title:o.path,children:[s.jsx("span",{className:"min-w-0 truncate typography-ui-label text-muted-foreground",style:te,children:De}),ie]})}t[23]=o.path,t[24]=B}else B=t[24];let q;t[30]===Symbol.for("react.memo_cache_sentinel")?(q={color:"var(--status-success)"},t[30]=q):q=t[30];let i;t[31]!==M?(i=s.jsxs("span",{style:q,children:["+",M]}),t[31]=M,t[32]=i):i=t[32];let n,a;t[33]===Symbol.for("react.memo_cache_sentinel")?(n=s.jsx("span",{className:"text-muted-foreground mx-0.5",children:"/"}),a={color:"var(--status-error)"},t[33]=n,t[34]=a):(n=t[33],a=t[34]);let c;t[35]!==C?(c=s.jsxs("span",{style:a,children:["-",C]}),t[35]=C,t[36]=c):c=t[36];let k;t[37]!==i||t[38]!==c?(k=s.jsxs("span",{className:"shrink-0 typography-micro",children:[i,n,c]}),t[37]=i,t[38]=c,t[39]=k):k=t[39];let v;t[40]!==o.path||t[41]!==W||t[42]!==d||t[43]!==w||t[44]!==E?(v=w?s.jsxs(fe,{children:[s.jsx(me,{asChild:!0,children:s.jsx("button",{type:"button",onClick:W,disabled:d,className:"flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50","aria-label":E("gitView.changes.revertFileAria",{path:o.path}),children:d?s.jsx(R,{name:"loader-4",className:"size-3.5 animate-spin"}):s.jsx(R,{name:"arrow-go-back",className:"size-3.5"})})}),s.jsx(ue,{sideOffset:8,children:E("gitView.changes.revertFileTooltip")})]}):null,t[40]=o.path,t[41]=W,t[42]=d,t[43]=w,t[44]=E,t[45]=v):v=t[45];const _=r?null:H;let ee;return t[46]!==V||t[47]!==f||t[48]!==T||t[49]!==Y||t[50]!==G||t[51]!==O||t[52]!==B||t[53]!==k||t[54]!==v||t[55]!==_||t[56]!==X?(ee=s.jsxs("div",{className:X,role:"button",tabIndex:0,onClick:f,onKeyDown:V,style:T,children:[Y,G,O,B,k,v,_]}),t[46]=V,t[47]=f,t[48]=T,t[49]=Y,t[50]=G,t[51]=O,t[52]=B,t[53]=k,t[54]=v,t[55]=_,t[56]=X,t[57]=ee):ee=t[57],ee}),je=14,Se=p=>p.replace(/\\/g,"/").replace(/^\/+/,"").trim(),we=(p,e)=>({id:`dir:${p}`,path:p,name:e,children:new Map,directFiles:[],files:[]}),Fe=p=>{const e=we("","");for(const t of p){const o=Se(t.path);if(!o)continue;const b=o.split("/").filter(Boolean).slice(0,-1);let m=e;if(m.files.push(t),b.length>0){let f="";for(const l of b){f=f?`${f}/${l}`:l;const d=m.children.get(l);if(d){d.files.push(t),m=d;continue}const z=we(f,l);z.files.push(t),m.children.set(l,z),m=z}}m.directFiles.push(t)}return e},Pe=(p,e)=>{const t=[],o=(x,b)=>{const m=Array.from(x.children.values()).sort((l,d)=>l.path.localeCompare(d.path));for(const l of m)t.push({key:l.id,kind:"directory",depth:b,directory:l}),e.has(l.path)&&o(l,b+1);const f=[...x.directFiles].sort((l,d)=>l.path.localeCompare(d.path));for(const l of f)t.push({key:`file:${Se(l.path)}`,kind:"file",depth:b,file:l})};return o(p,0),t},Le=1e3,Ne=34,ce=30,le="pl-0 pr-2",de=(p,e)=>`${p} ${e}`,Ye=({groups:p,diffStats:e,revertingPaths:t,isRevertingAll:o=!1,headerBackgroundClassName:x="bg-sidebar",onVisiblePathsChange:b,onRevertAll:m,onRevertDirectory:f})=>{const{t:l}=Q(),d=S.useRef(null),g=Ce(i=>i.gitChangesViewMode)==="tree",y=S.useMemo(()=>p.filter(i=>i.entries.length>0),[p]),[A,$]=S.useState(new Set),[j,r]=S.useState(new Set),[w,N]=S.useState(!1),[h,E]=S.useState(null),F=S.useMemo(()=>y.map(i=>Fe(i.entries)),[y]),M=S.useMemo(()=>{const i=[];return y.forEach((n,a)=>{Array.from(F[a]?.children.values()??[]).forEach(c=>{i.push(de(n.id,c.path))})}),i},[F,y]);S.useEffect(()=>{g&&r(i=>{const n=new Set,a=new Set(M);return i.forEach(c=>{(c.slice(c.indexOf(" ")+1).includes("/")||a.has(c))&&n.add(c)}),M.forEach(c=>n.add(c)),n})},[g,M]);const C=S.useMemo(()=>{const i=[];return y.forEach((n,a)=>{if(i.push({type:"header",key:`header:${n.id}`,groupIndex:a}),!A.has(n.id)){if(g){const c=new Set;j.forEach(v=>{v.startsWith(`${n.id} `)&&c.add(v.slice(n.id.length+1))}),Pe(F[a],c).forEach(v=>{v.kind==="file"?i.push({type:"file",key:`${n.id}:${v.key}`,groupIndex:a,file:v.file,depth:v.depth}):i.push({type:"directory",key:`${n.id}:${v.key}`,groupIndex:a,directory:v.directory,depth:v.depth})});return}n.entries.forEach(c=>{i.push({type:"file",key:`${n.id}:file:${c.path}`,groupIndex:a,file:c,depth:0})})}}),m&&y.length>0&&i.push({type:"revert-all",key:"revert-all"}),i},[A,j,g,m,F,y]),D=C.length,V=D>=Le,I=Ae({count:D,enabled:V,getScrollElement:()=>d.current,estimateSize:()=>Ne,overscan:12,getItemKey:i=>C[i]?.key??i}),u=I.getVirtualItems(),P=S.useMemo(()=>{if(!V)return 0;const i=d.current?.scrollTop??0;return u.find(a=>a.end>i)?.index??0},[V,u,d]);S.useEffect(()=>{if(!b)return;const i=n=>n&&n.type==="file"?n.file.path:null;if(D===0){b([]);return}if(!V){const n=[];for(const a of C)if(a.type==="file"&&(n.push(a.file.path),n.length>=ce))break;b(n);return}b(C.slice(P,P+Math.ceil((d.current?.clientHeight??0)/Ne)+ce).map(n=>i(n)).filter(n=>!!n).slice(0,ce))},[b,D,C,V,P]);const W=S.useCallback(i=>{$(n=>{const a=new Set(n);return a.has(i)?a.delete(i):a.add(i),a})},[]),L=S.useCallback((i,n)=>{r(a=>{const c=new Set(a),k=de(i,n);return c.has(k)?c.delete(k):c.add(k),c})},[]),H=S.useMemo(()=>{const i=new Set;return y.forEach(n=>n.entries.forEach(a=>i.add(a.path))),Array.from(i)},[y]),X=H.length,T=h?o||h.paths.some(i=>t.has(i)):!1,Y=S.useCallback(async()=>{!m||o||H.length===0||(await m(H),N(!1))},[H,o,m]),K=S.useCallback(async()=>{!f||!h||T||(await f(h.paths),E(null))},[T,f,h]),G=S.useCallback((i,n)=>{const a=A.has(i.id),c=i.entries.length;return s.jsxs("div",{className:Z("sticky top-0 z-10 flex items-center gap-2 py-2",x,le,!n&&"mt-1 border-t border-border/40"),children:[s.jsx("button",{type:"button",onClick:()=>i.onActionAll(i.entries.map(k=>k.path)),className:"flex size-5 shrink-0 items-center justify-center rounded typography-micro font-semibold text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]","aria-label":i.actionAllLabel,title:i.actionAllLabel,children:i.actionSymbol}),s.jsxs("button",{type:"button",onClick:()=>W(i.id),className:"flex min-w-0 flex-1 items-center gap-2 rounded text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]","aria-expanded":!a,children:[s.jsx("h3",{className:"truncate typography-ui-header font-semibold text-foreground",children:i.title}),s.jsx("span",{className:"typography-meta text-muted-foreground",children:c}),s.jsx(R,{name:"arrow-down-s",className:Z("size-3.5 shrink-0 text-muted-foreground transition-transform",a&&"-rotate-90")})]})]})},[A,x,W]),O=S.useCallback((i,n,a)=>{const c=j.has(de(i.id,n.path)),k=n.files.map(_=>_.path),v=o||k.some(_=>t.has(_));return s.jsxs("div",{className:Z("group flex items-center gap-2 py-1.5",le),style:{paddingLeft:`${a*je}px`},children:[s.jsxs("button",{type:"button",onClick:()=>L(i.id,n.path),className:"flex min-w-0 flex-1 items-center gap-2 rounded text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary","aria-label":c?l("gitView.changes.collapseDirectoryAria",{path:n.path}):l("gitView.changes.expandDirectoryAria",{path:n.path}),children:[c?s.jsx(R,{name:"folder-open-fill",className:"h-4 w-4 flex-shrink-0 text-primary/60"}):s.jsx(R,{name:"folder-3-fill",className:"h-4 w-4 flex-shrink-0 text-primary/60"}),s.jsx("span",{className:"min-w-0 flex-1 truncate typography-ui-label text-foreground",title:n.path,children:n.name}),s.jsx("span",{className:"ml-auto shrink-0 typography-micro text-muted-foreground",children:n.files.length})]}),i.showRevertActions!==!1&&f?s.jsx("button",{type:"button",onClick:()=>E({path:n.path,paths:k,count:k.length}),disabled:v,className:"flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50","aria-label":l("gitView.changes.revertDirectoryAria",{path:n.path}),title:l("gitView.changes.revertDirectoryTooltip"),children:v?s.jsx(R,{name:"loader-4",className:"size-3.5 animate-spin"}):s.jsx(R,{name:"arrow-go-back",className:"size-3.5"})}):null,s.jsx("button",{type:"button",onClick:()=>i.onActionAll(n.files.map(_=>_.path)),className:"flex size-5 shrink-0 items-center justify-center rounded typography-micro font-semibold text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]","aria-label":l(i.actionSymbol==="+"?"gitView.changes.stageDirectoryAria":"gitView.changes.unstageDirectoryAria",{path:n.path}),title:l(i.actionSymbol==="+"?"gitView.changes.stageDirectoryAria":"gitView.changes.unstageDirectoryAria",{path:n.path}),children:i.actionSymbol})]})},[j,o,f,t,l,L]),B=S.useCallback((i,n)=>{if(i.type==="revert-all")return s.jsx("div",{className:Z("flex justify-end py-2",le),children:s.jsxs(J,{variant:"ghost",size:"sm",onClick:()=>N(!0),disabled:o,className:"gap-1.5 text-[var(--status-error)] hover:bg-[var(--status-error)]/10 hover:text-[var(--status-error)]",children:[s.jsx(R,{name:"arrow-go-back",className:"size-3.5"}),l("gitView.changes.revertAll")]})});const a=y[i.groupIndex];if(!a)return null;if(i.type==="header")return G(a,n);if(i.type==="directory")return O(a,i.directory,i.depth);const c=i.file;return s.jsx($e,{file:c,actionLabel:a.getActionLabel(c.path),actionSymbol:a.actionSymbol,onAction:()=>a.onActionFile(c.path),stats:e?.[c.path],onViewDiff:()=>a.onViewDiff(c.path),onRevert:()=>a.onRevertFile(c.path),isReverting:t.has(c.path)||o,rowPaddingClassName:le,indentPx:i.depth*je,actionAtStart:!g,showRevert:a.showRevertActions!==!1})},[e,o,g,O,G,t,l,y]),q=S.useCallback(i=>{const n=C[i],a=C[i-1];return!n||!a||n.type!=="file"&&n.type!=="directory"||a.type!=="file"&&a.type!=="directory"?!1:a.groupIndex===n.groupIndex},[C]);return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"relative flex h-full min-h-0 w-full flex-col overflow-hidden",children:[s.jsx(Ee,{ref:d,className:"overlay-scrollbar-target overlay-scrollbar-container min-h-0 w-full flex-1 overflow-x-hidden overflow-y-auto",children:V?s.jsx("div",{style:{height:I.getTotalSize(),position:"relative"},children:u.map(i=>{const n=C[i.index];return n?s.jsx("div",{"data-index":i.index,ref:I.measureElement,style:{position:"absolute",top:0,left:0,width:"100%",transform:`translateY(${i.start}px)`},className:Z(q(i.index)&&"before:pointer-events-none before:absolute before:left-0 before:right-2 before:top-0 before:border-t before:border-border/60"),children:B(n,i.index===0)},n.key):null})}):s.jsx("div",{role:"list","aria-label":l("gitView.changes.changedFilesAria"),children:C.map((i,n)=>s.jsx("div",{className:Z("relative",q(n)&&"before:pointer-events-none before:absolute before:left-0 before:right-2 before:top-0 before:border-t before:border-border/60"),children:B(i,n===0)},i.key))})}),s.jsx(Ie,{containerRef:d,disableHorizontal:!0})]}),s.jsx(pe,{open:w,onOpenChange:i=>{!o&&!i&&N(!1)},children:s.jsxs(ge,{className:"max-w-md",children:[s.jsxs(xe,{children:[s.jsx(be,{children:l("gitView.changes.revertAllDialogTitle")}),s.jsx(ye,{children:X===1?l("gitView.changes.revertAllDescriptionSingle",{count:X}):l("gitView.changes.revertAllDescriptionPlural",{count:X})})]}),s.jsxs(ve,{children:[s.jsx(J,{variant:"outline",size:"sm",onClick:()=>N(!1),disabled:o,children:l("gitView.common.cancel")}),s.jsx(J,{variant:"destructive",size:"sm",onClick:()=>{Y()},disabled:o,children:l(o?"gitView.changes.reverting":"gitView.changes.revertAll")})]})]})}),s.jsx(pe,{open:!!h,onOpenChange:i=>{!T&&!i&&E(null)},children:s.jsxs(ge,{className:"max-w-md",children:[s.jsxs(xe,{children:[s.jsx(be,{children:l("gitView.changes.revertDirectoryDialogTitle")}),s.jsx(ye,{children:h?h.count===1?l("gitView.changes.revertDirectoryDescriptionSingle",{count:h.count,path:h.path}):l("gitView.changes.revertDirectoryDescriptionPlural",{count:h.count,path:h.path}):null})]}),s.jsxs(ve,{children:[s.jsx(J,{variant:"outline",size:"sm",onClick:()=>E(null),disabled:T,children:l("gitView.common.cancel")}),s.jsx(J,{variant:"destructive",size:"sm",onClick:()=>{K()},disabled:T||!h,children:l(T?"gitView.changes.reverting":"gitView.changes.revertDirectory")})]})]})})]})},he=38,ae=200,Ge=p=>{const e=oe.c(23),{value:t,onChange:o,onSubmit:x,placeholder:b,disabled:m,hasTouchInput:f,isMobile:l}=p,d=m===void 0?!1:m,z=f===void 0?!1:f,g=l===void 0?!1:l,{t:y}=Q(),A=S.useRef(null),$=Ce(Oe);let j;e[0]===Symbol.for("react.memo_cache_sentinel")?(j=()=>{const u=A.current;if(!u)return;const P=document.activeElement===u,W=()=>{u.style.height=`${he}px`;const H=u.scrollHeight,X=Math.min(Math.max(H,he),ae);u.style.height=`${X}px`,u.style.overflowY=H>ae?"auto":"hidden",H>ae&&!P&&(u.scrollTop=u.scrollHeight)};W();const L=window.requestAnimationFrame(W);return()=>{window.cancelAnimationFrame(L)}},e[0]=j):j=e[0];let r;e[1]!==t?(r=[t],e[1]=t,e[2]=r):r=e[2],S.useLayoutEffect(j,r);let w;e[3]!==o?(w=u=>o(u.target.value),e[3]=o,e[4]=w):w=e[4];let N;e[5]!==x?(N=u=>{u.key==="Enter"&&(u.metaKey||u.ctrlKey)&&!u.shiftKey&&!u.altKey&&(u.preventDefault(),x?.())},e[5]=x,e[6]=N):N=e[6];let h;e[7]!==b||e[8]!==y?(h=b??y("gitView.commit.messagePlaceholder"),e[7]=b,e[8]=y,e[9]=h):h=e[9];const E=z?"on":"off",F=z?"sentences":"off",M=g||$,C=d&&"opacity-50";let D;e[10]!==C?(D=Z("w-full rounded-lg border border-border/60 bg-surface-elevated px-3 py-2 typography-ui-label text-foreground placeholder:text-muted-foreground","resize-none outline-none transition-[border-color,box-shadow] duration-150","focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]",C),e[10]=C,e[11]=D):D=e[11];let V;e[12]===Symbol.for("react.memo_cache_sentinel")?(V={minHeight:he,maxHeight:ae},e[12]=V):V=e[12];let I;return e[13]!==d||e[14]!==F||e[15]!==M||e[16]!==D||e[17]!==w||e[18]!==N||e[19]!==h||e[20]!==E||e[21]!==t?(I=s.jsx("textarea",{ref:A,value:t,onChange:w,onKeyDown:N,placeholder:h,rows:1,disabled:d,autoCorrect:E,autoCapitalize:F,spellCheck:M,className:D,style:V}),e[13]=d,e[14]=F,e[15]=M,e[16]=D,e[17]=w,e[18]=N,e[19]=h,e[20]=E,e[21]=t,e[22]=I):I=e[22],I};function Oe(p){return p.inputSpellcheckEnabled}const Ke=p=>{const e=oe.c(30),{highlights:t,onInsert:o}=p,{t:x}=Q();if(t.length===0)return null;let b;e[0]!==t||e[1]!==o?(b=()=>{o(t)},e[0]=t,e[1]=o,e[2]=b):b=e[2];const m=b;let f;e[3]!==x?(f=x("gitView.commit.aiHighlights.title"),e[3]=x,e[4]=f):f=e[4];let l;e[5]!==f?(l=s.jsx("p",{className:"typography-micro text-muted-foreground",children:f}),e[5]=f,e[6]=l):l=e[6];let d;e[7]!==x?(d=x("gitView.commit.aiHighlights.insertAria"),e[7]=x,e[8]=d):d=e[8];let z;e[9]===Symbol.for("react.memo_cache_sentinel")?(z=s.jsx(R,{name:"arrow-down",className:"size-4"}),e[9]=z):z=e[9];let g;e[10]!==m||e[11]!==d?(g=s.jsx(me,{asChild:!0,children:s.jsx(J,{variant:"ghost",size:"icon",className:"size-6",onClick:m,"aria-label":d,children:z})}),e[10]=m,e[11]=d,e[12]=g):g=e[12];let y;e[13]!==x?(y=x("gitView.commit.aiHighlights.insertTooltip"),e[13]=x,e[14]=y):y=e[14];let A;e[15]!==y?(A=s.jsx(ue,{sideOffset:8,children:y}),e[15]=y,e[16]=A):A=e[16];let $;e[17]!==g||e[18]!==A?($=s.jsxs(fe,{children:[g,A]}),e[17]=g,e[18]=A,e[19]=$):$=e[19];let j;e[20]!==l||e[21]!==$?(j=s.jsxs("div",{className:"flex items-center justify-between gap-2",children:[l,$]}),e[20]=l,e[21]=$,e[22]=j):j=e[22];let r;e[23]!==t?(r=t.map(Be),e[23]=t,e[24]=r):r=e[24];let w;e[25]!==r?(w=s.jsx("ul",{className:"space-y-1",children:r}),e[25]=r,e[26]=w):w=e[26];let N;return e[27]!==j||e[28]!==w?(N=s.jsxs("div",{className:"space-y-2 rounded-xl border border-border/60 bg-transparent px-3 py-2",children:[j,w]}),e[27]=j,e[28]=w,e[29]=N):N=e[29],N};function Be(p,e){return s.jsx("li",{className:"typography-meta text-foreground",children:p},`${p}-${e}`)}const qe=p=>{const e=oe.c(80),{stagedCount:t,commitMessage:o,onCommitMessageChange:x,generatedHighlights:b,onInsertHighlights:m,onGenerateMessage:f,isGeneratingMessage:l,onCommit:d,onCommitAndPush:z,commitAction:g,hasPendingIndexMutation:y,gitmojiEnabled:A,onOpenGitmojiPicker:$}=p,j=y===void 0?!1:y,{t:r}=Q(),w=t>0;let N;e[0]!==g||e[1]!==o||e[2]!==j||e[3]!==w?(N=o.trim()&&w&&g===null&&!j,e[0]=g,e[1]=o,e[2]=j,e[3]=w,e[4]=N):N=e[4];const h=N,{isMobile:E,hasTouchInput:F}=Te();let M;e[5]!==r?(M=r("gitView.commit.title"),e[5]=r,e[6]=M):M=e[6];let C;e[7]!==M?(C=s.jsx("h3",{className:"typography-ui-header font-semibold text-foreground",children:M}),e[7]=M,e[8]=C):C=e[8];let D;e[9]!==w||e[10]!==r?(D=w?null:s.jsx("span",{className:"min-w-0 truncate typography-meta text-muted-foreground",children:r("gitView.commit.stageFilesHint")}),e[9]=w,e[10]=r,e[11]=D):D=e[11];let V;e[12]!==C||e[13]!==D?(V=s.jsxs("div",{className:"flex w-full items-baseline gap-2 px-0 pt-2 pb-1",children:[C,D]}),e[12]=C,e[13]=D,e[14]=V):V=e[14];let I;e[15]!==b||e[16]!==m?(I=s.jsx(Ke,{highlights:b,onInsert:m}),e[15]=b,e[16]=m,e[17]=I):I=e[17];let u;e[18]!==h||e[19]!==l||e[20]!==d?(u=()=>{h&&!l&&d()},e[18]=h,e[19]=l,e[20]=d,e[21]=u):u=e[21];let P;e[22]!==r?(P=r("gitView.commit.messagePlaceholder"),e[22]=r,e[23]=P):P=e[23];const W=g!==null;let L;e[24]!==o||e[25]!==F||e[26]!==E||e[27]!==x||e[28]!==W||e[29]!==u||e[30]!==P?(L=s.jsx(Ge,{value:o,onChange:x,onSubmit:u,placeholder:P,disabled:W,hasTouchInput:F,isMobile:E}),e[24]=o,e[25]=F,e[26]=E,e[27]=x,e[28]=W,e[29]=u,e[30]=P,e[31]=L):L=e[31];let H;e[32]!==A||e[33]!==$||e[34]!==r?(H=A&&s.jsxs(J,{variant:"outline",size:"sm",onClick:$,className:"w-fit",type:"button",children:[s.jsx(R,{name:"emotion-happy",className:"size-4"}),r("gitView.commit.addGitmoji")]}),e[32]=A,e[33]=$,e[34]=r,e[35]=H):H=e[35];const X=l||g!==null||j||t===0;let T;e[36]!==r?(T=r("gitView.commit.generateAria"),e[36]=r,e[37]=T):T=e[37];let Y;e[38]!==l?(Y=l?s.jsx(R,{name:"loader-4",className:"size-4 animate-spin"}):s.jsx(R,{name:"ai-generate-2",className:"size-4 text-primary"}),e[38]=l,e[39]=Y):Y=e[39];let K;e[40]!==r?(K=r("gitView.commit.generate"),e[40]=r,e[41]=K):K=e[41];let G;e[42]!==K?(G=s.jsx("span",{className:"commit-actions__label",children:K}),e[42]=K,e[43]=G):G=e[43];let O;e[44]!==f||e[45]!==X||e[46]!==T||e[47]!==Y||e[48]!==G?(O=s.jsxs(J,{variant:"outline",size:"sm",onClick:f,disabled:X,type:"button","aria-label":T,className:"commit-actions__btn",children:[Y,G]}),e[44]=f,e[45]=X,e[46]=T,e[47]=Y,e[48]=G,e[49]=O):O=e[49];let B;e[50]===Symbol.for("react.memo_cache_sentinel")?(B=s.jsx("div",{className:"flex-1"}),e[50]=B):B=e[50];const q=!h||l;let i;e[51]!==r?(i=r("gitView.commit.commitAria"),e[51]=r,e[52]=i):i=e[52];let n;e[53]!==g||e[54]!==r?(n=g==="commit"?s.jsxs(s.Fragment,{children:[s.jsx(R,{name:"loader-4",className:"size-4 animate-spin"}),s.jsx("span",{className:"commit-actions__label",children:r("gitView.commit.committing")})]}):s.jsxs(s.Fragment,{children:[s.jsx(R,{name:"git-commit",className:"size-4"}),s.jsx("span",{className:"commit-actions__label",children:r("gitView.commit.commit")})]}),e[53]=g,e[54]=r,e[55]=n):n=e[55];let a;e[56]!==d||e[57]!==q||e[58]!==i||e[59]!==n?(a=s.jsx(J,{size:"sm",variant:"outline",onClick:d,disabled:q,className:"commit-actions__btn whitespace-nowrap","aria-label":i,children:n}),e[56]=d,e[57]=q,e[58]=i,e[59]=n,e[60]=a):a=e[60];let c;e[61]!==h||e[62]!==g||e[63]!==l||e[64]!==E||e[65]!==z||e[66]!==r?(c=E?s.jsxs(fe,{children:[s.jsx(me,{asChild:!0,children:s.jsx(J,{variant:"default",size:"sm",onClick:()=>z(),disabled:!h||l,className:"h-7 w-7 p-0","aria-label":r("gitView.commit.pushAria"),children:g==="commitAndPush"?s.jsx(R,{name:"loader-4",className:"size-4 animate-spin"}):s.jsx(R,{name:"arrow-up",className:"size-3.5"})})}),s.jsx(ue,{side:"top",children:s.jsx("p",{children:r("gitView.commit.push")})})]}):s.jsx(J,{size:"sm",variant:"default",onClick:()=>z(),disabled:!h||l,className:"commit-actions__btn","aria-label":r("gitView.commit.pushAria"),children:g==="commitAndPush"?s.jsxs(s.Fragment,{children:[s.jsx(R,{name:"loader-4",className:"size-4 animate-spin"}),s.jsx("span",{className:"commit-actions__label commit-actions__label--push",children:r("gitView.commit.pushing")})]}):s.jsxs(s.Fragment,{children:[s.jsx(R,{name:"arrow-up",className:"size-3.5"}),s.jsx("span",{className:"commit-actions__label commit-actions__label--push",children:r("gitView.commit.push")})]})}),e[61]=h,e[62]=g,e[63]=l,e[64]=E,e[65]=z,e[66]=r,e[67]=c):c=e[67];let k;e[68]!==O||e[69]!==a||e[70]!==c?(k=s.jsxs("div",{className:"@container/commit-actions flex items-center gap-2 min-w-0",children:[O,B,a,c]}),e[68]=O,e[69]=a,e[70]=c,e[71]=k):k=e[71];let v;e[72]!==L||e[73]!==H||e[74]!==k||e[75]!==I?(v=s.jsxs("div",{className:"flex flex-col gap-3 px-0 pt-1 pb-3",children:[I,L,H,k]}),e[72]=L,e[73]=H,e[74]=k,e[75]=I,e[76]=v):v=e[76];let _;return e[77]!==v||e[78]!==V?(_=s.jsxs("section",{className:"border-0 bg-transparent rounded-none",children:[V,v]}),e[77]=v,e[78]=V,e[79]=_):_=e[79],_};export{Ye as C,qe as a};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{R as o,j as n,f as he}from"./vendor-react-BUCujlKS.js";import{X as wn,a as ct,u as Y,F as Pe}from"./index-qES19dlJ.js";import{f as ge,V as Tt,ab as yn,ac as vn,b5 as jn,ae as Sn,ad as Nn,af as Fn,ag as Z,y as Ft,k as kn,hQ as Cn,hR as Rn,hS as Dn,cC as An,t as Ke,hT as En,an as Ve,B as pe,I as A,h as ue,a6 as Bn,a7 as Vn,a8 as Ln,hD as Mt,hU as Tn,fD as Mn,fI as Ge,a0 as In,c2 as at,ap as It,am as _n,b1 as On,b3 as zn,fJ as Pn,b4 as Gn}from"./useAppFontEffects-COAeIX-D.js";import{b as Kn}from"./runtimeEndpointReset-CRGn1gVj.js";import{c as $n,p as Hn}from"./vendor-zustand-BAGL70zf.js";import{P as Wn}from"./PierreDiffViewer-Ct2A13NO.js";import{u as Un,v as qn,g as Xn,W as Jn}from"./main-CYgSu6dx.js";import{f as Qn}from"./patchFileDiff-BpMQZnYu.js";import"./vendor-scheduler-7OC5HNn7.js";import"./vendor-vite-runtime-DD1OZmLC.js";import"./vendor-zod-BLfBSgBh.js";import"./vendor-opencode-sdk-BJ73u-bH.js";import"./vendor-simplewebauthn-browser-VDA66rT_.js";import"./vendor-base-ui-BeMD8X_w.js";import"./vendor-floating-ui-utils-D6FqdtJt.js";import"./vendor-floating-ui-react-dom-DxYCWdHj.js";import"./vendor-floating-ui-dom-BTvzWks8.js";import"./vendor-floating-ui-core-PuGzNPnN.js";import"./vendor-use-sync-external-store-D6wYuSt-.js";import"./contextPanelEmbeddedChat-C9EcRSDF.js";import"./vendor-class-variance-authority-5VPnzWs2.js";import"./vendor-clsx-B-dksMZM.js";import"./vendor-dnd-kit-core-BZknOX2w.js";import"./vendor-dnd-kit-utilities-B_MdXhJC.js";import"./vendor-dnd-kit-accessibility-BHxJPORy.js";import"./vendor-dnd-kit-sortable-CsEagZ81.js";import"./vendor-framer-motion-livSKyyV.js";import"./vendor-motion-dom-D_o3BTI3.js";import"./vendor-motion-utils-BGh8QBgx.js";import"./vendor-tanstack-react-virtual-g05Cx3z9.js";import"./vendor-tanstack-virtual-core-Dubg10g5.js";import"./vendor-sonner-DFyL3AvE.js";import"./vendor-cmdk-DgLInKvT.js";import"./vendor-radix-ui-react-dialog-B94Bt2qq.js";import"./vendor-radix-ui-primitive-Dc_FVRD7.js";import"./vendor-radix-ui-react-compose-refs-DcAh5WdT.js";import"./vendor-radix-ui-react-context-Czxm7Z62.js";import"./vendor-radix-ui-react-id-f5BLKEVw.js";import"./vendor-radix-ui-react-use-layout-effect-D_3IhJdJ.js";import"./vendor-radix-ui-react-use-controllable-state-BFT5YmkA.js";import"./vendor-radix-ui-react-dismissable-layer-D7kXcwgJ.js";import"./vendor-radix-ui-react-primitive-DhVoX9SD.js";import"./vendor-radix-ui-react-slot-BQgQOasS.js";import"./vendor-radix-ui-react-use-callback-ref-BZPnuXAC.js";import"./vendor-radix-ui-react-use-escape-keydown-oph88g-F.js";import"./vendor-radix-ui-react-focus-scope-CiaxW4dD.js";import"./vendor-radix-ui-react-portal-BMJYHWck.js";import"./vendor-radix-ui-react-presence-CNxf-uq4.js";import"./vendor-radix-ui-react-focus-guards-B6qJXYua.js";import"./vendor-react-remove-scroll-DO7dCTnK.js";import"./vendor-tslib-De9GV7Vy.js";import"./vendor-react-remove-scroll-bar-BcFYyj3E.js";import"./vendor-react-style-singleton-q6EMHnwf.js";import"./vendor-get-nonce-C-Z93AgS.js";import"./vendor-use-sidecar-zDC0RhA3.js";import"./vendor-use-callback-ref-D3RC8gqK.js";import"./vendor-aria-hidden-DvXkyWUv.js";import"./vendor-codemirror-language-BgPj_McA.js";import"./vendor-lezer-common-B3-cUCR_.js";import"./vendor-codemirror-state-C9awkmn-.js";import"./vendor-marijn-find-cluster-break-DXwl3gUT.js";import"./vendor-codemirror-view-CiLROUVV.js";import"./vendor-style-mod-NZ5MEPvj.js";import"./vendor-w3c-keyname-Vcq4gwWv.js";import"./vendor-crelt-C8TCjufn.js";import"./vendor-lezer-highlight-CDMHUZ74.js";import"./vendor-codemirror-lang-javascript-Cc2ZYbgX.js";import"./vendor-lezer-javascript-D7Tj24ot.js";import"./vendor-lezer-lr-bhwg1HMg.js";import"./vendor-codemirror-autocomplete-DzPz9Wgq.js";import"./vendor-codemirror-lang-json-CMBS2tG9.js";import"./vendor-lezer-json-Iaex0UN-.js";import"./vendor-codemirror-lang-css-O0cZX78y.js";import"./vendor-lezer-css-C5xB6jxd.js";import"./vendor-codemirror-lang-html-CfgK872x.js";import"./vendor-lezer-html-C0I1p52t.js";import"./vendor-codemirror-lang-markdown-BPGOH9ye.js";import"./vendor-lezer-markdown-C6g-d6P3.js";import"./vendor-codemirror-language-data-BG3v1Ghq.js";import"./vendor-codemirror-lang-python-HahnQaAS.js";import"./vendor-lezer-python-CvuFxeZl.js";import"./vendor-codemirror-commands-B7H_j0iU.js";import"./vendor-legendapp-list-gg7YLRW7.js";import"./vendor-tailwind-merge-CPcsbTWB.js";import"./vendor-fuse.js-Dw8P0qyA.js";import"./web-components-BNMwa0qm.js";import"./computeVirtualFileMetrics-DtyozJdt.js";import"./vendor-shiki-Bbf2GEcE.js";import"./vendor-shikijs-core-CGM_jqPK.js";import"./vendor-shikijs-types-CPSbSeK6.js";import"./vendor-shikijs-vscode-textmate-BgLrS_2D.js";import"./vendor-hast-util-to-html-BKBhbTDb.js";import"./vendor-html-void-elements-CkdplsNl.js";import"./vendor-property-information-rJCbAzvX.js";import"./vendor-zwitch-C2o2j-tx.js";import"./vendor-stringify-entities-CsH1VEn9.js";import"./vendor-character-entities-legacy-BpoLgcEt.js";import"./vendor-character-entities-html4-D7taRCQ7.js";import"./vendor-ccount-c2V3InAJ.js";import"./vendor-comma-separated-tokens-D8TqSuIK.js";import"./vendor-space-separated-tokens-DD3iYX1K.js";import"./vendor-hast-util-whitespace-D4Wp6AEg.js";import"./vendor-shikijs-engine-oniguruma-DPWuIF1G.js";import"./themeResolver-BmJyTmjJ.js";import"./vendor-pierre-theming-C6Z4M5_u.js";import"./vendor-shikijs-engine-javascript-Cme4830A.js";import"./vendor-oniguruma-to-es-DLBnFDCE.js";import"./vendor-oniguruma-parser-C0D4_9rT.js";import"./vendor-regex-BBWcyTkg.js";import"./vendor-regex-utilities-2BQyy0xI.js";import"./vendor-regex-recursion-JU4mF-dD.js";import"./vendor-shikijs-transformers-CZWsLLKm.js";import"./VirtualizedFileDiff-Dpz2ra8h.js";import"./isDiffPlainText-XyulMHxx.js";import"./vendor-diff-C3JhlQdm.js";import"./Virtualizer-D_a8gKmg.js";import"./useInlineCommentController-JsBboQwt.js";import"./appThemeRegistry-BK0dHKa6.js";import"./registerCustomTheme-BBXUCRnG.js";import"./useRootScrollLock-C0N9mCwz.js";import"./scheduledTasksApi-BSRCtP6T.js";import"./vendor-cron-parser-CUcP7OfX.js";import"./vendor-luxon-BZ0puJYg.js";const Yn="openchamber.git-base-branch",Zn=100,$e=(s,e)=>JSON.stringify([ct(),s,e]),kt=$n()(Hn((s,e)=>({overrides:{},getOverride:(i,a)=>!i||!a?null:e().overrides[$e(i,a)]??null,setOverride:(i,a,d)=>{!i||!a||!d||s(f=>{const h=$e(i,a),x=Object.entries({...f.overrides,[h]:d});for(;x.length>Zn;)x.shift();return{overrides:Object.fromEntries(x)}})},clearOverride:(i,a)=>{!i||!a||s(d=>{const f=$e(i,a);if(!(f in d.overrides))return d;const h={...d.overrides};return delete h[f],{overrides:h}})}}),{name:Yn,storage:wn(),partialize:s=>({overrides:s.overrides})})),es=(s,e)=>!!s&&e!==null&&s!==e,ts=(s,e,i,a)=>i?s===null||a&&e===null?!0:e!==null&&s===e:!1,ns=(s,e)=>s==="branch"&&!e?"working":s,ss=(s,e,i)=>JSON.stringify([s,e,i]),rs=(s,e,i,a,d,f)=>{const h=o.useRef({directory:"",attempts:0}),[x,u]=o.useState(()=>({directory:"",exhausted:!1})),p=o.useRef(d);p.current=d;const b=!!s&&x.directory===s&&x.exhausted;return o.useEffect(()=>{if(!s||!e||a||i)return;const w=h.current.directory===s?h.current.attempts:0;if(w>=f){x.directory===s&&x.exhausted||u({directory:s,exhausted:!0});return}h.current={directory:s,attempts:w+1},p.current()},[s,x,a,e,i,f]),b},is=(s,e,i,a)=>{const[d,f]=o.useState(()=>new Map),h=o.useRef(d);h.current=d;const x=o.useRef(i);x.current=i;const u=o.useCallback((p,b)=>{const w=new Map(h.current);if(b===null){if(!w.delete(p))return}else w.set(p,b);h.current=w,f(w)},[]);return o.useEffect(()=>{s&&(h.current=new Map,f(h.current))},[s]),o.useEffect(()=>{const p=x.current;if(!s||!p||!e)return;let b=!1;const w=new Set;for(const y of e.split("\0"))h.current.has(y)||(w.add(y),u(y,a),p(y).then(j=>{b||(w.delete(y),u(y,j))}).catch(()=>{b||(w.delete(y),u(y,null))}));return()=>{b=!0;for(const y of w)u(y,null)}},[e,a,s,u]),d},Ct=(s,e)=>{if(e.length===0)return null;let i=null,a=null;for(const f of e)f.top<=s?(!i||f.top>i.top)&&(i=f):(!a||f.top<a.top)&&(a=f);const d=i??a;return d?{path:d.path,topOffset:d.top-s}:null},os=(s,e,i,a)=>Math.min(Math.max(0,a),Math.max(0,s+i-e)),Rt=s=>{if(!s)return null;const e=s.split(`
|
|
2
|
-
`);let i=null;for(const a of e){const d=a.match(/^@@\s*-\d+(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s*@@/);if(d){const f=Number.parseInt(d[1]??"",10);i=Number.isFinite(f)&&f>=1?f:null;continue}if(i!==null){if(a.startsWith(" ")){i+=1;continue}if(a.startsWith("+"))return i;if(a.startsWith("-"))return Math.max(1,i)}}return null},as=1100,ls=15e3,Dt=500,At=300,cs=1e6,us=3,fs=s=>s<=6?s:s<=12?6:s<=25?4:2,ds={original:"",modified:"",isBinary:!1,contextMode:"patch"},ps=3,ms=o.memo(()=>{const s=he.c(4),{t:e}=ge();let i;s[0]!==e?(i=e("diffView.binary.unavailable"),s[0]=e,s[1]=i):i=s[1];let a;return s[2]!==i?(a=n.jsx("div",{className:"rounded-lg border border-border/60 bg-background px-3 py-2",children:n.jsx("div",{className:"typography-meta text-muted-foreground",children:i})}),s[2]=i,s[3]=a):a=s[3],a}),_t={"?":{code:"?",color:"var(--status-info)",descriptionKey:"diffView.change.untracked"},A:{code:"A",color:"var(--status-success)",descriptionKey:"diffView.change.new"},D:{code:"D",color:"var(--status-error)",descriptionKey:"diffView.change.deleted"},R:{code:"R",color:"var(--status-info)",descriptionKey:"diffView.change.renamed"},C:{code:"C",color:"var(--status-info)",descriptionKey:"diffView.change.copied"},M:{code:"M",color:"var(--status-warning)",descriptionKey:"diffView.change.modified"}},hs=_t.M,gs=s=>{const e=s.index?.trim(),i=s.working_dir?.trim();return e&&e!=="?"?e.charAt(0):i?i.charAt(0):e?.charAt(0)||i?.charAt(0)||"M"},Ot=s=>{const e=gs(s);return _t[e]??hs},xs=s=>{const{index:e,working_dir:i}=s;return e==="A"||i==="A"||e==="?"||i==="?"},Et=s=>{const e=s.index?.trim();return!!(e&&e!=="?")},Bt=s=>!!s.working_dir?.trim()||s.index==="?",bs=(s,e)=>Mn(s,e),Vt=s=>(s||"").replace(/\\/g,"/").replace(/\/+$/,""),Lt=(s,e)=>{const i=s.split(`
|
|
3
|
-
`),a=e.split(`
|
|
4
|
-
`),d=Math.min(i.length,a.length);for(let f=0;f<d;f+=1)if(i[f]!==a[f])return f+1;return a.length>i.length?i.length+1:i.length>a.length?Math.max(1,a.length):1},ws=s=>/^Binary files .+ differ$/m.test(s)||/^GIT binary patch$/m.test(s),ys=s=>Array.isArray(s)?s.filter(e=>!e||typeof e!="object"?!1:typeof e.file=="string"):[],vs=s=>s==="added"?"A":s==="deleted"?"D":"M",lt=(s,e,i)=>ws(e)?{original:"",modified:"",isBinary:!0,patch:e,contextMode:i}:{original:"",modified:"",patch:e,fileDiff:Qn(s,e),contextMode:i},zt=(s,e,i)=>{const a=s??0,d=e??0;return!a&&!d?null:n.jsxs("span",{className:ue("typography-meta flex items-center gap-1 text-xs whitespace-nowrap","flex-shrink-0",i?.className),children:[a?n.jsxs("span",{style:{color:"var(--status-success)"},children:["+",a]}):null,d?n.jsxs("span",{style:{color:"var(--status-error)"},children:["-",d]}):null]})},js=o.memo(s=>{const e=he.c(58),{scope:i,workingCount:a,stagedCount:d,turnCount:f,branchCount:h,showBranchOption:x,onScopeChange:u}=s,{t:p}=ge(),[b,w]=o.useState(!1),y=i==="staged"?d:i==="turn"?f:i==="branch"?h??0:a;let j;e[0]!==i||e[1]!==p?(j=p(i==="staged"?"diffView.scope.staged":i==="turn"?"diffView.scope.lastTurn":i==="branch"?"diffView.scope.branch":"diffView.scope.changed"),e[0]=i,e[1]=p,e[2]=j):j=e[2];const P=j;let m;e[3]!==p?(m=p("diffView.scope.selectorAria"),e[3]=p,e[4]=m):m=e[4];let le;e[5]!==y?(le=n.jsxs("span",{className:"diff-toolbar__scope-count",children:[": ",y]}),e[5]=y,e[6]=le):le=e[6];let k;e[7]!==P||e[8]!==le?(k=n.jsxs("span",{className:"whitespace-nowrap",children:[P,le]}),e[7]=P,e[8]=le,e[9]=k):k=e[9];let E;e[10]===Symbol.for("react.memo_cache_sentinel")?(E=n.jsx(A,{name:"arrow-down-s",className:"size-4 flex-shrink-0 opacity-60"}),e[10]=E):E=e[10];let L;e[11]!==m||e[12]!==k?(L=n.jsx(On,{asChild:!0,children:n.jsxs("button",{type:"button",className:"flex h-7 flex-shrink-0 items-center gap-1.5 rounded-md px-2 typography-ui-label font-semibold text-foreground outline-none hover:bg-interactive-hover focus-visible:ring-2 focus-visible:ring-ring","aria-label":m,children:[k,E]})}),e[11]=m,e[12]=k,e[13]=L):L=e[13];let W;e[14]!==u?(W=B=>{(B==="working"||B==="staged"||B==="turn"||B==="branch")&&(u?.(B),w(!1))},e[14]=u,e[15]=W):W=e[15];let N;e[16]!==p?(N=p("diffView.scope.changed"),e[16]=p,e[17]=N):N=e[17];let ee;e[18]!==N?(ee=n.jsx("span",{children:N}),e[18]=N,e[19]=ee):ee=e[19];let U;e[20]!==a?(U=n.jsx("span",{className:"typography-meta text-muted-foreground",children:a}),e[20]=a,e[21]=U):U=e[21];let q;e[22]!==U||e[23]!==ee?(q=n.jsx(Ge,{value:"working",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[ee,U]})}),e[22]=U,e[23]=ee,e[24]=q):q=e[24];let G;e[25]!==p?(G=p("diffView.scope.staged"),e[25]=p,e[26]=G):G=e[26];let K;e[27]!==G?(K=n.jsx("span",{children:G}),e[27]=G,e[28]=K):K=e[28];let te;e[29]!==d?(te=n.jsx("span",{className:"typography-meta text-muted-foreground",children:d}),e[29]=d,e[30]=te):te=e[30];let I;e[31]!==K||e[32]!==te?(I=n.jsx(Ge,{value:"staged",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[K,te]})}),e[31]=K,e[32]=te,e[33]=I):I=e[33];let _;e[34]!==p?(_=p("diffView.scope.lastTurn"),e[34]=p,e[35]=_):_=e[35];let V;e[36]!==_?(V=n.jsx("span",{children:_}),e[36]=_,e[37]=V):V=e[37];let O;e[38]!==f?(O=n.jsx("span",{className:"typography-meta text-muted-foreground",children:f}),e[38]=f,e[39]=O):O=e[39];let ne;e[40]!==V||e[41]!==O?(ne=n.jsx(Ge,{value:"turn",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[V,O]})}),e[40]=V,e[41]=O,e[42]=ne):ne=e[42];let T;e[43]!==h||e[44]!==x||e[45]!==p?(T=x?n.jsx(Ge,{value:"branch",children:n.jsxs("span",{className:"flex min-w-0 flex-1 items-center justify-between gap-3",children:[n.jsx("span",{children:p("diffView.scope.branch")}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:h??"…"})]})}):null,e[43]=h,e[44]=x,e[45]=p,e[46]=T):T=e[46];let se;e[47]!==i||e[48]!==q||e[49]!==I||e[50]!==ne||e[51]!==T||e[52]!==W?(se=n.jsx(zn,{align:"start",className:"w-40",children:n.jsxs(Pn,{value:i,onValueChange:W,children:[q,I,ne,T]})}),e[47]=i,e[48]=q,e[49]=I,e[50]=ne,e[51]=T,e[52]=W,e[53]=se):se=e[53];let re;return e[54]!==b||e[55]!==se||e[56]!==L?(re=n.jsxs(Gn,{open:b,onOpenChange:w,children:[L,se]}),e[54]=b,e[55]=se,e[56]=L,e[57]=re):re=e[57],re}),Ss=o.memo(s=>{const e=he.c(11),{changedFiles:i,selectedFile:a,onSelectFile:d}=s,{t:f}=ge();if(i.length===0)return null;let h;if(e[0]!==i||e[1]!==d||e[2]!==a||e[3]!==f){let u;e[5]!==d||e[6]!==a||e[7]!==f?(u=p=>{const b=Ot(p),w=a===p.path;return n.jsx("li",{children:n.jsxs("button",{type:"button",onClick:()=>d(p.path),className:ue("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left transition-colors",w?"bg-interactive-selection text-interactive-selection-foreground":"text-muted-foreground hover:bg-interactive-hover hover:text-foreground"),children:[n.jsx(It,{filePath:p.path,className:"h-3.5 w-3.5 flex-shrink-0"}),n.jsx("span",{className:"typography-micro font-semibold w-4 text-center uppercase",style:{color:b.color},title:f(b.descriptionKey),"aria-label":f(b.descriptionKey),children:b.code}),n.jsx("span",{className:"min-w-0 flex-1 truncate typography-meta",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},title:p.path,children:p.path}),zt(p.insertions,p.deletions)]})},p.path)},e[5]=d,e[6]=a,e[7]=f,e[8]=u):u=e[8],h=i.map(u),e[0]=i,e[1]=d,e[2]=a,e[3]=f,e[4]=h}else h=e[4];let x;return e[9]!==h?(x=n.jsx(at,{outerClassName:"flex-1 min-h-0",className:"px-2 py-2",children:n.jsx("ul",{className:"flex flex-col gap-1",children:h})}),e[9]=h,e[10]=x):x=e[10],x}),Ns=o.memo(s=>{const e=he.c(20),{filePath:i,diff:a,renderSideBySide:d}=s,{t:f}=ge(),h=a.original.length>0,x=a.modified.length>0,u=d?"flex flex-row gap-6 items-start justify-center":"flex flex-col gap-4 items-center",p=d?"flex flex-col items-center gap-2 flex-1 min-w-0":"flex flex-col items-center gap-2";let b;e[0]===Symbol.for("react.memo_cache_sentinel")?(b={contain:"layout"},e[0]=b):b=e[0];let w;e[1]!==a.original||e[2]!==i||e[3]!==h||e[4]!==p||e[5]!==d||e[6]!==f?(w=h&&n.jsxs("div",{className:p,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:f("diffView.image.original")}),n.jsx("img",{src:a.original,alt:f("diffView.image.originalAlt",{path:i}),className:d?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]}),e[1]=a.original,e[2]=i,e[3]=h,e[4]=p,e[5]=d,e[6]=f,e[7]=w):w=e[7];let y;e[8]!==a.modified||e[9]!==i||e[10]!==x||e[11]!==h||e[12]!==p||e[13]!==d||e[14]!==f?(y=x&&n.jsxs("div",{className:p,children:[n.jsx("span",{className:"typography-meta text-muted-foreground font-medium",children:f(h?"diffView.image.modified":"diffView.image.new")}),n.jsx("img",{src:a.modified,alt:f("diffView.image.modifiedAlt",{path:i}),className:d?"max-w-full max-h-[70vh] object-contain":"max-w-full object-contain",style:{imageRendering:"auto"}})]}),e[8]=a.modified,e[9]=i,e[10]=x,e[11]=h,e[12]=p,e[13]=d,e[14]=f,e[15]=y):y=e[15];let j;return e[16]!==u||e[17]!==w||e[18]!==y?(j=n.jsx("div",{className:"w-full overflow-auto p-4",style:b,children:n.jsxs("div",{className:u,children:[w,y]})}),e[16]=u,e[17]=w,e[18]=y,e[19]=j):j=e[19],j}),Fs=o.memo(s=>{const e=he.c(16),{filePath:i,diff:a,renderSideBySide:d,wrapLines:f}=s;let h;e[0]!==i?(h=_n(i)||"text",e[0]=i,e[1]=h):h=e[1];const x=h;if(a.isBinary){let b;return e[2]===Symbol.for("react.memo_cache_sentinel")?(b=n.jsx(ms,{}),e[2]=b):b=e[2],b}if(Ve(i)){let b;return e[3]!==a||e[4]!==i||e[5]!==d?(b=n.jsx(Ns,{filePath:i,diff:a,renderSideBySide:d}),e[3]=a,e[4]=i,e[5]=d,e[6]=b):b=e[6],b}let u;e[7]===Symbol.for("react.memo_cache_sentinel")?(u={contain:"layout"},e[7]=u):u=e[7];let p;return e[8]!==a.fileDiff||e[9]!==a.modified||e[10]!==a.original||e[11]!==i||e[12]!==x||e[13]!==d||e[14]!==f?(p=n.jsx("div",{className:"w-full",style:u,children:n.jsx(Wn,{original:a.original,modified:a.modified,fileDiff:a.fileDiff,language:x,fileName:i,renderSideBySide:d,wrapLines:f,layout:"inline"})}),e[8]=a.fileDiff,e[9]=a.modified,e[10]=a.original,e[11]=i,e[12]=x,e[13]=d,e[14]=f,e[15]=p):p=e[15],p}),ks=o.memo(s=>{const e=he.c(7),{filePath:i,staged:a,busyAction:d,disabled:f,onAction:h}=s,{t:x}=ge();let u;return e[0]!==d||e[1]!==f||e[2]!==i||e[3]!==h||e[4]!==a||e[5]!==x?(u=n.jsx("div",{className:"flex items-center gap-0.5 rounded-full border border-[var(--interactive-border)]/45 bg-[var(--surface-background)]/95 px-1 py-0.5 shadow-sm backdrop-blur-md",children:a?n.jsx(ot,{label:x("gitView.changes.unstageFileAria",{path:i}),icon:"arrow-go-back",loading:d==="unstage",disabled:f,onClick:()=>h("unstage")}):n.jsxs(n.Fragment,{children:[n.jsx(ot,{label:x("gitView.changes.revertFileAria",{path:i}),icon:"arrow-go-back",loading:d==="discard",disabled:f,tone:"failure",onClick:()=>h("discard")}),n.jsx(ot,{label:x("gitView.changes.stageFileAria",{path:i}),icon:"add",loading:d==="stage",disabled:f,tone:"success",onClick:()=>h("stage")})]})}),e[0]=d,e[1]=f,e[2]=i,e[3]=h,e[4]=a,e[5]=x,e[6]=u):u=e[6],u}),ot=s=>{const e=he.c(14),{label:i,icon:a,loading:d,disabled:f,tone:h,onClick:x}=s,u=h==="failure"&&"text-[var(--status-error)] hover:text-[var(--status-error)]",p=h==="success"&&"text-[var(--status-success)] hover:text-[var(--status-success)]";let b;e[0]!==u||e[1]!==p?(b=ue("h-6 w-6 rounded-none bg-transparent p-0 text-muted-foreground opacity-70 hover:bg-transparent hover:text-foreground hover:opacity-100",u,p),e[0]=u,e[1]=p,e[2]=b):b=e[2];let w;e[3]!==x?(w=P=>{P.stopPropagation(),x()},e[3]=x,e[4]=w):w=e[4];let y;e[5]!==a||e[6]!==d?(y=d?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:a,className:a==="add"?"size-4":"size-3.5"}),e[5]=a,e[6]=d,e[7]=y):y=e[7];let j;return e[8]!==f||e[9]!==i||e[10]!==b||e[11]!==w||e[12]!==y?(j=n.jsx(pe,{variant:"ghost",size:"sm",className:b,disabled:f,title:i,"aria-label":i,onClick:w,children:y}),e[8]=f,e[9]=i,e[10]=b,e[11]=w,e[12]=y,e[13]=j):j=e[13],j},Cs=o.memo(({directory:s,file:e,layout:i,wrapLines:a,isSelected:d,isExpanded:f,isMounted:h,onSelect:x,onExpandedChange:u,registerSectionRef:p,showOpenInEditorAction:b=!1,isOpeningInEditor:w=!1,onOpenInEditor:y,staged:j=!1,loadFullFiles:P=!1,initialDiffData:m=null,readOnlyActions:le=!1})=>{const{t:k}=ge(),{git:E}=Tt(),L=Z(o.useCallback(c=>c.directories.get(s)?.diffCache.get(e.path)??null,[s,e.path])),W=Z(c=>c.setDiff),N=Z(c=>c.fetchStatus),ee=Y(c=>c.setDiffFileLayout),[U,q]=o.useState(0),[G,K]=o.useState(null),[te,I]=o.useState(!1),[_,V]=o.useState(null),[O,ne]=o.useState(!1),[T,se]=o.useState(null),[re,B]=o.useState(null),ie=o.useRef(null),He=o.useRef(null),ce=o.useMemo(()=>Ot(e),[e]),fe=i==="side-by-side",xe=P?"full":"patch",Ce=`${e.index}:${e.working_dir}:${e.insertions}:${e.deletions}`,X=o.useMemo(()=>m||(j?re:T||(L?{original:L.original,modified:L.modified,isBinary:L.isBinary,contextMode:"full"}:null)),[L,m,T,j,re]),Re=X?.contextMode===xe,We=o.useCallback(c=>{He.current=c,p(e.path,c)},[e.path,p]),Le=o.useCallback(c=>{u(e.path,c)},[e.path,u]),be=o.useCallback(()=>{x(e.path)},[e.path,x]);o.useEffect(()=>{j?B(null):se(null),K(null),ie.current=null},[Ce,j]),o.useEffect(()=>{if(!f||!h)return;if(!s||m||X&&Re){ie.current=null,I(!1);return}const c=`${s}::${e.path}::${j?"staged":"unstaged"}::${Ce}::${xe}::${U}`;if(ie.current===c)return;ie.current=c,K(null),I(!0);let C=!1;const oe=ct(),Me=P?cs:us,de=Ve(e.path)?E.getGitFileDiff(s,{path:e.path,staged:j}):E.getGitDiff(s,{path:e.path,staged:j,contextLines:Me}),De=ls,Ae=new Promise(($,J)=>{setTimeout(()=>J(new Error(`Timed out after ${De}ms`)),De)});return Promise.race([de,Ae]).then($=>{if(!C){if("diff"in $){const J=lt(e.path,$.diff,xe);j?B(J):se(J)}else{const J={original:$.original??"",modified:$.modified??"",isBinary:$.isBinary,contextMode:"full"};j?B(J):W(s,e.path,J,oe)}I(!1)}}).catch($=>{if(C)return;const J=$ instanceof Error?$.message:String($);K(J),I(!1)}),()=>{C=!0,ie.current===c&&(ie.current=null)}},[xe,X,Re,U,s,e.path,Ce,E,m,f,h,P,W,j]);const we=o.useCallback(()=>{Le(!f),be()},[Le,be,f]),Te=o.useCallback(async c=>{if(!(!s||_!==null)){V(c);try{c==="stage"?await E.stageGitFile(s,e.path):c==="unstage"?await E.unstageGitFile(s,e.path):await E.revertGitFile(s,e.path,{scope:"working"}),q(C=>C+1),await N(s,E)}catch(C){const oe=c==="unstage"?"gitView.toast.unstageFileFailed":c==="stage"?"gitView.toast.stageFileFailed":"gitView.toast.revertFailed";Ke.error(C instanceof Error?C.message:k(oe))}finally{V(C=>C===c?null:C)}}},[s,N,e.path,_,E,k]);return n.jsxs("div",{ref:We,className:"scroll-mt-9 border-b border-[var(--interactive-border)]/40 last:border-b-0",children:[n.jsx("div",{className:"sticky top-0 z-30 border-b border-[var(--interactive-border)]/35 bg-[var(--surface-elevated)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--surface-elevated)]/80",children:n.jsxs("div",{role:"button",tabIndex:0,onClick:we,onKeyDown:c=>{c.target===c.currentTarget&&(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),we())},className:ue("cursor-pointer","group/header relative grid min-h-9 w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-2 overflow-hidden px-3 py-2","bg-transparent","text-muted-foreground hover:text-foreground",d?"bg-[var(--interactive-selection)]/35":null),children:[n.jsx("div",{className:"absolute inset-0 pointer-events-none group-hover/header:bg-[var(--interactive-hover)]/50"}),n.jsxs("div",{className:"relative flex min-w-0 flex-1 items-center gap-2",children:[n.jsx("span",{className:"flex size-5 items-center justify-center opacity-70 group-hover/header:opacity-100",children:f?n.jsx(A,{name:"arrow-down-s",className:"size-4"}):n.jsx(A,{name:"arrow-right-s",className:"size-4"})}),n.jsx("span",{className:"typography-micro font-semibold leading-none w-4 text-center uppercase",style:{color:ce.color},title:k(ce.descriptionKey),"aria-label":k(ce.descriptionKey),children:ce.code}),n.jsx("span",{className:"min-w-0 flex-1 overflow-hidden typography-ui-label",title:e.path,children:n.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[n.jsx(It,{filePath:e.path,className:"h-3.5 w-3.5 flex-shrink-0 align-middle"}),(()=>{const c=e.path.lastIndexOf("/");if(c===-1)return n.jsx("span",{className:"block min-w-0 truncate typography-ui-label text-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:e.path});const C=e.path.slice(0,c),oe=e.path.slice(c+1);return n.jsxs("span",{className:"flex min-w-0 items-baseline overflow-hidden",children:[n.jsx("span",{className:"min-w-0 truncate typography-ui-label text-muted-foreground",style:{direction:"rtl",textAlign:"left",unicodeBidi:"plaintext"},children:C}),n.jsxs("span",{className:"flex-shrink-0 typography-ui-label",children:[n.jsx("span",{className:"text-muted-foreground",children:"/"}),n.jsx("span",{className:"text-foreground",children:oe})]})]})})()]})})]}),n.jsxs("div",{className:"relative flex shrink-0 items-center justify-self-end gap-2",children:[zt(e.insertions,e.deletions),b&&y?n.jsx(pe,{variant:"ghost",size:"sm",className:"h-5 w-5 p-0 opacity-70 hover:opacity-100",title:k("diffView.actions.openFileInEditorAtChange"),onClick:c=>{c.stopPropagation(),y(e.path,X)},disabled:w,children:w?n.jsx(A,{name:"loader-4",className:"size-3.5 animate-spin"}):n.jsx(A,{name:"edit",className:"size-3.5"})}):null,n.jsx(Mt,{mode:fe?"side-by-side":"unified",onModeChange:c=>{const C=c==="side-by-side"?"side-by-side":"inline";ee(e.path,C)},className:"opacity-70"})]})]})}),f&&n.jsxs("div",{className:"relative bg-background overflow-hidden",children:[!h&&!G?n.jsx("div",{className:"h-40 border border-border/40 bg-background/40"}):null,G?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:k("diffView.state.failedToLoadDiff")}),n.jsx("div",{className:"typography-meta text-muted-foreground max-w-[32rem] text-center",children:G}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>q(c=>c+1),children:k("diffView.actions.retry")})]}):null,h&&te&&!X&&!G?n.jsxs("div",{className:"flex items-center justify-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),k("diffView.state.loadingDiff")]}):null,h&&X&&!O&&e.insertions+e.deletions>Dt?n.jsxs("div",{className:"flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:k("diffView.state.largeDiff",{count:e.insertions+e.deletions})}),n.jsx("div",{className:"typography-meta text-muted-foreground",children:k("diffView.state.largeDiffDescription")}),n.jsx("button",{type:"button",className:"typography-ui-label text-primary hover:underline",onClick:()=>ne(!0),children:k("diffView.actions.renderAnyway")})]}):null,h&&X&&(O||e.insertions+e.deletions<=Dt)?n.jsxs(n.Fragment,{children:[n.jsx(Fs,{filePath:e.path,diff:X,renderSideBySide:fe,wrapLines:a}),n.jsx("div",{className:"pointer-events-none absolute bottom-3 right-3 z-20",children:n.jsx("div",{className:"pointer-events-auto",children:le?null:n.jsx(ks,{filePath:e.path,staged:j,busyAction:_,disabled:_!==null,onAction:Te})})})]}):null]})]})}),Ki=({hideStackedFileSidebar:s=!1,stackedDefaultCollapsedAll:e=!1,pinSelectedFileHeaderToTopOnNavigate:i=!1,showOpenInEditorAction:a=!1,diffScope:d="all",onDiffScopeChange:f,targetFilePath:h=null,flushContent:x=!1})=>{const{t:u}=ge(),{git:p,files:b}=Tt(),w=yn(),{rootIsGitRepo:y,gitDirectory:j,nestedRepos:P}=vn(w??null),m=j??w,le=Y(t=>t.openContextSurface),k=Un(t=>t.requestSource),{screenWidth:E,isMobile:L}=jn(),W=Sn(m??null),N=Nn(m??null),ee=Fn(m??null),U=Z(t=>t.setActiveDirectory),q=Z(t=>t.ensureStatus),G=Z(t=>t.selectNestedRepo),K=Z(t=>t.fetchStatus),te=Z(t=>t.fetchBranches),I=Z(t=>t.clearDiffCache),_=Z(t=>t.setDiff),[V,O]=o.useState(null),[ne,T]=o.useState(!1),[se,re]=o.useState(null),[B,ie]=o.useState(()=>new Set),[He,ce]=o.useState(()=>new Set),[fe,xe]=o.useState(!1),[Ce,X]=o.useState(0),[Re,We]=o.useState(()=>new Map),[Le,be]=o.useState(!1),[we,Te]=o.useState(!1),[c,C]=o.useState(d);o.useEffect(()=>{C(d)},[d]);const oe=Y(t=>t.pendingDiffFile),Me=Y(t=>t.pendingDiffStaged),de=Y(t=>t.pendingDiffScope),De=Y(t=>t.setPendingDiffFile),Ae=Y(t=>t.diffLayoutPreference),$=Y(t=>t.diffFileLayout),J=Y(t=>t.setDiffFileLayout),ut=Y(t=>t.diffWrapLines),Pt=Y(t=>t.setDiffWrapLines),ft=Y(t=>t.openContextFileAtLine),ye=Ft(t=>t.currentSessionId),Ue=kn(ye??"",w??void 0),qe=ut,Xe=c==="staged"?!0:c==="working"?!1:null,Ie=Xe??ne,Je=L||E<=768,Gt=!!ye&&c!=="turn"&&!Je&&!Pe(),Kt=c!=="turn"&&!Je&&!Pe(),$t=!s&&!Je&&E>=1024,ve=o.useRef(null),Ee=o.useRef(new Map),me=o.useRef(null),z=o.useRef(null),je=o.useRef(!1),Se=o.useRef(null),dt=o.useRef(null),Qe=o.useRef(null),Ye=o.useRef(null),pt=o.useCallback(()=>{const t=ve.current;if(!t)return null;const r=t.getBoundingClientRect().top,l=[];for(const[g,v]of Ee.current)v&&l.push({path:g,top:v.getBoundingClientRect().top});return Ct(r,l)},[]),Ne=o.useCallback(()=>{me.current=null,je.current=!1,re(null),z.current!==null&&(window.cancelAnimationFrame(z.current),z.current=null)},[]),Fe=o.useCallback(t=>{ie(r=>{if(r.has(t))return r;const l=new Set(r);return l.add(t),l})},[]),Be=o.useMemo(()=>{for(let t=Ue.length-1;t>=0;t-=1){const r=Ue[t];if(r.role==="user")return ys(r.summary?.diffs)}return[]},[Ue]),Ht=o.useMemo(()=>{const t=new Map;for(const r of Be)if(r.file){if(typeof r.patch=="string"){t.set(r.file,lt(r.file,r.patch,"patch"));continue}t.set(r.file,{original:r.before??"",modified:r.after??"",contextMode:"full"})}return t},[Be]),Wt=o.useMemo(()=>N?.files?N.files.filter(Bt).length:0,[N]),Ut=o.useMemo(()=>N?.files?N.files.filter(Et).length:0,[N]),qt=Be.length,R=N?.current??null,ke=Z(t=>m?t.directories.get(m)?.branches??null:null),Xt=Z(t=>m?t.directories.get(m)?.isLoadingBranches??!1:!1),Jt=o.useCallback(()=>{m&&te(m,p)},[m,te,p]),Qt=rs(m??null,W!==!1,Xt,!!ke,Jt,ps),mt=o.useMemo(()=>{const t=N?.tracking?.trim().split("/")[0];return(t&&ke?.defaultBranches?.[t])??ke?.defaultBranches?.origin??null},[ke,N?.tracking]),Ze=!Pe()&&es(R,mt),Yt=N!==null,ht=Pe()||Qt||ts(R,mt,Yt,ke!==null),Zt=kt(t=>t.setOverride),en=kt(o.useCallback(t=>m&&R?t.overrides[$e(m,R)]??null:null,[R,m])),[tn,et]=o.useState(null),[nn,tt]=o.useState(!1),[gt,sn]=o.useState("");o.useEffect(()=>{const t=ns(c,!ht);t!==c&&(C(t),t==="working"&&f?.("working"))},[c,ht,f]),o.useEffect(()=>{if(!Ze||!m||!R){et(null),tt(!1);return}let t=!1;return tt(!1),Cn(m,R).then(r=>{t||et(r.base)}).catch(()=>{t||et(null)}).finally(()=>{t||tt(!0)}),()=>{t=!0}},[R,m,Ze]);const ae=en??tn,[_e,xt]=o.useState(null),[bt,wt]=o.useState(null),Oe=o.useRef(0),nt=o.useCallback(()=>{if(!m||!R||!ae)return;const t=Oe.current+1;Oe.current=t,xt(null),wt(null),Rn(m,{base:ae,head:R}).then(r=>{Oe.current===t&&xt(r)}).catch(r=>{Oe.current===t&&wt(r instanceof Error?r.message:u("diffView.branch.loadError"))})},[ae,R,m,u]);o.useEffect(()=>{c==="branch"&&nt()},[c,nt]);const yt=c==="branch"&&m&&R&&ae?ss(m,ae,R):null,rn=o.useMemo(()=>c==="branch"?Array.from(B).sort().join("\0"):"",[c,B]),on=o.useCallback(t=>!m||!ae||!R?Promise.reject(new Error("branch range is unavailable")):Dn(m,{base:ae,head:R,path:t}).then(r=>lt(t,r.diff,"patch")),[ae,R,m]),an=is(yt,rn,yt?on:null,ds),ln=_e?.length??null,S=o.useMemo(()=>{if(c==="branch")return(_e??[]).map(l=>({path:l.path,index:"",working_dir:l.status,insertions:0,deletions:0,isNew:l.status==="A"})).sort((l,g)=>l.path.localeCompare(g.path));if(c==="turn")return Be.map(l=>({path:l.file??"",index:"",working_dir:vs(l.status),insertions:l.additions??0,deletions:l.deletions??0,isNew:l.status==="added"})).filter(l=>l.path).sort((l,g)=>l.path.localeCompare(g.path));if(!N?.files)return[];const t=N.diffStats??{},r=c==="staged"?Et:c==="working"?Bt:()=>!0;return N.files.filter(r).map(l=>({...l,insertions:t[l.path]?.insertions??0,deletions:t[l.path]?.deletions??0,isNew:xs(l)})).sort((l,g)=>l.path.localeCompare(g.path))},[c,_e,Be,N]),st=o.useMemo(()=>S.map(t=>t.path).join("\0"),[S]);o.useEffect(()=>{const t=st?st.split("\0"):[],r=new Set(t),l=`${m??""}:${c}:${e?"collapsed":"default"}`,g=dt.current!==l;dt.current=l,ie(v=>{if(g){const D=e?0:fs(t.length);return new Set(t.slice(0,D))}let M=!1;const F=new Set;for(const D of v){if(!r.has(D)){M=!0;continue}F.add(D)}return M?F:v}),ce(v=>{if(g)return new Set;let M=!1;const F=new Set;for(const D of v){if(!r.has(D)){M=!0;continue}F.add(D)}return M?F:v})},[c,st,m,e]);const vt=o.useCallback(()=>{Se.current=null;const t=ve.current;if(!t)return;const r=t.getBoundingClientRect(),l=r.top-At,g=r.bottom+At,v={},M=[];for(const[F,D]of Ee.current){if(!D)continue;const H=D.getBoundingClientRect();M.push({path:F,top:H.top}),B.has(F)&&(H.bottom<l||H.top>g||(v[F]=!0))}Qe.current=Ct(r.top,M),ce(F=>{let D=!1;const H=new Set(F);for(const Nt of Object.keys(v))H.has(Nt)||(H.add(Nt),D=!0);return D?H:F})},[B]),Q=o.useCallback(()=>{typeof window>"u"||Se.current===null&&(Se.current=window.requestAnimationFrame(vt))},[vt]);o.useEffect(()=>{const t=ve.current;if(t)return Q(),t.addEventListener("scroll",Q,{passive:!0}),window.addEventListener("resize",Q),()=>{t.removeEventListener("scroll",Q),window.removeEventListener("resize",Q),Se.current!==null&&(window.cancelAnimationFrame(Se.current),Se.current=null)}},[S,B,Q]);const rt=o.useCallback(t=>{const r=$[t.path];if(r)return r;if(Ae==="inline")return"inline";if(Ae==="side-by-side")return"side-by-side";const l=E<as;return t.isNew||l?"inline":"side-by-side"},[$,Ae,E]),jt=o.useMemo(()=>S.length===0?null:S.every(t=>rt(t)==="side-by-side")?"side-by-side":"inline",[S,rt]);o.useEffect(()=>{m&&(U(m),q(m,p))},[m,U,q,p]),o.useEffect(()=>{if(m)return An.onGitRefreshHint(t=>{Vt(t.directory)===Vt(m)&&(t.paths?.length&&(Ye.current=pt()??Qe.current,I(m,t.paths),We(r=>{const l=new Map(r);for(const g of t.paths??[])l.set(g,(l.get(g)??0)+1);return l})),K(m,p,{silent:!0}))})},[pt,I,m,K,p]),o.useLayoutEffect(()=>{const t=Ye.current;if(!t)return;Ye.current=null;const r=ve.current,l=Ee.current.get(t.path);if(!r||!l)return;const g=r.getBoundingClientRect().top,v=l.getBoundingClientRect().top-g;r.scrollTop=os(r.scrollTop,t.topOffset,v,r.scrollHeight-r.clientHeight),Qe.current=t},[Re]),o.useEffect(()=>{c!=="all"&&!de||oe&&(de&&C(de),O(oe),T(de==="staged"||!de&&Me),De(null),je.current=!0,me.current=oe,Fe(oe),X(t=>t+1))},[c,Fe,oe,de,Me,De]),o.useEffect(()=>{if(c==="all")return;const t=h?.trim();t&&(O(t),T(c==="staged"),je.current=!0,me.current=t,Fe(t),X(r=>r+1))},[c,Fe,h]),o.useEffect(()=>{if(!V)return;S.some(r=>r.path===V)||(O(null),T(!1))},[S,V]);const cn=o.useCallback((t,r)=>{const l=Ee.current;r?l.set(t,r):l.delete(t),Q()},[Q]),un=o.useCallback((t,r)=>{Ne(),ie(l=>{const g=l.has(t);if(r===g)return l;const v=new Set(l);return r?v.add(t):v.delete(t),v}),r||ce(l=>{if(!l.has(t))return l;const g=new Set(l);return g.delete(t),g}),Q()},[Ne,Q]),fn=o.useCallback(()=>{Ne(),ie(t=>t.size>0?new Set:new Set(S.map(r=>r.path))),ce(new Set),Q()},[Ne,S,Q]),dn=o.useCallback(async t=>{if(!ye)return;const r=Ft.getState().getDirectoryForSession(ye)||w||"";if(!r){Ke.error(u("diffView.reviewDialog.toast.noSessionDirectory"));return}Te(!0);try{await En({originalSessionID:ye,directory:r,providerID:t.providerID,modelID:t.modelID,agent:t.agent||void 0,variant:t.variant||void 0,generateHandoff:t.generateHandoff,returnAfterHandoffRequest:t.generateHandoff,autoReview:t.autoReview}),be(!1)}catch(l){console.error("[review-flow] failed to start review flow",l),Ke.error(l instanceof Error?l.message:u("diffView.reviewDialog.toast.startFailed"))}finally{Te(!1)}},[ye,w,u]),ze=o.useCallback(t=>{const r=Ee.current.get(t),l=ve.current;if(!r||!l)return!1;const g=r.getBoundingClientRect().top-l.getBoundingClientRect().top;return l.scrollTo({top:l.scrollTop+g,behavior:"auto"}),!0},[]);o.useEffect(()=>{if(!me.current)return;let r=0;const l=20;let g=!1;const v=(F=!0)=>{g||(g=!0,me.current=null,je.current=!1,F&&re(null),z.current!==null&&(window.cancelAnimationFrame(z.current),z.current=null))},M=()=>{if(g){z.current=null;return}const F=me.current;if(!F){v(),z.current=null;return}if(!ze(F)){r+=1,r<l?z.current=window.requestAnimationFrame(M):(v(),z.current=null);return}if(i&&je.current){re(F),v(!1);return}v()};return z.current=window.requestAnimationFrame(M),()=>{g=!0,z.current!==null&&(window.cancelAnimationFrame(z.current),z.current=null)}},[i,Ce,ze]);const pn=o.useCallback(t=>{},[]),it=o.useCallback(t=>{Ne(),O(t),T(!1),je.current=!0,me.current=t,Fe(t),X(r=>r+1),ze(t)},[Ne,Fe,ze]);o.useEffect(()=>{const t=r=>{if(!r.altKey||r.metaKey||r.ctrlKey||r.shiftKey||r.key!=="ArrowDown"&&r.key!=="ArrowUp")return;const l=r.target;if(l instanceof HTMLElement&&(l.isContentEditable||l.tagName==="INPUT"||l.tagName==="TEXTAREA"||l.closest('[role="dialog"]'))||S.length===0)return;const g=r.key==="ArrowDown"?1:-1,v=V?S.findIndex(D=>D.path===V):-1,M=v===-1?g>0?0:S.length-1:v+g,F=S[M];F&&(r.preventDefault(),it(F.path))};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[S,V,it]);const mn=o.useCallback(t=>{const r=t==="side-by-side"?"side-by-side":"inline";S.forEach(l=>{J(l.path,r)})},[S,J]),[hn,St]=o.useState(null),gn=o.useCallback(async(t,r)=>{if(!m||!t)return;St(t);const l=ct();try{let g=null;if(r?.patch&&!r.isBinary&&!Ve(t)?g=Rt(r.patch):r&&r.contextMode==="full"&&!r.isBinary&&!Ve(t)&&(g=Lt(r.original,r.modified)),g===null)try{const H=await p.getGitDiff(m,{path:t,staged:Ie,contextLines:3});g=Rt(H.diff)}catch{g=null}let v=r;if(g===null||!v){const H=await p.getGitFileDiff(m,{path:t,staged:Ie});v={original:H.original??"",modified:H.modified??"",isBinary:H.isBinary},Ie||_(m,t,v,l)}const M=g??(v.isBinary||Ve(t)?1:Lt(v.original,v.modified)),F=bs(m,t),D=await qn(b,F,{directory:m});if(!D.ok){Ke.error(Xn(D.reason));return}ft(m,F,M,1)}finally{St(g=>g===t?null:g)}},[Ie,m,b,p,ft,_]),xn=()=>{if(!m)return null;const t=r=>Xe!==null?Xe:ne&&r===V;return n.jsxs("div",{className:ue("flex min-w-0 flex-1 min-h-0 h-full",x?"gap-0":"gap-3 px-3 pb-3 pt-2"),children:[$t&&n.jsxs("section",{className:"hidden lg:flex w-72 flex-col rounded-xl border border-border/60 bg-background/70 overflow-hidden",children:[n.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 border-b border-border/40",children:[n.jsx("span",{className:"typography-ui-header font-semibold text-foreground",children:u("diffView.section.files")}),n.jsx("span",{className:"typography-meta text-muted-foreground",children:S.length})]}),n.jsx(Ss,{changedFiles:S,selectedFile:null,onSelectFile:it})]}),n.jsx("div",{className:"relative flex-1 min-w-0 min-h-0 h-full",children:n.jsx(at,{ref:ve,outerClassName:"min-h-0 h-full",className:"[overflow-anchor:none] pb-16",disableHorizontal:!0,observeMutations:!1,preventOverscroll:!0,"data-diff-virtual-root":!0,children:n.jsx("div",{className:"flex flex-col [overflow-anchor:none]","data-diff-virtual-content":!0,children:S.map(r=>n.jsx(Cs,{directory:m,file:r,layout:rt(r),wrapLines:qe,isSelected:!1,isExpanded:B.has(r.path),isMounted:He.has(r.path)||r.path===se,onSelect:pn,onExpandedChange:un,registerSectionRef:cn,showOpenInEditorAction:a&&c!=="turn",isOpeningInEditor:hn===r.path,onOpenInEditor:(l,g)=>{gn(l,g)},staged:t(r.path),loadFullFiles:fe,readOnlyActions:c==="branch",initialDiffData:c==="turn"?Ht.get(r.path)??null:c==="branch"?an.get(r.path)??null:null},`${r.path}:${Re.get(r.path)??0}`))})})})]})},bn=()=>{if(!m)return n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:u("diffView.state.selectSessionDirectory")});if(c!=="turn"&&ee&&!N)return n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),u("diffView.state.loadingRepositoryStatus")]});if(c!=="turn"&&W===!1)return n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:u("diffView.state.notGitRepository")});if(c==="branch"){if(!nn)return n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),u("diffView.branch.resolvingBase")]});if(!ae){const t=(ke?.all??[]).map(l=>l.replace(/^remotes\//,"")).filter(l=>l!==R&&!l.endsWith(`/${R}`)).sort(),r=In(t,gt,l=>[l]);return n.jsxs("div",{className:"flex flex-1 flex-col items-center justify-center gap-3 px-6 text-center",children:[n.jsx(A,{name:"git-branch",className:"size-6 text-muted-foreground"}),n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:u("diffView.branch.noBaseTitle")}),n.jsx("div",{className:"max-w-sm typography-micro text-muted-foreground",children:u("diffView.branch.noBaseDescription")}),n.jsx("input",{type:"text",value:gt,onChange:l=>sn(l.target.value),placeholder:u("gitView.branch.searchPlaceholder"),"aria-label":u("gitView.branch.searchPlaceholder"),className:"w-full max-w-sm rounded-md border border-border/60 bg-[var(--surface-elevated)] px-2.5 py-1.5 typography-meta text-foreground outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]"}),n.jsx(at,{outerClassName:"max-h-48 w-full max-w-sm min-h-0",className:"px-1 py-1",children:r.length===0?n.jsx("div",{className:"px-2 py-3 typography-meta text-muted-foreground",children:u("gitView.branch.empty")}):n.jsx("div",{className:"flex flex-col gap-0.5",children:r.map(l=>n.jsxs("button",{type:"button",onClick:()=>m&&R&&Zt(m,R,l),className:"flex items-center gap-2 rounded-md px-2 py-1.5 text-left hover:bg-interactive-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]",children:[n.jsx(A,{name:"git-branch",className:"size-3.5 text-primary"}),n.jsx("span",{className:"truncate typography-ui-label text-foreground",title:l,children:l})]},l))})})]})}if(bt)return n.jsxs("div",{className:"flex flex-1 flex-col items-center justify-center gap-3 px-6 text-center",children:[n.jsx("div",{className:"typography-ui-label font-semibold text-foreground",children:u("diffView.branch.loadError")}),n.jsx("div",{className:"max-w-sm typography-micro text-muted-foreground",children:bt}),n.jsx(pe,{variant:"outline",size:"sm",onClick:()=>nt(),children:u("diffView.actions.retry")})]});if(_e===null)return n.jsxs("div",{className:"flex flex-1 items-center justify-center gap-2 text-sm text-muted-foreground",children:[n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}),u("diffView.branch.loadingFiles")]})}return S.length===0?n.jsx("div",{className:"flex flex-1 items-center justify-center text-sm text-muted-foreground",children:c==="turn"?u("diffView.state.noLastTurnChanges"):c==="branch"&&ae?u("diffView.branch.empty",{base:ae}):u("diffView.state.cleanWorkingTree")}):xn()};return n.jsxs("div",{className:"flex h-full flex-col overflow-hidden bg-background",children:[n.jsxs("div",{className:"@container/diff-toolbar flex min-w-0 items-center gap-2 px-3 py-2 bg-background",children:[y===!1&&Array.isArray(P)&&P.length>0?n.jsx(Kn,{repositories:P,selectedRepository:j??null,onSelectRepository:t=>{w&&G(w,t)},repositoryRoot:w??void 0}):null,!L&&(c==="working"||c==="staged"||c==="turn"||c==="branch"?n.jsx(js,{scope:c,workingCount:Wt,stagedCount:Ut,turnCount:qt,branchCount:ln,showBranchOption:Ze,onScopeChange:t=>{C(t),f?.(t)}}):n.jsx("div",{className:"flex items-center gap-1 rounded-md px-2 py-1 text-muted-foreground shrink-0",children:n.jsx("span",{className:"typography-ui-label font-semibold text-foreground",children:ee&&!N?u("diffView.state.loadingChanges"):S.length===1?u("diffView.summary.changedFilesSingle",{count:S.length}):u("diffView.summary.changedFilesPlural",{count:S.length})})})),S.length>0&&n.jsxs(pe,{variant:"ghost",size:"sm",onClick:fn,className:ue("diff-toolbar__expand-button h-7 flex-shrink-0 gap-1 px-1.5 text-muted-foreground hover:text-foreground","ml-auto"),title:B.size>0?u("diffView.actions.collapseAll"):u("diffView.actions.expandAll"),children:[n.jsx(A,{name:"expand-up-down",className:"size-4"}),n.jsx("span",{className:"diff-toolbar__expand-label typography-ui-label",children:B.size>0?u("diffView.actions.collapseAll"):u("diffView.actions.expandAll")})]}),S.length>0&&Gt&&n.jsxs(pe,{variant:"default",size:"sm",onClick:()=>be(!0),disabled:we,className:"diff-toolbar__review-button h-7 flex-shrink-0 gap-1.5 px-2","aria-label":u("diffView.actions.reviewAria"),children:[we?n.jsx(A,{name:"loader-4",className:"size-4 animate-spin"}):n.jsx(A,{name:"search-eye",className:"size-4"}),n.jsx("span",{className:"diff-toolbar__review-label typography-ui-label",children:u("diffView.actions.review")})]}),S.length>0&&Kt&&n.jsxs(pe,{variant:"outline",size:"sm",onClick:()=>{const t=m??"";k(t,{kind:"working-tree",scope:c==="staged"||c==="working"?c:"all"}),le(t,"walkthrough")},className:ue("diff-toolbar__walkthrough-button h-7 flex-shrink-0 gap-1.5 px-2",Jn),"aria-label":u("walkthrough.action.open"),children:[n.jsx(A,{name:"route",className:"size-4"}),n.jsx("span",{className:"diff-toolbar__walkthrough-label typography-ui-label",children:u("walkthrough.action.open")})]}),S.length>0&&n.jsxs(Bn,{children:[n.jsx(Vn,{asChild:!0,children:n.jsx(pe,{variant:"ghost",size:"sm",onClick:()=>xe(t=>!t),"aria-pressed":fe,"aria-label":u(fe?"diffView.actions.disableFullFiles":"diffView.actions.loadFullFiles"),className:ue("h-7 w-7 flex-shrink-0 p-0 text-muted-foreground hover:text-foreground",fe&&"bg-interactive-selection text-interactive-selection-foreground"),children:n.jsx(A,{name:"file-download",className:"size-4"})})}),n.jsx(Ln,{children:n.jsx("p",{children:u(fe?"diffView.actions.disableFullFiles":"diffView.actions.loadFullFiles")})})]}),S.length>0&&n.jsx(pe,{variant:"ghost",size:"sm",onClick:()=>Pt(!ut),className:ue("h-5 w-5 p-0 transition-opacity",qe?"text-foreground opacity-100":"text-muted-foreground opacity-60 hover:opacity-100"),title:u(qe?"diffView.actions.disableLineWrap":"diffView.actions.enableLineWrap"),children:n.jsx(A,{name:"text-wrap",className:"size-4"})}),jt&&n.jsx(Mt,{mode:jt==="side-by-side"?"side-by-side":"unified",onModeChange:mn})]}),n.jsx(Tn,{open:Le,onOpenChange:be,projectDirectory:m??null,submitting:we,onConfirm:dn}),bn()]})};export{Ki as DiffView};
|