Commit Graph
6 Commits
Author SHA1 Message Date
b9d78d3116 Simplify backend registry selection (#1046)
* Add partial stack modes to agent-canvas

Co-authored-by: openhands <openhands@all-hands.dev>

* Simplify backend registry selection

Co-authored-by: openhands <openhands@all-hands.dev>

* Fix backend selection CI regressions

* Seed local proxy backend in cloud tests

* Stabilize onboarding snapshot navigation

* Stabilize ingress tests on Windows

* Remove local backend fallback for cloud calls

* Fix frontend-only backend proxy target

* Test backend-only launch without build

* Add pending workflow and status updates

* Use active LLM profile for setup banner

* Show backend connection errors before saving

* Validate backend keys in health checks

* Update backend selector health test mock

* Fix frontend-only workspace path

* Preserve OpenHands proxy base URL

* Address backend review comments

* Preserve profile config when switching models

* Fail fast on profile export errors

* Throw AgentServerUnavailableError when backend registry is empty

When no backend is configured (empty registry / NO_BACKEND sentinel),
loadAgentServerInfo() was returning null without throwing, causing
OptionService.getConfig() to succeed silently. root.tsx then rendered
the home page instead of the MissingAgentServerScreen with the manage
backends modal.

Now loadAgentServerInfo() checks for the NO_BACKEND sentinel when
getEffectiveLocalBackend() returns null and throws
AgentServerUnavailableError, which root.tsx already handles by showing
the manage backends modal. The cloud-backend path (also null from
getEffectiveLocalBackend) is preserved — it still returns null.

Co-authored-by: openhands <openhands@all-hands.dev>

* chore: Remove PR-only artifacts

---------

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: allhands-bot <allhands-bot@users.noreply.github.com>
2026-06-03 15:26:51 +00:00
Rohit Malhotraandopenhands e2dd1b5f17 fix: unify session and automation API keys into a single credential with consistent header (#681)
* 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>
2026-05-26 22:15:27 +00:00
59058c7609 fix(ui): left navigation rail, mobile drawer, and responsive chrome (#623)
* fix: archived row icon, default-local config sync, and dockerless dev fixes

Archived MISSING sandboxes show an archive icon in the status column instead of a gray dot and pill; ERROR sandboxes keep the error pill. Harden port checks and automation CORS for alternate frontend ports, set agent-server HOME to the host home on macOS, sync legacy agent-server config when editing the default-local backend, and clarify static stack rebuild/skip-build behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): sidebar conversation list flush to rail with stable gutter

Drop expanded aside `md:pr-0` so the thread scrollbar aligns with the rail
while nav, logo row, and footer keep horizontal padding. Use scrollbar-gutter
on the conversation list for consistent right inset with or without overflow.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): 40px backend selector and non-italic combobox text

Pin the backend Dropdown trigger to h-10, add an italicPlaceholder escape
hatch, and force upright type for value/placeholder in the selector. Add a
subtle top border above Add Workspace in the new-conversation menu.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): full-bleed sidebar footer divider to left rail

Pull the backend block border past aside `pl-2` with matching width calc;
keep inner `px-2` so controls stay aligned with nav.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): align context menus with sidebar filter menu and muted row icons

Match list padding, border, and shadow to the conversations filter surface;
use theme foreground/muted tokens; reserve leading icons as muted until row
hover/focus. Simplify list-item rows and remove unused context-menu height
constant.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): unify menu dividers, section labels, and filter actions

Standardize full-bleed menu dividers via Divider inset="menu", give filter
menu section headings consistent pt-1 padding, and add icons to hide/show
and delete-all rows in the conversation panel filter menu.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): rename sidebar conversations link to New Chat

The /conversations nav entry should read "New Chat" instead of "Code" to match user expectations for starting a conversation.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): polish cloud new-thread popover search and repo list

Use a flat search row with icon and menu divider, align horizontal padding with list items, and show a custom scrollbar on the repository list.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): unify filter menu section headings and action icons

Share pt-1 section label padding via MenuHeading, fold hide/delete rows into
MenuRow with Eye and Trash icons, and add a regression test for both actions.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): add settings tooltip and neutral delete-all row

