Entscheidungen aus dem Testbetrieb umgesetzt (#572): #577 #579 #581 #589 #193 #205 #594 #595 #597 #598 #599 #588

- Engine: leere Antworten nachfassen, Aufgaben enden mit Ergebniszeile (EmptyResponse/Incomplete),
  gleiche Fehlschlaege erkennen (RepeatedFailure), Zeitzeile vor Chatnachrichten,
  Werkzeugergebnisse gerahmt, Vorpruefung vor dem Staging, Belegkosten wie RunUsage
- Staging: gescheiterte Freigaben als Failed; AgentEditor-Aenderungen freigabepflichtig,
  Selbstbearbeitung gesperrt (allowSelfEdit)
- Taskboard: Termine beim Anlegen pruefen, naechster/letzter Lauf, pausieren, Sofortlauf,
  Kostenprognose, Hinweis auf wachsenden Kontext; Jobs-Reiter und /api/jobs entfernt
- Release: Instanzmanager samt Weboberflaeche im Paket, setup.json fragt manager.json ab,
  Token nicht mehr ins systemd-Journal
Version 0.1.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-15 11:23:10 +02:00
co-authored by Claude Opus 5
parent 8ab9d99abe
commit 0b6ea73ec1
42 changed files with 2646 additions and 512 deletions
+47
View File
@@ -34,6 +34,7 @@ from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
PROJECT = REPO / "src" / "ClawdDotNet.Desktop" / "ClawdDotNet.Desktop.csproj"
MANAGER_PROJECT = REPO / "src" / "ClawdDotNet.ManagerApp" / "ClawdDotNet.ManagerApp.csproj"
CONFIG = REPO / "deploy" / "packager.config.json"
PACKAGER = Path(
"J:/Softwareprojekte/Deploymentcenter/client-dotnet/Deploymentcenter.Packager"
@@ -68,6 +69,52 @@ def publish(rid: str, out_dir: Path) -> None:
"-o", str(out_dir), "--nologo", "-v", "q",
])
# #588: Der Instanzmanager samt Weboberflaeche gehoert ins selbe Paket. Vorher kam
# ueber den Installer nur die Desktop-Anwendung an - keine Oberflaeche im Browser, und
# der Manager, der laut Konzept neben der Instanz liegt, fehlte ganz.
manager_dir = out_dir.parent / f"{out_dir.name}-manager"
if manager_dir.exists():
shutil.rmtree(manager_dir)
manager_dir.mkdir(parents=True)
run([
"dotnet", "publish", str(MANAGER_PROJECT),
"-c", "Release", "-r", rid, "--self-contained", "false",
"-o", str(manager_dir), "--nologo", "-v", "q",
])
merge_manager(manager_dir, out_dir)
def merge_manager(src: Path, dst: Path) -> None:
"""Legt den Manager neben die Instanz.
Beide Programme teilen viele Bibliotheken. Liegt eine schon da, muss sie bytegleich
sein - sonst ersetzte der zweite Publish die Fassung des ersten still, und eines der
beiden Programme liefe mit einer Bibliothek, gegen die es nicht gebaut wurde. Das
faellt nicht beim Bauen auf, sondern beim Kunden.
"""
conflicts = []
copied = 0
for f in sorted(src.rglob("*")):
if not f.is_file():
continue
rel = f.relative_to(src)
target = dst / rel
if target.exists():
if target.read_bytes() != f.read_bytes():
conflicts.append(str(rel))
continue
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(f, target)
copied += 1
if conflicts:
sys.exit("Instanz und Manager liefern unterschiedliche Fassungen derselben Datei:\n "
+ "\n ".join(conflicts[:30]))
shutil.rmtree(src)
print(f" Instanzmanager: {copied} Datei(en) neben die Instanz gelegt")
def fetch_agent(rid: str, out_dir: Path, agent_file: Path | None = None) -> None:
"""Holt den update-agent und prueft die Pruefsumme.