Skip to content

Port openframe-client updates from openframe-oss-tenant (post-extraction commits)#1359

Merged
mikhailm-coder merged 10 commits into
mainfrom
feat/port-tenant-client-updates
Jul 4, 2026
Merged

Port openframe-client updates from openframe-oss-tenant (post-extraction commits)#1359
mikhailm-coder merged 10 commits into
mainfrom
feat/port-tenant-client-updates

Conversation

@mikhailm-coder

@mikhailm-coder mikhailm-coder commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What & why

The shared Rust agent (openframe-agent-lib, PR #1265) was extracted from openframe-oss-tenant at tenant commit 6105a10bb (#1967, Jun 23). Since then 8 client commits were merged to tenant main. This PR ports all of them, 1:1, preserving original authorship and messages.

Ported commits (tenant → this branch)

tenant here title
37eddc66e 7b92b9f12 Hotfix/tool update resilience (#1966)
46084c181 d5b2afb34 fix(client): back off mesh self-heal to hourly after a no-op (#1981)
d167edb22 1ea2c8af3 Hotfix/mesh agent resilience (#1986)
31ce09e5a 96bd72d76 fix(client): cleaned up the force reinstall functionality (#1993)
d4ef43720 82e13fa93 chore: reduce logs
dd0bd79eb 2add28f60 Fix Fleet/tool force-reinstall (Windows + macOS/Linux Orbit cleanup) (#2030)
0dba362d0 aa9e2be28 Feat/tool remote uninstall
019691eba eb3168872 feat: delete tool

Plus one follow-up commit resolving the two clippy findings the ported code trips in this repo's -D warnings gate (see below).

Deviations from verbatim tenant code (all intentional)

  • cargo fmt folded into each commit — this repo's pre-commit hook enforces fmt; tenant does not.
  • Extraction-era clippy idioms preserved where ported hunks touched them: derive(Default) instead of manual impl Default (incl. the new ToolRecordState field), is_none_or(..) instead of map_or(true, ..), sorted module/import lists, no needless .clone() on a bool.
  • Installation-command timeout (from #1966) restructured from map_err(|e| { #[cfg(windows)] log…; e }) into explicit match arms: on non-Windows the cfg-stripped closure is |e| e, which fails clippy::map_identity. The match form keeps both the 300s timeout and the Windows file-lock logging (which the original extraction had dropped at this call site).
  • Clippy follow-up commit: dropped a dead trailing reinstall_dir_cleared = true; (dead in tenant too) and map_or(false, ..)is_some_and(..).

Verification (source ↔ target, 4 independent methods)

  1. Fmt-normalized full-tree diff + delta invariance: formatted tenant@main vs this branch; checked that every file's diff equals the extraction-time diff (fmt(tenant@6105a10bb) vs 258fa87c). Result: 231 files identical, 45 files with byte-identical constant extraction delta, 5 flagged — each explained by the deviations above.
  2. Per-commit file sets: all 8 tenant/ported commit pairs touch identical file lists.
  3. Symbol-level comparison (fns/structs/enums/consts): only extraction-era Default-idiom diffs and the main()run() hoist.
  4. Distinctive-marker sweep: every feature marker per commit present (e.g. ToolRecordState, TOOL_COMMAND_TIMEOUT_SECS, service_clear_for_install, tool_lock, orbit-spawned osqueryd); removed code confirmed absent (ReinstallBackupGuard, ToolUninstallResultPublisher, NOOP_COOLDOWN — superseded upstream by #1986/#1993/delete-tool).

Gates

  • cargo clippy --all-targets --features bin -- -D warnings ✅ (and hook variant without --features bin ✅)
  • cargo fmt --all -- --check ✅ (every commit)
  • cargo test --features bin: 82 passed; the 2 failures (platform::directories::tests::{test_directory_permissions,test_health_check}) fail identically on main — pre-existing, local-permissions-dependent, unrelated to this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_011z7MGH2qYeKt2ZQV88EaD8

Summary by CodeRabbit

  • New Features

    • Added an uninstall workflow that listens for uninstall messages and removes installed tools more reliably.
    • Introduced richer installed-tool state handling to support installs, repairs, and consistent finalization.
  • Bug Fixes

    • Reduced update conflicts by deferring client updates during active tool operations.
    • Improved Windows service stop/reinstall safety and recovery for stuck services.
    • Enhanced mesh self-healing logic to avoid unnecessary rewrites and retries.
  • Improvements

    • Added safer, concurrent persistence for installed tools and reduced routine log verbosity.

danylo-babenko-flamingo and others added 9 commits July 4, 2026 09:12
…msh target) (#1981)

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
- drop dead trailing assignment to reinstall_dir_cleared (unused_assignments;
  the flag is never read after the no-registry-record repair block)
- mesh self-heal: map_or(false, ..) -> is_some_and(..) (clippy::unnecessary_map_or)

Both warnings originate in code ported verbatim from openframe-oss-tenant;
this keeps the repo clippy gate (-D warnings) green.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011z7MGH2qYeKt2ZQV88EaD8
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 308ff8d9-95c5-4d39-978c-531b63ab2d49

📥 Commits

Reviewing files that changed from the base of the PR and between a467503 and 10c62a4.

📒 Files selected for processing (1)
  • clients/openframe-client/src/platform/directories.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • clients/openframe-client/src/platform/directories.rs

📝 Walkthrough

Walkthrough

This PR adds uninstall handling, explicit tool record state, per-tool coordination, service stop/delete hardening, mesh self-heal ServerID support, and lower-verbosity logging.

Changes

Tool Uninstall Feature

Layer / File(s) Summary
Uninstall contracts and exports
clients/openframe-client/src/config/update_config.rs, clients/openframe-client/src/models/tool_uninstall_message.rs, clients/openframe-client/src/models/mod.rs, clients/openframe-client/src/services/mod.rs, clients/openframe-client/src/listener/mod.rs
Adds uninstall consumer limits, the uninstall message model, and public exports for the new listener and outcome type.
Uninstall service flow
clients/openframe-client/src/services/tool_uninstall_service.rs
Adds UninstallOutcome, uninstall-by-tool-agent-id handling, and uninstall-time process stopping with allow_delete.
Uninstall listener and consumer
clients/openframe-client/src/listener/tool_uninstall_message_listener.rs
Implements the JetStream listener, message handling, consumer creation, and consumer configuration helpers.
Client wiring
clients/openframe-client/src/lib.rs
Adds the uninstall service and listener to Client construction and startup.

Tool State and Coordination

Layer / File(s) Summary
Tool record state and persistence
clients/openframe-client/src/models/installed_tool.rs, clients/openframe-client/src/services/installed_tools_service.rs
Adds ToolRecordState, the InstalledTool.state field, writer locking, set_state, and atomic persistence.
ToolRunManager tracking and reconciliation
clients/openframe-client/src/services/tool_run_manager.rs
Replaces update tracking with counters and per-tool locks, then reconciles Installing records during startup and supervision.
Agent update repair flow
clients/openframe-client/src/services/tool_agent_update_service.rs
Uses ToolRecordState and artifact presence to repair inconsistent tool records and finalize Installed after success.
Update deferral during tool operations
clients/openframe-client/src/services/openframe_client_update_service.rs, clients/openframe-client/src/services/tool_connection_processing_manager.rs, clients/openframe-client/src/lib.rs, clients/openframe-client/src/services/mesh_self_heal_service.rs
Adds tool-operation deferral in client updates and tool connection processing, including backoff behavior for agentId resolution.

Service Stop and Reinstall Hardening

Layer / File(s) Summary
Windows service stop and delete helpers
clients/openframe-client/src/platform/system_service.rs
Changes stop_service to accept allow_delete and adds Windows helpers for service verification, clearing, process killing, and deletion.
Kill service and updater call sites
clients/openframe-client/src/services/tool_kill_service.rs, clients/openframe-client/src/platform/tool_updater/*
Threads allow_delete through ToolKillService and updates the GUI and service updater stop calls.
Installation and reinstall flow
clients/openframe-client/src/services/tool_installation_service.rs, clients/openframe-client/src/platform/directories.rs, clients/openframe-client/src/platform/uninstall.rs
Adds command timeouts, install-state transitions, stale-directory cleanup, service verification, and explicit Installed persistence.

Mesh Self-Heal and Logging

Layer / File(s) Summary
Mesh self-heal ServerID support
clients/openframe-client/src/services/mesh_self_heal_service.rs
Adds tool-run coordination, ServerID-aware healing, cooldown handling, helper parsing, and updated newline reading behavior.
Logging verbosity adjustments
clients/openframe-client/src/logging/*
Lowers selected log messages to debug and changes the default async_nats filter fallback.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NATS
  participant ToolUninstallMessageListener
  participant ToolRunManager
  participant ToolUninstallService
  participant InstalledToolsService

  NATS->>ToolUninstallMessageListener: deliver ToolUninstallMessage
  ToolUninstallMessageListener->>ToolRunManager: tool_lock(tool_id)
  ToolUninstallMessageListener->>ToolRunManager: mark_updating(tool_id)
  ToolUninstallMessageListener->>ToolUninstallService: uninstall_by_tool_agent_id(id)
  ToolUninstallService->>InstalledToolsService: delete_by_tool_agent_id
  ToolUninstallService-->>ToolUninstallMessageListener: UninstallOutcome
  ToolUninstallMessageListener->>ToolRunManager: clear_updating(tool_id)
  ToolUninstallMessageListener->>NATS: ack (if Removed/NotInstalled)
Loading

Related issues: None found.

Related PRs: None found.

Suggested labels: rust, client, feature

Suggested reviewers: None found.

🐰 A tool once stuck, now knows to bow,
Uninstall whispers "not needed now."
Locks and states keep chaos tame,
Services stop without a claim,
The rabbit hops through logs so quiet—debug replaces the old riot.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: porting openframe-client updates from openframe-oss-tenant after extraction.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/port-tenant-client-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@clients/openframe-client/src/platform/system_service.rs`:
- Around line 582-599: The `.exe` detection in parse_exe_from_image_path should
use ASCII-only case folding because the current to_lowercase() can change string
length and break the byte slice used for the returned PathBuf. Update the
unquoted path handling in parse_exe_from_image_path to search against
to_ascii_lowercase() so the idx from find(".exe") still aligns with
&trimmed[..idx + 4] and the parsed executable path stays correct.

In `@clients/openframe-client/src/services/tool_agent_update_service.rs`:
- Around line 80-122: The update path in tool_agent_update_service is not
serialized with the per-tool lock, so an uninstall can race with process_update
while binaries or state are being modified. Update tool_agent_update_listener or
process_update to acquire tool_run_manager.tool_lock(tool_agent_id) before doing
any update work, and hold it for the full duration of the update flow so it
matches the uninstall listener’s locking behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 78cc5207-9f79-47f6-be3b-1ff12f2c90ca

📥 Commits

Reviewing files that changed from the base of the PR and between 8a49943 and a467503.

📒 Files selected for processing (25)
  • clients/openframe-client/src/config/update_config.rs
  • clients/openframe-client/src/lib.rs
  • clients/openframe-client/src/listener/mod.rs
  • clients/openframe-client/src/listener/tool_uninstall_message_listener.rs
  • clients/openframe-client/src/logging/log_source.rs
  • clients/openframe-client/src/logging/mod.rs
  • clients/openframe-client/src/logging/nats_streaming.rs
  • clients/openframe-client/src/models/installed_tool.rs
  • clients/openframe-client/src/models/mod.rs
  • clients/openframe-client/src/models/tool_uninstall_message.rs
  • clients/openframe-client/src/platform/directories.rs
  • clients/openframe-client/src/platform/system_service.rs
  • clients/openframe-client/src/platform/tool_updater/gui_app.rs
  • clients/openframe-client/src/platform/tool_updater/service.rs
  • clients/openframe-client/src/platform/uninstall.rs
  • clients/openframe-client/src/services/installed_tools_service.rs
  • clients/openframe-client/src/services/mesh_self_heal_service.rs
  • clients/openframe-client/src/services/mod.rs
  • clients/openframe-client/src/services/openframe_client_update_service.rs
  • clients/openframe-client/src/services/tool_agent_update_service.rs
  • clients/openframe-client/src/services/tool_connection_processing_manager.rs
  • clients/openframe-client/src/services/tool_installation_service.rs
  • clients/openframe-client/src/services/tool_kill_service.rs
  • clients/openframe-client/src/services/tool_run_manager.rs
  • clients/openframe-client/src/services/tool_uninstall_service.rs

Comment thread clients/openframe-client/src/platform/system_service.rs
Comment thread clients/openframe-client/src/services/tool_agent_update_service.rs
@mikhailm-coder

Copy link
Copy Markdown
Contributor Author

CI status note: the Test Rust (macos-latest) job was cancelled manually — platform::permissions::tests::test_ensure_admin hung (>60s): on a headless macOS runner it triggers an interactive osascript admin prompt. This is pre-existing (this PR does not touch permissions.rs — the ported commits' file sets are listed in the description) and is fixed by #1352, which #[ignore]s the privileged/interactive tests. Plan: once #1352 merges, this branch gets rebased and CI re-run. The Windows Rust job passed (10m40s).

@mikhailm-coder
mikhailm-coder merged commit 03feabe into main Jul 4, 2026
8 checks passed
@mikhailm-coder
mikhailm-coder deleted the feat/port-tenant-client-updates branch July 4, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants