- build.sh scripts prioritize ~/.gradle/gradle-8.5/bin/gradle - New build_all.sh orchestrates generic-client and sageclient builds - sageclient build includes JDK 17/21 auto-detection - Avoids network timeouts from services.gradle.org
Sage desktop client sample
This directory is an independent Compose Desktop sample app for Sage on top of the
root bricks-mp shared module. It is intentionally not included from the
root settings.gradle.kts, so normal library builds are unchanged.
Build
From any directory:
/path/to/bricks-mp/test/sageclient/build.sh
The script:
- resolves its own directory,
- uses JDK 17 or JDK 21; on macOS it auto-selects an installed 21/17 via
/usr/libexec/java_homewhen the active Java is unsupported, - uses the repository Gradle wrapper when present, otherwise system
gradle, - runs
gradle buildfor this standalone sample.
Kotlin 2.1.0 / this Gradle setup does not work with newer Java versions such as 26.0.1. If your default java -version is 26, install JDK 21 or 17 and either let build.sh auto-detect it or export JAVA_HOME explicitly:
brew install --cask temurin@21
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
./test/sageclient/build.sh
Extra Gradle arguments can be appended, for example:
./test/sageclient/build.sh --info
Run
Run without arguments to open the sample shell:
cd /path/to/bricks-mp/test/sageclient
../../gradlew run \
-Dsage.baseUrl=http://localhost:8080 \
-Dsage.centerUi=/center.ui
Run with a startup URL to enter that UI directly without showing the sample base URL / login input shell:
cd /path/to/bricks-mp/test/sageclient
../../gradlew run --args="https://ai.atvoe.com/center.ui"
The packaged macOS app also accepts the URL as its first argument:
open build/compose/binaries/main/app/sageclient.app --args https://ai.atvoe.com/center.ui
If the argument is an absolute http:// or https:// URL, sageclient uses the URL origin as baseUrl and dispatches that same absolute URL through the Bricks urlwidget loading path. If the argument is a relative path such as /center.ui, it uses sage.baseUrl and loads that path. The actual HTTP request is still issued through BricksHttp, so startup URLs ending in .ui / .dspy are requested with _webbricks_=1, _width, _height, _is_mobile and _lang; they must not be fetched as raw HTML/template pages.
Optional properties:
sage.baseUrldefaults tohttp://localhost:8080sage.centerUidefaults to/center.uisage.loginActiondefaults to/rbac/user/loginsage.loginUidefaults to/rbac/user/login.uisage.username/sage.passwordprefill the login formsage.langoverrides the default JVM locale tag
What the sample demonstrates
- Uses the generic
BricksHttpclient from the shared module for Sage login andcenter.uiloading. Sage-specific bootstrapping lives here, not in the shared library package. - Loads
center.uiviaActionDispatcher.dispatch(BricksBind(actiontype = "urlwidget", ...)), so HTTP handling stays in the shared ActionDispatcher / BricksHttp flow. BricksHttpautomatically appends the correct WebBricks query parameters for.ui/.dspybackend requests:_webbricks_,_width,_height,_is_mobile,_lang.BricksHttpsurfaces HTTP 403, 401 and 3xx (including 301) asBricksHttpException.ActionDispatcherhandles them generically:- 403 loads the configured login UI (
sage.loginUi) in a dialog, - 401 shows the server response as an unauthorized message,
- 3xx follows the
Locationheader as a UI navigation target.
- 403 loads the configured login UI (
The sample is wired as a Gradle composite build through includeBuild("../..")
and depends on the root project module using implementation("com.bricks.mp:shared")
with dependency substitution to :shared.