-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix: setInputFiles() not working on Browserbase
#1267
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
Merged
seanmcguire12
merged 5 commits into
main
from
seanmcguire/stg-973-fix-file-uploads-not-working
Nov 14, 2025
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
fda7c8c
fix file uploads for remote browsers
seanmcguire12 05c64b4
make sure test uses an actual file
seanmcguire12 0648c53
add tests for various file input shapes
seanmcguire12 7305fab
make NormalizedFilePayload a private type
seanmcguire12 6e1378c
fix import
seanmcguire12 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@browserbasehq/stagehand": patch | ||
| --- | ||
|
|
||
| fix: file uploads failing on Browserbase |
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { Buffer } from "buffer"; | ||
|
|
||
| export interface NormalizedFilePayload { | ||
| name: string; | ||
| mimeType: string; | ||
| buffer: Buffer; | ||
| lastModified: number; | ||
| /** Absolute path to the source file when provided by the caller. */ | ||
| absolutePath?: string; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { Buffer } from "buffer"; | ||
|
|
||
| export interface SetInputFilePayload { | ||
| name: string; | ||
| mimeType?: string; | ||
| buffer: ArrayBuffer | Uint8Array | Buffer | string; | ||
| lastModified?: number; | ||
| } | ||
|
|
||
| export type SetInputFilesArgument = | ||
| | string | ||
| | string[] | ||
| | SetInputFilePayload | ||
| | SetInputFilePayload[]; |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| import { promises as fs, type Stats } from "fs"; | ||
| import path from "path"; | ||
| import { Buffer } from "buffer"; | ||
| import { StagehandInvalidArgumentError } from "../types/public/sdkErrors"; | ||
| import { | ||
| SetInputFilesArgument, | ||
| SetInputFilePayload, | ||
| } from "../types/public/locator"; | ||
| import { NormalizedFilePayload } from "../types/private/locator"; | ||
|
|
||
| const DEFAULT_MIME_TYPE = "application/octet-stream"; | ||
|
|
||
| /** | ||
| * Normalize user-provided setInputFiles arguments into in-memory payloads. | ||
| * - Resolves string paths relative to the provided base directory. | ||
| * - Validates that each path exists and is a regular file. | ||
| * - Converts all buffers into Node Buffers for downstream processing. | ||
| */ | ||
| export async function normalizeInputFiles( | ||
| files: SetInputFilesArgument, | ||
| opts: { baseDir?: string } = {}, | ||
| ): Promise<NormalizedFilePayload[]> { | ||
| if (files === null || files === undefined) return []; | ||
|
|
||
| const flattened = Array.isArray(files) | ||
| ? (files as Array<string | SetInputFilePayload>) | ||
| : [files]; | ||
| if (!flattened.length) return []; | ||
|
|
||
| const baseDir = opts.baseDir ?? process.cwd(); | ||
| const normalized: NormalizedFilePayload[] = []; | ||
|
|
||
| for (const entry of flattened) { | ||
| if (typeof entry === "string") { | ||
| const absolutePath = path.isAbsolute(entry) | ||
| ? entry | ||
| : path.resolve(baseDir, entry); | ||
| const stat = await statFile(absolutePath); | ||
| if (!stat.isFile()) { | ||
| throw new StagehandInvalidArgumentError( | ||
| `setInputFiles(): expected a file but received directory or special entry at ${absolutePath}`, | ||
| ); | ||
| } | ||
| const buffer = await fs.readFile(absolutePath); | ||
| normalized.push({ | ||
| name: path.basename(absolutePath) || "upload.bin", | ||
| mimeType: DEFAULT_MIME_TYPE, | ||
| buffer, | ||
| lastModified: stat.mtimeMs || Date.now(), | ||
| absolutePath, | ||
| }); | ||
| continue; | ||
| } | ||
|
|
||
| if (entry && typeof entry === "object" && "buffer" in entry) { | ||
| const payload = entry as SetInputFilePayload; | ||
| const buffer = toBuffer(payload.buffer); | ||
| normalized.push({ | ||
| name: payload.name || "upload.bin", | ||
| mimeType: payload.mimeType || DEFAULT_MIME_TYPE, | ||
| buffer, | ||
| lastModified: | ||
| typeof payload.lastModified === "number" | ||
| ? payload.lastModified | ||
| : Date.now(), | ||
| }); | ||
| continue; | ||
| } | ||
|
|
||
| throw new StagehandInvalidArgumentError( | ||
| "setInputFiles(): expected file path(s) or payload object(s)", | ||
| ); | ||
| } | ||
|
|
||
| return normalized; | ||
| } | ||
|
|
||
| async function statFile(absolutePath: string): Promise<Stats> { | ||
| try { | ||
| return await fs.stat(absolutePath); | ||
| } catch (error) { | ||
| const code = (error as NodeJS.ErrnoException)?.code; | ||
| if (code === "ENOENT") { | ||
| throw new StagehandInvalidArgumentError( | ||
| `setInputFiles(): file not found at ${absolutePath}`, | ||
| ); | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| export function toBuffer( | ||
| data: ArrayBuffer | Uint8Array | Buffer | string, | ||
| ): Buffer { | ||
| if (Buffer.isBuffer(data)) return data; | ||
| if (data instanceof Uint8Array) return Buffer.from(data); | ||
| if (typeof data === "string") return Buffer.from(data); | ||
| if (data instanceof ArrayBuffer) return Buffer.from(new Uint8Array(data)); | ||
| throw new StagehandInvalidArgumentError( | ||
| "Unsupported file payload buffer type", | ||
| ); | ||
| } | ||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.