Repository navigation
feat(files): download and upload files from the path picker - #631
Draft
shenlvkang-collab wants to merge 2 commits into
Draft
shenlvkang-collab wants to merge 2 commits into
shenlvkang-collab wants to merge 2 commits into
Conversation
The path picker (mobile Path key) is the fast way to browse: one folder per request, any allowed root. It could not move files, so the Files panel was still needed for that, and a desktop browser could not reach the picker at all. - GET /api/filesystem/download: any regular file the picker can list, sent as an attachment. - POST /api/filesystem/upload: one multipart file into the folder on screen. Same-origin check (shared with paste-image), per-IP rate bucket, bounded folder probe, sanitized basename, blocked-name check, O_EXCL|O_NOFOLLOW creation with " (n)" suffixes (never overwrites, never follows a planted symlink), partial files unlinked. 1GB cap (CODEMAN_MAX_PICKER_UPLOAD_BYTES). - Both resolve through resolveFilesystemPickerPath(), so they reach exactly what browse can list, including the multi-user root scoping. - Picker `fileTransfer` option: a download link per file row and an Upload button (multi-select, XHR progress) that reloads the folder and selects the last upload. On for the Path key and the new quick-browser button in the Files panel header; Link Existing stays browse-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The key already exists further down the table; an object literal keeps the last one, so the first copy was dead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The path picker (the mobile keyboard's 📁 Path key) is the fast way to browse files: one folder per request, any allowed root, previews, typed-path jump, sort. It could not move files, though, so the Files panel was still needed for that, and a desktop browser could not open the picker at all. This PR fills both gaps.
GET /api/filesystem/download). Any regular file the picker can list is sent as an attachment and never rendered.POST /api/filesystem/upload, multipart fieldfile). XHR shows progress; afterwards the folder reloads and the last upload is selected, so Insert Path puts it on the prompt in one tap.fileTransferpicker option: on for the Path key and the Files panel button. Link Existing stays browse-only, and so does afetchListing(container) picker.Safety
resolveFilesystemPickerPath(): allowlisted roots, realpath containment, the hidden-entries opt-in,isBlockedPickerPath, thesessionIdownership check and multi-user root scoping. They reach exactly what browse can list.isSameOriginMultipartRequest()helper with unchanged behaviourcredentials.jsonor a key file is refusedO_CREAT|O_EXCL|O_NOFOLLOWcreation with(n)suffixes: it never overwrites and never follows a planted symlinkCODEMAN_MAX_PICKER_UPLOAD_BYTES)Validation
test/routes/filesystem-transfer.test.ts(24 tests, real temp dirs). Download covers: allowed file, a path outside the roots, a symlink escape, a sensitive file, a folder. Upload covers: writes and returns the path, never overwrites, does not follow a planted symlink, strips path components, refuses an out-of-root folder, a sensitive name, a cross-site request, an unknown session and the wrong field. Plus the name sanitizer.npm run typecheck,npm run lint, Prettier andcheck:frontend-syntaxpass.npm testlocally: 11179 passed. The only failures were the 4 spreadsheet/public-asset files, which need the exceljs vendor assets that this worktree'snode_moduleslacked.CODEMAN_INSTANCE), 19 checks, desktop 1400px and phone 412px:readme (1).txt), and the listing refreshes and selects the uploadCODEMAN_FILE_PICKER_ROOTS) and for Home.Docs:
CLAUDE.mdpath-picker bullet,docs/architecture-invariants.md#filesystem-path-picker,docs/wiki/Working-With-Files.md. Changeset: minor.🤖 Generated with Claude Code