mirror of
https://github.com/sst/opencode.git
synced 2025-07-07 16:14:59 +00:00
file attachments
This commit is contained in:
parent
32d5db4f0a
commit
ee01f01271
2 changed files with 51 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
||||||
import path from "path"
|
import path from "node:path"
|
||||||
import { App } from "../app/app"
|
import { App } from "../app/app"
|
||||||
import { Identifier } from "../id/id"
|
import { Identifier } from "../id/id"
|
||||||
import { Storage } from "../storage/storage"
|
import { Storage } from "../storage/storage"
|
||||||
|
@ -15,6 +15,7 @@ import {
|
||||||
type UIMessage,
|
type UIMessage,
|
||||||
type ProviderMetadata,
|
type ProviderMetadata,
|
||||||
wrapLanguageModel,
|
wrapLanguageModel,
|
||||||
|
type Attachment,
|
||||||
} from "ai"
|
} from "ai"
|
||||||
import { z, ZodSchema } from "zod"
|
import { z, ZodSchema } from "zod"
|
||||||
import { Decimal } from "decimal.js"
|
import { Decimal } from "decimal.js"
|
||||||
|
@ -187,7 +188,6 @@ export namespace Session {
|
||||||
export async function unshare(id: string) {
|
export async function unshare(id: string) {
|
||||||
const share = await getShare(id)
|
const share = await getShare(id)
|
||||||
if (!share) return
|
if (!share) return
|
||||||
console.log("share", share)
|
|
||||||
await Storage.remove("session/share/" + id)
|
await Storage.remove("session/share/" + id)
|
||||||
await update(id, (draft) => {
|
await update(id, (draft) => {
|
||||||
draft.share = undefined
|
draft.share = undefined
|
||||||
|
@ -361,6 +361,36 @@ export namespace Session {
|
||||||
if (lastSummary) msgs = msgs.filter((msg) => msg.id >= lastSummary.id)
|
if (lastSummary) msgs = msgs.filter((msg) => msg.id >= lastSummary.id)
|
||||||
|
|
||||||
const app = App.info()
|
const app = App.info()
|
||||||
|
input.parts = await Promise.all(
|
||||||
|
input.parts.map(async (part) => {
|
||||||
|
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) {
|
||||||
|
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:text/plain;base64," + btoa(content),
|
||||||
|
mediaType: "text/plain",
|
||||||
|
filename: part.filename,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return part
|
||||||
|
}),
|
||||||
|
)
|
||||||
if (msgs.length === 0 && !session.parentID) {
|
if (msgs.length === 0 && !session.parentID) {
|
||||||
generateText({
|
generateText({
|
||||||
maxTokens: input.providerID === "google" ? 1024 : 20,
|
maxTokens: input.providerID === "google" ? 1024 : 20,
|
||||||
|
@ -376,7 +406,7 @@ export namespace Session {
|
||||||
{
|
{
|
||||||
role: "user",
|
role: "user",
|
||||||
content: "",
|
content: "",
|
||||||
parts: toParts(input.parts),
|
...toParts(input.parts),
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
@ -1028,7 +1058,7 @@ function toUIMessage(msg: Message.Info): UIMessage {
|
||||||
id: msg.id,
|
id: msg.id,
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
content: "",
|
content: "",
|
||||||
parts: toParts(msg.parts),
|
...toParts(msg.parts),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,35 +1067,41 @@ function toUIMessage(msg: Message.Info): UIMessage {
|
||||||
id: msg.id,
|
id: msg.id,
|
||||||
role: "user",
|
role: "user",
|
||||||
content: "",
|
content: "",
|
||||||
parts: toParts(msg.parts),
|
...toParts(msg.parts),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("not implemented")
|
throw new Error("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
function toParts(parts: Message.MessagePart[]): UIMessage["parts"] {
|
function toParts(parts: Message.MessagePart[]) {
|
||||||
const result: UIMessage["parts"] = []
|
const result: {
|
||||||
|
parts: UIMessage["parts"]
|
||||||
|
experimental_attachments: Attachment[]
|
||||||
|
} = {
|
||||||
|
parts: [],
|
||||||
|
experimental_attachments: [],
|
||||||
|
}
|
||||||
for (const part of parts) {
|
for (const part of parts) {
|
||||||
switch (part.type) {
|
switch (part.type) {
|
||||||
case "text":
|
case "text":
|
||||||
result.push({ type: "text", text: part.text })
|
result.parts.push({ type: "text", text: part.text })
|
||||||
break
|
break
|
||||||
case "file":
|
case "file":
|
||||||
result.push({
|
result.experimental_attachments.push({
|
||||||
type: "file",
|
url: part.url,
|
||||||
data: part.url,
|
contentType: part.mediaType,
|
||||||
mimeType: part.mediaType,
|
name: part.filename,
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case "tool-invocation":
|
case "tool-invocation":
|
||||||
result.push({
|
result.parts.push({
|
||||||
type: "tool-invocation",
|
type: "tool-invocation",
|
||||||
toolInvocation: part.toolInvocation,
|
toolInvocation: part.toolInvocation,
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case "step-start":
|
case "step-start":
|
||||||
result.push({
|
result.parts.push({
|
||||||
type: "step-start",
|
type: "step-start",
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
|
@ -108,7 +108,7 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
attachment := &textarea.Attachment{
|
attachment := &textarea.Attachment{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
Display: "@" + fileName,
|
Display: "@" + fileName,
|
||||||
URL: fmt.Sprintf("file://%s", filePath),
|
URL: fmt.Sprintf("file://./%s", filePath),
|
||||||
Filename: fileName,
|
Filename: fileName,
|
||||||
MediaType: mediaType,
|
MediaType: mediaType,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue