harness: wally openwork with every RunAnywhere model

Merged
SI
8h ago
+1241-14

wally openwork -m <model> opens the OpenWork desktop app (different-ai/openwork) with every RunAnywhere model in its model picker.

How it works: wally builds an opencode config and hands it to the app in OPENCODE_CONFIG_CONTENT. OpenWork passes its environment to the opencode 1.18.33 engine it bundles, and that engine merges the variable last, after OpenWork's own config file. The hosted catalog goes under runanywhere. A local -m starts the kit server on loopback and adds runanywhere-local beside the hosted list. The launched model is selected.

The app runs as a second instance on a profile under the state dir (openwork/). Its Electron data, runtime DB, server settings, opencode history and workspace all live there, so the user's own OpenWork, opencode history and home folder are never written. The profile is kept between runs.

Two OpenWork defaults are switched off for that profile, both found by running it:

  • A fresh profile sends chats to OpenWork's opencode 2 engine, which gets an allowlisted environment and never sees the provider. OPENWORK_ENGINE_V2_PREVIEW=off and OPENWORK_ENGINE_AUTO_UPGRADE=0 keep chats on the v1 engine.
  • With no workspace list, OpenWork creates ~/OpenWork Chat in the real home. wally writes a list naming its own folder first, using OpenWork's id scheme (ws_ + sha256(path)[:12]).

The provider declares X-RA-Harness: opencode, because the contract has no openwork value yet. On macOS a missing app gets a brew install --cask openwork offer (never npm i openwork, which is a different project). Quitting the app ends the run, and Ctrl-C quits the app. open_code_provider was split out of build_open_code_config so both providers share one builder.

Tested on macOS arm64 with OpenWork 0.18.63:

  • tests/test_wally_openwork.rs: 9 hermetic tests (config, profile env, workspace id, app detection, launch command).
  • tests/local_harness: a stand-in openwork app, signed out and signed in, plus the missing-app path.
  • scripts/test/e2e-openwork.sh (opt-in, WALLY_E2E_OPENWORK=1): real app. 10 hosted models plus 1 local listed and connected, the launched one selected, pong back on runanywhere-local/qwen3-4b-instruct-2507 and runanywhere/glm-5.3-flash, then a clean quit. wally models list --cloud shows 11; the 11th is eve, a decision model kept out on purpose.
  • ctest (6/6), fmt, clippy -D warnings, test ledger, agents sync, versions, sys bindings.
  • Goldens: the new command line shows up in the usual 31 root-list cases, plus help__openwork and help__help__openwork.

Not done:

  • GUI checks by a person (onboarding screen, picker, Ctrl-C, running beside an existing OpenWork).
  • Windows: the install path %LOCALAPPDATA%\Programs\OpenWork\OpenWork.exe is a guess, and nothing has run there.
  • Linux.
  • The engine still writes its log to the real ~/.local/share/opencode/log, and the user's global ~/.config/opencode providers show up next to ours.

Summary by cubic

Adds wally openwork -m <model>, which opens the OpenWork desktop app with every RunAnywhere model in its model picker. The app runs as a second instance on a private profile so the user's own OpenWork, opencode history, and home folder are never written.

Behavior

  • The provider config goes in OPENCODE_CONFIG_CONTENT: hosted models under runanywhere, a local model starts the kit server and adds runanywhere-local, with the launched model selected. An expired account token is refreshed first and the hosted endpoint passes the image gate.
  • The app is launched from its own executable rather than open, so the profile environment (carrying the account token) reaches the child directly and the app stays wally's child: Ctrl-C reaches it and its exit ends the run.
  • Before the first launch the profile gets a workspace list that names its workspace exactly as OpenWork resolves it (canonicalized, native separators, Windows \\?\ prefix stripped), so no ~/OpenWork Chat is created in the real home.
  • Two OpenWork defaults are switched off so chats stay on the opencode 1.x engine, which reads the variable before OpenWork's own config. XDG_DATA_HOME also moves to the profile, so the engine's log and saved logins stay out of the real home.
  • The app is found by bundle ID on macOS, WALLY_OPENWORK_APP points at any other install, and Linux looks only for OpenWork.AppImage on PATH (a bare openwork is a different npm project). A missing app on macOS offers brew install --cask openwork and never npm i openwork.
  • Quitting the app ends the run; Ctrl-C quits the app.
  • Windows and Linux are not yet verified against a real install.

Summary by CodeRabbit

  • New Features

    • Added wally openwork to launch OpenWork with a local or hosted model, or without model configuration. OpenWork uses a separate persistent profile and workspace.
    • Added model selection and instructions for missing installations, including an optional Homebrew install on macOS.
    • Updated command help and guides with usage examples.
  • Tests

    • Added coverage for OpenWork launches, model configuration, app discovery, and missing-app handling, including an opt-in macOS end-to-end test.