Skip to content

feat(windows): add HyperHQ launcher and bridge plugin#806

Open
wizzomafizzo wants to merge 13 commits into
mainfrom
feat/windows-hyperhq-launcher
Open

feat(windows): add HyperHQ launcher and bridge plugin#806
wizzomafizzo wants to merge 13 commits into
mainfrom
feat/windows-hyperhq-launcher

Conversation

@wizzomafizzo
Copy link
Copy Markdown
Member

@wizzomafizzo wizzomafizzo commented May 10, 2026

  • Adds a HyperHQ launcher to the Windows platform. Core hosts a named pipe at \\.\pipe\zaparoo-hyperhq-ipc and exchanges JSON-line messages with a separate bridge plugin under scripts/windows/hyperhq-plugin/ that HyperHQ runs as a Socket.IO plugin per the HyperAI plugin API.
  • Two wire formats: pipe (Core ↔ bridge) is internal PascalCase JSON; HyperHQ Socket.IO (bridge ↔ HyperHQ) is camelCase per the API. The bridge handles challenge-response auth, plugin:register, subscribeEvents, requestData/dataResponse routing by requestId, and the hyperHqEvent envelope (gameLaunched / gameClosed).
  • Bridge module is exempt from forbidigo and depguard so it can use stdlib sync and log without pulling Zaparoo Core internals into its dep tree. Linted via task cross-lint:windows since winio is Windows-only.

Summary by CodeRabbit

  • New Features

    • Windows HyperHQ integration: discover games, map systems, and launch via local HyperHQ bridge.
    • Support for the hyperhq:// URI scheme and a corresponding virtual-path launcher.
  • Bug Fixes

    • Safer plugin connection handling to avoid writes when disconnected.
    • LaunchBox mapping and media handling now treat unknown platforms as "Custom" rather than skipping.
  • Chores

    • Added Windows HyperHQ plugin build pipeline, Dockerfile, and module files; updated lint config/tasks and toolchain version.
  • Tests

    • Extensive unit tests for HyperHQ bridge, protocol parsing, mapping logic, and large-payload handling.

Review Change Stack

Adds a HyperHQ launcher to the Windows platform. Zaparoo Core hosts a
named pipe at \\.\pipe\zaparoo-hyperhq-ipc and exchanges JSON-line
messages with a bridge plugin (separate Go module under
scripts/windows/hyperhq-plugin/) that HyperHQ launches as a Socket.IO
plugin per the API at https://docs.hyperai.io/docs/plugins/.

Two wire formats: pipe (Core <-> bridge) is internal PascalCase JSON;
HyperHQ Socket.IO (bridge <-> HyperHQ) is camelCase per the API. The
bridge handles challenge-response auth, plugin:register, subscribeEvents,
requestData/dataResponse routing by requestId, and the hyperHqEvent
envelope (gameLaunched / gameClosed).

Bridge module is exempt from forbidigo and depguard so it can use stdlib
sync and log without pulling Zaparoo Core internals into its dep tree.
Linted via task cross-lint:windows since winio is Windows-only.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

Walkthrough

Adds Windows HyperHQ support: a named-pipe server in core, a Windows bridge plugin (Socket.IO client) with build artifacts, hyperhq URI scheme, a HyperHQ launcher, mapping/assets, tests, and lint/build task updates.

Changes

HyperHQ Windows Integration

