feat: add safe Javis startup script
This commit is contained in:
@@ -4,34 +4,46 @@ Javis ist ein langfristiges, lokal-first ausgerichtetes Projekt für einen pers
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
Der erste lokale Textchat funktioniert auf Windows mit Ollama und `qwen3:8b`.
|
||||
Er bietet echte lokale Modellantworten ohne Cloud-Fallback, neue und fortsetzbare
|
||||
Sitzungen sowie SQLite-Persistenz außerhalb des Repositories.
|
||||
Der lokale Textchat funktioniert auf Windows mit Ollama und `qwen3:8b`.
|
||||
Ein optionaler Gemini-Free-Provider ist auf einem Feature-Branch vorbereitet;
|
||||
Datenschutzrouter, Nullkostenmodus und lokales Fallback sind automatisiert
|
||||
getestet, aber noch nicht von Pascal mit einem echten Key abgenommen.
|
||||
|
||||
Noch nicht implementiert sind Obsidian-Zugriff, Serverzugriff, Sprache, Mobile
|
||||
Client und Living Mind.
|
||||
|
||||
## Lokaler Start
|
||||
## Einfacher Start
|
||||
|
||||
Ollama läuft in einem eigenen Terminal ausschließlich auf localhost:
|
||||
Aus dem Repository:
|
||||
|
||||
```powershell
|
||||
$env:OLLAMA_MODELS = 'D:\Javis-Data\ollama-models'
|
||||
$env:OLLAMA_HOST = '127.0.0.1:11434'
|
||||
& 'D:\Javis-Tools\ollama\ollama.exe' serve
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\start-javis.ps1
|
||||
```
|
||||
|
||||
Der Chat startet aus dem Repository in einem zweiten Terminal:
|
||||
Das Skript findet die portablen Werkzeuge standardmäßig relativ zum Laufwerk des
|
||||
Repositories, setzt Variablen nur für seinen Prozess, prüft Ollama ausschließlich
|
||||
auf `127.0.0.1:11434`, startet es bei Bedarf versteckt und öffnet den Chat. Es
|
||||
ändert weder PATH, Registry, Autostart, Windows-Dienste noch die systemweite
|
||||
PowerShell-Ausführungsrichtlinie.
|
||||
|
||||
```powershell
|
||||
$env:UV_CACHE_DIR = 'D:\Javis-Tools\uv-cache'
|
||||
$env:JAVIS_DATA_DIR = 'D:\Javis-Data\runtime'
|
||||
& 'D:\Javis-Tools\uv\uv.exe' run javis chat
|
||||
```
|
||||
Abweichende Pfade sind über die Skriptparameter `-UvPath`, `-OllamaPath`,
|
||||
`-OllamaModels`, `-DataDir`, `-UvCacheDir` und `-PythonInstallDir` oder die
|
||||
entsprechenden `JAVIS_*`-Umgebungsvariablen möglich.
|
||||
|
||||
Im Chat zeigt `/help` alle Befehle. Ohne `JAVIS_DATA_DIR` nutzt Javis einen
|
||||
sicheren benutzerspezifischen Plattformstandard.
|
||||
|
||||
Gemini bleibt standardmäßig aus. Die spätere lokale Einrichtung erfolgt ohne
|
||||
Key in der Konfigurationsdatei:
|
||||
|
||||
```powershell
|
||||
& 'D:\Javis-Tools\uv\uv.exe' run javis configure gemini
|
||||
& 'D:\Javis-Tools\uv\uv.exe' run javis secrets set gemini
|
||||
```
|
||||
|
||||
Der Key wird bei der zweiten Zeile verdeckt eingegeben und im
|
||||
Betriebssystem-Keyring gespeichert, niemals in Git oder TOML.
|
||||
|
||||
## Grundregeln
|
||||
|
||||
- Plattformunabhängiger modularer Monolith, voraussichtlich in Python.
|
||||
|
||||
+11
-5
@@ -95,6 +95,9 @@ Rootserver:
|
||||
- Der echte CLI-Chat verwendet nun `hybrid/auto`; der Key wird erst vor einem
|
||||
zulässigen Cloudaufruf gelesen. `/provider`, `/privacy` und `/status` zeigen
|
||||
ausschließlich bereinigte Modi, Entscheidungen und Zähler.
|
||||
- `scripts/start-javis.ps1` verifiziert das Repository, setzt nur
|
||||
Prozessvariablen, prüft Ollama auf Loopback, startet es bei Bedarf versteckt
|
||||
und wartet begrenzt. Pfade sind per Parameter oder `JAVIS_*` überschreibbar.
|
||||
|
||||
## Aktuelle Architektur
|
||||
|
||||
@@ -151,6 +154,8 @@ Rootserver:
|
||||
- Hybridprovider in die CLI verdrahtet, sicheren Aktivierungsdialog und
|
||||
bereinigte Provider-/Datenschutz-/Statusbefehle ergänzt.
|
||||
- Lesender Ollama-Status prüft nur Loopback-Erreichbarkeit und Modellliste.
|
||||
- Sicheres PowerShell-Startskript und kompakte Startdokumentation ergänzt; keine
|
||||
PATH-, Registry-, Autostart-, Dienst- oder Richtlinienänderung.
|
||||
|
||||
## Aktuelle Tests
|
||||
|
||||
@@ -165,8 +170,8 @@ Letzter bestätigter Projektstand:
|
||||
- uv-Lock und `uv sync --dev`: bestanden
|
||||
- Python in `.venv`: 3.12.13
|
||||
- Ruff in `.venv`: 0.16.0
|
||||
- Unit-Tests: 59 bestanden; CLI-Befehle, doppelte Bestätigung, verzögertes
|
||||
Key-Laden und Ollama-Status sind abgedeckt
|
||||
- Unit-Tests: 60 bestanden; Startskript-Sicherheitsregeln zusätzlich abgedeckt
|
||||
- PowerShell-Syntax des Startskripts: erfolgreich geparst
|
||||
- Ruff Lint: bestanden
|
||||
- Ruff Formatprüfung: bestanden
|
||||
|
||||
@@ -252,9 +257,10 @@ Abnahmestatus:
|
||||
|
||||
Auf dem bestehenden Feature-Branch als nächstes einzelnes Arbeitspaket:
|
||||
|
||||
1. sicheres `scripts/start-javis.ps1` ohne Systemänderungen ergänzen
|
||||
2. Start- und Einrichtungsablauf kompakt dokumentieren und automatisiert prüfen
|
||||
3. noch keine echte Cloudanfrage ausführen und noch nicht nach `main` mergen
|
||||
1. geforderte Resttests ergänzen, insbesondere Timeout und bereinigte Fehler
|
||||
2. vollständige Qualitäts-, Gitignore-, Secret- und Außenbereichsprüfung ausführen
|
||||
3. Abschlussdokumentation aktualisieren, Feature-Branch pushen und vor Pascals
|
||||
manuellem Live-Test stoppen; nicht nach `main` mergen
|
||||
|
||||
Keinen API-Key in Chat, Git, Obsidian, Logs oder Dokumentation übernehmen.
|
||||
|
||||
|
||||
+18
-10
@@ -35,19 +35,27 @@ $env:UV_CACHE_DIR = 'D:\Javis-Tools\uv-cache'
|
||||
& 'D:\Javis-Tools\uv\uv.exe' run ruff format --check .
|
||||
```
|
||||
|
||||
Vor dem Chat wird Ollama in einem eigenen Terminal gestartet:
|
||||
## Komfortabler Start
|
||||
|
||||
Der normale Start aus dem Repository benötigt nur:
|
||||
|
||||
```powershell
|
||||
$env:OLLAMA_MODELS = 'D:\Javis-Data\ollama-models'
|
||||
$env:OLLAMA_HOST = '127.0.0.1:11434'
|
||||
& 'D:\Javis-Tools\ollama\ollama.exe' serve
|
||||
powershell -ExecutionPolicy Bypass -File .\scripts\start-javis.ps1
|
||||
```
|
||||
|
||||
Danach:
|
||||
`-ExecutionPolicy Bypass` gilt nur für diesen Prozess; das Skript ändert keine
|
||||
systemweite Richtlinie. Es prüft Ollama auf Loopback, startet bei Bedarf die
|
||||
portable Laufzeit versteckt und wartet höchstens 15 Sekunden. Werkzeug- und
|
||||
Datenpfade können mit Parametern oder folgenden Umgebungsvariablen überschrieben
|
||||
werden:
|
||||
|
||||
```powershell
|
||||
$env:JAVIS_DATA_DIR = 'D:\Javis-Data\runtime'
|
||||
& 'D:\Javis-Tools\uv\uv.exe' run javis chat
|
||||
```
|
||||
- `JAVIS_UV_PATH`
|
||||
- `JAVIS_OLLAMA_PATH`
|
||||
- `JAVIS_OLLAMA_MODELS`
|
||||
- `JAVIS_DATA_DIR`
|
||||
- `JAVIS_UV_CACHE_DIR`
|
||||
- `JAVIS_PYTHON_INSTALL_DIR`
|
||||
|
||||
Die absoluten Pfade sind ausschließlich lokale Entwicklungsdokumentation. Der Anwendungscode darf keine festen Windows-Pfade enthalten.
|
||||
Die Standardpfade werden vom Laufwerk des Repositorys abgeleitet; persönliche
|
||||
Windows-Benutzerpfade sind nicht eingebrannt. PATH, Registry, Autostart und
|
||||
Windows-Dienste bleiben unverändert.
|
||||
|
||||
@@ -58,7 +58,9 @@ Stand: lokaler Textchat auf `main`, 30.07.2026.
|
||||
- `javis configure gemini` mit doppelter ausdrücklicher Bestätigung
|
||||
- echter Chat auf Hybridprovider verdrahtet; Key wird verzögert geladen
|
||||
- `/provider`, `/privacy` und `/status` geben keine Inhalte oder Keywerte aus
|
||||
- 59 Unit-Tests aktuell erfolgreich; Ruff-Format und Lint sauber
|
||||
- sicheres `scripts/start-javis.ps1` mit relativer Repositoryprüfung,
|
||||
Loopback-Ollama und überschreibbaren externen Pfaden
|
||||
- 60 Unit-Tests aktuell erfolgreich; PowerShell-Syntax, Ruff-Format und Lint sauber
|
||||
|
||||
## Nicht implementiert
|
||||
|
||||
@@ -83,6 +85,6 @@ Living-Mind-Frontend und automatische Ollama-Prozessverwaltung.
|
||||
Ollama wird bewusst manuell in einem eigenen Terminal gestartet. Antworten werden
|
||||
noch nicht gestreamt; Sitzungen haben noch keine Titel, Suche oder Löschfunktion.
|
||||
`qwen3:8b` ist nicht automatisch für die GTX 1050 des späteren Zielhosts geeignet.
|
||||
Das sichere Startskript und die abschließende Bedienungsdokumentation fehlen noch.
|
||||
Abschließende Resttests, Qualitätsprüfung und Feature-Branch-Push fehlen noch.
|
||||
Es wurde kein echter API-Key angefordert, angezeigt oder konfiguriert und keine
|
||||
Cloudanfrage ausgeführt.
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$UvPath,
|
||||
[string]$OllamaPath,
|
||||
[string]$OllamaModels,
|
||||
[string]$DataDir,
|
||||
[string]$UvCacheDir,
|
||||
[string]$PythonInstallDir
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Get-ConfiguredPath {
|
||||
param(
|
||||
[string]$ParameterValue,
|
||||
[string]$EnvironmentName,
|
||||
[string]$DefaultValue
|
||||
)
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($ParameterValue)) {
|
||||
return [System.IO.Path]::GetFullPath($ParameterValue)
|
||||
}
|
||||
$environmentValue = [System.Environment]::GetEnvironmentVariable($EnvironmentName)
|
||||
if (-not [string]::IsNullOrWhiteSpace($environmentValue)) {
|
||||
return [System.IO.Path]::GetFullPath($environmentValue)
|
||||
}
|
||||
return [System.IO.Path]::GetFullPath($DefaultValue)
|
||||
}
|
||||
|
||||
function Test-OllamaReady {
|
||||
try {
|
||||
$null = Invoke-RestMethod `
|
||||
-Uri 'http://127.0.0.1:11434/api/version' `
|
||||
-Method Get `
|
||||
-TimeoutSec 2
|
||||
return $true
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
$repositoryRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $repositoryRoot 'pyproject.toml') -PathType Leaf)) {
|
||||
throw "Das Repository konnte relativ zum Startskript nicht verifiziert werden."
|
||||
}
|
||||
|
||||
$driveRoot = [System.IO.Path]::GetPathRoot($repositoryRoot)
|
||||
$resolvedUv = Get-ConfiguredPath `
|
||||
-ParameterValue $UvPath `
|
||||
-EnvironmentName 'JAVIS_UV_PATH' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Tools\uv\uv.exe')
|
||||
$resolvedOllama = Get-ConfiguredPath `
|
||||
-ParameterValue $OllamaPath `
|
||||
-EnvironmentName 'JAVIS_OLLAMA_PATH' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Tools\ollama\ollama.exe')
|
||||
$resolvedModels = Get-ConfiguredPath `
|
||||
-ParameterValue $OllamaModels `
|
||||
-EnvironmentName 'JAVIS_OLLAMA_MODELS' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Data\ollama-models')
|
||||
$resolvedData = Get-ConfiguredPath `
|
||||
-ParameterValue $DataDir `
|
||||
-EnvironmentName 'JAVIS_DATA_DIR' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Data\runtime')
|
||||
$resolvedCache = Get-ConfiguredPath `
|
||||
-ParameterValue $UvCacheDir `
|
||||
-EnvironmentName 'JAVIS_UV_CACHE_DIR' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Tools\uv-cache')
|
||||
$resolvedPython = Get-ConfiguredPath `
|
||||
-ParameterValue $PythonInstallDir `
|
||||
-EnvironmentName 'JAVIS_PYTHON_INSTALL_DIR' `
|
||||
-DefaultValue (Join-Path $driveRoot 'Javis-Tools\python')
|
||||
|
||||
if (-not (Test-Path -LiteralPath $resolvedUv -PathType Leaf)) {
|
||||
throw "uv.exe wurde nicht gefunden: $resolvedUv"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $resolvedModels -PathType Container)) {
|
||||
throw "Der externe Ollama-Modellpfad wurde nicht gefunden: $resolvedModels"
|
||||
}
|
||||
|
||||
$env:JAVIS_DATA_DIR = $resolvedData
|
||||
$env:OLLAMA_MODELS = $resolvedModels
|
||||
$env:OLLAMA_HOST = '127.0.0.1:11434'
|
||||
$env:UV_CACHE_DIR = $resolvedCache
|
||||
$env:UV_PYTHON_INSTALL_DIR = $resolvedPython
|
||||
|
||||
if (-not (Test-OllamaReady)) {
|
||||
if (-not (Test-Path -LiteralPath $resolvedOllama -PathType Leaf)) {
|
||||
throw "Ollama ist nicht erreichbar und ollama.exe wurde nicht gefunden: $resolvedOllama"
|
||||
}
|
||||
Write-Host "Ollama wird lokal auf 127.0.0.1:11434 gestartet ..."
|
||||
$ollamaProcess = Start-Process `
|
||||
-FilePath $resolvedOllama `
|
||||
-ArgumentList 'serve' `
|
||||
-WindowStyle Hidden `
|
||||
-PassThru
|
||||
|
||||
$ready = $false
|
||||
for ($attempt = 1; $attempt -le 30; $attempt++) {
|
||||
if ($ollamaProcess.HasExited) {
|
||||
throw "Ollama wurde beendet, bevor die lokale API bereit war."
|
||||
}
|
||||
Start-Sleep -Milliseconds 500
|
||||
if (Test-OllamaReady) {
|
||||
$ready = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $ready) {
|
||||
throw "Ollama war nach 15 Sekunden nicht unter 127.0.0.1:11434 erreichbar."
|
||||
}
|
||||
}
|
||||
|
||||
Push-Location $repositoryRoot
|
||||
try {
|
||||
& $resolvedUv run javis chat
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class StartScriptTests(unittest.TestCase):
|
||||
def test_script_is_local_overridable_and_avoids_system_changes(self) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[2]
|
||||
script = (repository_root / "scripts" / "start-javis.ps1").read_text(encoding="utf-8")
|
||||
normalized = script.lower()
|
||||
|
||||
self.assertIn("$psscriptroot", normalized)
|
||||
self.assertIn("http://127.0.0.1:11434/api/version", normalized)
|
||||
self.assertIn("-windowstyle hidden", normalized)
|
||||
self.assertIn("javis_uv_path", normalized)
|
||||
self.assertIn("javis_ollama_path", normalized)
|
||||
self.assertIn("javis_data_dir", normalized)
|
||||
self.assertIn("run javis chat", normalized)
|
||||
self.assertNotIn("c:\\users\\", normalized)
|
||||
for forbidden in (
|
||||
"set-executionpolicy",
|
||||
"setx ",
|
||||
"new-service",
|
||||
"schtasks",
|
||||
"hkey_",
|
||||
):
|
||||
self.assertNotIn(forbidden, normalized)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user