Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

feat(web-server): port CLIENT_DIST_DIR pluggability from OSS (Phase 1.7) - #68

Closed
jgluck96 wants to merge 5 commits into
mainfrom
josh/phase-1.7-client-dist-dir-pluggability
Closed

jgluck96 wants to merge 5 commits into
mainfrom
josh/phase-1.7-client-dist-dir-pluggability

Conversation

@jgluck96

@jgluck96 jgluck96 commented Jun 1, 2026

Copy link
Copy Markdown

Summary

Port the CLIENT_DIST_DIR env-var override from OSS sutando (commit c350a10 on josh/migrate-to-react) so stando can serve any UI bundle without source edits. After this PR:

# Default: serves stando's bundled client/dist (unchanged behavior)
bash src/startup.sh

# Override: serves any other UI bundle
CLIENT_DIST_DIR=/abs/path/to/dist bash src/startup.sh

Why

Phase 1.7 of the OSS sync roadmap. Unblocks the workflow where the production stando deployment overrides the default UI with a private branded dist, while dev / demo builds still serve stando's vendored client/ UI for parity checks.

Pairs with the wire contract at AG2Platform/sutando-client/WIRE.md: any bundle that honors the contract works.

What's NOT in this PR (deliberate)

  • No submodule conversion of client/. Stando's UI stays vendored. Goal here is independence from OSS UI updates, not auto-sync — the override mechanism is what we want, not the submodule.
  • No startup.sh submodule auto-init block from sutando's PR. That block is submodule-specific and stando isn't using a submodule.
  • No UI changes. stando's React UI continues to live at client/ exactly as before.

What changed

Two files:

  • src/web-server.ts (+37/-6) — adds resolveClientDistDir(), replaces the static CLIENT_DIST_DIR const with a let binding refreshed inside startWebServer(). JSDoc updated.
  • tests/client-dist-dir-override.test.ts (+130) — verbatim port of sutando's regression test. 3 cases, all pass.

Mechanics ported verbatim from sutando so the contract stays in lockstep between repos.

Test plan

  • pnpm exec tsx --test tests/client-dist-dir-override.test.ts → 3/3 pass
  • pnpm exec tsc --noEmit -p tsconfig.json → no new errors (pre-existing @ai-sdk/openai warning on voice-agent.ts:48 unchanged)
  • Reviewer: smoke test by exporting CLIENT_DIST_DIR=/some/tmp/dist, dropping an index.html sentinel there, running bash src/startup.sh, confirming :8080 serves the sentinel.

Related

Made with Cursor

jgluck96 and others added 3 commits June 1, 2026 14:23
Adds the same env-var-driven UI override that sutando's web-server has
(see josh/migrate-to-react on sonichi/sutando, commit c350a10). With
this in place, stando can serve any UI bundle by exporting:

  CLIENT_DIST_DIR=/abs/path/to/dist bash src/startup.sh

before launching the voice agent. Without the env var, behavior is
unchanged — stando serves its bundled client/dist/ as before.

Phase 1.7 of the OSS sync roadmap. Unblocks the workflow where
production stando deployments override the default UI with a private
branded dist while developer / demo builds still serve the stando
default UI from client/.

Mechanics ported verbatim from sutando:
- resolveClientDistDir() function with tilde expansion
- module-level `let CLIENT_DIST_DIR = resolveClientDistDir()` so
  existing references keep working
- per-call re-resolve inside startWebServer() so tests + dynamic env
  changes pick up the latest value
- JSDoc updated to document the override

Submodule auto-init block from sutando's startup.sh deliberately NOT
ported — stando's client/ is still vendored (not a submodule), and
the goal is independence from OSS UI updates, not auto-sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
Ports sutando/tests/client-dist-dir-override.test.ts verbatim so the
private repo's pluggability contract stays in lockstep with OSS. Same
3 cases: custom dir override serves, default fallback serves bundled
UI, path traversal blocked.

All 3 pass against the new resolveClientDistDir() in src/web-server.ts.

Co-authored-by: Cursor <cursoragent@cursor.com>
The React frontend (client/) is moved out of this repo into the private
AG2Platform/stando-ui repo (full history preserved via git subtree split)
and plugs back in via CLIENT_DIST_DIR — the same pluggability seam ported
in #68. Stando's backend and the UI now ship and version independently;
the private UI no longer has to track the OSS sutando UI.

Removals:
- client/ (97 files) — now lives at AG2Platform/stando-ui
- package.json: build:client / dev:client scripts
- pnpm-workspace.yaml: client workspace member (lockfile re-pruned)

Rewiring so everything still works:
- web-server.ts: default dist resolves to ../client/dist (present only in
  the packaged app, staged by build-app.sh); a dev checkout sets
  CLIENT_DIST_DIR or gets a 503 with a build hint. Docs/JSDoc updated.
- startup.sh: auto-detects a built sibling ../stando-ui/dist when
  CLIENT_DIST_DIR is unset; otherwise warns. Override always wins.
- app/build-app.sh: sources the UI from CLIENT_DIST_DIR or a sibling
  stando-ui checkout (builds it), stages it at the bundle's client/dist
  path so the shipped app stays self-contained with no runtime env var.
- .github/workflows/release.yml: checks out + builds AG2Platform/stando-ui
  and passes its dist via CLIENT_DIST_DIR. REQUIRES a new repo secret
  STANDO_UI_TOKEN (PAT with read access to the private UI repo) — the
  default GITHUB_TOKEN can't reach another repo.
- docs/WIRE.md: the wire contract any UI must honor (ported from OSS).
- .env.example / CONTRIBUTING.md / .gitignore: documented + cleaned up.

Verified: tsc clean (pre-existing @ai-sdk/openai error unrelated), the
CLIENT_DIST_DIR test passes 3/3, frozen lockfile installs, and the server
serves the real stando-ui dist end-to-end (200 + hashed assets).

Co-authored-by: Cursor <cursoragent@cursor.com>
jgluck96 and others added 2 commits June 1, 2026 15:24
refactor: extract conversation UI to private stando-ui repo
@jgluck96

jgluck96 commented Jun 3, 2026

Copy link
Copy Markdown
Author

Superseded by #98 — clean cherry-pick onto current main (was showing 109-file diff due to PR #69 ancestor commits). #98 shows the actual 2-file change.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant