Skip to content

feat(codex): Route B marketplace registration + cross-platform @-scoped path alias#54

Merged
chenliuyun merged 31 commits into
mainfrom
feat/codex-marketplace-improvements
May 24, 2026
Merged

feat(codex): Route B marketplace registration + cross-platform @-scoped path alias#54
chenliuyun merged 31 commits into
mainfrom
feat/codex-marketplace-improvements

Conversation

@chenliuyun
Copy link
Copy Markdown
Collaborator

Summary

  • Route B: register the Codex plugin via a git marketplace URL instead of a local path, making installation portable
  • Cross-platform @-scoped alias: extend the Windows junction workaround to Linux/macOS — symlink at an @-free path created on all platforms
  • WSL auth crash fix: pre-check PowerShell path in WSL, fall back to printing the URL instead of crashing

Test plan

  • codex setup / codex repair register plugin via git marketplace URL
  • resolveMarketplaceSourceRoot creates dir symlink on Linux/macOS for @-scoped paths
  • auth login on WSL without PowerShell prints URL instead of crashing
  • npm test passes

chenliuyun 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.
…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
…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
@chenliuyun chenliuyun merged commit caedffc into main May 24, 2026
@chenliuyun chenliuyun deleted the feat/codex-marketplace-improvements branch May 25, 2026 04:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant