Buckets:
| import { getFilename } from "@opencode-ai/core/util/path" | |
| import { type AgentPartInput, type FilePartInput, type Part, type TextPartInput } from "@opencode-ai/sdk/v2/client" | |
| import type { FileSelection } from "@/context/file" | |
| import { encodeFilePath } from "@/context/file/path" | |
| import type { AgentPart, FileAttachmentPart, ImageAttachmentPart, Prompt } from "@/context/prompt" | |
| import { Identifier } from "@/utils/id" | |
| import { createCommentMetadata, formatCommentNote } from "@/utils/comment-note" | |
| type PromptRequestPart = (TextPartInput | FilePartInput | AgentPartInput) & { id: string } | |
| type ContextFile = { | |
| key: string | |
| type: "file" | |
| path: string | |
| selection?: FileSelection | |
| comment?: string | |
| commentID?: string | |
| commentOrigin?: "review" | "file" | |
| preview?: string | |
| } | |
| type BuildRequestPartsInput = { | |
| prompt: Prompt | |
| context: ContextFile[] | |
| images: ImageAttachmentPart[] | |
| text: string | |
| messageID: string | |
| sessionID: string | |
| sessionDirectory: string | |
| } | |
| const absolute = (directory: string, path: string) => { | |
| if (path.startsWith("/")) return path | |
| if (/^[A-Za-z]:[\\/]/.test(path) || /^[A-Za-z]:$/.test(path)) return path | |
| if (path.startsWith("\\\\") || path.startsWith("//")) return path | |
| return `${directory.replace(/[\\/]+$/, "")}/${path}` | |
| } | |
| const fileQuery = (selection: FileSelection | undefined) => | |
| selection ? `?start=${selection.startLine}&end=${selection.endLine}` : "" | |
| const mention = /(^|[\s([{"'])@(\S+)/g | |
| const parseCommentMentions = (comment: string) => { | |
| return Array.from(comment.matchAll(mention)).flatMap((match) => { | |
| const path = (match[2] ?? "").replace(/[.,!?;:)}\]"']+$/, "") | |
| if (!path) return [] | |
| return [path] | |
| }) | |
| } | |
| const isFileAttachment = (part: Prompt[number]): part is FileAttachmentPart => part.type === "file" | |
| const isAgentAttachment = (part: Prompt[number]): part is AgentPart => part.type === "agent" | |
| const toOptimisticPart = (part: PromptRequestPart, sessionID: string, messageID: string): Part => { | |
| if (part.type === "text") { | |
| return { | |
| id: part.id, | |
| type: "text", | |
| text: part.text, | |
| synthetic: part.synthetic, | |
| ignored: part.ignored, | |
| time: part.time, | |
| metadata: part.metadata, | |
| sessionID, | |
| messageID, | |
| } | |
| } | |
| if (part.type === "file") { | |
| return { | |
| id: part.id, | |
| type: "file", | |
| mime: part.mime, | |
| filename: part.filename, | |
| url: part.url, | |
| source: part.source, | |
| sessionID, | |
| messageID, | |
| } | |
| } | |
| return { | |
| id: part.id, | |
| type: "agent", | |
| name: part.name, | |
| source: part.source, | |
| sessionID, | |
| messageID, | |
| } | |
| } | |
| export function buildRequestParts(input: BuildRequestPartsInput) { | |
| const requestParts: PromptRequestPart[] = [ | |
| { | |
| id: Identifier.ascending("part"), | |
| type: "text", | |
| text: input.text, | |
| }, | |
| ] | |
| const files = input.prompt.filter(isFileAttachment).map((attachment) => { | |
| const path = absolute(input.sessionDirectory, attachment.path) | |
| return { | |
| id: Identifier.ascending("part"), | |
| type: "file", | |
| mime: "text/plain", | |
| url: `file://${encodeFilePath(path)}${fileQuery(attachment.selection)}`, | |
| filename: getFilename(attachment.path), | |
| source: { | |
| type: "file", | |
| text: { | |
| value: attachment.content, | |
| start: attachment.start, | |
| end: attachment.end, | |
| }, | |
| path, | |
| }, | |
| } satisfies PromptRequestPart | |
| }) | |
| const agents = input.prompt.filter(isAgentAttachment).map((attachment) => { | |
| return { | |
| id: Identifier.ascending("part"), | |
| type: "agent", | |
| name: attachment.name, | |
| source: { | |
| value: attachment.content, | |
| start: attachment.start, | |
| end: attachment.end, | |
| }, | |
| } satisfies PromptRequestPart | |
| }) | |
| const used = new Set(files.map((part) => part.url)) | |
| const context = input.context.flatMap((item) => { | |
| const path = absolute(input.sessionDirectory, item.path) | |
| const url = `file://${encodeFilePath(path)}${fileQuery(item.selection)}` | |
| const comment = item.comment?.trim() | |
| if (!comment && used.has(url)) return [] | |
| used.add(url) | |
| const filePart = { | |
| id: Identifier.ascending("part"), | |
| type: "file", | |
| mime: "text/plain", | |
| url, | |
| filename: getFilename(item.path), | |
| } satisfies PromptRequestPart | |
| if (!comment) return [filePart] | |
| const mentions = parseCommentMentions(comment).flatMap((path) => { | |
| const url = `file://${encodeFilePath(absolute(input.sessionDirectory, path))}` | |
| if (used.has(url)) return [] | |
| used.add(url) | |
| return [ | |
| { | |
| id: Identifier.ascending("part"), | |
| type: "file", | |
| mime: "text/plain", | |
| url, | |
| filename: getFilename(path), | |
| } satisfies PromptRequestPart, | |
| ] | |
| }) | |
| return [ | |
| { | |
| id: Identifier.ascending("part"), | |
| type: "text", | |
| text: formatCommentNote({ path: item.path, selection: item.selection, comment }), | |
| synthetic: true, | |
| metadata: createCommentMetadata({ | |
| path: item.path, | |
| selection: item.selection, | |
| comment, | |
| preview: item.preview, | |
| origin: item.commentOrigin, | |
| }), | |
| } satisfies PromptRequestPart, | |
| filePart, | |
| ...mentions, | |
| ] | |
| }) | |
| const images = input.images.map((attachment) => { | |
| return { | |
| id: Identifier.ascending("part"), | |
| type: "file", | |
| mime: attachment.mime, | |
| url: attachment.dataUrl, | |
| filename: attachment.filename, | |
| } satisfies PromptRequestPart | |
| }) | |
| requestParts.push(...files, ...context, ...agents, ...images) | |
| return { | |
| requestParts, | |
| optimisticParts: requestParts.map((part) => toOptimisticPart(part, input.sessionID, input.messageID)), | |
| } | |
| } | |
Xet Storage Details
- Size:
- 5.74 kB
- Xet hash:
- 7202fb20880be26114a6a8f77e2d1c6f13ab2d451da05fe2cecac7f1ab805593
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.