Skip to content

feat(desktop): Electron desktop app skeleton + Windows enablement groundwork#752

Draft
AbirAbbas wants to merge 6 commits into
mainfrom
feat/desktop-app
Draft

feat(desktop): Electron desktop app skeleton + Windows enablement groundwork#752
AbirAbbas wants to merge 6 commits into
mainfrom
feat/desktop-app

Conversation

@AbirAbbas

Copy link
Copy Markdown
Contributor

First cut of the AgentField desktop app (Docker-Desktop-style, for non-technical users on Mac and Windows), plus the Windows enablement groundwork the desktop story depends on.

Part 1 — desktop/: Electron app skeleton (read-only v1)

Electron 33 + electron-vite + React 18 + TypeScript, fully self-contained (own package.json; no root Makefile/CI changes). Secure IPC defaults: contextIsolation: true, nodeIntegration: false, sandbox: true, window-open denied, a single getSnapshot() bridge.

  • Control plane status card — polls GET /health (3s timeout), distinguishes running / reachable-but-unhealthy / not reachable.
  • Installed agents list — reads ~/.agentfield/installed.yaml (platform-aware home dir), shows name, version, language, port, PID.
  • Running badges — registry runtime cross-checked against GET /api/v1/nodes (running / stopped / unknown, including stale-registry and conflict cases).
  • 5s polling + manual refresh, graceful empty states (no ~/.agentfield, zero agents, control plane down).
  • All data access isolated in desktop/src/main/agentfield.ts with a marked TODO(af-cli) seam to swap to af list -o json (added by feat(control-plane): agent-mode steering verbs, events query resource, and --json lifecycle output #751).
  • 29 vitest tests on the data layer (registry fixtures, malformed YAML, badge truth table, health mapping).

Known v1 limits (deliberate): read-only, hardcoded localhost:8080, no packaging/electron-builder yet. Developed in a headless environment — tsc, production build, and unit tests are green, but the GUI has not been visually smoke-tested.

Part 2 — Windows enablement (compile-verified only)

  • .goreleaser.yml: real agentfield-windows-amd64 build block (CGO=1 via mingw-w64, embedded+sqlite_fts5 tags) replacing the stale commented one; archive config modernized (builds/formatids/formats, goreleaser check now passes clean).
  • Build-tagged process stop/liveness (proc_unix.go / proc_windows.go): SIGINT + signal-0 on unix; taskkill + tasklist PID query on Windows (os.FindProcess always succeeds there). stop.go call-site swaps only.
  • af logs tailing: unchanged tail(1) on unix; PowerShell Get-Content -Tail [-Wait] on Windows.
  • Go node binaries: install-time go build -o gets .exe on Windows and manifest-declared extensionless paths resolve to it. No-op elsewhere.
  • Already portable, no change needed: venv Scripts\ handling, home-dir resolution, af-tray build tags. Deferred: pyenv fallback path (pyenv is effectively unix-only).

⚠️ Windows caveats

  1. Everything is compile-verified (windows/linux/darwin cross-builds) + unit-tested — not yet run on a real Windows machine.
  2. The goreleaser windows target is inert until release.yml adds the new build id to its matrix (needs mingw-w64 on the linux runner or a windows runner for the CGO sqlite dep). CI workflows deliberately untouched here.

Notes for review

  • The agent-CLI PR touches stop.go's output layer while this one extracts its process ops — whichever merges second needs a trivial rebase.
  • Dev-machine go test failures (TestDevServiceRunDev et al.) are pre-existing/environmental (fail identically at base 6b8b404e); touched packages fully green including new tests.

🤖 Generated with Claude Code

AbirAbbas and others added 5 commits July 10, 2026 15:20
Docker-Desktop-style dashboard for non-technical users: shows control
plane health (GET /health) and the locally installed agent nodes from
~/.agentfield/installed.yaml, cross-checked against GET /api/v1/nodes
for a running/stopped/unknown badge per agent. Polls every 5s with a
manual Refresh button and graceful empty states.

Electron + electron-vite + React + TypeScript, plain CSS. Secure
defaults: contextIsolation on, nodeIntegration off, sandboxed renderer,
single contextBridge API. All data access is isolated in
src/main/agentfield.ts with a marked seam to later swap the registry
read to `af list -o json`. 29 vitest unit tests cover registry parsing,
health mapping, and badge derivation.

Self-contained under desktop/ (own package.json); no packaging
(electron-builder) yet, and the GUI is untested in this headless
environment — typecheck, production build, and unit tests all pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the stale commented-out windows block with a real
agentfield-windows-amd64 build mirroring the linux/darwin ones
(goreleaser appends .exe on its own). Groundwork only: the release
workflow's build matrix filters by --id and does not build this id yet;
shipping the artifact needs a follow-up matrix entry (windows runner,
or mingw-w64 on the linux runner for the CGO sqlite dependency).

Also modernizes archives.builds/format to ids/formats so
`goreleaser check` passes clean again (both were deprecated).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`af stop` used process.Signal(os.Interrupt) and a signal-0 probe, both
unsupported on Windows (and os.FindProcess always succeeds there, so
the liveness check was meaningless). Extract the two process operations
into build-tagged helpers: proc_unix.go keeps the existing SIGINT +
signal-0 behaviour; proc_windows.go uses taskkill for the graceful
request and a tasklist PID query for liveness.

stop.go changes are limited to swapping the two call sites and the
now-unused syscall import. Windows paths are compile-verified only
(GOOS=windows cross-build), not yet tested on a real Windows machine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`af logs` shelled out to tail(1), which does not exist on Windows. The
tail/follow commands now go through one tailCommand helper: unchanged
tail(1) invocations on Unix, PowerShell Get-Content -Tail (-Wait for
follow) on Windows, with proper single-quote escaping of the log path.
Windows path is compile-verified only, not yet run on a real machine.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Go agent nodes declare unix-style binary paths in their manifests
(entrypoint.start: bin/foo). On Windows the install-time `go build -o`
output now carries the conventional .exe extension, and the runner's
GoBinaryProgram resolves an extensionless start path to the built .exe
when present. No behaviour change on other platforms; windows path is
compile-verified only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage gate

Thresholds from .coverage-gate.toml: per-surface ≥ 84%, aggregate ≥ 85%, max per-surface regression ≤ 1.0 pp, max aggregate regression ≤ 0.50 pp.

Surface Current Baseline Δ
control-plane 86.90% 87.40% ↓ -0.50 pp 🟡
sdk-go 91.90% 92.00% ↓ -0.10 pp 🟢
sdk-python 93.76% 93.73% ↑ +0.03 pp 🟢
sdk-typescript 90.45% 90.42% ↑ +0.03 pp 🟢
web-ui 84.75% 84.79% ↓ -0.04 pp 🟡
aggregate 85.54% 85.75% ↓ -0.21 pp 🟡

✅ Gate passed

No surface regressed past the allowed threshold and the aggregate stayed above the floor.

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

📐 Patch coverage gate

Threshold: 80% on lines this PR touches vs origin/main (from .coverage-gate.toml:thresholds.min_patch).

Surface Touched lines Patch coverage Status
control-plane 52 100.00%
sdk-go 0 ➖ no changes
sdk-python 0 ➖ no changes
sdk-typescript 0 ➖ no changes
web-ui 0 ➖ no changes

✅ Patch gate passed

Every surface whose lines were touched by this PR has patch coverage at or above the threshold.

…ed helpers

The patch-coverage gate flagged the runtime.GOOS-gated windows branches
(PowerShell tail construction in logs.go, .exe naming/resolution in
gointerp.go) as untestable on linux CI. Extract each into a pure helper
taking an explicit goos string — tailCommandArgs, withExeSuffixFor,
goBinaryProgramFor — with the exported wrappers passing runtime.GOOS,
so behavior is unchanged while both platform paths are unit-testable
anywhere. Table-driven tests cover the windows tail command (incl.
single-quote escaping), .exe suffixing, and the built-.exe fallback
resolution; refactored regions now profile with zero uncovered blocks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant