Files
desktop/LLM.md
e7547de725 feat(desktop): shared NetworkSwitcher + WalletMenu — the ONE hanzo.network standard (#29)
* wip(desktop): GPU-node connect (gpu.rs/useGpuConnect/hanzo-auth) + luxwallet start + brand assets

* feat(desktop): native omnichain post-quantum Lux Wallet (node-independent)

Mirror of the live fix in hanzoai/gui pkgs/ai (@hanzo/ai) applied to this
repo's pre-convergence frontend tree. Replaces the hanzo-node-backed crypto
wallet — which couldn't create/show a wallet without a connected node — with a
self-contained stack under apps/hanzo-desktop/src/lib/lux-wallet:

- luxfi/crypto WASM (real FIPS-204 ML-DSA-65 + secp256k1 + keccak); EVM keys via
  BIP-44 keys.deriveSecp256k1 (bit-identical to ethers/MetaMask), PQ identity
  via keys.serviceIdentity. Secrets sealed in OS keychain, never plaintext.
- create / import / list / reveal / balance / send across the 11 ready EVM
  chains (@luxwallet/chains + /rpc); non-EVM X/P/Q/Z marked "coming soon".
- Sign-In-With-Wallet: /v1/iam/web3/nonce -> CAIP-122 -> EIP-191 sign ->
  /v1/iam/web3/verify (@luxwallet/connect + @luxfi/crypto).
- local-HD-PQ default; MPC / Safe selectable (coming soon).

Wiring: rewrite pages/crypto-wallet.tsx onto the store; node-independent /wallet
route + "Sign in with Wallet" on quick-connection; drop dead wallets-context.
MIT/BSD deps vendored under apps/hanzo-desktop/vendor.

NOTE: this app now renders @hanzo/ai (main.tsx), so the shipping wallet fix
lands via hanzoai/gui; this mirror keeps the repo's own tree consistent.

* feat(desktop): the ONE network/wallet standard — shared NetworkSwitcher + WalletMenu

Aligns the desktop onto the shared hanzo.network model (@hanzo/ui/network +
@hanzo/ui/wallet from @hanzo/[email protected] — same standard as the hanzo
CLI and console):

- lib/network.ts: ONE place composing the brand network list (hanzo →
  canonical mainnet/testnet/devnet/local envs; zoo/lux → brand mainnet)
  into the shared selected-network store.
- Sidebar footer mounts <NetworkSwitcher/> + <WalletMenu/> (menuSide=top);
  wallet auto-provisions the PQ HD account via the lux-wallet adapter
  (keychain-sealed secrets; backup stays on the crypto-wallet page).
- Selected network drives endpoints: lux-wallet brandRpcConfig gateway +
  rpc override, defaultChainId, and useChainBalance now follow the
  selection (switch env → every chain/cloud call repoints).
- styles.css: semantic token aliases + @source for the shared components.
- tsconfig: moduleResolution bundler (exports-aware; tsc clean).
- package.json: declare @hanzo/ai (was undeclared — npm install pruned it
  and broke main.tsx) + @hanzo/ui alias.

tsc 0 errors; vite build green; vitest 81/81.

* docs(LLM.md): the network/wallet standard — seams + gotchas

* chore(desktop): bump @hanzo/ui-shadcn 5.7.3 -> 5.7.4 (genesis-canonical chain IDs)

Picks up the corrected network set (testnet 36962, devnet 36964, local
1337 @ :9630/v1/bc/C/rpc). tsc 0; vite build green.

---------

Co-authored-by: hanzo-dev <[email protected]>
2026-07-08 09:12:15 -07:00

6.4 KiB

Hanzo Desktop

Project

Desktop AI agent app. React + Vite + Tauri (Rust backend).

Structure

apps/hanzo-desktop/
  src/               # React frontend
  src-tauri/         # Rust Tauri backend
  public/            # Static assets
libs/
  hanzo-ui/          # Shared UI components
  hanzo-i18n/        # Internationalization
  hanzo-message-ts/  # Message/job API types

Commands

npx nx serve hanzo-desktop     # Dev (Tauri, uses tauri.conf.local.json)
npx nx build hanzo-desktop     # Production build
npx nx test hanzo-desktop      # Vitest
npx nx lint hanzo-desktop      # ESLint
npx nx run hanzo-desktop:typecheck
npx nx run hanzo-desktop:cargo-check

Alternative: cd apps/hanzo-desktop && npm run dev|build|lint

Code Style

  • 2 spaces, Prettier + Tailwind plugin, single quotes
  • Files/dirs: kebab-case. Components/types: PascalCase. Vars/functions: camelCase
  • Tests: Vitest + @testing-library/react, co-located in __tests__/, *.test.ts(x)
  • Commits: Conventional (feat:, fix:, chore:, docs:)

Tooling

  • Node 20+, npm 10+, Rust toolchain for Tauri
  • postinstall runs patch-package
  • Env: copy .env.example, never commit secrets

Release Pipeline

Workflows

  • Production: .github/workflows/release-prod.yml on tags [0-9]+.[0-9]+.[0-9]+
  • Development: .github/workflows/release-dev.yml on tags dev-v[0-9]+.[0-9]+.[0-9]+

Required Secrets

Apple (macOS signing): APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITY, APPLE_ID, APPLE_PASSWORD, APPLE_TEAM_ID, KEYCHAIN_PASSWORD

Tauri updates: TAURI_PRIVATE_KEY, TAURI_KEY_PASSWORD

Windows EV (Google Cloud KMS): EV_CODE_SIGNING_CERTIFICATE

Infrastructure: R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, SLACK_BOT_TOKEN

App: VITE_POSTHOG_API_KEY, SECRET_DESKTOP_INSTALLATION_PROOF_KEY

Build Artifacts

  • Installers: .AppImage (Linux), .dmg (macOS), .exe (Windows)
  • Update bundles: .tar.gz (macOS/Linux), .nsis.zip (Windows)
  • Signature files: .sig for Tauri auto-updater
  • Uploaded to: GitHub Releases + Cloudflare R2 (download.hanzo.ai)
  • Rollout: rename updates-next.json to updates.json

Troubleshooting

  • APPLE_CERTIFICATE must be base64 without newlines
  • Use base64 --decode > file not base64 --decode -o file
  • Ensure package.json version matches git tag
  • Update check failures are handled gracefully (no user-facing errors)

Model Tools (hanzo-ml integration)

The Node Manager window has a Model Tools tab (components/hanzo-node-manager/model-tools.tsx) that drives the hanzoai/ml features via the Tauri backend (src-tauri/src/model_tools):

  • Model soups + BitDelta — fully wired. Shells out to the hanzo-ml soup CLI (hanzo_ml::model_delta): average (uniform/weighted soup), delta (base + mean fine-tune delta), bitdelta-encode / bitdelta-apply (1-bit delta compress/restore). Binary resolved via HANZO_SOUP_BIN, a bundled soup-<arch> next to the app, or soup on PATH. The UI gates on availability.
  • Frontend: lib/model-tools/model-tools-client.ts (invoke wrappers + React Query hooks). Tauri commands: model_tools_soup_*, model_tools_bitdelta_*.

Machines (Docker Desktop replacement)

Desktop UI for Linux VMs (vfkit) and the docker / k3s stack served by the hanzod daemon in hanzoai/node/machine/. Hanzo Desktop is a drop-in all-in-one Docker Desktop replacement: containers, Kubernetes, and Linux machines from one app, one binary backend.

apps/hanzo-desktop/
  src-tauri/src/machine/    # Tauri commands -> unix socket client
    socket.rs               # ~/.hanzo/run/machined.sock resolver
    types.rs                # mirrors machine/proto.go (Machine, ExecFrame, ...)
  src/pages/machines/       # React UI (list, create dialog, exec stream)
  • Tauri commands: machine_health, machine_list, machine_create, machine_start, machine_stop, machine_delete, machine_exec (streaming).
  • Wire format is JSON over the daemon's UNIX socket - see hanzoai/node/machine/proto.go for the authoritative contract.
  • Brand gating: the Machines / Containers / K8s pages are Hanzo-only by default. Other brands (zoo, liquidity) must set VITE_ENABLE_MACHINES=true (or the equivalent runtime flag in libs/brand-config) to reveal them. See libs/brand-config/src/index.ts::isMachinesEnabled.

e2e

e2e-tests/machine-flow.spec.ts runs against pnpm dev, mocks window.__TAURI_INTERNALS__.invoke for the machine_* commands, and asserts the create dialog round-trip. CI must pass VITE_BRAND=hanzo so the Machines route renders.

GRPO Status

Trainer-free GRPO lives in hanzo_training::grpo (a Rust library + a runnable grpo_toy example) — there is no GRPO server/daemon yet. The desktop exposes a developer-preview entry (model_tools_grpo_run, surfaced in the Model Tools tab) that runs cargo run -p hanzo-training --example grpo_toy from a local checkout (HANZO_ML_DIR). This is plumbing/demo only.

Productizing GRPO in-app still needs: experience/trajectory storage, agent versioning / A/B testing, a real training job pipeline (driving the Policy trait on a packaged model), feedback→reward mapping, and ML metrics. Foundation exists (agent CRUD, message history with tool metadata, Zustand, React Query).

Network + Wallet (the ONE standard)

Shared components from @hanzo/ui/network + @hanzo/ui/wallet (npm alias @hanzo/ui -> @hanzo/ui-shadcn@^5.7.3, the 5.x line — same standard as the hanzo CLI network.rs and the console):

  • Model: Network = (env, label, networkID, evmChainID, rpcEndpoint, apiEndpoint). Sovereign L1 => networkID === evmChainID. Hanzo envs: mainnet 36963 / testnet 36964 / devnet 36965 / local 31337; public envs share api.hanzo.ai; RPC per env (rpc.hanzo[-test|-dev].network).
  • src/lib/network.ts is the ONE composition point (brand -> network list -> shared store). Endpoint consumers: lux-wallet/chains.ts (brandRpcConfig/defaultChainId) + hooks/useChainBalance.ts read the SELECTED network via getNetwork()/useNetwork().
  • Wallet: lux-wallet/ui-adapter.ts adapts the PQ HD keychain wallet to the shared <WalletMenu/> (auto-provisions on first connect; secrets never leave the store/keychain).
  • Mounted in the sidebar footer of pages/layout/main-layout.tsx (menuSide="top"). Semantic token aliases live in libs/hanzo-ui/src/styles/styles.css.
  • @hanzo/ai is a REAL dependency of src/main.tsx — keep it declared in package.json (it was once undeclared and npm install pruned it).