-
Notifications
You must be signed in to change notification settings - Fork 1k
upload method for stagehand #1037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Removed the file download function from the upload example, simplifying the process by allowing direct URL uploads. - Integrated dotenv for environment variable management. - Updated the upload method to handle URLs directly, downloading files as needed. - Improved error messages for better debugging and user feedback. - Adjusted logging to provide clearer insights into the upload process.
- Set the environment to "BROWSERBASE" in the Stagehand initialization. - Enhanced debugging by adding console logs for element evaluation in the file input check.
🦋 Changeset detectedLatest commit: bce40bc The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Summary
This PR introduces file upload functionality to Stagehand, addressing a significant capability gap in the web automation library. The implementation adds a new upload()
method that accepts natural language instructions to locate file inputs and supports multiple file sources including URLs, local file paths, and in-memory buffers.
The core architecture employs a three-tier fallback strategy: first attempting direct file input detection, then triggering file choosers, and finally using heuristic search to find associated upload controls. The method leverages Stagehand's existing observe()
functionality for AI-powered element detection, ensuring it works with complex scenarios like hidden inputs, iframes, and shadow DOM elements.
Key additions include new TypeScript types (FileSpec
and UploadResult
) that provide flexible file specification options and structured feedback about upload operations. The implementation handles URL fetching with automatic MIME type detection, processes files entirely in memory without temporary files, and maintains consistent behavior across both local and Browserbase environments.
The upload method integrates seamlessly with Stagehand's existing history tracking system, logging upload events for observability. An example test file demonstrates the intended usage pattern: providing natural language hints to identify upload elements, followed by standard form interactions.
Confidence score: 3/5
- This PR introduces complex new functionality with multiple execution paths that could fail in various edge cases
- Score reflects concerns about package.json changes that could break build processes and potential type definition issues in FileSpec
- Pay close attention to lib/package.json build configuration changes and types/stagehand.ts FileSpec type definition
4 files reviewed, 4 comments
types/stagehand.ts
Outdated
export type FileSpec = | ||
| string | ||
| { | ||
/** Absolute path on disk to the file. */ | ||
path?: string; | ||
/** Name to use for the file (required if using buffer). */ | ||
name?: string; | ||
/** MIME type for the file (required if using buffer). */ | ||
mimeType?: string; | ||
/** Raw file bytes (requires name + mimeType). */ | ||
buffer?: Buffer; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: FileSpec type allows invalid combinations like { name: 'file.txt' }
without buffer or path. Consider using discriminated unions to enforce valid combinations.
export type FileSpec = | |
| string | |
| { | |
/** Absolute path on disk to the file. */ | |
path?: string; | |
/** Name to use for the file (required if using buffer). */ | |
name?: string; | |
/** MIME type for the file (required if using buffer). */ | |
mimeType?: string; | |
/** Raw file bytes (requires name + mimeType). */ | |
buffer?: Buffer; | |
}; | |
export type FileSpec = | |
| string | |
| { | |
/** Absolute path on disk to the file. */ | |
path: string; | |
} | |
| { | |
/** Name to use for the file (required if using buffer). */ | |
name: string; | |
/** MIME type for the file (required if using buffer). */ | |
mimeType: string; | |
/** Raw file bytes (requires name + mimeType). */ | |
buffer: Buffer; | |
}; |
lib/index.ts
Outdated
(el): boolean => { | ||
const tagName = el.tagName.toLowerCase(); | ||
const type = (el as HTMLInputElement).type; | ||
console.log(`DEBUG: Element tagName=${tagName}, type=${type}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Debug console.log statements should be removed from production code
console.log(`DEBUG: Element tagName=${tagName}, type=${type}`); | |
const tagName = el.tagName.toLowerCase(); | |
const type = (el as HTMLInputElement).type; | |
return tagName === "input" && type === "file"; |
lib/index.ts
Outdated
}, | ||
) | ||
.catch((e) => { | ||
console.log(`DEBUG: evaluate failed:`, e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Debug console.log statements should be removed from production code
console.log(`DEBUG: evaluate failed:`, e); | |
.catch((e) => { | |
return false; | |
}); |
lib/package.json
Outdated
"main": "./index.js", | ||
"module": "./index.js", | ||
"types": "./index.d.ts", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Path change from '../dist/' to './' may break builds if corresponding build scripts haven't been updated. Verify that 'pnpm run build-js' outputs to lib/ instead of dist/.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Summary
This review covers only the changes made since the last review (commit 318aef5), not the entire PR. The recent changes focus on implementing the feedback from previous reviews regarding package.json path configuration and FileSpec type safety improvements.
The key changes include:
-
Package.json Path Correction: The entry points have been updated from
../dist/
back to./
paths (main, module, and types fields), which appears to address the build output concerns raised in the previous review about potential build script mismatches. -
FileSpec Type Safety Enhancement: The
FileSpec
type has been restructured to use proper discriminated unions as suggested in the previous review. The type now enforces three distinct valid combinations: string URLs, objects with requiredpath
property, or objects with requiredname
,mimeType
, andbuffer
properties. This prevents invalid partial combinations that could fail at runtime. -
Type Guard Implementation: The upload method implementation now includes proper type guards to safely handle the discriminated union FileSpec type, with consistent logic for extracting file names across all three upload strategies (input, chooser, fallback).
-
Debug Code Cleanup: Console.log statements have been removed from the production code as requested in previous reviews.
These changes address the type safety, build configuration, and code quality concerns identified in previous reviews while maintaining the core upload functionality. The implementation follows TypeScript best practices with discriminated unions and type guards to ensure compile-time safety for the flexible file specification system.
Confidence score: 4/5
- This PR addresses previous review feedback effectively with proper type safety and build configuration fixes
- Score reflects solid implementation of discriminated unions and removal of debug code, but package.json changes need verification
- Pay close attention to build scripts to ensure they output to the correct directory matching the package.json paths
3 files reviewed, no comments
@greptileai review again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Summary
This review covers only the changes made since the last review, not the entire PR. The latest changes focus on completing the upload functionality implementation with the addition of a test file and some final adjustments.
The changes add a new uploads.test.ts
file in the deterministic test suite that provides comprehensive testing for the new upload functionality. This test follows the established testing patterns in the codebase, using the same Stagehand
initialization approach with StagehandConfig
and proper setup/teardown hooks. The test verifies the upload feature by navigating to a test URL, locating a file input element, uploading a logo.png file, and asserting that both the file name and size are correctly displayed.
The test integrates well with the existing deterministic test infrastructure in the evals/deterministic/tests/browserbase/
directory, maintaining consistency with other Browserbase-specific tests. It uses standard Playwright testing patterns with locators and assertions, and follows the same asynchronous testing approach as other tests in the suite. The test validates the core upload functionality by checking that the uploaded file's metadata (name and non-zero size) is correctly processed and displayed, ensuring the upload method works as expected in a real browser environment.
Confidence score: 4/5
- This PR adds well-tested upload functionality with minimal risk of breaking existing features
- Score reflects solid implementation with proper testing coverage and integration with existing patterns
- The upload test file requires attention to ensure it aligns with the final API and file structure
3 files reviewed, no comments
stagehand upload method
why
stagehand could click, type, scrape… but uploads were messy.
no way to handle hidden inputs, chooser popups, urls, buffers.
no natural language → file input.
no clean support across local + browserbase.
so i built it.
what changed
1. new types
2. new api
observe
)UploadResult
3. file processing
4. integration
test plan
✅ done
🧪 next
notes
usage
impact
stagehand now does uploads properly.
handles messy real-world forms.
natural language → correct element.
works across environments.
less brittle, more useful.
opens up workflows like automated form filling + doc processing.
basically: it can now upload files.
p.s. also my first oss contribution