mirror of
https://github.com/aljazceru/opencode.git
synced 2026-01-30 13:15:08 +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 z from "zod/v4"
|
||||||
import { Bus } from "../bus"
|
import { Bus } from "../bus"
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
|
import type { BunFile } from "bun"
|
||||||
import { formatPatch, structuredPatch } from "diff"
|
import { formatPatch, structuredPatch } from "diff"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
@@ -41,6 +42,7 @@ export namespace File {
|
|||||||
|
|
||||||
export const Content = z
|
export const Content = z
|
||||||
.object({
|
.object({
|
||||||
|
type: z.literal("text"),
|
||||||
content: z.string(),
|
content: z.string(),
|
||||||
diff: z.string().optional(),
|
diff: z.string().optional(),
|
||||||
patch: z
|
patch: z
|
||||||
@@ -61,12 +63,53 @@ export namespace File {
|
|||||||
index: z.string().optional(),
|
index: z.string().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
encoding: z.literal("base64").optional(),
|
||||||
|
mimeType: z.string().optional(),
|
||||||
})
|
})
|
||||||
.meta({
|
.meta({
|
||||||
ref: "FileContent",
|
ref: "FileContent",
|
||||||
})
|
})
|
||||||
export type Content = z.infer<typeof Content>
|
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 = {
|
export const Event = {
|
||||||
Edited: Bus.event(
|
Edited: Bus.event(
|
||||||
"file.edited",
|
"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 })
|
using _ = log.time("read", { file })
|
||||||
const project = Instance.project
|
const project = Instance.project
|
||||||
const full = path.join(Instance.directory, file)
|
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()
|
.text()
|
||||||
.catch(() => "")
|
.catch(() => "")
|
||||||
.then((x) => x.trim())
|
.then((x) => x.trim())
|
||||||
|
|
||||||
if (project.vcs === "git") {
|
if (project.vcs === "git") {
|
||||||
let diff = await $`git diff ${file}`.cwd(Instance.directory).quiet().nothrow().text()
|
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()
|
if (!diff.trim()) diff = await $`git diff --staged ${file}`.cwd(Instance.directory).quiet().nothrow().text()
|
||||||
@@ -206,10 +265,10 @@ export namespace File {
|
|||||||
ignoreWhitespace: true,
|
ignoreWhitespace: true,
|
||||||
})
|
})
|
||||||
const diff = formatPatch(patch)
|
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) {
|
export async function list(dir?: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user