mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 11:14:23 +01:00
tweak: adjust file api to encode images (#3292)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import z from "zod/v4"
|
||||
import { Bus } from "../bus"
|
||||
import { $ } from "bun"
|
||||
import type { BunFile } from "bun"
|
||||
import { formatPatch, structuredPatch } from "diff"
|
||||
import path from "path"
|
||||
import fs from "fs"
|
||||
@@ -41,6 +42,7 @@ export namespace File {
|
||||
|
||||
export const Content = z
|
||||
.object({
|
||||
type: z.literal("text"),
|
||||
content: z.string(),
|
||||
diff: z.string().optional(),
|
||||
patch: z
|
||||
@@ -61,12 +63,53 @@ export namespace File {
|
||||
index: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
encoding: z.literal("base64").optional(),
|
||||
mimeType: z.string().optional(),
|
||||
})
|
||||
.meta({
|
||||
ref: "FileContent",
|
||||
})
|
||||
export type Content = z.infer<typeof Content>
|
||||
|
||||
async function shouldEncode(file: BunFile): Promise<boolean> {
|
||||
const type = file.type?.toLowerCase()
|
||||
if (!type) return false
|
||||
|
||||
if (type.startsWith("text/")) return false
|
||||
if (type.includes("charset=")) return false
|
||||
|
||||
const parts = type.split("/", 2)
|
||||
const top = parts[0]
|
||||
const rest = parts[1] ?? ""
|
||||
const sub = rest.split(";", 1)[0]
|
||||
|
||||
const tops = ["image", "audio", "video", "font", "model", "multipart"]
|
||||
if (tops.includes(top)) return true
|
||||
|
||||
if (type === "application/octet-stream") return true
|
||||
|
||||
const bins = [
|
||||
"zip",
|
||||
"gzip",
|
||||
"bzip",
|
||||
"compressed",
|
||||
"binary",
|
||||
"stream",
|
||||
"pdf",
|
||||
"msword",
|
||||
"powerpoint",
|
||||
"excel",
|
||||
"ogg",
|
||||
"exe",
|
||||
"dmg",
|
||||
"iso",
|
||||
"rar",
|
||||
]
|
||||
if (bins.some((mark) => sub.includes(mark))) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export const Event = {
|
||||
Edited: Bus.event(
|
||||
"file.edited",
|
||||
@@ -188,14 +231,30 @@ export namespace File {
|
||||
}))
|
||||
}
|
||||
|
||||
export async function read(file: string) {
|
||||
export async function read(file: string): Promise<Content> {
|
||||
using _ = log.time("read", { file })
|
||||
const project = Instance.project
|
||||
const full = path.join(Instance.directory, file)
|
||||
const content = await Bun.file(full)
|
||||
const bunFile = Bun.file(full)
|
||||
|
||||
if (!(await bunFile.exists())) {
|
||||
return { type: "text", content: "" }
|
||||
}
|
||||
|
||||
const encode = await shouldEncode(bunFile)
|
||||
|
||||
if (encode) {
|
||||
const buffer = await bunFile.arrayBuffer().catch(() => new ArrayBuffer(0))
|
||||
const content = Buffer.from(buffer).toString("base64")
|
||||
const mimeType = bunFile.type || "application/octet-stream"
|
||||
return { type: "text", content, mimeType, encoding: "base64" }
|
||||
}
|
||||
|
||||
const content = await bunFile
|
||||
.text()
|
||||
.catch(() => "")
|
||||
.then((x) => x.trim())
|
||||
|
||||
if (project.vcs === "git") {
|
||||
let diff = await $`git diff ${file}`.cwd(Instance.directory).quiet().nothrow().text()
|
||||
if (!diff.trim()) diff = await $`git diff --staged ${file}`.cwd(Instance.directory).quiet().nothrow().text()
|
||||
@@ -206,10 +265,10 @@ export namespace File {
|
||||
ignoreWhitespace: true,
|
||||
})
|
||||
const diff = formatPatch(patch)
|
||||
return { content, patch, diff }
|
||||
return { type: "text", content, patch, diff }
|
||||
}
|
||||
}
|
||||
return { content }
|
||||
return { type: "text", content }
|
||||
}
|
||||
|
||||
export async function list(dir?: string) {
|
||||
|
||||
Reference in New Issue
Block a user