Show a white hover tooltip on the backend selector settings button and
style Delete all like other filter menu actions instead of danger red.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): theme scrollbars/skeletons and improve settings tooltips

Derive scrollbar colors from the cool-grey scale, use interactive-active
for skeleton loaders, and fix settings tooltip placement when the drawer
is open plus collapsed-sidebar coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): replace mobile top nav with left drawer

On small screens, hide the horizontal sidebar strip and open the full
vertical nav from a top-bar chevron toggle, matching the desktop collapse
control icon.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): restore mobile page gutters and center home title

Apply 14px horizontal padding in the root outlet on mobile, keep
conversation full-bleed, and center the home heading with w-full text-center.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): correct mobile nav icons and home title line height

Use PanelLeft for the mobile menu trigger, ChevronLeft to close the
drawer, and relax the home headline leading when it wraps.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): remove border under mobile nav menu bar

The top-bar menu trigger no longer draws a divider above page content.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(ui): mobile settings/customize hubs and animated nav drawer

On mobile, Settings and Customize open list hubs matching desktop left nav;
detail pages show drawer and back controls in the top bar. The slide-out nav
drawer now animates open and closed with a fading scrim.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep sidebar icons aligned when collapsing the rail

Use shared h-10 row geometry and a fixed icon column so collapsed and
expanded states share padding and gap; labels clip instead of recentering.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): stabilize collapsed sidebar icon column and hover targets

Use a shared 18px icon slot in both rail states, square collapsed
controls for hover/active, and symmetric rail padding so icons and the
logo stay aligned without full-width row highlights.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): refine collapsed sidebar slots and empty-list load-more

Use consistent px-2.5 rail padding with 40×40 collapsed icon slots via
SidebarCollapsedIconSlot, fix backend dot anchoring and logo alignment,
and hide “Load more” when no conversations are visible after filtering.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): keep conversations header on one line during sidebar resize

Use flex-nowrap with a truncating title so the toolbar row does not wrap
while the drawer animates, and nudge the collapsed backend status dot up-left.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): align DropdownMenu padding and tighten backend footer actions

Use uniform `p-1` on the combobox menu panel to match other menus, and
remove vertical gap between Add/Manage backend items in the selector footer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): trim vertical padding on cloud repo search row

Drop wrapper `py-1` so the new-conversation repo search aligns with the
dropdown chrome; horizontal inset stays `px-2`.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): flush cloud repo menu divider against search and list

Drop flex `gap-1` on the popover so the rule sits tight to the search row
and repository list; keep tab stripe spacing with `py-1` on the provider row.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): show backend settings tooltip above when sidebar is expanded

Use `useSidebarCollapsed()` so the gear tooltip uses top placement on the
full-width rail while keeping left placement for the icon-only strip unless
the conversation right drawer is open.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): use full-screen route for mobile tools panel and tidy conversation chrome

Restore horizontal inset on the conversation route, fold the sidebar opener into the chat header, and open Files/Tools via `/conversations/:id/panel` with a dedicated back affordance instead of a bottom sheet.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): only show sidebar drawer toggle when the rail is hidden

The hamburger used the 1024px layout breakpoint while the sidebar stays visible from the `md` rail width up, so it duplicated chrome between tablet widths. Gate the toggle and header padding on the same max-md width as the rail (<=767px). Mirror the right-panel icon horizontally for the right-side drawer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): align mobile conversation chrome, chat padding, and settings scroll

Unify mobile top-bar icon buttons with shared classes; add compact conversation
tabs and consistent horizontal padding for chat plus stable composer/git chrome.
Move settings and extensions horizontal inset into layout helpers and drop the
root outlet gutter so pages control their own padding.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): home mobile padding and Lucide sizes in chat mobile header

Add px-4 to the home shell on small viewports and shift launcher inset to
md+ only. Pin PanelLeft/ChevronLeft to 20px to match the right-panel icon and
restore chat header left inset when the rail menu toggle shows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ui): use block-drawer icon for mobile sidebar toggle

Match the right-panel control’s SVG so both header icons share the same
optical weight instead of Lucide PanelLeft filling the hit target.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: remove unrelated file