Layer / File(s) Summary
URI Scheme, System Asset & Constants
pkg/platforms/shared/schemes.go, pkg/assets/systems/Custom.json, pkg/database/systemdefs/systemdefs.go
Registers SchemeHyperHq = "hyperhq", adds Custom.json asset, and defines SystemCustom = "Custom".
HyperHQ Pipe Server Core
pkg/platforms/windows/hyperhq.go
Implements HyperHqPipeServer with Start/Stop, callbacks, RequestSystems, RequestGamesForSystemSync (single-flight sync + timeout), LaunchGame, pinging, accept loop, scanning, and mapping builders.
Connection Scanning & Event Dispatch
pkg/platforms/windows/hyperhq.go
Scanner goroutine parses newline-delimited JSON, unmarshals HyperHQ events, dispatches Media/Systems/Games events, and fulfills synchronous Games requests.
Platform Integration & Launcher
pkg/platforms/windows/platform.go, pkg/platforms/windows/hyperhq.go
Extends Windows Platform with HyperHQ mapping state and pipe, initializes/stops the pipe server, wires event handlers to active media and mapping tables, and adds NewHyperHqLauncher().
LaunchBox Mapping & Robustness
pkg/platforms/windows/launchbox.go, pkg/platforms/windows/launchbox_test.go
Adds nil-writer check before GetGames writes, refactors mapping helpers, ignores empty platform refreshes, and maps unknown platforms to SystemCustom; adds tests for these behaviors.
Plugin Bridge Core & RPC
scripts/windows/hyperhq-plugin/main.go
Adds bridge executable with Socket.IO auth/registration, lifecycle request handling, requestData RPCs with requestId/sessionToken and waiter routing, pushSystems/pushGames, launch handling, pipe session loop, and JSON framing utilities.
Plugin Manifest & Build
scripts/windows/hyperhq-plugin/plugin.json, scripts/windows/hyperhq-plugin/go.mod, scripts/windows/hyperhq-plugin/Dockerfile
Adds plugin manifest, module (go 1.26.3) with winspecific deps, and Dockerfile to cross-compile a static Windows AMD64 executable.
Plugin Unit Tests & Bridge Tests
scripts/windows/hyperhq-plugin/main_test.go
Adds tests and fakes for plugin manifest, socket/emit fakes, pending-data routing/cleanup, lifecycle responses, pipe session writes, decode helpers, and request ID uniqueness.
Platform & Launcher Tests
pkg/platforms/windows/hyperhq_test.go
Adds HyperHQ platform tests: event/command JSON, Systems/Games deserialization and error propagation, mapping construction, virtual-path round-trip, launcher fields, disconnected pipe behavior, and >1MB scanner regression test.
Build Tasks & Linting
scripts/tasks/windows.yml, scripts/tasks/cross-lint.yml, .golangci.yml, Taskfile.dist.yml
Adds build-hyperhq-plugin task, adjusts cross-lint command flow, documents Windows-only lint path in Taskfile, and excludes depguard/forbidigo for plugin dir; updates golangci run.go to 1.26.3.
Pipe Dial Implementations
scripts/windows/hyperhq-plugin/pipe_windows.go, scripts/windows/hyperhq-plugin/pipe_unsupported.go
Adds Windows dialPipeContext using go-winio and a non-Windows stub returning an unavailable error.
Clock Monitor Healing Logic & Tests
pkg/service/clock_monitor.go, pkg/service/clock_monitor_test.go
Treats successful HealTimestamps (including zero rows) as complete and updates tests to expect immediate stop after noop heal.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

"🐰
I stitch a pipe from sky to ground,
JSON hops and echoes round,
Games and mappings, neat and spry,
I nibble bugs and let them fly."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding HyperHQ launcher support and a bridge plugin for Windows.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/windows-hyperhq-launcher

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

@sentry
Copy link
Copy Markdown

sentry Bot commented May 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/windows/hyperhq-plugin/main.go (1)

224-857: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Please add tests for the new bridge module.

I don't see companion coverage in this diff for the auth handshake, pipe request routing, or reconnect/error paths, and this file carries most of the new protocol risk.

As per coding guidelines, "Write tests for all new code — follow TESTING.md and pkg/testing/README.md patterns".

🤖 Prompt for 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.

In `@scripts/windows/hyperhq-plugin/main.go` around lines 224 - 857, Add
unit/integration tests for the new bridge behavior: create tests exercising the
authentication handshake and reconnect path (exercise connectSocket by driving
"connect" and "authenticated" events and assert sessionToken set and authDone
behavior), request/response routing (test requestData/requestDataCtx together
with handleDataResponse to ensure pendingData mapping, cleanup, and error
paths), lifecycle request handling (call handleLifecycleRequest with various
hqLifecycleRequest payloads including missing ID and hqMethodShutdown to verify
plugin:response emit and cancel), pipe interaction (exercise writePipeEvent,
servePipeOnce/runPipeLoop by faking a pipe connection or using an in-memory
net.Pipe to verify pushed Systems/Games and command routing via
handlePipeCommand), and edge cases (decodeFirst, unmarshalIfPresent,
newRequestID uniqueness/fallback). Follow TESTING.md and pkg/testing/README.md
patterns: add a _test.go beside main.go, use test doubles/mocked socketio server
and a fake pipe connection, control contexts/timeouts to exercise reconnects and
error returns, and assert logs/returned errors where appropriate.
🤖 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 `@scripts/windows/hyperhq-plugin/go.mod`:
- Line 3: The linter version in .golangci.yml is pinned to go: "1.25" which
conflicts with the root module's go 1.26.3 and the plugin's go 1.26.2; update
the go setting in .golangci.yml from "1.25" to "1.26.3" so the linter target
matches the root go.mod, and optionally also bump the plugin's go directive in
scripts/windows/hyperhq-plugin/go.mod from 1.26.2 to 1.26.3 to keep all go
versions consistent across the repo.

