feat(compact): expose upload_file - #2678
Conversation
|
@alectimison-maker is attempting to deploy a commit to the esokullu's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Exposes a platform-specific upload_file workflow to Compact Act mode across Chrome and Firefox.
Changes:
- Adds narrow Compact upload schemas and prompt guidance.
- Preserves Ask mode and excludes download workflows.
- Adds cross-browser tool-boundary and guidance tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/chrome/src/agent/tools.js |
Adds Chrome Compact upload support. |
src/firefox/src/agent/tools.js |
Adds Firefox Compact upload and picker support. |
test/run.js |
Tests Compact upload schemas, prompts, and boundaries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 'click', 'type_text', 'press_keys', | ||
| 'navigate', 'new_tab', 'wait_for_element', | ||
| 'fetch_url', | ||
| 'upload_file', |
| 'click', 'type_text', 'press_keys', | ||
| 'navigate', 'new_tab', 'wait_for_element', | ||
| 'fetch_url', | ||
| 'upload_file', |
|
PR 2678 — feat(compact): expose upload_file What it does: adds upload_file to COMPACT_TOOL_NAMES in both browsers, and rewrites the tool schema for the compact tier only (via compactUploadFileTool) so the model sees a narrower parameter set — Chrome: selector/attachmentId/filePath; Firefox: selector/attachmentId. downloadId is hidden in both. Compact prompts get a matching upload_file line, and the attachment-notice test flips to expect upload guidance in compact. The tier-scoped schema override is a nice pattern — the notice builder (agent.js:20313) already derives canUseUploadTool from the live tool catalog, so the [UNTRUSTED USER ATTACHMENTS] handles start appearing in compact automatically with no extra wiring. Blocking: compact has no way out of the ambiguous-selector gate upload_file sets a per-tab recovery latch on an ambiguous selector, and the only thing that clears it is a successful get_interactive_elements returning a file-input record:
get_interactive_elements is not in COMPACT_TOOL_NAMES (tools.js:1697-1705). So in compact, one ambiguous selector permanently bricks uploads for that tab until a page replacement, and the error text instructs the model to call a tool it doesn't have — the exact "point at an unavailable tool" problem the PR's schema work is trying to avoid. Also note agent.js:17028 (input-not-found) names get_interactive_elements and get_accessibility_tree; the latter is in compact, so that one is only half-wrong. Pick one:
Either way it needs a test — the new test only asserts schema/prompt shape, never exercises the handler. Security: drop filePath from the Chrome compact schema Compact has no downloads, no list_downloads, no read_downloaded_file — so there is no legitimate in-run source for a local path other than the user literally typing one. Meanwhile compact drops the full-tier hardening that exists precisely to stop invented paths (tools.js:1562, the /Users/Shared/… failure note). filePath on Chrome is a CDP-backed arbitrary local-file read that lands in a page input on an untrusted site; compact Act is also the tier most exposed to page-content injection. The schema string "explicitly supplied by the user" is guidance, not enforcement. Recommendation: make compact attachmentId-only on Chrome, matching Firefox. That is a one-line schema change and the compact prompt line loses |filePath. If you keep it, add an explicit "never construct or guess a path; only a path the user typed in this conversation" clause. Related, weaker point: hiding downloadId from the compact schema is prompt-level only — _executeTool still honors it if the model emits it. Harmless today (no downloadIds exist in compact), but it's a soft boundary, not a real one, and the test name (must hide downloadId) reads stronger than what's enforced. Smaller notes
|
An ambiguous selector latches upload_file until get_interactive_elements returns a verified file-input selector, and nothing else clears it. That tool was not in the compact catalog, so one ambiguous selector left compact unable to upload for the rest of the page's life while the handler kept asking for a tool the model had not been given. Compact now carries get_interactive_elements, and the tool description and prompt bullet name it as the recovery path. A test asserts the coupling for every tier that ships upload_file. Compact also no longer advertises filePath. It has no download tools, so the only file it can legitimately reach is the one the user attached to this run; a path could only come from the model inventing one, and on Chrome filePath is a CDP-backed read of any local file into an untrusted page's input. Hidden parameters are now deleted from the base schema rather than rebuilt, so a future upload_file parameter still reaches compact. Prompt assertions moved off character-distance regexes onto the upload_file bullet itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The ambiguity test proved the latch clears but stopped there. Assert the step it exists for: after get_interactive_elements supplies a unique selector, the corrected upload dispatches and leaves the latch clear. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Pushed three commits to this branch addressing the ambiguity dead-end and tightening the compact schema. Copilot flagged the same recovery problem on both The dead-end. An ambiguous selector latches I checked whether the latch could clear on something compact already had. It can't: So it's in
While there I switched the transform from rebuilding Tests. The character-distance regexes ( Copilot also asked for coverage of the ambiguous-selector retry itself. The existing handler test proved the latch clears but stopped there, so I extended it through the step the recovery exists for: after the inspection supplies a unique selector, the corrected upload dispatches and leaves the latch clear. Full suite 1451 passed, security corpus 60/60. The one failure is the pre-existing One judgment call worth a second opinion: adding |
|
Thanks for the detailed review and the follow-up commits. I reviewed the current head (
I reran the repository test runner (1,453 passed, with only the existing package/CHANGELOG version mismatch), the security corpus (60/60), syntax checks, and |
Problem
Compact Act receives user-attachment handles, but it could not attach them to a page file input. Exposing
upload_filealone was not sufficient: an ambiguous selector latches the handler untilget_interactive_elementsreturns a verified file-input selector, and Chrome's full upload schema also exposes local-path and download inputs that Compact cannot safely source.Closes #413.
Change
upload_fileand itsget_interactive_elementsrecovery path in Compact Act for Chrome and FirefoxdownloadIdandfilePathChrome Compact accepts a current user
attachmentId. Firefox accepts a currentattachmentIdor opens WebBrain's existing user-controlled picker. Ask remains read-only, and Compact still has no download tools.Safety and scope
The schema override deletes hidden properties from a clone of the base schema rather than rebuilding it manually, so future safe base parameters continue to propagate. Compact cannot supply
filePathordownloadId, and the prompt does not claim that attaching a file to an input proves remote upload or submission.No handler semantics or public API are changed. The added recovery tool exposes an existing inspection capability because
upload_filealready depends on it.Validation
node test/run.js? 1,453 passed; the only failure is the pre-existingpackage.json26.0.10 vsCHANGELOG.md26.0.0 assertionnode test/security/injection-corpus.mjs? 60/60 passednode --checkfor the changed Chrome/Firefox tool modules andtest/run.js? passedgit diff --check? passed