Kiosk K3a: agent sidecar lifecycle, external-agent mode, standalone Linux distribution - #101
Conversation
…tandalone Linux distribution
…l agent mode, standalone Linux distribution 9 tasks covering: generalized build_agent_url/agent_request for external targets (Rust, TDD), sidecar spawn/stop/restart commands + clean shutdown, agentConfig.ts mode persistence, agent.ts routed through the configured target, restart supervisor hook + app-boot wiring, Equipment's embedded/external toggle, agent version/port surfaced in status displays, agent/dist/ systemd unit + install script, and a new release.yml job to publish per-arch standalone agent bundles. Verified the Rust API surface (tauri 2.11.5, tauri-plugin-shell 2.3.5) against the actual vendored crate source rather than from memory. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…dency bug, doc comment useAgentSupervisor's effect depended only on [health.data, health.isLoading]; since checkAgentHealth() resolves the same boolean on every consecutive failed poll, health.data never changes value between polls and the effect would never re-run past the first failure. Added health.dataUpdatedAt (a fresh timestamp per settled poll regardless of value) to the dependency array. Also documented why Equipment.tsx's new reconnectAgent() is deliberately not shared with the pre-existing mount effect's cancellation-guarded logic. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n shutdown on exit
Adds useAgentSupervisor (K3a Task 5): restarts the embedded agent sidecar after 3 consecutive health-check failures via the Rust restart_agent command, with exponential backoff (1s->30s), full reset on the next healthy poll, and a no-op in external mode. Evaluates the ["agent","health"] query cache directly (queryClient.getQueryState + getQueryCache().subscribe) rather than a useEffect keyed on useAgentHealth()'s returned data -- TanStack Query defers the observer's React-facing re-render by one macrotask (notifyManager batches it through a 0ms setTimeout), which is invisible in the running app but caused the poll-counting tests to observe stale data one tick late under fake timers; subscribing to the cache's own (synchronous) notifications avoids that lag while still reading the same single source of truth the status chip uses. AgentLifecycle mounts once at the app root, spawning the embedded sidecar on boot (best-effort, swallowed outside Tauri) and keeping the supervisor alive for the session.
…il abort Under set -euo pipefail, a failing left-hand command in a pipeline (e.g. `hostname -I` on a freshly-imaged Pi with no network yet, or `grep -o` finding no match yet in a config-write race) propagates its non-zero status into the plain variable assignment, which trips set -e and kills the whole script -- for HOST_IP, right after the systemd service was already installed and started but before the Base URL/Token block ever prints, defeating a core purpose of the script. Append `|| true` inside each command substitution's pipeline so a failing source command yields an empty variable instead of aborting; existing fallback logic (default IP text, "not generated yet" token message) already handles the empty case correctly. No other behavior changed.
…ble-v version, unused import Addresses 3 findings from the K3a whole-branch review: 1. (Important) Equipment.tsx: /health and /info are auth-exempt, so a mistyped external-agent token still shows "connected" -- the first real endpoint call (e.g. /printers) then 401s. Add a distinct agentUnauthorized signal (detected from the 401 in fetchEquipmentData()'s error, in both reconnectAgent and the mount effect) with a translated warning line in the agent-connection section. 2. (Minor) agentDetail.ts's formatAgentDetail: strip any existing leading v/V from `version` before re-adding one, so a released standalone agent's CI-baked "v1.2.3"-shaped version string doesn't render as "vv1.2.3". Added a regression test. 3. (Minor) commands.rs: drop the unused `Manager` import (only needed in lib.rs, which is untouched) to clear a harmless compiler warning.
|
Warning Review limit reached
Next review available in: 30 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThe desktop now supports embedded or external agents with persisted configuration, Rust-proxied requests, managed sidecar lifecycle, health-based restarts, connection controls, and status metadata. Release automation also builds amd64 and arm64 standalone agent bundles. ChangesKiosk K3a agent support
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant EquipmentPage
participant agentConfig
participant agent_request
participant ExternalAgent
EquipmentPage->>agentConfig: save external URL and token
EquipmentPage->>agent_request: request agent health or equipment
agent_request->>ExternalAgent: send validated authenticated request
ExternalAgent-->>agent_request: return response
agent_request-->>EquipmentPage: return agent data or authorization error
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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 @.github/workflows/release.yml:
- Around line 127-165: Add a validation step or dependency to
agent-standalone-bundle that runs the agent’s tests, linting, and security
checks before the Package bundle and upload-artifact steps. Reuse the
repository’s established validation commands or reusable job, and ensure
artifact publication cannot proceed when any check fails.
- Around line 141-150: Update the Build step in the release workflow to assign
github.ref_name to RELEASE_TAG, validate RELEASE_TAG against the expected
release-tag format, and use the validated shell variable in the
main.agentVersion ldflags value instead of directly interpolating
github.ref_name.
In @.superpowers/sdd/final-review-fix-report.md:
- Line 53: Update all fenced code blocks in final-review-fix-report.md,
including the listed occurrences, to specify sh for command examples and text
for build output, resolving markdownlint MD040 without changing the block
contents.
In `@desktop/src/features/checkin/useAgentSupervisor.ts`:
- Around line 92-100: The cooldown timer in the restart flow should trigger a
health refetch when it expires, rather than only clearing cooldownActiveRef and
updating backoffMsRef. Update the timer callback near restartAgentProcess so the
refetch result is settled and drives the existing health/restart decision logic,
preserving the intended 1s→2s→4s progression and cooldown gate behavior.
In `@desktop/src/lib/agent.ts`:
- Around line 25-27: Update the browser request construction around the target
base URL and fetch call to parse and validate the base as a URL, rejecting
non-HTTP(S) schemes and any username or password userinfo before sending
credentials. Resolve path with new URL(path, base) rather than string
concatenation, and preserve the existing fallback and Authorization behavior for
valid targets.
In `@docs/superpowers/specs/2026-07-21-kiosk-k3a-agent-distribution-design.md`:
- Line 28: Update the K3a documentation around externalBin and tauri.conf.json
to state that bundle.externalBin remains [] in committed configuration; allow
externalBin: ["sidecars/idento-agent"] only as an uncommitted local override for
manual sidecar testing, while preserving manual spawning from
src-tauri/sidecars/.
🪄 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
Run ID: 9595ac28-a060-41dc-9abe-f668832b51d6
⛔ Files ignored due to path filters (2)
agent/dist/idento-agent.serviceis excluded by!**/dist/**agent/dist/install.shis excluded by!**/dist/**
📒 Files selected for processing (23)
.github/workflows/release.yml.superpowers/sdd/final-review-fix-report.md.superpowers/sdd/progress.mddesktop/README.mddesktop/src-tauri/src/commands.rsdesktop/src-tauri/src/lib.rsdesktop/src/App.tsxdesktop/src/components/AgentLifecycle.tsxdesktop/src/features/checkin/agentDetail.test.tsdesktop/src/features/checkin/agentDetail.tsdesktop/src/features/checkin/hooks.test.tsxdesktop/src/features/checkin/hooks.tsdesktop/src/features/checkin/useAgentSupervisor.test.tsxdesktop/src/features/checkin/useAgentSupervisor.tsdesktop/src/i18n.tsdesktop/src/lib/agent.test.tsdesktop/src/lib/agent.tsdesktop/src/lib/agentConfig.test.tsdesktop/src/lib/agentConfig.tsdesktop/src/pages/Equipment.tsxdesktop/src/pages/Run.tsxdocs/superpowers/plans/2026-07-21-kiosk-k3a-agent-distribution.mddocs/superpowers/specs/2026-07-21-kiosk-k3a-agent-distribution-design.md
|
|
||
| ### Verification (all run from repo root) | ||
|
|
||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add fence language identifiers.
These fences trigger markdownlint MD040. Use sh for commands and text for build output.
Proposed fix
-```
+```sh
npm test -w idento-desktop</details>
Also applies to: 58-58, 63-63, 68-68, 74-74, 82-82, 90-90
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.23.0)</summary>
[warning] 53-53: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.superpowers/sdd/final-review-fix-report.md at line 53, Update all fenced
code blocks in final-review-fix-report.md, including the listed occurrences, to
specify sh for command examples and text for build output, resolving
markdownlint MD040 without changing the block contents.
</details>
<!-- fingerprinting:phantom:poseidon:terra -->
<!-- cr-indicator-types:potential_issue -->
<!-- cr-comment:v1:d220c85c1c9ed9da65262274 -->
_Source: Linters/SAST tools_
<!-- This is an auto-generated comment by CodeRabbit -->
…esktop-app-k3 # Conflicts: # .superpowers/sdd/progress.md
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sanitize github.ref_name before shell interpolation in the new agent-standalone-bundle release job (mirrors onprem-bundle's existing RELEASE_TAG/case-validation pattern), add a go test step before packaging, validate external-agent base URLs in agent.ts's browser-dev fallback path (rejects non-http(s) schemes and userinfo before building the fetch URL), and make useAgentSupervisor's exponential backoff actually drive retry cadence via a forced health-query refetch instead of passively gating behind the 20s poll interval. Also clarifies the K3a spec doc's externalBin wording to match the actual committed-vs-local-only behavior. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thanks for the review — addressed in 845d8db:
Declined: the markdownlint fence-language nitpick on |
Summary
Makes the K1-era sidecar-spawn stub actually work, adds an "external agent" connection mode so the kiosk can talk to a standalone agent on another machine, and gives that standalone agent an official Linux/systemd distribution.
spawn_agent/stop_agent/restart_agentTauri commands backed byAgentProcessstate; clean shutdown viaRunEvent::Exit(tauri-plugin-shell's own cleanup only covers processes spawned through its JS-invoked IPC command, notCommand::spawn()called directly from Rust, so this is additionally required).useAgentSupervisorrides the existinguseAgentHealthpoller — 3 consecutive failures trigger a restart, exponential backoff (1s→30s cap) between further attempts, full reset on the next healthy check. Evaluates off the query cache's synchronous subscription rather than auseEffectdependency array (TanStack Query defers the React-facing re-render by one macrotask; the cache's own listeners are synchronous — verified against the installed@tanstack/query-coresource).agent_request's SSRF-hardened URL builder is generalized to accept a caller-supplied{base_url, token}target instead of only the hardcoded embedded one, preserving every existing anti-injection invariant for both paths. A wrong token is now surfaced explicitly (previously/health's auth-exempt status let a mistyped token show a false "connected").agent/dist/idento-agent.service+install.sh(systemd unit,dialoutgroup, prints the Base URL + auth token to paste into Equipment), plus a newagent-standalone-bundlerelease CI job mirroring the existing per-archbinariesjob.Out of scope (deferred to K3b): automated sidecar-binary embedding into official Tauri release bundles,
tauri-plugin-updater, code signing, adesktop-v*release workflow.Process
Spec → plan → 9 tasks executed via subagent-driven-development (fresh implementer + reviewer per task), then a final whole-branch review. Two tasks needed a fix-and-re-review round (a verified TanStack Query timing deviation in the supervisor hook; a
set -e/pipefail bug ininstall.sh). The final review found one Important, since-fixed issue (external-mode token-mismatch false-green) plus two cosmetic Minors (double-vversion prefix, unused Rust import).Two things this branch could not exercise in its sandboxed development environment and that should be checked before relying on this in production:
install.shon a real Linux/systemd box (e.g. a Raspberry Pi).Test plan
npm test -w idento-desktop— 70/70 passingnpm run typecheck -w idento-desktop— cleannpm run build -w idento-desktop— cleancargo build/cargo test --lib(desktop/src-tauri) — clean, 15/15, zero warningsinstall.shon a real Linux/systemd box🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation