feat: Add image upload support with file path handling (#8830)

* ✨ (data.py): introduce a new function get_file_paths to resolve file paths before creating image URLs in HumanMessage contents

* ✨ (general-bugs-agent-images-playground.spec.ts): add test case for user to send images in the playground with the agent component

* 📝 (general-bugs-agent-images-playground.spec.ts): update file path to image file to fix test failure due to incorrect file path

* [autofix.ci] apply automated fixes

* fix: autofix.ci / Update Starter Projects (pull_request)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-07-04 10:54:22 -03:00 • committed by GitHub
commit 557f7b31aa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 216 additions and 121 deletions

View file

@ -0,0 +1,92 @@
import { expect, test } from "@playwright/test";
import dotenv from "dotenv";
import { readFileSync } from "fs";
import path from "path";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
test(
"user must be able to send images in the playground with the agent component",
{ tag: ["@release", "@components"] },
async ({ page }) => {
test.skip(
!process?.env?.ANTHROPIC_API_KEY,
"ANTHROPIC_API_KEY required to run this test",
);
if (!process.env.CI) {
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
}
await awaitBootstrapTest(page);
await page.getByTestId("side_nav_options_all-templates").click();
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
await page.getByTestId("value-dropdown-dropdown_str_agent_llm").click();
await page.waitForTimeout(200);
await page.getByText("Anthropic").last().click();
await page
.getByTestId("popover-anchor-input-api_key")
.fill(process.env.ANTHROPIC_API_KEY || "");
await page.getByTestId("playground-btn-flow-io").click();
// Read the image file as a binary string
const filePath = "tests/assets/chain.png";
const fileContent = readFileSync(filePath, "base64");
// Create the DataTransfer and File objects within the browser context
const dataTransfer = await page.evaluateHandle(
({ fileContent }) => {
const dt = new DataTransfer();
const byteCharacters = atob(fileContent);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const file = new File([byteArray], "chain.png", { type: "image/png" });
dt.items.add(file);
return dt;
},
{ fileContent },
);
await page.waitForSelector('[data-testid="input-chat-playground"]', {
timeout: 100000,
});
// Locate the target element
const element = await page.getByTestId("input-chat-playground");
// Dispatch the drop event on the target element
await element.dispatchEvent("drop", { dataTransfer });
await page
.getByTestId("input-chat-playground")
.fill("tell me a small history about the image");
await page.waitForSelector('[data-testid="button-send"]', {
timeout: 100000,
});
await page.getByTestId("button-send").click();
await page.waitForSelector("text=chain.png", { timeout: 30000 });
await page.getByText("chain.png").isVisible();
await page.waitForTimeout(5000);
const textFromLlm = await page
.locator(".markdown.prose")
.last()
.textContent();
expect(textFromLlm?.toLowerCase()).toContain("chain");
const lengthOfTextFromLlm = textFromLlm?.length;
expect(lengthOfTextFromLlm).toBeGreaterThan(100);
},
);