mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-07 16:19:05 +08:00
* fix: unify session and automation API keys into a single credential Both the agent-server and automation backend now share the same API key value. The agent-server validates it via `X-Session-API-Key` and the automation backend validates it via `Authorization: Bearer …` — different header formats, same credential. Changes: - Frontend: automation axios client reads `VITE_SESSION_API_KEY` instead of the now-removed `VITE_AUTOMATION_API_KEY` - Dev launcher: removed separate `AUTOMATION_LOCAL_API_KEY` generation and persistence (`automation-api-key.txt`); `localApiKey` is set to `sessionApiKey` so both backends receive the same value - Static build: stopped baking `VITE_AUTOMATION_API_KEY` (the frontend reads from `VITE_SESSION_API_KEY`) - Docker entrypoint: `OPENHANDS_AUTOMATION_API_KEY`, `AUTOMATION_LOCAL_API_KEY`, and `AUTOMATION_AGENT_SERVER_API_KEY` all default to the session key when not explicitly overridden - Tests updated to verify unified key behavior Fixes the 401 on `/api/automation/v1` when the automation backend is running but no separate `VITE_AUTOMATION_API_KEY` was configured. Co-authored-by: openhands <openhands@all-hands.dev> * fix: use X-Session-API-Key header for automation backend auth (consistent with agent-server) Switch automation backend requests from `Authorization: Bearer …` to `X-Session-API-Key` header, matching the agent-server's auth pattern. Both backends now authenticate using the same header and the same key value (`VITE_SESSION_API_KEY`). Co-authored-by: openhands <openhands@all-hands.dev> * fix: address review — remove localApiKey alias, dead constant, add entrypoint guard - Remove `localApiKey` from config; all call sites now use `config.sessionApiKey` directly, making the unified-key intent obvious. - Delete `DEFAULT_AUTOMATION_API_KEY_PATH` constant and its export (no downstream consumers in beta). - Add fail-fast guard in docker/entrypoint.sh when no session key is available, instead of silently exporting empty strings. Co-authored-by: openhands <openhands@all-hands.dev> * fix: update stale comment on AUTOMATION_LOCAL_API_KEY to reflect unified session key Co-authored-by: openhands <openhands@all-hands.dev> --------- Co-authored-by: openhands <openhands@all-hands.dev>
82 lines
2.6 KiB
JavaScript
82 lines
2.6 KiB
JavaScript
import { spawnSync } from "node:child_process";
|
|
import { existsSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
import {
|
|
buildAutomationRuntimeServicesInfo,
|
|
c,
|
|
logError,
|
|
logService,
|
|
logStep,
|
|
logSuccess,
|
|
} from "./dev-with-automation.mjs";
|
|
import { buildNpmScriptCommand } from "./dev-safe.mjs";
|
|
|
|
export function buildFrontend(config, args = {}) {
|
|
const buildDir = join(config.canvasPath, "build");
|
|
|
|
if (args.skipBuild) {
|
|
if (!existsSync(buildDir)) {
|
|
logError(
|
|
"--skip-build was passed but build/ does not exist. Run without --skip-build first.",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
logStep("build", "Skipping frontend build (--skip-build)");
|
|
logService("build", `Reusing existing build/ at ${buildDir}`, c.dim);
|
|
logService(
|
|
"build",
|
|
"Source edits will NOT appear until you run without --skip-build (or `npm run build`).",
|
|
c.yellow,
|
|
);
|
|
return;
|
|
}
|
|
|
|
logStep("build", "Building frontend (npm run build:app)...");
|
|
logService(
|
|
"build",
|
|
"This typically takes 30-60s; cached as build/ for --skip-build reuse",
|
|
c.dim,
|
|
);
|
|
|
|
const cmd = buildNpmScriptCommand("build:app");
|
|
const result = spawnSync(cmd.command, cmd.args, {
|
|
cwd: config.canvasPath,
|
|
stdio: "inherit",
|
|
env: {
|
|
...process.env,
|
|
// Bake the same default workspace path that the dynamic launcher passes
|
|
// to Vite.
|
|
VITE_WORKING_DIR:
|
|
config.viteWorkingDir ?? join(config.stateDir, "workspaces"),
|
|
// Bake the session API key — used by the frontend for both agent-server
|
|
// and automation auth via the `X-Session-API-Key` header.
|
|
VITE_SESSION_API_KEY: config.sessionApiKey,
|
|
// Bake a description of the runtime services in this dev stack so the
|
|
// frontend can populate the agent's <RUNTIME_SERVICES> system-prompt
|
|
// block when creating a conversation.
|
|
VITE_RUNTIME_SERVICES_INFO: JSON.stringify(
|
|
buildAutomationRuntimeServicesInfo(config),
|
|
),
|
|
// Intentionally do NOT set VITE_BACKEND_BASE_URL: leaving it unset makes
|
|
// the runtime fall back to window.location.origin, which keeps the build
|
|
// portable across localhost, LAN hosts, and tunnels such as ngrok.
|
|
},
|
|
});
|
|
|
|
if (result.status !== 0) {
|
|
logError(`Build failed with exit code ${result.status ?? "null"}`);
|
|
process.exit(result.status ?? 1);
|
|
}
|
|
|
|
if (!existsSync(join(buildDir, "index.html"))) {
|
|
logError(
|
|
`Build completed but ${join(buildDir, "index.html")} is missing. ` +
|
|
"Did react-router build write somewhere unexpected?",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
logSuccess("Build complete");
|
|
}
|