@@ -2,6 +2,7 @@ import { BoxRenderable, TextareaRenderable, MouseEvent, PasteEvent, decodePasteB
22import { createEffect , createMemo , onMount , createSignal , onCleanup , on , Show , Switch , Match } from "solid-js"
33import "opentui-spinner/solid"
44import path from "path"
5+ import { fileURLToPath } from "url"
56import { Filesystem } from "@/util/filesystem"
67import { useLocal } from "@tui/context/local"
78import { useTheme } from "@tui/context/theme"
@@ -248,7 +249,7 @@ export function Prompt(props: PromptProps) {
248249 onSelect : async ( ) => {
249250 const content = await Clipboard . read ( )
250251 if ( content ?. mime . startsWith ( "image/" ) ) {
251- await pasteImage ( {
252+ await pasteAttachment ( {
252253 filename : "clipboard" ,
253254 mime : content . mime ,
254255 content : content . data ,
@@ -771,11 +772,16 @@ export function Prompt(props: PromptProps) {
771772 )
772773 }
773774
774- async function pasteImage ( file : { filename ?: string ; content : string ; mime : string } ) {
775+ async function pasteAttachment ( file : { filename ?: string ; filepath ?: string ; content : string ; mime : string } ) {
775776 const currentOffset = input . visualCursor . offset
776777 const extmarkStart = currentOffset
777- const count = store . prompt . parts . filter ( ( x ) => x . type === "file" && x . mime . startsWith ( "image/" ) ) . length
778- const virtualText = `[Image ${ count + 1 } ]`
778+ const pdf = file . mime === "application/pdf"
779+ const count = store . prompt . parts . filter ( ( x ) => {
780+ if ( x . type !== "file" ) return false
781+ if ( pdf ) return x . mime === "application/pdf"
782+ return x . mime . startsWith ( "image/" )
783+ } ) . length
784+ const virtualText = pdf ? `[PDF ${ count + 1 } ]` : `[Image ${ count + 1 } ]`
779785 const extmarkEnd = extmarkStart + virtualText . length
780786 const textToInsert = virtualText + " "
781787
@@ -796,7 +802,7 @@ export function Prompt(props: PromptProps) {
796802 url : `data:${ file . mime } ;base64,${ file . content } ` ,
797803 source : {
798804 type : "file" ,
799- path : file . filename ?? "" ,
805+ path : file . filepath ?? file . filename ?? "" ,
800806 text : {
801807 start : extmarkStart ,
802808 end : extmarkEnd ,
@@ -926,7 +932,7 @@ export function Prompt(props: PromptProps) {
926932 const content = await Clipboard . read ( )
927933 if ( content ?. mime . startsWith ( "image/" ) ) {
928934 e . preventDefault ( )
929- await pasteImage ( {
935+ await pasteAttachment ( {
930936 filename : "clipboard" ,
931937 mime : content . mime ,
932938 content : content . data ,
@@ -1012,9 +1018,16 @@ export function Prompt(props: PromptProps) {
10121018 return
10131019 }
10141020
1015- // trim ' from the beginning and end of the pasted content. just
1016- // ' and nothing else
1017- const filepath = pastedContent . replace ( / ^ ' + | ' + $ / g, "" ) . replace ( / \\ / g, " " )
1021+ const filepath = iife ( ( ) => {
1022+ const raw = pastedContent . replace ( / ^ [ ' " ] + | [ ' " ] + $ / g, "" )
1023+ if ( raw . startsWith ( "file://" ) ) {
1024+ try {
1025+ return fileURLToPath ( raw )
1026+ } catch { }
1027+ }
1028+ if ( process . platform === "win32" ) return raw
1029+ return raw . replace ( / \\ ( .) / g, "$1" )
1030+ } )
10181031 const isUrl = / ^ ( h t t p s ? ) : \/ \/ / . test ( filepath )
10191032 if ( ! isUrl ) {
10201033 try {
@@ -1029,14 +1042,15 @@ export function Prompt(props: PromptProps) {
10291042 return
10301043 }
10311044 }
1032- if ( mime . startsWith ( "image/" ) ) {
1045+ if ( mime . startsWith ( "image/" ) || mime === "application/pdf" ) {
10331046 event . preventDefault ( )
10341047 const content = await Filesystem . readArrayBuffer ( filepath )
10351048 . then ( ( buffer ) => Buffer . from ( buffer ) . toString ( "base64" ) )
10361049 . catch ( ( ) => { } )
10371050 if ( content ) {
1038- await pasteImage ( {
1051+ await pasteAttachment ( {
10391052 filename,
1053+ filepath,
10401054 mime,
10411055 content,
10421056 } )
0 commit comments