In `@scripts/windows/hyperhq-plugin/main.go`:
- Around line 584-586: The goroutines started by b.pushSystems and pushGames are
using the shared b.pipeWriter and can outlive servePipeOnce, causing late writes
to hit a new session; fix by making the work session-scoped: in servePipeOnce
create a per-connection context or generation ID and a session-scoped writer
(e.g. capture the current b.pipeWriter into a local variable or pass a
sessionWriter interface into pushSystems/pushGames), pass that session writer
and context/generation into the goroutines, have the goroutines check the
context/generation (or return early if writer is nil/closed) before writing, and
cancel or bump the generation on reconnect so late completions are dropped
instead of writing to the new pipe.
- Around line 384-386: The disconnect handler registered via onSocket should
clear the bridge's authentication state so requestDataCtx doesn't think the
bridge is still authenticated; inside the "disconnect" callback clear
b.sessionToken (and optionally b.authenticated or any flag used to indicate an
authenticated state) so subsequent transient reconnects don't use a stale token
until a new "authenticated" event repopulates it.

---

Outside diff comments:
In `@scripts/windows/hyperhq-plugin/main.go`:
- Around line 224-857: Add unit/integration tests for the new bridge behavior:
create tests exercising the authentication handshake and reconnect path
(exercise connectSocket by driving "connect" and "authenticated" events and
assert sessionToken set and authDone behavior), request/response routing (test
requestData/requestDataCtx together with handleDataResponse to ensure
pendingData mapping, cleanup, and error paths), lifecycle request handling (call
handleLifecycleRequest with various hqLifecycleRequest payloads including
missing ID and hqMethodShutdown to verify plugin:response emit and cancel), pipe
interaction (exercise writePipeEvent, servePipeOnce/runPipeLoop by faking a pipe
connection or using an in-memory net.Pipe to verify pushed Systems/Games and
command routing via handlePipeCommand), and edge cases (decodeFirst,
unmarshalIfPresent, newRequestID uniqueness/fallback). Follow TESTING.md and
pkg/testing/README.md patterns: add a _test.go beside main.go, use test
doubles/mocked socketio server and a fake pipe connection, control
contexts/timeouts to exercise reconnects and error returns, and assert
logs/returned errors where appropriate.
🪄 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: 207c0fcd-bec9-4c97-98a6-7d6d7c3f1593

📥 Commits

Reviewing files that changed from the base of the PR and between 1221591 and 47551af.

