feat(agent-server): add include_hidden to file browser endpoints#3740
feat(agent-server): add include_hidden to file browser endpoints#3740xingyaoww wants to merge 1 commit into
Conversation
The folder/file browser endpoints (/api/file/search_subdirs and /api/file/home) unconditionally skip dot-entries, so GUIs built on them cannot browse or select hidden directories (e.g. ~/.config). Add an optional include_hidden query param (default False, so existing behavior is unchanged) to both endpoints. When true, dot-directories are listed; files and symlinks are still skipped. Co-authored-by: openhands <openhands@all-hands.dev>
Python API breakage checks — ✅ PASSEDResult: ✅ PASSED |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
all-hands-bot
left a comment
There was a problem hiding this comment.
⚠️ QA Report: PASS WITH ISSUES
Functional QA passed: the running agent-server now exposes hidden directories only when include_hidden=true, while default behavior still omits them.
Does this PR achieve its stated goal?
Yes. I started the actual agent-server and made real HTTP requests against /api/file/search_subdirs and /api/file/home before and after the PR. On origin/main, adding include_hidden=true still omitted dot-directories; on commit ad0f28e8, the same requests returned .hidden_repo and .config only with the opt-in flag, while files and symlinks remained excluded.
| Phase | Result |
|---|---|
| Environment Setup | ✅ make build completed and installed the uv workspace dependencies. |
| CI Status | Validate PR description failed. |
| Functional Verification | ✅ Real HTTP requests verified both changed endpoints and unchanged defaults. |
Functional Verification
Test 1: /api/file/search_subdirs hidden directory opt-in
Step 1 — Reproduce / establish baseline without the fix:
Checked out origin/main, created a real directory containing projects/, .hidden_repo/, README.md, and a symlink, then started the server with:
HOME=/tmp/file-browser-qa-base/home OPENHANDS_SUPPRESS_BANNER=1 uv run agent-server --host 127.0.0.1 --port 8765Ran:
curl 'http://127.0.0.1:8765/api/file/search_subdirs?path=%2Ftmp%2Ffile-browser-qa-base%2Fsearch'
curl 'http://127.0.0.1:8765/api/file/search_subdirs?path=%2Ftmp%2Ffile-browser-qa-base%2Fsearch&include_hidden=true'Observed both responses returned only the visible directory:
{
"items": [
{"name": "projects", "path": "/tmp/file-browser-qa-base/search/projects"}
],
"next_page_id": null
}This establishes the prior behavior: even when a client sent include_hidden=true, hidden directories were not listed.
Step 2 — Apply the PR's changes:
Checked out ad0f28e881ee8e6c8182bb4257f31f2370046357 and recreated the same fixture shape under /tmp/file-browser-qa-pr/search.
Step 3 — Re-run with the fix in place:
Ran the equivalent requests against the PR server. Default behavior still omitted hidden entries:
{
"items": [
{"name": "projects", "path": "/tmp/file-browser-qa-pr/search/projects"}
],
"next_page_id": null
}With include_hidden=true, the hidden directory appeared and the file/symlink stayed excluded:
{
"items": [
{"name": ".hidden_repo", "path": "/tmp/file-browser-qa-pr/search/.hidden_repo"},
{"name": "projects", "path": "/tmp/file-browser-qa-pr/search/projects"}
],
"next_page_id": null
}This confirms the new opt-in behavior works and the backward-compatible default is preserved.
Test 2: /api/file/home hidden favorite opt-in
Step 1 — Reproduce / establish baseline without the fix:
On origin/main, started the server with HOME=/tmp/file-browser-qa-base/home where the home directory contained Documents/, .config/, readme.txt, and a symlink.
Ran:
curl 'http://127.0.0.1:8765/api/file/home'
curl 'http://127.0.0.1:8765/api/file/home?include_hidden=true'Observed both responses returned only Documents in favorites:
{
"home": "/tmp/file-browser-qa-base/home",
"favorites": [
{"label": "Documents", "path": "/tmp/file-browser-qa-base/home/Documents"}
],
"locations": [{"label": "/", "path": "/"}]
}This confirms the old endpoint could not opt into hidden home favorites.
Step 2 — Apply the PR's changes:
Checked out ad0f28e881ee8e6c8182bb4257f31f2370046357 and recreated the same fixture shape under /tmp/file-browser-qa-pr/home.
Step 3 — Re-run with the fix in place:
Default behavior still returned only the visible favorite:
{
"home": "/tmp/file-browser-qa-pr/home",
"favorites": [
{"label": "Documents", "path": "/tmp/file-browser-qa-pr/home/Documents"}
],
"locations": [{"label": "/", "path": "/"}]
}With include_hidden=true, .config appeared before Documents, while the file and symlink stayed excluded:
{
"home": "/tmp/file-browser-qa-pr/home",
"favorites": [
{"label": ".config", "path": "/tmp/file-browser-qa-pr/home/.config"},
{"label": "Documents", "path": "/tmp/file-browser-qa-pr/home/Documents"}
],
"locations": [{"label": "/", "path": "/"}]
}This confirms /api/file/home now supports the same hidden-directory opt-in behavior as the search endpoint.
Issues Found
- 🟡 Non-functional CI issue:
Validate PR descriptionis failing with:A human must check A human has tested these changes.andAdd a short human-written note between HUMAN: and the human-tested checkbox.Per repo policy, a human author needs to update those human-only PR description fields.
No functional issues found in the changed behavior.
This QA review was created by an AI agent (OpenHands) on behalf of the user.
HUMAN:
AGENT:
Why
The agent-server file browser endpoints
GET /api/file/search_subdirsandGET /api/file/homeunconditionally skip dot-entries (entry.name.startswith(".")). GUIs built on these endpoints (e.g. agent-canvas' workspace picker) therefore cannot browse or select hidden directories such as~/.config,~/.ssh, or a hidden repo. There was no server-side way to opt in to seeing them.This is the backend half of "Option B" for OpenHands/agent-canvas — letting users add a hidden directory as a workspace via a "Show hidden folders" toggle.
Summary
include_hiddenquery param (defaultFalse) toGET /api/file/search_subdirs. Whentrue, dot-directories are listed; files and symlinks are still skipped.include_hiddenparam toGET /api/file/homeso hidden top-level directories can appear infavorites.include_hidden=False), so this is fully backward-compatible — no existing client is affected.Issue Number
Relates to OpenHands/agent-canvas hidden-workspace support (Option B).
How to Test
Manual:
Evidence (local run):
uv run pytest tests/agent_server/test_file_router.py -q→28 passed(incl. newtest_search_subdirs_include_hidden_lists_dot_directoriesandtest_get_home_include_hidden_lists_hidden_favorites).uv run ruff check/ruff format --check→ clean.Type
Notes
Follow-up wiring (separate PRs):
@openhands/typescript-client: forwardinclude_hiddenfromFileClient.searchSubdirectories(extendFileSearchSubdirsOptions) and accept it ongetHome; release a new version.includeHiddenthroughuseSearchSubdirs/useHomeDirectory.This PR was created by an AI agent (OpenHands) on behalf of the user.
Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.13-nodejs22-slimgolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:ad0f28e-pythonRun
All tags pushed for this build
About Multi-Architecture Support
ad0f28e-python) is a multi-arch manifest supporting both amd64 and arm64ad0f28e-python-amd64) are also available if needed