Repository navigation
[WIP] Android: backend compat (CI only, do not merge) - #205
Draft
nt-nerdtechnic wants to merge 11 commits into
Draft
nt-nerdtechnic wants to merge 11 commits into
nt-nerdtechnic wants to merge 11 commits into
Conversation
Android's CPython has no os.link, and skills_store read it at import time while computing _DIRECTORY_FDS, so the whole backend failed to start there. Detect hard-link support instead and, without it, publish each file with an O_EXCL copy that still refuses to replace an entry that raced us; rollback compares against the copy's own inode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
promote_stranded_auth hard-linked the newest in-pane auth.json into the real Codex home. Where os.link does not exist (Android) it raised AttributeError past the OSError handler. Fall back to an exclusive copy that keeps the source mode, so a concurrent writer still wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plugins/host.py imports packaging.version at load, but packaging only arrived through the dev group (pytest, pyinstaller). An install with runtime dependencies alone could not import the backend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chaquopy's CPython on Android has neither os.openpty nor os.forkpty, so every terminal spawn failed there. Unlock /dev/ptmx and open the slave by number (TIOCSPTLCK, TIOCGPTN) instead. Wherever os.openpty exists, which is every desktop build, spawn still calls pty.openpty unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Android has only /system/bin/sh, and Termux keeps its shells under its own prefix, so shell_command and the login-path probe pointed at files that are not there. Use /bin/sh and /bin/bash when they exist, as before, and fall back to PATH and then /system/bin/sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…proxy
Codex ships as a static musl binary, and musl resolves names from
/etc/resolv.conf alone, which Android does not have, so every request
failed. On Android only (osplat.paths.needs_loopback_dns_proxy), the backend
starts a CONNECT proxy bound to 127.0.0.1 and a Codex spawn gets
HTTPS_PROXY pointing at it, SSL_CERT_FILE from certifi and TMPDIR. The proxy
resolves through the system, never reads the tunnelled bytes, and records
the hosts asked for so the UI can disclose them (ANDROID_DISCLOSED_HOSTS).
VendorSpec.spawn_env_extra is the per-spawn counterpart of
spawn_env_defaults with the same precedence: a value from the request or
the inherited environment always wins. It returns {} on every desktop
platform, so their spawns are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any app on an Android device can connect to 127.0.0.1, so the CONNECT proxy was an open relay: another app could reach the network through it, around its own permissions. Mint a random token per process and answer 407 to a CONNECT without Proxy-Authorization: Basic navide:<token>. Codex receives the credential in HTTPS_PROXY's userinfo and sends it itself; other apps cannot read another process's environment on Android. Destinations stay unrestricted and are disclosed instead (hosts_seen). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps both sides of the two conflicts: the Android loopback-proxy spawn env in cli_vendors/codex.py next to main's extensions inventory, and the no-os.link auth promotion test next to main's hook-trust, skills-link and temp-file tests in test_codex_home.py. .gitleaksignore gains the commit-less fingerprint of main's quick-menu token alphabet: the merge's staged scan sees that file as new, and main's entry is pinned to the commit that added it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Android branch resolves sh when /bin/sh is missing, so on the Windows runner _posix_paths.shell_command found Git's sh.exe and the desktop assertion failed. Production Windows never calls the POSIX module; the test now states the host it describes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both tests delete os.link to stand in for Android, but on a Windows host the fallback then reaches os.fchmod, which Windows CPython lacks. The fallback only runs where os.link is missing, which is never Windows, and it asserts POSIX modes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CI-only draft for the Android branch, kept up to date with main after each release. Do not merge.
This push merges origin/main (d1d81ef, v0.2.21 + #204) into
feat/android-backend-compat:cli_vendors/codex.py: kept the Android loopback-proxy spawn env next to main's extensions inventory.tests/test_codex_home.py: kept the no-os.linkauth promotion test next to main's new hook-trust, skills-link and temp-file tests..gitleaksignore: added the commit-less fingerprint for main's quick-menu token alphabet (a known false positive), which the merge's staged scan sees as new.🤖 Generated with Claude Code