feat: Windows-Kompatibilität

- WorkspaceHelper: Zentrale Hilfsmethoden (IsWindows, TempDir, IsSubPathOf,
  GetRelativePath, ShellExecutable, ShellArguments)
- ToolService: execute nutzt cmd.exe auf Windows, GetRelativePath mit
  Forward-Slashes, IsSubPathOf für case-insensitive Pfadprüfung
- SessionEndpoint: /tmp → Path.GetTempPath(), bash → cmd.exe,
  Fire-and-forget via .bat statt systemd-run auf Windows
- ChatService: /tmp → WorkspaceHelper.TempDir
- MemoryService: IsSubPathOf + GetRelativePath
- WorkspaceEndpoint: HandleBrowse zeigt Laufwerke auf Windows,
  IsSubPathOf statt StartsWith
- InfoEndpoint: gott.exe auf Windows, isWindows-Flag in API-Response
- Frontend: File-Explorer mit Laufwerks-Navigation auf Windows
This commit is contained in:
Meleki committed 2026-03-09 11:35:04 +01:00
1 parent 79899a6981
commit 5d090e160b
9 files changed
+155 -61

No files matched your search

+10 -3
View File
@@ -535,7 +535,7 @@ function openFolderBrowser(opts = {}) {
_feState._keyHandler = (e) => { if (e.key === 'Escape') closeFileExplorer(); };
document.addEventListener('keydown', _feState._keyHandler);
fbLoadDir(opts.startPath || '/');
fbLoadDir(opts.startPath || (serverIsWindows ? '' : '/'));
}
async function fbLoadDir(absPath) {
@@ -581,7 +581,7 @@ async function fbLoadDir(absPath) {
const currentNorm = data.current.replace(/\/+$/, '');
const atBase = _feState.basePath && currentNorm === _feState.basePath;
const atRoot = currentNorm === '' || currentNorm === '/';
const atRoot = currentNorm === '' || currentNorm === '/' || (serverIsWindows && /^[A-Z]:$/i.test(currentNorm));
document.getElementById('feBack').disabled = atBase || (atRoot && _feState.history.length === 0);
} catch (e) {
sidebar.innerHTML = '<div class="fe-error">Netzwerk-Fehler</div>';
@@ -605,7 +605,14 @@ function fbGoBack() {
fbLoadDir(prev);
} else {
// Kein History-Eintrag → zum Parent navigieren
const parent = currentNorm.includes('/') ? currentNorm.substring(0, currentNorm.lastIndexOf('/')) || '/' : '/';
let parent;
if (serverIsWindows && /^[A-Z]:$/i.test(currentNorm)) {
parent = ''; // Laufwerk → zurück zur Laufwerksauswahl
} else if (serverIsWindows && /^[A-Z]:\/[^/]*$/i.test(currentNorm)) {
parent = currentNorm.substring(0, 2); // z.B. C:/Users → C:
} else {
parent = currentNorm.includes('/') ? currentNorm.substring(0, currentNorm.lastIndexOf('/')) || (serverIsWindows ? '' : '/') : (serverIsWindows ? '' : '/');
}
if (parent !== currentNorm) {
fbLoadDir(parent);
}
+2
View File
@@ -1,7 +1,9 @@
let buildTime = 0;
let serverIsWindows = false;
fetch('/api/info').then(r => r.json()).then(data => {
buildTime = data.buildTime || 0;
serverIsWindows = !!data.isWindows;
updateTitle();
setInterval(updateTitle, 1000);
});