summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2026-02-02 15:28:02 -0600
committerGitHub <[email protected]>2026-02-02 15:28:02 -0600
commitaa6b552c39fce24d35097de4feb6d1aa0598b1c5 (patch)
tree3568faad7787f8f2056b408da3b4f60d5037f691 /packages
parenta3f1918489942eb2d99c1ef4e3b8628d55d0dfc7 (diff)
downloadopencode-aa6b552c39fce24d35097de4feb6d1aa0598b1c5.tar.gz
opencode-aa6b552c39fce24d35097de4feb6d1aa0598b1c5.zip
Revert pr that was mistakenly merged (#11844)
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/session/processor.ts10
-rw-r--r--packages/opencode/src/session/prompt.ts69
-rw-r--r--packages/opencode/src/tool/batch.ts8
-rw-r--r--packages/opencode/src/tool/read.ts4
-rw-r--r--packages/opencode/src/tool/tool.ts2
-rw-r--r--packages/opencode/test/session/prompt.test.ts62
6 files changed, 33 insertions, 122 deletions
diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts
index 24b4a4f9f..b5289e903 100644
--- a/packages/opencode/src/session/processor.ts
+++ b/packages/opencode/src/session/processor.ts
@@ -172,14 +172,6 @@ export namespace SessionProcessor {
case "tool-result": {
const match = toolcalls[value.toolCallId]
if (match && match.state.status === "running") {
- const attachments = value.output.attachments?.map(
- (attachment: Omit<MessageV2.FilePart, "id" | "messageID" | "sessionID">) => ({
- ...attachment,
- id: Identifier.ascending("part"),
- messageID: match.messageID,
- sessionID: match.sessionID,
- }),
- )
await Session.updatePart({
...match,
state: {
@@ -192,7 +184,7 @@ export namespace SessionProcessor {
start: match.state.time.start,
end: Date.now(),
},
- attachments,
+ attachments: value.output.attachments,
},
})
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index 98dce97ba..e0861c4df 100644
--- a/packages/opencode/src/session/prompt.ts
+++ b/packages/opencode/src/session/prompt.ts
@@ -187,17 +187,13 @@ export namespace SessionPrompt {
text: template,
},
]
- const matches = ConfigMarkdown.files(template)
+ const files = ConfigMarkdown.files(template)
const seen = new Set<string>()
- const names = matches
- .map((match) => match[1])
- .filter((name) => {
- if (seen.has(name)) return false
+ await Promise.all(
+ files.map(async (match) => {
+ const name = match[1]
+ if (seen.has(name)) return
seen.add(name)
- return true
- })
- const resolved = await Promise.all(
- names.map(async (name) => {
const filepath = name.startsWith("~/")
? path.join(os.homedir(), name.slice(2))
: path.resolve(Instance.worktree, name)
@@ -205,34 +201,33 @@ export namespace SessionPrompt {
const stats = await fs.stat(filepath).catch(() => undefined)
if (!stats) {
const agent = await Agent.get(name)
- if (!agent) return undefined
- return {
- type: "agent",
- name: agent.name,
- } satisfies PromptInput["parts"][number]
+ if (agent) {
+ parts.push({
+ type: "agent",
+ name: agent.name,
+ })
+ }
+ return
}
if (stats.isDirectory()) {
- return {
+ parts.push({
type: "file",
url: `file://${filepath}`,
filename: name,
mime: "application/x-directory",
- } satisfies PromptInput["parts"][number]
+ })
+ return
}
- return {
+ parts.push({
type: "file",
url: `file://${filepath}`,
filename: name,
mime: "text/plain",
- } satisfies PromptInput["parts"][number]
+ })
}),
)
- for (const item of resolved) {
- if (!item) continue
- parts.push(item)
- }
return parts
}
@@ -432,12 +427,6 @@ export namespace SessionPrompt {
assistantMessage.time.completed = Date.now()
await Session.updateMessage(assistantMessage)
if (result && part.state.status === "running") {
- const attachments = result.attachments?.map((attachment) => ({
- ...attachment,
- id: Identifier.ascending("part"),
- messageID: assistantMessage.id,
- sessionID: assistantMessage.sessionID,
- }))
await Session.updatePart({
...part,
state: {
@@ -446,7 +435,7 @@ export namespace SessionPrompt {
title: result.title,
metadata: result.metadata,
output: result.output,
- attachments,
+ attachments: result.attachments,
time: {
...part.state.time,
end: Date.now(),
@@ -785,13 +774,16 @@ export namespace SessionPrompt {
)
const textParts: string[] = []
- const attachments: Omit<MessageV2.FilePart, "id" | "messageID" | "sessionID">[] = []
+ const attachments: MessageV2.FilePart[] = []
for (const contentItem of result.content) {
if (contentItem.type === "text") {
textParts.push(contentItem.text)
} else if (contentItem.type === "image") {
attachments.push({
+ id: Identifier.ascending("part"),
+ sessionID: input.session.id,
+ messageID: input.processor.message.id,
type: "file",
mime: contentItem.mimeType,
url: `data:${contentItem.mimeType};base64,${contentItem.data}`,
@@ -803,6 +795,9 @@ export namespace SessionPrompt {
}
if (resource.blob) {
attachments.push({
+ id: Identifier.ascending("part"),
+ sessionID: input.session.id,
+ messageID: input.processor.message.id,
type: "file",
mime: resource.mimeType ?? "application/octet-stream",
url: `data:${resource.mimeType ?? "application/octet-stream"};base64,${resource.blob}`,
@@ -1051,7 +1046,6 @@ export namespace SessionPrompt {
pieces.push(
...result.attachments.map((attachment) => ({
...attachment,
- id: Identifier.ascending("part"),
synthetic: true,
filename: attachment.filename ?? part.filename,
messageID: info.id,
@@ -1189,18 +1183,7 @@ export namespace SessionPrompt {
},
]
}),
- )
- .then((x) => x.flat())
- .then((drafts) =>
- drafts.map(
- (part): MessageV2.Part => ({
- ...part,
- id: Identifier.ascending("part"),
- messageID: info.id,
- sessionID: input.sessionID,
- }),
- ),
- )
+ ).then((x) => x.flat())
await Plugin.trigger(
"chat.message",
diff --git a/packages/opencode/src/tool/batch.ts b/packages/opencode/src/tool/batch.ts
index b5c3ad0a1..ba34eb48f 100644
--- a/packages/opencode/src/tool/batch.ts
+++ b/packages/opencode/src/tool/batch.ts
@@ -77,12 +77,6 @@ export const BatchTool = Tool.define("batch", async () => {
})
const result = await tool.execute(validatedParams, { ...ctx, callID: partID })
- const attachments = result.attachments?.map((attachment) => ({
- ...attachment,
- id: Identifier.ascending("part"),
- messageID: ctx.messageID,
- sessionID: ctx.sessionID,
- }))
await Session.updatePart({
id: partID,
@@ -97,7 +91,7 @@ export const BatchTool = Tool.define("batch", async () => {
output: result.output,
title: result.title,
metadata: result.metadata,
- attachments,
+ attachments: result.attachments,
time: {
start: callStartTime,
end: Date.now(),
diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts
index 13236d44d..f230cdf44 100644
--- a/packages/opencode/src/tool/read.ts
+++ b/packages/opencode/src/tool/read.ts
@@ -6,6 +6,7 @@ import { LSP } from "../lsp"
import { FileTime } from "../file/time"
import DESCRIPTION from "./read.txt"
import { Instance } from "../project/instance"
+import { Identifier } from "../id/id"
import { assertExternalDirectory } from "./external-directory"
import { InstructionPrompt } from "../session/instruction"
@@ -78,6 +79,9 @@ export const ReadTool = Tool.define("read", {
},
attachments: [
{
+ id: Identifier.ascending("part"),
+ sessionID: ctx.sessionID,
+ messageID: ctx.messageID,
type: "file",
mime,
url: `data:${mime};base64,${Buffer.from(await file.bytes()).toString("base64")}`,
diff --git a/packages/opencode/src/tool/tool.ts b/packages/opencode/src/tool/tool.ts
index 0e78ba665..3d17ea192 100644
--- a/packages/opencode/src/tool/tool.ts
+++ b/packages/opencode/src/tool/tool.ts
@@ -36,7 +36,7 @@ export namespace Tool {
title: string
metadata: M
output: string
- attachments?: Omit<MessageV2.FilePart, "id" | "sessionID" | "messageID">[]
+ attachments?: MessageV2.FilePart[]
}>
formatValidationError?(error: z.ZodError): string
}>
diff --git a/packages/opencode/test/session/prompt.test.ts b/packages/opencode/test/session/prompt.test.ts
deleted file mode 100644
index e778bfe51..000000000
--- a/packages/opencode/test/session/prompt.test.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import path from "path"
-import { describe, expect, test } from "bun:test"
-import { Session } from "../../src/session"
-import { SessionPrompt } from "../../src/session/prompt"
-import { MessageV2 } from "../../src/session/message-v2"
-import { Instance } from "../../src/project/instance"
-import { Log } from "../../src/util/log"
-import { tmpdir } from "../fixture/fixture"
-
-Log.init({ print: false })
-
-describe("SessionPrompt ordering", () => {
- test("keeps @file order with read output parts", async () => {
- await using tmp = await tmpdir({
- git: true,
- init: async (dir) => {
- await Bun.write(path.join(dir, "a.txt"), "28\n")
- await Bun.write(path.join(dir, "b.txt"), "42\n")
- },
- })
-
- await Instance.provide({
- directory: tmp.path,
- fn: async () => {
- const session = await Session.create({})
- const template = "What numbers are written in files @a.txt and @b.txt ?"
- const parts = await SessionPrompt.resolvePromptParts(template)
- const fileParts = parts.filter((part) => part.type === "file")
-
- expect(fileParts.map((part) => part.filename)).toStrictEqual(["a.txt", "b.txt"])
-
- const message = await SessionPrompt.prompt({
- sessionID: session.id,
- parts,
- noReply: true,
- })
- const stored = await MessageV2.get({ sessionID: session.id, messageID: message.info.id })
- const items = stored.parts
- const aPath = path.join(tmp.path, "a.txt")
- const bPath = path.join(tmp.path, "b.txt")
- const sequence = items.flatMap((part) => {
- if (part.type === "text") {
- if (part.text.includes(aPath)) return ["input:a"]
- if (part.text.includes(bPath)) return ["input:b"]
- if (part.text.includes("00001| 28")) return ["output:a"]
- if (part.text.includes("00001| 42")) return ["output:b"]
- return []
- }
- if (part.type === "file") {
- if (part.filename === "a.txt") return ["file:a"]
- if (part.filename === "b.txt") return ["file:b"]
- }
- return []
- })
-
- expect(sequence).toStrictEqual(["input:a", "output:a", "file:a", "input:b", "output:b", "file:b"])
-
- await Session.remove(session.id)
- },
- })
- })
-})