Add skill file upload to agent resources panel#677
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🔴
Review Details
Code Review Summary
This PR adds file upload functionality to the agent resources panel, allowing users to import existing .md skill files directly alongside creating new skills. The implementation reuses the existing useUploadResource hook and follows established patterns in the codebase for file handling.
The PR also includes a minor visual tweak to the onboarding UI (tab background color improvement from #1e1e1e to #3a3a3a).
Risk Assessment
Low risk — UI-only feature with no database migrations, API changes, or breaking changes.
Key Findings
🔴 Data-Loss Bug (HIGH): The upload handler maps all files literally named SKILL.md to the same destination path (skills/uploaded-skill/SKILL.md). When users multi-select multiple skill files, the server's resourcePut() function uses ON CONFLICT (path, owner) DO UPDATE, which silently overwrites earlier uploads with later ones. This is the exact workflow this PR enables, making it a critical bug.
Example scenario:
- User selects two exported skill files:
TaskMgr.mdandScheduler.md - Both files get slugified to
uploaded-skill(as they're not literally namedSKILL.md, they should generate unique slugs) - But wait — any file literally named
SKILL.mdfrom a folder export would collide with ALL otherSKILL.mduploads from the same user to the same resource path
🧪 Browser testing: Will run after this review (PR touches UI code)
| const baseName = file.name.replace(/\.[^./]+$/, ""); | ||
| const slug = slugifyName( | ||
| baseName.toLowerCase() === "skill" ? "uploaded-skill" : baseName, | ||
| ); | ||
| const formData = new FormData(); | ||
| formData.append("file", file); | ||
| formData.append("path", `skills/${slug}/SKILL.md`); | ||
| formData.append("shared", scope === "shared" ? "true" : "false"); | ||
| uploadResource.mutate(formData); |
There was a problem hiding this comment.
🔴 Multiple SKILL.md file uploads silently overwrite each other
When a user selects multiple skill files (especially if they're all named SKILL.md from folder exports), the handler maps them to the same destination path: skills/uploaded-skill/SKILL.md. The backend's resourcePut() upserts by (path, owner), so later uploads silently overwrite earlier ones, causing data loss. Generate unique paths per file (e.g., via UUID suffix, counter, or nanoid) to prevent collisions.
Or react with 🚀 to auto-fix.
There was a problem hiding this comment.
Browser testing: 8/9 passed
Test Results: 8/9 passed ⚠️
✅ TC-01: ResourcesPanel loads and "Upload Skill" appears in CreateMenu (succeeded)
URLs tested: http://localhost:8080/dispatch, http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
✅ TC-02: Full CreateMenu layout — all 7 items in correct order (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
✅ TC-03: Upload Skill icon renders correctly (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 1 screenshot captured
⚠️ TC-04: File picker triggered when "Upload Skill" is clicked (couldnt_verify)
Steps: 1. Opened CreateMenu. 2. Clicked Upload Skill item. 3. Checked for dialog via handle_dialog (not triggered — native file pickers are not JS dialogs). 4. Re-tried via DOM click and Enter. Menu stayed open (expected by design).
Failure: feature_not_reachable — Clicking Upload Skill triggers skillFileInputRef.current?.click() which opens a native OS file dialog — unreachable by headless browser automation. Menu staying open is correct per source (setOpen(false) only called after file selection in handleUploadSkillFiles). TC-05 confirms the wired file input exists with correct accept/multiple attrs.
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 1 screenshot captured
✅ TC-05: Hidden file input has correct attributes (.md accept, multiple) (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 1 screenshot captured
✅ TC-06: Onboarding tab active state shows #3a3a3a background (improved contrast) (succeeded)
URLs tested: http://localhost:8080/dispatch
Evidence: 1 screenshot captured
✅ TC-07: CreateMenu dismisses cleanly on Escape (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 3 screenshots captured
✅ TC-08: Regression — "Create Skill" option still works after Upload Skill addition (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
✅ TC-09: Regression — Agent panel Chat and Settings tabs remain functional (succeeded)
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 4 screenshots captured
Details
PR #677 (Upload Skill feature) passed 8/9 test cases with visual evidence. TC-04 (native file picker confirmation) is a known automation limitation — not a product bug. All functional, icon, menu layout, color, and regression tests passed.
|
@SajalChaplot doesn't standard file upload work for this? iirc you can upload a file and just make its path i'm not 100% convinced making this a top level line item is the right place for it. maybe when you choose "create skill" show an upload option there? this top level menu is already large and i'm hesitatnt to keep packing it with more things, vs put it under the existing skill creation option |
|
Yes, I can include it withing create skill. Upload file for uploading skill is not intuitive given, everywhere there is an upload option with create skill. I actually wanted it to include it in the create skill, but Auth issues didn't let me test out the UI. Which is why I didn't add you as reviewer yet. |
|
Sent a pr in hope of testing ui on deployed link. Sometimes it works better than in-app previews |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@builderio-bot fix the failing changeset CI |
|
This is the required changeset file per the repo's CI convention (the ⠀ |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Browser testing: 5/5 passed
Test Results: 5/5 passed ✅
✅ TC-01: ResourcesPanel loads and CreateMenu contains "Upload Skill" (succeeded)
Steps: 1. Navigated to /dispatch and created a new account. 2. Opened the agent panel and switched to Workspace mode. 3. Clicked the CreateMenu (+) button and confirmed "Upload Skill" was present in the popover.
URLs tested: http://localhost:8080/dispatch, http://localhost:8080/dispatch/overview
Evidence: 3 screenshots captured
✅ TC-02: CreateMenu shows all 7 items in the correct order (succeeded)
Steps: 1. Opened the Workspace panel. 2. Confirmed the CreateMenu popover was open. 3. Extracted menu item labels from the popover and verified their order.
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
✅ TC-05: Hidden skill file input has correct attributes (accept=".md" and multiple) (succeeded)
Steps: 1. Kept the ResourcesPanel open. 2. Inspected the hidden file input via JavaScript (querySelector). 3. Verified accept=".md,text/markdown" and multiple=true.
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
✅ TC-06: Sign-in page active tab has background color #3a3a3a (succeeded)
Steps: 1. Opened /dispatch in an isolated browser context. 2. Read computed background-color of .tab.active on "Create account". 3. Clicked "Sign in" tab and re-verified active/inactive colors.
URLs tested: http://localhost:8080/dispatch
Evidence: 3 screenshots captured
✅ TC-08: "Create Skill" option opens the skill creation sub-view (succeeded)
Steps: 1. Opened the Workspace panel and CreateMenu. 2. Clicked "Create Skill". 3. Confirmed popover changed to the "Create Skill" sub-view with the prompt composer visible.
URLs tested: http://localhost:8080/dispatch/overview
Evidence: 2 screenshots captured
Details
All 5 incremental smoke tests for PR #677 passed. No regressions detected after documentation-only changes to ResourcesPanel.tsx.
There was a problem hiding this comment.
Builder reviewed your changes — no new findings
Review Details
Incremental Code Review — PR #677
The PR has been updated with a .changeset/upload-skill-file.md file and minor documentation edits in ResourcesPanel.tsx. The core feature code remains unchanged.
Changes Since Last Review
✅ Changeset Added: .changeset/upload-skill-file.md is properly formatted with @agent-native/core: minor bump and accurate description of the feature.
📝 Documentation Updated: Added "Workspace files" section to ResourcesPanel explaining workspace resources vs. agent-created scratch resources (no functional impact).
🔴 Critical Issue Status: The HIGH severity data-loss bug identified in the previous review remains unfixed.
Data-Loss Bug Still Present
Lines 296-304 in packages/core/src/client/resources/ResourcesPanel.tsx still have the collision issue:
Multiple skill files with identical base names (or the same filename from different folders) will be saved to the same path and overwrite each other:
- File
SKILL.md→skills/uploaded-skill/SKILL.md - File
SKILL.md(again) →skills/uploaded-skill/SKILL.md(overwrites first)
The backend's resourcePut() function uses ON CONFLICT (path, owner) DO UPDATE, silently replacing earlier uploads.
This is the exact workflow the PR enables, making it a critical data-loss issue that must be fixed before merge.
Browser Testing
✅ Incremental smoke test passed — All 5 key test cases passed with no regressions:
- ResourcesPanel loads + Upload Skill menu option visible
- Full 7-item CreateMenu layout intact
- Hidden file input properly configured
- Onboarding tab color (#3a3a3a) displaying correctly
- Create Skill regression path functional
🧪 Browser testing: Complete — no visual regressions detected
Status: 🔴 Blocking — The data-loss bug from the previous review is still present and must be fixed before merge.
Summary
Adds the ability for users to upload existing
SKILL.mdfiles directly into the agent's resources panel, alongside a minor visual tweak to the active tab style in the onboarding UI.Problem
Previously, users could only create new skills from scratch via the resources panel. There was no way to import or reuse an existing skill file, making it cumbersome to bring in pre-built agent skills.
Solution
A hidden file input is added to the
CreateMenucomponent, triggered by a new "Upload Skill" menu option. Selected.mdfiles are uploaded via the existinguseUploadResourcehook, placed under theskills/<slug>/SKILL.mdpath with the appropriate scope.Key Changes
<input type="file">(accepting.md/text/markdown, supports multiple) wired to askillFileInputRefhandleUploadSkillFileshandler that slugifies the filename, builds aFormDatapayload, and callsuploadResource.mutatefor each selected fileCreateMenuaction list, triggering the file picker on clickonboarding-html.tsfrom#1e1e1eto#3a3a3afor improved contrastTo clone this PR locally use the Github CLI with command
gh pr checkout 677You can tag me at @BuilderIO for anything you want me to fix or change