@alivault/pico 0.11.0 → 0.13.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/.output/nitro.json +1 -1
- package/.output/public/assets/addon-fit-CMMXLNsg.js +1 -0
- package/.output/public/assets/{index-DPU34F0T.js → index-CW1T9dk-.js} +11 -10
- package/.output/public/assets/routes-2LboeUx4.js +2194 -0
- package/.output/public/assets/styles-B1ITYh-r.css +2 -0
- package/.output/public/assets/xterm-CCMwI7sy.js +36 -0
- package/.output/server/_libs/lucide-react.mjs +46 -1
- package/.output/server/_libs/xterm__addon-fit.mjs +44 -0
- package/.output/server/_libs/xterm__xterm.mjs +10234 -0
- package/.output/server/_ssr/{router-Ccz1kegF.mjs → router-l__gf5Y7.mjs} +866 -173
- package/.output/server/_ssr/{routes-D3Hu5M6D.mjs → routes-CuWg5WTI.mjs} +167 -27
- package/.output/server/_ssr/{routes-DGf2MDLT.mjs → routes-DySm_W8N.mjs} +1946 -631
- package/.output/server/_ssr/ssr.mjs +2 -2
- package/.output/server/{_tanstack-start-manifest_v-BWLjOj7J.mjs → _tanstack-start-manifest_v-CVoKKKc_.mjs} +5 -4
- package/.output/server/index.mjs +542 -528
- package/.output/server/node_modules/node-pty/LICENSE +69 -0
- package/.output/server/node_modules/node-pty/README.md +165 -0
- package/.output/server/node_modules/node-pty/binding.gyp +111 -0
- package/.output/server/node_modules/node-pty/build/Makefile +369 -0
- package/.output/server/node_modules/node-pty/build/Release/pty.node +0 -0
- package/.output/server/node_modules/node-pty/build/binding.Makefile +6 -0
- package/.output/server/node_modules/node-pty/build/pty.target.mk +168 -0
- package/.output/server/node_modules/node-pty/deps/.editorconfig +2 -0
- package/.output/server/node_modules/node-pty/deps/winpty/.drone.yml +17 -0
- package/.output/server/node_modules/node-pty/deps/winpty/.gitattributes +19 -0
- package/.output/server/node_modules/node-pty/deps/winpty/LICENSE +21 -0
- package/.output/server/node_modules/node-pty/deps/winpty/Makefile +166 -0
- package/.output/server/node_modules/node-pty/deps/winpty/README.md +151 -0
- package/.output/server/node_modules/node-pty/deps/winpty/RELEASES.md +280 -0
- package/.output/server/node_modules/node-pty/deps/winpty/VERSION.txt +1 -0
- package/.output/server/node_modules/node-pty/deps/winpty/configure +167 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/BufferResizeTests.cc +90 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ChangeScreenBuffer.cc +53 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ClearConsole.cc +72 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ConinMode.cc +117 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ConinMode.ps1 +116 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ConoutMode.cc +113 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/DebugClient.py +42 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/DebugServer.py +63 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/DumpLines.py +5 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/EnableExtendedFlags.txt +46 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt +528 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt +633 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP932.txt +630 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP936.txt +630 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP949.txt +630 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/CP950.txt +630 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt +16 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/Results.txt +4 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt +144 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/FontSurvey.cc +100 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/FormatChar.h +21 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/FreezePerfTest.cc +62 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/GetCh.cc +20 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/GetConsolePos.cc +41 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/GetFont.cc +261 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/IdentifyConsoleWindow.ps1 +51 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/IsNewConsole.cc +87 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/MouseInputNotes.txt +90 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/MoveConsoleWindow.cc +34 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Notes.txt +219 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/OSVersion.cc +27 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ScreenBufferFreezeInactive.cc +101 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ScreenBufferTest.cc +671 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ScreenBufferTest2.cc +151 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/SelectAllTest.cc +45 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/SetBufferSize.cc +32 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/SetCursorPos.cc +10 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/SetFont.cc +145 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/SetWindowRect.cc +36 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ShowArgv.cc +12 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/ShowConsoleInput.cc +40 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Spew.py +5 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/TestUtil.cc +172 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/UnicodeDoubleWidthTest.cc +102 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/UnicodeWideTest1.cc +246 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/UnicodeWideTest2.cc +130 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/UnixEcho.cc +89 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Utf16Echo.cc +46 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/VeryLargeRead.cc +122 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/VkEscapeTest.cc +56 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win10ResizeWhileFrozen.cc +52 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win10WrapTest1.cc +57 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win10WrapTest2.cc +30 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Echo1.cc +26 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Echo2.cc +19 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Test1.cc +46 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Test2.cc +70 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Test3.cc +78 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/Win32Write1.cc +44 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/WindowsBugCrashReader.cc +27 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/WriteConsole.cc +106 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/build32.sh +9 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/build64.sh +9 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/color-test.sh +212 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/font-notes.txt +300 -0
- package/.output/server/node_modules/node-pty/deps/winpty/misc/winbug-15048.cc +201 -0
- package/.output/server/node_modules/node-pty/deps/winpty/ship/build-pty4j-libpty.bat +36 -0
- package/.output/server/node_modules/node-pty/deps/winpty/ship/common_ship.py +53 -0
- package/.output/server/node_modules/node-pty/deps/winpty/ship/make_msvc_package.py +165 -0
- package/.output/server/node_modules/node-pty/deps/winpty/ship/ship.py +108 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Agent.cc +613 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Agent.h +103 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/AgentCreateDesktop.cc +84 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/AgentCreateDesktop.h +28 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleFont.cc +632 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleFont.h +28 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleInput.cc +852 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleInput.h +109 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleInputReencoding.cc +121 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleInputReencoding.h +36 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleLine.cc +152 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/ConsoleLine.h +41 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Coord.h +87 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/DebugShowInput.cc +239 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/DebugShowInput.h +32 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/DefaultInputMap.cc +422 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/DefaultInputMap.h +28 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/DsrSender.h +30 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/EventLoop.cc +99 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/EventLoop.h +47 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/InputMap.cc +246 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/InputMap.h +114 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/LargeConsoleRead.cc +71 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/LargeConsoleRead.h +68 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/NamedPipe.cc +378 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/NamedPipe.h +125 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Scraper.cc +699 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Scraper.h +103 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/SimplePool.h +75 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/SmallRect.h +143 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Terminal.cc +535 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Terminal.h +69 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/UnicodeEncoding.h +157 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/UnicodeEncodingTest.cc +189 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Win32Console.cc +107 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Win32Console.h +67 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Win32ConsoleBuffer.cc +193 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/Win32ConsoleBuffer.h +99 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/main.cc +114 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/agent/subdir.mk +61 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/configurations.gypi +60 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/debugserver/DebugServer.cc +117 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/debugserver/subdir.mk +41 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/include/winpty.h +242 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/include/winpty_constants.h +131 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/AgentLocation.cc +75 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/AgentLocation.h +28 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/LibWinptyException.h +54 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/WinptyInternal.h +72 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/subdir.mk +46 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/libwinpty/winpty.cc +970 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/AgentMsg.h +38 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/BackgroundDesktop.cc +122 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/BackgroundDesktop.h +73 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/Buffer.cc +103 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/Buffer.h +102 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/DebugClient.cc +187 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/DebugClient.h +38 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/GenRandom.cc +138 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/GenRandom.h +55 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/GetCommitHash.bat +13 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/Mutex.h +54 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/OsModule.h +63 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/OwnedHandle.cc +36 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/OwnedHandle.h +45 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/PrecompiledHeader.h +43 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/StringBuilder.h +227 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/StringBuilderTest.cc +114 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/StringUtil.cc +55 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/StringUtil.h +80 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/TimeMeasurement.h +63 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/UnixCtrlChars.h +45 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/UpdateGenVersion.bat +20 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WindowsSecurity.cc +460 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WindowsSecurity.h +104 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WindowsVersion.cc +252 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WindowsVersion.h +29 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyAssert.cc +55 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyAssert.h +64 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyException.cc +57 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyException.h +43 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyVersion.cc +42 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/WinptyVersion.h +27 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/shared/winpty_snprintf.h +99 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/subdir.mk +5 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/tests/subdir.mk +28 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/tests/trivial_test.cc +158 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/InputHandler.cc +114 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/InputHandler.h +56 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/OutputHandler.cc +80 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/OutputHandler.h +53 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/Util.cc +86 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/Util.h +31 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/WakeupFd.cc +70 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/WakeupFd.h +42 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/main.cc +729 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/unix-adapter/subdir.mk +41 -0
- package/.output/server/node_modules/node-pty/deps/winpty/src/winpty.gyp +234 -0
- package/.output/server/node_modules/node-pty/deps/winpty/vcbuild.bat +83 -0
- package/.output/server/node_modules/node-pty/lib/conpty_console_list_agent.js +16 -0
- package/.output/server/node_modules/node-pty/lib/conpty_console_list_agent.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/eventEmitter2.js +47 -0
- package/.output/server/node_modules/node-pty/lib/eventEmitter2.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/eventEmitter2.test.js +30 -0
- package/.output/server/node_modules/node-pty/lib/eventEmitter2.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/index.js +52 -0
- package/.output/server/node_modules/node-pty/lib/index.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/interfaces.js +7 -0
- package/.output/server/node_modules/node-pty/lib/interfaces.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/shared/conout.js +11 -0
- package/.output/server/node_modules/node-pty/lib/shared/conout.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/terminal.js +190 -0
- package/.output/server/node_modules/node-pty/lib/terminal.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/terminal.test.js +139 -0
- package/.output/server/node_modules/node-pty/lib/terminal.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/testUtils.test.js +28 -0
- package/.output/server/node_modules/node-pty/lib/testUtils.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/types.js +7 -0
- package/.output/server/node_modules/node-pty/lib/types.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/unixTerminal.js +346 -0
- package/.output/server/node_modules/node-pty/lib/unixTerminal.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/unixTerminal.test.js +351 -0
- package/.output/server/node_modules/node-pty/lib/unixTerminal.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/utils.js +39 -0
- package/.output/server/node_modules/node-pty/lib/utils.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
- package/.output/server/node_modules/node-pty/lib/windowsConoutConnection.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/windowsPtyAgent.js +320 -0
- package/.output/server/node_modules/node-pty/lib/windowsPtyAgent.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/windowsPtyAgent.test.js +90 -0
- package/.output/server/node_modules/node-pty/lib/windowsPtyAgent.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/windowsTerminal.js +199 -0
- package/.output/server/node_modules/node-pty/lib/windowsTerminal.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/windowsTerminal.test.js +219 -0
- package/.output/server/node_modules/node-pty/lib/windowsTerminal.test.js.map +1 -0
- package/.output/server/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/.output/server/node_modules/node-pty/lib/worker/conoutSocketWorker.js.map +1 -0
- package/.output/server/node_modules/node-pty/package.json +64 -0
- package/.output/server/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/pty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/pty.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/winpty-agent.exe +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/winpty-agent.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/winpty.dll +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-arm64/winpty.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/pty.node +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/pty.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/winpty-agent.exe +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/winpty-agent.pdb +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/winpty.dll +0 -0
- package/.output/server/node_modules/node-pty/prebuilds/win32-x64/winpty.pdb +0 -0
- package/.output/server/node_modules/node-pty/scripts/gen-compile-commands.js +8 -0
- package/.output/server/node_modules/node-pty/scripts/increment-version.js +54 -0
- package/.output/server/node_modules/node-pty/scripts/post-install.js +80 -0
- package/.output/server/node_modules/node-pty/scripts/prebuild.js +34 -0
- package/.output/server/node_modules/node-pty/src/conpty_console_list_agent.ts +15 -0
- package/.output/server/node_modules/node-pty/src/eventEmitter2.test.ts +30 -0
- package/.output/server/node_modules/node-pty/src/eventEmitter2.ts +48 -0
- package/.output/server/node_modules/node-pty/src/index.ts +52 -0
- package/.output/server/node_modules/node-pty/src/interfaces.ts +130 -0
- package/.output/server/node_modules/node-pty/src/native.d.ts +54 -0
- package/.output/server/node_modules/node-pty/src/shared/conout.ts +15 -0
- package/.output/server/node_modules/node-pty/src/terminal.test.ts +119 -0
- package/.output/server/node_modules/node-pty/src/terminal.ts +211 -0
- package/.output/server/node_modules/node-pty/src/testUtils.test.ts +23 -0
- package/.output/server/node_modules/node-pty/src/tsconfig.json +22 -0
- package/.output/server/node_modules/node-pty/src/types.ts +15 -0
- package/.output/server/node_modules/node-pty/src/unix/pty.cc +799 -0
- package/.output/server/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
- package/.output/server/node_modules/node-pty/src/unixTerminal.test.ts +367 -0
- package/.output/server/node_modules/node-pty/src/unixTerminal.ts +388 -0
- package/.output/server/node_modules/node-pty/src/utils.ts +29 -0
- package/.output/server/node_modules/node-pty/src/win/conpty.cc +583 -0
- package/.output/server/node_modules/node-pty/src/win/conpty.h +41 -0
- package/.output/server/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
- package/.output/server/node_modules/node-pty/src/win/path_util.cc +95 -0
- package/.output/server/node_modules/node-pty/src/win/path_util.h +26 -0
- package/.output/server/node_modules/node-pty/src/win/winpty.cc +333 -0
- package/.output/server/node_modules/node-pty/src/windowsConoutConnection.ts +82 -0
- package/.output/server/node_modules/node-pty/src/windowsPtyAgent.test.ts +94 -0
- package/.output/server/node_modules/node-pty/src/windowsPtyAgent.ts +321 -0
- package/.output/server/node_modules/node-pty/src/windowsTerminal.test.ts +229 -0
- package/.output/server/node_modules/node-pty/src/windowsTerminal.ts +203 -0
- package/.output/server/node_modules/node-pty/src/worker/conoutSocketWorker.ts +22 -0
- package/.output/server/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
- package/.output/server/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
- package/.output/server/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
- package/.output/server/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
- package/.output/server/node_modules/node-pty/typings/node-pty.d.ts +211 -0
- package/.output/server/package.json +1 -0
- package/package.json +11 -4
- package/.output/public/assets/routes-CVlcrX-A.js +0 -2195
- package/.output/public/assets/styles-Chvsnn7o.css +0 -2
- package/scripts/patch-react-jsx-dev-runtime.mjs +0 -93
- /package/.output/public/assets/{wasm-CEUrWlVz.js → wasm-D_MQmneJ.js} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as __toESM } from "../_runtime.mjs";
|
|
2
2
|
import { $ as require_react, A as TabsTab, B as Input, C as MenuPositioner, D as MenuGroupLabel, E as MenuItem, F as DialogPopup, H as useRender, I as DialogDescription$1, L as DialogClose$1, M as DialogTitle$1, N as DialogRoot, O as MenuGroup, P as DialogPortal$1, Q as require_jsx_runtime, R as DialogBackdrop, S as MenuRoot, T as MenuPopup, V as Button, Y as mergeProps, _ as AccordionItem$1, a as ContextMenuRoot, b as MenuTrigger, c as CollapsibleRoot, d as PopoverPortal, f as PopoverTrigger$1, g as AccordionHeader, h as AccordionTrigger$1, i as ContextMenuTrigger$1, j as TabsRoot, k as TabsList$1, l as PopoverPopup, m as AccordionPanel, n as ToggleGroup, o as CollapsiblePanel, p as PopoverRoot, r as Toggle, s as CollapsibleTrigger$1, t as AlertDialogRoot, u as PopoverPositioner, v as AccordionRoot, w as MenuPortal, x as MenuSubmenuRoot, y as MenuSubmenuTrigger, z as Separator } from "../_libs/@base-ui/react+[...].mjs";
|
|
3
3
|
import { t as cva } from "../_libs/class-variance-authority+clsx.mjs";
|
|
4
|
-
import { A as
|
|
5
|
-
import { $ as
|
|
4
|
+
import { A as Folder, B as ChevronsUpDown, C as ListStart, D as GitPullRequestArrow, E as ImagePlus, F as EllipsisVertical, G as Check, I as Download, J as ArrowUpRight, K as ArrowUp, L as Copy, M as FileDiff, N as ExternalLink, O as GitBranch, P as Ellipsis, R as Command, S as Maximize2, U as ChevronRight, V as ChevronsDownUp, W as ChevronDown, X as ArrowLeft, Z as ArrowDown, _ as PanelLeftClose, a as TriangleAlert, b as Minus, c as Square, d as Settings2, f as Search, g as PanelLeftOpen, h as PanelLeft, i as Undo2, j as FolderPlus, k as GitCommitHorizontal, l as SquareTerminal, m as PanelRight, n as WandSparkles, o as Trash2, p as Plus, q as ArrowUpToLine, r as Upload, s as Tag, t as X, u as SquarePen, w as ListEnd, x as Minimize2, y as OctagonX } from "../_libs/lucide-react.mjs";
|
|
5
|
+
import { $ as normalizeSessionSelectionKeys, A as THEME_STORAGE_KEY, At as themeFamilyDescription, B as buildItemsFromSync, C as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, Ct as rememberStoredPromptDraft, D as TERMINAL_PANEL_OPEN_STORAGE_KEY, Dt as sameContextUsage, E as TERMINAL_PANEL_HEIGHT_STORAGE_KEY, Et as safeLocalStorageSetItem, F as TooltipTrigger, Ft as thinkingSummaryText, G as exploreShellCommandNameFromTool, I as VIEWER_CONTEXT_STORAGE_KEY, It as toolArgsAreIncompleteJsonObject, L as appliedThemeClass, Lt as toolCategoryFromTool, M as Tooltip$1, Mt as themeFamilyKeywords, N as TooltipContent, Nt as themeFamilyLabel, O as THEME_COLOR_MODE_STORAGE_KEY, Ot as sessionListEntryKey, Pt as themeFamilySupportsColorMode, Q as normalizePromptImage, R as appliedThemeClassColorMode, Rt as toolCouldBecomeExploreFromTool, S as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, St as readStoredThemeColorMode, T as Spinner, Tt as safeLocalStorageGetItem, U as createContextId, V as cn, W as createInitialSessionState, X as getSessionTitle, Y as flattenTree, _ as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, _t as readStoredSessionDoneSoundEnabled, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as promptDraftKeyMatchesOwner, b as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, bt as readStoredTerminalTabs, c as Kbd, ct as readStoredCenterMessages, d as PICO_DIFF_SHIKI_THEMES, dt as readStoredHideToolBlocks, et as normalizeStoredDirectoryList, f as PICO_SHIKI_VARIABLE_DEFAULTS, ft as readStoredPinnedSessionKeys, g as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, gt as readStoredSessionDoneDesktopNotificationsEnabled, h as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ht as readStoredRightSidebarOpen, i as CENTER_MESSAGES_STORAGE_KEY, it as promptDraftKey, j as TitleTooltip, jt as themeFamilyFixedMode, k as THEME_FAMILIES, kt as themeColorModeLabel, l as KeyboardShortcutContent, lt as readStoredCollapsedDirectories, m as RECENT_DIRECTORIES_STORAGE_KEY, mt as readStoredRecentDirectories, n as APPLIED_THEME_STORAGE_KEY, nt as normalizeThemeFamily, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as rawShellCommandTextFromTool, p as PINNED_SESSIONS_STORAGE_KEY, pt as readStoredPromptDraft, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as previewUrlForImage, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredAutoScrollEnabled, tt as normalizeThemeColorMode, ut as readStoredDraftDirectory, v as RIGHT_SIDEBAR_HISTORY_TAB_STORAGE_KEY, vt as readStoredSidebarDirectories, w as SIDEBAR_DIRECTORIES_STORAGE_KEY, wt as rememberStoredTerminalTabs, x as Route, xt as readStoredTheme, y as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, yt as readStoredTerminalPanelOpen } from "./routes-CuWg5WTI.mjs";
|
|
6
6
|
import { i as useQuery, n as useIsMutating, o as useQueryClient, r as useIsFetching, t as useMutation } from "../_libs/tanstack__react-query.mjs";
|
|
7
7
|
import { t as useHotkeys } from "../_libs/tanstack__react-hotkeys.mjs";
|
|
8
8
|
import { a as matchesKeyboardEvent, i as batch, o as formatForDisplay, r as createStore } from "../_libs/@tanstack/hotkeys+[...].mjs";
|
|
@@ -22,7 +22,7 @@ import { t as remarkGfm } from "../_libs/remark-gfm.mjs";
|
|
|
22
22
|
import { a as getBuiltInSpriteSheet, i as getBuiltInFileIconColor, n as FileTree, r as createFileTreeIconResolver, t as useFileTree } from "../_libs/@pierre/trees+[...].mjs";
|
|
23
23
|
import { a as closestCenter, c as useDraggable, d as useSensors, f as CSS$1, i as PointerSensor, n as DragOverlay, t as DndContext, u as useSensor } from "../_libs/@dnd-kit/core+[...].mjs";
|
|
24
24
|
import { a as verticalListSortingStrategy, i as useSortable, n as arrayMove, r as horizontalListSortingStrategy, t as SortableContext } from "../_libs/dnd-kit__sortable.mjs";
|
|
25
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/routes-
|
|
25
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/routes-DySm_W8N.js
|
|
26
26
|
var import_react = /* @__PURE__ */ __toESM(require_react());
|
|
27
27
|
var import_jsx_runtime = require_jsx_runtime();
|
|
28
28
|
var MOBILE_BREAKPOINT = 768;
|
|
@@ -503,8 +503,9 @@ function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange: set
|
|
|
503
503
|
window.addEventListener("keydown", handleKeyDown);
|
|
504
504
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
505
505
|
}, [toggleSidebarRef]);
|
|
506
|
+
const state = open ? "expanded" : "collapsed";
|
|
506
507
|
const contextValue = {
|
|
507
|
-
state
|
|
508
|
+
state,
|
|
508
509
|
open,
|
|
509
510
|
setOpen,
|
|
510
511
|
isMobile,
|
|
@@ -522,6 +523,7 @@ function SidebarProvider({ defaultOpen = true, open: openProp, onOpenChange: set
|
|
|
522
523
|
value: contextValue,
|
|
523
524
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
524
525
|
"data-slot": "sidebar-wrapper",
|
|
526
|
+
"data-sidebar-state": state,
|
|
525
527
|
style: {
|
|
526
528
|
...style,
|
|
527
529
|
"--sidebar-width": sidebarWidth,
|
|
@@ -6150,6 +6152,17 @@ function updateDirectoryIndexLoadingState(current, directories, loading) {
|
|
|
6150
6152
|
}
|
|
6151
6153
|
return changed ? next : current;
|
|
6152
6154
|
}
|
|
6155
|
+
function normalizeOptimisticSidebarPreview(value) {
|
|
6156
|
+
const text = value.replace(/\s+/g, " ").trim();
|
|
6157
|
+
if (!text) return "";
|
|
6158
|
+
if (text.length <= 240) return text;
|
|
6159
|
+
return `${text.slice(0, 239).trimEnd()}…`;
|
|
6160
|
+
}
|
|
6161
|
+
function sidebarEntryMatchesIdentity(entry, identity) {
|
|
6162
|
+
const sessionId = identity.sessionId?.trim() || "";
|
|
6163
|
+
const sessionPath = identity.sessionPath?.trim() || "";
|
|
6164
|
+
return Boolean(sessionPath && entry.path === sessionPath || sessionId && entry.id === sessionId);
|
|
6165
|
+
}
|
|
6153
6166
|
function upsertOptimisticSidebarSessionEntry(current, entry) {
|
|
6154
6167
|
const directory = entry.cwd.trim();
|
|
6155
6168
|
const optimisticId = entry.id.trim();
|
|
@@ -6175,6 +6188,40 @@ function upsertOptimisticSidebarSessionEntry(current, entry) {
|
|
|
6175
6188
|
}
|
|
6176
6189
|
};
|
|
6177
6190
|
}
|
|
6191
|
+
function updateOptimisticSidebarSessionPreviewEntry(current, options) {
|
|
6192
|
+
const preview = normalizeOptimisticSidebarPreview(options.preview);
|
|
6193
|
+
if (!preview) return current;
|
|
6194
|
+
let changed = false;
|
|
6195
|
+
const next = { ...current };
|
|
6196
|
+
for (const [directory, snapshot] of Object.entries(current)) {
|
|
6197
|
+
const updatedEntries = [];
|
|
6198
|
+
let sessionsChanged = false;
|
|
6199
|
+
const sessions = snapshot.sessions.map((entry) => {
|
|
6200
|
+
if (!sidebarEntryMatchesIdentity(entry, options)) return entry;
|
|
6201
|
+
const nextEntry = {
|
|
6202
|
+
...entry,
|
|
6203
|
+
modified: options.modified,
|
|
6204
|
+
lastUserMessageAt: options.modified,
|
|
6205
|
+
lastMessageAt: options.modified,
|
|
6206
|
+
lastMessagePreview: preview,
|
|
6207
|
+
streaming: true,
|
|
6208
|
+
unread: false
|
|
6209
|
+
};
|
|
6210
|
+
updatedEntries.push(nextEntry);
|
|
6211
|
+
sessionsChanged ||= nextEntry !== entry;
|
|
6212
|
+
return nextEntry;
|
|
6213
|
+
});
|
|
6214
|
+
if (!sessionsChanged) continue;
|
|
6215
|
+
const updatedKeys = new Set(updatedEntries.map(sessionListEntryKey));
|
|
6216
|
+
next[directory] = {
|
|
6217
|
+
...snapshot,
|
|
6218
|
+
revision: `optimistic-preview:${options.modified}:${snapshot.revision}`,
|
|
6219
|
+
sessions: [...updatedEntries, ...sessions.filter((entry) => !updatedKeys.has(sessionListEntryKey(entry)))]
|
|
6220
|
+
};
|
|
6221
|
+
changed = true;
|
|
6222
|
+
}
|
|
6223
|
+
return changed ? next : current;
|
|
6224
|
+
}
|
|
6178
6225
|
function removeOptimisticSidebarSessionEntry(current, optimisticId) {
|
|
6179
6226
|
const targetId = optimisticId?.trim() || "";
|
|
6180
6227
|
if (!targetId) return current;
|
|
@@ -10573,10 +10620,9 @@ var PICO_DIFF_COLOR_CSS = `
|
|
|
10573
10620
|
--diffs-bg-deletion-emphasis-override: color-mix(in lab, var(--diffs-bg) 42%, var(--diffs-deletion-base));
|
|
10574
10621
|
}
|
|
10575
10622
|
|
|
10576
|
-
|
|
10577
|
-
|
|
10578
|
-
|
|
10579
|
-
}
|
|
10623
|
+
[data-overflow="wrap"] [data-annotation-content] {
|
|
10624
|
+
inline-size: var(--diffs-column-content-width, auto);
|
|
10625
|
+
max-inline-size: min(100%, calc(100vw - 1rem));
|
|
10580
10626
|
}
|
|
10581
10627
|
|
|
10582
10628
|
[data-line-type="change-addition"]:is(
|
|
@@ -10768,22 +10814,7 @@ function formatToolArgString(value) {
|
|
|
10768
10814
|
return trimmed;
|
|
10769
10815
|
}
|
|
10770
10816
|
function rawShellCommandText(block) {
|
|
10771
|
-
|
|
10772
|
-
if (typeof block.args === "string") {
|
|
10773
|
-
const trimmed = block.args.trim();
|
|
10774
|
-
if (!trimmed) return "";
|
|
10775
|
-
try {
|
|
10776
|
-
const parsed = JSON.parse(trimmed);
|
|
10777
|
-
if (parsed && typeof parsed === "object" && "command" in parsed) {
|
|
10778
|
-
const command = parsed.command;
|
|
10779
|
-
return typeof command === "string" ? command.trim() : trimmed;
|
|
10780
|
-
}
|
|
10781
|
-
} catch {
|
|
10782
|
-
return trimmed;
|
|
10783
|
-
}
|
|
10784
|
-
return trimmed;
|
|
10785
|
-
}
|
|
10786
|
-
return getToolArgText(normalizeToolArgs(block.args), "command") || toolCommandPreview(block);
|
|
10817
|
+
return block.type === "tool" ? rawShellCommandTextFromTool(block.name, block.args) : "";
|
|
10787
10818
|
}
|
|
10788
10819
|
function toolCallText(block) {
|
|
10789
10820
|
if (block.type !== "tool") return "";
|
|
@@ -10817,64 +10848,12 @@ function toolOutputText(block) {
|
|
|
10817
10848
|
if (block.isError) return "Tool failed with no output.";
|
|
10818
10849
|
return "No output available.";
|
|
10819
10850
|
}
|
|
10820
|
-
var EXPLORE_TOOL_NAMES = new Set([
|
|
10821
|
-
"read",
|
|
10822
|
-
"grep",
|
|
10823
|
-
"glob",
|
|
10824
|
-
"find",
|
|
10825
|
-
"ls",
|
|
10826
|
-
"list",
|
|
10827
|
-
"rg"
|
|
10828
|
-
]);
|
|
10829
|
-
var EXPLORE_SHELL_COMMAND_NAMES = new Set([
|
|
10830
|
-
"find",
|
|
10831
|
-
"grep",
|
|
10832
|
-
"ls",
|
|
10833
|
-
"rg"
|
|
10834
|
-
]);
|
|
10835
|
-
var SKIPPABLE_SHELL_COMMAND_NAMES = new Set([
|
|
10836
|
-
"cd",
|
|
10837
|
-
"export",
|
|
10838
|
-
"pwd",
|
|
10839
|
-
"set"
|
|
10840
|
-
]);
|
|
10841
|
-
var SHELL_COMMAND_WRAPPER_NAMES = new Set([
|
|
10842
|
-
"command",
|
|
10843
|
-
"env",
|
|
10844
|
-
"noglob",
|
|
10845
|
-
"sudo",
|
|
10846
|
-
"time"
|
|
10847
|
-
]);
|
|
10848
|
-
function shellCommandNameFromSegment(segment) {
|
|
10849
|
-
let text = segment.trim();
|
|
10850
|
-
while (text) {
|
|
10851
|
-
const assignmentMatch = text.match(/^[A-Za-z_][A-Za-z0-9_]*=\S+\s+/);
|
|
10852
|
-
if (assignmentMatch) {
|
|
10853
|
-
text = text.slice(assignmentMatch[0].length).trimStart();
|
|
10854
|
-
continue;
|
|
10855
|
-
}
|
|
10856
|
-
const commandMatch = text.match(/^([./A-Za-z0-9_-]+)\b/);
|
|
10857
|
-
if (!commandMatch) return "";
|
|
10858
|
-
const commandPath = commandMatch[1] || "";
|
|
10859
|
-
const commandName = pathBaseName$1(commandPath);
|
|
10860
|
-
if (!SHELL_COMMAND_WRAPPER_NAMES.has(commandName)) return commandName;
|
|
10861
|
-
text = text.slice(commandPath.length).trimStart();
|
|
10862
|
-
}
|
|
10863
|
-
return "";
|
|
10864
|
-
}
|
|
10865
10851
|
function exploreShellCommandName(block) {
|
|
10866
|
-
|
|
10867
|
-
const segments = rawShellCommandText(block).split(/(?:&&|\|\||;)/);
|
|
10868
|
-
for (const segment of segments) {
|
|
10869
|
-
const commandName = shellCommandNameFromSegment(segment);
|
|
10870
|
-
if (!commandName || SKIPPABLE_SHELL_COMMAND_NAMES.has(commandName)) continue;
|
|
10871
|
-
return EXPLORE_SHELL_COMMAND_NAMES.has(commandName) ? commandName : "";
|
|
10872
|
-
}
|
|
10873
|
-
return "";
|
|
10852
|
+
return block.type === "tool" ? exploreShellCommandNameFromTool(block.name, block.args) : "";
|
|
10874
10853
|
}
|
|
10875
10854
|
function matchesExploreToolBlock(block) {
|
|
10876
10855
|
if (block.type !== "tool") return false;
|
|
10877
|
-
return block.category === "explore" ||
|
|
10856
|
+
return block.category === "explore" || toolCategoryFromTool(block.name, block.args) === "explore";
|
|
10878
10857
|
}
|
|
10879
10858
|
function isExploreToolBlock(block) {
|
|
10880
10859
|
return matchesExploreToolBlock(block);
|
|
@@ -10882,7 +10861,10 @@ function isExploreToolBlock(block) {
|
|
|
10882
10861
|
function isPendingUnclassifiedToolBlock(block) {
|
|
10883
10862
|
if (block.type !== "tool" || !block.running || matchesExploreToolBlock(block)) return false;
|
|
10884
10863
|
if (!block.name) return true;
|
|
10885
|
-
if (block.name === "bash")
|
|
10864
|
+
if (block.name === "bash") {
|
|
10865
|
+
const category = toolCategoryFromTool(block.name, block.args);
|
|
10866
|
+
return !rawShellCommandText(block) || category !== "explore" && (toolArgsAreIncompleteJsonObject(block.args) || toolCouldBecomeExploreFromTool(block.name, block.args));
|
|
10867
|
+
}
|
|
10886
10868
|
return false;
|
|
10887
10869
|
}
|
|
10888
10870
|
function getToolArgNumber(args, key) {
|
|
@@ -11176,18 +11158,22 @@ function assistantMessagesModelLabel(items) {
|
|
|
11176
11158
|
function assistantItemIsWorking(item) {
|
|
11177
11159
|
return Boolean(item.streaming) || item.done === false || item.blocks.some((block) => block.type === "tool" && block.running);
|
|
11178
11160
|
}
|
|
11161
|
+
function assistantItemIsStreaming(item) {
|
|
11162
|
+
return Boolean(item.streaming);
|
|
11163
|
+
}
|
|
11179
11164
|
function assistantMessagesShellSnapshotFromBlocks(snapshot, blocks) {
|
|
11180
11165
|
const anchorBlockIndex = blocks.findIndex(assistantBlockIsMessageJumpAnchor);
|
|
11181
11166
|
const anchorBlock = anchorBlockIndex >= 0 ? blocks[anchorBlockIndex] : void 0;
|
|
11182
11167
|
const copyText = assistantCopyTextFromItems(snapshot.items);
|
|
11183
11168
|
const modelLabel = assistantMessagesModelLabel(snapshot.items);
|
|
11169
|
+
const streaming = snapshot.items.some(assistantItemIsStreaming);
|
|
11184
11170
|
const working = snapshot.items.some(assistantItemIsWorking);
|
|
11185
|
-
const hasFooter = Boolean(copyText.trim() || modelLabel
|
|
11171
|
+
const hasFooter = Boolean(copyText.trim() || modelLabel);
|
|
11186
11172
|
return {
|
|
11187
11173
|
...anchorBlock ? { anchorBlockKey: assistantBlockRenderKey(anchorBlock, anchorBlockIndex) } : {},
|
|
11188
11174
|
hasBlocks: blocks.length > 0,
|
|
11189
11175
|
hasFooter,
|
|
11190
|
-
streaming
|
|
11176
|
+
streaming,
|
|
11191
11177
|
working,
|
|
11192
11178
|
copyText,
|
|
11193
11179
|
modelLabel
|
|
@@ -11676,7 +11662,7 @@ function PlainToolOutput({ isError = false, text }) {
|
|
|
11676
11662
|
children: text
|
|
11677
11663
|
});
|
|
11678
11664
|
}
|
|
11679
|
-
function scrollDistanceFromBottom(element) {
|
|
11665
|
+
function scrollDistanceFromBottom$1(element) {
|
|
11680
11666
|
return element.scrollHeight - element.clientHeight - element.scrollTop;
|
|
11681
11667
|
}
|
|
11682
11668
|
function scrollElementToBottom(element) {
|
|
@@ -11700,7 +11686,7 @@ function useRunningToolAutoScroll({ contentKey, enabled }) {
|
|
|
11700
11686
|
}, [contentKey, enabled]);
|
|
11701
11687
|
const handleScroll = (event) => {
|
|
11702
11688
|
if (!enabled) return;
|
|
11703
|
-
autoScrollRef.current = scrollDistanceFromBottom(event.currentTarget) < 1;
|
|
11689
|
+
autoScrollRef.current = scrollDistanceFromBottom$1(event.currentTarget) < 1;
|
|
11704
11690
|
};
|
|
11705
11691
|
return {
|
|
11706
11692
|
onScroll: handleScroll,
|
|
@@ -12006,53 +11992,67 @@ var UserMessageCard = import_react.memo(function UserMessageCard({ item }) {
|
|
|
12006
11992
|
const selectedImage = selectedImageIndex === null ? null : item.images[selectedImageIndex] ?? null;
|
|
12007
11993
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
12008
11994
|
className: "mr-2 ml-auto w-fit max-w-[80%]",
|
|
12009
|
-
children: [
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
11995
|
+
children: [
|
|
11996
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
11997
|
+
className: "relative rounded-3xl bg-primary px-5 py-2.5 text-primary-foreground before:absolute before:-right-1.75 before:bottom-0 before:h-5.5 before:w-4 before:rounded-bl-[16px_14px] before:bg-primary before:content-[''] after:absolute after:-right-6.5 after:bottom-0 after:h-6.25 after:w-6.5 after:rounded-bl-[10px] after:bg-background after:content-['']",
|
|
11998
|
+
children: [
|
|
11999
|
+
labelText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
12000
|
+
className: "mb-2 flex items-center gap-2",
|
|
12001
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
|
|
12002
|
+
variant: "outline",
|
|
12003
|
+
className: "border-primary-foreground/35 bg-primary-foreground/10 text-primary-foreground",
|
|
12004
|
+
children: labelText
|
|
12005
|
+
})
|
|
12006
|
+
}) : null,
|
|
12007
|
+
item.text ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
12008
|
+
className: "text-sm break-words whitespace-pre-wrap text-primary-foreground",
|
|
12009
|
+
children: item.text
|
|
12010
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
12011
|
+
className: "text-sm text-primary-foreground/80",
|
|
12012
|
+
children: "Image prompt"
|
|
12013
|
+
}),
|
|
12014
|
+
item.images.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
12015
|
+
className: "mt-3 flex flex-wrap gap-3",
|
|
12016
|
+
children: item.images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
12017
|
+
type: "button",
|
|
12018
|
+
className: "max-w-full cursor-zoom-in overflow-hidden rounded-lg border border-primary-foreground/20 bg-primary-foreground/10 p-0 transition hover:opacity-90 focus-visible:ring-2 focus-visible:ring-primary-foreground/70 focus-visible:ring-offset-2 focus-visible:ring-offset-primary focus-visible:outline-none",
|
|
12019
|
+
onClick: () => setSelectedImageIndex(index),
|
|
12020
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
|
|
12021
|
+
src: image.previewUrl,
|
|
12022
|
+
alt: "Prompt upload",
|
|
12023
|
+
className: "block h-28 max-w-full object-cover"
|
|
12024
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
12025
|
+
className: "sr-only",
|
|
12026
|
+
children: "Open prompt upload"
|
|
12027
|
+
})]
|
|
12028
|
+
}, `${promptImageKey(image)}:${index}`))
|
|
12029
|
+
}) : null
|
|
12030
|
+
]
|
|
12031
|
+
}),
|
|
12032
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserMessageFooter, { copyText: item.text }),
|
|
12033
|
+
selectedImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageLightbox, {
|
|
12034
|
+
open: true,
|
|
12035
|
+
onOpenChange: (open) => {
|
|
12036
|
+
if (!open) setSelectedImageIndex(null);
|
|
12037
|
+
},
|
|
12038
|
+
imageSrc: selectedImage.previewUrl,
|
|
12039
|
+
imageAlt: "Prompt upload",
|
|
12040
|
+
title: "Prompt upload preview",
|
|
12041
|
+
description: "Expanded preview of an image attached to a user message."
|
|
12042
|
+
}) : null
|
|
12043
|
+
]
|
|
12054
12044
|
});
|
|
12055
12045
|
});
|
|
12046
|
+
function UserMessageFooter({ copyText }) {
|
|
12047
|
+
if (!copyText.trim()) return null;
|
|
12048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
12049
|
+
className: "mt-1 flex justify-end gap-1.5 text-xs font-medium text-muted-foreground",
|
|
12050
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageFooterCopyButton, {
|
|
12051
|
+
idleLabel: "Copy user message",
|
|
12052
|
+
text: copyText
|
|
12053
|
+
})
|
|
12054
|
+
});
|
|
12055
|
+
}
|
|
12056
12056
|
function assistantBlockIsVisible({ block, hideThinking, hideToolBlocks }) {
|
|
12057
12057
|
switch (block.type) {
|
|
12058
12058
|
case "text": return Boolean(block.text.trim());
|
|
@@ -12070,7 +12070,7 @@ function assistantMessageHasVisibleBlocks({ item, hideThinking, hideToolBlocks }
|
|
|
12070
12070
|
}));
|
|
12071
12071
|
}
|
|
12072
12072
|
function assistantMessageHasFooterMeta(item) {
|
|
12073
|
-
return Boolean(
|
|
12073
|
+
return Boolean(item.model || assistantCopyTextFromItems([item]));
|
|
12074
12074
|
}
|
|
12075
12075
|
var AssistantBlockGroupView = import_react.memo(function AssistantBlockGroupView({ anchorBlockKey, descriptor, store, streaming }) {
|
|
12076
12076
|
if (descriptor.type === "explore") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantExploreBlockGroupView, {
|
|
@@ -12151,7 +12151,7 @@ function AssistantBlockGroupsView({ anchorBlockKey, store, streaming }) {
|
|
|
12151
12151
|
streaming
|
|
12152
12152
|
}, descriptor.key)) });
|
|
12153
12153
|
}
|
|
12154
|
-
function
|
|
12154
|
+
function MessageFooterCopyButton({ className, idleLabel, text }) {
|
|
12155
12155
|
const [copyState, setCopyState] = import_react.useState("idle");
|
|
12156
12156
|
const canCopy = Boolean(text.trim());
|
|
12157
12157
|
const copyMessage = async () => {
|
|
@@ -12165,13 +12165,13 @@ function AssistantMessageFooterCopyButton({ text }) {
|
|
|
12165
12165
|
window.setTimeout(() => setCopyState("idle"), 1400);
|
|
12166
12166
|
}
|
|
12167
12167
|
};
|
|
12168
|
-
const label = copyState === "copied" ? "Copied" : copyState === "error" ? "Retry copy" :
|
|
12168
|
+
const label = copyState === "copied" ? "Copied" : copyState === "error" ? "Retry copy" : idleLabel;
|
|
12169
12169
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
12170
12170
|
title: label,
|
|
12171
12171
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
12172
12172
|
variant: "ghost",
|
|
12173
12173
|
size: "icon-xs",
|
|
12174
|
-
className: "
|
|
12174
|
+
className: cn("text-muted-foreground", className),
|
|
12175
12175
|
disabled: !canCopy,
|
|
12176
12176
|
"aria-label": label,
|
|
12177
12177
|
onClick: copyMessage,
|
|
@@ -12185,13 +12185,17 @@ function AssistantMessageFooter({ copyText, modelLabel, streaming }) {
|
|
|
12185
12185
|
if (!showCopyButton && !modelLabel) return null;
|
|
12186
12186
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
12187
12187
|
className: "-mt-2 flex items-center gap-1.5 text-xs font-medium text-muted-foreground",
|
|
12188
|
-
children: [showCopyButton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
12188
|
+
children: [showCopyButton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessageFooterCopyButton, {
|
|
12189
|
+
className: "-ml-2",
|
|
12190
|
+
idleLabel: "Copy assistant message",
|
|
12191
|
+
text: copyText
|
|
12192
|
+
}) : null, modelLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
12189
12193
|
className: "truncate",
|
|
12190
12194
|
children: modelLabel
|
|
12191
12195
|
}) : null]
|
|
12192
12196
|
});
|
|
12193
12197
|
}
|
|
12194
|
-
function AssistantMessagesStoreCard({ hideFooter = false, store }) {
|
|
12198
|
+
function AssistantMessagesStoreCard({ className, hideFooter = false, store }) {
|
|
12195
12199
|
const initialSnapshot = store.getSnapshot();
|
|
12196
12200
|
const initialBlocks = visibleAssistantBlocksFromSnapshot(initialSnapshot);
|
|
12197
12201
|
const assistantBlockStoreRef = import_react.useRef(null);
|
|
@@ -12215,20 +12219,21 @@ function AssistantMessagesStoreCard({ hideFooter = false, store }) {
|
|
|
12215
12219
|
store
|
|
12216
12220
|
]);
|
|
12217
12221
|
const shellSnapshot = import_react.useSyncExternalStore(shellStore.subscribe, shellStore.getSnapshot, shellStore.getSnapshot);
|
|
12218
|
-
|
|
12222
|
+
const showFooter = Boolean(!hideFooter && !shellSnapshot.working && shellSnapshot.hasFooter);
|
|
12223
|
+
if (!shellSnapshot.hasBlocks && !showFooter) return null;
|
|
12219
12224
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
12220
|
-
className: "flex flex-col gap-4",
|
|
12225
|
+
className: cn("flex flex-col gap-4", className),
|
|
12221
12226
|
"data-conversation-assistant-group": "true",
|
|
12222
12227
|
"data-conversation-streaming": shellSnapshot.streaming ? "true" : void 0,
|
|
12223
12228
|
children: [shellSnapshot.hasBlocks ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantBlockGroupsView, {
|
|
12224
12229
|
anchorBlockKey: shellSnapshot.anchorBlockKey,
|
|
12225
12230
|
store: assistantBlockStore,
|
|
12226
12231
|
streaming: shellSnapshot.streaming
|
|
12227
|
-
}) : null,
|
|
12232
|
+
}) : null, showFooter ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantMessageFooter, {
|
|
12228
12233
|
copyText: shellSnapshot.copyText,
|
|
12229
12234
|
modelLabel: shellSnapshot.modelLabel,
|
|
12230
12235
|
streaming: shellSnapshot.streaming
|
|
12231
|
-
})]
|
|
12236
|
+
}) : null]
|
|
12232
12237
|
});
|
|
12233
12238
|
}
|
|
12234
12239
|
function createSelectionStore(initialValue = 0) {
|
|
@@ -14543,6 +14548,78 @@ function useAppShellMessageScroll({ autoScrollEnabled, isSessionViewLoading, ses
|
|
|
14543
14548
|
syncAfterConversationChange
|
|
14544
14549
|
};
|
|
14545
14550
|
}
|
|
14551
|
+
var DEFAULT_SCROLL_GRADIENT_MAX_HEIGHT = 4;
|
|
14552
|
+
var EMPTY_SCROLL_GRADIENT_STATE = {
|
|
14553
|
+
bottomHeight: 0,
|
|
14554
|
+
topHeight: 0
|
|
14555
|
+
};
|
|
14556
|
+
function scrollDistanceFromBottom(element) {
|
|
14557
|
+
return Math.max(0, element.scrollHeight - element.scrollTop - element.clientHeight);
|
|
14558
|
+
}
|
|
14559
|
+
function scrollGradientHeight(distanceFromEdge, maxHeight) {
|
|
14560
|
+
return Math.min(maxHeight, Math.max(0, distanceFromEdge));
|
|
14561
|
+
}
|
|
14562
|
+
function scrollGradientState(element, maxHeight) {
|
|
14563
|
+
if (!element) return EMPTY_SCROLL_GRADIENT_STATE;
|
|
14564
|
+
return {
|
|
14565
|
+
bottomHeight: scrollGradientHeight(scrollDistanceFromBottom(element), maxHeight),
|
|
14566
|
+
topHeight: scrollGradientHeight(element.scrollTop, maxHeight)
|
|
14567
|
+
};
|
|
14568
|
+
}
|
|
14569
|
+
function setScrollGradientState(setState, nextState) {
|
|
14570
|
+
setState((currentState) => currentState.bottomHeight === nextState.bottomHeight && currentState.topHeight === nextState.topHeight ? currentState : nextState);
|
|
14571
|
+
}
|
|
14572
|
+
function useScrollGradients({ disabled = false, maxHeight = DEFAULT_SCROLL_GRADIENT_MAX_HEIGHT } = {}) {
|
|
14573
|
+
const elementRef = import_react.useRef(null);
|
|
14574
|
+
const [state, setState] = import_react.useState(EMPTY_SCROLL_GRADIENT_STATE);
|
|
14575
|
+
const syncScrollGradients = import_react.useCallback((element = elementRef.current) => {
|
|
14576
|
+
setScrollGradientState(setState, disabled ? EMPTY_SCROLL_GRADIENT_STATE : scrollGradientState(element, maxHeight));
|
|
14577
|
+
}, [disabled, maxHeight]);
|
|
14578
|
+
const setScrollElement = import_react.useCallback((element) => {
|
|
14579
|
+
elementRef.current = element;
|
|
14580
|
+
syncScrollGradients(element);
|
|
14581
|
+
}, [syncScrollGradients]);
|
|
14582
|
+
const onScroll = import_react.useCallback((event) => {
|
|
14583
|
+
syncScrollGradients(event.currentTarget);
|
|
14584
|
+
}, [syncScrollGradients]);
|
|
14585
|
+
import_react.useLayoutEffect(() => {
|
|
14586
|
+
const element = elementRef.current;
|
|
14587
|
+
syncScrollGradients(element);
|
|
14588
|
+
if (!element || typeof ResizeObserver === "undefined") return;
|
|
14589
|
+
let animationFrame = 0;
|
|
14590
|
+
const scheduleSync = () => {
|
|
14591
|
+
window.cancelAnimationFrame(animationFrame);
|
|
14592
|
+
animationFrame = window.requestAnimationFrame(() => {
|
|
14593
|
+
animationFrame = 0;
|
|
14594
|
+
syncScrollGradients(elementRef.current);
|
|
14595
|
+
});
|
|
14596
|
+
};
|
|
14597
|
+
const resizeObserver = new ResizeObserver(scheduleSync);
|
|
14598
|
+
resizeObserver.observe(element);
|
|
14599
|
+
const content = element.firstElementChild;
|
|
14600
|
+
if (content instanceof HTMLElement) resizeObserver.observe(content);
|
|
14601
|
+
return () => {
|
|
14602
|
+
window.cancelAnimationFrame(animationFrame);
|
|
14603
|
+
resizeObserver.disconnect();
|
|
14604
|
+
};
|
|
14605
|
+
}, [syncScrollGradients]);
|
|
14606
|
+
return {
|
|
14607
|
+
bottomHeight: state.bottomHeight,
|
|
14608
|
+
onScroll,
|
|
14609
|
+
setScrollElement,
|
|
14610
|
+
syncScrollGradients,
|
|
14611
|
+
topHeight: state.topHeight
|
|
14612
|
+
};
|
|
14613
|
+
}
|
|
14614
|
+
function ScrollGradientOverlays({ bottomClassName, bottomHeight, className, topClassName, topHeight }) {
|
|
14615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14616
|
+
className: cn("pointer-events-none absolute inset-x-0 top-0 z-10 bg-gradient-to-b from-black/10 to-transparent transition-[height,opacity] duration-150", topHeight > 0 ? "opacity-100" : "opacity-0", className, topClassName),
|
|
14617
|
+
style: { height: topHeight }
|
|
14618
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14619
|
+
className: cn("pointer-events-none absolute inset-x-0 bottom-0 z-10 bg-gradient-to-t from-black/10 to-transparent transition-[height,opacity] duration-150", bottomHeight > 0 ? "opacity-100" : "opacity-0", className, bottomClassName),
|
|
14620
|
+
style: { height: bottomHeight }
|
|
14621
|
+
})] });
|
|
14622
|
+
}
|
|
14546
14623
|
function ConversationLatestMessageButton({ conversationItemsStore, draft, onClick, scrollStateStore }) {
|
|
14547
14624
|
const hasMessages = useConversationHasMessages(conversationItemsStore);
|
|
14548
14625
|
const isDisabled = useMessageScrollValue(scrollStateStore, (snapshot) => draft || !hasMessages || snapshot.isMessagesNearBottom);
|
|
@@ -14609,6 +14686,11 @@ function AppShellConversationFrame({ autoScrollEnabled, children, centerMessages
|
|
|
14609
14686
|
isSessionViewLoading,
|
|
14610
14687
|
sessionState
|
|
14611
14688
|
});
|
|
14689
|
+
const { bottomHeight: conversationScrollBottomGradientHeight, onScroll: onConversationScrollGradientScroll, setScrollElement: setConversationScrollGradientElement, topHeight: conversationScrollTopGradientHeight } = useScrollGradients({ disabled: isSessionViewLoading });
|
|
14690
|
+
const setMessagesScrollAreaElement = import_react.useCallback((element) => {
|
|
14691
|
+
messagesScrollAreaRef.current = element;
|
|
14692
|
+
setConversationScrollGradientElement(element);
|
|
14693
|
+
}, [messagesScrollAreaRef, setConversationScrollGradientElement]);
|
|
14612
14694
|
import_react.useImperativeHandle(ref, () => ({
|
|
14613
14695
|
jumpToNextMessage,
|
|
14614
14696
|
jumpToPreviousMessage,
|
|
@@ -14622,47 +14704,59 @@ function AppShellConversationFrame({ autoScrollEnabled, children, centerMessages
|
|
|
14622
14704
|
]);
|
|
14623
14705
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
14624
14706
|
className: "relative min-h-0 flex-1",
|
|
14625
|
-
children: [
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14707
|
+
children: [
|
|
14708
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14709
|
+
ref: setMessagesScrollAreaElement,
|
|
14710
|
+
"data-conversation-viewport": "true",
|
|
14711
|
+
tabIndex: 0,
|
|
14712
|
+
role: "region",
|
|
14713
|
+
"aria-label": "Conversation messages",
|
|
14714
|
+
className: "h-full overflow-x-hidden overflow-y-auto overscroll-contain px-4 outline-none [overflow-anchor:none]",
|
|
14715
|
+
onScroll: onConversationScrollGradientScroll,
|
|
14716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
14717
|
+
ref: messagesContentRef,
|
|
14718
|
+
className: "flex min-h-full flex-col",
|
|
14719
|
+
children: [
|
|
14720
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationScrollRevisionObserver, {
|
|
14721
|
+
conversationItemsStore,
|
|
14722
|
+
disabled: isSessionViewLoading,
|
|
14723
|
+
onRevisionChange: syncAfterConversationChange
|
|
14724
|
+
}),
|
|
14725
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationContentChangeContext.Provider, {
|
|
14726
|
+
value: syncAfterConversationChange,
|
|
14727
|
+
children
|
|
14728
|
+
}),
|
|
14729
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: bottomRef })
|
|
14730
|
+
]
|
|
14731
|
+
})
|
|
14732
|
+
}),
|
|
14733
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollGradientOverlays, {
|
|
14734
|
+
bottomHeight: conversationScrollBottomGradientHeight,
|
|
14735
|
+
topHeight: conversationScrollTopGradientHeight
|
|
14736
|
+
}),
|
|
14737
|
+
!isSessionViewLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationLatestMessageButton, {
|
|
14738
|
+
conversationItemsStore,
|
|
14739
|
+
draft: sessionState.draft,
|
|
14740
|
+
onClick: scrollConversationToBottom,
|
|
14741
|
+
scrollStateStore
|
|
14742
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConversationPreviousMessageButton, {
|
|
14743
|
+
centerMessages,
|
|
14744
|
+
onClick: jumpToPreviousMessage,
|
|
14745
|
+
scrollStateStore
|
|
14746
|
+
})] }) : null
|
|
14747
|
+
]
|
|
14658
14748
|
});
|
|
14659
14749
|
}
|
|
14660
14750
|
function AppShellWorkingIndicatorLabel({ fallbackLabel, hiddenThinkingPreviewStore, useHiddenThinkingPreview }) {
|
|
14661
14751
|
const hiddenThinkingPreview = useSelector(hiddenThinkingPreviewStore);
|
|
14662
14752
|
const visibleLabel = useHiddenThinkingPreview && hiddenThinkingPreview ? hiddenThinkingPreview : fallbackLabel;
|
|
14663
|
-
if (!visibleLabel.trim()) return
|
|
14753
|
+
if (!visibleLabel.trim()) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14754
|
+
"aria-hidden": "true",
|
|
14755
|
+
className: "invisible leading-5 font-medium",
|
|
14756
|
+
children: "Working…"
|
|
14757
|
+
});
|
|
14664
14758
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14665
|
-
className: "font-medium text-foreground",
|
|
14759
|
+
className: "leading-5 font-medium text-foreground",
|
|
14666
14760
|
children: visibleLabel
|
|
14667
14761
|
});
|
|
14668
14762
|
}
|
|
@@ -14677,7 +14771,7 @@ function AppShellMessagesWorkingIndicator({ hiddenThinkingPreviewStore, onCancel
|
|
|
14677
14771
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
14678
14772
|
className: "min-w-0 flex-1",
|
|
14679
14773
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
14680
|
-
className: "flex min-w-0 items-center justify-start gap-2",
|
|
14774
|
+
className: "flex min-h-5 min-w-0 items-center justify-start gap-2",
|
|
14681
14775
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14682
14776
|
className: "min-w-0 shrink-0",
|
|
14683
14777
|
children: state.done ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -14764,12 +14858,10 @@ function ConversationAssistantGroupView({ className, groupKey, hideFooter, hideT
|
|
|
14764
14858
|
store,
|
|
14765
14859
|
syncAfterConversationContentChange
|
|
14766
14860
|
]);
|
|
14767
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
14861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AssistantMessagesStoreCard, {
|
|
14768
14862
|
className,
|
|
14769
|
-
|
|
14770
|
-
|
|
14771
|
-
store: assistantMessagesStore
|
|
14772
|
-
})
|
|
14863
|
+
hideFooter,
|
|
14864
|
+
store: assistantMessagesStore
|
|
14773
14865
|
});
|
|
14774
14866
|
}
|
|
14775
14867
|
function AppShellConversationItemGroups({ centerMessages, conversationItemsStore, hideFooter, hideThinking, hideToolBlocks }) {
|
|
@@ -14839,14 +14931,13 @@ function AppShellConversationWorkingFooter({ centerMessages, conversationItemsSt
|
|
|
14839
14931
|
}
|
|
14840
14932
|
function AppShellConversationMessageStack({ centerMessages, conversationItemsStore, hideToolBlocks, sessionStore }) {
|
|
14841
14933
|
const hideThinking = useSelector(sessionStore, (sessionState) => sessionState.hideThinkingBlock);
|
|
14842
|
-
const streaming = useSelector(sessionStore, (sessionState) => sessionState.streaming);
|
|
14843
14934
|
if (!useConversationHasMessages(conversationItemsStore)) return null;
|
|
14844
14935
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
14845
14936
|
className: "flex flex-col gap-4 pt-4",
|
|
14846
14937
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellConversationItemGroups, {
|
|
14847
14938
|
centerMessages,
|
|
14848
14939
|
conversationItemsStore,
|
|
14849
|
-
hideFooter:
|
|
14940
|
+
hideFooter: false,
|
|
14850
14941
|
hideThinking,
|
|
14851
14942
|
hideToolBlocks
|
|
14852
14943
|
})
|
|
@@ -16711,6 +16802,7 @@ function GitRepositorySummary({ viewerContextId, cwd, active, onBranchClick }) {
|
|
|
16711
16802
|
}
|
|
16712
16803
|
function GitPanelToolbar({ viewerContextId, cwd, active }) {
|
|
16713
16804
|
const queryClient = useQueryClient();
|
|
16805
|
+
const isMobile = useIsMobile();
|
|
16714
16806
|
const normalizedCwd = normalizeCwd(cwd);
|
|
16715
16807
|
const [branchDialogOpen, setBranchDialogOpen] = import_react.useState(false);
|
|
16716
16808
|
const [commitDialogOpen, setCommitDialogOpen] = import_react.useState(false);
|
|
@@ -16824,6 +16916,7 @@ function GitPanelToolbar({ viewerContextId, cwd, active }) {
|
|
|
16824
16916
|
kbd: formatShortcutLabel("Control+C"),
|
|
16825
16917
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
16826
16918
|
variant: "outline",
|
|
16919
|
+
size: isMobile ? "default" : "sm",
|
|
16827
16920
|
onClick: () => {
|
|
16828
16921
|
setCommitDialogOpen(true);
|
|
16829
16922
|
},
|
|
@@ -16835,6 +16928,7 @@ function GitPanelToolbar({ viewerContextId, cwd, active }) {
|
|
|
16835
16928
|
kbd: formatShortcutLabel("Control+P"),
|
|
16836
16929
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
16837
16930
|
variant: "outline",
|
|
16931
|
+
size: isMobile ? "default" : "sm",
|
|
16838
16932
|
disabled: gitActionBusy,
|
|
16839
16933
|
onClick: () => {
|
|
16840
16934
|
gitActionMutation.mutate("push");
|
|
@@ -16847,6 +16941,7 @@ function GitPanelToolbar({ viewerContextId, cwd, active }) {
|
|
|
16847
16941
|
kbd: formatShortcutLabel("Control+Shift+P"),
|
|
16848
16942
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
16849
16943
|
variant: "outline",
|
|
16944
|
+
size: isMobile ? "default" : "sm",
|
|
16850
16945
|
disabled: gitActionBusy,
|
|
16851
16946
|
onClick: () => {
|
|
16852
16947
|
gitActionMutation.mutate("force-push");
|
|
@@ -16859,6 +16954,7 @@ function GitPanelToolbar({ viewerContextId, cwd, active }) {
|
|
|
16859
16954
|
kbd: formatShortcutLabel("Alt+P"),
|
|
16860
16955
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
16861
16956
|
variant: "outline",
|
|
16957
|
+
size: isMobile ? "default" : "sm",
|
|
16862
16958
|
disabled: gitActionBusy,
|
|
16863
16959
|
onClick: () => {
|
|
16864
16960
|
gitActionMutation.mutate("pull");
|
|
@@ -16967,26 +17063,6 @@ function AlertDialogCancel({ className, variant = "outline", size = "default", .
|
|
|
16967
17063
|
...props
|
|
16968
17064
|
});
|
|
16969
17065
|
}
|
|
16970
|
-
function setDerivedScrollState(setState, nextState) {
|
|
16971
|
-
setState((current) => Object.is(current, nextState) ? current : nextState);
|
|
16972
|
-
}
|
|
16973
|
-
function hasScrolledContent(scrollElement) {
|
|
16974
|
-
return Boolean(scrollElement && scrollElement.scrollTop > 0);
|
|
16975
|
-
}
|
|
16976
|
-
function hasRemainingScrollContent(scrollElement) {
|
|
16977
|
-
if (!scrollElement) return false;
|
|
16978
|
-
return scrollElement.scrollHeight - scrollElement.clientHeight - scrollElement.scrollTop > 1;
|
|
16979
|
-
}
|
|
16980
|
-
function getStuckScrollTriggerValue({ getValue, scrollElement, selector }) {
|
|
16981
|
-
if (!scrollElement || scrollElement.scrollTop <= 0) return "";
|
|
16982
|
-
const containerTop = scrollElement.getBoundingClientRect().top;
|
|
16983
|
-
const triggers = Array.from(scrollElement.querySelectorAll(selector));
|
|
16984
|
-
for (const trigger of triggers) {
|
|
16985
|
-
const rect = trigger.getBoundingClientRect();
|
|
16986
|
-
if (rect.top <= containerTop + 1 && rect.bottom > containerTop + 1) return getValue(trigger);
|
|
16987
|
-
}
|
|
16988
|
-
return "";
|
|
16989
|
-
}
|
|
16990
17066
|
function GitSection({ title, meta, controls, className, bodyClassName, children }) {
|
|
16991
17067
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
16992
17068
|
className: cn("overflow-hidden rounded-xl border border-border/80 bg-card/50", className),
|
|
@@ -17030,10 +17106,7 @@ var initialGitCommitRowState = {
|
|
|
17030
17106
|
formDialog: null,
|
|
17031
17107
|
confirmDialog: null,
|
|
17032
17108
|
contextMenuOpen: false,
|
|
17033
|
-
contextMenuKey: 0
|
|
17034
|
-
scrollValue: "",
|
|
17035
|
-
commitBodyHeaderShadowed: false,
|
|
17036
|
-
commitBodyFooterShadowed: false
|
|
17109
|
+
contextMenuKey: 0
|
|
17037
17110
|
};
|
|
17038
17111
|
function gitCommitRowReducer(state, action) {
|
|
17039
17112
|
switch (action.type) {
|
|
@@ -17081,18 +17154,10 @@ function gitCommitRowReducer(state, action) {
|
|
|
17081
17154
|
contextMenuOpen: false,
|
|
17082
17155
|
contextMenuKey: state.contextMenuKey + 1
|
|
17083
17156
|
};
|
|
17084
|
-
case "set-scroll-shadows":
|
|
17085
|
-
if (state.scrollValue === action.value && state.commitBodyHeaderShadowed === action.headerShadowed && state.commitBodyFooterShadowed === action.footerShadowed) return state;
|
|
17086
|
-
return {
|
|
17087
|
-
...state,
|
|
17088
|
-
scrollValue: action.value,
|
|
17089
|
-
commitBodyHeaderShadowed: action.headerShadowed,
|
|
17090
|
-
commitBodyFooterShadowed: action.footerShadowed
|
|
17091
|
-
};
|
|
17092
17157
|
}
|
|
17093
17158
|
}
|
|
17094
17159
|
function gitGraphLaneColor(index, active = false) {
|
|
17095
|
-
if (active) return "
|
|
17160
|
+
if (active) return "var(--warning)";
|
|
17096
17161
|
return GIT_GRAPH_LANE_COLORS[index % GIT_GRAPH_LANE_COLORS.length];
|
|
17097
17162
|
}
|
|
17098
17163
|
var GitCommitGraphBranch = class {
|
|
@@ -17717,8 +17782,8 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
17717
17782
|
const [rowState, dispatchRow] = import_react.useReducer(gitCommitRowReducer, initialGitCommitRowState);
|
|
17718
17783
|
const hashCopiedResetRef = import_react.useRef(void 0);
|
|
17719
17784
|
const messageCopiedResetRef = import_react.useRef(void 0);
|
|
17720
|
-
const commitBodyScrollRef = import_react.useRef(null);
|
|
17721
17785
|
const contextMenuActionsRef = import_react.useRef(null);
|
|
17786
|
+
const { bottomHeight: commitBodyBottomGradientHeight, onScroll: onCommitBodyGradientScroll, setScrollElement: setCommitBodyGradientElement, topHeight: commitBodyTopGradientHeight } = useScrollGradients();
|
|
17722
17787
|
const title = parsed.subject.trim();
|
|
17723
17788
|
const time = formatGitCommitDetailTime(parsed.relativeDate);
|
|
17724
17789
|
const fullTime = formatGitCommitFullDate(parsed.fullDate);
|
|
@@ -17727,19 +17792,6 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
17727
17792
|
const shortHash = parsed.hash || parsed.fullHash.slice(0, 7);
|
|
17728
17793
|
const canRunCommitAction = Boolean(viewerContextId && cwd && parsed.fullHash);
|
|
17729
17794
|
const { hashCopied, messageCopied, formDialog, confirmDialog, contextMenuOpen, contextMenuKey } = rowState;
|
|
17730
|
-
const commitBodyHeaderShadowed = rowState.scrollValue === value && rowState.commitBodyHeaderShadowed;
|
|
17731
|
-
const commitBodyFooterShadowed = rowState.scrollValue === value && rowState.commitBodyFooterShadowed;
|
|
17732
|
-
const updateCommitBodyScrollShadows = (scrollElement) => {
|
|
17733
|
-
dispatchRow({
|
|
17734
|
-
type: "set-scroll-shadows",
|
|
17735
|
-
value,
|
|
17736
|
-
headerShadowed: hasScrolledContent(scrollElement),
|
|
17737
|
-
footerShadowed: hasRemainingScrollContent(scrollElement)
|
|
17738
|
-
});
|
|
17739
|
-
};
|
|
17740
|
-
import_react.useLayoutEffect(() => {
|
|
17741
|
-
updateCommitBodyScrollShadows(commitBodyScrollRef.current);
|
|
17742
|
-
});
|
|
17743
17795
|
import_react.useEffect(() => {
|
|
17744
17796
|
return () => {
|
|
17745
17797
|
if (typeof hashCopiedResetRef.current === "number") window.clearTimeout(hashCopiedResetRef.current);
|
|
@@ -17906,7 +17958,7 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
17906
17958
|
});
|
|
17907
17959
|
};
|
|
17908
17960
|
if (!parsed.hash && !parsed.subject) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
17909
|
-
className: "flex h-8 max-w-full min-w-0 items-center
|
|
17961
|
+
className: "flex h-8 max-w-full min-w-0 items-center text-[13px] leading-5",
|
|
17910
17962
|
children: parsed.subject ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
17911
17963
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
17912
17964
|
children: parsed.subject
|
|
@@ -17914,7 +17966,7 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
17914
17966
|
});
|
|
17915
17967
|
const trigger = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionTrigger, {
|
|
17916
17968
|
headerClassName: "min-w-0",
|
|
17917
|
-
className: cn("h-8 min-h-8 w-full items-center gap-2 rounded-none px-1.5 py-0
|
|
17969
|
+
className: cn("h-8 min-h-8 w-full items-center gap-2 rounded-none px-1.5 py-0 text-[13px] leading-5 font-normal transition-[background-color,box-shadow,color] hover:no-underline focus-visible:ring-0 aria-expanded:bg-muted/50 **:data-[slot=accordion-trigger-icon]:size-4"),
|
|
17918
17970
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
17919
17971
|
className: "min-w-0 flex-1 truncate pr-8 text-foreground",
|
|
17920
17972
|
style: { paddingLeft: graphWidth },
|
|
@@ -18056,122 +18108,119 @@ function useGitCommitRowView({ viewerContextId, cwd, graphWidth, line, value, on
|
|
|
18056
18108
|
}),
|
|
18057
18109
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionContent, {
|
|
18058
18110
|
className: "relative h-[200px] border-b border-border/70 bg-muted/50 p-0",
|
|
18059
|
-
children: [
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
|
|
18063
|
-
|
|
18064
|
-
|
|
18065
|
-
},
|
|
18066
|
-
children:
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18111
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
18112
|
+
ref: setCommitBodyGradientElement,
|
|
18113
|
+
className: "h-full overflow-y-auto pr-2 pb-2",
|
|
18114
|
+
onScroll: onCommitBodyGradientScroll,
|
|
18115
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18116
|
+
className: "grid content-start gap-1.5 pt-1 text-xs leading-4",
|
|
18117
|
+
style: { paddingLeft: graphWidth },
|
|
18118
|
+
children: [
|
|
18119
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18120
|
+
className: "flex min-w-0 flex-wrap items-center gap-1.5 font-sans",
|
|
18121
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
18122
|
+
type: "button",
|
|
18123
|
+
size: "xs",
|
|
18124
|
+
variant: "outline",
|
|
18125
|
+
disabled: !canRunCommitAction,
|
|
18126
|
+
onClick: () => openDiff("commit"),
|
|
18127
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileDiff, {}), "View diff"]
|
|
18128
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitCommitActionsMenu, { ...commitActionProps })]
|
|
18129
|
+
}),
|
|
18130
|
+
parsed.author || time || parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18131
|
+
className: "flex max-w-full flex-wrap items-center gap-x-2 gap-y-1 text-muted-foreground",
|
|
18132
|
+
children: [
|
|
18133
|
+
parsed.author ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: parsed.author }) : null,
|
|
18134
|
+
parsed.author && time ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18135
|
+
"aria-hidden": true,
|
|
18136
|
+
children: "·"
|
|
18137
|
+
}) : null,
|
|
18138
|
+
time ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
18139
|
+
title: fullTime,
|
|
18140
|
+
side: "top",
|
|
18141
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: time })
|
|
18142
|
+
}) : null,
|
|
18143
|
+
(parsed.author || time) && parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18144
|
+
"aria-hidden": true,
|
|
18145
|
+
children: "·"
|
|
18146
|
+
}) : null,
|
|
18147
|
+
parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18148
|
+
className: "inline-flex min-w-0 items-center gap-1.5",
|
|
18149
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18150
|
+
className: "min-w-0 truncate",
|
|
18151
|
+
children: shortHash
|
|
18152
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
18153
|
+
title: hashCopied ? "Copied" : "Copy full commit hash",
|
|
18154
|
+
side: "top",
|
|
18155
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
18156
|
+
type: "button",
|
|
18157
|
+
"aria-label": "Copy full commit hash",
|
|
18158
|
+
className: "inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
18159
|
+
onClick: (event) => {
|
|
18160
|
+
event.preventDefault();
|
|
18161
|
+
event.stopPropagation();
|
|
18162
|
+
copyFullHashInline();
|
|
18163
|
+
},
|
|
18164
|
+
children: hashCopied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-3.5" })
|
|
18165
|
+
})
|
|
18166
|
+
})]
|
|
18167
|
+
}) : null
|
|
18168
|
+
]
|
|
18169
|
+
}) : null,
|
|
18170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18171
|
+
className: "max-w-full break-words whitespace-normal text-foreground",
|
|
18172
|
+
children: [title || "No commit message", title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
18173
|
+
title: messageCopied ? "Copied" : "Copy commit message",
|
|
18174
|
+
side: "top",
|
|
18175
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
18073
18176
|
type: "button",
|
|
18074
|
-
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18177
|
+
"aria-label": "Copy commit message",
|
|
18178
|
+
className: "ml-1 inline-flex size-4 items-center justify-center rounded-sm align-middle text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
18179
|
+
onClick: (event) => {
|
|
18180
|
+
event.preventDefault();
|
|
18181
|
+
event.stopPropagation();
|
|
18182
|
+
copyCommitMessageInline();
|
|
18183
|
+
},
|
|
18184
|
+
children: messageCopied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-3.5" })
|
|
18185
|
+
})
|
|
18186
|
+
}) : null]
|
|
18187
|
+
}),
|
|
18188
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18189
|
+
className: "flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1",
|
|
18190
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18191
|
+
className: "text-emerald-500",
|
|
18083
18192
|
children: [
|
|
18084
|
-
|
|
18085
|
-
|
|
18086
|
-
|
|
18087
|
-
|
|
18088
|
-
}) : null,
|
|
18089
|
-
time ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
18090
|
-
title: fullTime,
|
|
18091
|
-
side: "top",
|
|
18092
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: time })
|
|
18093
|
-
}) : null,
|
|
18094
|
-
(parsed.author || time) && parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18095
|
-
"aria-hidden": true,
|
|
18096
|
-
children: "·"
|
|
18097
|
-
}) : null,
|
|
18098
|
-
parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18099
|
-
className: "inline-flex min-w-0 items-center gap-1.5",
|
|
18100
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
18101
|
-
className: "min-w-0 truncate",
|
|
18102
|
-
children: shortHash
|
|
18103
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
18104
|
-
title: hashCopied ? "Copied" : "Copy full commit hash",
|
|
18105
|
-
side: "top",
|
|
18106
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
18107
|
-
type: "button",
|
|
18108
|
-
"aria-label": "Copy full commit hash",
|
|
18109
|
-
className: "inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
18110
|
-
onClick: (event) => {
|
|
18111
|
-
event.preventDefault();
|
|
18112
|
-
event.stopPropagation();
|
|
18113
|
-
copyFullHashInline();
|
|
18114
|
-
},
|
|
18115
|
-
children: hashCopied ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Copy, { className: "size-3.5" })
|
|
18116
|
-
})
|
|
18117
|
-
})]
|
|
18118
|
-
}) : null
|
|
18193
|
+
"+",
|
|
18194
|
+
insertions,
|
|
18195
|
+
" addition",
|
|
18196
|
+
insertions === 1 ? "" : "s"
|
|
18119
18197
|
]
|
|
18120
|
-
})
|
|
18121
|
-
|
|
18122
|
-
|
|
18123
|
-
|
|
18124
|
-
|
|
18125
|
-
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
|
|
18133
|
-
|
|
18134
|
-
|
|
18135
|
-
|
|
18136
|
-
|
|
18137
|
-
|
|
18138
|
-
|
|
18139
|
-
|
|
18140
|
-
|
|
18141
|
-
|
|
18142
|
-
|
|
18143
|
-
|
|
18144
|
-
|
|
18145
|
-
|
|
18146
|
-
" addition",
|
|
18147
|
-
insertions === 1 ? "" : "s"
|
|
18148
|
-
]
|
|
18149
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18150
|
-
className: "text-red-400",
|
|
18151
|
-
children: [
|
|
18152
|
-
"-",
|
|
18153
|
-
deletions,
|
|
18154
|
-
" deletion",
|
|
18155
|
-
deletions === 1 ? "" : "s"
|
|
18156
|
-
]
|
|
18157
|
-
})]
|
|
18158
|
-
}),
|
|
18159
|
-
parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitCommitFilesList, {
|
|
18160
|
-
viewerContextId,
|
|
18161
|
-
cwd,
|
|
18162
|
-
commit: parsed.fullHash,
|
|
18163
|
-
shortHash,
|
|
18164
|
-
previousShortHash: parsed.parents[0]?.slice(0, 7) || "",
|
|
18165
|
-
subject: title,
|
|
18166
|
-
disabled: !canRunCommitAction,
|
|
18167
|
-
onOpenCommitDiff
|
|
18168
|
-
}) : null
|
|
18169
|
-
]
|
|
18170
|
-
})
|
|
18171
|
-
}),
|
|
18172
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("pointer-events-none absolute inset-x-0 top-0 h-1 bg-gradient-to-b from-black/10 to-transparent transition-opacity duration-150", commitBodyHeaderShadowed ? "opacity-100" : "opacity-0") }),
|
|
18173
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("pointer-events-none absolute inset-x-0 bottom-0 h-1 bg-gradient-to-t from-black/10 to-transparent transition-opacity duration-150", commitBodyFooterShadowed ? "opacity-100" : "opacity-0") })
|
|
18174
|
-
]
|
|
18198
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
18199
|
+
className: "text-red-400",
|
|
18200
|
+
children: [
|
|
18201
|
+
"-",
|
|
18202
|
+
deletions,
|
|
18203
|
+
" deletion",
|
|
18204
|
+
deletions === 1 ? "" : "s"
|
|
18205
|
+
]
|
|
18206
|
+
})]
|
|
18207
|
+
}),
|
|
18208
|
+
parsed.fullHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitCommitFilesList, {
|
|
18209
|
+
viewerContextId,
|
|
18210
|
+
cwd,
|
|
18211
|
+
commit: parsed.fullHash,
|
|
18212
|
+
shortHash,
|
|
18213
|
+
previousShortHash: parsed.parents[0]?.slice(0, 7) || "",
|
|
18214
|
+
subject: title,
|
|
18215
|
+
disabled: !canRunCommitAction,
|
|
18216
|
+
onOpenCommitDiff
|
|
18217
|
+
}) : null
|
|
18218
|
+
]
|
|
18219
|
+
})
|
|
18220
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollGradientOverlays, {
|
|
18221
|
+
bottomHeight: commitBodyBottomGradientHeight,
|
|
18222
|
+
topHeight: commitBodyTopGradientHeight
|
|
18223
|
+
})]
|
|
18175
18224
|
}),
|
|
18176
18225
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog$1, {
|
|
18177
18226
|
open: formDialog !== null,
|
|
@@ -18422,6 +18471,22 @@ function GitCommitsSection({ viewerContextId, cwd, active, onOpenCommitDiff, onR
|
|
|
18422
18471
|
children: content
|
|
18423
18472
|
});
|
|
18424
18473
|
}
|
|
18474
|
+
function setDerivedScrollState(setState, nextState) {
|
|
18475
|
+
setState((current) => Object.is(current, nextState) ? current : nextState);
|
|
18476
|
+
}
|
|
18477
|
+
function hasScrolledContent(scrollElement) {
|
|
18478
|
+
return Boolean(scrollElement && scrollElement.scrollTop > 0);
|
|
18479
|
+
}
|
|
18480
|
+
function getStuckScrollTriggerValue({ getValue, scrollElement, selector }) {
|
|
18481
|
+
if (!scrollElement || scrollElement.scrollTop <= 0) return "";
|
|
18482
|
+
const containerTop = scrollElement.getBoundingClientRect().top;
|
|
18483
|
+
const triggers = Array.from(scrollElement.querySelectorAll(selector));
|
|
18484
|
+
for (const trigger of triggers) {
|
|
18485
|
+
const rect = trigger.getBoundingClientRect();
|
|
18486
|
+
if (rect.top <= containerTop + 1 && rect.bottom > containerTop + 1) return getValue(trigger);
|
|
18487
|
+
}
|
|
18488
|
+
return "";
|
|
18489
|
+
}
|
|
18425
18490
|
function GitFileStatus({ status }) {
|
|
18426
18491
|
const [indexCharacter, worktreeCharacter] = gitFileStatusCharacters(status);
|
|
18427
18492
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
@@ -18461,6 +18526,30 @@ function GitFileDiff({ file }) {
|
|
|
18461
18526
|
}) : null]
|
|
18462
18527
|
});
|
|
18463
18528
|
}
|
|
18529
|
+
function gitFileCanStage(file) {
|
|
18530
|
+
const [indexStatus, worktreeStatus] = gitFileStatusCharacters(file.status);
|
|
18531
|
+
return worktreeStatus !== " " || indexStatus === "?";
|
|
18532
|
+
}
|
|
18533
|
+
function gitFileCanUnstage(file) {
|
|
18534
|
+
const [indexStatus] = gitFileStatusCharacters(file.status);
|
|
18535
|
+
return indexStatus !== " " && indexStatus !== "?";
|
|
18536
|
+
}
|
|
18537
|
+
function reviewBulkGitActionSuccessLabel(action) {
|
|
18538
|
+
switch (action) {
|
|
18539
|
+
case "discard-all": return "Discarded all changes";
|
|
18540
|
+
case "nuke-working-tree": return "Nuked working tree";
|
|
18541
|
+
case "unstage-all": return "Unstaged all changes";
|
|
18542
|
+
case "stage-all": return "Staged all changes";
|
|
18543
|
+
}
|
|
18544
|
+
}
|
|
18545
|
+
function reviewBulkGitActionErrorFallback(action) {
|
|
18546
|
+
switch (action) {
|
|
18547
|
+
case "discard-all": return "Failed to discard changes";
|
|
18548
|
+
case "nuke-working-tree": return "Failed to nuke working tree";
|
|
18549
|
+
case "unstage-all": return "Failed to unstage changes";
|
|
18550
|
+
case "stage-all": return "Failed to stage changes";
|
|
18551
|
+
}
|
|
18552
|
+
}
|
|
18464
18553
|
function reviewDiffCommentSideLabel(side) {
|
|
18465
18554
|
return side === "deletions" ? "old" : "new";
|
|
18466
18555
|
}
|
|
@@ -18501,7 +18590,7 @@ function ReviewDiffPendingLineComment({ comment }) {
|
|
|
18501
18590
|
comment.onSubmit(normalizedText);
|
|
18502
18591
|
};
|
|
18503
18592
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", {
|
|
18504
|
-
className: "m-2 w-[
|
|
18593
|
+
className: "m-2 w-[calc(100%_-_1rem)] max-w-[38rem] rounded-lg border border-border/70 bg-background p-2 shadow-sm",
|
|
18505
18594
|
onPointerDown: (event) => event.stopPropagation(),
|
|
18506
18595
|
onSubmit: (event) => {
|
|
18507
18596
|
event.preventDefault();
|
|
@@ -18680,6 +18769,7 @@ function FileReviewContent(props) {
|
|
|
18680
18769
|
}
|
|
18681
18770
|
function useFileReviewContentView({ viewerContextId, cwd, active, diffLineComments = [], onAddDiffLineComment, onMaximizeHistory, onOpenCommitDiff, onOpenFile, showEmbeddedHistory = true }) {
|
|
18682
18771
|
const normalizedCwd = normalizeCwd(cwd);
|
|
18772
|
+
const queryClient = useQueryClient();
|
|
18683
18773
|
const isMobile = useIsMobile();
|
|
18684
18774
|
const [state, dispatch] = import_react.useReducer(fileReviewReducer, initialFileReviewState, (initialState) => ({
|
|
18685
18775
|
...initialState,
|
|
@@ -18700,6 +18790,11 @@ function useFileReviewContentView({ viewerContextId, cwd, active, diffLineCommen
|
|
|
18700
18790
|
});
|
|
18701
18791
|
};
|
|
18702
18792
|
const changesScrollRef = import_react.useRef(null);
|
|
18793
|
+
const { bottomHeight: changesScrollBottomGradientHeight, onScroll: onChangesScrollGradientScroll, setScrollElement: setChangesScrollGradientElement, topHeight: changesScrollTopGradientHeight } = useScrollGradients();
|
|
18794
|
+
const setChangesScrollElement = import_react.useCallback((element) => {
|
|
18795
|
+
changesScrollRef.current = element;
|
|
18796
|
+
setChangesScrollGradientElement(element);
|
|
18797
|
+
}, [setChangesScrollGradientElement]);
|
|
18703
18798
|
const reviewContentRef = import_react.useRef(null);
|
|
18704
18799
|
const historyPanelRef = import_react.useRef(null);
|
|
18705
18800
|
const historyScrollRef = import_react.useRef(null);
|
|
@@ -18720,14 +18815,41 @@ function useFileReviewContentView({ viewerContextId, cwd, active, diffLineCommen
|
|
|
18720
18815
|
});
|
|
18721
18816
|
const files = filesQuery.data;
|
|
18722
18817
|
const changedFiles = Array.isArray(files) ? files : [];
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
|
|
18728
|
-
|
|
18729
|
-
|
|
18730
|
-
|
|
18818
|
+
const canStageAll = changedFiles.some(gitFileCanStage);
|
|
18819
|
+
const canUnstageAll = changedFiles.some(gitFileCanUnstage);
|
|
18820
|
+
const canDiscardAll = changedFiles.length > 0;
|
|
18821
|
+
const [confirmNukeWorkingTreeOpen, setConfirmNukeWorkingTreeOpen] = import_react.useState(false);
|
|
18822
|
+
const bulkGitActionMutation = useMutation({
|
|
18823
|
+
mutationFn: async (action) => {
|
|
18824
|
+
return await fetchJson(buildRequestUrl(action === "discard-all" || action === "nuke-working-tree" ? "/api/git-discard" : "/api/git-stage", { contextId: viewerContextId }), {
|
|
18825
|
+
method: "POST",
|
|
18826
|
+
headers: { "content-type": "application/json" },
|
|
18827
|
+
body: JSON.stringify({
|
|
18828
|
+
action,
|
|
18829
|
+
cwd: normalizedCwd
|
|
18830
|
+
})
|
|
18831
|
+
});
|
|
18832
|
+
},
|
|
18833
|
+
onSuccess: async (_response, action) => {
|
|
18834
|
+
await invalidateGitQueries({
|
|
18835
|
+
queryClient,
|
|
18836
|
+
viewerContextId,
|
|
18837
|
+
cwd: normalizedCwd
|
|
18838
|
+
});
|
|
18839
|
+
toast.success(reviewBulkGitActionSuccessLabel(action));
|
|
18840
|
+
},
|
|
18841
|
+
onError: (error, action) => {
|
|
18842
|
+
toast.error(getErrorMessage(error, reviewBulkGitActionErrorFallback(action)));
|
|
18843
|
+
}
|
|
18844
|
+
});
|
|
18845
|
+
import_react.useEffect(() => {
|
|
18846
|
+
if (previousNormalizedCwdRef.current === normalizedCwd) return;
|
|
18847
|
+
previousNormalizedCwdRef.current = normalizedCwd;
|
|
18848
|
+
dispatch({
|
|
18849
|
+
type: "cwdChanged",
|
|
18850
|
+
historyPanelHeight: readStoredGitHistoryPanelHeight()
|
|
18851
|
+
});
|
|
18852
|
+
}, [normalizedCwd]);
|
|
18731
18853
|
const updateStickyReviewFileHeader = (scrollElement) => {
|
|
18732
18854
|
setDerivedScrollState(setStickyReviewFileValue, getStuckScrollTriggerValue({
|
|
18733
18855
|
getValue: (trigger) => trigger.dataset.reviewFileValue || "",
|
|
@@ -18822,12 +18944,28 @@ function useFileReviewContentView({ viewerContextId, cwd, active, diffLineCommen
|
|
|
18822
18944
|
normalizedCwd
|
|
18823
18945
|
]);
|
|
18824
18946
|
const hasOpenFile = openFiles.length > 0;
|
|
18947
|
+
const bulkActionPending = bulkGitActionMutation.isPending;
|
|
18948
|
+
const bulkActionDisabled = bulkActionPending || !viewerContextId || !normalizedCwd || typeof files === "undefined" || files === null || Boolean(filesQuery.error);
|
|
18949
|
+
const discardAllPending = bulkGitActionMutation.isPending && bulkGitActionMutation.variables === "discard-all";
|
|
18950
|
+
const nukeWorkingTreePending = bulkGitActionMutation.isPending && bulkGitActionMutation.variables === "nuke-working-tree";
|
|
18951
|
+
const stageAllPending = bulkGitActionMutation.isPending && bulkGitActionMutation.variables === "stage-all";
|
|
18952
|
+
const unstageAllPending = bulkGitActionMutation.isPending && bulkGitActionMutation.variables === "unstage-all";
|
|
18825
18953
|
const toggleAll = () => {
|
|
18826
18954
|
dispatch({
|
|
18827
18955
|
type: "openFilesChanged",
|
|
18828
18956
|
openFiles: hasOpenFile ? [] : changedFiles.map(reviewFileValue)
|
|
18829
18957
|
});
|
|
18830
18958
|
};
|
|
18959
|
+
const runBulkGitAction = (action) => {
|
|
18960
|
+
bulkGitActionMutation.mutate(action);
|
|
18961
|
+
};
|
|
18962
|
+
const requestNukeWorkingTree = () => {
|
|
18963
|
+
setConfirmNukeWorkingTreeOpen(true);
|
|
18964
|
+
};
|
|
18965
|
+
const runConfirmedNukeWorkingTree = () => {
|
|
18966
|
+
bulkGitActionMutation.mutate("nuke-working-tree");
|
|
18967
|
+
setConfirmNukeWorkingTreeOpen(false);
|
|
18968
|
+
};
|
|
18831
18969
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18832
18970
|
ref: reviewContentRef,
|
|
18833
18971
|
className: "flex h-full min-h-0 flex-col bg-background",
|
|
@@ -18850,82 +18988,130 @@ function useFileReviewContentView({ viewerContextId, cwd, active, diffLineCommen
|
|
|
18850
18988
|
children: "Diffs"
|
|
18851
18989
|
})
|
|
18852
18990
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18853
|
-
className: "flex shrink-0 items-center gap-2",
|
|
18854
|
-
children: [
|
|
18855
|
-
|
|
18856
|
-
|
|
18991
|
+
className: "flex shrink-0 flex-wrap items-center justify-end gap-2",
|
|
18992
|
+
children: [
|
|
18993
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenu, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuTrigger, {
|
|
18994
|
+
render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
18995
|
+
variant: "outline",
|
|
18996
|
+
size: isMobile ? "icon" : "icon-sm",
|
|
18997
|
+
"aria-label": "Diff actions",
|
|
18998
|
+
disabled: bulkActionDisabled
|
|
18999
|
+
}),
|
|
19000
|
+
children: bulkActionPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, { className: "size-4" })
|
|
19001
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuContent, {
|
|
19002
|
+
align: "end",
|
|
19003
|
+
className: "w-52",
|
|
19004
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuGroup, { children: [
|
|
19005
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
19006
|
+
disabled: bulkActionDisabled || !canStageAll,
|
|
19007
|
+
onClick: () => runBulkGitAction("stage-all"),
|
|
19008
|
+
children: [stageAllPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, {}), "Stage all"]
|
|
19009
|
+
}),
|
|
19010
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
19011
|
+
disabled: bulkActionDisabled || !canUnstageAll,
|
|
19012
|
+
onClick: () => runBulkGitAction("unstage-all"),
|
|
19013
|
+
children: [unstageAllPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minus, {}), "Unstage all"]
|
|
19014
|
+
}),
|
|
19015
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
19016
|
+
variant: "destructive",
|
|
19017
|
+
disabled: bulkActionDisabled || !canDiscardAll,
|
|
19018
|
+
onClick: () => runBulkGitAction("discard-all"),
|
|
19019
|
+
children: [discardAllPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Undo2, {}), "Discard all"]
|
|
19020
|
+
}),
|
|
19021
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DropdownMenuSeparator, {}),
|
|
19022
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuItem, {
|
|
19023
|
+
variant: "destructive",
|
|
19024
|
+
disabled: bulkActionDisabled,
|
|
19025
|
+
onClick: requestNukeWorkingTree,
|
|
19026
|
+
children: [nukeWorkingTreePending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Trash2, {}), "Nuke working tree"]
|
|
19027
|
+
})
|
|
19028
|
+
] })
|
|
19029
|
+
})] }),
|
|
19030
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
19031
|
+
title: hasOpenFile ? "Collapse all" : "Expand all",
|
|
19032
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
19033
|
+
variant: "outline",
|
|
19034
|
+
size: isMobile ? "icon" : "icon-sm",
|
|
19035
|
+
"aria-label": hasOpenFile ? "Collapse all" : "Expand all",
|
|
19036
|
+
disabled: changedFiles.length === 0,
|
|
19037
|
+
onClick: toggleAll,
|
|
19038
|
+
children: hasOpenFile ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronsDownUp, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronsUpDown, { className: "size-4" })
|
|
19039
|
+
})
|
|
19040
|
+
}),
|
|
19041
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroup$1, {
|
|
18857
19042
|
variant: "outline",
|
|
18858
|
-
size: "
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
18862
|
-
|
|
19043
|
+
size: isMobile ? "default" : "sm",
|
|
19044
|
+
value: [diffStyle],
|
|
19045
|
+
onValueChange: (values) => {
|
|
19046
|
+
const value = values[0];
|
|
19047
|
+
if (value === "unified" || value === "split") dispatch({
|
|
19048
|
+
type: "diffStyleChanged",
|
|
19049
|
+
diffStyle: value
|
|
19050
|
+
});
|
|
19051
|
+
},
|
|
19052
|
+
children: ["unified", "split"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroupItem, {
|
|
19053
|
+
value,
|
|
19054
|
+
children: value === "unified" ? "Unified" : "Split"
|
|
19055
|
+
}, value))
|
|
18863
19056
|
})
|
|
18864
|
-
|
|
18865
|
-
variant: "outline",
|
|
18866
|
-
value: [diffStyle],
|
|
18867
|
-
onValueChange: (values) => {
|
|
18868
|
-
const value = values[0];
|
|
18869
|
-
if (value === "unified" || value === "split") dispatch({
|
|
18870
|
-
type: "diffStyleChanged",
|
|
18871
|
-
diffStyle: value
|
|
18872
|
-
});
|
|
18873
|
-
},
|
|
18874
|
-
children: ["unified", "split"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleGroupItem, {
|
|
18875
|
-
value,
|
|
18876
|
-
children: value === "unified" ? "Unified" : "Split"
|
|
18877
|
-
}, value))
|
|
18878
|
-
})]
|
|
19057
|
+
]
|
|
18879
19058
|
})]
|
|
18880
19059
|
}),
|
|
18881
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
children: "No directory selected."
|
|
18890
|
-
}) : !viewerContextId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
18891
|
-
className: "px-3 py-2.5",
|
|
18892
|
-
children: "Waiting for viewer context…"
|
|
18893
|
-
}) : filesQuery.isPending && typeof files === "undefined" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(GitSectionNote, {
|
|
18894
|
-
className: "px-3 py-2.5",
|
|
18895
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}), " Loading changes…"]
|
|
18896
|
-
}) : filesQuery.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
18897
|
-
tone: "destructive",
|
|
18898
|
-
className: "px-3 py-2.5",
|
|
18899
|
-
children: getErrorMessage(filesQuery.error, "Failed to load changes")
|
|
18900
|
-
}) : files === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
18901
|
-
className: "px-3 py-2.5",
|
|
18902
|
-
children: "No git repository detected."
|
|
18903
|
-
}) : changedFiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Accordion$1, {
|
|
18904
|
-
multiple: true,
|
|
18905
|
-
value: openFiles,
|
|
18906
|
-
onValueChange: (nextOpenFiles) => {
|
|
18907
|
-
dispatch({
|
|
18908
|
-
type: "openFilesChanged",
|
|
18909
|
-
openFiles: nextOpenFiles
|
|
18910
|
-
});
|
|
19060
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
19061
|
+
className: "relative min-h-0 flex-1",
|
|
19062
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19063
|
+
ref: setChangesScrollElement,
|
|
19064
|
+
className: "h-full overflow-auto",
|
|
19065
|
+
onScroll: (event) => {
|
|
19066
|
+
updateStickyReviewFileHeader(event.currentTarget);
|
|
19067
|
+
onChangesScrollGradientScroll(event);
|
|
18911
19068
|
},
|
|
18912
|
-
|
|
18913
|
-
|
|
18914
|
-
|
|
18915
|
-
|
|
18916
|
-
|
|
18917
|
-
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
19069
|
+
children: !normalizedCwd ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
19070
|
+
className: "px-3 py-2.5",
|
|
19071
|
+
children: "No directory selected."
|
|
19072
|
+
}) : !viewerContextId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
19073
|
+
className: "px-3 py-2.5",
|
|
19074
|
+
children: "Waiting for viewer context…"
|
|
19075
|
+
}) : filesQuery.isPending && typeof files === "undefined" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(GitSectionNote, {
|
|
19076
|
+
className: "px-3 py-2.5",
|
|
19077
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}), " Loading changes…"]
|
|
19078
|
+
}) : filesQuery.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
19079
|
+
tone: "destructive",
|
|
19080
|
+
className: "px-3 py-2.5",
|
|
19081
|
+
children: getErrorMessage(filesQuery.error, "Failed to load changes")
|
|
19082
|
+
}) : files === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
19083
|
+
className: "px-3 py-2.5",
|
|
19084
|
+
children: "No git repository detected."
|
|
19085
|
+
}) : changedFiles.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Accordion$1, {
|
|
19086
|
+
multiple: true,
|
|
19087
|
+
value: openFiles,
|
|
19088
|
+
onValueChange: (nextOpenFiles) => {
|
|
19089
|
+
dispatch({
|
|
19090
|
+
type: "openFilesChanged",
|
|
19091
|
+
openFiles: nextOpenFiles
|
|
19092
|
+
});
|
|
19093
|
+
},
|
|
19094
|
+
className: "border-b border-border/80",
|
|
19095
|
+
children: changedFiles.map((file) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReviewFileAccordionItem, {
|
|
19096
|
+
viewerContextId,
|
|
19097
|
+
cwd: normalizedCwd,
|
|
19098
|
+
active,
|
|
19099
|
+
diffLineComments,
|
|
19100
|
+
diffStyle,
|
|
19101
|
+
file,
|
|
19102
|
+
open: openFiles.includes(reviewFileValue(file)),
|
|
19103
|
+
stuck: stickyReviewFileValue === reviewFileValue(file),
|
|
19104
|
+
onAddDiffLineComment,
|
|
19105
|
+
onOpenFile
|
|
19106
|
+
}, reviewFileValue(file)))
|
|
19107
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
19108
|
+
className: "px-3 py-2.5",
|
|
19109
|
+
children: "Working tree clean."
|
|
19110
|
+
})
|
|
19111
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollGradientOverlays, {
|
|
19112
|
+
bottomHeight: changesScrollBottomGradientHeight,
|
|
19113
|
+
topHeight: changesScrollTopGradientHeight
|
|
19114
|
+
})]
|
|
18929
19115
|
}),
|
|
18930
19116
|
showEmbeddedHistory && normalizedCwd && viewerContextId && files !== null && !filesQuery.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
18931
19117
|
ref: historyPanelRef,
|
|
@@ -18984,7 +19170,21 @@ function useFileReviewContentView({ viewerContextId, cwd, active, diffLineCommen
|
|
|
18984
19170
|
})
|
|
18985
19171
|
}) : null
|
|
18986
19172
|
]
|
|
18987
|
-
}) : null
|
|
19173
|
+
}) : null,
|
|
19174
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialog$1, {
|
|
19175
|
+
open: confirmNukeWorkingTreeOpen,
|
|
19176
|
+
onOpenChange: setConfirmNukeWorkingTreeOpen,
|
|
19177
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogHeader, { children: [
|
|
19178
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogMedia, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {}) }),
|
|
19179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogTitle, { children: "Nuke working tree?" }),
|
|
19180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogDescription, { children: "This restores tracked files to HEAD and deletes untracked and ignored files in this repository. This cannot be undone from Pico." })
|
|
19181
|
+
] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogCancel, { children: "Cancel" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogAction, {
|
|
19182
|
+
variant: "destructive",
|
|
19183
|
+
disabled: bulkActionDisabled,
|
|
19184
|
+
onClick: runConfirmedNukeWorkingTree,
|
|
19185
|
+
children: "Nuke working tree"
|
|
19186
|
+
})] })] })
|
|
19187
|
+
})
|
|
18988
19188
|
]
|
|
18989
19189
|
});
|
|
18990
19190
|
}
|
|
@@ -19061,8 +19261,8 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffLineComment
|
|
|
19061
19261
|
onGutterUtilityClick: startLineComment
|
|
19062
19262
|
} : {};
|
|
19063
19263
|
const themeOptions = usePicoDiffThemeOptions();
|
|
19064
|
-
const
|
|
19065
|
-
const
|
|
19264
|
+
const canStage = gitFileCanStage(file);
|
|
19265
|
+
const canUnstage = gitFileCanUnstage(file);
|
|
19066
19266
|
const invalidateChangedFileQueries = async () => {
|
|
19067
19267
|
await invalidateGitQueries({
|
|
19068
19268
|
queryClient,
|
|
@@ -19071,26 +19271,27 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffLineComment
|
|
|
19071
19271
|
});
|
|
19072
19272
|
};
|
|
19073
19273
|
const stageMutation = useMutation({
|
|
19074
|
-
mutationFn: async () => await fetchJson(buildRequestUrl("/api/git-stage", { contextId: viewerContextId }), {
|
|
19274
|
+
mutationFn: async (action) => await fetchJson(buildRequestUrl("/api/git-stage", { contextId: viewerContextId }), {
|
|
19075
19275
|
method: "POST",
|
|
19076
19276
|
headers: { "content-type": "application/json" },
|
|
19077
19277
|
body: JSON.stringify({
|
|
19278
|
+
action,
|
|
19078
19279
|
cwd: normalizedCwd,
|
|
19079
19280
|
path: file.path,
|
|
19080
19281
|
previousPath: file.previousPath
|
|
19081
19282
|
})
|
|
19082
19283
|
}),
|
|
19083
|
-
onSuccess: async () => {
|
|
19284
|
+
onSuccess: async (_response, action) => {
|
|
19084
19285
|
await queryClient.invalidateQueries({
|
|
19085
19286
|
queryKey: picoQueryKeys.gitStatus(viewerContextId, normalizedCwd),
|
|
19086
19287
|
exact: true,
|
|
19087
19288
|
refetchType: "active"
|
|
19088
19289
|
});
|
|
19089
19290
|
await invalidateChangedFileQueries();
|
|
19090
|
-
toast.success("Staged changes", { description: file.path });
|
|
19291
|
+
toast.success(action === "unstage" ? "Unstaged changes" : "Staged changes", { description: file.path });
|
|
19091
19292
|
},
|
|
19092
|
-
onError: (error) => {
|
|
19093
|
-
toast.error(getErrorMessage(error, "Failed to stage changes"));
|
|
19293
|
+
onError: (error, action) => {
|
|
19294
|
+
toast.error(getErrorMessage(error, action === "unstage" ? "Failed to unstage changes" : "Failed to stage changes"));
|
|
19094
19295
|
}
|
|
19095
19296
|
});
|
|
19096
19297
|
const discardMutation = useMutation({
|
|
@@ -19127,6 +19328,9 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffLineComment
|
|
|
19127
19328
|
oldContent,
|
|
19128
19329
|
newContent
|
|
19129
19330
|
]);
|
|
19331
|
+
const gitActionDisabled = actionPending || !viewerContextId || !normalizedCwd;
|
|
19332
|
+
const stagePending = stageMutation.isPending && stageMutation.variables === "stage";
|
|
19333
|
+
const unstagePending = stageMutation.isPending && stageMutation.variables === "unstage";
|
|
19130
19334
|
const openFile = (event) => {
|
|
19131
19335
|
event?.stopPropagation();
|
|
19132
19336
|
onOpenFile?.(file.path, { pin: true });
|
|
@@ -19137,50 +19341,81 @@ function ReviewFileAccordionItem({ viewerContextId, cwd, active, diffLineComment
|
|
|
19137
19341
|
};
|
|
19138
19342
|
const stageFileChanges = (event) => {
|
|
19139
19343
|
event?.stopPropagation();
|
|
19140
|
-
stageMutation.mutate();
|
|
19344
|
+
stageMutation.mutate("stage");
|
|
19345
|
+
};
|
|
19346
|
+
const unstageFileChanges = (event) => {
|
|
19347
|
+
event?.stopPropagation();
|
|
19348
|
+
stageMutation.mutate("unstage");
|
|
19141
19349
|
};
|
|
19350
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionTrigger$1, {
|
|
19351
|
+
"data-review-file-trigger": true,
|
|
19352
|
+
"data-review-file-value": value,
|
|
19353
|
+
className: "group/review-file-trigger relative flex min-h-10 min-w-0 flex-1 items-center justify-between gap-3 rounded-none border border-transparent bg-background px-3 py-2 text-left text-[13px] font-medium transition-all outline-none hover:no-underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
19354
|
+
children: [
|
|
19355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
19356
|
+
className: "grid min-w-0 flex-1 grid-cols-[auto_auto_minmax(0,1fr)_auto] items-center gap-2",
|
|
19357
|
+
children: [
|
|
19358
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFileStatus, { status: file.status }),
|
|
19359
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFileTypeIcon, { path: file.path }),
|
|
19360
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19361
|
+
className: "min-w-0 truncate text-left",
|
|
19362
|
+
children: file.previousPath ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
19363
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19364
|
+
className: "text-muted-foreground",
|
|
19365
|
+
children: file.previousPath
|
|
19366
|
+
}),
|
|
19367
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19368
|
+
className: "text-muted-foreground/70",
|
|
19369
|
+
children: " → "
|
|
19370
|
+
}),
|
|
19371
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: file.path })
|
|
19372
|
+
] }) : file.path
|
|
19373
|
+
}),
|
|
19374
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFileDiff, { file })
|
|
19375
|
+
]
|
|
19376
|
+
}),
|
|
19377
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, {
|
|
19378
|
+
"data-slot": "accordion-trigger-icon",
|
|
19379
|
+
className: "pointer-events-none size-4 shrink-0 group-aria-expanded/review-file-trigger:hidden"
|
|
19380
|
+
}),
|
|
19381
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {
|
|
19382
|
+
"data-slot": "accordion-trigger-icon",
|
|
19383
|
+
className: "pointer-events-none hidden size-4 shrink-0 group-aria-expanded/review-file-trigger:inline"
|
|
19384
|
+
})
|
|
19385
|
+
]
|
|
19386
|
+
});
|
|
19142
19387
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionItem, {
|
|
19143
19388
|
value,
|
|
19144
19389
|
className: "border-border/70",
|
|
19145
19390
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionHeader, {
|
|
19146
19391
|
className: cn("group/review-file-header sticky top-0 z-20 flex bg-background transition-shadow", stuck && "shadow-sm"),
|
|
19147
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
19148
|
-
"
|
|
19149
|
-
"data-review-file-value": value,
|
|
19150
|
-
className: "group/review-file-trigger relative flex min-h-10 min-w-0 flex-1 items-center justify-between gap-3 rounded-none border border-transparent bg-background px-3 py-2 text-left font-mono text-[13px] font-medium transition-all outline-none hover:no-underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
19392
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenu$1, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuTrigger, { render: trigger }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuContent, {
|
|
19393
|
+
className: "w-48",
|
|
19151
19394
|
children: [
|
|
19152
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFileTypeIcon, { path: file.path }),
|
|
19157
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19158
|
-
className: "min-w-0 truncate text-left",
|
|
19159
|
-
children: file.previousPath ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
19160
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19161
|
-
className: "text-muted-foreground",
|
|
19162
|
-
children: file.previousPath
|
|
19163
|
-
}),
|
|
19164
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
19165
|
-
className: "text-muted-foreground/70",
|
|
19166
|
-
children: " → "
|
|
19167
|
-
}),
|
|
19168
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: file.path })
|
|
19169
|
-
] }) : file.path
|
|
19170
|
-
}),
|
|
19171
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitFileDiff, { file })
|
|
19172
|
-
]
|
|
19395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuItem, {
|
|
19396
|
+
disabled: !onOpenFile,
|
|
19397
|
+
onClick: openFile,
|
|
19398
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUpRight, {}), "Open file"]
|
|
19173
19399
|
}),
|
|
19174
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
19175
|
-
|
|
19176
|
-
|
|
19400
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContextMenuSeparator, {}),
|
|
19401
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuItem, {
|
|
19402
|
+
disabled: gitActionDisabled || !canStage,
|
|
19403
|
+
onClick: stageFileChanges,
|
|
19404
|
+
children: [stagePending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, {}), "Stage changes"]
|
|
19177
19405
|
}),
|
|
19178
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
19179
|
-
|
|
19180
|
-
|
|
19406
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuItem, {
|
|
19407
|
+
disabled: gitActionDisabled || !canUnstage,
|
|
19408
|
+
onClick: unstageFileChanges,
|
|
19409
|
+
children: [unstagePending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Minus, {}), "Unstage changes"]
|
|
19410
|
+
}),
|
|
19411
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ContextMenuItem, {
|
|
19412
|
+
variant: "destructive",
|
|
19413
|
+
disabled: gitActionDisabled,
|
|
19414
|
+
onClick: discardFileChanges,
|
|
19415
|
+
children: [discardMutation.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Undo2, {}), "Discard changes"]
|
|
19181
19416
|
})
|
|
19182
19417
|
]
|
|
19183
|
-
})
|
|
19418
|
+
})] })
|
|
19184
19419
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionContent, {
|
|
19185
19420
|
className: "bg-background p-0",
|
|
19186
19421
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -19425,7 +19660,7 @@ function assignClassName(element, className) {
|
|
|
19425
19660
|
}
|
|
19426
19661
|
function renderPendingCommitDiffLineComment(pendingComment) {
|
|
19427
19662
|
const form = document.createElement("form");
|
|
19428
|
-
assignClassName(form, "m-2 w-[
|
|
19663
|
+
assignClassName(form, "m-2 w-[calc(100%_-_1rem)] max-w-[38rem] rounded-lg border border-border/70 bg-background p-2 shadow-sm");
|
|
19429
19664
|
const header = document.createElement("div");
|
|
19430
19665
|
assignClassName(header, "mb-2 flex min-w-0 items-center justify-between gap-2 text-xs text-muted-foreground");
|
|
19431
19666
|
const label = document.createElement("span");
|
|
@@ -19568,7 +19803,7 @@ function CommitFileDiffAccordionItem({ comments, diffStyle, fileDiff, index, onS
|
|
|
19568
19803
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionTrigger$1, {
|
|
19569
19804
|
"data-commit-file-trigger": true,
|
|
19570
19805
|
"data-commit-file-value": value,
|
|
19571
|
-
className: "group/commit-file-trigger relative flex min-h-10 min-w-0 flex-1 items-center justify-between gap-3 rounded-none border border-transparent bg-background px-3 py-2 text-left
|
|
19806
|
+
className: "group/commit-file-trigger relative flex min-h-10 min-w-0 flex-1 items-center justify-between gap-3 rounded-none border border-transparent bg-background px-3 py-2 text-left text-[13px] font-medium transition-all outline-none hover:no-underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
19572
19807
|
children: [
|
|
19573
19808
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
19574
19809
|
className: "grid min-w-0 flex-1 grid-cols-[minmax(0,1fr)_auto] items-baseline gap-3",
|
|
@@ -19706,8 +19941,14 @@ function CommitDiffHeaderTitle({ tab }) {
|
|
|
19706
19941
|
function CommitDiffContent({ viewerContextId, cwd, active, diffLineComments, onAddDiffLineComment, tab }) {
|
|
19707
19942
|
const [diffStyle, setDiffStyle] = import_react.useState("unified");
|
|
19708
19943
|
const [stickyCommitFileValue, setStickyCommitFileValue] = import_react.useState("");
|
|
19944
|
+
const isMobile = useIsMobile();
|
|
19709
19945
|
const [commentTarget, setCommentTarget] = import_react.useState(null);
|
|
19710
19946
|
const diffScrollRef = import_react.useRef(null);
|
|
19947
|
+
const { bottomHeight: diffScrollBottomGradientHeight, onScroll: onDiffScrollGradientScroll, setScrollElement: setDiffScrollGradientElement, topHeight: diffScrollTopGradientHeight } = useScrollGradients();
|
|
19948
|
+
const setDiffScrollElement = import_react.useCallback((element) => {
|
|
19949
|
+
diffScrollRef.current = element;
|
|
19950
|
+
setDiffScrollGradientElement(element);
|
|
19951
|
+
}, [setDiffScrollGradientElement]);
|
|
19711
19952
|
const updateStickyCommitFileHeader = (scrollElement) => {
|
|
19712
19953
|
setDerivedScrollState(setStickyCommitFileValue, getStuckScrollTriggerValue({
|
|
19713
19954
|
getValue: (trigger) => trigger.dataset.commitFileValue || "",
|
|
@@ -19773,6 +20014,7 @@ function CommitDiffContent({ viewerContextId, cwd, active, diffLineComments, onA
|
|
|
19773
20014
|
className: "flex min-h-10 shrink-0 items-center justify-between gap-2 border-b border-border/70 bg-background p-2",
|
|
19774
20015
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitDiffHeaderTitle, { tab }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ToggleGroup$1, {
|
|
19775
20016
|
variant: "outline",
|
|
20017
|
+
size: isMobile ? "default" : "sm",
|
|
19776
20018
|
value: [diffStyle],
|
|
19777
20019
|
onValueChange: (values) => {
|
|
19778
20020
|
const value = values[0];
|
|
@@ -19786,41 +20028,48 @@ function CommitDiffContent({ viewerContextId, cwd, active, diffLineComments, onA
|
|
|
19786
20028
|
children: "Split"
|
|
19787
20029
|
})]
|
|
19788
20030
|
})]
|
|
19789
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.
|
|
19790
|
-
|
|
19791
|
-
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
20031
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20032
|
+
className: "relative min-h-0 flex-1",
|
|
20033
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20034
|
+
ref: setDiffScrollElement,
|
|
20035
|
+
className: "h-full overflow-auto",
|
|
20036
|
+
onScroll: (event) => {
|
|
20037
|
+
updateStickyCommitFileHeader(event.currentTarget);
|
|
20038
|
+
onDiffScrollGradientScroll(event);
|
|
20039
|
+
},
|
|
20040
|
+
children: diffQuery.isPending && !diffQuery.data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20041
|
+
className: "p-4",
|
|
20042
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(GitSectionNote, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}), " Loading commit diff…"] })
|
|
20043
|
+
}) : diffQuery.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20044
|
+
className: "p-4",
|
|
20045
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
|
|
20046
|
+
tone: "destructive",
|
|
20047
|
+
children: getErrorMessage(diffQuery.error, "Failed to load commit diff")
|
|
20048
|
+
})
|
|
20049
|
+
}) : diffQuery.data?.patch && tab.path ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitSingleFileDiff, {
|
|
20050
|
+
comments: commentsForTab.filter((comment) => {
|
|
20051
|
+
if (!tab.path) return true;
|
|
20052
|
+
return comment.path === tab.path || comment.path === tab.previousPath;
|
|
20053
|
+
}),
|
|
20054
|
+
diffStyle,
|
|
20055
|
+
onStartComment: startLineComment,
|
|
20056
|
+
patch: diffQuery.data.patch,
|
|
20057
|
+
pendingComment
|
|
20058
|
+
}) : diffQuery.data?.patch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitPatchDiffs, {
|
|
20059
|
+
comments: commentsForTab,
|
|
20060
|
+
diffStyle,
|
|
20061
|
+
onStartComment: startLineComment,
|
|
20062
|
+
patch: diffQuery.data.patch,
|
|
20063
|
+
pendingComment,
|
|
20064
|
+
stuckFileValue: stickyCommitFileValue
|
|
20065
|
+
}, `${diffQuery.data.commit}:${diffQuery.data.mode}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20066
|
+
className: "p-4",
|
|
20067
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, { children: "No line changes." })
|
|
19803
20068
|
})
|
|
19804
|
-
})
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
}),
|
|
19809
|
-
diffStyle,
|
|
19810
|
-
onStartComment: startLineComment,
|
|
19811
|
-
patch: diffQuery.data.patch,
|
|
19812
|
-
pendingComment
|
|
19813
|
-
}) : diffQuery.data?.patch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CommitPatchDiffs, {
|
|
19814
|
-
comments: commentsForTab,
|
|
19815
|
-
diffStyle,
|
|
19816
|
-
onStartComment: startLineComment,
|
|
19817
|
-
patch: diffQuery.data.patch,
|
|
19818
|
-
pendingComment,
|
|
19819
|
-
stuckFileValue: stickyCommitFileValue
|
|
19820
|
-
}, `${diffQuery.data.commit}:${diffQuery.data.mode}`) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
19821
|
-
className: "p-4",
|
|
19822
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, { children: "No line changes." })
|
|
19823
|
-
})
|
|
20069
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollGradientOverlays, {
|
|
20070
|
+
bottomHeight: diffScrollBottomGradientHeight,
|
|
20071
|
+
topHeight: diffScrollTopGradientHeight
|
|
20072
|
+
})]
|
|
19824
20073
|
})]
|
|
19825
20074
|
});
|
|
19826
20075
|
}
|
|
@@ -20053,28 +20302,723 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
|
|
|
20053
20302
|
})
|
|
20054
20303
|
}) : null]
|
|
20055
20304
|
})]
|
|
20056
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFilesWorkspace, {
|
|
20057
|
-
viewerContextId,
|
|
20058
|
-
cwd: normalizedCwd,
|
|
20059
|
-
active: active && activeTab === "files",
|
|
20060
|
-
activeFilePath: currentFilePath,
|
|
20061
|
-
onOpenFile: openFile,
|
|
20062
|
-
previewMode
|
|
20063
|
-
})
|
|
20064
|
-
}),
|
|
20065
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectOpenFileDialog, {
|
|
20066
|
-
open: localState.openFileDialogOpen,
|
|
20067
|
-
onOpenChange: (open) => dispatchLocal({
|
|
20068
|
-
type: "set-open-file-dialog-open",
|
|
20069
|
-
open
|
|
20305
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFilesWorkspace, {
|
|
20306
|
+
viewerContextId,
|
|
20307
|
+
cwd: normalizedCwd,
|
|
20308
|
+
active: active && activeTab === "files",
|
|
20309
|
+
activeFilePath: currentFilePath,
|
|
20310
|
+
onOpenFile: openFile,
|
|
20311
|
+
previewMode
|
|
20312
|
+
})
|
|
20313
|
+
}),
|
|
20314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectOpenFileDialog, {
|
|
20315
|
+
open: localState.openFileDialogOpen,
|
|
20316
|
+
onOpenChange: (open) => dispatchLocal({
|
|
20317
|
+
type: "set-open-file-dialog-open",
|
|
20318
|
+
open
|
|
20319
|
+
}),
|
|
20320
|
+
paths: fileDialogPaths,
|
|
20321
|
+
onOpenFile: (path) => {
|
|
20322
|
+
openFile(path, { pin: true });
|
|
20323
|
+
}
|
|
20324
|
+
})
|
|
20325
|
+
]
|
|
20326
|
+
})]
|
|
20327
|
+
});
|
|
20328
|
+
}
|
|
20329
|
+
var TERMINAL_ANSI_THEMES = {
|
|
20330
|
+
dark: {
|
|
20331
|
+
black: "#484f58",
|
|
20332
|
+
red: "#ff7b72",
|
|
20333
|
+
green: "#3fb950",
|
|
20334
|
+
yellow: "#d29922",
|
|
20335
|
+
blue: "#58a6ff",
|
|
20336
|
+
magenta: "#bc8cff",
|
|
20337
|
+
cyan: "#39c5cf",
|
|
20338
|
+
white: "#b1bac4",
|
|
20339
|
+
brightBlack: "#6e7681",
|
|
20340
|
+
brightRed: "#ffa198",
|
|
20341
|
+
brightGreen: "#56d364",
|
|
20342
|
+
brightYellow: "#e3b341",
|
|
20343
|
+
brightBlue: "#79c0ff",
|
|
20344
|
+
brightMagenta: "#d2a8ff",
|
|
20345
|
+
brightCyan: "#56d4dd",
|
|
20346
|
+
brightWhite: "#f0f6fc"
|
|
20347
|
+
},
|
|
20348
|
+
light: {
|
|
20349
|
+
black: "#24292f",
|
|
20350
|
+
red: "#cf222e",
|
|
20351
|
+
green: "#116329",
|
|
20352
|
+
yellow: "#953800",
|
|
20353
|
+
blue: "#0969da",
|
|
20354
|
+
magenta: "#8250df",
|
|
20355
|
+
cyan: "#1b7c83",
|
|
20356
|
+
white: "#6e7781",
|
|
20357
|
+
brightBlack: "#57606a",
|
|
20358
|
+
brightRed: "#a40e26",
|
|
20359
|
+
brightGreen: "#1a7f37",
|
|
20360
|
+
brightYellow: "#9a6700",
|
|
20361
|
+
brightBlue: "#218bff",
|
|
20362
|
+
brightMagenta: "#a475f9",
|
|
20363
|
+
brightCyan: "#3192aa",
|
|
20364
|
+
brightWhite: "#24292f"
|
|
20365
|
+
}
|
|
20366
|
+
};
|
|
20367
|
+
var terminalTabCounter = 0;
|
|
20368
|
+
function createTerminalTabId() {
|
|
20369
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return `terminal-tab-${crypto.randomUUID()}`;
|
|
20370
|
+
terminalTabCounter += 1;
|
|
20371
|
+
return `terminal-tab-${Date.now()}-${terminalTabCounter}`;
|
|
20372
|
+
}
|
|
20373
|
+
function createTerminalTab(id = createTerminalTabId()) {
|
|
20374
|
+
return {
|
|
20375
|
+
id,
|
|
20376
|
+
status: { type: "idle" },
|
|
20377
|
+
terminalId: null
|
|
20378
|
+
};
|
|
20379
|
+
}
|
|
20380
|
+
function createTerminalTabsState(scopeKey) {
|
|
20381
|
+
const storedTabs = readStoredTerminalTabs(scopeKey);
|
|
20382
|
+
const tabs = storedTabs.tabs.map((id) => createTerminalTab(id));
|
|
20383
|
+
return {
|
|
20384
|
+
activeTabId: storedTabs.activeTabId ?? tabs[0]?.id ?? null,
|
|
20385
|
+
scopeKey,
|
|
20386
|
+
tabs
|
|
20387
|
+
};
|
|
20388
|
+
}
|
|
20389
|
+
function rememberTerminalTabsState(state) {
|
|
20390
|
+
rememberStoredTerminalTabs(state.scopeKey, {
|
|
20391
|
+
activeTabId: state.activeTabId,
|
|
20392
|
+
tabs: state.tabs.map((tab) => tab.id)
|
|
20393
|
+
});
|
|
20394
|
+
}
|
|
20395
|
+
function terminalStatusText(status) {
|
|
20396
|
+
switch (status.type) {
|
|
20397
|
+
case "idle": return "Idle";
|
|
20398
|
+
case "connecting": return "Connecting…";
|
|
20399
|
+
case "connected": return status.shell ? `Running ${status.shell}` : "Connected";
|
|
20400
|
+
case "exited": return `Exited ${status.exitCode}`;
|
|
20401
|
+
case "error": return "Terminal error";
|
|
20402
|
+
}
|
|
20403
|
+
}
|
|
20404
|
+
function terminalStatusDetail(status) {
|
|
20405
|
+
switch (status.type) {
|
|
20406
|
+
case "idle": return "This terminal has not started yet.";
|
|
20407
|
+
case "connecting": return "Pico is connecting to the terminal process.";
|
|
20408
|
+
case "connected": return status.shell ? `The terminal is connected and running ${status.shell}.` : "The terminal is connected.";
|
|
20409
|
+
case "exited": return typeof status.signal === "number" ? `The terminal process exited with code ${status.exitCode} and signal ${status.signal}.` : `The terminal process exited with code ${status.exitCode}.`;
|
|
20410
|
+
case "error": return status.message;
|
|
20411
|
+
}
|
|
20412
|
+
}
|
|
20413
|
+
function terminalTabLabel(tab, index) {
|
|
20414
|
+
if (tab.status.type === "connected" && tab.status.shell) return `${index + 1}: ${tab.status.shell}`;
|
|
20415
|
+
return `Terminal ${index + 1}`;
|
|
20416
|
+
}
|
|
20417
|
+
function statusDotClassName(status) {
|
|
20418
|
+
switch (status.type) {
|
|
20419
|
+
case "connected": return "bg-success";
|
|
20420
|
+
case "connecting": return "bg-warning";
|
|
20421
|
+
case "error":
|
|
20422
|
+
case "exited": return "bg-destructive";
|
|
20423
|
+
case "idle": return "bg-muted-foreground/50";
|
|
20424
|
+
}
|
|
20425
|
+
}
|
|
20426
|
+
function cssVariable(name, fallback) {
|
|
20427
|
+
return window.getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
|
|
20428
|
+
}
|
|
20429
|
+
function resolveTerminalThemeMode() {
|
|
20430
|
+
for (const className of document.documentElement.classList) {
|
|
20431
|
+
const mode = appliedThemeClassColorMode(className);
|
|
20432
|
+
if (mode) return mode;
|
|
20433
|
+
}
|
|
20434
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
20435
|
+
}
|
|
20436
|
+
function terminalAnsiTheme() {
|
|
20437
|
+
const fallback = TERMINAL_ANSI_THEMES[resolveTerminalThemeMode()];
|
|
20438
|
+
return {
|
|
20439
|
+
black: cssVariable("--terminal-ansi-black", fallback.black),
|
|
20440
|
+
red: cssVariable("--terminal-ansi-red", fallback.red),
|
|
20441
|
+
green: cssVariable("--terminal-ansi-green", fallback.green),
|
|
20442
|
+
yellow: cssVariable("--terminal-ansi-yellow", fallback.yellow),
|
|
20443
|
+
blue: cssVariable("--terminal-ansi-blue", fallback.blue),
|
|
20444
|
+
magenta: cssVariable("--terminal-ansi-magenta", fallback.magenta),
|
|
20445
|
+
cyan: cssVariable("--terminal-ansi-cyan", fallback.cyan),
|
|
20446
|
+
white: cssVariable("--terminal-ansi-white", fallback.white),
|
|
20447
|
+
brightBlack: cssVariable("--terminal-ansi-bright-black", fallback.brightBlack),
|
|
20448
|
+
brightRed: cssVariable("--terminal-ansi-bright-red", fallback.brightRed),
|
|
20449
|
+
brightGreen: cssVariable("--terminal-ansi-bright-green", fallback.brightGreen),
|
|
20450
|
+
brightYellow: cssVariable("--terminal-ansi-bright-yellow", fallback.brightYellow),
|
|
20451
|
+
brightBlue: cssVariable("--terminal-ansi-bright-blue", fallback.brightBlue),
|
|
20452
|
+
brightMagenta: cssVariable("--terminal-ansi-bright-magenta", fallback.brightMagenta),
|
|
20453
|
+
brightCyan: cssVariable("--terminal-ansi-bright-cyan", fallback.brightCyan),
|
|
20454
|
+
brightWhite: cssVariable("--terminal-ansi-bright-white", fallback.brightWhite)
|
|
20455
|
+
};
|
|
20456
|
+
}
|
|
20457
|
+
function createTerminalTheme() {
|
|
20458
|
+
const ansiTheme = terminalAnsiTheme();
|
|
20459
|
+
return {
|
|
20460
|
+
...ansiTheme,
|
|
20461
|
+
background: cssVariable("--terminal-background", cssVariable("--background", "#111111")),
|
|
20462
|
+
cursor: cssVariable("--terminal-cursor", cssVariable("--primary", "#7aa2f7")),
|
|
20463
|
+
foreground: cssVariable("--terminal-foreground", cssVariable("--foreground", ansiTheme.brightWhite)),
|
|
20464
|
+
selectionBackground: cssVariable("--terminal-selection-background", cssVariable("--code-selection", "#334155"))
|
|
20465
|
+
};
|
|
20466
|
+
}
|
|
20467
|
+
function createTerminalFontFamily() {
|
|
20468
|
+
return cssVariable("--font-mono", "Menlo, ui-monospace, SFMono-Regular, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace");
|
|
20469
|
+
}
|
|
20470
|
+
function errorMessage(error) {
|
|
20471
|
+
if (error instanceof Error && error.message.trim()) return error.message;
|
|
20472
|
+
if (typeof error === "string" && error.trim()) return error;
|
|
20473
|
+
return "Unknown terminal error";
|
|
20474
|
+
}
|
|
20475
|
+
function exitedStatus(event) {
|
|
20476
|
+
return typeof event.signal === "number" && event.signal > 0 ? {
|
|
20477
|
+
type: "exited",
|
|
20478
|
+
exitCode: event.exitCode,
|
|
20479
|
+
signal: event.signal
|
|
20480
|
+
} : {
|
|
20481
|
+
type: "exited",
|
|
20482
|
+
exitCode: event.exitCode
|
|
20483
|
+
};
|
|
20484
|
+
}
|
|
20485
|
+
function isTerminalToggleEvent(event) {
|
|
20486
|
+
return event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey && (event.key === "`" || event.code === "Backquote");
|
|
20487
|
+
}
|
|
20488
|
+
function TerminalStatusDot({ status }) {
|
|
20489
|
+
if (status.type === "connecting") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
20490
|
+
size: "xs",
|
|
20491
|
+
className: "shrink-0"
|
|
20492
|
+
});
|
|
20493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
20494
|
+
"aria-hidden": "true",
|
|
20495
|
+
className: cn("size-2 shrink-0 rounded-full", statusDotClassName(status))
|
|
20496
|
+
});
|
|
20497
|
+
}
|
|
20498
|
+
function TerminalStatusDialog({ cwd, index, onOpenChange, open, tab }) {
|
|
20499
|
+
const status = tab?.status ?? { type: "idle" };
|
|
20500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog$1, {
|
|
20501
|
+
open,
|
|
20502
|
+
onOpenChange,
|
|
20503
|
+
focusPromptOnClose: false,
|
|
20504
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
|
|
20505
|
+
className: "max-w-sm",
|
|
20506
|
+
children: [
|
|
20507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle, { children: [tab ? terminalTabLabel(tab, index) : "Terminal", " status"] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: terminalStatusDetail(status) })] }),
|
|
20508
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
|
|
20509
|
+
className: "grid gap-3 text-sm",
|
|
20510
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20511
|
+
className: "grid gap-1",
|
|
20512
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
20513
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
20514
|
+
children: "Status"
|
|
20515
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: terminalStatusText(status) })]
|
|
20516
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20517
|
+
className: "grid gap-1",
|
|
20518
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
20519
|
+
className: "text-xs font-medium text-muted-foreground",
|
|
20520
|
+
children: "Working directory"
|
|
20521
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
|
|
20522
|
+
className: "break-all",
|
|
20523
|
+
children: cwd
|
|
20524
|
+
})]
|
|
20525
|
+
})]
|
|
20526
|
+
}),
|
|
20527
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogFooter, { showCloseButton: true })
|
|
20528
|
+
]
|
|
20529
|
+
})
|
|
20530
|
+
});
|
|
20531
|
+
}
|
|
20532
|
+
function TerminalTabPane({ active, cwd, onStatusChange, onTerminalIdChange, selected, sessionId, tabId, viewerContextId }) {
|
|
20533
|
+
const terminalElementRef = import_react.useRef(null);
|
|
20534
|
+
const terminalRef = import_react.useRef(null);
|
|
20535
|
+
const terminalIdRef = import_react.useRef(null);
|
|
20536
|
+
const activeRef = import_react.useRef(active);
|
|
20537
|
+
const fitAndResizeRef = import_react.useRef(() => {});
|
|
20538
|
+
const onStatusChangeRef = import_react.useRef(onStatusChange);
|
|
20539
|
+
const onTerminalIdChangeRef = import_react.useRef(onTerminalIdChange);
|
|
20540
|
+
const [status, setStatus] = import_react.useState({ type: "idle" });
|
|
20541
|
+
import_react.useLayoutEffect(() => {
|
|
20542
|
+
activeRef.current = active;
|
|
20543
|
+
}, [active]);
|
|
20544
|
+
import_react.useEffect(() => {
|
|
20545
|
+
onStatusChangeRef.current = onStatusChange;
|
|
20546
|
+
}, [onStatusChange]);
|
|
20547
|
+
import_react.useEffect(() => {
|
|
20548
|
+
onTerminalIdChangeRef.current = onTerminalIdChange;
|
|
20549
|
+
}, [onTerminalIdChange]);
|
|
20550
|
+
import_react.useEffect(() => {
|
|
20551
|
+
if (!cwd) {
|
|
20552
|
+
setStatus({ type: "idle" });
|
|
20553
|
+
onStatusChangeRef.current(tabId, { type: "idle" });
|
|
20554
|
+
return;
|
|
20555
|
+
}
|
|
20556
|
+
const terminalElement = terminalElementRef.current;
|
|
20557
|
+
if (!terminalElement) return;
|
|
20558
|
+
let disposed = false;
|
|
20559
|
+
let eventSource = null;
|
|
20560
|
+
let inputDisposable = null;
|
|
20561
|
+
let fitAddon = null;
|
|
20562
|
+
let resizeObserver = null;
|
|
20563
|
+
let inputFlushTimer = null;
|
|
20564
|
+
let resizeFrame = null;
|
|
20565
|
+
let inputBuffer = "";
|
|
20566
|
+
let lastResizeKey = "";
|
|
20567
|
+
const requestOptions = sessionId ? {
|
|
20568
|
+
contextId: viewerContextId,
|
|
20569
|
+
sessionId
|
|
20570
|
+
} : { contextId: viewerContextId };
|
|
20571
|
+
const publishStatus = (nextStatus) => {
|
|
20572
|
+
if (disposed) return;
|
|
20573
|
+
setStatus(nextStatus);
|
|
20574
|
+
onStatusChangeRef.current(tabId, nextStatus);
|
|
20575
|
+
};
|
|
20576
|
+
const postJson = async (path, body) => {
|
|
20577
|
+
return await fetchJson(buildRequestUrl(path, requestOptions), {
|
|
20578
|
+
body: JSON.stringify(body),
|
|
20579
|
+
headers: { "content-type": "application/json" },
|
|
20580
|
+
method: "POST"
|
|
20581
|
+
});
|
|
20582
|
+
};
|
|
20583
|
+
const flushInput = () => {
|
|
20584
|
+
inputFlushTimer = null;
|
|
20585
|
+
const id = terminalIdRef.current;
|
|
20586
|
+
if (!id || !inputBuffer) return;
|
|
20587
|
+
const data = inputBuffer;
|
|
20588
|
+
inputBuffer = "";
|
|
20589
|
+
postJson(`/api/terminal/${encodeURIComponent(id)}/input`, { data }).catch((error) => {
|
|
20590
|
+
if (!disposed) publishStatus({
|
|
20591
|
+
type: "error",
|
|
20592
|
+
message: errorMessage(error)
|
|
20593
|
+
});
|
|
20594
|
+
});
|
|
20595
|
+
};
|
|
20596
|
+
const scheduleInputFlush = () => {
|
|
20597
|
+
if (inputFlushTimer !== null) return;
|
|
20598
|
+
inputFlushTimer = window.setTimeout(flushInput, 12);
|
|
20599
|
+
};
|
|
20600
|
+
const fitAndResize = () => {
|
|
20601
|
+
const terminal = terminalRef.current;
|
|
20602
|
+
if (!terminal || !fitAddon) return;
|
|
20603
|
+
try {
|
|
20604
|
+
fitAddon.fit();
|
|
20605
|
+
} catch {
|
|
20606
|
+
return;
|
|
20607
|
+
}
|
|
20608
|
+
const id = terminalIdRef.current;
|
|
20609
|
+
if (!id) return;
|
|
20610
|
+
const resizeKey = `${terminal.cols}x${terminal.rows}`;
|
|
20611
|
+
if (resizeKey === lastResizeKey) return;
|
|
20612
|
+
lastResizeKey = resizeKey;
|
|
20613
|
+
postJson(`/api/terminal/${encodeURIComponent(id)}/resize`, {
|
|
20614
|
+
cols: terminal.cols,
|
|
20615
|
+
rows: terminal.rows
|
|
20616
|
+
}).catch(() => {});
|
|
20617
|
+
};
|
|
20618
|
+
const scheduleFitAndResize = () => {
|
|
20619
|
+
if (resizeFrame !== null) return;
|
|
20620
|
+
resizeFrame = window.requestAnimationFrame(() => {
|
|
20621
|
+
resizeFrame = null;
|
|
20622
|
+
fitAndResize();
|
|
20623
|
+
});
|
|
20624
|
+
};
|
|
20625
|
+
fitAndResizeRef.current = scheduleFitAndResize;
|
|
20626
|
+
const startTerminal = async () => {
|
|
20627
|
+
try {
|
|
20628
|
+
publishStatus({ type: "connecting" });
|
|
20629
|
+
terminalElement.textContent = "";
|
|
20630
|
+
const [{ Terminal }, { FitAddon }] = await Promise.all([import("../_libs/xterm__xterm.mjs").then((n) => n.t), import("../_libs/xterm__addon-fit.mjs").then((n) => n.t)]);
|
|
20631
|
+
if (disposed) return;
|
|
20632
|
+
const terminal = new Terminal({
|
|
20633
|
+
allowTransparency: true,
|
|
20634
|
+
convertEol: false,
|
|
20635
|
+
cursorBlink: true,
|
|
20636
|
+
fontFamily: createTerminalFontFamily(),
|
|
20637
|
+
fontSize: 12,
|
|
20638
|
+
letterSpacing: 0,
|
|
20639
|
+
lineHeight: 1.2,
|
|
20640
|
+
scrollback: 5e3,
|
|
20641
|
+
theme: createTerminalTheme()
|
|
20642
|
+
});
|
|
20643
|
+
fitAddon = new FitAddon();
|
|
20644
|
+
terminal.loadAddon(fitAddon);
|
|
20645
|
+
terminal.open(terminalElement);
|
|
20646
|
+
terminalRef.current = terminal;
|
|
20647
|
+
inputDisposable = terminal.onData((data) => {
|
|
20648
|
+
if (!activeRef.current) return;
|
|
20649
|
+
inputBuffer += data;
|
|
20650
|
+
scheduleInputFlush();
|
|
20651
|
+
});
|
|
20652
|
+
scheduleFitAndResize();
|
|
20653
|
+
const terminalResponse = await postJson("/api/terminal", {
|
|
20654
|
+
clientKey: tabId,
|
|
20655
|
+
cols: terminal.cols,
|
|
20656
|
+
rows: terminal.rows
|
|
20657
|
+
});
|
|
20658
|
+
if (disposed) return;
|
|
20659
|
+
terminalIdRef.current = terminalResponse.id;
|
|
20660
|
+
onTerminalIdChangeRef.current(tabId, terminalResponse.id);
|
|
20661
|
+
publishStatus({
|
|
20662
|
+
type: "connected",
|
|
20663
|
+
shell: terminalResponse.shell
|
|
20664
|
+
});
|
|
20665
|
+
eventSource = new EventSource(buildRequestUrl(`/api/terminal/${encodeURIComponent(terminalResponse.id)}/events`, requestOptions));
|
|
20666
|
+
eventSource.onmessage = (message) => {
|
|
20667
|
+
if (disposed) return;
|
|
20668
|
+
const event = JSON.parse(message.data);
|
|
20669
|
+
if (event.type === "output") {
|
|
20670
|
+
terminal.write(event.data);
|
|
20671
|
+
return;
|
|
20672
|
+
}
|
|
20673
|
+
if (event.type === "ready") {
|
|
20674
|
+
publishStatus({
|
|
20675
|
+
type: "connected",
|
|
20676
|
+
shell: event.shell
|
|
20677
|
+
});
|
|
20678
|
+
return;
|
|
20679
|
+
}
|
|
20680
|
+
if (event.type === "exit") {
|
|
20681
|
+
publishStatus(exitedStatus(event));
|
|
20682
|
+
return;
|
|
20683
|
+
}
|
|
20684
|
+
if (event.type === "error") publishStatus({
|
|
20685
|
+
type: "error",
|
|
20686
|
+
message: event.error
|
|
20687
|
+
});
|
|
20688
|
+
};
|
|
20689
|
+
eventSource.onerror = () => {
|
|
20690
|
+
if (!disposed && terminalIdRef.current) setStatus((current) => {
|
|
20691
|
+
if (current.type === "connected") return current;
|
|
20692
|
+
const nextStatus = {
|
|
20693
|
+
type: "error",
|
|
20694
|
+
message: "Terminal connection interrupted."
|
|
20695
|
+
};
|
|
20696
|
+
onStatusChangeRef.current(tabId, nextStatus);
|
|
20697
|
+
return nextStatus;
|
|
20698
|
+
});
|
|
20699
|
+
};
|
|
20700
|
+
resizeObserver = new ResizeObserver(scheduleFitAndResize);
|
|
20701
|
+
resizeObserver.observe(terminalElement);
|
|
20702
|
+
scheduleFitAndResize();
|
|
20703
|
+
} catch (error) {
|
|
20704
|
+
if (disposed) return;
|
|
20705
|
+
const message = errorMessage(error);
|
|
20706
|
+
publishStatus({
|
|
20707
|
+
type: "error",
|
|
20708
|
+
message
|
|
20709
|
+
});
|
|
20710
|
+
terminalRef.current?.writeln(`\r\n${message}`);
|
|
20711
|
+
}
|
|
20712
|
+
};
|
|
20713
|
+
startTerminal();
|
|
20714
|
+
return () => {
|
|
20715
|
+
disposed = true;
|
|
20716
|
+
if (inputFlushTimer !== null) window.clearTimeout(inputFlushTimer);
|
|
20717
|
+
if (resizeFrame !== null) window.cancelAnimationFrame(resizeFrame);
|
|
20718
|
+
flushInput();
|
|
20719
|
+
resizeObserver?.disconnect();
|
|
20720
|
+
eventSource?.close();
|
|
20721
|
+
inputDisposable?.dispose();
|
|
20722
|
+
terminalRef.current?.dispose();
|
|
20723
|
+
terminalRef.current = null;
|
|
20724
|
+
terminalIdRef.current = null;
|
|
20725
|
+
fitAndResizeRef.current = () => {};
|
|
20726
|
+
};
|
|
20727
|
+
}, [
|
|
20728
|
+
cwd,
|
|
20729
|
+
sessionId,
|
|
20730
|
+
tabId,
|
|
20731
|
+
viewerContextId
|
|
20732
|
+
]);
|
|
20733
|
+
import_react.useEffect(() => {
|
|
20734
|
+
const applyTheme = () => {
|
|
20735
|
+
const terminal = terminalRef.current;
|
|
20736
|
+
if (!terminal) return;
|
|
20737
|
+
terminal.options.theme = createTerminalTheme();
|
|
20738
|
+
terminal.options.fontFamily = createTerminalFontFamily();
|
|
20739
|
+
};
|
|
20740
|
+
const observer = new MutationObserver(applyTheme);
|
|
20741
|
+
observer.observe(document.documentElement, {
|
|
20742
|
+
attributeFilter: ["class", "data-pico-theme-mode"],
|
|
20743
|
+
attributes: true
|
|
20744
|
+
});
|
|
20745
|
+
applyTheme();
|
|
20746
|
+
return () => observer.disconnect();
|
|
20747
|
+
}, []);
|
|
20748
|
+
import_react.useEffect(() => {
|
|
20749
|
+
if (!active) {
|
|
20750
|
+
terminalRef.current?.blur();
|
|
20751
|
+
return;
|
|
20752
|
+
}
|
|
20753
|
+
const frame = window.requestAnimationFrame(() => {
|
|
20754
|
+
fitAndResizeRef.current();
|
|
20755
|
+
terminalRef.current?.focus();
|
|
20756
|
+
});
|
|
20757
|
+
return () => window.cancelAnimationFrame(frame);
|
|
20758
|
+
}, [active, status]);
|
|
20759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20760
|
+
"aria-hidden": !selected,
|
|
20761
|
+
"data-terminal-tab": tabId,
|
|
20762
|
+
className: cn("absolute inset-0 min-h-0 w-full overflow-hidden bg-background", selected ? "z-10 opacity-100" : "pointer-events-none z-0 opacity-0"),
|
|
20763
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20764
|
+
ref: terminalElementRef,
|
|
20765
|
+
className: "h-full min-h-0 w-full"
|
|
20766
|
+
})
|
|
20767
|
+
});
|
|
20768
|
+
}
|
|
20769
|
+
function TerminalPanel({ active, className, cwd, onClose, sessionId, showCloseButton = true, viewerContextId }) {
|
|
20770
|
+
const normalizedCwd = cwd?.trim() || "";
|
|
20771
|
+
const scopeKey = `${viewerContextId}:${sessionId ?? "no-session"}:${normalizedCwd}`;
|
|
20772
|
+
const [tabsState, setTabsState] = import_react.useState(() => createTerminalTabsState(scopeKey));
|
|
20773
|
+
const [statusDialogTabId, setStatusDialogTabId] = import_react.useState(null);
|
|
20774
|
+
const tabs = tabsState.scopeKey === scopeKey ? tabsState.tabs : [];
|
|
20775
|
+
const selectedTabId = tabsState.scopeKey === scopeKey ? tabsState.activeTabId ?? tabs[0]?.id ?? null : null;
|
|
20776
|
+
import_react.useEffect(() => {
|
|
20777
|
+
if (tabsState.scopeKey === scopeKey) return;
|
|
20778
|
+
setTabsState(createTerminalTabsState(scopeKey));
|
|
20779
|
+
}, [scopeKey, tabsState.scopeKey]);
|
|
20780
|
+
import_react.useEffect(() => {
|
|
20781
|
+
if (!active || !normalizedCwd || tabs.length > 0 || tabsState.scopeKey !== scopeKey) return;
|
|
20782
|
+
const tab = createTerminalTab();
|
|
20783
|
+
const nextState = {
|
|
20784
|
+
activeTabId: tab.id,
|
|
20785
|
+
scopeKey,
|
|
20786
|
+
tabs: [tab]
|
|
20787
|
+
};
|
|
20788
|
+
rememberTerminalTabsState(nextState);
|
|
20789
|
+
setTabsState(nextState);
|
|
20790
|
+
}, [
|
|
20791
|
+
active,
|
|
20792
|
+
normalizedCwd,
|
|
20793
|
+
scopeKey,
|
|
20794
|
+
tabs.length,
|
|
20795
|
+
tabsState.scopeKey
|
|
20796
|
+
]);
|
|
20797
|
+
const activeStatus = tabs.find((tab) => tab.id === selectedTabId)?.status ?? { type: "idle" };
|
|
20798
|
+
const activeError = activeStatus.type === "error" ? activeStatus.message : void 0;
|
|
20799
|
+
const statusDialogTab = tabs.find((tab) => tab.id === statusDialogTabId);
|
|
20800
|
+
const statusDialogTabIndex = statusDialogTab ? tabs.indexOf(statusDialogTab) : 0;
|
|
20801
|
+
const requestOptions = sessionId ? {
|
|
20802
|
+
contextId: viewerContextId,
|
|
20803
|
+
sessionId
|
|
20804
|
+
} : { contextId: viewerContextId };
|
|
20805
|
+
const addTerminalTab = () => {
|
|
20806
|
+
if (!normalizedCwd) return;
|
|
20807
|
+
const tab = createTerminalTab();
|
|
20808
|
+
setTabsState((current) => {
|
|
20809
|
+
const nextState = current.scopeKey !== scopeKey ? {
|
|
20810
|
+
activeTabId: tab.id,
|
|
20811
|
+
scopeKey,
|
|
20812
|
+
tabs: [tab]
|
|
20813
|
+
} : {
|
|
20814
|
+
...current,
|
|
20815
|
+
activeTabId: tab.id,
|
|
20816
|
+
tabs: [...current.tabs, tab]
|
|
20817
|
+
};
|
|
20818
|
+
rememberTerminalTabsState(nextState);
|
|
20819
|
+
return nextState;
|
|
20820
|
+
});
|
|
20821
|
+
};
|
|
20822
|
+
const closeServerTerminal = (terminalId) => {
|
|
20823
|
+
if (!terminalId) return;
|
|
20824
|
+
fetchJson(buildRequestUrl(`/api/terminal/${encodeURIComponent(terminalId)}/close`, requestOptions), { method: "POST" }).catch(() => {});
|
|
20825
|
+
};
|
|
20826
|
+
const closeTerminalTab = (tabId) => {
|
|
20827
|
+
if (tabs.length <= 0) return;
|
|
20828
|
+
closeServerTerminal(tabs.find((tab) => tab.id === tabId)?.terminalId ?? null);
|
|
20829
|
+
setTabsState((current) => {
|
|
20830
|
+
if (current.scopeKey !== scopeKey || current.tabs.length <= 0) return current;
|
|
20831
|
+
const closingIndex = current.tabs.findIndex((tab) => tab.id === tabId);
|
|
20832
|
+
const nextTabs = current.tabs.filter((tab) => tab.id !== tabId);
|
|
20833
|
+
const nextActiveTabId = current.activeTabId === tabId ? nextTabs[Math.min(Math.max(closingIndex, 0), nextTabs.length - 1)]?.id ?? null : current.activeTabId;
|
|
20834
|
+
const nextState = {
|
|
20835
|
+
...current,
|
|
20836
|
+
activeTabId: nextActiveTabId,
|
|
20837
|
+
tabs: nextTabs
|
|
20838
|
+
};
|
|
20839
|
+
rememberTerminalTabsState(nextState);
|
|
20840
|
+
return nextState;
|
|
20841
|
+
});
|
|
20842
|
+
};
|
|
20843
|
+
const updateTabStatus = (tabId, status) => {
|
|
20844
|
+
setTabsState((current) => {
|
|
20845
|
+
if (current.scopeKey !== scopeKey) return current;
|
|
20846
|
+
return {
|
|
20847
|
+
...current,
|
|
20848
|
+
tabs: current.tabs.map((tab) => tab.id === tabId ? {
|
|
20849
|
+
...tab,
|
|
20850
|
+
status
|
|
20851
|
+
} : tab)
|
|
20852
|
+
};
|
|
20853
|
+
});
|
|
20854
|
+
};
|
|
20855
|
+
const updateTabTerminalId = (tabId, terminalId) => {
|
|
20856
|
+
setTabsState((current) => {
|
|
20857
|
+
if (current.scopeKey !== scopeKey) return current;
|
|
20858
|
+
return {
|
|
20859
|
+
...current,
|
|
20860
|
+
tabs: current.tabs.map((tab) => tab.id === tabId ? {
|
|
20861
|
+
...tab,
|
|
20862
|
+
terminalId
|
|
20863
|
+
} : tab)
|
|
20864
|
+
};
|
|
20865
|
+
});
|
|
20866
|
+
};
|
|
20867
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
20868
|
+
"data-terminal-panel": "true",
|
|
20869
|
+
className: cn("pico-terminal-panel flex h-full min-h-0 w-full min-w-0 flex-col bg-background", className),
|
|
20870
|
+
onKeyDownCapture: (event) => {
|
|
20871
|
+
if (!isTerminalToggleEvent(event) || !onClose) return;
|
|
20872
|
+
event.preventDefault();
|
|
20873
|
+
event.stopPropagation();
|
|
20874
|
+
event.nativeEvent.stopImmediatePropagation();
|
|
20875
|
+
onClose();
|
|
20876
|
+
},
|
|
20877
|
+
children: [
|
|
20878
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20879
|
+
className: "flex min-h-10 shrink-0 items-center gap-2 border-b border-border/70 px-2",
|
|
20880
|
+
children: [
|
|
20881
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20882
|
+
className: "hidden max-w-56 min-w-0 flex-col gap-0 px-1 sm:flex",
|
|
20883
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20884
|
+
className: "truncate text-xs font-medium",
|
|
20885
|
+
children: "Terminal"
|
|
20886
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20887
|
+
className: "flex min-w-0 items-center gap-1 truncate text-[11px] text-muted-foreground",
|
|
20888
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalStatusDot, { status: activeStatus }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
20889
|
+
className: "truncate",
|
|
20890
|
+
children: normalizedCwd ? formatDisplayPath$1(normalizedCwd) : "No cwd"
|
|
20891
|
+
})]
|
|
20892
|
+
})]
|
|
20070
20893
|
}),
|
|
20071
|
-
|
|
20072
|
-
|
|
20073
|
-
|
|
20074
|
-
|
|
20894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20895
|
+
className: "flex min-w-0 flex-1 items-center gap-1 overflow-x-auto py-1",
|
|
20896
|
+
children: [tabs.map((tab, index) => {
|
|
20897
|
+
const selected = tab.id === selectedTabId;
|
|
20898
|
+
const label = terminalTabLabel(tab, index);
|
|
20899
|
+
const statusText = terminalStatusText(tab.status);
|
|
20900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20901
|
+
className: cn("group flex h-7 max-w-48 shrink-0 items-center overflow-hidden rounded-md border text-xs", selected ? "border-border bg-muted text-foreground" : "border-transparent bg-transparent text-muted-foreground hover:bg-muted/60 hover:text-foreground"),
|
|
20902
|
+
children: [
|
|
20903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20904
|
+
title: `${label} · ${statusText}`,
|
|
20905
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
20906
|
+
type: "button",
|
|
20907
|
+
className: "flex h-full w-7 shrink-0 items-center justify-center outline-hidden focus-visible:ring-1 focus-visible:ring-ring",
|
|
20908
|
+
"aria-label": `Show ${label} status`,
|
|
20909
|
+
onClick: (event) => {
|
|
20910
|
+
event.stopPropagation();
|
|
20911
|
+
setStatusDialogTabId(tab.id);
|
|
20912
|
+
},
|
|
20913
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalStatusDot, { status: tab.status })
|
|
20914
|
+
})
|
|
20915
|
+
}),
|
|
20916
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20917
|
+
title: `${label} · ${statusText}`,
|
|
20918
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
20919
|
+
type: "button",
|
|
20920
|
+
className: "flex h-full min-w-0 flex-1 items-center px-1 text-left outline-hidden focus-visible:ring-1 focus-visible:ring-ring",
|
|
20921
|
+
onClick: () => {
|
|
20922
|
+
setTabsState((current) => {
|
|
20923
|
+
if (current.scopeKey !== scopeKey) return current;
|
|
20924
|
+
const nextState = {
|
|
20925
|
+
...current,
|
|
20926
|
+
activeTabId: tab.id
|
|
20927
|
+
};
|
|
20928
|
+
rememberTerminalTabsState(nextState);
|
|
20929
|
+
return nextState;
|
|
20930
|
+
});
|
|
20931
|
+
},
|
|
20932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
20933
|
+
className: "truncate",
|
|
20934
|
+
children: label
|
|
20935
|
+
})
|
|
20936
|
+
})
|
|
20937
|
+
}),
|
|
20938
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20939
|
+
title: `Close ${label}`,
|
|
20940
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
|
|
20941
|
+
type: "button",
|
|
20942
|
+
className: "flex h-full w-6 shrink-0 items-center justify-center text-muted-foreground opacity-70 outline-hidden group-hover:opacity-100 hover:bg-muted hover:text-foreground focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-30",
|
|
20943
|
+
"aria-label": `Close ${label}`,
|
|
20944
|
+
onClick: (event) => {
|
|
20945
|
+
event.stopPropagation();
|
|
20946
|
+
closeTerminalTab(tab.id);
|
|
20947
|
+
},
|
|
20948
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
|
|
20949
|
+
})
|
|
20950
|
+
})
|
|
20951
|
+
]
|
|
20952
|
+
}, tab.id);
|
|
20953
|
+
}), normalizedCwd ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20954
|
+
title: "New terminal tab",
|
|
20955
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
20956
|
+
size: "icon",
|
|
20957
|
+
variant: "ghost",
|
|
20958
|
+
className: "size-7 shrink-0",
|
|
20959
|
+
"aria-label": "New terminal tab",
|
|
20960
|
+
onClick: addTerminalTab,
|
|
20961
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "size-4" })
|
|
20962
|
+
})
|
|
20963
|
+
}) : null]
|
|
20964
|
+
}),
|
|
20965
|
+
activeError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20966
|
+
title: activeError,
|
|
20967
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
20968
|
+
className: "hidden max-w-48 truncate text-[11px] text-destructive sm:inline",
|
|
20969
|
+
children: activeError
|
|
20970
|
+
})
|
|
20971
|
+
}) : null,
|
|
20972
|
+
onClose && showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20973
|
+
title: "Hide terminal",
|
|
20974
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
20975
|
+
size: "icon",
|
|
20976
|
+
variant: "ghost",
|
|
20977
|
+
className: "size-8 shrink-0",
|
|
20978
|
+
"aria-label": "Hide terminal",
|
|
20979
|
+
onClick: onClose,
|
|
20980
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, {})
|
|
20981
|
+
})
|
|
20982
|
+
}) : null
|
|
20983
|
+
]
|
|
20984
|
+
}),
|
|
20985
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalStatusDialog, {
|
|
20986
|
+
cwd: normalizedCwd,
|
|
20987
|
+
index: statusDialogTabIndex,
|
|
20988
|
+
open: statusDialogTab !== void 0,
|
|
20989
|
+
tab: statusDialogTab,
|
|
20990
|
+
onOpenChange: (open) => {
|
|
20991
|
+
if (!open) setStatusDialogTabId(null);
|
|
20992
|
+
}
|
|
20993
|
+
}),
|
|
20994
|
+
normalizedCwd ? tabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20995
|
+
className: "relative min-h-0 flex-1 overflow-hidden bg-background",
|
|
20996
|
+
children: tabs.map((tab) => {
|
|
20997
|
+
const selected = tab.id === selectedTabId;
|
|
20998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalTabPane, {
|
|
20999
|
+
active: active && selected,
|
|
21000
|
+
cwd: normalizedCwd,
|
|
21001
|
+
onStatusChange: updateTabStatus,
|
|
21002
|
+
onTerminalIdChange: updateTabTerminalId,
|
|
21003
|
+
selected,
|
|
21004
|
+
sessionId,
|
|
21005
|
+
tabId: tab.id,
|
|
21006
|
+
viewerContextId
|
|
21007
|
+
}, tab.id);
|
|
20075
21008
|
})
|
|
20076
|
-
|
|
20077
|
-
|
|
21009
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
21010
|
+
className: "flex min-h-0 flex-1 flex-col items-center justify-center gap-3 p-6 text-sm text-muted-foreground",
|
|
21011
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: "No terminal tabs are open." }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
|
|
21012
|
+
size: "sm",
|
|
21013
|
+
variant: "outline",
|
|
21014
|
+
onClick: addTerminalTab,
|
|
21015
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Plus, { className: "size-4" }), "New terminal tab"]
|
|
21016
|
+
})]
|
|
21017
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21018
|
+
className: "flex min-h-0 flex-1 items-center justify-center p-6 text-sm text-muted-foreground",
|
|
21019
|
+
children: "Open a session before starting a terminal."
|
|
21020
|
+
})
|
|
21021
|
+
]
|
|
20078
21022
|
});
|
|
20079
21023
|
}
|
|
20080
21024
|
function readStoredRightSidebarActiveTab() {
|
|
@@ -20191,22 +21135,33 @@ function reorderRightSidebarFiles(store, paths) {
|
|
|
20191
21135
|
fileTabs: uniquePaths
|
|
20192
21136
|
}));
|
|
20193
21137
|
}
|
|
21138
|
+
function shallowTerminalSession(left, right) {
|
|
21139
|
+
return left.cwd === right.cwd && left.sessionId === right.sessionId;
|
|
21140
|
+
}
|
|
20194
21141
|
function AppShellTabsList({ sessionStore, viewerContextId }) {
|
|
20195
21142
|
const cwd = useSelector(sessionStore, (sessionState) => sessionState.cwd);
|
|
20196
21143
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TabsList, {
|
|
20197
21144
|
className: "w-full gap-2 rounded-none border-b border-border/70 bg-background p-2 group-data-horizontal/tabs:h-auto md:hidden",
|
|
20198
|
-
children: [
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
|
|
20203
|
-
|
|
20204
|
-
|
|
20205
|
-
|
|
20206
|
-
|
|
20207
|
-
|
|
21145
|
+
children: [
|
|
21146
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, {
|
|
21147
|
+
value: "session",
|
|
21148
|
+
className: "h-8 data-active:bg-muted dark:data-active:bg-muted",
|
|
21149
|
+
children: "Session"
|
|
21150
|
+
}),
|
|
21151
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, {
|
|
21152
|
+
value: "git",
|
|
21153
|
+
className: "h-8 data-active:bg-muted dark:data-active:bg-muted",
|
|
21154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitTabStatusText, {
|
|
21155
|
+
viewerContextId,
|
|
21156
|
+
cwd
|
|
21157
|
+
})
|
|
21158
|
+
}),
|
|
21159
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, {
|
|
21160
|
+
value: "terminal",
|
|
21161
|
+
className: "h-8 data-active:bg-muted dark:data-active:bg-muted",
|
|
21162
|
+
children: "Terminal"
|
|
20208
21163
|
})
|
|
20209
|
-
|
|
21164
|
+
]
|
|
20210
21165
|
});
|
|
20211
21166
|
}
|
|
20212
21167
|
var AppShellGitPanelController = import_react.memo(function AppShellGitPanelController({ active, composerDiffLineComments, onAddDiffLineComment, onCloseAllFiles, onCloseFile, onCloseFilesToRight, onCloseOtherFiles, onOpenFile, onReorderFiles, rightSidebarStore, sessionStore, viewerContextId }) {
|
|
@@ -20285,6 +21240,10 @@ var DESKTOP_DEFAULT_GIT_PANEL_WIDTH = 320;
|
|
|
20285
21240
|
var DESKTOP_MIN_SESSION_WIDTH = 320;
|
|
20286
21241
|
var DESKTOP_MIN_SIDE_PANEL_WIDTH = 260;
|
|
20287
21242
|
var DESKTOP_MAX_STORED_SIDE_PANEL_WIDTH = 1600;
|
|
21243
|
+
var DESKTOP_DEFAULT_TERMINAL_PANEL_HEIGHT = 280;
|
|
21244
|
+
var DESKTOP_MIN_TERMINAL_PANEL_HEIGHT = 160;
|
|
21245
|
+
var DESKTOP_MIN_TOP_PANEL_HEIGHT = 220;
|
|
21246
|
+
var DESKTOP_MAX_STORED_TERMINAL_PANEL_HEIGHT = 1200;
|
|
20288
21247
|
function defaultDesktopSidePanelWidths() {
|
|
20289
21248
|
return {
|
|
20290
21249
|
fileViewWidth: DESKTOP_DEFAULT_FILE_VIEW_WIDTH,
|
|
@@ -20319,6 +21278,18 @@ function storeDesktopSidePanelWidths(widths) {
|
|
|
20319
21278
|
function sameDesktopSidePanelWidths(left, right) {
|
|
20320
21279
|
return left.fileViewWidth === right.fileViewWidth && left.gitPanelWidth === right.gitPanelWidth;
|
|
20321
21280
|
}
|
|
21281
|
+
function clampStoredDesktopTerminalPanelHeight(value) {
|
|
21282
|
+
if (value == null || value === "") return DESKTOP_DEFAULT_TERMINAL_PANEL_HEIGHT;
|
|
21283
|
+
const height = typeof value === "number" ? value : Number(value);
|
|
21284
|
+
if (!Number.isFinite(height)) return DESKTOP_DEFAULT_TERMINAL_PANEL_HEIGHT;
|
|
21285
|
+
return Math.round(Math.min(DESKTOP_MAX_STORED_TERMINAL_PANEL_HEIGHT, Math.max(DESKTOP_MIN_TERMINAL_PANEL_HEIGHT, height)));
|
|
21286
|
+
}
|
|
21287
|
+
function readStoredDesktopTerminalPanelHeight() {
|
|
21288
|
+
return clampStoredDesktopTerminalPanelHeight(safeLocalStorageGetItem(TERMINAL_PANEL_HEIGHT_STORAGE_KEY));
|
|
21289
|
+
}
|
|
21290
|
+
function storeDesktopTerminalPanelHeight(height) {
|
|
21291
|
+
safeLocalStorageSetItem(TERMINAL_PANEL_HEIGHT_STORAGE_KEY, String(clampStoredDesktopTerminalPanelHeight(height)));
|
|
21292
|
+
}
|
|
20322
21293
|
function clampDesktopPanelSize(value, min, max) {
|
|
20323
21294
|
if (!Number.isFinite(value)) return min;
|
|
20324
21295
|
if (max <= min) return Math.max(0, max);
|
|
@@ -20442,21 +21413,106 @@ function AppShellDesktopResizeHandle({ label, max, min, onResize, onResizeEnd, o
|
|
|
20442
21413
|
}
|
|
20443
21414
|
});
|
|
20444
21415
|
}
|
|
21416
|
+
function AppShellDesktopVerticalResizeHandle({ label, max, min, onResize, onResizeEnd, onResizeStart, size }) {
|
|
21417
|
+
const propsRef = useLatestRef({
|
|
21418
|
+
max,
|
|
21419
|
+
min,
|
|
21420
|
+
onResize,
|
|
21421
|
+
onResizeEnd,
|
|
21422
|
+
onResizeStart,
|
|
21423
|
+
size
|
|
21424
|
+
});
|
|
21425
|
+
const [verticalResizeCursor, setVerticalResizeCursor] = import_react.useState("row-resize");
|
|
21426
|
+
const [resizeTargetMinimumSize, setResizeTargetMinimumSize] = import_react.useState(10);
|
|
21427
|
+
import_react.useEffect(() => {
|
|
21428
|
+
const updateResizeTarget = () => {
|
|
21429
|
+
setResizeTargetMinimumSize(getSidebarResizeTargetMinimumSize());
|
|
21430
|
+
};
|
|
21431
|
+
const coarsePointerQuery = window.matchMedia("(pointer:coarse)");
|
|
21432
|
+
setVerticalResizeCursor(getSidebarVerticalResizeCursor());
|
|
21433
|
+
updateResizeTarget();
|
|
21434
|
+
coarsePointerQuery.addEventListener("change", updateResizeTarget);
|
|
21435
|
+
return () => {
|
|
21436
|
+
coarsePointerQuery.removeEventListener("change", updateResizeTarget);
|
|
21437
|
+
};
|
|
21438
|
+
}, []);
|
|
21439
|
+
const verticalResizeCursorClass = verticalResizeCursor === "ns-resize" ? "cursor-ns-resize" : "cursor-row-resize";
|
|
21440
|
+
const resizeTo = (nextSize) => {
|
|
21441
|
+
const current = propsRef.current;
|
|
21442
|
+
current.onResize(clampDesktopPanelSize(nextSize, current.min, current.max));
|
|
21443
|
+
};
|
|
21444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21445
|
+
role: "separator",
|
|
21446
|
+
"aria-label": label,
|
|
21447
|
+
"aria-orientation": "horizontal",
|
|
21448
|
+
tabIndex: 0,
|
|
21449
|
+
style: {
|
|
21450
|
+
"--resize-target-height": `${resizeTargetMinimumSize}px`,
|
|
21451
|
+
cursor: verticalResizeCursor
|
|
21452
|
+
},
|
|
21453
|
+
className: `absolute inset-x-0 top-0 z-20 h-(--resize-target-height) -translate-y-1/2 touch-none bg-transparent outline-hidden after:absolute after:inset-x-0 after:top-1/2 after:h-px after:bg-transparent focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 ${resizeRailPrimaryInteractiveClass} ${verticalResizeCursorClass}`,
|
|
21454
|
+
onKeyDown: (event) => {
|
|
21455
|
+
if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
|
|
21456
|
+
event.preventDefault();
|
|
21457
|
+
const delta = event.shiftKey ? 48 : 16;
|
|
21458
|
+
resizeTo(propsRef.current.size + (event.key === "ArrowUp" ? delta : -delta));
|
|
21459
|
+
},
|
|
21460
|
+
onPointerDown: (event) => {
|
|
21461
|
+
if (event.button !== 0) return;
|
|
21462
|
+
event.preventDefault();
|
|
21463
|
+
const current = propsRef.current;
|
|
21464
|
+
const startY = event.clientY;
|
|
21465
|
+
const startSize = current.size;
|
|
21466
|
+
const cursor = getSidebarVerticalResizeCursor();
|
|
21467
|
+
const previousCursor = document.body.style.cursor;
|
|
21468
|
+
const previousUserSelect = document.body.style.userSelect;
|
|
21469
|
+
const cleanupGlobalResizeCursor = installGlobalResizeCursor(cursor);
|
|
21470
|
+
current.onResizeStart?.();
|
|
21471
|
+
Object.assign(document.body.style, {
|
|
21472
|
+
userSelect: "none",
|
|
21473
|
+
cursor
|
|
21474
|
+
});
|
|
21475
|
+
const handlePointerMove = (moveEvent) => {
|
|
21476
|
+
resizeTo(startSize + startY - moveEvent.clientY);
|
|
21477
|
+
};
|
|
21478
|
+
const handlePointerUp = () => {
|
|
21479
|
+
cleanupGlobalResizeCursor();
|
|
21480
|
+
Object.assign(document.body.style, {
|
|
21481
|
+
userSelect: previousUserSelect,
|
|
21482
|
+
cursor: previousCursor
|
|
21483
|
+
});
|
|
21484
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
21485
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
21486
|
+
document.removeEventListener("pointercancel", handlePointerUp);
|
|
21487
|
+
propsRef.current.onResizeEnd?.();
|
|
21488
|
+
};
|
|
21489
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
21490
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
21491
|
+
document.addEventListener("pointercancel", handlePointerUp);
|
|
21492
|
+
}
|
|
21493
|
+
});
|
|
21494
|
+
}
|
|
20445
21495
|
function AppShellTabsController(props) {
|
|
20446
21496
|
return useAppShellTabsControllerView(props);
|
|
20447
21497
|
}
|
|
20448
|
-
function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTurn, composerDiffLineComments, composerPanelRef, contextUsageStore, conversationFrameRef, conversationItemsStore, defaultNewSessionDirectory, displaySettingsStore, fileInputRef, gitPanelOpen, hiddenThinkingPreviewStore, isSessionViewLoading, isSubmitting, isMobile, newSessionDirectoryOptions, onCancelCompaction, onCreateSession, onOpenAddDirectoryDialog, onCloseAllFileViewTabs, onCloseFileViewTab, onCloseFileViewTabsToRight, onCloseOtherFileViewTabs, onAddDiffLineComment, onOpenFileViewTab, onReorderFileViewTabs, onValueChange, rightSidebarStore, sessionStore, store, viewerContextId, workingStateStore }) {
|
|
21498
|
+
function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTurn, composerDiffLineComments, composerPanelRef, contextUsageStore, conversationFrameRef, conversationItemsStore, defaultNewSessionDirectory, displaySettingsStore, fileInputRef, gitPanelOpen, terminalPanelOpen, hiddenThinkingPreviewStore, isSessionViewLoading, isSubmitting, isMobile, newSessionDirectoryOptions, onCancelCompaction, onCreateSession, onOpenAddDirectoryDialog, onCloseAllFileViewTabs, onCloseFileViewTab, onCloseFileViewTabsToRight, onCloseOtherFileViewTabs, onCloseTerminalPanel, onAddDiffLineComment, onOpenFileViewTab, onReorderFileViewTabs, onValueChange, rightSidebarStore, sessionStore, store, viewerContextId, workingStateStore }) {
|
|
20449
21499
|
const currentTab = useSelector(appUiStore, (state) => state.currentTab);
|
|
20450
21500
|
const isDraftSession = useSelector(sessionStore, (sessionState) => sessionState.draft);
|
|
21501
|
+
const terminalSession = useSelector(sessionStore, (sessionState) => ({
|
|
21502
|
+
cwd: sessionState.cwd,
|
|
21503
|
+
sessionId: sessionState.sessionId
|
|
21504
|
+
}), { compare: shallowTerminalSession });
|
|
20451
21505
|
const showTabsList = isMobile || !isDraftSession || isSessionViewLoading;
|
|
20452
|
-
const sessionVisibleClassName = currentTab === "
|
|
21506
|
+
const sessionVisibleClassName = currentTab === "session" ? "flex min-h-0 flex-1 flex-col" : "hidden min-h-0 flex-1 flex-col md:flex";
|
|
20453
21507
|
const mobileGitClassName = currentTab === "git" ? "min-h-0 flex-1 overflow-hidden md:hidden" : "hidden";
|
|
21508
|
+
const mobileTerminalClassName = currentTab === "terminal" ? "min-h-0 flex-1 overflow-hidden md:hidden" : "hidden";
|
|
20454
21509
|
const rightSidebarHasVisibleFiles = useSelector(rightSidebarStore, selectRightSidebarHasVisibleFiles);
|
|
20455
21510
|
const desktopGitPanelOpen = !isMobile && gitPanelOpen;
|
|
20456
21511
|
const desktopFileViewOpen = !isMobile && gitPanelOpen && rightSidebarHasVisibleFiles;
|
|
20457
21512
|
const desktopSideWorkspaceOpen = desktopFileViewOpen || desktopGitPanelOpen;
|
|
20458
21513
|
const desktopLayoutRef = import_react.useRef(null);
|
|
20459
21514
|
const [desktopLayoutWidth, setDesktopLayoutWidth] = import_react.useState(0);
|
|
21515
|
+
const [desktopLayoutHeight, setDesktopLayoutHeight] = import_react.useState(0);
|
|
20460
21516
|
const [desktopSidePanelWidths, setDesktopSidePanelWidthsState] = import_react.useState(() => defaultDesktopSidePanelWidths());
|
|
20461
21517
|
const desktopSidePanelWidthsLoadedRef = import_react.useRef(false);
|
|
20462
21518
|
const desktopSidePanelWidthsRef = import_react.useRef(desktopSidePanelWidths);
|
|
@@ -20484,12 +21540,30 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20484
21540
|
}));
|
|
20485
21541
|
};
|
|
20486
21542
|
const [desktopGitPanelMounted, setDesktopGitPanelMounted] = import_react.useState(desktopGitPanelOpen);
|
|
21543
|
+
const [desktopTerminalPanelHeight, setDesktopTerminalPanelHeightState] = import_react.useState(() => DESKTOP_DEFAULT_TERMINAL_PANEL_HEIGHT);
|
|
21544
|
+
const desktopTerminalPanelHeightLoadedRef = import_react.useRef(false);
|
|
21545
|
+
const desktopTerminalPanelHeightRef = import_react.useRef(desktopTerminalPanelHeight);
|
|
21546
|
+
desktopTerminalPanelHeightRef.current = desktopTerminalPanelHeight;
|
|
21547
|
+
const [desktopTerminalPanelMounted, setDesktopTerminalPanelMounted] = import_react.useState(!isMobile && terminalPanelOpen);
|
|
20487
21548
|
const [desktopPanelResizing, setDesktopPanelResizing] = import_react.useState(false);
|
|
21549
|
+
const [desktopTerminalResizing, setDesktopTerminalResizing] = import_react.useState(false);
|
|
21550
|
+
const setDesktopTerminalPanelHeight = (action) => {
|
|
21551
|
+
const current = desktopTerminalPanelHeightRef.current;
|
|
21552
|
+
const next = clampStoredDesktopTerminalPanelHeight(applyStoreAction(current, action));
|
|
21553
|
+
if (current === next) return;
|
|
21554
|
+
desktopTerminalPanelHeightRef.current = next;
|
|
21555
|
+
setDesktopTerminalPanelHeightState(next);
|
|
21556
|
+
if (desktopTerminalPanelHeightLoadedRef.current) storeDesktopTerminalPanelHeight(next);
|
|
21557
|
+
};
|
|
20488
21558
|
import_react.useEffect(() => {
|
|
20489
21559
|
const storedWidths = readStoredDesktopSidePanelWidths();
|
|
21560
|
+
const storedTerminalPanelHeight = readStoredDesktopTerminalPanelHeight();
|
|
20490
21561
|
desktopSidePanelWidthsLoadedRef.current = true;
|
|
21562
|
+
desktopTerminalPanelHeightLoadedRef.current = true;
|
|
20491
21563
|
desktopSidePanelWidthsRef.current = storedWidths;
|
|
21564
|
+
desktopTerminalPanelHeightRef.current = storedTerminalPanelHeight;
|
|
20492
21565
|
setDesktopSidePanelWidthsState((current) => sameDesktopSidePanelWidths(current, storedWidths) ? current : storedWidths);
|
|
21566
|
+
setDesktopTerminalPanelHeightState((current) => current === storedTerminalPanelHeight ? current : storedTerminalPanelHeight);
|
|
20493
21567
|
}, []);
|
|
20494
21568
|
const sessionPane = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20495
21569
|
className: "flex h-full min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
|
|
@@ -20517,7 +21591,7 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20517
21591
|
viewerContextId,
|
|
20518
21592
|
workingStateStore
|
|
20519
21593
|
})
|
|
20520
|
-
}), isMobile ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21594
|
+
}), isMobile ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
20521
21595
|
className: mobileGitClassName,
|
|
20522
21596
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellGitPanelController, {
|
|
20523
21597
|
viewerContextId,
|
|
@@ -20533,32 +21607,50 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20533
21607
|
onOpenFile: onOpenFileViewTab,
|
|
20534
21608
|
onReorderFiles: onReorderFileViewTabs
|
|
20535
21609
|
})
|
|
20536
|
-
})
|
|
21610
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21611
|
+
className: mobileTerminalClassName,
|
|
21612
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalPanel, {
|
|
21613
|
+
active: currentTab === "terminal",
|
|
21614
|
+
cwd: terminalSession.cwd,
|
|
21615
|
+
onClose: onCloseTerminalPanel,
|
|
21616
|
+
sessionId: terminalSession.sessionId,
|
|
21617
|
+
showCloseButton: false,
|
|
21618
|
+
viewerContextId
|
|
21619
|
+
})
|
|
21620
|
+
})] }) : null]
|
|
20537
21621
|
});
|
|
20538
21622
|
import_react.useLayoutEffect(() => {
|
|
20539
21623
|
if (isMobile) {
|
|
20540
21624
|
setDesktopGitPanelMounted(false);
|
|
21625
|
+
setDesktopTerminalPanelMounted(false);
|
|
20541
21626
|
return;
|
|
20542
21627
|
}
|
|
20543
21628
|
if (desktopSideWorkspaceOpen) setDesktopGitPanelMounted(true);
|
|
20544
|
-
|
|
21629
|
+
if (terminalPanelOpen) setDesktopTerminalPanelMounted(true);
|
|
21630
|
+
}, [
|
|
21631
|
+
desktopSideWorkspaceOpen,
|
|
21632
|
+
isMobile,
|
|
21633
|
+
terminalPanelOpen
|
|
21634
|
+
]);
|
|
20545
21635
|
import_react.useLayoutEffect(() => {
|
|
20546
21636
|
if (isMobile) return;
|
|
20547
21637
|
const element = desktopLayoutRef.current;
|
|
20548
21638
|
if (!element) return;
|
|
20549
|
-
const
|
|
21639
|
+
const updateSize = () => {
|
|
20550
21640
|
setDesktopLayoutWidth(element.clientWidth);
|
|
21641
|
+
setDesktopLayoutHeight(element.clientHeight);
|
|
20551
21642
|
};
|
|
20552
|
-
|
|
21643
|
+
updateSize();
|
|
20553
21644
|
if (typeof ResizeObserver === "undefined") {
|
|
20554
|
-
window.addEventListener("resize",
|
|
20555
|
-
return () => window.removeEventListener("resize",
|
|
21645
|
+
window.addEventListener("resize", updateSize);
|
|
21646
|
+
return () => window.removeEventListener("resize", updateSize);
|
|
20556
21647
|
}
|
|
20557
|
-
const observer = new ResizeObserver(
|
|
21648
|
+
const observer = new ResizeObserver(updateSize);
|
|
20558
21649
|
observer.observe(element);
|
|
20559
21650
|
return () => observer.disconnect();
|
|
20560
21651
|
}, [isMobile]);
|
|
20561
21652
|
const desktopAvailableWidth = desktopLayoutWidth || (typeof window === "undefined" ? 1200 : window.innerWidth);
|
|
21653
|
+
const desktopAvailableHeight = desktopLayoutHeight || (typeof window === "undefined" ? 800 : window.innerHeight);
|
|
20562
21654
|
const desktopGitPanelRendered = desktopSideWorkspaceOpen || desktopGitPanelMounted || desktopGitPanelOpen;
|
|
20563
21655
|
const desktopFittedWidths = fitDesktopSidePanelWidths({
|
|
20564
21656
|
availableWidth: desktopAvailableWidth,
|
|
@@ -20569,14 +21661,25 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20569
21661
|
});
|
|
20570
21662
|
const desktopSideWorkspaceRendered = desktopSideWorkspaceOpen || desktopGitPanelMounted;
|
|
20571
21663
|
const desktopSideWorkspaceWidth = desktopSideWorkspaceOpen ? desktopFittedWidths.sideWidth : 0;
|
|
20572
|
-
const
|
|
20573
|
-
const
|
|
21664
|
+
const desktopTerminalOpen = !isMobile && terminalPanelOpen;
|
|
21665
|
+
const desktopTerminalRendered = desktopTerminalOpen || desktopTerminalPanelMounted;
|
|
21666
|
+
const desktopTerminalMaxHeight = Math.max(DESKTOP_MIN_TERMINAL_PANEL_HEIGHT, desktopAvailableHeight - DESKTOP_MIN_TOP_PANEL_HEIGHT);
|
|
21667
|
+
const desktopFittedTerminalPanelHeight = clampDesktopPanelSize(desktopTerminalPanelHeight, Math.min(DESKTOP_MIN_TERMINAL_PANEL_HEIGHT, desktopTerminalMaxHeight), desktopTerminalMaxHeight);
|
|
21668
|
+
const desktopTerminalVisibleHeight = desktopTerminalOpen ? desktopFittedTerminalPanelHeight : 0;
|
|
21669
|
+
const desktopTransitionClassName = !desktopPanelResizing && !desktopTerminalResizing ? "transition-[width,height] duration-200 ease-linear" : "";
|
|
21670
|
+
const desktopPanelGroupClassName = "relative flex min-h-0 w-full shrink-0 overflow-hidden";
|
|
20574
21671
|
const desktopResizeStart = () => {
|
|
20575
21672
|
setDesktopPanelResizing(true);
|
|
20576
21673
|
};
|
|
20577
21674
|
const desktopResizeEnd = () => {
|
|
20578
21675
|
setDesktopPanelResizing(false);
|
|
20579
21676
|
};
|
|
21677
|
+
const desktopTerminalResizeStart = () => {
|
|
21678
|
+
setDesktopTerminalResizing(true);
|
|
21679
|
+
};
|
|
21680
|
+
const desktopTerminalResizeEnd = () => {
|
|
21681
|
+
setDesktopTerminalResizing(false);
|
|
21682
|
+
};
|
|
20580
21683
|
const desktopSideWorkspaceMaxWidth = Math.max(0, desktopAvailableWidth - DESKTOP_MIN_SESSION_WIDTH);
|
|
20581
21684
|
const setDesktopSideWorkspaceWidth = (nextSize) => {
|
|
20582
21685
|
if (!desktopFileViewOpen) {
|
|
@@ -20585,6 +21688,9 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20585
21688
|
}
|
|
20586
21689
|
setDesktopFileViewWidth(Math.max(DESKTOP_MIN_SIDE_PANEL_WIDTH, nextSize - desktopGitPanelWidth));
|
|
20587
21690
|
};
|
|
21691
|
+
const setDesktopTerminalHeight = (nextSize) => {
|
|
21692
|
+
setDesktopTerminalPanelHeight(clampDesktopPanelSize(nextSize, Math.min(DESKTOP_MIN_TERMINAL_PANEL_HEIGHT, desktopTerminalMaxHeight), desktopTerminalMaxHeight));
|
|
21693
|
+
};
|
|
20588
21694
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Tabs$1, {
|
|
20589
21695
|
value: currentTab,
|
|
20590
21696
|
onValueChange,
|
|
@@ -20597,54 +21703,83 @@ function useAppShellTabsControllerView({ actionsRef, appUiStore, awaitingFirstTu
|
|
|
20597
21703
|
children: sessionPane
|
|
20598
21704
|
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20599
21705
|
ref: desktopLayoutRef,
|
|
20600
|
-
className:
|
|
20601
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
|
|
20608
|
-
|
|
20609
|
-
|
|
20610
|
-
|
|
20611
|
-
|
|
20612
|
-
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
className: `relative h-full min-h-0 min-w-0 shrink-0 overflow-visible ${desktopTransitionClassName}`,
|
|
21706
|
+
className: "flex min-h-0 flex-1 flex-col overflow-hidden",
|
|
21707
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
21708
|
+
className: desktopPanelGroupClassName,
|
|
21709
|
+
style: { height: desktopTerminalOpen ? `calc(100% - ${desktopTerminalVisibleHeight}px)` : "100%" },
|
|
21710
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21711
|
+
"data-desktop-panel": "session",
|
|
21712
|
+
className: `h-full min-h-0 min-w-0 shrink-0 overflow-hidden max-md:w-full! ${desktopTransitionClassName}`,
|
|
21713
|
+
style: { width: desktopSideWorkspaceOpen ? `calc(100% - ${desktopSideWorkspaceWidth}px)` : "100%" },
|
|
21714
|
+
children: sessionPane
|
|
21715
|
+
}), desktopSideWorkspaceRendered ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("aside", {
|
|
21716
|
+
"aria-label": "Desktop side workspace",
|
|
21717
|
+
"aria-hidden": !desktopSideWorkspaceOpen,
|
|
21718
|
+
"data-state": desktopSideWorkspaceOpen ? "open" : "closed",
|
|
21719
|
+
"data-desktop-panel": "side-workspace",
|
|
21720
|
+
className: `hidden h-full min-h-0 min-w-0 shrink-0 overflow-visible bg-background data-[state=closed]:pointer-events-none md:flex ${desktopTransitionClassName}`,
|
|
20616
21721
|
style: { width: `${desktopSideWorkspaceWidth}px` },
|
|
20617
|
-
children:
|
|
20618
|
-
|
|
20619
|
-
|
|
20620
|
-
|
|
20621
|
-
|
|
20622
|
-
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
|
|
20626
|
-
|
|
20627
|
-
|
|
20628
|
-
|
|
20629
|
-
|
|
20630
|
-
|
|
20631
|
-
|
|
20632
|
-
|
|
20633
|
-
|
|
20634
|
-
|
|
20635
|
-
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20640
|
-
|
|
20641
|
-
|
|
20642
|
-
|
|
21722
|
+
children: desktopGitPanelRendered ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
21723
|
+
"data-desktop-panel": "git",
|
|
21724
|
+
className: `relative h-full min-h-0 min-w-0 shrink-0 overflow-visible ${desktopTransitionClassName}`,
|
|
21725
|
+
style: { width: `${desktopSideWorkspaceWidth}px` },
|
|
21726
|
+
children: [desktopGitPanelOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellDesktopResizeHandle, {
|
|
21727
|
+
label: "Resize right sidebar",
|
|
21728
|
+
min: Math.min(DESKTOP_MIN_SIDE_PANEL_WIDTH, desktopSideWorkspaceMaxWidth),
|
|
21729
|
+
max: desktopSideWorkspaceMaxWidth,
|
|
21730
|
+
size: desktopSideWorkspaceWidth,
|
|
21731
|
+
onResize: setDesktopSideWorkspaceWidth,
|
|
21732
|
+
onResizeStart: desktopResizeStart,
|
|
21733
|
+
onResizeEnd: desktopResizeEnd
|
|
21734
|
+
}) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21735
|
+
className: "h-full min-h-0 min-w-0 overflow-hidden",
|
|
21736
|
+
children: desktopGitPanelRendered ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellDesktopGitPanel, {
|
|
21737
|
+
viewerContextId,
|
|
21738
|
+
sessionStore,
|
|
21739
|
+
active: desktopGitPanelOpen,
|
|
21740
|
+
composerDiffLineComments,
|
|
21741
|
+
rightSidebarStore,
|
|
21742
|
+
onAddDiffLineComment,
|
|
21743
|
+
onCloseAllFiles: onCloseAllFileViewTabs,
|
|
21744
|
+
onCloseFile: onCloseFileViewTab,
|
|
21745
|
+
onCloseFilesToRight: onCloseFileViewTabsToRight,
|
|
21746
|
+
onCloseOtherFiles: onCloseOtherFileViewTabs,
|
|
21747
|
+
onOpenFile: onOpenFileViewTab,
|
|
21748
|
+
onReorderFiles: onReorderFileViewTabs
|
|
21749
|
+
}) : null
|
|
21750
|
+
})]
|
|
21751
|
+
}) : null
|
|
21752
|
+
}) : null]
|
|
21753
|
+
}), desktopTerminalRendered ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", {
|
|
21754
|
+
"aria-label": "Terminal",
|
|
21755
|
+
"aria-hidden": !desktopTerminalOpen,
|
|
21756
|
+
"data-state": desktopTerminalOpen ? "open" : "closed",
|
|
21757
|
+
"data-desktop-panel": "terminal",
|
|
21758
|
+
className: `relative hidden min-h-0 w-full shrink-0 overflow-visible border-t border-border/70 bg-background data-[state=closed]:pointer-events-none data-[state=closed]:border-transparent md:flex ${desktopTransitionClassName}`,
|
|
21759
|
+
style: { height: `${desktopTerminalVisibleHeight}px` },
|
|
21760
|
+
children: [desktopTerminalOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppShellDesktopVerticalResizeHandle, {
|
|
21761
|
+
label: "Resize terminal",
|
|
21762
|
+
min: Math.min(DESKTOP_MIN_TERMINAL_PANEL_HEIGHT, desktopTerminalMaxHeight),
|
|
21763
|
+
max: desktopTerminalMaxHeight,
|
|
21764
|
+
size: desktopTerminalVisibleHeight,
|
|
21765
|
+
onResize: setDesktopTerminalHeight,
|
|
21766
|
+
onResizeStart: desktopTerminalResizeStart,
|
|
21767
|
+
onResizeEnd: desktopTerminalResizeEnd
|
|
21768
|
+
}) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
21769
|
+
className: "h-full min-h-0 w-full min-w-0 overflow-hidden",
|
|
21770
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TerminalPanel, {
|
|
21771
|
+
active: desktopTerminalOpen,
|
|
21772
|
+
cwd: terminalSession.cwd,
|
|
21773
|
+
onClose: onCloseTerminalPanel,
|
|
21774
|
+
sessionId: terminalSession.sessionId,
|
|
21775
|
+
viewerContextId
|
|
21776
|
+
})
|
|
21777
|
+
})]
|
|
20643
21778
|
}) : null]
|
|
20644
21779
|
})]
|
|
20645
21780
|
});
|
|
20646
21781
|
}
|
|
20647
|
-
var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ actionsRef, defaultNewSessionDirectory, displaySessionCwd, gitPanelOpen, loadingDisplaySessionTitle, currentSessionPinned, displaySettingsStore, isSessionViewLoading, newSessionDirectoryOptions, onToggleGitPanel, sessionStore, viewerContextId }) {
|
|
21782
|
+
var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ actionsRef, defaultNewSessionDirectory, displaySessionCwd, gitPanelOpen, terminalPanelOpen, loadingDisplaySessionTitle, currentSessionPinned, displaySettingsStore, isSessionViewLoading, newSessionDirectoryOptions, onToggleGitPanel, onToggleTerminalPanel, sessionStore, viewerContextId }) {
|
|
20648
21783
|
const sessionHeaderState = useSelector(sessionStore, (sessionState) => ({
|
|
20649
21784
|
firstMessage: sessionState.firstMessage,
|
|
20650
21785
|
hideThinkingBlock: sessionState.hideThinkingBlock,
|
|
@@ -20653,8 +21788,6 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
|
|
|
20653
21788
|
sessionStreaming: sessionState.streaming
|
|
20654
21789
|
}), { compare: shallowRecordEqual });
|
|
20655
21790
|
const hideToolBlocks = useSelector(displaySettingsStore, (settings) => settings.hideToolBlocks);
|
|
20656
|
-
const { isMobile: sidebarIsMobile, openMobile: sidebarOpenMobile, state: sidebarState } = useSidebar();
|
|
20657
|
-
const showCollapsedNewSessionButton = !(sidebarIsMobile ? sidebarOpenMobile : sidebarState === "expanded");
|
|
20658
21791
|
const displaySessionTitle = isSessionViewLoading ? loadingDisplaySessionTitle : getCurrentSessionTitleFromState(sessionHeaderState);
|
|
20659
21792
|
const moveSessionDirectoryOptions = newSessionDirectoryOptions.filter((option) => option.path !== displaySessionCwd);
|
|
20660
21793
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
@@ -20663,25 +21796,26 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
|
|
|
20663
21796
|
className: "relative flex w-full items-center gap-1",
|
|
20664
21797
|
children: [
|
|
20665
21798
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarTrigger, { className: "shrink-0" }),
|
|
20666
|
-
|
|
21799
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20667
21800
|
title: defaultNewSessionDirectory ? `Create a new session in ${formatDisplayPath$1(defaultNewSessionDirectory)}` : "Create a new session",
|
|
20668
21801
|
kbd: formatShortcutLabel("Control+N"),
|
|
20669
21802
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
20670
21803
|
size: "icon",
|
|
20671
21804
|
variant: "ghost",
|
|
20672
|
-
className: "shrink-0",
|
|
21805
|
+
className: "shrink-0 md:group-data-[sidebar-state=expanded]/sidebar-wrapper:hidden",
|
|
20673
21806
|
"aria-label": "Create a new session",
|
|
20674
21807
|
onClick: () => {
|
|
20675
21808
|
actionsRef.current.createSession();
|
|
20676
21809
|
},
|
|
20677
21810
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SquarePen, {})
|
|
20678
21811
|
})
|
|
20679
|
-
})
|
|
21812
|
+
}),
|
|
20680
21813
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20681
21814
|
className: "absolute left-1/2 flex w-max max-w-[calc(100%-4rem)] -translate-x-1/2 flex-col items-center justify-center gap-0 text-center",
|
|
20682
21815
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20683
21816
|
className: "flex max-w-full min-w-0 items-center justify-center gap-1.5",
|
|
20684
21817
|
children: [!isSessionViewLoading && sessionHeaderState.sessionStreaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
21818
|
+
size: "xs",
|
|
20685
21819
|
className: "shrink-0",
|
|
20686
21820
|
"aria-label": "Session streaming"
|
|
20687
21821
|
}) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
@@ -20692,7 +21826,7 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
|
|
|
20692
21826
|
})
|
|
20693
21827
|
})]
|
|
20694
21828
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
20695
|
-
className: "flex max-w-full min-w-0 items-center justify-center gap-x-
|
|
21829
|
+
className: "flex max-w-full min-w-0 items-center justify-center gap-x-2",
|
|
20696
21830
|
children: [displaySessionCwd ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
20697
21831
|
className: "inline-flex min-w-0 items-center text-xs text-muted-foreground",
|
|
20698
21832
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
@@ -20830,6 +21964,19 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
|
|
|
20830
21964
|
})
|
|
20831
21965
|
]
|
|
20832
21966
|
})] }),
|
|
21967
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
21968
|
+
title: "Toggle terminal",
|
|
21969
|
+
kbd: formatShortcutLabel("Control+`"),
|
|
21970
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
|
|
21971
|
+
size: "icon",
|
|
21972
|
+
variant: "ghost",
|
|
21973
|
+
className: "hidden md:inline-flex",
|
|
21974
|
+
"aria-pressed": terminalPanelOpen,
|
|
21975
|
+
"aria-label": "Toggle terminal panel",
|
|
21976
|
+
onClick: onToggleTerminalPanel,
|
|
21977
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SquareTerminal, {})
|
|
21978
|
+
})
|
|
21979
|
+
}),
|
|
20833
21980
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
20834
21981
|
title: "Toggle right sidebar",
|
|
20835
21982
|
kbd: formatShortcutLabel("Control+\\"),
|
|
@@ -21175,7 +22322,10 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
|
|
|
21175
22322
|
},
|
|
21176
22323
|
children: [entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
21177
22324
|
className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
|
|
21178
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
22325
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
22326
|
+
size: "xs",
|
|
22327
|
+
"aria-label": "Session streaming"
|
|
22328
|
+
})
|
|
21179
22329
|
}) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
21180
22330
|
className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
|
|
21181
22331
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
@@ -21352,7 +22502,10 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
|
|
|
21352
22502
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryPathLabel, { path: directory })
|
|
21353
22503
|
}),
|
|
21354
22504
|
!searchActive && !overlay ? collapsed ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "size-4 shrink-0 opacity-0 transition-opacity group-hover/directory-label:opacity-100 group-focus-visible/directory-label:opacity-100" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "size-4 shrink-0 opacity-0 transition-opacity group-hover/directory-label:opacity-100 group-focus-visible/directory-label:opacity-100" }) : null,
|
|
21355
|
-
showHeaderLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
22505
|
+
showHeaderLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
|
|
22506
|
+
size: "xs",
|
|
22507
|
+
className: "shrink-0"
|
|
22508
|
+
}) : null
|
|
21356
22509
|
]
|
|
21357
22510
|
}),
|
|
21358
22511
|
onCreateSessionInDirectory && !overlay && !isMobile ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
|
|
@@ -21422,7 +22575,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
|
|
|
21422
22575
|
]
|
|
21423
22576
|
})] }) : directoryHeader, !overlay ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollapsibleContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SidebarGroupContent, { children: showLoadingState ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
21424
22577
|
className: "flex items-center gap-2 p-2 text-sm text-sidebar-foreground/70",
|
|
21425
|
-
children: [showLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
22578
|
+
children: [showLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
21426
22579
|
className: "size-4",
|
|
21427
22580
|
"aria-hidden": "true"
|
|
21428
22581
|
}), "Loading sessions…"]
|
|
@@ -22845,11 +23998,21 @@ function usePromptMutationSessionSnapshot(store) {
|
|
|
22845
23998
|
function normalizeQueuedStreamingBehavior(streamingBehavior) {
|
|
22846
23999
|
return streamingBehavior === "followUp" ? "followUp" : "steer";
|
|
22847
24000
|
}
|
|
24001
|
+
function promptSidebarPreview(message, images) {
|
|
24002
|
+
const text = message.replace(/\s+/g, " ").trim();
|
|
24003
|
+
if (text) return text;
|
|
24004
|
+
if (images.length === 0) return "";
|
|
24005
|
+
return `${images.length.toLocaleString()} image${images.length === 1 ? "" : "s"}`;
|
|
24006
|
+
}
|
|
22848
24007
|
function createLocalPendingId() {
|
|
22849
24008
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return `optimistic:${crypto.randomUUID()}`;
|
|
22850
24009
|
return `optimistic:${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
22851
24010
|
}
|
|
22852
|
-
function buildCurrentSessionRequestUrl(path, { contextId, sessionState, fallbackSessionId }) {
|
|
24011
|
+
function buildCurrentSessionRequestUrl(path, { contextId, sessionState, fallbackSessionId, targetSessionKey }) {
|
|
24012
|
+
if (targetSessionKey) return buildRequestUrl(path, {
|
|
24013
|
+
contextId,
|
|
24014
|
+
searchParams: { sessionKey: targetSessionKey }
|
|
24015
|
+
});
|
|
22853
24016
|
const sessionKey = sessionState.sessionKey && !sessionState.sessionKey.startsWith("optimistic:") ? sessionState.sessionKey : void 0;
|
|
22854
24017
|
const shouldUseSessionKey = Boolean(sessionKey && (sessionState.draft || !sessionState.sessionId));
|
|
22855
24018
|
return buildRequestUrl(path, {
|
|
@@ -22907,16 +24070,17 @@ function movePendingComposerMessage(messages, pendingId, direction) {
|
|
|
22907
24070
|
next.splice(targetIndex, 0, movedItem);
|
|
22908
24071
|
return next;
|
|
22909
24072
|
}
|
|
22910
|
-
function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultNewSessionDirectory, sessionStore, sessionStateRef, draftSessionLoadingOwnerKey, pendingDraftPrompt, pendingDraftFollowUps, awaitingFirstTurn, pendingMessages, composerDiffLineCommentsRef, composerImagesRef, composerTextRef, composerSkillRef, replaceComposerDraft, lastSyncedEditorTextRef, rememberRecentDirectory, prefetchDirectorySessionsIndex, addOptimisticUserMessage, removeOptimisticUserMessage, addOptimisticSidebarSession, removeOptimisticSidebarSession, setSidebarDirectories, setStoredDraftDirectory, setDraftSessionLoadingOwnerKey, setPendingDraftPrompt, setPendingDraftFollowUps, setPendingMessages, setAwaitingFirstTurn, setIsSubmitting, setComposerDiffLineComments, setComposerImages }) {
|
|
24073
|
+
function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultNewSessionDirectory, sessionStore, sessionStateRef, draftSessionLoadingOwnerKey, pendingDraftPrompt, pendingDraftFollowUps, awaitingFirstTurn, pendingMessages, composerDiffLineCommentsRef, composerImagesRef, composerTextRef, composerSkillRef, replaceComposerDraft, lastSyncedEditorTextRef, rememberRecentDirectory, prefetchDirectorySessionsIndex, addOptimisticUserMessage, removeOptimisticUserMessage, addOptimisticSidebarSession, removeOptimisticSidebarSession, updateOptimisticSidebarSessionPreview, setSidebarDirectories, setStoredDraftDirectory, setDraftSessionLoadingOwnerKey, setPendingDraftPrompt, setPendingDraftFollowUps, setPendingMessages, setAwaitingFirstTurn, setIsSubmitting, setComposerDiffLineComments, setComposerImages }) {
|
|
22911
24074
|
const queryClient = useQueryClient();
|
|
22912
24075
|
const draftSessionLoadingOwnerKeyRef = import_react.useRef(draftSessionLoadingOwnerKey);
|
|
24076
|
+
const pendingNewSessionPromptTargetRef = import_react.useRef(null);
|
|
24077
|
+
const newSessionRequestNonceRef = import_react.useRef(0);
|
|
22913
24078
|
const pendingDraftPromptRef = import_react.useRef(pendingDraftPrompt);
|
|
22914
24079
|
const pendingDraftFollowUpsRef = import_react.useRef(pendingDraftFollowUps);
|
|
22915
24080
|
const pendingMessagesRef = import_react.useRef(pendingMessages);
|
|
22916
24081
|
const awaitingFirstTurnRef = import_react.useRef(awaitingFirstTurn);
|
|
22917
24082
|
const awaitingFirstTurnAssistantOutputSignatureRef = import_react.useRef(null);
|
|
22918
24083
|
const sessionSnapshot = usePromptMutationSessionSnapshot(sessionStore);
|
|
22919
|
-
const sessionStreamingRef = import_react.useRef(sessionSnapshot.streaming);
|
|
22920
24084
|
const flushPendingDraftPromptRef = import_react.useRef(async () => false);
|
|
22921
24085
|
import_react.useEffect(() => {
|
|
22922
24086
|
draftSessionLoadingOwnerKeyRef.current = draftSessionLoadingOwnerKey;
|
|
@@ -22933,9 +24097,6 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22933
24097
|
import_react.useEffect(() => {
|
|
22934
24098
|
awaitingFirstTurnRef.current = awaitingFirstTurn;
|
|
22935
24099
|
}, [awaitingFirstTurn]);
|
|
22936
|
-
import_react.useEffect(() => {
|
|
22937
|
-
sessionStreamingRef.current = sessionSnapshot.streaming;
|
|
22938
|
-
}, [sessionSnapshot.streaming]);
|
|
22939
24100
|
const updatePendingMessages = import_react.useCallback((updater) => {
|
|
22940
24101
|
setPendingMessages((current) => {
|
|
22941
24102
|
const next = updater(current);
|
|
@@ -22990,6 +24151,7 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
22990
24151
|
removeOptimisticUserMessage(nextPrompt.optimisticId);
|
|
22991
24152
|
removeOptimisticSidebarSession(nextPrompt.optimisticSidebarSessionId);
|
|
22992
24153
|
for (const followUp of pendingDraftFollowUpsRef.current) removeOptimisticUserMessage(followUp.optimisticId);
|
|
24154
|
+
pendingNewSessionPromptTargetRef.current = null;
|
|
22993
24155
|
pendingDraftPromptRef.current = null;
|
|
22994
24156
|
pendingDraftFollowUpsRef.current = [];
|
|
22995
24157
|
setPendingDraftPrompt(null);
|
|
@@ -23062,17 +24224,32 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23062
24224
|
const ownerKey = promptDraftKey({ cwd: nextCwd });
|
|
23063
24225
|
draftSessionLoadingOwnerKeyRef.current = ownerKey;
|
|
23064
24226
|
setDraftSessionLoadingOwnerKey(ownerKey);
|
|
24227
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = null;
|
|
24228
|
+
awaitingFirstTurnRef.current = false;
|
|
24229
|
+
setAwaitingFirstTurn(false);
|
|
24230
|
+
pendingMessagesRef.current = [];
|
|
24231
|
+
setPendingMessages((current) => current.length === 0 ? current : []);
|
|
24232
|
+
const requestNonce = newSessionRequestNonceRef.current + 1;
|
|
24233
|
+
newSessionRequestNonceRef.current = requestNonce;
|
|
23065
24234
|
try {
|
|
23066
|
-
await createSessionRequest({ cwd: nextCwd });
|
|
24235
|
+
const response = await createSessionRequest({ cwd: nextCwd });
|
|
24236
|
+
if (newSessionRequestNonceRef.current !== requestNonce) return true;
|
|
24237
|
+
pendingNewSessionPromptTargetRef.current = {
|
|
24238
|
+
ownerKey,
|
|
24239
|
+
sessionKey: response.sessionKey,
|
|
24240
|
+
cwd: response.cwd
|
|
24241
|
+
};
|
|
23067
24242
|
if (draftSessionLoadingOwnerKeyRef.current === ownerKey) {
|
|
23068
24243
|
draftSessionLoadingOwnerKeyRef.current = null;
|
|
23069
24244
|
setDraftSessionLoadingOwnerKey((current) => current === ownerKey ? null : current);
|
|
23070
24245
|
}
|
|
23071
|
-
if (pendingDraftPromptRef.current?.ownerKey === ownerKey) flushPendingDraftPromptRef.current(ownerKey);
|
|
24246
|
+
if (pendingDraftPromptRef.current?.ownerKey === ownerKey) flushPendingDraftPromptRef.current(ownerKey, response.sessionKey);
|
|
23072
24247
|
return true;
|
|
23073
24248
|
} catch (error) {
|
|
24249
|
+
if (newSessionRequestNonceRef.current !== requestNonce) return true;
|
|
23074
24250
|
if (draftSessionLoadingOwnerKeyRef.current === ownerKey) draftSessionLoadingOwnerKeyRef.current = null;
|
|
23075
24251
|
setDraftSessionLoadingOwnerKey((current) => current === ownerKey ? null : current);
|
|
24252
|
+
if (pendingNewSessionPromptTargetRef.current?.ownerKey === ownerKey) pendingNewSessionPromptTargetRef.current = null;
|
|
23076
24253
|
restorePendingDraftPrompt(ownerKey);
|
|
23077
24254
|
toast.error(error instanceof Error ? error.message : "Failed to create session");
|
|
23078
24255
|
return false;
|
|
@@ -23083,12 +24260,14 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23083
24260
|
rememberRecentDirectory,
|
|
23084
24261
|
restorePendingDraftPrompt,
|
|
23085
24262
|
sessionStateRef,
|
|
24263
|
+
setAwaitingFirstTurn,
|
|
23086
24264
|
setDraftSessionLoadingOwnerKey,
|
|
24265
|
+
setPendingMessages,
|
|
23087
24266
|
setStoredDraftDirectory,
|
|
23088
24267
|
viewerContextId
|
|
23089
24268
|
]);
|
|
23090
|
-
const queuePendingDraftPrompt = import_react.useCallback((streamingBehavior) => {
|
|
23091
|
-
const ownerKey = draftSessionLoadingOwnerKeyRef.current;
|
|
24269
|
+
const queuePendingDraftPrompt = import_react.useCallback((streamingBehavior, ownerKeyOverride) => {
|
|
24270
|
+
const ownerKey = ownerKeyOverride || draftSessionLoadingOwnerKeyRef.current;
|
|
23092
24271
|
if (!ownerKey) return false;
|
|
23093
24272
|
const message = buildComposerPromptMessage({
|
|
23094
24273
|
text: composerTextRef.current,
|
|
@@ -23097,17 +24276,20 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23097
24276
|
}).trim();
|
|
23098
24277
|
const images = composerImagesRef.current.map((image) => ({ ...image }));
|
|
23099
24278
|
if (!message && images.length === 0) return false;
|
|
23100
|
-
|
|
24279
|
+
const currentPendingPrompt = pendingDraftPromptRef.current?.ownerKey === ownerKey ? pendingDraftPromptRef.current : null;
|
|
24280
|
+
const sidebarPreview = promptSidebarPreview(message, images);
|
|
24281
|
+
if (!currentPendingPrompt) {
|
|
23101
24282
|
const nextPrompt = {
|
|
23102
24283
|
ownerKey,
|
|
23103
24284
|
message,
|
|
23104
24285
|
images,
|
|
24286
|
+
streamingBehavior,
|
|
23105
24287
|
optimisticId: addOptimisticUserMessage({
|
|
23106
24288
|
message,
|
|
23107
24289
|
images,
|
|
23108
24290
|
queued: false
|
|
23109
24291
|
}),
|
|
23110
|
-
optimisticSidebarSessionId: addOptimisticSidebarSession()
|
|
24292
|
+
optimisticSidebarSessionId: addOptimisticSidebarSession({ lastMessagePreview: sidebarPreview })
|
|
23111
24293
|
};
|
|
23112
24294
|
pendingDraftPromptRef.current = nextPrompt;
|
|
23113
24295
|
setPendingDraftPrompt(nextPrompt);
|
|
@@ -23117,6 +24299,10 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23117
24299
|
} else {
|
|
23118
24300
|
const queuedStreamingBehavior = normalizeQueuedStreamingBehavior(streamingBehavior);
|
|
23119
24301
|
const optimisticId = createLocalPendingId();
|
|
24302
|
+
updateOptimisticSidebarSessionPreview({
|
|
24303
|
+
...currentPendingPrompt.optimisticSidebarSessionId ? { optimisticSidebarSessionId: currentPendingPrompt.optimisticSidebarSessionId } : {},
|
|
24304
|
+
preview: sidebarPreview
|
|
24305
|
+
});
|
|
23120
24306
|
const nextFollowUps = [...pendingDraftFollowUpsRef.current, {
|
|
23121
24307
|
message,
|
|
23122
24308
|
images,
|
|
@@ -23144,15 +24330,17 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23144
24330
|
setComposerDiffLineComments,
|
|
23145
24331
|
setComposerImages,
|
|
23146
24332
|
setPendingDraftFollowUps,
|
|
23147
|
-
setPendingDraftPrompt
|
|
24333
|
+
setPendingDraftPrompt,
|
|
24334
|
+
updateOptimisticSidebarSessionPreview
|
|
23148
24335
|
]);
|
|
23149
24336
|
const promptMutation = useMutation({
|
|
23150
|
-
mutationFn: async ({ message, images, streamingBehavior, pendingId, thinkingLevel }) => {
|
|
24337
|
+
mutationFn: async ({ message, images, streamingBehavior, pendingId, thinkingLevel, targetSessionKey, draftTarget }) => {
|
|
23151
24338
|
if (!viewerContextId) throw new Error("Viewer context unavailable");
|
|
23152
24339
|
return await fetchJson(buildCurrentSessionRequestUrl("/api/prompt", {
|
|
23153
24340
|
contextId: viewerContextId,
|
|
23154
24341
|
sessionState: sessionStateRef.current,
|
|
23155
|
-
fallbackSessionId: activeSessionId
|
|
24342
|
+
fallbackSessionId: activeSessionId,
|
|
24343
|
+
targetSessionKey
|
|
23156
24344
|
}), {
|
|
23157
24345
|
method: "POST",
|
|
23158
24346
|
headers: { "content-type": "application/json" },
|
|
@@ -23161,7 +24349,9 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23161
24349
|
images,
|
|
23162
24350
|
streamingBehavior,
|
|
23163
24351
|
pendingId,
|
|
23164
|
-
thinkingLevel
|
|
24352
|
+
thinkingLevel,
|
|
24353
|
+
draftOwnerKey: draftTarget?.ownerKey,
|
|
24354
|
+
draftCwd: draftTarget?.cwd
|
|
23165
24355
|
})
|
|
23166
24356
|
});
|
|
23167
24357
|
},
|
|
@@ -23182,12 +24372,29 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23182
24372
|
diffLineComments: submittedDiffLineComments
|
|
23183
24373
|
}).trim();
|
|
23184
24374
|
if (!message && composerImagesRef.current.length === 0) return false;
|
|
23185
|
-
const
|
|
24375
|
+
const currentSessionState = sessionStateRef.current;
|
|
24376
|
+
const pendingNewSessionPromptTarget = pendingNewSessionPromptTargetRef.current;
|
|
24377
|
+
const currentDraftOwnerKey = currentSessionState.draft ? promptDraftKey(currentSessionState) : "";
|
|
24378
|
+
const implicitTargetSessionKey = !options?.targetSessionKey && currentSessionState.draft && pendingNewSessionPromptTarget && promptDraftKeyMatchesOwner(currentDraftOwnerKey, pendingNewSessionPromptTarget.ownerKey) ? pendingNewSessionPromptTarget.sessionKey : void 0;
|
|
24379
|
+
const targetSessionKey = options?.targetSessionKey || implicitTargetSessionKey;
|
|
24380
|
+
const targetDraft = currentSessionState.draft ? {
|
|
24381
|
+
ownerKey: options?.targetDraftOwnerKey || (targetSessionKey && pendingNewSessionPromptTarget?.sessionKey === targetSessionKey ? pendingNewSessionPromptTarget.ownerKey : currentDraftOwnerKey),
|
|
24382
|
+
cwd: options?.targetDraftCwd || (targetSessionKey && pendingNewSessionPromptTarget?.sessionKey === targetSessionKey ? pendingNewSessionPromptTarget.cwd || currentSessionState.cwd : currentSessionState.cwd)
|
|
24383
|
+
} : void 0;
|
|
24384
|
+
if (currentSessionState.draft && currentSessionState.sessionKey?.startsWith("optimistic:") && !targetSessionKey) {
|
|
24385
|
+
if (!draftSessionLoadingOwnerKeyRef.current && currentDraftOwnerKey) {
|
|
24386
|
+
draftSessionLoadingOwnerKeyRef.current = currentDraftOwnerKey;
|
|
24387
|
+
setDraftSessionLoadingOwnerKey(currentDraftOwnerKey);
|
|
24388
|
+
}
|
|
24389
|
+
return queuePendingDraftPrompt(streamingBehavior, currentDraftOwnerKey);
|
|
24390
|
+
}
|
|
24391
|
+
const treatAsQueuedPrompt = options?.forceFirstPrompt ? false : Boolean(currentSessionState.streaming || awaitingFirstTurnRef.current);
|
|
23186
24392
|
const normalizedStreamingBehavior = treatAsQueuedPrompt ? normalizeQueuedStreamingBehavior(streamingBehavior) : void 0;
|
|
23187
24393
|
const submittedImages = composerImagesRef.current.map((image) => ({ ...image }));
|
|
24394
|
+
const sidebarPreview = promptSidebarPreview(message, submittedImages);
|
|
23188
24395
|
const queuedPendingId = treatAsQueuedPrompt ? createLocalPendingId() : void 0;
|
|
23189
24396
|
if (!treatAsQueuedPrompt) {
|
|
23190
|
-
awaitingFirstTurnAssistantOutputSignatureRef.current = sessionAssistantOutputSignature(
|
|
24397
|
+
awaitingFirstTurnAssistantOutputSignatureRef.current = sessionAssistantOutputSignature(currentSessionState.items);
|
|
23191
24398
|
awaitingFirstTurnRef.current = true;
|
|
23192
24399
|
setAwaitingFirstTurn(true);
|
|
23193
24400
|
}
|
|
@@ -23196,7 +24403,11 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23196
24403
|
images: submittedImages,
|
|
23197
24404
|
queued: false
|
|
23198
24405
|
}));
|
|
23199
|
-
const optimisticSidebarSessionId = options?.optimisticSidebarSessionId ?? (!treatAsQueuedPrompt &&
|
|
24406
|
+
const optimisticSidebarSessionId = options?.optimisticSidebarSessionId ?? (!treatAsQueuedPrompt && currentSessionState.draft ? addOptimisticSidebarSession({ lastMessagePreview: sidebarPreview }) : void 0);
|
|
24407
|
+
updateOptimisticSidebarSessionPreview({
|
|
24408
|
+
...optimisticSidebarSessionId ? { optimisticSidebarSessionId } : {},
|
|
24409
|
+
preview: sidebarPreview
|
|
24410
|
+
});
|
|
23200
24411
|
if (queuedPendingId && normalizedStreamingBehavior) addOptimisticPendingMessage({
|
|
23201
24412
|
pendingId: queuedPendingId,
|
|
23202
24413
|
text: message,
|
|
@@ -23214,9 +24425,12 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23214
24425
|
images: submittedImages,
|
|
23215
24426
|
streamingBehavior: normalizedStreamingBehavior,
|
|
23216
24427
|
pendingId: queuedPendingId,
|
|
23217
|
-
thinkingLevel:
|
|
24428
|
+
thinkingLevel: currentSessionState.thinkingLevel,
|
|
24429
|
+
targetSessionKey,
|
|
24430
|
+
draftTarget: targetDraft
|
|
23218
24431
|
});
|
|
23219
24432
|
if (queuedPendingId && "queued" in response && (!response.queued || response.canceled)) removeOptimisticPendingMessage(queuedPendingId);
|
|
24433
|
+
if (targetSessionKey && pendingNewSessionPromptTargetRef.current?.sessionKey === targetSessionKey) pendingNewSessionPromptTargetRef.current = null;
|
|
23220
24434
|
return true;
|
|
23221
24435
|
} catch (error) {
|
|
23222
24436
|
if (queuedPendingId) removeOptimisticPendingMessage(queuedPendingId);
|
|
@@ -23259,10 +24473,12 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23259
24473
|
setAwaitingFirstTurn,
|
|
23260
24474
|
setComposerDiffLineComments,
|
|
23261
24475
|
setComposerImages,
|
|
24476
|
+
setDraftSessionLoadingOwnerKey,
|
|
23262
24477
|
setIsSubmitting,
|
|
24478
|
+
updateOptimisticSidebarSessionPreview,
|
|
23263
24479
|
viewerContextId
|
|
23264
24480
|
]);
|
|
23265
|
-
const flushPendingDraftFollowUps = import_react.useCallback(async () => {
|
|
24481
|
+
const flushPendingDraftFollowUps = import_react.useCallback(async (targetSessionKey, draftTarget) => {
|
|
23266
24482
|
if (draftSessionLoadingOwnerKeyRef.current) return false;
|
|
23267
24483
|
const pendingFollowUps = pendingDraftFollowUpsRef.current;
|
|
23268
24484
|
if (pendingFollowUps.length === 0) return false;
|
|
@@ -23283,7 +24499,9 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23283
24499
|
images: followUp.images,
|
|
23284
24500
|
streamingBehavior: followUp.streamingBehavior,
|
|
23285
24501
|
pendingId: followUp.optimisticId,
|
|
23286
|
-
thinkingLevel: sessionStateRef.current.thinkingLevel
|
|
24502
|
+
thinkingLevel: sessionStateRef.current.thinkingLevel,
|
|
24503
|
+
targetSessionKey,
|
|
24504
|
+
draftTarget
|
|
23287
24505
|
});
|
|
23288
24506
|
} catch (error) {
|
|
23289
24507
|
for (const unsentFollowUp of followUps.slice(index)) removeOptimisticUserMessage(unsentFollowUp.optimisticId);
|
|
@@ -23306,24 +24524,35 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23306
24524
|
setComposerImages,
|
|
23307
24525
|
setPendingDraftFollowUps
|
|
23308
24526
|
]);
|
|
23309
|
-
const flushPendingDraftPrompt = import_react.useCallback(async (ownerKey) => {
|
|
24527
|
+
const flushPendingDraftPrompt = import_react.useCallback(async (ownerKey, targetSessionKey) => {
|
|
23310
24528
|
const nextPrompt = pendingDraftPromptRef.current;
|
|
23311
24529
|
if (!nextPrompt || nextPrompt.ownerKey !== ownerKey || draftSessionLoadingOwnerKeyRef.current) return false;
|
|
24530
|
+
const pendingTarget = pendingNewSessionPromptTargetRef.current;
|
|
24531
|
+
const resolvedTargetSessionKey = targetSessionKey || (pendingTarget?.ownerKey === ownerKey ? pendingTarget.sessionKey : void 0);
|
|
24532
|
+
const resolvedDraftTarget = {
|
|
24533
|
+
ownerKey,
|
|
24534
|
+
cwd: pendingTarget?.cwd || sessionStateRef.current.cwd
|
|
24535
|
+
};
|
|
23312
24536
|
pendingDraftPromptRef.current = null;
|
|
23313
24537
|
setPendingDraftPrompt(null);
|
|
23314
24538
|
applyPendingDraftPromptToComposer(nextPrompt);
|
|
23315
24539
|
if (!await submitPrompt(nextPrompt.streamingBehavior, {
|
|
23316
24540
|
forceFirstPrompt: true,
|
|
23317
24541
|
optimisticId: nextPrompt.optimisticId,
|
|
23318
|
-
optimisticSidebarSessionId: nextPrompt.optimisticSidebarSessionId
|
|
24542
|
+
optimisticSidebarSessionId: nextPrompt.optimisticSidebarSessionId,
|
|
24543
|
+
targetSessionKey: resolvedTargetSessionKey,
|
|
24544
|
+
targetDraftOwnerKey: resolvedDraftTarget.ownerKey,
|
|
24545
|
+
targetDraftCwd: resolvedDraftTarget.cwd
|
|
23319
24546
|
})) {
|
|
23320
24547
|
removeOptimisticSidebarSession(nextPrompt.optimisticSidebarSessionId);
|
|
23321
24548
|
for (const followUp of pendingDraftFollowUpsRef.current) removeOptimisticUserMessage(followUp.optimisticId);
|
|
23322
24549
|
pendingDraftFollowUpsRef.current = [];
|
|
23323
24550
|
setPendingDraftFollowUps([]);
|
|
24551
|
+
if (pendingNewSessionPromptTargetRef.current?.ownerKey === ownerKey) pendingNewSessionPromptTargetRef.current = null;
|
|
23324
24552
|
return false;
|
|
23325
24553
|
}
|
|
23326
|
-
await flushPendingDraftFollowUps();
|
|
24554
|
+
await flushPendingDraftFollowUps(resolvedTargetSessionKey, resolvedDraftTarget);
|
|
24555
|
+
if (pendingNewSessionPromptTargetRef.current?.ownerKey === ownerKey) pendingNewSessionPromptTargetRef.current = null;
|
|
23327
24556
|
return true;
|
|
23328
24557
|
}, [
|
|
23329
24558
|
applyPendingDraftPromptToComposer,
|
|
@@ -23341,9 +24570,15 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
|
|
|
23341
24570
|
if (currentSessionState.sessionKey?.startsWith("optimistic:")) return;
|
|
23342
24571
|
const currentOwnerKey = promptDraftKey(currentSessionState);
|
|
23343
24572
|
if (!currentSessionState.draft || !promptDraftKeyMatchesOwner(currentOwnerKey, draftSessionLoadingOwnerKey)) return;
|
|
24573
|
+
const targetSessionKey = currentSessionState.sessionKey?.startsWith("optimistic:") ? void 0 : currentSessionState.sessionKey;
|
|
24574
|
+
if (targetSessionKey) pendingNewSessionPromptTargetRef.current = {
|
|
24575
|
+
ownerKey: draftSessionLoadingOwnerKey,
|
|
24576
|
+
sessionKey: targetSessionKey,
|
|
24577
|
+
cwd: currentSessionState.cwd
|
|
24578
|
+
};
|
|
23344
24579
|
draftSessionLoadingOwnerKeyRef.current = null;
|
|
23345
24580
|
setDraftSessionLoadingOwnerKey(null);
|
|
23346
|
-
if (pendingDraftPromptRef.current?.ownerKey === draftSessionLoadingOwnerKey) flushPendingDraftPrompt(draftSessionLoadingOwnerKey);
|
|
24581
|
+
if (pendingDraftPromptRef.current?.ownerKey === draftSessionLoadingOwnerKey) flushPendingDraftPrompt(draftSessionLoadingOwnerKey, targetSessionKey);
|
|
23347
24582
|
}, [
|
|
23348
24583
|
draftSessionLoadingOwnerKey,
|
|
23349
24584
|
flushPendingDraftPrompt,
|
|
@@ -24750,10 +25985,13 @@ function useAppShellSessionSync({ viewerContextId, sessionId, draftSessionLoadin
|
|
|
24750
25985
|
]);
|
|
24751
25986
|
}
|
|
24752
25987
|
var DOUBLE_ESCAPE_INTERVAL_MS = 500;
|
|
25988
|
+
function isTerminalTarget(target) {
|
|
25989
|
+
return target instanceof HTMLElement && target.closest("[data-terminal-panel=\"true\"]") !== null;
|
|
25990
|
+
}
|
|
24753
25991
|
function isEditableTarget(target) {
|
|
24754
25992
|
if (!(target instanceof HTMLElement)) return false;
|
|
24755
25993
|
const tagName = target.tagName.toLowerCase();
|
|
24756
|
-
return target.isContentEditable || tagName === "input" || tagName === "textarea" || target.closest("[contenteditable=\"true\"]") !== null;
|
|
25994
|
+
return target.isContentEditable || isTerminalTarget(target) || tagName === "input" || tagName === "textarea" || target.closest("[contenteditable=\"true\"]") !== null;
|
|
24757
25995
|
}
|
|
24758
25996
|
function isPromptTextareaTarget(target) {
|
|
24759
25997
|
return target instanceof HTMLTextAreaElement && target.name === "prompt";
|
|
@@ -24793,7 +26031,7 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
24793
26031
|
};
|
|
24794
26032
|
const handleEscape = (event) => {
|
|
24795
26033
|
const context = getShortcutContext(event);
|
|
24796
|
-
if (event.repeat || context.modalOpen || event.defaultPrevented) return;
|
|
26034
|
+
if (event.repeat || context.modalOpen || event.defaultPrevented || isTerminalTarget(event.target)) return;
|
|
24797
26035
|
const now = Date.now();
|
|
24798
26036
|
if (now - lastEscapeKeyDownAtRef.current <= DOUBLE_ESCAPE_INTERVAL_MS) {
|
|
24799
26037
|
lastEscapeKeyDownAtRef.current = 0;
|
|
@@ -24832,7 +26070,7 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
24832
26070
|
};
|
|
24833
26071
|
const handleFocusPrompt = (event) => {
|
|
24834
26072
|
const context = getShortcutContext(event);
|
|
24835
|
-
if (context.blockingModalOpen || event.defaultPrevented) return;
|
|
26073
|
+
if (context.blockingModalOpen || event.defaultPrevented || isTerminalTarget(event.target)) return;
|
|
24836
26074
|
event.preventDefault();
|
|
24837
26075
|
closeCommandPaletteForShortcut(context.commandPaletteOpen);
|
|
24838
26076
|
shortcutActionsRef.current.focusPrompt();
|
|
@@ -24859,12 +26097,19 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
24859
26097
|
const key = event.altKey && event.code.startsWith("Key") ? event.code.slice(3).toLowerCase() : event.key.toLowerCase();
|
|
24860
26098
|
const context = getShortcutContext(event);
|
|
24861
26099
|
if (context.blockingModalOpen || event.defaultPrevented) return;
|
|
26100
|
+
if (isTerminalTarget(event.target) && !context.commandPaletteOpen && key !== "`") return;
|
|
24862
26101
|
if (key === "\\") {
|
|
24863
26102
|
event.preventDefault();
|
|
24864
26103
|
closeCommandPaletteForShortcut(context.commandPaletteOpen);
|
|
24865
26104
|
shortcutActionsRef.current.toggleGitPanel();
|
|
24866
26105
|
return;
|
|
24867
26106
|
}
|
|
26107
|
+
if (key === "`") {
|
|
26108
|
+
event.preventDefault();
|
|
26109
|
+
closeCommandPaletteForShortcut(context.commandPaletteOpen);
|
|
26110
|
+
shortcutActionsRef.current.toggleTerminalPanel();
|
|
26111
|
+
return;
|
|
26112
|
+
}
|
|
24868
26113
|
if (key === "k") {
|
|
24869
26114
|
event.preventDefault();
|
|
24870
26115
|
shortcutActionsRef.current.openCommandPalette();
|
|
@@ -25036,6 +26281,7 @@ function useAppShellShortcuts({ addDirectoryOpenRef, commandPaletteOpenRef, comp
|
|
|
25036
26281
|
})),
|
|
25037
26282
|
...[
|
|
25038
26283
|
{ key: "\\" },
|
|
26284
|
+
{ key: "`" },
|
|
25039
26285
|
{ key: "K" },
|
|
25040
26286
|
{ key: "P" },
|
|
25041
26287
|
{
|
|
@@ -25104,6 +26350,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25104
26350
|
if (!appUiStoreRef.current) appUiStoreRef.current = createPicoStore({
|
|
25105
26351
|
currentTab: "session",
|
|
25106
26352
|
gitPanelOpen: false,
|
|
26353
|
+
terminalPanelOpen: false,
|
|
25107
26354
|
initialLoadingSessionId: sessionId || null,
|
|
25108
26355
|
loadingSessionId: null
|
|
25109
26356
|
}, shallowRecordEqual);
|
|
@@ -25119,6 +26366,11 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25119
26366
|
setStoreField(appUiStore, "gitPanelOpen", nextOpen);
|
|
25120
26367
|
safeLocalStorageSetItem(RIGHT_SIDEBAR_OPEN_STORAGE_KEY, nextOpen ? "1" : "0");
|
|
25121
26368
|
}, [appUiStore]);
|
|
26369
|
+
const setTerminalPanelOpen = import_react.useCallback((action) => {
|
|
26370
|
+
const nextOpen = applyStoreAction(appUiStore.state.terminalPanelOpen, action);
|
|
26371
|
+
setStoreField(appUiStore, "terminalPanelOpen", nextOpen);
|
|
26372
|
+
safeLocalStorageSetItem(TERMINAL_PANEL_OPEN_STORAGE_KEY, nextOpen ? "1" : "0");
|
|
26373
|
+
}, [appUiStore]);
|
|
25122
26374
|
const setLoadingSessionId = import_react.useCallback((action) => {
|
|
25123
26375
|
setStoreField(appUiStore, "loadingSessionId", action);
|
|
25124
26376
|
}, [appUiStore]);
|
|
@@ -25544,6 +26796,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25544
26796
|
sessionKey: currentSessionState.sessionKey
|
|
25545
26797
|
}), { compare: shallowRecordEqual });
|
|
25546
26798
|
const gitPanelOpen = useSelector(appUiStore, (state) => state.gitPanelOpen);
|
|
26799
|
+
const terminalPanelOpen = useSelector(appUiStore, (state) => state.terminalPanelOpen);
|
|
25547
26800
|
const openFileViewTab = (path, options) => {
|
|
25548
26801
|
if (!path) return;
|
|
25549
26802
|
batch(() => {
|
|
@@ -25640,7 +26893,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25640
26893
|
} : currentSession : { draft: true }, sessionId);
|
|
25641
26894
|
setStoreState(appUiStore, (current) => ({
|
|
25642
26895
|
...current,
|
|
25643
|
-
currentTab: current.currentTab === "git" ? "session" : current.currentTab,
|
|
26896
|
+
currentTab: current.currentTab === "git" || current.currentTab === "terminal" ? "session" : current.currentTab,
|
|
25644
26897
|
initialLoadingSessionId: sessionId ? current.initialLoadingSessionId : null,
|
|
25645
26898
|
loadingSessionId: sessionId && sessionStateRef.current.sessionId !== sessionId ? sessionId : null
|
|
25646
26899
|
}));
|
|
@@ -25652,7 +26905,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25652
26905
|
]);
|
|
25653
26906
|
import_react.useEffect(() => {
|
|
25654
26907
|
if (isMobile) return;
|
|
25655
|
-
setCurrentTab((tab) => tab === "git" ? "session" : tab);
|
|
26908
|
+
setCurrentTab((tab) => tab === "git" || tab === "terminal" ? "session" : tab);
|
|
25656
26909
|
}, [isMobile, setCurrentTab]);
|
|
25657
26910
|
const syncComposerDraft = (value, target = sessionStateRef.current) => {
|
|
25658
26911
|
const parsed = parseComposerSkillMessage(value);
|
|
@@ -25696,6 +26949,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25696
26949
|
const applyStoredClientPreferences = () => {
|
|
25697
26950
|
batch(() => {
|
|
25698
26951
|
setGitPanelOpen(readStoredRightSidebarOpen());
|
|
26952
|
+
setTerminalPanelOpen(readStoredTerminalPanelOpen());
|
|
25699
26953
|
setStoredDraftDirectory(readStoredDraftDirectory() || "");
|
|
25700
26954
|
setSessionDoneSoundEnabled(readStoredSessionDoneSoundEnabled());
|
|
25701
26955
|
setSessionDoneDesktopNotificationsEnabled(readStoredSessionDoneDesktopNotificationsEnabled());
|
|
@@ -25859,6 +27113,20 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
25859
27113
|
}
|
|
25860
27114
|
setGitPanelOpen((open) => !open);
|
|
25861
27115
|
};
|
|
27116
|
+
const toggleTerminalPanel = () => {
|
|
27117
|
+
if (isMobile) {
|
|
27118
|
+
setCurrentTab((tab) => tab === "terminal" ? "session" : "terminal");
|
|
27119
|
+
return;
|
|
27120
|
+
}
|
|
27121
|
+
setTerminalPanelOpen((open) => !open);
|
|
27122
|
+
};
|
|
27123
|
+
const closeTerminalPanel = () => {
|
|
27124
|
+
if (isMobile) {
|
|
27125
|
+
setCurrentTab((tab) => tab === "terminal" ? "session" : tab);
|
|
27126
|
+
return;
|
|
27127
|
+
}
|
|
27128
|
+
setTerminalPanelOpen(false);
|
|
27129
|
+
};
|
|
25862
27130
|
const openRenameDialog = () => {
|
|
25863
27131
|
const currentState = sessionStateRef.current;
|
|
25864
27132
|
if (!currentState.sessionFile) return;
|
|
@@ -26177,6 +27445,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26177
27445
|
title: "New session",
|
|
26178
27446
|
modified,
|
|
26179
27447
|
lastUserMessageAt: modified,
|
|
27448
|
+
lastMessageAt: modified,
|
|
27449
|
+
...options?.lastMessagePreview ? { lastMessagePreview: options.lastMessagePreview } : {},
|
|
26180
27450
|
streaming: true,
|
|
26181
27451
|
unread: false,
|
|
26182
27452
|
optimistic: true
|
|
@@ -26223,6 +27493,29 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26223
27493
|
sidebarStore.setSidebarSessionSelectionAnchor((current) => current === entryKey ? "" : current);
|
|
26224
27494
|
}
|
|
26225
27495
|
}, [sidebarStore]);
|
|
27496
|
+
const updateOptimisticSidebarSessionPreview = import_react.useCallback((options) => {
|
|
27497
|
+
const preview = options.preview.trim();
|
|
27498
|
+
if (!preview) return;
|
|
27499
|
+
const currentState = sessionStateRef.current;
|
|
27500
|
+
const modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
27501
|
+
const sessionId = options.optimisticSidebarSessionId || currentState.sessionId || currentState.sessionKey;
|
|
27502
|
+
const sessionPath = currentState.sessionFile;
|
|
27503
|
+
const previewUpdate = {
|
|
27504
|
+
...sessionId ? { sessionId } : {},
|
|
27505
|
+
...sessionPath ? { sessionPath } : {},
|
|
27506
|
+
preview,
|
|
27507
|
+
modified
|
|
27508
|
+
};
|
|
27509
|
+
sidebarStore.setDirectoryIndexDataByPath((current) => updateOptimisticSidebarSessionPreviewEntry(current, previewUpdate));
|
|
27510
|
+
sidebarStore.setSessionsEvent((current) => {
|
|
27511
|
+
if (!current?.directoryIndexes) return current;
|
|
27512
|
+
const directoryIndexes = updateOptimisticSidebarSessionPreviewEntry(current.directoryIndexes, previewUpdate);
|
|
27513
|
+
return directoryIndexes === current.directoryIndexes ? current : {
|
|
27514
|
+
...current,
|
|
27515
|
+
directoryIndexes
|
|
27516
|
+
};
|
|
27517
|
+
});
|
|
27518
|
+
}, [sessionStateRef, sidebarStore]);
|
|
26226
27519
|
const clearSelectedSidebarSelection = import_react.useCallback(() => {
|
|
26227
27520
|
sidebarStore.setSelectedSidebarSessionKeys((current) => current.length === 0 ? current : []);
|
|
26228
27521
|
sidebarStore.setSidebarSessionSelectionAnchor((current) => current ? "" : current);
|
|
@@ -26255,6 +27548,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26255
27548
|
removeOptimisticUserMessage,
|
|
26256
27549
|
addOptimisticSidebarSession,
|
|
26257
27550
|
removeOptimisticSidebarSession,
|
|
27551
|
+
updateOptimisticSidebarSessionPreview,
|
|
26258
27552
|
setSidebarDirectories: sidebarStore.setSidebarDirectories,
|
|
26259
27553
|
setStoredDraftDirectory,
|
|
26260
27554
|
setDraftSessionLoadingOwnerKey,
|
|
@@ -26311,10 +27605,6 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26311
27605
|
const createSessionPromise = requestCreateSession(nextCwd);
|
|
26312
27606
|
handleSelectSession(void 0);
|
|
26313
27607
|
clearSelectedSidebarSelection();
|
|
26314
|
-
if (shouldCloseMobileSidebar) {
|
|
26315
|
-
pendingMobileSidebarPromptFocusRef.current = true;
|
|
26316
|
-
setOpenMobile(false);
|
|
26317
|
-
} else focusPrompt();
|
|
26318
27608
|
setAwaitingFirstTurn(false);
|
|
26319
27609
|
setPendingMessages((current) => current.length === 0 ? current : []);
|
|
26320
27610
|
const nextState = createOptimisticDraftSessionState({
|
|
@@ -26325,6 +27615,10 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26325
27615
|
sessionStateRef.current = nextState;
|
|
26326
27616
|
conversationItemsStore.setItems(nextState.items);
|
|
26327
27617
|
setSessionState(nextState);
|
|
27618
|
+
if (shouldCloseMobileSidebar) {
|
|
27619
|
+
pendingMobileSidebarPromptFocusRef.current = true;
|
|
27620
|
+
setOpenMobile(false);
|
|
27621
|
+
} else focusPrompt();
|
|
26328
27622
|
if (await createSessionPromise) return;
|
|
26329
27623
|
if (sessionStateRef.current.sessionKey !== optimisticSessionKey) return;
|
|
26330
27624
|
sessionStateRef.current = previousState;
|
|
@@ -26711,7 +28005,8 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26711
28005
|
hasAvailableModels: sessionStateRef.current.availableModels.length > 0,
|
|
26712
28006
|
isMobile,
|
|
26713
28007
|
selectedSidebarSessions,
|
|
26714
|
-
sessionFile: sessionState.sessionFile
|
|
28008
|
+
sessionFile: sessionState.sessionFile,
|
|
28009
|
+
terminalPanelOpen
|
|
26715
28010
|
});
|
|
26716
28011
|
const buildCommandPaletteCommands = () => {
|
|
26717
28012
|
const commandState = commandPaletteStateRef.current;
|
|
@@ -26762,6 +28057,21 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
26762
28057
|
],
|
|
26763
28058
|
onSelect: toggleGitPanel
|
|
26764
28059
|
},
|
|
28060
|
+
{
|
|
28061
|
+
id: "toggle-terminal",
|
|
28062
|
+
group: "Workspace",
|
|
28063
|
+
title: commandState.isMobile ? "Toggle terminal tab" : commandState.terminalPanelOpen ? "Close terminal" : "Open terminal",
|
|
28064
|
+
description: commandState.isMobile ? "Switch the mobile terminal tab on or off" : "Toggle the bottom terminal panel",
|
|
28065
|
+
shortcut: formatShortcutLabel("Control+`"),
|
|
28066
|
+
keywords: [
|
|
28067
|
+
"terminal",
|
|
28068
|
+
"shell",
|
|
28069
|
+
"console",
|
|
28070
|
+
"bottom",
|
|
28071
|
+
"panel"
|
|
28072
|
+
],
|
|
28073
|
+
onSelect: toggleTerminalPanel
|
|
28074
|
+
},
|
|
26765
28075
|
{
|
|
26766
28076
|
id: "commit-changes",
|
|
26767
28077
|
group: "Git",
|
|
@@ -27126,6 +28436,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
27126
28436
|
conversationFrameRef.current?.scrollConversationToTop();
|
|
27127
28437
|
},
|
|
27128
28438
|
toggleGitPanel,
|
|
28439
|
+
toggleTerminalPanel,
|
|
27129
28440
|
toggleHideThinking,
|
|
27130
28441
|
toggleHideToolBlocks,
|
|
27131
28442
|
cycleThinkingLevel
|
|
@@ -27266,12 +28577,14 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
27266
28577
|
defaultNewSessionDirectory,
|
|
27267
28578
|
displaySessionCwd,
|
|
27268
28579
|
gitPanelOpen,
|
|
28580
|
+
terminalPanelOpen,
|
|
27269
28581
|
loadingDisplaySessionTitle,
|
|
27270
28582
|
currentSessionPinned,
|
|
27271
28583
|
displaySettingsStore,
|
|
27272
28584
|
isSessionViewLoading,
|
|
27273
28585
|
newSessionDirectoryOptions,
|
|
27274
28586
|
onToggleGitPanel: toggleGitPanel,
|
|
28587
|
+
onToggleTerminalPanel: toggleTerminalPanel,
|
|
27275
28588
|
sessionStore,
|
|
27276
28589
|
viewerContextId
|
|
27277
28590
|
}),
|
|
@@ -27291,6 +28604,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
27291
28604
|
displaySettingsStore,
|
|
27292
28605
|
fileInputRef,
|
|
27293
28606
|
gitPanelOpen,
|
|
28607
|
+
terminalPanelOpen,
|
|
27294
28608
|
hiddenThinkingPreviewStore,
|
|
27295
28609
|
isSessionViewLoading,
|
|
27296
28610
|
isSubmitting,
|
|
@@ -27308,6 +28622,7 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
|
|
|
27308
28622
|
onAddDiffLineComment: addComposerDiffLineComment,
|
|
27309
28623
|
onOpenFileViewTab: openFileViewTab,
|
|
27310
28624
|
onReorderFileViewTabs: reorderFileViewTabs,
|
|
28625
|
+
onCloseTerminalPanel: closeTerminalPanel,
|
|
27311
28626
|
rightSidebarStore,
|
|
27312
28627
|
sessionStore,
|
|
27313
28628
|
store: composerStore,
|