#9803: fix(#9801): auto-build control ui assets on demand
app: web-ui
gateway
stale
Cluster:
UI and Model Management Enhancements
## Summary
Adds automatic build logic for control UI assets when they are missing at runtime.
### Changes
- Added `tryAutoBuildControlUi()` function that:
- Checks if auto-build is enabled (via OPENCLAW_CONTROL_UI_AUTO_BUILD env var)
- Resolves the control UI repo root
- Executes scripts/ui.js build with 10-minute timeout
- Handles errors gracefully
- Integrated auto-build into request handler: attempts build if assets not found
- Updated error message to indicate auto-build was attempted
### Testing
- Manual verification: Confirm auto-build triggers when assets missing
- Error response: Verify updated message appears when build fails
- Environment variable: Test OPENCLAW_CONTROL_UI_AUTO_BUILD=0 disables auto-build
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR introduces a new plugin hook (`before_model_select`) and wires it into model selection, plus adds an on-demand Control UI asset build attempt when the UI bundle is missing at runtime.
Key codepaths touched:
- `src/auto-reply/reply/model-selection.ts` now calls the global hook runner during model selection, passing `{ provider, model, sessionKey, allowedModelKeys, prompt }`.
- `src/plugins/types.ts` and `src/plugins/hooks.ts` add the new hook type and runner method.
- `src/gateway/control-ui.ts` attempts to run `scripts/ui.js build` once per process when the Control UI assets directory can’t be found.
Tests were added for the new hook runner behavior and for the model-selection integration.
<h3>Confidence Score: 2/5</h3>
- This PR has a couple of correctness issues that can cause confusing runtime behavior and failures in critical paths.
- Control UI auto-build can silently fail because non-zero exit statuses aren’t handled, and the enable/disable env var is read only at module load time. On the plugin side, exceptions from the before_model_select hook can bubble up and break model selection if hooks are configured to throw, and hooks may receive an empty allowlist even when the catalog is available/needed for enforcement.
- src/gateway/control-ui.ts, src/auto-reply/reply/model-selection.ts
<!-- greptile_other_comments_section -->
<sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#8522: feat(control-ui): Add Model Requests panel for real-time API monito...
by GiantAxeWhy · 2026-02-04
74.8%
#8644: Fix Control UI asset resolution for global installs
by codvik · 2026-02-04
74.5%
#6440: feat(ui): add model picker dialog with provider filtering
by igorls · 2026-02-01
74.2%
#11115: [AI-assisted] Add /model-set chat command with autocompletion and s...
by dorgonman · 2026-02-07
74.1%
#8022: feat: implement before_model_select plugin hook
by dead-pool-aka-wilson · 2026-02-03
73.6%
#8546: Fix/config UI improvements
by RandomRaine · 2026-02-04
73.5%
#7794: fix(tui): refresh session info periodically to reflect config changes
by GuoxiangZu · 2026-02-03
72.7%
#9914: fix(hooks): resolve bundled hook dist paths and packaging checks
by zimmra · 2026-02-05
72.7%
#8083: fix(tui): update model status immediately after /model command
by rohanjangala · 2026-02-03
72.1%
#12168: feat: integrate Mission Control dashboard into Control UI
by riftagent-git · 2026-02-08
72.0%