summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-07-04 16:20:12 -0400
committerDax Raad <[email protected]>2025-07-04 16:21:26 -0400
commit45b139390caa95038266d97c7de7e5b86fda5e7c (patch)
tree0f1e0fb014da7a95c901a35e68c09474614b738f
parent994368de15f580d02f54fa244bac6375aece9a46 (diff)
downloadopencode-45b139390caa95038266d97c7de7e5b86fda5e7c.tar.gz
opencode-45b139390caa95038266d97c7de7e5b86fda5e7c.zip
make file attachments work good like
-rw-r--r--packages/opencode/src/session/index.ts64
-rw-r--r--packages/tui/internal/components/chat/messages.go3
2 files changed, 46 insertions, 21 deletions
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 2afba4711..7dd0b325b 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -362,35 +362,57 @@ export namespace Session {
const app = App.info()
input.parts = await Promise.all(
- input.parts.map(async (part) => {
+ input.parts.map(async (part): Promise<Message.MessagePart[]> => {
if (part.type === "file") {
const url = new URL(part.url)
switch (url.protocol) {
case "file:":
- let content = await Bun.file(
- path.join(app.path.cwd, url.pathname),
- ).text()
- const range = {
- start: url.searchParams.get("start"),
- end: url.searchParams.get("end"),
- }
- if (range.start != null && part.mediaType === "text/plain") {
- const lines = content.split("\n")
- const start = parseInt(range.start)
- const end = range.end ? parseInt(range.end) : lines.length
- content = lines.slice(start, end).join("\n")
- }
- return {
- type: "file",
- url: `data:${part.mediaType};base64,` + btoa(content),
- mediaType: part.mediaType,
- filename: part.filename,
+ let content = Bun.file(path.join(app.path.cwd, url.pathname))
+
+ if (part.mediaType === "text/plain") {
+ let text = await content.text()
+ const range = {
+ start: url.searchParams.get("start"),
+ end: url.searchParams.get("end"),
+ }
+ if (range.start != null && part.mediaType === "text/plain") {
+ const lines = text.split("\n")
+ const start = parseInt(range.start)
+ const end = range.end ? parseInt(range.end) : lines.length
+ text = lines.slice(start, end).join("\n")
+ }
+ return [
+ {
+ type: "text",
+ text: [
+ "Called the Read tool on " + url.pathname,
+ "<results>",
+ text,
+ "</results>",
+ ].join("\n"),
+ },
+ ]
}
+
+ return [
+ {
+ type: "text",
+ text: ["Called the Read tool on " + url.pathname].join("\n"),
+ },
+ {
+ type: "file",
+ url:
+ `data:${part.mediaType};base64,` +
+ Buffer.from(await content.bytes()).toString("base64url"),
+ mediaType: part.mediaType,
+ filename: path.basename(part.filename!),
+ },
+ ]
}
}
- return part
+ return [part]
}),
- )
+ ).then((x) => x.flat())
if (msgs.length === 0 && !session.parentID) {
generateText({
maxTokens: input.providerID === "google" ? 1024 : 20,
diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go
index 49fdf7235..3d0011301 100644
--- a/packages/tui/internal/components/chat/messages.go
+++ b/packages/tui/internal/components/chat/messages.go
@@ -134,6 +134,7 @@ func (m *messagesComponent) renderView(width int) {
switch message.Role {
case opencode.MessageRoleUser:
+ userLoop:
for partIndex, part := range message.Parts {
switch part := part.AsUnion().(type) {
case opencode.TextPart:
@@ -195,6 +196,8 @@ func (m *messagesComponent) renderView(width int) {
m = m.updateSelected(content, part.Text)
blocks = append(blocks, content)
}
+ // Only render the first text part
+ break userLoop
}
}