Skip to content

Add skill file upload to agent resources panel#677

Open
SajalChaplot wants to merge 4 commits into
mainfrom
ai_main_22449b4f97c8409686c0
Open

Add skill file upload to agent resources panel#677
SajalChaplot wants to merge 4 commits into
mainfrom
ai_main_22449b4f97c8409686c0

Conversation

@SajalChaplot
Copy link
Copy Markdown

@SajalChaplot SajalChaplot commented May 13, 2026

Summary

Adds the ability for users to upload existing SKILL.md files 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 CreateMenu component, triggered by a new "Upload Skill" menu option. Selected .md files are uploaded via the existing useUploadResource hook, placed under the skills/<slug>/SKILL.md path with the appropriate scope.

Key Changes

  • Added a hidden <input type="file"> (accepting .md/text/markdown, supports multiple) wired to a skillFileInputRef
  • Introduced handleUploadSkillFiles handler that slugifies the filename, builds a FormData payload, and calls uploadResource.mutate for each selected file
  • Added an "Upload Skill" entry (with upload icon) to the CreateMenu action list, triggering the file picker on click
  • Updated active tab background color in onboarding-html.ts from #1e1e1e to #3a3a3a for improved contrast

Edit in Builder  Preview


To clone this PR locally use the Github CLI with command gh pr checkout 677

You can tag me at @BuilderIO for anything you want me to fix or change

@builder-io-integration builder-io-integration Bot changed the title Update from the Builder.io agent Add skill file upload to agent resources panel May 13, 2026
@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@builder-io-integration builder-io-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.md and Scheduler.md
  • Both files get slugified to uploaded-skill (as they're not literally named SKILL.md, they should generate unique slugs)
  • But wait — any file literally named SKILL.md from a folder export would collide with ALL other SKILL.md uploads from the same user to the same resource path

🧪 Browser testing: Will run after this review (PR touches UI code)

Comment on lines +291 to +299
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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.

Fix in Builder

Or react with 🚀 to auto-fix.

Copy link
Copy Markdown
Contributor

@builder-io-integration builder-io-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual Verification

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.

@steve8708
Copy link
Copy Markdown
Contributor

@SajalChaplot doesn't standard file upload work for this? iirc you can upload a file and just make its path skills/skill-name/SKILL.md or does that not work?

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

@SajalChaplot
Copy link
Copy Markdown
Author

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.

@SajalChaplot
Copy link
Copy Markdown
Author

Sent a pr in hope of testing ui on deployed link. Sometimes it works better than in-app previews

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot fix the failing changeset CI

@builder-io-integration
Copy link
Copy Markdown
Contributor

This is the required changeset file per the repo's CI convention (the Require changeset for publishable package changes job is failing because packages/core was modified without one). Per CLAUDE.md: every PR touching packages/core must include a .changeset/<slug>.md. Created code/.changeset/upload-skill-file.md to unblock the failing check.



🟢 Added changeset to fix the failing changeset CI check

@netlify

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@builder-io-integration builder-io-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual Verification

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.

Copy link
Copy Markdown
Contributor

@builder-io-integration builder-io-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.mdskills/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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants