Replaces the single monolithic LLM call (which timed out on PRs >~150KB)
with a batching strategy:
- Changed files are grouped into batches capped at 2500 lines each,
always respecting file boundaries (no file is split across batches)
- Each batch is sent as an independent LLM call (max-time 600s)
- Verdicts are aggregated: harshest verdict across all batches wins
- Single-batch PRs produce identical output to the old workflow
- Multi-batch PRs get a combined review with per-batch sections and
an Overall Verdict line at the end
- Partial failures are tolerated: if some batches succeed, the review
is posted with a note about any failed batches
- Cleanup removes /tmp/pr_batch_*.txt alongside existing temp files
qwen3.5-122b-think on a 253KB prompt was consistently hitting the 300s
--max-time wall. --retry-max-time also equalled --max-time, so retries
never fired. Now: 10 min per attempt, 2 retries, 20 min total budget.
handle_response() in client.rs already strips the {"data":...} wrapper
before returning to callers. Every proxmox module was calling .get("data")
a second time on the already-unwrapped Value, which always returned None
and caused all API responses to silently yield empty results or errors.
vm.rs had an additional bug: list_vms used POST on cluster/resources (a
GET-only endpoint) and dropped VMs with no cpu field via filter_map ?
instead of unwrap_or(0.0). Both corrected.
Affected modules: vm, ceph, ceph_cluster, certificates, acme, firewall,
sdn, ha, apt, updates, updates_ext, tasks, migration, metrics, shell,
auth_realm, views, backup — 18 files, 19 functions.
426 Rust tests pass. clippy -D warnings clean. tsc --noEmit clean.
Root cause: authenticate() tried to deserialize the Proxmox API response
directly into AuthResponse, but Proxmox wraps every response in
{"data": {...}}. This caused every reconnect attempt after app restart
to fail silently.
Additional fixes bundled in this commit:
- add_proxmox_cluster now authenticates immediately so the in-memory pool
always contains a live, ticketed client (not a bare unauthenticated stub)
- ProxmoxClient stores the CSRFPreventionToken and includes it in the
CSRFPreventionToken header on POST/PUT/DELETE requests (Proxmox requires
this for all mutating calls)
- accept-invalid-certs enabled on the reqwest Client so self-signed PVE
certificates do not block connections
- Removed double-unwrap of the data field in 10 commands (list_acls,
list_users, get_cluster_notes, search_proxmox_resources, get_node_status,
get_syslog, list_network_interfaces, get_subscription_status,
list_cluster_tasks, list_proxmox_containers) — handle_response already
strips the envelope before returning to callers
- Added connect_proxmox_cluster and disconnect_proxmox_cluster Tauri
commands so the UI can explicitly connect/disconnect sessions
- Wired RemotesPage Connect/Disconnect buttons to the real backend commands
- Updated and added tests covering envelope parsing, CSRF header logic,
already-unwrapped response handling, and the new connect/disconnect paths
Race condition in get_proxmox_client_for_cluster: two concurrent callers
for an uncached cluster could both authenticate and insert, with the second
overwriting the first. Re-check under write lock before inserting so the
later caller returns the already-stored client instead of overwriting it.
handleConnectRemote used getProxmoxCluster (a DB-only lookup) to set status
'connected', which passed even when the Proxmox API was unreachable. Replace
with pingProxmoxCluster, a new command that authenticates and calls
GET /api2/json/version, providing a real end-to-end connectivity test.
handleEditRemote used remove-then-add, leaving a gap where the record was
absent and silently lost if addProxmoxCluster failed. Replace with
updateProxmoxCluster, a new command that issues a single SQL UPDATE (plus
in-memory pool eviction) so the record is never transiently missing.
ActionsMenu useEffect added the mousedown listener only when open=true but
the dependency array contained open, causing ambiguity about cleanup timing.
Attach the listener unconditionally on mount (empty dep array) so there is
always exactly one add and one remove with no conditional branches.
New Rust tests cover update_proxmox_cluster not-found logic and ping error
message format (420 Rust + 386 frontend, zero failures).
Half-completed refactor left 68 Tauri command functions with orphaned
.ok_or_else() chains after the old clusters.get() pattern was removed
without inserting the replacement helper call. Also fixed two bugs in the
new get_proxmox_client_for_cluster helper: undeclared `clusters` variable
in the early-return check, and client_arc going out of scope before return.
fix(ai): enforce system-message-first ordering for strict LLM providers
Qwen3.5-122b (and other models via LiteLLM) reject requests where system
messages appear after user/assistant turns. Moved tool-calling format
and iteration-budget system messages to before history is appended.
Changed mid-loop iteration warning and forced-stop instruction from
system role to user role so they can safely appear mid-conversation.
fix(proxmox): Remotes actions menu and connect/disconnect behaviour
Replaced the non-functional "..." toast placeholder with a proper
ActionsMenu dropdown (Edit / Test Connection / Delete). Removed inline
emoji buttons folded into the menu. Connect now calls getProxmoxCluster
as a live connection test and reflects real status; disconnect marks the
remote disconnected locally. Remote status now maps correctly from the
backend ClusterInfoWithHealth.connected field instead of hardcoding
'connected' for every entry.
fix(proxmox): Ceph page no longer shows HEALTH_OK on non-Ceph clusters
Page now fetches real health data on mount. If getCephHealth fails the
page renders an informational notice rather than fake HEALTH_OK. When
Ceph is present, pools and OSDs are loaded and displayed live.
The Tauri v2 IPC layer expects camelCase parameter names. The frontend
was sending cluster_type (snake_case), causing the deserialization
failure with error 'command add_proxmox_cluster missing required key
clusterType'.
Changed proxmoxClient.ts line 28 from:
cluster_type: clusterType
to:
clusterType
This aligns with the project's convention where all multi-word
parameters use camelCase (clusterId, nodeId, vmId, etc.).
Fixes the 'Failed to add remote' error when adding new Proxmox remotes.
- Change password parameter from &str to String in add_proxmox_cluster
so Tauri v2 IPC can deserialize it (requires DeserializeOwned + Send)
- Construct full https:// URL with port in ProxmoxClient::get_api_url()
and authenticate() since the frontend strips the protocol before
sending the hostname
- Show actual error string in AddRemoteForm instead of generic fallback
(Tauri errors are plain strings, not Error instances)
- Update client tests to reflect bare-hostname input from the frontend
compile("memset_shim") produces libmemset_shim.a, not memset_shim.o, so the
previous cargo:rustc-link-arg pointed at a file that never exists. Switching to
get_compiler().to_command() compiles memset_s_shim.c directly to a .o file at
a known OUT_DIR path and passes it as a positional linker arg. A positional .o
is always included unconditionally, which also resolves the archive-extraction
ordering issue where -l flags only pull symbols that are already undefined at
that point in the link command.
- Use rustc-link-arg to directly link memset_shim.o object file
instead of -l flag, ensuring symbol is available regardless of
link order with libsodium_sys
- Add #[allow(dead_code)] to find_ollama_binary() which is only
used inside cfg(target_os = "macos") and cfg(target_os = "linux")
blocks, causing false positive warning when cross-compiling for Windows
- Add __MINGW32__ detection in memset_s_shim.c for proper EXPORT macro
- Add WIN32 and __WIN32__ defines when compiling the shim in build.rs
- The memset_explicit symbol is required by libsodium-sys-stable but not
available in MinGW runtime
- The shim is compiled as a static library and linked before libsodium
- Add __declspec(dllexport) to memset_explicit in memset_s_shim.c
- Explicitly link memset_shim library in build.rs for Windows MinGW target
- Fixes undefined reference to memset_explicit when building for x86_64-pc-windows-gnu
Cargo injects [env] entries directly into build script environments,
bypassing shell-level unset and env -u entirely. SODIUM_USE_PKG_CONFIG
was set to "0" in [env], which libsodium-sys-stable build.rs treats as
"pkg-config enabled" (env::var().is_ok() returns true for any value
including "0"). Combined with SODIUM_LIB_DIR set in the workflow, this
triggered the incompatibility panic on every build.
The original comment claiming this "avoids memset_explicit on Windows"
was incorrect — SODIUM_USE_PKG_CONFIG controls detection strategy, not
link behaviour. The actual Windows memset_explicit fix is handled via
SODIUM_LIB_DIR pointing to pre-built MinGW sodium.
bash unset modifies the current shell's environment but the act_runner
at 172.0.0.29 re-injects runner-level environment variables before each
cargo invocation, making unset ineffective. env -u removes the variable
from the child process's environment at the exec() level, bypassing any
runner re-injection entirely.
Applies to all three non-macOS platforms (linux-amd64, windows-amd64,
linux-arm64) in both release-beta.yml and auto-tag.yml.
The libsodium-sys-stable build.rs panics if both SODIUM_LIB_DIR and
SODIUM_USE_PKG_CONFIG are set simultaneously. The runner infrastructure
at 172.0.0.29 has SODIUM_USE_PKG_CONFIG in its container environment
(not traceable to any workflow file or Docker image ENV layer), which
conflicts with the SODIUM_LIB_DIR approach used for cross-compilation.
Explicitly unset SODIUM_USE_PKG_CONFIG in the shell before npm/cargo
runs on all three platforms (linux-amd64, windows-amd64, linux-arm64)
in both release-beta.yml and auto-tag.yml. This is a defensive no-op
when the variable is absent, and a clean fix when it is present.
Master added `unset SODIUM_USE_PKG_CONFIG` to the linux-amd64 and
linux-arm64 build steps in auto-tag.yml (PR #111). Beta's copy of
auto-tag.yml was already ahead of master via the previous sync but
lacked those two unset lines, causing a line-level conflict.
Resolution: take master's version in both conflict regions, adding the
unset to both linux build steps. All three platforms (amd64, Windows,
arm64) now have consistent SODIUM_LIB_DIR + unset configuration.
The libsodium-sys-stable build.rs panics when both SODIUM_LIB_DIR and
SODIUM_USE_PKG_CONFIG are set simultaneously. The runner environment at
172.0.0.29 has SODIUM_USE_PKG_CONFIG set (not traceable to any workflow
file or Docker image ENV layer), which conflicts with any step that sets
SODIUM_LIB_DIR.
For all three platform builds (linux-amd64, windows-amd64, linux-arm64):
- Add `unset SODIUM_USE_PKG_CONFIG` to the shell before cargo runs
- Switch Linux builds from inline apt-get to SODIUM_LIB_DIR (Docker
images already include libsodium-dev, removing the redundant install)
- Extend arm64 PKG_CONFIG_PATH to include /usr/aarch64-linux-gnu/lib/pkgconfig
(matching the beta workflow for consistency)
The unset is a no-op when the variable is absent; it cleanly clears any
ambient value injected by the runner infrastructure.
Tested locally with Ubuntu 22.04 + libsodium-sys-stable 1.24.0:
- No env vars → install_from_source() needs 'make', fails in slim containers
- SODIUM_LIB_DIR alone → works when libsodium is installed in the image
- SODIUM_LIB_DIR + SODIUM_USE_PKG_CONFIG → immediate panic (incompatible by design)
Fixes three broken build targets introduced by the merge conflict resolution:
- linux-amd64: was missing all sodium config, add SODIUM_LIB_DIR
- windows: had SODIUM_LIB_DIR + SODIUM_USE_PKG_CONFIG (incompatible), remove the latter
- linux-arm64: was missing sodium config, add SODIUM_LIB_DIR
Resolves conflicts in auto-tag.yml and release-beta.yml caused by two
independent libsodium fixes landing on separate branches (PR #105 on beta
via SODIUM_LIB_DIR, PR #106 on master via apt-get install).
Resolution keeps beta's approach throughout: SODIUM_LIB_DIR env vars
pointing at pre-installed system libraries, with no runtime apt-get install.
Also carries forward master's Dockerfile.linux-arm64 libsodium addition and
CHANGELOG.md update.
tauri-plugin-stronghold pulls in libsodium-sys-stable which panics at
build time if libsodium is not found via pkg-config — it does not compile
from source. All builder images and the test job inline apt installs were
missing libsodium-dev, breaking every Rust compilation step.
- Add libsodium-dev to Dockerfile.linux-amd64
- Add libsodium-dev (host) + libsodium-dev:arm64 (cross target) to
Dockerfile.linux-arm64
- Add libsodium-dev to all three Rust jobs in test.yml
- Add inline apt-get install to linux-amd64 and linux-arm64 Build steps
in auto-tag.yml and release-beta.yml (bridges the timing race between
build-images and auto-tag triggering on the same push)
- Add SODIUM_LIB_DIR + SODIUM_STATIC to Windows Build env (Dockerfile
already pre-builds libsodium; this tells the crate where to find it)