run: inline files for attached servers (#33317)

This commit is contained in:
Simon Klee
2026-06-22 13:20:43 +02:00
committed by GitHub
parent cd292a4ecb
commit c7efbe6fc0
3 changed files with 351 additions and 16 deletions
+43 -2
View File
@@ -1,4 +1,5 @@
import type { PermissionV1 } from "@opencode-ai/core/v1/permission"
import { FSUtil } from "@opencode-ai/core/fs-util"
// CLI entry point for `opencode run`.
//
// Handles three modes:
@@ -15,6 +16,7 @@ import type { PermissionV1 } from "@opencode-ai/core/v1/permission"
import type { Argv } from "yargs"
import path from "path"
import { pathToFileURL } from "url"
import { open } from "node:fs/promises"
import { Effect } from "effect"
import { UI } from "../ui"
import { effectCmd } from "../effect-cmd"
@@ -54,6 +56,8 @@ type FilePart = {
mime: string
}
const ATTACH_FILE_MAX_BYTES = 10 * 1024 * 1024
type Inline = {
icon: string
title: string
@@ -337,11 +341,48 @@ export const RunCommand = effectCmd({
process.exit(1)
}
const mime = (await Filesystem.isDir(resolvedPath)) ? "application/x-directory" : "text/plain"
const stat = Filesystem.stat(resolvedPath)
const isDirectory = stat?.isDirectory() ?? false
if (args.attach && isDirectory) {
UI.error(`Cannot attach local directory without a shared filesystem: ${filePath}`)
process.exit(1)
}
const content = await (async () => {
if (!args.attach) return
const handle = await open(resolvedPath, "r")
try {
const opened = await handle.stat()
if (!opened.isFile() || Number(opened.size) > ATTACH_FILE_MAX_BYTES) {
UI.error(`Cannot attach local file larger than 10 MiB or a special file: ${filePath}`)
process.exit(1)
}
if (opened.size === 0) return Buffer.alloc(0)
const buffer = Buffer.alloc(Number(opened.size))
let offset = 0
while (offset < buffer.length) {
const read = await handle.read(buffer, offset, buffer.length - offset, offset)
if (read.bytesRead === 0) break
offset += read.bytesRead
}
return buffer.subarray(0, offset)
} finally {
await handle.close()
}
})()
const detected = FSUtil.mimeType(resolvedPath)
const text = content?.toString("utf8")
const mime = !args.attach
? isDirectory
? "application/x-directory"
: "text/plain"
: content && text !== undefined && Buffer.from(text, "utf8").equals(content)
? "text/plain"
: detected
files.push({
type: "file",
url: pathToFileURL(resolvedPath).href,
url: content ? `data:${mime};base64,${content.toString("base64")}` : pathToFileURL(resolvedPath).href,
filename: path.basename(resolvedPath),
mime,
})