Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/app/e2e/commands/input-focus.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ test("ctrl+l focuses the prompt", async ({ page, gotoSession }) => {
const prompt = page.locator(promptSelector)
await expect(prompt).toBeVisible()

await page.locator("main").click({ position: { x: 5, y: 5 } })
await prompt.evaluate((node) => {
if (node instanceof HTMLElement) node.blur()
})
await expect(prompt).not.toBeFocused()

await page.keyboard.press("Control+L")
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,8 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
const slashMatch = rawText.match(/^\/(\S*)$/)

if (atMatch) {
atOnInput(atMatch[1])
const mentionQuery = atMatch[1].replace(/\\/g, "/")
atOnInput(mentionQuery)
setStore("popover", "at")
} else if (slashMatch) {
slashOnInput(slashMatch[1])
Expand Down
5 changes: 0 additions & 5 deletions packages/opencode/script/seed-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,16 @@ const now = Date.now()
const seed = async () => {
const { Instance } = await import("../src/project/instance")
const { InstanceBootstrap } = await import("../src/project/bootstrap")
const { Config } = await import("../src/config/config")
const { Session } = await import("../src/session")
const { MessageID, PartID } = await import("../src/session/schema")
const { Project } = await import("../src/project/project")
const { ModelID, ProviderID } = await import("../src/provider/schema")
const { ToolRegistry } = await import("../src/tool/registry")

try {
await Instance.provide({
directory: dir,
init: InstanceBootstrap,
fn: async () => {
await Config.waitForDependencies()
await ToolRegistry.ids()

const session = await Session.create({ title })
const messageID = MessageID.ascending()
const partID = PartID.ascending()
Expand Down
2 changes: 0 additions & 2 deletions packages/opencode/src/server/projectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,3 @@ export function initProjectors() {
},
})
}

initProjectors()
4 changes: 3 additions & 1 deletion packages/opencode/src/session/message-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,9 @@ export namespace MessageV2 {
attachments?: Array<{ mime: string; url: string }>
}
const attachments = (outputObject.attachments ?? []).filter((attachment) => {
return attachment.url.startsWith("data:") && attachment.url.includes(",")
if (!attachment.url.startsWith("data:") || !attachment.url.includes(",")) return false
if (attachment.mime === "application/pdf" && !model.capabilities.input.pdf) return false
return true
})

return {
Expand Down
79 changes: 79 additions & 0 deletions packages/opencode/test/session/message-v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,85 @@ describe("session.message-v2.toModelMessage", () => {
])
})

test("omits pdf tool-result attachments for models without pdf input support", async () => {
const userID = "m-user"
const assistantID = "m-assistant"

const input: MessageV2.WithParts[] = [
{
info: userInfo(userID),
parts: [
{
...basePart(userID, "u1"),
type: "text",
text: "read pdf",
},
] as MessageV2.Part[],
},
{
info: assistantInfo(assistantID, userID),
parts: [
{
...basePart(assistantID, "a1"),
type: "tool",
callID: "call-1",
tool: "read",
state: {
status: "completed",
input: { filePath: "debug/cv-print-test.pdf" },
output: "PDF read successfully",
title: "Read PDF",
metadata: {},
time: { start: 0, end: 1 },
attachments: [
{
...basePart(assistantID, "file-1"),
type: "file",
mime: "application/pdf",
filename: "cv-print-test.pdf",
url: "data:application/pdf;base64,Zm9v",
},
],
},
},
] as MessageV2.Part[],
},
]

expect(await MessageV2.toModelMessages(input, model)).toStrictEqual([
{
role: "user",
content: [{ type: "text", text: "read pdf" }],
},
{
role: "assistant",
content: [
{
type: "tool-call",
toolCallId: "call-1",
toolName: "read",
input: { filePath: "debug/cv-print-test.pdf" },
providerExecuted: undefined,
},
],
},
{
role: "tool",
content: [
{
type: "tool-result",
toolCallId: "call-1",
toolName: "read",
output: {
type: "content",
value: [{ type: "text", text: "PDF read successfully" }],
},
},
],
},
])
})

test("omits provider metadata when assistant model differs", async () => {
const userID = "m-user"
const assistantID = "m-assistant"
Expand Down
14 changes: 14 additions & 0 deletions packages/opencode/test/tool/edit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ describe("tool.edit", () => {
const { FileWatcher } = await import("../../src/file/watcher")

const events: string[] = []
let resolveUpdated!: () => void
const updated = new Promise<void>((resolve) => {
resolveUpdated = resolve
})
const unsubUpdated = Bus.subscribe(FileWatcher.Event.Updated, () => events.push("updated"))
const unsubUpdatedOnce = Bus.subscribe(FileWatcher.Event.Updated, () => resolveUpdated())

const edit = await EditTool.init()
await edit.execute(
Expand All @@ -101,7 +106,9 @@ describe("tool.edit", () => {
ctx,
)

await updated
expect(events).toContain("updated")
unsubUpdatedOnce()
unsubUpdated()
},
})
Expand Down Expand Up @@ -305,7 +312,12 @@ describe("tool.edit", () => {
const { FileWatcher } = await import("../../src/file/watcher")

const events: string[] = []
let resolveUpdated!: () => void
const updated = new Promise<void>((resolve) => {
resolveUpdated = resolve
})
const unsubUpdated = Bus.subscribe(FileWatcher.Event.Updated, () => events.push("updated"))
const unsubUpdatedOnce = Bus.subscribe(FileWatcher.Event.Updated, () => resolveUpdated())

const edit = await EditTool.init()
await edit.execute(
Expand All @@ -317,7 +329,9 @@ describe("tool.edit", () => {
ctx,
)

await updated
expect(events).toContain("updated")
unsubUpdatedOnce()
unsubUpdated()
},
})
Expand Down
Loading