Add file attachments with @ mentions and drag & drop support

- Create attachment type system with file, text, symbol, and agent sources
- Implement file picker with SDK integration (find.files, file.status)
- Add @ detection in prompt input to trigger file search
- Create attachment chips UI for managing attached files
- Add attachment state management per session
- Update message submission to include attachments
- Implement drag & drop support for adding files
- Show git-modified files first in file picker with +/- indicators
- Filter files as user types after @
- Clear attachments after successful message send
This commit is contained in:
Shantur Rathore
2025-10-23 22:46:29 +01:00
parent 9dfb3cd612
commit bdd9837538
7 changed files with 536 additions and 18 deletions

87
src/types/attachment.ts Normal file
View File

@@ -0,0 +1,87 @@
export interface Attachment {
id: string
type: AttachmentType
display: string
url: string
filename: string
mediaType: string
source: AttachmentSource
}
export type AttachmentType = "file" | "text" | "symbol" | "agent"
export type AttachmentSource = FileSource | TextSource | SymbolSource | AgentSource
export interface FileSource {
type: "file"
path: string
mime: string
data?: Uint8Array
}
export interface TextSource {
type: "text"
value: string
}
export interface SymbolSource {
type: "symbol"
path: string
name: string
kind: number
range: SymbolRange
}
export interface SymbolRange {
start: Position
end: Position
}
export interface Position {
line: number
char: number
}
export interface AgentSource {
type: "agent"
name: string
}
export function createFileAttachment(
path: string,
filename: string,
mime: string = "text/plain",
data?: Uint8Array,
): Attachment {
const absolutePath = path.startsWith("/") ? path : `/${path}`
return {
id: crypto.randomUUID(),
type: "file",
display: `@${filename}`,
url: `file://${absolutePath}`,
filename,
mediaType: mime,
source: {
type: "file",
path: absolutePath,
mime,
data,
},
}
}
export function createTextAttachment(value: string, display: string, filename: string): Attachment {
const base64 = btoa(value)
return {
id: crypto.randomUUID(),
type: "text",
display,
url: `data:text/plain;base64,${base64}`,
filename,
mediaType: "text/plain",
source: {
type: "text",
value,
},
}
}