Commit Graph
7180 Commits
Author SHA1 Message Date
Graham Neubigandopenhands e8ffdd2829 Render ACP sub-agent tool-call events in chat (port of OpenHands#13994 + #14246 + #14247) (#142)
* Render ACP sub-agent tool-call events in chat (#132)

Port of upstream OpenHands frontend PRs:
  - OpenHands#13994 — initial ACPToolCallEvent rendering
  - OpenHands#14246 — drop the 'ACP · ' prefix from titles
  - OpenHands#14247 — suppress in_progress events to avoid empty-args flash

Adds end-to-end support for the new V1 ACPToolCallEvent surfaced by ACP
sub-agents (Claude Code, Codex, Gemini CLI, …). Each tool call is rendered
through the same GenericEventMessage wrapper used for observation events,
so the resulting card shape, success indicator, and markdown formatting
match the rest of the OpenHands chat.

Highlights:
  - New ACPToolCallEvent type + isACPToolCallEvent type guard, wired into
    the OpenHandsEvent union.
  - getACPToolCallContent + getACPToolCallTitleKey helpers — execute calls
    render as Command:/Output: blocks just like getTerminalObservationContent;
    non-execute calls render their raw_input as a JSON Input: block. Errors
    use **Error:**, missing output falls back to OBSERVATION$COMMAND_NO_OUTPUT,
    and very long output is truncated to MAX_CONTENT_LENGTH.
  - getACPToolCallResult — maps status + is_error to success | error |
    undefined, mirroring getObservationResult so in_progress calls render
    without a check mark.
  - shouldRenderEvent — hides in_progress ACP events to avoid an empty-args
    card flashing before the first populated event arrives (matches #14247).
  - handleEventForUI — dedupes ACP events by tool_call_id so streaming
    in_progress → completed/failed transitions update the card in place
    instead of stacking duplicate cards.
  - EventMessage dispatch — routes ACP events to GenericEventMessageWrapper
    after hook execution events, before generic action handling.
  - Five new ACTION_MESSAGE$ACP_* i18n keys (RUN / EDIT / READ / FETCH /
    TOOL) localised across all bundled languages, with the title rendered
    inline via the existing <cmd> Trans component (no 'ACP · ' prefix per
    #14246).

Tests: 39 new/modified vitest cases across get-acp-tool-call-content,
should-render-event, handle-event-for-ui, and event-message-acp-tool-call.

Visual verification + demo GIF: .pr/issue-132/

This commit was created by an AI agent (OpenHands) on behalf of the user.

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

* Capture real ACP card rendering for #142 demo

Addresses @neubig's review feedback on PR #142 ('I did not see any
examples of ACP events being rendered in the interface'):

  - Updates demo.gif to actually show three ACPToolCallEvent cards
    rendering in the live conversation UI (collapsed view + expanded
    view with Command/Output/Input blocks).
  - Adds 04-acp-cards-collapsed.png + 05-acp-cards-expanded.png as the
    individual frames, plus 04-acp-rendering-notes.md explaining what
    each frame shows and why a synthetic event injection was needed
    (no Claude Code / Codex / Gemini CLI binary in the sandbox).
  - Adds capture.mjs (the Playwright script used to record the demo) so
    future re-records are reproducible.
  - In src/stores/use-event-store.ts, exposes the existing Zustand
    store on window.__OH_EVENT_STORE__ when import.meta.env.DEV is
    true. Tree-shaken from production builds; no behaviour change for
    end users. Useful as a general dev affordance for fixture/preview
    tooling beyond this PR.

Functional verification (unchanged from the original PR):

    npx vitest run         __tests__/components/v1/chat/event-content-helpers/get-acp-tool-call-content.test.ts         __tests__/components/v1/chat/event-message-acp-tool-call.test.tsx
    Test Files  2 passed (2)
         Tests  20 passed (20)

This commit was created by an AI agent (OpenHands) on behalf of the user.

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 20:35:11 -04:00
Rohit Malhotraandopenhands 6d1f0a74d9 feat: seed automation API key into agent-server secrets (#160)
* feat: seed automation API key into agent-server secrets

- Add seedAutomationSecret() that calls PUT /api/settings/secrets after
  agent-server is ready, storing the automation API key as
  OPENHANDS_AUTOMATION_API_KEY
- This makes the key available to agents during conversations so they can
  authenticate with the automation backend
- Add sessionApiKey to config for optional auth header
- Update help text and documentation

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

* test: add tests for seed automation secret and fix CI failure

- Add tests for localApiKey and sessionApiKey config in buildConfig
- Add tests for secrets documentation in help output
- Fix root-layout-refetch.test.tsx unhandled rejection from framer-motion
  by adding async cleanup with microtask flush

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

* fix: detect SESSION_API_KEY when seeding automation secret

The seedAutomationSecret() function was failing with 401 Unauthorized
because it wasn't detecting the SESSION_API_KEY environment variable
that the agent-server uses by default (V0 config).

The agent-server checks these env vars for session API keys:
- SESSION_API_KEY (V0 config, picked up by default factory)
- OH_SESSION_API_KEYS_0 (V1 config)

The original code only checked OH_SESSION_API_KEY and VITE_SESSION_API_KEY,
missing the actual env vars the server reads. In OpenHands Cloud
environments, SESSION_API_KEY is set automatically, causing the 401.

This fix adds SESSION_API_KEY and OH_SESSION_API_KEYS_0 to the
fallback chain, with SESSION_API_KEY taking highest precedence
since it matches the agent-server's default behavior.

Adds tests verifying:
- SESSION_API_KEY detection
- OH_SESSION_API_KEYS_0 detection
- Precedence order (SESSION_API_KEY > OH_SESSION_API_KEYS_0 > others)

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

* fix: add retry logic and longer timeout for secret seeding

On slower systems, the agent-server may take longer to start up,
causing the secret seeding to fail with 'fetch failed' errors.

This fix adds:
1. Increased initial wait timeout from 30s to 60s for agent-server startup
2. Retry logic in seedAutomationSecret (5 retries with 2s delay)
3. Better error logging showing elapsed time and last error
4. AbortSignal.timeout on fetch requests to avoid hanging
5. Skip seeding if server fails to start (with warning message)

The retry logic handles transient failures during server warmup
but immediately fails on 401/403 auth errors (no point retrying).

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 17:29:46 -04:00
Hiep Le 951919f2c5 refactor: remove redundant AgentServerSettingsScreen (#162) 2026-05-08 03:06:37 +07:00
Xingyao Wangandopenhands c38422fa43 ci: enable sub-agent delegation for PR reviews (#158)
This repo typically has large PRs spanning multiple files, so enabling
sub-agent delegation lets the review bot fan out file-level reviews to
dedicated sub-agents for better coverage.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 15:32:41 -04:00
Hiep Le 9aebb35cfa fix: always send param to git branches search (#157) 2026-05-08 02:19:03 +07:00
6ebe7b4e7e feat: add automations frontend on /automations subpath (#141)
* feat: add automations frontend on /automations subpath

Port automations frontend from automation-repo to agent-canvas.

## Changes

### New Routes
- /automations - List view of all automations
- /automations/:automationId - Automation detail view

### New Components
- Automation list components: card, card-skeleton, group, empty-state, error-state
- Automation detail components: header, sections (config, prompt, plugins, activity)
- Shared UI components: toggle-switch, metadata-chip, status-badge, kebab-menu, search-input

### API Integration
- automation-service.api.ts - API client for automation CRUD operations
- Uses existing openHands axios client (shared base URL with agent server)

### MSW Mock Server Handlers
- automation-handlers.ts - Mock handlers for testing
- automations.mock.ts - Sample automation data
- automation-runs.mock.ts - Sample automation run data

### Tests
- API tests: automation-service.test.ts, automation-handlers.test.ts
- Component tests: toggle-switch, metadata-chip, search-input, error-state
- Detail component tests: section-card, run-status-badge, not-found-state

### Hooks
- use-automations.ts - React Query hook for fetching automations list
- use-automation-detail.ts - React Query hook for fetching single automation
- use-has-permission.ts - Permission checking utility hook

### Types
- automation.ts - TypeScript types for automation entities

### Icons
- Added SVG icons: activity, bell, calendar, check-circle, chevron-down,
  chevron-left, clock, cog, database, exclamation-circle, git-branch,
  kebab-vertical, power, puzzle, search, sparkle, target, trash, x-circle, x-mark

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

* feat: add local API key auth for automation backend

- Use VITE_AUTOMATION_API_KEY env var for frontend to authenticate
- Pass AUTOMATION_LOCAL_API_KEY to automation backend in dev mode
- Use dedicated axios instance with Bearer auth interceptor
- Add --refresh to uvx to ensure latest git commits are fetched
- URL-encode automation IDs in API paths

The default local API key is 'openhands-local-api-key' which matches
between the frontend and backend for local development.

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

* fix: automation service tests and ingress port conflicts

- Fix automation-service.test.ts to mock axios instance correctly
  (was mocking openHands but service uses automationAxios)
- Use vi.hoisted() for mock functions available during vi.mock hoisting
- Change ingress test ports from 19000-19003 to 29000-29003 to avoid
  conflict with VS Code server on port 19000

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

* fix: add CORS origins for automation backend in dev mode

The automation backend defaults CORS origins to app.all-hands.dev,
which blocks localhost requests. Add localhost origins for the
ingress port and Vite dev server port.

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

* fix: update create-instructions styling and add missing i18n keys

- Use semantic color tokens (text-content, text-basic, bg-base-secondary,
  bg-base, border-default) instead of hardcoded neutral-* colors
- Add all AUTOMATIONS$ i18n keys for the automations frontend

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: hieptl <hieptl.developer@gmail.com>
2026-05-08 01:49:13 +07:00
Rohit Malhotraandopenhands 48b275a94f feat: track install immediately and use reverse proxy for ad blocker bypass (#155)
* feat: track install immediately without consent, add proxy support

BREAKING CHANGE: Install event (canvas_install) is now sent immediately
on first use, regardless of consent status. Users can still opt out via
VITE_DO_NOT_TRACK=1 or browser's Do Not Track setting.

Changes:
- trackInstall() sends the install event immediately without waiting for consent
- trackFirstUse() is now deprecated, calls trackInstall() for backward compat
- Session/custom events still require user consent
- Add VITE_POSTHOG_UI_HOST env var for reverse proxy support
- PostHog initialization now includes ui_host configuration

This change allows tracking library adoption even if users haven't made
a consent choice yet, while still respecting hard opt-outs.

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

* feat: default PostHog host to z.openhands.dev proxy

Use OpenHands' managed reverse proxy by default to bypass ad blockers.
The proxy at z.openhands.dev routes telemetry to PostHog's US region.

Library consumers can still override with VITE_POSTHOG_HOST if needed.

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

* chore: remove deprecated trackFirstUse function

Only trackInstall() is now exported. No backwards compatibility shim needed.

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

* docs: add privacy/GDPR compliance notes to install tracking

Address review feedback by documenting the privacy implications and
GDPR legal basis (legitimate interest under Article 6(1)(f)) for
sending the anonymous install event before consent.

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

* fix: wait for translations before showing consent modal

- Use useTranslation's 'ready' state to wait for translations to load
- Add small delay (50ms) to ensure DOM is fully hydrated
- Prevents translation keys from flashing on first appearance

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 14:29:32 -04:00
Hiep Le dd744b13f6 feat: cloud backend support with multi-backend selector and SaaS proxy routing (#145)
* feat: multi-backend support with cloud SaaS proxy routing

* feat: route conversation export through cloud proxy on cloud backends

* fix: route conversation delete through cloud proxy on cloud backends

* fix: forward settings diffs verbatim through cloud proxy save

* fix: surface cloud-aware settings sub-pages and gate local-only routes

* fix: route secrets settings through cloud proxy on cloud backends

* fix: route conversation stop runtime through cloud proxy on cloud backends

* fix: re-expose planning agent UI for cloud backends and route plan file reads through cloud proxy

* fix: route Display Cost runtime fetch through cloud proxy and ungate local metrics without session API key

* fix: handle WAITING_FOR_SANDBOX task status from cloud backends to prevent UI crash

* fix: re-expose Public Share in conversation menu for cloud backends

* fix: redirect to home when switching backends from a conversation page

* fix: hide cloud orgs the API key can't access in backend selector

* feat: support running multiple local agent-servers with shared persistence

* fix: lint

* fix: failing tests
2026-05-08 01:17:40 +07:00
dependabot[bot]andopenhands ee0359b0f3 deps(deps-dev): bump eslint-plugin-react-hooks from 4.6.2 to 7.1.1 in the react group (#149)
* deps(deps-dev): bump eslint-plugin-react-hooks in the react group

Bumps the react group with 1 update: [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks).


Updates `eslint-plugin-react-hooks` from 4.6.2 to 7.1.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/eslint-plugin-react-hooks@7.1.1/packages/eslint-plugin-react-hooks)

---
updated-dependencies:
- dependency-name: eslint-plugin-react-hooks
  dependency-version: 7.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: react
...

Signed-off-by: dependabot[bot] <support@github.com>

* ci: allow eslint-plugin-react-hooks v5+ alongside airbnb-19

- Add npm override so eslint-config-airbnb's strict ^4.3.0 peer dep on
  eslint-plugin-react-hooks does not block dependabot version bumps.
- Disable the new React Compiler-aware rules introduced in
  eslint-plugin-react-hooks@5+ (immutability, preserve-manual-memoization,
  refs, set-state-in-effect) to avoid retroactively flagging existing code
  on every plugin bump. They can be re-enabled if/when we adopt the
  React Compiler.

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 13:43:24 -04:00
517c631b29 perf(markdown): allowlist syntax-highlighter languages (#154)
Switch the markdown code block component from `Prism` (which pulls in
all ~300 refractor grammars, including curiosities like brainfuck) to
`PrismLight` with an explicit allowlist of ~58 commonly-used languages.

Each grammar's built-in `aliases` array (e.g. `js`, `ts`, `py`,
`html`) is auto-wired, plus a small `EXTRA_ALIASES` map covers
aliases the prism modules don't declare themselves (`terraform`/`tf`
for hcl, `c++`/`cxx` for cpp, `rs` for rust, `ml` for ocaml,
`ps1` for powershell, etc.).

Unrecognized languages still render correctly: react-syntax-highlighter
silently falls back to plain text when a grammar isn't registered.

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: hieptl <hieptl.developer@gmail.com>
2026-05-08 00:33:34 +07:00
Rohit Malhotraandopenhands e2615344df feat: add first-use telemetry tracking with consent (#138)
* feat: add first-use telemetry tracking with consent

- Add telemetry service with consent management (src/services/telemetry.ts)
- Add useTelemetry React hook for easy integration (src/hooks/use-telemetry.ts)
- Add TelemetryConsentBanner component with i18n support
- Add local development server for testing (scripts/telemetry-dev-server.mjs)
- Add comprehensive tests for telemetry service and hook
- Export telemetry utilities from library index
- Respect DO_NOT_TRACK environment variable for privacy
- Uses localhost:8080 endpoint for development

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

* fix: address PR review feedback

- Make TELEMETRY_ENDPOINT configurable via VITE_TELEMETRY_ENDPOINT env var
- Make POSTHOG_API_KEY configurable via VITE_POSTHOG_API_KEY env var
- Add validation to skip telemetry if API key not configured (except localhost)
- Fix DO_NOT_TRACK to work in browser environments using VITE_DO_NOT_TRACK
- Also respect browser's navigator.doNotTrack standard
- Update consent banner hint text to reference correct env var
- Add documentation comments for all configuration options

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

* feat: hardcode PostHog credentials for centralized telemetry

- Use OpenHands PostHog project API key for all library users
- Use PostHog US Cloud endpoint (https://us.i.posthog.com/capture)
- Remove environment variable configuration for endpoint/API key
- Telemetry now automatically sends to centralized project when consent granted
- Users can still opt out via UI, VITE_DO_NOT_TRACK, or browser DNT setting

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

* feat: use separate PostHog API keys for dev and production

- Dev environment: phc_kBtz5nKmxVRRQ7HtPwr2QX9eMC5j65zE86QKocVNwb4U
- Production: phc_BgzfxKdgsYMLFTmJqt424ZoyVHvKFfrwttLimzdYTKFK
- Automatically selects key based on import.meta.env.DEV

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

* chore: use single production PostHog API key everywhere

Simplify by using the same API key for all environments.

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

* chore: rename telemetry events

- library_first_use → canvas_install
- library_session_start → canvas_new_session

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

* feat: migrate telemetry to PostHog SDK

Replace raw HTTP requests with PostHog SDK for:
- Automatic event batching
- Built-in retry logic with exponential backoff
- Offline support (queues events, sends when back online)
- Automatic session tracking
- Better device/browser info enrichment

Benefits:
- More reliable event delivery
- Reduced network requests
- Cleaner code with less manual state management
- Future-proof for feature flags, session replay, etc.

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

* refactor: remove redundant hasTrackedFirstUse state in hook

The trackFirstUse() function already has built-in deduplication via
localStorage, so the local React state was unnecessary. Simplified
the hook and added a comment explaining the deduplication mechanism.

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

* chore: remove obsolete telemetry dev server

The local dev server was used when telemetry used raw HTTP requests
to a configurable endpoint. Now that we use the PostHog SDK with
the real PostHog endpoint, this is no longer needed.

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

* fix: remove trailing comma in package.json

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

* fix: address PR review feedback

- Make POSTHOG_API_KEY configurable via VITE_POSTHOG_API_KEY env var
- Make POSTHOG_HOST configurable via VITE_POSTHOG_HOST env var
- Add session deduplication using sessionStorage to prevent duplicate
  canvas_new_session events from multiple hook instances
- Clear sessionStorage in clearTelemetryData()

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

* fix: use dynamic imports for PostHog SSR compatibility

- Convert top-level posthog-js import to dynamic import for SSR safety
- Add getPostHog() lazy loader that only imports in browser context
- Make setTelemetryConsent, clearTelemetryData, getPostHogInstance async
- Update documentation to clarify default telemetry destination
- Update tests for async function signatures

This ensures the library works correctly in SSR frameworks (Next.js, Remix,
etc.) that might import this module server-side.

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

* feat: add telemetry consent banner to app layout

The consent banner now appears on all pages until the user explicitly
accepts or declines telemetry. This ensures users are always prompted
for consent on their first visit regardless of which page they land on.

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

* refactor: update telemetry consent banner to modal style

- Changed from bottom banner to centered modal overlay (matching OpenHands)
- Uses ModalBackdrop, ModalBody, BaseModalTitle, BaseModalDescription
- Single checkbox with 'Confirm preferences' button pattern
- Full-screen overlay blocks interaction until user makes a choice
- Added i18n keys: TELEMETRY$SEND_ANONYMOUS_DATA, TELEMETRY$CONFIRM_PREFERENCES

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

* fix: ensure PostHog is initialized before tracking events

- Made grantConsent/denyConsent in useTelemetry hook async to ensure
  PostHog initialization completes before state update triggers tracking
- Updated tests for async consent functions
- This fixes a race condition where trackFirstUse() could be called before
  PostHog's opt_in_capturing() had been executed

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 13:18:01 -04:00
dependabot[bot] dc0b5ac964 deps(deps): bump @microlink/react-json-view from 1.31.18 to 1.31.19 (#153)
Bumps [@microlink/react-json-view](https://github.com/microlinkhq/react-json-view) from 1.31.18 to 1.31.19.
- [Release notes](https://github.com/microlinkhq/react-json-view/releases)
- [Changelog](https://github.com/microlinkhq/react-json-view/blob/master/CHANGELOG.md)
- [Commits](https://github.com/microlinkhq/react-json-view/compare/v1.31.18...v1.31.19)

---
updated-dependencies:
- dependency-name: "@microlink/react-json-view"
  dependency-version: 1.31.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:06:22 -04:00
dependabot[bot] d5c6a6522d deps(deps-dev): bump the testing group with 3 updates (#151)
Bumps the testing group with 3 updates: [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8), [msw](https://github.com/mswjs/msw) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/coverage-v8` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.5/packages/coverage-v8)

Updates `msw` from 2.13.4 to 2.14.2
- [Release notes](https://github.com/mswjs/msw/releases)
- [Changelog](https://github.com/mswjs/msw/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mswjs/msw/compare/v2.13.4...v2.14.2)

Updates `vitest` from 4.1.4 to 4.1.5
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.5/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: testing
- dependency-name: msw
  dependency-version: 2.14.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: testing
- dependency-name: vitest
  dependency-version: 4.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: testing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:06:16 -04:00
dependabot[bot] 5592d903ee deps(deps): bump the react-router group with 4 updates (#150)
Bumps the react-router group with 4 updates: [@react-router/node](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-node), [@react-router/serve](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-serve), [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) and [@react-router/dev](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dev).


Updates `@react-router/node` from 7.14.1 to 7.14.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-node/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/node@7.14.2/packages/react-router-node)

Updates `@react-router/serve` from 7.14.1 to 7.14.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-serve/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/serve@7.14.2/packages/react-router-serve)

Updates `react-router` from 7.14.1 to 7.14.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.14.2/packages/react-router)

Updates `@react-router/dev` from 7.14.1 to 7.14.2
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dev/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/dev@7.14.2/packages/react-router-dev)

---
updated-dependencies:
- dependency-name: "@react-router/node"
  dependency-version: 7.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react-router
- dependency-name: "@react-router/serve"
  dependency-version: 7.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react-router
- dependency-name: react-router
  dependency-version: 7.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react-router
- dependency-name: "@react-router/dev"
  dependency-version: 7.14.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: react-router
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:06:10 -04:00
dependabot[bot] 5b36c6c444 deps(deps): bump react-i18next in the i18next group (#148)
Bumps the i18next group with 1 update: [react-i18next](https://github.com/i18next/react-i18next).


Updates `react-i18next` from 17.0.4 to 17.0.6
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v17.0.4...v17.0.6)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-version: 17.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: i18next
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:06:05 -04:00
dependabot[bot] 1e2646a26a ci(deps): bump dawidd6/action-download-artifact in the actions group (#147)
Bumps the actions group with 1 update: [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact).


Updates `dawidd6/action-download-artifact` from 20 to 21
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/v20...v21)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-version: '21'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 13:05:23 -04:00
Graham Neubigandopenhands c8959713b2 Translate hardcoded settings strings (#134, ports OpenHands#14286) (#143)
Ports the i18n half of upstream OpenHands frontend PR #14286
('fix(i18n): translate hardcoded settings strings'):

  - app-settings.tsx: replaced the hardcoded
    placeholder='Username for git commits' and
    placeholder='Email for git commits' strings on the Git Settings
    inputs with t(I18nKey.SETTINGS$GIT_USERNAME_PLACEHOLDER) and
    t(I18nKey.SETTINGS$GIT_EMAIL_PLACEHOLDER).
  - mcp-server-form.tsx: replaced the hardcoded label='Timeout (seconds)'
    on the SHTTP timeout input with t(I18nKey.SETTINGS$MCP_TIMEOUT_LABEL).

All three new keys ship with translations for every locale agent-canvas
bundles (en/ja/zh-CN/zh-TW/ko-KR/no/it/pt/es/ar/fr/tr/de/uk/ca), and
make-i18n regenerates declaration.ts with matching enum members.

The companion upstream PR #14291 — which drops the
ENABLE_SANDBOX_GROUPING() feature-flag gate around the
sandbox-grouping-strategy dropdown — is a no-op here: the
sandbox-grouping field, the dropdown, and the feature flag were all
already stripped from agent-canvas during the original OSS port, and
sandbox_grouping_strategy is not exposed by openhands-agent-server's
settings schemas (verified against 1.20.1). Per the issue's own
acceptance criteria, this PR therefore does not re-introduce the
control; see .pr/issue-134/visual-verification.md for details.

Visual verification + demo GIF: .pr/issue-134/

This commit was created by an AI agent (OpenHands) on behalf of the user.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 12:54:56 -04:00
Robert Brennan 3b364ca389 switch to uuid package (#146) 2026-05-07 12:50:05 -04:00
Graham Neubigandopenhands dbcbe506fc deps(deps): group related dependabot updates (#144)
Group npm packages by feature area so related libraries land in a
single PR rather than as separate, racing updates. This avoids the
package-lock.json conflicts we saw when sequential PRs all touched
the same lockfile entries (e.g. tailwindcss + @tailwindcss/vite),
and reduces churn for users that watch the dependencies label.

Groups:
- tailwind, tanstack, i18next, react, react-router, testing,
  eslint, monaco, xterm, types

High-impact packages that are not assigned to a group (vite,
framer-motion, axios, posthog-js, lucide-react, etc.) still get
their own PR so each can be reviewed and tested independently.

GitHub Actions updates are now also grouped into a single weekly PR.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 12:32:33 -04:00
988cfed5c6 feat: add automation backend integration with standalone ingress proxy (#127)
* feat: add automation backend integration with standalone ingress proxy

- Add scripts/ingress.mjs: standalone HTTP reverse proxy for routing traffic
  to multiple backends based on URL path prefix
- Add scripts/dev-with-automation.mjs: orchestrates full stack with
  agent-server, automation backend (both via uvx), Vite, and ingress
- Make 'npm run dev' run full stack by default (was dev:safe, now dev:automation)
- Rename 'npm run dev:safe' to 'npm run dev:minimal' for agent-server + Vite only
- Update README with new quickstart showing full stack as default
- Update AGENTS.md with architecture documentation

Architecture:
  http://localhost:8000 (Ingress)
  ├── /api/automation/* → Automation Backend (:18001)
  ├── /api/*, /sockets  → Agent Server (:18000)
  └── /* (default)      → Vite Dev Server (:3001)

* test: add tests for ingress and dev-with-automation scripts

- Add __tests__/scripts/ingress.test.ts with 14 tests covering:
  - CLI argument parsing (--help, --port, --route, --default)
  - Route matching (exact, prefix, longest-match-first)
  - Proxy functionality (forwarding, query params, error handling)
  - 502 response when backend unavailable
  - 503 response for unmatched routes with no default

- Add __tests__/scripts/dev-with-automation.test.ts with 19 tests covering:
  - buildAutomationCommand() with various git refs/repos
  - buildConfig() port and path configuration
  - CLI --help output
  - Graceful exit when uvx is missing

- Export testable functions from dev-with-automation.mjs

* fix: prevent dev-with-automation from auto-executing when imported

The script was calling main() unconditionally, which caused test failures
when vitest imported the module. Now check if the module is the main entry
point before executing.

---------

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: hieptl <hieptl.developer@gmail.com>
2026-05-07 12:02:15 -04:00
dependabot[bot] ef03d8c144 deps(deps-dev): bump tailwindcss from 4.2.2 to 4.2.4 (#72)
Bumps [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.2.4/packages/tailwindcss)

---
updated-dependencies:
- dependency-name: tailwindcss
  dependency-version: 4.2.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:29:26 -04:00
dependabot[bot] 8fc6eb97ef deps(deps): bump @tailwindcss/vite from 4.2.2 to 4.2.4 (#73)
Bumps [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.2.4/packages/@tailwindcss-vite)

---
updated-dependencies:
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:22:03 -04:00
dependabot[bot] 05dcac1131 deps(deps): bump i18next from 26.0.6 to 26.0.8 (#74)
Bumps [i18next](https://github.com/i18next/i18next) from 26.0.6 to 26.0.8.
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.0.6...v26.0.8)

---
updated-dependencies:
- dependency-name: i18next
  dependency-version: 26.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:21:59 -04:00
dependabot[bot] 8a5c944e4f deps(deps): bump vite from 8.0.9 to 8.0.10 (#80)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.0.9 to 8.0.10.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.10/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.0.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:21:48 -04:00
dependabot[bot] 0ade8e2578 deps(deps-dev): bump jsdom from 29.0.2 to 29.1.1 (#81)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 29.0.2 to 29.1.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Commits](https://github.com/jsdom/jsdom/compare/v29.0.2...v29.1.1)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-version: 29.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:15:10 -04:00
dependabot[bot] f6f966a6d2 deps(deps): bump i18next-http-backend from 3.0.5 to 3.0.6 (#79)
Bumps [i18next-http-backend](https://github.com/i18next/i18next-http-backend) from 3.0.5 to 3.0.6.
- [Changelog](https://github.com/i18next/i18next-http-backend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-http-backend/compare/v3.0.5...v3.0.6)

---
updated-dependencies:
- dependency-name: i18next-http-backend
  dependency-version: 3.0.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:15:05 -04:00
dependabot[bot] 49aa6e1149 deps(deps): bump @tanstack/react-query from 5.99.2 to 5.100.6 (#78)
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.99.2 to 5.100.6.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/react-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/react-query@5.100.6/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-version: 5.100.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:15:00 -04:00
dependabot[bot] d1314cedf2 deps(deps-dev): bump @tanstack/eslint-plugin-query (#77)
Bumps [@tanstack/eslint-plugin-query](https://github.com/TanStack/query/tree/HEAD/packages/eslint-plugin-query) from 5.99.2 to 5.100.6.
- [Release notes](https://github.com/TanStack/query/releases)
- [Changelog](https://github.com/TanStack/query/blob/main/packages/eslint-plugin-query/CHANGELOG.md)
- [Commits](https://github.com/TanStack/query/commits/@tanstack/eslint-plugin-query@5.100.6/packages/eslint-plugin-query)

---
updated-dependencies:
- dependency-name: "@tanstack/eslint-plugin-query"
  dependency-version: 5.100.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:14:56 -04:00
dependabot[bot] e28cd11d37 deps(deps): bump posthog-js from 1.369.3 to 1.372.5 (#76)
Bumps [posthog-js](https://github.com/PostHog/posthog-js) from 1.369.3 to 1.372.5.
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/compare/posthog-js@1.369.3...posthog-js@1.372.5)

---
updated-dependencies:
- dependency-name: posthog-js
  dependency-version: 1.372.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:14:52 -04:00
dependabot[bot] 4336329009 deps(deps): bump lucide-react from 1.8.0 to 1.14.0 (#75)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.8.0 to 1.14.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.14.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 11:14:28 -04:00
Graham Neubigandopenhands 84ed4d1217 Show full model name in conversation header (#135) (#139)
Port of OpenHands/OpenHands#14284. The LLM model badge in the conversation
header was constrained to max-w-[150px] with an inner `truncate`, which
cut off long model identifiers such as `litellm_proxy/claude-sonnet-4-5-20250929`
to `litellm_proxy/cl…`. Drop the width cap and inner truncate, and apply
`whitespace-nowrap` to the outer span so the full name renders inline.

Also adds scripts/record-demo.mjs - a small playwright recorder used to
capture the verification GIF under .pr/issue-135/ - and updates the
existing test to assert the un-truncated structure.

Closes #135.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 10:46:05 -04:00
Graham Neubigandopenhands 0cd6ed390e Add lint guard for settings query keys (#131)
Mirrors OpenHands/OpenHands#14011: introduces a shared
SETTINGS_QUERY_KEYS helper as the source of truth for settings query
keys, migrates existing call sites to use it, and adds an ESLint rule
that rejects raw queryKey: ["settings", ...] arrays outside the helper
module. Keeps the same shape of guardrail to prevent settings cache
invalidation bugs from drifting back in.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-07 09:44:47 -04:00
Hiep Le c3433d9a58 feat: temporarily disable planning agent UI and drop /new from slash menu (#126) 2026-05-07 03:29:47 +07:00
Hiep Le 6b4fb427e9 feat: always render Workspaces tab regardless of Git PAT (#125) 2026-05-07 03:06:05 +07:00
Hiep Le 7e221c4b65 fix(frontend): revert HeroUI v3 to v2 and scope body for portal'd popovers (#124)
* feat: revert HeroUI v3 to v2 and scope body for portal'd popovers

* fix: failing tests

* fix: failing tests
2026-05-07 02:24:35 +07:00
Hiep Le 3de362249f feat: derive provider_tokens_set from local git provider cache (#123) 2026-05-07 00:55:55 +07:00
Graham Neubigandopenhands 62871d3a7b rename agent-server-gui to agent-canvas (#121)
- npm package: @openhands/agent-server-gui -> @openhands/agent-canvas
- README/DEVELOPMENT/AGENTS/codereview guide updated to new name
- GitHub URL in onboarding screen + tests updated
- dev launcher env vars renamed: OH_GUI_SAFE_* -> OH_CANVAS_SAFE_*
- default state dir: ~/.openhands/agent-server-gui -> ~/.openhands/agent-canvas
- i18n strings replace 'GUI' phrasing with 'Agent Canvas' across settings,
  upgrade, onboarding, and unavailable copy
- Test fixtures, working-dir paths, and library-consumer smoke updated

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-06 13:07:01 -04:00
Rohit Malhotraandopenhands cccecf1100 Fix uvx command to use --from syntax for PyPI packages (#122)
The openhands-agent-server package exposes an executable named
'agent-server', not 'openhands-agent-server'. When using PyPI versions
(either specific or latest), we need to use the --from syntax:
  uvx --from openhands-agent-server agent-server

This fixes the error:
  An executable named 'openhands-agent-server' is not provided by
  package 'openhands-agent-server'.
  Use 'uvx --from openhands-agent-server agent-server' instead.

Fixes #117

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-06 12:07:41 -04:00
Hiep Le 6a5d1b0049 feat: migrate folder browser to /api/file/search_subdirs (#100) 2026-05-06 21:40:45 +07:00
Rohit Malhotraandopenhands 179192ca01 feat: export buildAgentServerEnv helper for downstream consumers (#119)
Add a new exported function that builds the environment variables object
for spawning the agent-server process. This allows downstream consumers
(e.g., the automation service) to use the same env vars without
duplicating the mapping logic.

When new env vars are added or existing ones are renamed, downstream
consumers will automatically inherit the changes by using this helper.

Refactored main() to use the new helper internally.

Closes #118

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-05 22:02:44 -04:00
Rohit Malhotraandopenhands f9006b4bf0 feat: use agent server APIs for settings persistence (#98)
* feat: use agent server APIs for settings persistence

- Replace localStorage with HTTP API for settings storage
- Use `X-Expose-Secrets: encrypted` header for GET /api/settings
  to receive encrypted secrets (not exposing raw values)
- Use `secrets_encrypted: true` in start conversation payload
- Add `getSettingsForConversation()` to build encrypted settings
  payload for conversation start endpoint
- Update secrets service to use /api/settings/secrets endpoints
- Add mock handlers for settings and secrets API endpoints
- Update tests for new API-based settings flow

This integrates with software-agent-sdk PR #3060
(feat/encrypted-secrets-in-transit) which adds server-side
encryption support for secrets in transit.

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

* fix: update test mocks for encrypted settings API and add OH_SECRET_KEY support

- Update use-create-conversation-metadata.test.ts to mock getSettingsForConversation()
  which is now called by buildStartConversationRequestWithEncryptedSettings
- Skip flaky onOpen websocket test that times out intermittently in CI
- Add OH_SECRET_KEY environment variable support in dev-safe.mjs:
  - Uses default key for local development
  - Can be overridden via OH_SECRET_KEY environment variable
  - Logs secret key source at startup

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

* docs: update AGENTS.md for settings API and OH_SECRET_KEY

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

* fix: update secrets service to use agent-server API routes

Changes:
- Update SecretsService to use /api/settings/secrets endpoints instead of /api/v1/secrets
- Simplify secrets-service.types.ts to remove unused pagination types
- Update use-get-secrets hook to do client-side filtering (agent-server doesn't support pagination)
- Update mock handlers to only use agent-server API routes
- Update secrets-settings test to mock getSecrets instead of searchSecrets
- Remove pageSize option from useSearchSecrets since agent-server doesn't paginate

The agent-server API routes (per SDK PR #3060):
- GET /api/settings/secrets - List secrets (names/descriptions only)
- GET /api/settings/secrets/{name} - Get secret value
- PUT /api/settings/secrets - Upsert secret
- DELETE /api/settings/secrets/{name} - Delete secret

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

* docs: update AGENTS.md for secrets API routes

- Document the agent-server secrets CRUD routes in MSW handlers list
- Update git provider token persistence note to reflect server-side storage

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

* fix: update secret name validation to match agent-server requirements

- Change pattern from '^\S*$' (no whitespace) to '^[a-zA-Z][a-zA-Z0-9_]{0,63}$'
- Add title prop to SettingsInput component for validation error messages
- Secret names must: start with letter, contain only letters/numbers/underscores, be 1-64 chars

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

* feat: include custom secrets in conversation requests via LookupSecret

Custom secrets configured in Settings > Secrets are now automatically
included in conversation start requests. Instead of exposing secret values
to the frontend, we use LookupSecret entries that point to the agent-server
endpoint /api/settings/secrets/{name}. The agent-server fetches the actual
values at runtime.

Changes:
- Add LookupSecret interface to agent-server-adapter.ts
- Add customSecrets option to StartConversationOptions
- Build LookupSecret entries for each custom secret in buildStartConversationRequest
- Update buildStartConversationRequestWithEncryptedSettings to fetch and include
  custom secrets list from SecretsService.getSecrets()
- Include X-Session-API-Key header in LookupSecret when configured

This ensures secrets never touch the frontend in plaintext while still
making them available to conversations.

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

* fix: address review comments - no localStorage fallback, retry logic, SDK docs

Review feedback addressed:
1. secrets-service.ts: Server storage MUST succeed before updating localStorage
   - addGitProvider now stores to server FIRST, only updates localStorage on success
   - createSecret/updateSecret/deleteSecret now throw on failure (no silent returns)
   - Added retry logic with exponential backoff for all API calls

2. settings-service.api.ts: No silent fallback for encrypted settings
   - getSettingsForConversation now throws if encrypted fetch fails
   - Conversations should not start with broken/redacted credentials
   - Added retry logic with exponential backoff

3. AGENTS.md: Document SDK dependency
   - Settings persistence APIs require SDK PR #3060
   - Until released, npm run dev defaults to main branch
   - Documented git provider storage design (server + localStorage)

4. dev-safe.mjs: Default to SDK main branch
   - Added DEFAULT_GIT_REF='main' constant
   - npm run dev now uses main until settings APIs are released
   - TODO comment to update once released

Note: Git provider tokens still use localStorage for frontend git API calls
(repo search, branches), but MUST succeed on server first.

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

* fix: update server secret when only host changes

When updating just the host (empty token), the server secret's description
must also be updated to keep metadata in sync. Previously, only localStorage
was updated, violating the 'server storage must succeed first' principle.

Now the host-only update path also calls createSecret() to update the
server secret's description before updating localStorage.

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-05 20:39:46 -04:00
Rohit Malhotraandopenhands 6fa219cf25 feat: use uvx for temporary agent-server installation in dev mode (#99)
* feat: use uvx for temporary agent-server installation in dev mode

- Replace direct agent-server CLI invocation with uvx temporary install
- Add OH_AGENT_SERVER_VERSION env var for specific PyPI versions
- Add OH_AGENT_SERVER_GIT_REF env var for git commits/branches
- Auto-install uv in .openhands/setup.sh if not present
- Update documentation (README, DEVELOPMENT.md, AGENTS.md)
- Add comprehensive tests for buildAgentServerCommand()

This removes the requirement to permanently install agent-server via
'uv tool install'. Users only need uv installed, and npm run dev will
automatically download and run the appropriate agent-server version.

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

* fix: use subdirectory syntax for git ref in uvx monorepo

The software-agent-sdk is a uv workspace monorepo with packages in
subdirectories (openhands-agent-server/, openhands-tools/, etc.).

When installing from git, uvx requires the #subdirectory= fragment to
specify which package to install from the workspace.

Tested with: OH_AGENT_SERVER_GIT_REF=main npm run dev

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

---------

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-05 13:14:14 -04:00
Hiep Le e90db6fa53 feat(frontend): browser-side git provider integrations (#96)
* feat: browser-side git provider integrations

* feat: add workspaces tab for launching v1 conversations from local folders
2026-05-05 22:44:11 +07:00
Hiep Le 5d85eb0f5d fix: default v1 conversation title (#91) 2026-05-05 01:39:37 +07:00
Hiep Le 1cc616921f feat(frontend): isolate per-conversation working directories (#90)
* feat: isolate per-conversation working directories

* fix: failing tests
2026-05-05 01:32:24 +07:00
Hiep Le ba1d192f92 refactor: remove sandbox concept (#89) 2026-05-04 22:21:02 +07:00
Hiep Le dd8a44231f fix(frontend): remove SaaS and enterprise terminology (#88)
* fix: remove SaaS and enterprise terminology

* refactor: remove unrelated file
2026-05-04 21:27:45 +07:00
Hiep Le c27acde8a0 refactor: remove organization concept (#83) 2026-05-04 20:02:32 +07:00
Graham Neubigandopenhands 25510608a1 Fix scoped UI root foreground inheritance (#66)
Restore the default foreground color on the themed AgentServerUIRoot wrapper so inherited text and currentColor icons match the pre-scoping dark theme again.

Co-authored-by: openhands <openhands@all-hands.dev>
2026-05-01 12:20:17 -07:00
Graham Neubigandopenhands 8a8288d3f6 Default working dir to workspace/project (#63)
Co-authored-by: openhands <openhands@all-hands.dev>
2026-04-30 22:55:49 -07:00