The file router can read directories (search_subdirs, home) but has no way to
create one — the only mkdir is the incidental parent-creation inside
_upload_file. A GUI folder picker therefore cannot offer 'New Folder': the user
has to leave the app and mkdir by hand before a directory is selectable.
Adds an explicit endpoint mirroring _upload_file's posture: absolute-path
check, parents=True, exist_ok=True so repeat calls are idempotent, and 400
rather than 500 when the path exists as a file or sits under one.
HUMAN:
Fully tested and working for me
AGENT:
End-to-end evidence (not just unit tests): the agent-server was started from this branch on
:18923and driven over real HTTP through a locally built@openhands/typescript-clientwith a hand-writtencreateDirectorycaller. Verified live: creating a nested directory with a space in the name (confirmed on disk), a repeat call against the same path (idempotent, contents untouched), the new directory immediately visible toGET /api/file/search_subdirs(the folder picker's own listing endpoint), create-over-existing-file → 400, and relative path → 400. Unit:tests/agent_server/test_file_router.py85/85 (7 new),ruffclean,make test-server-schemapasses (OpenAPI determinism + quality + swagger validate).Why
The OpenHands frontend's workspace folder picker cannot create a directory — there is no directory-creation endpoint anywhere in the file API, so a "New Folder" button has nothing to call (OpenHands/OpenHands#16561). The only stock mechanism that materializes a directory is
_upload_file's incidentalmkdirof the target's parent, which collapses all failures to 500 and can't clean up after itself (no file-delete endpoint exists).Summary
POST /api/file/create_directory?path=<abs>:mkdir(parents=True, exist_ok=True)viaasyncio.to_thread(same offload pattern as_upload_file), idempotent on repeat calls.search_subdirs).chmod 0o500with root skip, missing path param).Issue Number
OpenHands/OpenHands#16561
How to Test
Run the agent-server from this branch, then:
Or just
uv run pytest tests/agent_server/test_file_router.py(85 tests).Video/Screenshots
Type
Notes
Purely additive endpoint; no existing contract changes, so no deprecation runway is engaged. Companion typescript-client change (
FileClient.createDirectory) is ready and will follow once this lands in an agent-server release, per the release-train dependency. Design alternatives considered and rejected are documented on the linked issue (upload-.keepshim, bashmkdir).