⛔ Files ignored due to path filters (1)
  • scripts/windows/hyperhq-plugin/go.sum is excluded by !**/*.sum
📒 Files selected for processing (13)
  • .golangci.yml
  • Taskfile.dist.yml
  • pkg/platforms/shared/schemes.go
  • pkg/platforms/windows/hyperhq.go
  • pkg/platforms/windows/hyperhq_test.go
  • pkg/platforms/windows/launchbox.go
  • pkg/platforms/windows/platform.go
  • scripts/tasks/cross-lint.yml
  • scripts/tasks/windows.yml
  • scripts/windows/hyperhq-plugin/Dockerfile
  • scripts/windows/hyperhq-plugin/go.mod
  • scripts/windows/hyperhq-plugin/main.go
  • scripts/windows/hyperhq-plugin/plugin.json

Comment thread scripts/windows/hyperhq-plugin/go.mod Outdated
Comment thread scripts/windows/hyperhq-plugin/main.go Outdated
Comment thread scripts/windows/hyperhq-plugin/main.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/platforms/windows/hyperhq.go (1)

1-986: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add missing unit coverage for HyperHQ request/response correlation

pkg/platforms/windows/hyperhq_test.go already covers the HyperHQ wire structs (JSON serialization/deserialization), the mapping helpers (buildHqMappings, shouldIgnoreEmptyHqSystemsRefresh, buildHqSystemLookup via TestHyperHqPlatformMapping), and scanner buffer sizing, plus “not connected” error paths for IsConnected/LaunchGame/RequestSystems.

Add unit tests for hqSystemQueryKey and for the "Games" event handling logic that matches pendingGamesReq.queryKey and sends on pendingGamesReq.response (there are currently no tests exercising RequestGamesForSystemSync or this pending-response correlation path).

🤖 Prompt for 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.

In `@pkg/platforms/windows/hyperhq.go` around lines 1 - 986, Add unit tests to
cover hqSystemQueryKey and the pending-games response correlation: write a test
that verifies hqSystemQueryKey produces the expected null-separated key for a
hqSystemQueryTarget, and write a test that simulates receiving a "Games" event
string by calling handleEvent (or by invoking the scanner path) with a JSON
payload whose SystemId/SystemName/SystemReferenceId matches a
pendingGamesReq.queryKey; set up the HyperHqPipeServer with a
pendingGamesReq.response channel (protected by pendingGamesReqMu) and assert the
response channel receives the expected hqGamesResponse (including Error and
Games fields), and also a negative case where queryKey mismatches so no send
occurs. Use the server methods RequestGamesForSystemSync and/or directly
manipulate pendingGamesReq/pendingGamesReqMu to emulate an in-flight request and
ensure proper locking/unlocking around pendingGamesReq in the test.
🧹 Nitpick comments (1)
pkg/platforms/windows/hyperhq.go (1)

277-318: 💤 Low value

Consider using afero for filesystem detection to improve testability.

findHyperHqDir uses os.Stat directly, making it difficult to unit test without real filesystem access. Injecting an afero.Fs parameter would allow mocking the filesystem in tests.

As per coding guidelines: "Use afero for filesystem operations in testable code".

🤖 Prompt for 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.

In `@pkg/platforms/windows/hyperhq.go` around lines 277 - 318, The findHyperHqDir
function currently calls os.Stat directly which prevents unit tests from mocking
the filesystem; change its signature to accept an afero.Fs (e.g. func
findHyperHqDir(fs afero.Fs, cfg *config.Instance) (string, error)), keep using
os.UserHomeDir() for home resolution, replace any os.Stat(dir) checks with
fs.Stat(dir) (or afero.Exists equivalents) and update all callers to pass an
appropriate Fs (real afero.NewOsFs() in production, afero.NewMemMapFs() in
tests); update tests to inject a mock in-memory FS and assert directory
discovery without touching the real filesystem.
🤖 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.

Outside diff comments:
In `@pkg/platforms/windows/hyperhq.go`:
- Around line 1-986: Add unit tests to cover hqSystemQueryKey and the
pending-games response correlation: write a test that verifies hqSystemQueryKey
produces the expected null-separated key for a hqSystemQueryTarget, and write a
test that simulates receiving a "Games" event string by calling handleEvent (or
by invoking the scanner path) with a JSON payload whose
SystemId/SystemName/SystemReferenceId matches a pendingGamesReq.queryKey; set up
the HyperHqPipeServer with a pendingGamesReq.response channel (protected by
pendingGamesReqMu) and assert the response channel receives the expected
hqGamesResponse (including Error and Games fields), and also a negative case
where queryKey mismatches so no send occurs. Use the server methods
RequestGamesForSystemSync and/or directly manipulate
pendingGamesReq/pendingGamesReqMu to emulate an in-flight request and ensure
proper locking/unlocking around pendingGamesReq in the test.

---

Nitpick comments:
In `@pkg/platforms/windows/hyperhq.go`:
- Around line 277-318: The findHyperHqDir function currently calls os.Stat
directly which prevents unit tests from mocking the filesystem; change its
signature to accept an afero.Fs (e.g. func findHyperHqDir(fs afero.Fs, cfg
*config.Instance) (string, error)), keep using os.UserHomeDir() for home
resolution, replace any os.Stat(dir) checks with fs.Stat(dir) (or afero.Exists
equivalents) and update all callers to pass an appropriate Fs (real
afero.NewOsFs() in production, afero.NewMemMapFs() in tests); update tests to
inject a mock in-memory FS and assert directory discovery without touching the
real filesystem.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ac8b2721-0204-436f-a7f5-d90ee18e46d3

📥 Commits

Reviewing files that changed from the base of the PR and between ad3633c and f3f1fd9.

⛔ Files ignored due to path filters (1)
  • scripts/windows/hyperhq-plugin/go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • pkg/assets/systems/Custom.json
  • pkg/database/systemdefs/systemdefs.go
  • pkg/platforms/windows/hyperhq.go
  • pkg/platforms/windows/hyperhq_test.go
  • pkg/platforms/windows/launchbox.go
  • pkg/platforms/windows/launchbox_test.go
  • pkg/platforms/windows/platform.go
  • pkg/service/clock_monitor.go
  • pkg/service/clock_monitor_test.go
  • scripts/tasks/windows.yml
  • scripts/windows/hyperhq-plugin/go.mod
  • scripts/windows/hyperhq-plugin/main.go
  • scripts/windows/hyperhq-plugin/main_test.go
  • scripts/windows/hyperhq-plugin/pipe_windows.go
  • scripts/windows/hyperhq-plugin/plugin.json
💤 Files with no reviewable changes (1)
  • scripts/tasks/windows.yml
✅ Files skipped from review due to trivial changes (1)
  • pkg/assets/systems/Custom.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • scripts/windows/hyperhq-plugin/pipe_windows.go
  • pkg/platforms/windows/platform.go
  • pkg/platforms/windows/hyperhq_test.go
  • scripts/windows/hyperhq-plugin/main.go

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