* refactor: remove unrelated files

* fix: failing tests

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: hieptl <hieptl.developer@gmail.com>
2026-05-21 02:18:19 +07:00
Rohit Malhotraandopenhands edb998220a Remove Docker dependency from dev workflow (#635)
- Delete scripts/dev-docker.mjs and its test
- Simplify package.json: 'npm run dev' now runs local uvx stack directly
  (agent-server + automation + Vite + ingress), no Docker needed
- Remove dev:docker, dev:docker:dynamic, dev:dangerously-dockerless scripts
- Add dev:static for production-build frontend variant
- Update bin/agent-canvas.mjs CLI to use uvx-based stack
- Rename Docker-specific variables: DOCKER_PROJECTS_PATH → PROJECTS_PATH,
  shouldDefaultToDockerProjects → shouldDefaultToProjectsPath
- Update i18n: HOST_HOME_NOT_MOUNTED_HINT no longer references Docker
- Update all docs (README, DEVELOPMENT, SELF_HOSTING, AGENTS.md, CHANGELOG)
- Rename e2e snapshot: docker-workspace-browser → projects-workspace-browser
- Fix all tests to reflect new script names and remove Docker references

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-19 15:27:25 -04:00
Tim O'Farrellandopenhands b2b71855c6 feat(dev): surface dev-stack runtime services in agent system prompt (#503)
* feat(dev): surface dev-stack runtime services in agent system prompt

Add a structured 'runtime services' info object that the dev launchers
(`dev:safe`, `dev:automation`, `dev:docker`, and the published
`agent-canvas` binary) propagate to the frontend via
`VITE_RUNTIME_SERVICES_INFO`. The frontend renders it into a
`<RUNTIME_SERVICES>` markdown block and attaches it as
`AgentContext.system_message_suffix` on every `POST /api/conversations`.

This means agents start each conversation knowing exactly what services
exist in the current dev stack (ingress URL, automation backend URL +
`/api/automation` prefix, auth header, etc.), instead of having to probe
or — worse — assume `localhost:8000` is the automation server when it is
actually the Agent Server they are running inside of.

URLs are written from the agent's point of view: dockerless modes use
`localhost`, `dev:docker` uses `host.docker.internal`. When automation
isn't running in the current mode (e.g. `dev:safe`), the block says so
explicitly so agents know to skip `/api/automation` calls.

Co-authored-by: openhands <openhands@all-hands.dev>

* fix(runtime-services): address review feedback on PR #503

- Validate required `agentServerPort` in `buildRuntimeServicesInfo`;
  previously a missing port baked `http://localhost:undefined` into
  the agent's system prompt.
- Skip the automation entry when the supplied `automation` object has
  no `port` (e.g. a bare `{}` from a misconfigured launcher).
- Rename the JSON service key from `vite` to `frontend` and add a
  `kind: "vite" | "static"` discriminator + mode-aware description,
  so static-build dev stacks (`dev:docker`, the published binary, ...)
  no longer surface a misleading "Vite dev server" line in the agent
  system prompt. The renderer still accepts the legacy `vite` key.
- Anchor the "don't guess" warning to the actual agent-server URL from
  runtime info instead of hardcoded `localhost:8000`, since the
  agent-server uses different ports across dev modes (18000 in
  dev:safe, 8000 in dev:docker, ...).
- Plumb `frontendKind` through `buildAutomationRuntimeServicesInfo`
  and stamp `config.frontendKind` in `dev-with-automation.mjs::main`
  so both Vite spawn and static-build paths describe the frontend
  correctly.
- Expand AGENTS.md with the JSON schema of `VITE_RUNTIME_SERVICES_INFO`
  and a concrete example of the rendered `<RUNTIME_SERVICES>` block.
- Tests: assert the new URL-in-warning behavior, the new `frontend` /
  legacy `vite` rendering, the `agentServerPort`-required guard, the
  `automation: {}` skip, and the legacy `vitePort` alias.

Co-authored-by: openhands <openhands@all-hands.dev>

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-15 20:53:45 -06:00
Graham Neubigandopenhands a4089e0e4a Default user launchers to static frontend (#434)
Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-14 18:18:36 +00:00