mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-06 14:33:11 +08:00
Add frontend-only and backend-only agent-canvas modes (#1040)
* Add partial stack modes to agent-canvas Co-authored-by: openhands <openhands@all-hands.dev> * fix: address PR review feedback (#1040) - Replace padEnd(75) with ANSI-aware ansiPadEnd helper in printBanner; String.padEnd counts invisible escape bytes as visible chars, causing the box border to misalign in colour terminals - Deduplicate storage directory creation in ensureDirectories; was being pushed once per launchAgentServer block and once per launchAutomation block (always both true together) — move to a shared unconditional slot - Add explanatory comment to the checkNpm two-clause OR condition Co-authored-by: openhands <openhands@all-hands.dev> * test: add e2e tests for --frontend-only, --backend-only, and port conflicts Add mock-llm-partial-stack.spec.ts with three test groups: 1. --frontend-only: verifies static frontend is served (200 on /), backend routes return 503 (/server_info, /api/settings, /api/automation/v1), and the browser shows the manage-backends modal. 2. --backend-only: verifies /server_info returns 200, /api/settings is reachable, automation endpoint works, and root/asset requests return 503 (no frontend configured). 3. Port conflict: verifies the process exits non-zero with a clear error when the ingress port is occupied, then starts successfully on a free port. Unlike the other mock-llm specs, these tests spawn their own bin/agent-canvas.mjs child processes with isolated state dirs and high port numbers (18310+ range) to avoid collisions. Co-authored-by: openhands <openhands@all-hands.dev> * fix: adjust frontend-only test to expect SPA fallback instead of 503 In frontend-only mode the ingress has no backend routes — all requests (including /server_info, /api/*) fall through to the static server's default backend, which returns index.html via SPA fallback (200 with HTML). The test now verifies that /server_info returns HTML (not JSON) and that the browser detects the missing backend and shows the manage-backends modal. Co-authored-by: openhands <openhands@all-hands.dev> * feat: add --reject-prefix to static server for clean 503 on missing backends In --frontend-only mode the static server was SPA-fallbacking API paths (/server_info, /api/*, /sockets, etc.) to index.html, returning 200 with HTML content instead of a clear failure. This made the frontend's /server_info probe ambiguous. Add a --reject-prefix flag to static-server.mjs: any matching request returns 503 ('Service Unavailable') before the SPA fallback runs. Wire it through dev-with-automation.mjs: getRejectPrefixes(config) computes which API prefixes have no backend configured (e.g. all of them in frontend-only mode) and buildRejectPrefixArgs() passes them as --reject-prefix flags to the static server. Restore the e2e test to assert 503 for /server_info, /api/settings, and /api/automation/v1 in frontend-only mode. Co-authored-by: openhands <openhands@all-hands.dev> * fix: treat non-401 HTTP errors from /server_info as unavailable loadAgentServerInfo was re-throwing all SDK HttpErrors (including 503) as-is, but root.tsx only checks for AgentServerUnavailableError. A 503 from the static server in --frontend-only mode (or any non-401 error) would fall through to the Outlet instead of showing the manage-backends modal. Narrow the re-throw to only preserve 401 (needed for the auth screen in public mode). All other HTTP errors are now wrapped as AgentServerUnavailableError so the app shows the correct recovery UI. Co-authored-by: openhands <openhands@all-hands.dev> * fix: poll automation readiness in backend-only test; retry on 5xx The automation backend starts independently from the agent-server and may not be ready when /server_info first returns 200. pollUrl now treats 5xx responses as 'not ready yet' and keeps retrying. The backend-only test also polls /api/automation/v1 before asserting on it. Co-authored-by: openhands <openhands@all-hands.dev> --------- Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
openhands
Rohit Malhotra
parent
a53bff52d4
commit
8bb2b8c518
+26
-3
@@ -2,7 +2,7 @@
|
||||
/**
|
||||
* CLI entry point for @openhands/agent-canvas
|
||||
*
|
||||
* Runs the full Agent Canvas stack locally:
|
||||
* Runs the full Agent Canvas stack locally by default:
|
||||
* - Agent-server via uvx
|
||||
* - Automation backend via uvx
|
||||
* - Pre-built static frontend
|
||||
@@ -50,6 +50,9 @@ Override versions via environment variables:
|
||||
process.exit(0);
|
||||
}
|
||||
const isPublic = args.includes("--public");
|
||||
const isFrontendOnly = args.includes("--frontend-only");
|
||||
const isBackendOnly = args.includes("--backend-only");
|
||||
|
||||
if (args.includes("-h") || args.includes("--help")) {
|
||||
console.log(`
|
||||
@openhands/agent-canvas - Run the Agent Canvas UI with agent-server
|
||||
@@ -71,6 +74,8 @@ AUTH MODES:
|
||||
OPTIONS:
|
||||
-p, --port <port> Ingress port (default: 8000)
|
||||
--public Enable public mode (see above)
|
||||
--frontend-only Start only the static frontend behind ingress
|
||||
--backend-only Start only agent-server + automation behind ingress
|
||||
-v, --version Show version number
|
||||
--info Show version and default stack configuration
|
||||
-h, --help Show this help message
|
||||
@@ -100,6 +105,12 @@ EXAMPLES:
|
||||
# Use a specific port
|
||||
npx @openhands/agent-canvas --port 3000
|
||||
|
||||
# Start only the static frontend behind ingress
|
||||
npx @openhands/agent-canvas --frontend-only
|
||||
|
||||
# Start only the agent-server and automation backend behind ingress
|
||||
npx @openhands/agent-canvas --backend-only
|
||||
|
||||
# Show default stack versions and ports
|
||||
npx @openhands/agent-canvas --info
|
||||
|
||||
@@ -109,8 +120,20 @@ EXAMPLES:
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Check build exists before doing anything else
|
||||
if (!existsSync(BUILD_DIR)) {
|
||||
if (isFrontendOnly && isBackendOnly) {
|
||||
console.error(
|
||||
"Error: --frontend-only and --backend-only cannot be used together",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (isFrontendOnly && isPublic) {
|
||||
console.error("Error: --public cannot be used with --frontend-only");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Check build exists before doing anything else unless no frontend will run.
|
||||
if (!isBackendOnly && !existsSync(BUILD_DIR)) {
|
||||
console.error(`
|
||||
Error: No build found at ${BUILD_DIR}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user