feat(codex): Route B marketplace registration + cross-platform @-scoped path alias#54
Merged
Merged
Conversation
added 30 commits
May 23, 2026 23:51
Switch codex plugin registration from npm-local path to OpenWonderLabs/switchbot-openapi-cli git marketplace source (--sparse packages/codex-plugin --ref main). Avoids the @-scoped path misclassification entirely and makes the plugin discoverable without a prior npm install. - Add CODEX_GIT_MARKETPLACE_REPO/SPARSE/REF constants - Add runCodexPluginRegistrationGit() and registerCodexPluginGit() - Update stepRegisterPluginShared (codex.ts) and stepRegisterCodexPlugin (default-steps.ts) to use the git path - Update tests: remove npm-root-g mock from stepRegisterCodexPlugin; add runCodexPluginRegistrationGit and registerCodexPluginGit suites
…rash resolveMarketplaceSourceRoot was gating the junction/symlink workaround behind process.platform === 'win32', so Linux paths containing a scoped npm segment (e.g. /@switchbot/codex-plugin) were passed raw to Codex CLI, which misclassifies any source path containing '@' as a ref-bearing git source and exits 1 with "--ref is only supported for git marketplace sources". - Detect '/@scope/' on Linux/macOS with /\/@[^/]+\//.test(packageRoot) - Create a 'dir' symlink (not a junction) on non-Windows platforms - Use case-sensitive realpath comparison on non-Windows - Update error message to "not a symlink/junction" to cover both cases - Add 5 new tests that mock process.platform='linux' to cover all alias branches (create, reuse, repair, plain-path, real-dir-throws) Also fix auth login crash in WSL: open v10 does not attach an error handler to the spawned ChildProcess when wait=false (the default), so ENOENT from a missing PowerShell fires via process.nextTick before await open() resolves — no try/catch can intercept it. Pre-check the WSL PowerShell path with existsSync and fall back to printing the URL instead of crashing.
…detection, env-override REF
…egisterCodexPluginAuto)
…ext, rm dead imports - browser-login: call close() in catch so the OAuth callback server port is always released when wait() rejects (timeout or cancel) - codex-checks: registerCodexPluginAuto now surfaces both git and npm error messages when both routes fail, instead of silently dropping the git failure - codex-checks: read CODEX_GIT_MARKETPLACE_REF at call time inside runCodexPluginRegistrationGit so env overrides applied after module load are respected - codex.ts / default-steps.ts: remove dead imports of registerCodexPlugin and registerCodexPluginGit (neither is called directly) - tests: add close mock to browser-login fixture and assert it fires on rejection; strengthen dual-failure test to verify combined error message
…of as a fixed step The install-codex-plugin step ran unconditionally even when Route B (git marketplace) would succeed without any local npm package. Fold the npm install into register-plugin: try Route B first; only install the package and fall back to Route A when Route B fails. This keeps air- gapped environments working while avoiding a needless global npm install in the common case. SETUP_STEPS shrinks from 6 to 5. Dry-run output and --skip no longer expose install-codex-plugin as a standalone step.
Add direct git marketplace registration command so users can register the plugin without going through codex setup. Clarify that the plugin lives in packages/codex-plugin/ of this repo and no separate npm package install is required.
…mulate entries - rules: broaden parent description to reflect full command set (author/lint/run/debug/simulate) - rules: add trace-explain and simulate to the addHelpText subcommand list - auth: remove stale (preview) label, shipped in v3.7.1
- Translate Chinese JSDoc comment in codex-checks.ts to English - Document intentional ignored exit code on `plugin remove` pre-clean - Move on-demand @switchbot/codex-plugin install into registerCodexPluginAuto so setup, repair, and install --agent codex all behave consistently - Simplify setupStepRegisterPlugin to delegate entirely to registerCodexPluginAuto; remove now-unused registerCodexPlugin/registerCodexPluginGit imports and CODEX_PLUGIN_PACKAGE constant from codex.ts - Add WSL context hint to browser-login fallback message when browser cannot open - Document CODEX_GIT_MARKETPLACE_REF env var in README environment variables table - Update tests: expand registerCodexPluginAuto coverage with on-demand install scenarios; fix stepRegisterCodexPlugin throws-test mock count; simplify codex setup on-demand test to match new single-call boundary
…ices table - preflight: downgrade codex-plugin-npm check from fail → warn so switchbot install --agent codex can reach stepRegisterCodexPlugin() and attempt Route B (git marketplace) when the npm package is absent - add preflight test covering agent: 'codex' without global npm package - registerCodexPluginAuto: append "Run: switchbot codex repair" hint to all-routes-failed error messages - install.js resolveMarketplaceSourceRoot: add comment noting intentional sync with src/install/codex-checks.ts - README: restore Supported devices compatibility table (removed in trim) - codex setup --help: surface CODEX_GIT_MARKETPLACE_REF env var
…s, skip compat, pluginId - Increase marketplace-add timeout from 10s to 60s to survive slow git clones - Broaden Linux @-scope regex in resolveMarketplaceSourceRoot to match paths without a node_modules segment (custom npm prefix layouts) - Remove legacy plugin IDs (switchbot@switchbot-skill) in Route B pre-clean step - validateSkip now silently ignores unknown/removed step names so --skip install-codex-plugin no longer exits 2 in existing automation scripts - registerCodexPluginAuto failure returns use CODEX_PLUGIN_DEFAULT_ID as fallback instead of spreading an empty pluginId from the npm result
…pluginId in errors - validateSkip now rejects unknown step names again (restores typo detection); only explicitly deprecated names like install-codex-plugin are silently no-ops - Add CODEX_MARKETPLACE_ADD_TIMEOUT env var to override the 60 s marketplace-add timeout, giving users on slow networks / Windows with AV scanning an escape hatch - Error return paths in registerCodexPluginAuto always report CODEX_PLUGIN_DEFAULT_ID instead of propagating a potentially stale/wrong ID from a corrupted manifest
- setup --skip option description now lists deprecated accepted names alongside the two skippable steps, so the help text matches actual behavior - CODEX_MARKETPLACE_ADD_TIMEOUT parsing uses Number.isFinite + >0 guard instead of || 60000, preventing falsy-zero or negative values from silently bypassing the env var or removing timeout protection
… actionable message
…egacy IDs in Route A Smoke test still asserted the removed install-codex-plugin step, causing CI to fail. Also extend runCodexPluginRegistration to clean CODEX_PLUGIN_LEGACY_IDS before re-adding, matching Route B behaviour so switchbot@switchbot-skill is removed even when the git-marketplace path is unavailable.
…code, prefix verify, timeout warning - install.js: remove switchbot@switchbot-skill legacy ID before re-adding, mirroring the CODEX_PLUGIN_LEGACY_IDS loop already in codex-checks.ts - installCodexPluginGlobally: parse npm list JSON regardless of exit code so peer-dep warnings (npm exits 1) no longer trigger an unnecessary reinstall - installCodexPluginGlobally: verify package presence after npm install -g to catch npm prefix mismatches early with a clear diagnostic message - runCodexPluginRegistrationGit: warn when CODEX_MARKETPLACE_ADD_TIMEOUT is set to empty string (was silently ignored) - tests: wrap process.stderr.write monkey-patches in try/finally to prevent stderr corruption when assertions fail
…mes out
When spawnSync status is null (killed/timed out), stdout is also null.
The previous code fell through the catch block and returned {ok:true},
masking a failed or unverifiable install. Now guard on status===null before
the try/catch and return a descriptive error.
…egacy IDs, thread install flag
- resolveMarketplaceSourceRoot: wrap realpathSync in try/catch so a dangling
symlink (e.g. after nvm switch or npm uninstall) is silently recreated
instead of crashing; mirrors the same fix in packages/codex-plugin/bin/install.js
- runCodexPluginRegistrationGit: use || instead of ?? for CODEX_GIT_MARKETPLACE_REF
env lookup so an empty string correctly falls back to the default "main" ref
- installCodexPluginGlobally: return { installed: boolean } flag so the caller
can distinguish "we just installed the package" from "it was already present";
registerCodexPluginAuto now emits "@switchbot/codex-plugin already present"
instead of "installed @switchbot/codex-plugin" when no install was needed
- CODEX_PLUGIN_LEGACY_IDS: exported so repairStepRemovePlugin in codex.ts can
import and loop over [currentId, ...legacyIds] in a single pre-clean pass,
matching the behavior already present in runCodexPluginRegistration and
runCodexPluginRegistrationGit; non-zero exit codes are now logged as warnings
rather than aborting the repair step
- error message in resolveMarketplaceSourceRoot is now platform-split
("not a junction" on Windows, "not a symlink" on Linux/macOS)
The switchbot-codex-install binary is deprecated in favour of 'switchbot codex setup'. Mark the local copy as frozen so it no longer needs to track changes in src/install/codex-checks.ts, eliminating the manual keep-in-sync contract that caused repeated review findings.
- checkCodexPluginNpm: verify packageRoot is null when npm root -g fails - runCodexPluginRegistrationGit: verify custom CODEX_GIT_MARKETPLACE_REF is forwarded as --ref (complements the empty-string guard added in Fix 2) - registerCodexPluginAuto: verify npm install is called when initial npm list stdout is invalid JSON (json parse falls through to install path); verify Route A retry proceeds when post-install verify output is unparseable (verification-inconclusive path) - repairStepRemovePlugin: verify fallback to default ID when npm root -g fails during resolveCodexPackageRoot - setupStepAuth: verify auth step returns failed when auth login spawn exits non-zero
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.
Summary
@-scoped alias: extend the Windows junction workaround to Linux/macOS — symlink at an@-free path created on all platformsTest plan
codex setup/codex repairregister plugin via git marketplace URLresolveMarketplaceSourceRootcreatesdirsymlink on Linux/macOS for@-scoped pathsauth loginon WSL without PowerShell prints URL instead of crashingnpm testpasses