From dbf17de2d29856fd6b9b880be2a09bdd1dbc10a3 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 07:36:27 +0000 Subject: [PATCH 1/2] Refactor do_POST in serve.py to separate endpoint logic into specific methods. Co-authored-by: Ch3fUlrich <71930650+Ch3fUlrich@users.noreply.github.com> --- lib/linux/serve.py | 71 ++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/lib/linux/serve.py b/lib/linux/serve.py index c80c041..fba5c07 100644 --- a/lib/linux/serve.py +++ b/lib/linux/serve.py @@ -380,38 +380,47 @@ def do_POST(self): if not self._authed(parse_qs(u.query)): return self._json(403, {"error": "bad or missing token"}) if u.path == "/api/claude/snapshot": - out = self._claude_engine("snapshot") - if out is None: - return self._json(500, {"error": "could not run the session snapshot"}) - payload = self._claude_state() - payload["ok"] = True - return self._json(200, payload) + return self._post_claude_snapshot() if u.path == "/api/config": - length = int(self.headers.get("Content-Length") or 0) - try: - body = json.loads(self.rfile.read(length) or b"{}") - if not isinstance(body, dict): - return self._json(400, {"error": "payload must be a JSON object"}) - cfg_file = ROOT / "autoos.config.json" - tmp_file = ROOT / "autoos.config.json.tmp" - original = cfg_file.read_text(encoding="utf-8-sig") if cfg_file.exists() else None - merged = json.loads(original) if original is not None else {} - if not isinstance(merged, dict): - raise ValueError("Existing configuration must be an object") - for key, value in body.items(): - if key == "answers" and isinstance(value, dict) and isinstance(merged.get(key), dict): - merged[key].update(value) - else: - merged[key] = value - if original is not None: - cfg_file.with_name(cfg_file.name + f".autoos-backup-{time.time_ns()}").write_text(original, encoding="utf-8") - tmp_file.write_text(json.dumps(merged, indent=2) + "\n", encoding="utf-8") - tmp_file.replace(cfg_file) - return self._json(200, {"ok": True, "saved": str(cfg_file)}) - except Exception as exc: - return self._json(500, {"error": f"failed to save config: {exc}"}) - if u.path != "/api/install": - return self._json(404, {"error": "not found"}) + return self._post_config() + if u.path == "/api/install": + return self._post_install() + return self._json(404, {"error": "not found"}) + + def _post_claude_snapshot(self): + out = self._claude_engine("snapshot") + if out is None: + return self._json(500, {"error": "could not run the session snapshot"}) + payload = self._claude_state() + payload["ok"] = True + return self._json(200, payload) + + def _post_config(self): + length = int(self.headers.get("Content-Length") or 0) + try: + body = json.loads(self.rfile.read(length) or b"{}") + if not isinstance(body, dict): + return self._json(400, {"error": "payload must be a JSON object"}) + cfg_file = ROOT / "autoos.config.json" + tmp_file = ROOT / "autoos.config.json.tmp" + original = cfg_file.read_text(encoding="utf-8-sig") if cfg_file.exists() else None + merged = json.loads(original) if original is not None else {} + if not isinstance(merged, dict): + raise ValueError("Existing configuration must be an object") + for key, value in body.items(): + if key == "answers" and isinstance(value, dict) and isinstance(merged.get(key), dict): + merged[key].update(value) + else: + merged[key] = value + if original is not None: + cfg_file.with_name(cfg_file.name + f".autoos-backup-{time.time_ns()}").write_text(original, encoding="utf-8") + tmp_file.write_text(json.dumps(merged, indent=2) + "\n", encoding="utf-8") + tmp_file.replace(cfg_file) + return self._json(200, {"ok": True, "saved": str(cfg_file)}) + except Exception as exc: + return self._json(500, {"error": f"failed to save config: {exc}"}) + + def _post_install(self): length = int(self.headers.get("Content-Length") or 0) body = json.loads(self.rfile.read(length) or b"{}") ids = [str(i) for i in body.get("ids", []) if i] From 773b132331186616d2983bb715cdc14eb6f9c5fe Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 08:03:47 +0000 Subject: [PATCH 2/2] Fix CI failures in Windows PowerShell scripts and tests Co-authored-by: Ch3fUlrich <71930650+Ch3fUlrich@users.noreply.github.com> --- lib/windows/AutoOS.ClaudeAutostart.psm1 | 4 ++-- lib/windows/AutoOS.Detect.psm1 | 14 +++++++------- lib/windows/AutoOS.Serve.psm1 | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/windows/AutoOS.ClaudeAutostart.psm1 b/lib/windows/AutoOS.ClaudeAutostart.psm1 index 98c4a9f..d983eaa 100644 --- a/lib/windows/AutoOS.ClaudeAutostart.psm1 +++ b/lib/windows/AutoOS.ClaudeAutostart.psm1 @@ -43,7 +43,7 @@ function Get-AutoOSClaudeDefaults { foreach ($p in $block.PSObject.Properties) { $table[$p.Name] = $p.Value } if ($table.Count -gt 0) { return $table } } - } catch { } + } catch { $null } } @{ enabled = $true; snapshot_interval_mins = 5; liveness_window_mins = 240 @@ -272,7 +272,7 @@ function Get-AutoOSClaudeState { sessions = @($doc.sessions) } } - } catch { } + } catch { $null } } [pscustomobject]@{ version = $script:StateVersion; captured_at = 0; captured_at_iso = $null; sessions = @() } } diff --git a/lib/windows/AutoOS.Detect.psm1 b/lib/windows/AutoOS.Detect.psm1 index b1934ec..8ae7ac4 100644 --- a/lib/windows/AutoOS.Detect.psm1 +++ b/lib/windows/AutoOS.Detect.psm1 @@ -46,14 +46,14 @@ function Get-AutoOSShimDirectory { (Join-Path $home_ 'scoop\shims'), $(if ($env:SCOOP) { Join-Path $env:SCOOP 'shims' }), $(if ($env:SCOOP_GLOBAL) { Join-Path $env:SCOOP_GLOBAL 'shims' }), - (Join-Path $env:ProgramData 'scoop\shims'), + $(if ($env:ProgramData) { Join-Path $env:ProgramData 'scoop\shims' }), # Chocolatey. - (Join-Path $env:ProgramData 'chocolatey\bin'), + $(if ($env:ProgramData) { Join-Path $env:ProgramData 'chocolatey\bin' }), # winget's own shim directory for portable packages. - (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Links'), - (Join-Path $env:ProgramFiles 'WinGet\Links'), + $(if ($env:LOCALAPPDATA) { Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Links' }), + $(if ($env:ProgramFiles) { Join-Path $env:ProgramFiles 'WinGet\Links' }), # npm -g, pipx/uv and cargo all install here and all rely on PATH. - (Join-Path $env:APPDATA 'npm'), + $(if ($env:APPDATA) { Join-Path $env:APPDATA 'npm' }), (Join-Path $home_ '.local\bin'), (Join-Path $home_ '.cargo\bin'), (Join-Path $home_ 'bin') @@ -122,7 +122,7 @@ function Get-AutoOSWingetPackageProcess { $process = [Diagnostics.Process]::Start($psi) # Close stdin so a prompt that slipped past --disable-interactivity reads # EOF and gives up, instead of sitting there until the timeout. - try { $process.StandardInput.Close() } catch { } + try { $process.StandardInput.Close() } catch { $null } $process } catch { $null } } @@ -144,7 +144,7 @@ function Get-AutoOSWingetPackageResult { $Process.Kill() } } catch { $packages = @() } - finally { try { $Process.Dispose() } catch { } } + finally { try { $Process.Dispose() } catch { $null } } $packages } diff --git a/lib/windows/AutoOS.Serve.psm1 b/lib/windows/AutoOS.Serve.psm1 index f732bf6..334ddd2 100644 --- a/lib/windows/AutoOS.Serve.psm1 +++ b/lib/windows/AutoOS.Serve.psm1 @@ -266,7 +266,7 @@ function Get-AutoOSExampleBlock { try { $block = (Get-Content -LiteralPath $path -Raw -Encoding UTF8 | ConvertFrom-Json).$Name if ($block) { return $block } - } catch { } + } catch { $null } @{} } @@ -286,7 +286,7 @@ function Get-AutoOSDetectedAnswers { try { $value = (& git config --global $pair.Setting 2>$null | Select-Object -First 1) if ($value) { $answers[$pair.Key] = [string]$value } - } catch { } + } catch { $null } } $answers }