MCPcopy Create free account
hub / github.com/OpenHands/OpenHands / buildConfigFromPorts

Function buildConfigFromPorts

scripts/dev-safe.mjs:609–676  ·  view source on GitHub ↗

* Internal helper to build config from already-resolved ports. * @param {{backendPort: number, vscodePort: number}} ports * @param {string} cwd * @param {Record } env * @returns {SafeDevConfig}

(ports, cwd, env)

Source from the content-addressed store, hash-verified

607 * @returns {SafeDevConfig}
608 */
609function buildConfigFromPorts(ports, cwd, env) {
610 const { backendPort, vscodePort } = ports;
611 const stateDir = path.resolve(
612 cwd,
613 env.OH_CANVAS_SAFE_STATE_DIR ||
614 path.join(homedir(), ".openhands", "agent-canvas"),
615 );
616 const conversationsPath = path.join(stateDir, "dev_conversations");
617 const workspacesPath = path.join(stateDir, "workspaces");
618 // Use provided secret key, or read/generate one persisted to
619 // ~/.openhands/agent-canvas/secret-key.txt. Persisting ensures dev mode
620 // and Docker mode share the same encryption key when they mount the same
621 // ~/.openhands directory (docker/entrypoint.sh reads/writes the same file).
622 const secretKeyPath =
623 env.OH_SECRET_KEY_PATH || DEFAULT_SECRET_KEY_PATH;
624 const secretKey =
625 env.OH_SECRET_KEY || getOrCreatePersistedApiKey(secretKeyPath, "secret");
626 // Use the user-provided LOCAL_BACKEND_API_KEY or fall back to a key
627 // persisted to ~/.openhands/agent-canvas/api-key.txt. Persisting on disk
628 // keeps the agent-server, the Vite-baked VITE_SESSION_API_KEY, and any
629 // `openhands-backends` localStorage entries the frontend has cached all
630 // pointing at the same value across dev restarts.
631 //
632 // LOCAL_BACKEND_API_KEY is the single user-facing env var for the API key.
633 // OH_SESSION_API_KEY_PATH overrides the persisted file path (used by tests).
634 const persistedKeyPath = env.OH_SESSION_API_KEY_PATH || DEFAULT_API_KEY_PATH;
635 const sessionApiKey =
636 env.LOCAL_BACKEND_API_KEY ||
637 getOrCreatePersistedApiKeyFile(persistedKeyPath);
638
639 // Host directory containing the legacy canvas_ui Python module. Persisted
640 // conversations created before the client_tools migration still reference
641 // its module qualname, so the agent-server can import it when resuming them.
642 const canvasToolsDir = fileURLToPath(new URL("../tools", import.meta.url));
643
644 return {
645 cwd,
646 backendPort,
647 vscodePort,
648 stateDir,
649 // tmux socket directory. Defaults to <stateDir>/tmux (under
650 // ~/.openhands/agent-canvas), matching where the rest of dev state lives
651 // and persisting across restarts.
652 //
653 // Do NOT use os.tmpdir() here: on macOS it resolves to the per-user
654 // $TMPDIR (/var/folders/.../T), which the OS periodically reaps
655 // (com.apple.bsd.dirhelper deletes entries untouched for a few days).
656 // Reaping deletes the live tmux socket while the server process keeps
657 // running, orphaning it — every later new-window then fails with
658 // "error connecting to .../openhands (No such file or directory)".
659 //
660 // The only hosts where <stateDir>/tmux can't hold the socket are those
661 // whose $HOME is a network/overlay mount without Unix-domain-socket
662 // support (some devcontainers, NFS/CIFS homes). Those rare cases can point
663 // tmux at a local, socket-capable path with the standard TMUX_TMPDIR env
664 // var (e.g. TMUX_TMPDIR=/tmp), which we honor and pass through below.
665 tmuxTmpDir: env.TMUX_TMPDIR || path.join(stateDir, "tmux"),
666 conversationsPath,

Callers 2

buildSafeDevConfigFunction · 0.85
buildSafeDevConfigAsyncFunction · 0.85

Calls 2

Tested by

no test coverage detected