Revert pr that was mistakenly merged (#11844)
This commit is contained in:
@@ -172,14 +172,6 @@ export namespace SessionProcessor {
|
|||||||
case "tool-result": {
|
case "tool-result": {
|
||||||
const match = toolcalls[value.toolCallId]
|
const match = toolcalls[value.toolCallId]
|
||||||
if (match && match.state.status === "running") {
|
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({
|
await Session.updatePart({
|
||||||
...match,
|
...match,
|
||||||
state: {
|
state: {
|
||||||
@@ -192,7 +184,7 @@ export namespace SessionProcessor {
|
|||||||
start: match.state.time.start,
|
start: match.state.time.start,
|
||||||
end: Date.now(),
|
end: Date.now(),
|
||||||
},
|
},
|
||||||
attachments,
|
attachments: value.output.attachments,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -187,17 +187,13 @@ export namespace SessionPrompt {
|
|||||||
text: template,
|
text: template,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
const matches = ConfigMarkdown.files(template)
|
const files = ConfigMarkdown.files(template)
|
||||||
const seen = new Set<string>()
|
const seen = new Set<string>()
|
||||||
const names = matches
|
await Promise.all(
|
||||||
.map((match) => match[1])
|
files.map(async (match) => {
|
||||||
.filter((name) => {
|
const name = match[1]
|
||||||
if (seen.has(name)) return false
|
if (seen.has(name)) return
|
||||||
seen.add(name)
|
seen.add(name)
|
||||||
return true
|
|
||||||
})
|
|
||||||
const resolved = await Promise.all(
|
|
||||||
names.map(async (name) => {
|
|
||||||
const filepath = name.startsWith("~/")
|
const filepath = name.startsWith("~/")
|
||||||
? path.join(os.homedir(), name.slice(2))
|
? path.join(os.homedir(), name.slice(2))
|
||||||
: path.resolve(Instance.worktree, name)
|
: path.resolve(Instance.worktree, name)
|
||||||
@@ -205,34 +201,33 @@ export namespace SessionPrompt {
|
|||||||
const stats = await fs.stat(filepath).catch(() => undefined)
|
const stats = await fs.stat(filepath).catch(() => undefined)
|
||||||
if (!stats) {
|
if (!stats) {
|
||||||
const agent = await Agent.get(name)
|
const agent = await Agent.get(name)
|
||||||
if (!agent) return undefined
|
if (agent) {
|
||||||
return {
|
parts.push({
|
||||||
type: "agent",
|
type: "agent",
|
||||||
name: agent.name,
|
name: agent.name,
|
||||||
} satisfies PromptInput["parts"][number]
|
})
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
return {
|
parts.push({
|
||||||
type: "file",
|
type: "file",
|
||||||
url: `file://${filepath}`,
|
url: `file://${filepath}`,
|
||||||
filename: name,
|
filename: name,
|
||||||
mime: "application/x-directory",
|
mime: "application/x-directory",
|
||||||
} satisfies PromptInput["parts"][number]
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
parts.push({
|
||||||
type: "file",
|
type: "file",
|
||||||
url: `file://${filepath}`,
|
url: `file://${filepath}`,
|
||||||
filename: name,
|
filename: name,
|
||||||
mime: "text/plain",
|
mime: "text/plain",
|
||||||
} satisfies PromptInput["parts"][number]
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
for (const item of resolved) {
|
|
||||||
if (!item) continue
|
|
||||||
parts.push(item)
|
|
||||||
}
|
|
||||||
return parts
|
return parts
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,12 +427,6 @@ export namespace SessionPrompt {
|
|||||||
assistantMessage.time.completed = Date.now()
|
assistantMessage.time.completed = Date.now()
|
||||||
await Session.updateMessage(assistantMessage)
|
await Session.updateMessage(assistantMessage)
|
||||||
if (result && part.state.status === "running") {
|
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({
|
await Session.updatePart({
|
||||||
...part,
|
...part,
|
||||||
state: {
|
state: {
|
||||||
@@ -446,7 +435,7 @@ export namespace SessionPrompt {
|
|||||||
title: result.title,
|
title: result.title,
|
||||||
metadata: result.metadata,
|
metadata: result.metadata,
|
||||||
output: result.output,
|
output: result.output,
|
||||||
attachments,
|
attachments: result.attachments,
|
||||||
time: {
|
time: {
|
||||||
...part.state.time,
|
...part.state.time,
|
||||||
end: Date.now(),
|
end: Date.now(),
|
||||||
@@ -785,13 +774,16 @@ export namespace SessionPrompt {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const textParts: string[] = []
|
const textParts: string[] = []
|
||||||
const attachments: Omit<MessageV2.FilePart, "id" | "messageID" | "sessionID">[] = []
|
const attachments: MessageV2.FilePart[] = []
|
||||||
|
|
||||||
for (const contentItem of result.content) {
|
for (const contentItem of result.content) {
|
||||||
if (contentItem.type === "text") {
|
if (contentItem.type === "text") {
|
||||||
textParts.push(contentItem.text)
|
textParts.push(contentItem.text)
|
||||||
} else if (contentItem.type === "image") {
|
} else if (contentItem.type === "image") {
|
||||||
attachments.push({
|
attachments.push({
|
||||||
|
id: Identifier.ascending("part"),
|
||||||
|
sessionID: input.session.id,
|
||||||
|
messageID: input.processor.message.id,
|
||||||
type: "file",
|
type: "file",
|
||||||
mime: contentItem.mimeType,
|
mime: contentItem.mimeType,
|
||||||
url: `data:${contentItem.mimeType};base64,${contentItem.data}`,
|
url: `data:${contentItem.mimeType};base64,${contentItem.data}`,
|
||||||
@@ -803,6 +795,9 @@ export namespace SessionPrompt {
|
|||||||
}
|
}
|
||||||
if (resource.blob) {
|
if (resource.blob) {
|
||||||
attachments.push({
|
attachments.push({
|
||||||
|
id: Identifier.ascending("part"),
|
||||||
|
sessionID: input.session.id,
|
||||||
|
messageID: input.processor.message.id,
|
||||||
type: "file",
|
type: "file",
|
||||||
mime: resource.mimeType ?? "application/octet-stream",
|
mime: resource.mimeType ?? "application/octet-stream",
|
||||||
url: `data:${resource.mimeType ?? "application/octet-stream"};base64,${resource.blob}`,
|
url: `data:${resource.mimeType ?? "application/octet-stream"};base64,${resource.blob}`,
|
||||||
@@ -1051,7 +1046,6 @@ export namespace SessionPrompt {
|
|||||||
pieces.push(
|
pieces.push(
|
||||||
...result.attachments.map((attachment) => ({
|
...result.attachments.map((attachment) => ({
|
||||||
...attachment,
|
...attachment,
|
||||||
id: Identifier.ascending("part"),
|
|
||||||
synthetic: true,
|
synthetic: true,
|
||||||
filename: attachment.filename ?? part.filename,
|
filename: attachment.filename ?? part.filename,
|
||||||
messageID: info.id,
|
messageID: info.id,
|
||||||
@@ -1189,18 +1183,7 @@ export namespace SessionPrompt {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
)
|
).then((x) => x.flat())
|
||||||
.then((x) => x.flat())
|
|
||||||
.then((drafts) =>
|
|
||||||
drafts.map(
|
|
||||||
(part): MessageV2.Part => ({
|
|
||||||
...part,
|
|
||||||
id: Identifier.ascending("part"),
|
|
||||||
messageID: info.id,
|
|
||||||
sessionID: input.sessionID,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
await Plugin.trigger(
|
await Plugin.trigger(
|
||||||
"chat.message",
|
"chat.message",
|
||||||
|
|||||||
@@ -77,12 +77,6 @@ export const BatchTool = Tool.define("batch", async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const result = await tool.execute(validatedParams, { ...ctx, callID: partID })
|
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({
|
await Session.updatePart({
|
||||||
id: partID,
|
id: partID,
|
||||||
@@ -97,7 +91,7 @@ export const BatchTool = Tool.define("batch", async () => {
|
|||||||
output: result.output,
|
output: result.output,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
metadata: result.metadata,
|
metadata: result.metadata,
|
||||||
attachments,
|
attachments: result.attachments,
|
||||||
time: {
|
time: {
|
||||||
start: callStartTime,
|
start: callStartTime,
|
||||||
end: Date.now(),
|
end: Date.now(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { LSP } from "../lsp"
|
|||||||
import { FileTime } from "../file/time"
|
import { FileTime } from "../file/time"
|
||||||
import DESCRIPTION from "./read.txt"
|
import DESCRIPTION from "./read.txt"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
|
import { Identifier } from "../id/id"
|
||||||
import { assertExternalDirectory } from "./external-directory"
|
import { assertExternalDirectory } from "./external-directory"
|
||||||
import { InstructionPrompt } from "../session/instruction"
|
import { InstructionPrompt } from "../session/instruction"
|
||||||
|
|
||||||
@@ -78,6 +79,9 @@ export const ReadTool = Tool.define("read", {
|
|||||||
},
|
},
|
||||||
attachments: [
|
attachments: [
|
||||||
{
|
{
|
||||||
|
id: Identifier.ascending("part"),
|
||||||
|
sessionID: ctx.sessionID,
|
||||||
|
messageID: ctx.messageID,
|
||||||
type: "file",
|
type: "file",
|
||||||
mime,
|
mime,
|
||||||
url: `data:${mime};base64,${Buffer.from(await file.bytes()).toString("base64")}`,
|
url: `data:${mime};base64,${Buffer.from(await file.bytes()).toString("base64")}`,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export namespace Tool {
|
|||||||
title: string
|
title: string
|
||||||
metadata: M
|
metadata: M
|
||||||
output: string
|
output: string
|
||||||
attachments?: Omit<MessageV2.FilePart, "id" | "sessionID" | "messageID">[]
|
attachments?: MessageV2.FilePart[]
|
||||||
}>
|
}>
|
||||||
formatValidationError?(error: z.ZodError): string
|
formatValidationError?(error: z.ZodError): string
|
||||||
}>
|
}>
|
||||||
|
|||||||
@@ -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)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user