mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-01 22:23:07 +00:00
fix(antigravity): support uploaded_file attachments in prompt encoding
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { ProviderPrompt } from "@getpaseo/plugin/server/provider";
|
||||
@@ -10,6 +10,8 @@ interface EncodedPrompt {
|
||||
nativeText: string;
|
||||
}
|
||||
|
||||
const MAX_INLINE_FILE_BYTES = 2 * 1024 * 1024; // 2 MB
|
||||
|
||||
export class PromptFiles {
|
||||
private directory: string | null = null;
|
||||
|
||||
@@ -20,19 +22,16 @@ export class PromptFiles {
|
||||
prompt.outputSchema !== undefined
|
||||
)
|
||||
throw new AntigravityError("Antigravity supports messages only");
|
||||
const parts = prompt.input.content.map((part) => {
|
||||
if (part.type === "text") return part;
|
||||
if (part.type === "image") return { ...part, extension: imageExtension(part.mimeType) };
|
||||
throw new AntigravityError("Antigravity supports text and image content only");
|
||||
});
|
||||
|
||||
const text: string[] = [];
|
||||
const native: string[] = [];
|
||||
for (const part of parts) {
|
||||
|
||||
for (const part of prompt.input.content) {
|
||||
if (part.type === "text") {
|
||||
text.push(part.text);
|
||||
native.push(part.text);
|
||||
} else if (part.type === "image") {
|
||||
const extension = part.extension;
|
||||
const extension = imageExtension(part.mimeType);
|
||||
if (this.directory === null) {
|
||||
this.directory = await mkdtemp(path.join(os.tmpdir(), "paseo-antigravity-images-"));
|
||||
await chmod(this.directory, 0o700);
|
||||
@@ -41,8 +40,32 @@ export class PromptFiles {
|
||||
await writeFile(file, Buffer.from(part.data, "base64"), { flag: "wx", mode: 0o600 });
|
||||
await chmod(file, 0o600);
|
||||
native.push(`Attached image: ${file}`);
|
||||
} else if (part.type === "uploaded_file") {
|
||||
if (part.mimeType && part.mimeType.startsWith("image/")) {
|
||||
native.push(`Attached image: ${part.path}`);
|
||||
} else if (part.size > MAX_INLINE_FILE_BYTES) {
|
||||
const notice = `[Attached large file: ${part.fileName} at ${part.path} (${part.size} bytes)]`;
|
||||
text.push(notice);
|
||||
native.push(notice);
|
||||
} else {
|
||||
try {
|
||||
const content = await readFile(part.path, "utf8");
|
||||
const fileBlock = `[File: ${part.fileName}]\n${content}`;
|
||||
text.push(fileBlock);
|
||||
native.push(fileBlock);
|
||||
} catch {
|
||||
const notice = `[Attached file: ${part.fileName} at ${part.path}]`;
|
||||
text.push(notice);
|
||||
native.push(notice);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new AntigravityError(
|
||||
`Antigravity does not support content type: ${(part as { type?: string }).type ?? "unknown"}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { text: text.join("\n"), nativeText: native.join("\n") };
|
||||
}
|
||||
|
||||
|
||||
@@ -774,6 +774,52 @@ describe("image prompts", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("uploaded file prompts", () => {
|
||||
it("inlines readable text files and references uploaded images and large files", async () => {
|
||||
const h = await harness();
|
||||
await h.open();
|
||||
const txtFile = path.join(h.cwd, "notes.txt");
|
||||
await writeFile(txtFile, "export const meaning = 42;");
|
||||
const imgFile = path.join(h.cwd, "photo.png");
|
||||
await writeFile(imgFile, "png bytes");
|
||||
|
||||
await h.completed(
|
||||
await h.message([
|
||||
{ type: "text", text: "Please review these attachments:" },
|
||||
{
|
||||
type: "uploaded_file",
|
||||
id: "upload-txt-1",
|
||||
fileName: "notes.txt",
|
||||
mimeType: "text/plain",
|
||||
size: 26,
|
||||
path: txtFile,
|
||||
},
|
||||
{
|
||||
type: "uploaded_file",
|
||||
id: "upload-img-1",
|
||||
fileName: "photo.png",
|
||||
mimeType: "image/png",
|
||||
size: 9,
|
||||
path: imgFile,
|
||||
},
|
||||
{
|
||||
type: "uploaded_file",
|
||||
id: "upload-big-1",
|
||||
fileName: "dataset.bin",
|
||||
mimeType: "application/octet-stream",
|
||||
size: 3 * 1024 * 1024,
|
||||
path: "/tmp/dataset.bin",
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const sent = (await h.records()).find((entry) => entry.input).input.message.content;
|
||||
expect(sent).toBe(
|
||||
`SYSTEM PREFIX\n\nPlease review these attachments:\n[File: notes.txt]\nexport const meaning = 42;\nAttached image: ${imgFile}\n[Attached large file: dataset.bin at /tmp/dataset.bin (3145728 bytes)]`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it.runIf(process.platform === "win32")(
|
||||
"launches an Antigravity command shim for probes and conversation startup",
|
||||
async () => {
|
||||
|
||||
Reference in New Issue
Block a user