mirror of
https://github.com/alphaXiv/OpenResearch.git
synced 2026-11-11 09:59:34 +08:00
ea41b76ee197fa0aae9bb7461fc015de75b7ed03
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2cdbb324af |
feat: improve research workspace (#803)
- Clearer model selection - Faster new chat shortcuts - Cleaner session previews - Easier sidebar navigation - More reliable unsent drafts - Safer message retries - Smoother menus and dialogs - Better small-window layouts - More useful tooltips - Improved experiment visibility - More reliable release builds Assisted-by: gpt-6.1-terra Assisted-by: gpt-6.1-sol Assisted-by: claude-sonnet-5.5 |
||
|
|
9f53431c37 |
fix: supervise managed experiment rentals remotely (#717)
* fix: supervise managed experiment rentals remotely * fix: scope collection timer to remote supervisor builds * fix: harden rental launch and cancellation handshakes * fix: wake waiting chats when rental outcomes are unavailable * fix: redact rental capabilities from public run APIs * fix: redact the serialized rental lease field * fix: detach rental supervisor without retaining SSH pipes * ci: pin Ubuntu LTS and keep the current package version |
||
|
|
643b385abf |
OR-423 Open the desktop app when orx.exe is double-clicked on Windows (#539)
* Open the desktop app when orx.exe is double-clicked on Windows A double-clicked orx.exe ran `orx up`: a console window plus a browser tab, counted in telemetry as a terminal `orx up`. It now relaunches itself as `orx app` in a hidden console with null stdio, as OpenResearch.exe does, so the user gets the app window and Explorer's console closes. Removes code that only served the old path: the `orx up` "already running" browser reopen, the empty-args `up` relaunch, and their tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep --no-telemetry when a double-click relaunches as the app `orx app`'s argv must stay exactly `app`, so the opt-out rides in ORX_APP_NO_TELEMETRY, which self-update restarts inherit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5538a61f44 |
OR-423 Install Git and OpenCode reliably on Windows (#540)
* Install Git and OpenCode reliably on Windows Re-read the registry PATH so a Git installed while orx runs is found, offer an orx-installed PortableGit in onboarding, download OpenCode via the system proxy with an npm fallback, and keep the install script's own text out of setup telemetry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review: registry flags, 7z output path, install prompt on both steps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review round two; reword the OpenCode architecture error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review round three: full install error chain, tidy portable Git Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Windows install script borrow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep concurrent PortableGit installs from undoing each other Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cut registry PATH values at their first NUL RegGetValueW can report an expanded value's size past its terminator, which left a NUL in the PATH orx hands every child, so every spawn failed with "nul byte found in provided data". Also log Git install failures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Space the onboarding Git card from the agent cards Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
78c61c52bf |
Sign Windows desktop releases with alphaXiv certificates (#507)
* Sign Windows releases with Azure Artifact Signing * Limit Windows signing to OIDC credentials * Use current signing action when packaging older releases |
||
|
|
c95be22a35 |
OR-326 Add the Linux desktop app as a self-updating AppImage (#445)
* Open the macOS app's dashboard in its own window The OpenResearch.app now hosts the dashboard in a native window (tao + wry WKWebView) instead of handing it to the user's browser. It adds a standard menu bar, save panels for downloads, a native window.confirm panel, and a Cmd+Q that flushes workspace state and shuts the server down cleanly. Pop-ups open in the system browser (http/https/mailto only). The app now prefers port 4792 so the window's localStorage survives relaunches. The Dock-click tab-focus script, its Apple-events entitlement, and the SSE client counter it relied on are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Open the dashboard in its own window on Windows Adds the Windows desktop app. A small GUI-subsystem OpenResearch.exe (windows/launcher) starts the orx.exe beside it as `orx app` in a hidden console, so orx and the git, shell, and agent processes it runs share one invisible console instead of each flashing a window. `orx app` shares the macOS window code in src/commands/app.rs: WebView2 window, pop-ups to the system browser, save panel, page-load reveal, and port 4792. On Windows, closing the window quits, a second launch focuses the running window (named mutex + event), and the taskbar groups the window with the Start menu shortcut. An update restart relaunches as the app on the same port. Quit on both platforms now goes through up::request_shutdown instead of a self-sent SIGTERM. An Inno Setup script builds a per-user OpenResearch-Setup.exe with a Start menu entry and a WebView2 bootstrap. CI builds it as an artifact, and release-windows-app.yml attaches it to releases once WINDOWS_APP_ENABLED is set. The icon is embedded via embed-resource. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Windows build and address review of the Windows app - The focus listener captured its bare HANDLE (edition 2021 disjoint capture) instead of the Send wrapper, which failed to compile on Windows. - An orx.exe away from the CLI installer's prefix, like the app's, is now Portable even when the installer's receipt exists, so it can update itself. - Single instance creates its event before the mutex; the launcher hands its foreground rights to orx.exe. - Focus requests and server readiness are ignored while quitting, and focus waits for the first load. The save dialog is owned by the window. - Telemetry counts an app start only after the instance claim. - The installer reports a failed WebView2 bootstrap and shows progress. - Icon embedding now fails the build if no resource compiler is found. - CI format-checks the launcher; the release job drops an unpinned action. - Docs: maintainer notes for the release gate, two known gaps, and wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tighten the Windows app after a second review - Keep the macOS save panel free-floating: only Windows gets the window as its owner, since a parent makes rfd show a sheet on macOS. - Treat the WebView2 bootstrap as failed unless the runtime is then present. - Move the UTF-16 helper out of the single-instance module, and bind the kernel object names before the mutex call that GetLastError follows. - Docs and a dead_code reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add the Linux desktop app as a self-updating AppImage A `desktop` cargo feature builds the windowed app on Linux (glibc, WebKitGTK), leaving the static musl CLI builds untouched. build.rs sets cfg(desktop_app) for macOS, Windows, and Linux with the feature, replacing the macOS-or-Windows gates. The AppImage's AppRun starts `orx app`, sharing the Windows entry point: the webview is built into the GTK window's box (X11 and Wayland), closing quits, a Unix socket in XDG_RUNTIME_DIR keeps one instance and focuses it, and the login shell's PATH is adopted as on macOS. scripts/build-linux-appimage.sh bundles WebKitGTK with pinned linuxdeploy, its GTK plugin, and appimagetool, copying WebKit's helper processes and rewriting libwebkit2gtk's /usr paths to ././ so they resolve inside the image. CI builds x86_64 and aarch64 AppImages on Ubuntu 22.04 and smoke-tests each under Xvfb; release-linux-app.yml attaches them with linux-app.json once LINUX_APP_ENABLED is set. The AppImage updates itself (InstallChannel::AppImage, updates/linux_app.rs): a sha256-checked download renamed over the file, production builds only, and Restart execs the new AppImage on the same port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Linux app's downloads, bundled WebKit, and host environment From review of the Linux desktop app: - Downloads froze the app: rfd's GTK backend runs its dialog on a thread of its own, which waits forever on the main context tao holds. The save dialog is now a gtk::FileChooserDialog run on the main thread. - The bundled WebKit helpers found their libraries only beside themselves, so they loaded the host's WebKit or none. They now get an RPATH to the image's usr/lib, and linuxdeploy no longer makes stray copies of them. - The GTK hook's variables reached every host program orx opens. AppRun now saves the session's values and orx hands them back to xdg-open, the folder picker, error dialogs, and agents. - The smoke test now runs after WebKitGTK is removed from the runner and checks that each WebKit helper runs, and loads libwebkit2gtk, from the image; cleanup kills the app's whole process group. - Startup failures now reach stderr and a zenity or kdialog dialog. - The tools and the AppImage runtime are pinned by sha256, and only the release job that publishes can write to the release. - Smaller fixes: the shell probe runs after the single-instance claim and falls back to /bin/sh; APPDIR is canonicalized and must not be empty or root; relative project paths resolve against home inside the image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the session's GTK settings across Linux app restarts and terminals Restore the host GTK variables before an update relaunches the AppImage, so the new AppRun doesn't save the old image's values as the session's, and in the dashboard's terminals. Share one APPDIR containment check between the update channel, relative project paths, and the folder picker, which now keeps a terminal `orx up`'s working directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Relaunch the AppImage only from inside it, and tidy after review Pick the relaunch target with the same APPDIR check as the update channel, so an `orx app` started from the app's terminal restarts itself. Hand the shell probe the session's GTK settings, harden the smoke test's helper checks and cleanup, and bring the docs up to date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Run the AppImage detection test only on Unix Its mount paths aren't absolute on Windows, which has no AppImage anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Import the AppImage test's helper inside the Unix-only test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show the app window even when the dashboard never finishes loading On a UTM VM the Linux app ran with no window: it stays hidden until the page finishes loading, and that never happened. Show it 15 seconds after the server is up regardless, say so on stderr, and have the smoke test fail if that fallback fires or no window appears. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Give the Linux app its name and icon in the dock, and keep GIO off host modules GNOME shows an unmatched window as a gear named after its class, so name the program OpenResearch and have each launch install a desktop entry and icon pointing at the AppImage (TryExec hides it once the file is gone). Bundle GLib's TLS module and set GIO_MODULE_DIR to the image's, so the bundled GLib stops loading the host's modules, built against a newer one. A second launch now shows the window even before the page loads, so a stuck instance can't swallow it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tidy the Linux app after the fourth review Write the desktop entry only from the AppImage's own orx (shared with the update relaunch), keep a session's GIO_EXTRA_MODULES off the bundled GLib, mark a Dock-reopened macOS window as shown so the load fallback can't reopen it, close a race in the smoke test, and note the Fedora and openSUSE TLS gap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show a stalled app window, and close the app before the installer runs If the dashboard never finishes loading, show the window 15 seconds after the server is up and say so on stderr; a relaunch (or a Dock click on macOS) also shows it before the page loads. The installer and uninstaller now check the app's single-instance mutex and ask the user to close it, rather than replacing files under a running app and skipping its shutdown path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a replaced download's original until it lands, and don't offer a launch without WebView2 Move the file a download replaces aside and restore it if the download fails or is cancelled (WebView2's flyout can cancel), rather than deleting it up front. The installer no longer offers to start OpenResearch when the WebView2 Runtime is still missing, since the window could not open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
2c63f548c2 |
OR-326 Open the dashboard in its own window on Windows (#439)
* Open the macOS app's dashboard in its own window The OpenResearch.app now hosts the dashboard in a native window (tao + wry WKWebView) instead of handing it to the user's browser. It adds a standard menu bar, save panels for downloads, a native window.confirm panel, and a Cmd+Q that flushes workspace state and shuts the server down cleanly. Pop-ups open in the system browser (http/https/mailto only). The app now prefers port 4792 so the window's localStorage survives relaunches. The Dock-click tab-focus script, its Apple-events entitlement, and the SSE client counter it relied on are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Open the dashboard in its own window on Windows Adds the Windows desktop app. A small GUI-subsystem OpenResearch.exe (windows/launcher) starts the orx.exe beside it as `orx app` in a hidden console, so orx and the git, shell, and agent processes it runs share one invisible console instead of each flashing a window. `orx app` shares the macOS window code in src/commands/app.rs: WebView2 window, pop-ups to the system browser, save panel, page-load reveal, and port 4792. On Windows, closing the window quits, a second launch focuses the running window (named mutex + event), and the taskbar groups the window with the Start menu shortcut. An update restart relaunches as the app on the same port. Quit on both platforms now goes through up::request_shutdown instead of a self-sent SIGTERM. An Inno Setup script builds a per-user OpenResearch-Setup.exe with a Start menu entry and a WebView2 bootstrap. CI builds it as an artifact, and release-windows-app.yml attaches it to releases once WINDOWS_APP_ENABLED is set. The icon is embedded via embed-resource. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix the Windows build and address review of the Windows app - The focus listener captured its bare HANDLE (edition 2021 disjoint capture) instead of the Send wrapper, which failed to compile on Windows. - An orx.exe away from the CLI installer's prefix, like the app's, is now Portable even when the installer's receipt exists, so it can update itself. - Single instance creates its event before the mutex; the launcher hands its foreground rights to orx.exe. - Focus requests and server readiness are ignored while quitting, and focus waits for the first load. The save dialog is owned by the window. - Telemetry counts an app start only after the instance claim. - The installer reports a failed WebView2 bootstrap and shows progress. - Icon embedding now fails the build if no resource compiler is found. - CI format-checks the launcher; the release job drops an unpinned action. - Docs: maintainer notes for the release gate, two known gaps, and wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tighten the Windows app after a second review - Keep the macOS save panel free-floating: only Windows gets the window as its owner, since a parent makes rfd show a sheet on macOS. - Treat the WebView2 bootstrap as failed unless the runtime is then present. - Move the UTF-16 helper out of the single-instance module, and bind the kernel object names before the mutex call that GetLastError follows. - Docs and a dead_code reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show a stalled app window, and close the app before the installer runs If the dashboard never finishes loading, show the window 15 seconds after the server is up and say so on stderr; a relaunch (or a Dock click on macOS) also shows it before the page loads. The installer and uninstaller now check the app's single-instance mutex and ask the user to close it, rather than replacing files under a running app and skipping its shutdown path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep a replaced download's original until it lands, and don't offer a launch without WebView2 Move the file a download replaces aside and restore it if the download fails or is cancelled (WebView2's flyout can cancel), rather than deleting it up front. The installer no longer offers to start OpenResearch when the WebView2 Runtime is still missing, since the window could not open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
46bdceba46 | fix(windows): avoid false SSH disconnection status (#345) | ||
|
|
4a646d9b4c |
Add self-update on Windows (#334)
Windows installs could never update themselves: the PowerShell installer's receipt lives under %LOCALAPPDATA%, which orx did not look in, and the installer cannot overwrite a running exe. orx now stages the release via the installer beside orx.exe and swaps it in with two renames, parks the old binary under a unique .old name, and rewrites the receipt version itself. A zip-extracted orx.exe outside package-manager and cargo target paths is a new "portable" channel that updates in place with no receipt. `orx up` relaunches on Windows by spawning the new binary, which waits on the parent's process handle before binding the port. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
9b05f9771c |
OR-199 Windows support for the CLI and dashboard (#299)
* Make orx build and resolve its tools on Windows Block A of the Windows beta: the fixes that need no Windows machine to write, so the branch is ready to clone the moment one is set up. - Extend a bare binary name with PATHEXT when searching PATH. Every harness is looked up by bare name, so on Windows the picker reported Claude Code, Codex and OpenCode all absent and the dashboard could do nothing. - Compose a child's PATH with `;` rather than a hardcoded `:`. - Find bash through `git` rather than PATH. The `bash.exe` usually on PATH is the WSL launcher in System32, which sees a different filesystem than the run directory it would be handed. - Give git an empty path it understands. `/dev/null` reads as a missing relative path on Windows, silently re-enabling repository hooks. - Check a local run's liveness with a zero-timeout wait; there is no `ps` to shell out to. - Link through native_store::create_symlink, which already has both branches, instead of calling the unix symlink directly. - Add a windows-latest CI job so none of this regresses. The Windows branches here have not been compiled yet — that is the next step, on the machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Allow CI to be dispatched against a branch * Compile the remaining unix-only code paths out on Windows Round one of the Windows compile, from the first CI run: 25 diagnostics, seven root causes. - Give remote_host the `#[cfg(not(unix))]` twins its uid/mode helpers were missing, matching what `directory_writable` already does. Windows keeps only the symlink and directory checks in `ensure_private_dir`, which is a weaker guarantee than the unix path makes. - Gate the control channel itself. It is a Unix domain socket, so `--remote-host` is now refused up front on Windows rather than starting a host nothing could attach to. Local `orx up` is untouched. - Annotate `signal`, whose type came only from the cfg(unix) block. - Gate the EXDEV rename fallback, the inode and mode assertions, and the shell-hook tests, all of which assert on things Windows does not have. - Silence the parameters that are only read on unix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Gate the remote-host command surface off on Windows Round two, from the cascade the unresolved socket import had been suppressing: every caller of the six control-channel functions. The module splits cleanly in two. `orx up` uses its types and its dashboard locking — HostDescriptor, DashboardLock, canonical_data_dir — and none of that needs a socket. The `orx remote-host` command surface is socket-backed all the way down, so it is gated as a unit and the command now refuses on Windows instead of failing somewhere further in. Also: the two imports only the gated half reached, and `signal`, which loses its one assignment on Windows and with it the need for `mut`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Keep the compiled-out remote-host half rather than gate it item by item Round three was 24 dead-code and unused-import lints and no real compile errors — the tail of removing a feature's entry points while its machinery stays behind. One scoped allow on the module says that plainly. Gating each constant, helper and request type would be bulkier than the code it guards, would have to be unpicked the moment the control channel gets a Windows transport, and would say nothing the module comment does not. updates.rs is the same shape at smaller scale: relaunch_target and relaunch_args keep their tests on every platform and lose only their caller in the binary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Stop handing git a verbatim path, and let test cleanup fail The Windows suite ran for the first time: 662 passed, 46 failed. Two causes account for 27 of them. `repository_git_dir` canonicalizes, and Windows answers canonicalize with a `\\?\C:\…` verbatim path. Git rejects those outright — "not a git repository" — so importing any existing repository failed. This is a real bug, not a test artifact; the prefix now comes off for drive paths, which are the only ones with a plain form. The other 21 were `remove_dir_all(root).unwrap()` in test teardown, which Windows refuses while any handle into the tree is still open. The codebase already prefers a tolerant cleanup in 146 other places; these 86 now match. All of them are inside `#[cfg(test)]`. Also: the probe fixtures asserted on POSIX PATHs, which are not absolute on Windows and so were rejected by the parser under test. They are parameterized rather than gated — the parsing they cover is not platform-specific, only the fixture was. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Check out LF on every platform Git for Windows defaults to core.autocrlf=true, and SYSTEM_PROMPT.md and the agent-skills SKILL.md files are include_str!'d at build time. A Windows build therefore embedded CRLF and then failed to parse it: playbook_md() splits the template on `-->\n\n` to drop its leading HTML comment, that split stopped matching, and `unwrap_or` kept the comment — so every agent session would have been handed OpenResearch's internal notes as the opening of its system prompt. Two tests caught it, one of them by scanning the rendered playbook for unresolved `{token}` placeholders rather than a fixed list. That is the only reason this surfaced as a test failure and not as a shipped binary. Nothing renormalizes: no tracked text file has CRLF in the index today, so this only governs what lands in a working tree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Fix what Windows found: exec bits, remote paths, cancellation Round two of the Windows suite: 691 passed, 17 failed. Four of those were real bugs rather than test artifacts. Demo onboarding rejected the demo it had just built. NTFS has no executable bit, so runcpu.sh committed as 100644, the tree hash moved, and the commit ids drifted off the BASELINE_SHA/EXPERIMENT_SHA the demo validates itself against. The mode now reaches the tree through the index, where it does not depend on the filesystem. Remote paths were validated with local rules. `storage_root` asked `Path::is_absolute` about `/home/me/.cargo/bin/orx`, which is false under Windows, so a Windows client rejected every legitimate remote path — and the PathBuf it built would have reached a Linux shell separated by backslashes. Remote paths are POSIX whatever the client runs, so they are handled as strings now. `manage_local_file` took `reports/result.md` from the dashboard and answered `reports\summary.md`, which the next request would have carried straight back. Relative paths cross the API `/`-separated. Cancelling a local run did nothing: there is no process group to TERM. `taskkill /T` takes the tree instead, which is what TERMing the group was for. The rest were fixtures asserting on POSIX shapes, a filename using a character Windows reserves, and two LaTeX tests that need a symlink and a shebang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Let the index own the demo's exec bit Setting the mode through `update-index` fixed the commit ids but left the index at 100755 against a working tree NTFS always reports as 0644. With `core.filemode true` git believed the filesystem, read runcpu.sh as modified, and refused to check main back out. Windows trusts the index instead, which is where the mode came from. The two telemetry failures are not diagnosed. HTTP delivery itself works on Windows — `sender_posts_the_first_party_endpoint` asserts an Acknowledged post and passes — so what fails is the removal that follows it, and reading has not told me why. Both assertions now report what a second removal says, which separates a blocked delete from a delete that succeeded while the name lingered. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Keep the demo's origin path native, and judge cancel by liveness Three down to two. `join("demo-repos/nanochat.git")` embeds a separator the platform did not choose, so on Windows the bare origin came out as `...\data\demo-repos/nanochat.git` — mixed, and textually unequal to what git echoes back for the remote it was given. Filesystem calls did not care; comparing the recorded URL to git's answer did. Split into two joins, in product code as well as the tests that caught it. `taskkill /T` returns non-zero when any descendant has already exited on its own, which says nothing about whether the run stopped. Cancellation now reads the leader's liveness, which is the question actually being asked. The telemetry pair is one step from diagnosed. The retry in the previous round answered Ok(()), so the file was there and freely deletable and the removal was never reached — delivery must have come back Retryable. The assertion now names the outcome, which separates a request that never landed from a response classified unexpectedly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Read the request before answering it in the telemetry mock servers The last two Windows failures, and they were the tests' fault rather than delivery's. Two of the three mock servers accepted a connection and wrote their response without ever reading the request. Closing a socket that still holds unread data aborts the connection on Windows instead of closing it gracefully, so the client saw a reset rather than the reply it had already been sent, and classified a 400 as Retryable — which left the outbox file the assertion expected to be gone. The third server always read, which is why it passed and misled the search toward the removal. The read loop it already had is now shared by all three. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Canonicalize into paths a child process can actually use An audit of the `orx up` paths no test exercises. Every bug this branch has fixed so far was in code a test happened to touch; the dashboard's own request handling was the largest area where that was not true. Windows `canonicalize` answers with a verbatim `\\?\C:\…` path, and `CreateProcessW` will not take one as a working directory. The dashboard canonicalizes a session's checkout root and then runs git in it — twelve call sites behind `resolve_checkout_root`, covering the code tree, file reads and writes, and diffs — so none of that could have worked. The same root reaches `run_shell_command` as the cwd for a `!` command, and Codex receives canonicalized paths as its sandbox writable roots. Consistency matters as much as the spelling: containment checks compare a canonicalized child against a canonicalized root, and a mix of the two forms denies access to paths that are genuinely inside. So every canonicalization in the crate now goes through one helper rather than the handful that happened to be reachable from a failing test — that is what makes the property hold rather than the individual fixes. The earlier one-off in `repository_git_dir`, which the import failure found, is folded into it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Look for the harness binaries under the names they actually have Second audit pass, over the spawn path. `find_claude` and `find_opencode` fall back to their installers' drop locations when PATH does not answer, and both spell them as bare names — `~/.local/bin/claude`, `~/.opencode/bin/opencode` — which match no file on Windows. `~/.local/bin` is exactly where Claude Code's own Windows installer puts claude.exe, so the fallback was dead precisely where it was needed. Both now look for the same names PATH does. The rest of the spawn path holds up: config directories travel as environment variables, where a raw path is correct; Codex's config.toml is written through serde_json, whose backslash escape is the one TOML wants; and the binaries themselves come from find_on_path, which learned about PATHEXT earlier on this branch. One gap left deliberately: the PATH guard writes zsh and bash startup hooks and needs ZDOTDIR or HOME to place them, neither of which Windows sets, so it returns early and the guard is simply absent there. It fails closed — a session gets no hook rather than a broken one — and building a Windows equivalent is worth more than a beta needs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round one Six blockers, all real. `orx_bin_dir` dropped any directory whose name contains a colon, which on Windows is every absolute path, so agents were never handed the running orx on PATH — and the separator constant added earlier sat in a branch that never ran. It filters on that constant now. A dashboard shell command that hit its timeout killed nothing on Windows and then waited on the child with no timeout, hanging the turn forever. The non-unix arm terminates the tree, the shape latex already used. BIBINPUTS/BSTINPUTS joined with a colon, so bibtex on Windows lost both the paper's own directory and the system defaults. `restore_local_repository` never pinned core.autocrlf, so a restored demo clone was written CRLF against LF blobs and then failed the cleanliness check that reads it with global config disabled — telling the user their demo "is not the OpenResearch nanochat demo". The remove_dir_all sweep had converted four setup removals along with the teardown, letting tests pass while testing nothing. The Windows uid/mode stubs were unreachable: their whole chain is rooted in cfg(unix) entry points. Gated instead, stubs deleted, and with them a comment claiming a weaker-but-working private runtime directory that does not exist. Also from review: prefix stripping now matches the parsed prefix, so a non-UTF-8 name cannot keep `\\?\` while its root loses it and fail its own containment check; UNC verbatim paths are decoded rather than passed through. PATHEXT set-but-empty no longer reports every tool missing. The bash fallback no longer resolves back to the WSL launcher it rejects. pdfPath goes through the same API path rule as every other relative path. The telemetry signature widened for a test message is reverted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round two Two blockers, both introduced by round one's own fixes. Deleting the Windows uid/mode stubs was wrong: `open_lock` is ungated and calls all three, and `DashboardLock::acquire` reaches it on every `orx up`. That is a Windows compile error on the one platform this branch exists for, and macOS cannot see it. The ownership and mode checks are gated inside `open_lock` now, which keeps the file-type check everywhere and states plainly what Windows does not enforce. Teaching `orx_bin_dir` about the platform separator also handed `ORX_BIN_DIR` to PATH_GUARD, a POSIX snippet that joins `PATH` on colons. Under Git Bash a drive letter split it in two and the guard re-prepended on every startup. The stamp is skipped off unix; `prepare_env` still fronts the directory, which was the point. Also: `cancel_job`'s cfg'd `return` is the function's last statement once stripped, which the Windows clippy job would have rejected; the restore path pins `core.eol` alongside autocrlf so a global `core.eol=crlf` cannot reproduce the same dirty checkout; the verbatim UNC head is built from `OsString` like the tail it is joined to; and the null-device comment no longer claims git falls back to the repository's own hooks, which it does not. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Polish from review round three No blockers in either round-three review. Taking the nits: `open_lock` fstats once instead of twice; the Windows branch of the `ORX_BIN_DIR` stamp is a `#[cfg]` rather than a runtime-false `cfg!`, so it stops resolving the executable only to discard it; two doc comments that described one platform now describe both; and the ownership comment names the case it does not cover — a lock under a shared `ORX_DATA_DIR` has only its ACL on Windows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Keep the windows job out of the release gate release.yml calls ci.yml and requires it to pass, so the windows job added here would have held up a macOS or Linux release over a platform those releases ship nothing for. `plan` is passed only by release.yml, so skipping on it draws the line where it belongs: Windows still gates pull requests, which is what keeps it from rotting, and never gates a release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Upload a release orx.exe, not a debug one The artifact is what a tester is handed, and a debug build is slow enough to colour their impression of the dashboard rather than the code's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Turn SSH multiplexing off explicitly on Windows Win32-OpenSSH implements no connection multiplexing: it accepts ControlMaster and ControlPath and then never creates a master. Omitting them is not enough, because the user's own ssh_config can still set a ControlPath, and one it honours fails the connection outright with "getsockname failed: Not a socket". Passing ControlMaster=no and ControlPath=none is what overrides that. The socket machinery goes with it — the control directory, its path hash and its preparation are unix's, and `master_is_running` can only answer false where no master is ever created. Nothing changes on unix, where the shared master still covers later status, log and job commands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review Two tests asserted the unix option set unconditionally and would have failed on Windows — the very platform this change is for, and one CI never builds. Both derive the expectation from the platform now. `PathBuf`'s only uses became unix-gated, so its import would have failed the Windows clippy job under -D warnings. git shells out to ssh with its own command line, which never carried the override, so a user's ssh_config could still break git-over-SSH on Windows for exactly the reason this change exists. Routed through one helper. The rest: a doc comment my new test had come between and its rightful test; four comments still promising multiplexing unconditionally, the `interactive_args` one worst because it states the invariant that is false on Windows; the new test pinned to the exact vector the way its neighbour already is; and BatchMode coverage split out, since it holds on every platform and was about to be gated away with the ControlPath half. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round two No blockers in either round-two review. Taking the nits. Deriving the option count from `multiplexing_opts` had quietly removed the only assertion pinning the unix vector — ControlPersist could have been deleted and nothing in the tree would have failed. Pinned alongside the Windows one. The rest: a test whose name promised reuse on a platform that reuses nothing; `git_ssh_command` says which command it builds; two more doc comments of the class round one fixed, in the two other files that carry them; and the Windows sentence dropped from `ssh_opts`, where it was the third statement of the same fact within 150 lines. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Point git's config paths at an empty file, not the null device Onboarding died on Windows at the demo's first `git init`: fatal: unable to access 'NUL': Invalid argument `NUL` is right for `diff --no-index`, which recognizes it before touching the path, and wrong everywhere a path is actually read. Git skips a config file that reports ENOENT and fatals on any other error, and Windows cannot `access()` its null device by name at all. A real empty file behaves the same on every platform, and this file already had that idiom in `clone_public_repository`. Shared now, and pointing `hooksPath` at it still disables hooks, since git finds no hook inside a file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Give the spawned bash its own toolchain on PATH A local run died at `run.sh: line 6: mkdir: command not found`. bash was running; it just had no coreutils. Git for Windows keeps those in `usr\bin` and puts only `cmd` on the Windows PATH, so a bash started from a Windows process inherits a PATH with no Unix tools at all. Fronted for the two bash spawns only — a local run's launcher and the composer's `!` command. Doing it for every child would shadow Windows' own `find` and `sort` with the MSYS ones, which is a worse bug than the one being fixed. prepare_env's PATH is now a function the bash spawn can extend, so the running orx still comes first and the toolchain sits ahead of both. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Fold the toolchain into the PATH run.sh exports The previous commit set the toolchain PATH on the spawn, which run.sh then overwrote on its second line: localrun exports the shell's PATH into the script so a user's own command finds python and uv, and that export wins over anything the process was started with. Caught by the agent inside the dashboard, which read the generated run.sh rather than the launcher and saw the hardcoded Windows PATH for what it was. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Let the demo probe run under Git Bash Two things differ there, and the probe hit both. uv ships no shell installer for Windows, so the setup uses its PowerShell one; and uv lays the venv out as `Scripts/` rather than `bin/`, so both activations are tried — either platform can have either layout depending on how the venv was made. These are Rust constants rather than files in the demo repository, so the commit ids the demo validates itself against do not move. `runs/runcpu.sh` carries the same POSIX assumption and is committed, so making the project's own run command portable is a separate change that regenerates those ids. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Stop writing a Windows PATH into a bash script The run script exported the process PATH so a user's command could find python and uv. On Windows that value is semicolon-separated, and bash splits PATH on `:` — so it collapsed at the first drive colon and nothing resolved, `mkdir` included. Adding the Git toolchain to it, as the last two commits did, only added more entries to the same unusable string. Git Bash converts the PATH it inherits into POSIX form for itself, so the fix is to leave it alone: the launcher sets the process PATH, and the script no longer overwrites it. The `cd` on the next line had the same shape — bash reads a quoted `C:\…` literally — so the run directory is forward-slashed now. Found by the agent running inside the dashboard, which read the generated run.sh, spotted the separator mismatch, and verified a candidate PATH against both splitters before proposing anything. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Hand the shell paths it can read, not Windows ones `tar: Cannot connect to C: resolve failed` — GNU tar reads a colon before the first slash as a `host:path` remote spec, so the snapshot archive's Windows path made it try to resolve `C:` as a hostname. Forward slashes would not have helped; the colon is what triggers it. One conversion now covers both places a local path reaches the shell: the archive tar unpacks, and the `cd` the launcher writes. `/c/Users/…` has no colon at all. The HF backend passes a Linux container path and is deliberately left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Give runs a UTF-8 stdout A run died mid-training on `UnicodeEncodeError`: CPython encodes stdout in the console's codepage, cp1252 on a default Windows install, and the script printed a banner outside Latin-1. Nothing to do with the experiment — it had already trained a tokenizer by then. `PYTHONIOENCODING=utf-8` joins `PYTHONUNBUFFERED` as a default the author can override, through the same helper every backend already calls, and open-coded once more for kubernetes, whose env is a JSON array. Set on every platform rather than only Windows: a Linux container with `LANG=C` has the same ASCII default and would fail the same way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Let git write paths past Windows' 260-character cap Creating a session worktree for a deep repository failed partway through with "Filename too long". Windows refuses paths over 260 characters unless a program opts into the wide API, and a session worktree spends about a hundred of them on `worktrees/<project>/chat_<session>` before the repository's own paths begin. `core.longpaths=true` on the invocations that write a working tree: the shared helper every worktree and checkout goes through, the authenticated fetch, and the anonymous clone. Read-only plumbing does not need it. This was graded Minor in the original survey. It is a blocker for any repository with a deep tree, which is most of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Link the agent's config without asking Windows for a privilege Windows grants symlinks only to an elevated process or one in Developer Mode, so preparing the isolated agent home failed onboarding outright with os error 1314. Fall back to the links that need no privilege: a junction for a directory, which reads back exactly like a symlink, and a hard link for a file, which does not — so the reconcile now recognizes one instead of filing a conflict against it on every launch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Stop asking Windows' ssh to multiplex Windows' OpenSSH cannot create the AF_UNIX socket ControlMaster needs, and rather than decline the option it kills the connection outright with "getsockname failed: Not a socket" — so every ssh call orx made from Windows failed, whatever the destination. Drop the Control* options there and pay a handshake per call. Same option vector, same platform: `UserKnownHostsFile=/dev/null` is a name Windows' ssh takes literally, creating a `\dev\null` on the current drive. It now gets a scratch file of orx's own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Count the Windows ssh opts the Windows way Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Revert the duplicate multiplexing fix PR #302 already turns Windows' multiplexing off, and does it by setting ControlMaster=no explicitly rather than by omission — which is what overrides a ControlPath in the user's own ssh_config — and covers git's ssh besides. Take that one instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Give Windows a real file for the host keys it must forget `UserKnownHostsFile=/dev/null` is a name Windows' ssh takes literally, creating a `\dev\null` on whichever drive is current. Point it at a scratch file of orx's own instead; StrictHostKeyChecking=no is what makes a recycled provider key acceptable, so the behaviour is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Ship a Windows binary and a way to install it The demo's own run command reached for a POSIX uv installer and `.venv/bin/activate`, neither of which exists on Windows, so the nanochat demo could not run there; both now branch at runtime. That changes the experiment tree, hence the new EXPERIMENT_SHA. Releases built no Windows artifact at all, which is what the CI job's non-blocking rationale rested on. Add the target and a PowerShell installer so a beta tester has something to install. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Tell Windows testers what they need before they need it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Let Windows hold up a release now that a release ships it The job skipped release runs because releases carried no Windows artifact. They do now, so a regression on main would ship broken rather than fail loudly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Say what signing will and will not fix Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Say Git for Windows is missing at startup, not at the first run Without it there is no usable bash, so experiments and the demo die on their first command with a spawn error naming a path the user has never heard of. The agents check next to it already warns this way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Make a second click reach the dashboard, not die on its port Double-clicking orx.exe runs `orx up`. Doing it while orx is already running failed the bind, printed an error into a console Explorer then closed, and looked to the user like nothing happened at all. Open the running dashboard instead, and hold the console open for whatever else a startup failure has to say. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Make a failed start say so where a console cannot The console Explorer opens for a double-clicked orx.exe dies with the process, so both ways this program exits with something to say — a returned error and a panic — reached a window that was already gone. Put the message in a dialog instead, and only when no terminal is attached to read the printed one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Start the dashboard when orx.exe is double-clicked A bare `orx` prints usage and exits, which is right at a prompt and useless from Explorer: the console it printed into closes with the process, so the gesture looked like nothing happening. Owning the console is what tells the two apart, and it now starts `up` — the same trade the macOS .app makes for the same gesture. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Keep demo installs seeded before the Windows change working Moving EXPERIMENT_SHA left every existing mac and linux install pointing at a commit its repository does not contain. Each agent turn resolves the session worktree from that commit, so all three demo chats would have failed on their next message after upgrading. An install now starts its sessions from whichever known experiment its demo branch descends from. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round four - Release verify job reads the Windows .zip and orx.exe; without it no release would have published for any platform. - "Already running" reuse only for a double-click, and only of a dashboard speaking this build's protocol. On mac and linux a second `orx up` fails on the port again, as it did before this branch. - An old demo install whose cache was wiped but origin kept restores its own experiment rather than building a sibling it cannot push. - Same-file probe errors fall through to the old reconcile; the demo probe only puts ~/.local/bin on PATH after installing uv; the panic hook is Windows-only. - Docs name the assets cargo-dist actually publishes. - Comments cut to the one-or-two-line house rule; three doc comments moved back onto the functions they describe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round five - A double-click keeps the flags it was given (`--no-telemetry` from a shortcut no longer turns telemetry back on). - A kept demo origin is validated before a clone is restored from it, so a foreign or moved origin is named as the problem instead of the cache. - The ssh opt-vector test reads the Windows known-hosts path once; it follows XDG_CONFIG_HOME, which telemetry tests mutate in parallel. - Every comment this branch adds is now one or two lines. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Address review round six - Remote storage paths accept an interior `.` again. `Path::components` skipped it on main, so `ORX_DATA_DIR=./orx` on a remote box — probed as `/home/u/./orx/orx.db` — broke `orx up --remote` on this branch. - A foreign kept demo origin is rejected before anything is restored from it, now with a test; `install_repository` keeps main's shape, since the restore helper creates its own parent. - Comments trimmed last round get back the why they lost, and the PYTHONIOENCODING one no longer claims the console codepage: redirected output uses the ANSI one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
00fe5ab7b7 |
Add local endpoints to the OpenCode model picker (OR-245) (#300)
* Support local OpenCode models in onboarding * Add local endpoint setup to OpenCode settings and model picker * Handle recovered OpenCode context compaction without false failures * Bump version to 0.1.122 for local model release |