@@ -713,6 +713,49 @@ describe("AssetAccess", () => {
713713 } ) . pipe ( Effect . provide ( testLayer ) ) ,
714714 ) ;
715715
716+ it . effect ( "previews workspace files with literal fragment characters in their paths" , ( ) =>
717+ Effect . gen ( function * ( ) {
718+ const fileSystem = yield * FileSystem . FileSystem ;
719+ const path = yield * Path . Path ;
720+ const root = yield * fileSystem . makeTempDirectoryScoped ( { prefix : "t3-preview-literal-" } ) ;
721+ const directory = path . join ( root , "assets#archive" ) ;
722+ yield * fileSystem . makeDirectory ( directory ) ;
723+
724+ for ( const name of [ "icon#v2.png" , "report#draft.pdf" ] ) {
725+ const filePath = path . join ( directory , name ) ;
726+ yield * fileSystem . writeFileString ( filePath , "preview fixture" ) ;
727+ const canonicalFile = yield * fileSystem . realPath ( filePath ) ;
728+ const result = yield * issueAssetUrl ( {
729+ resource : {
730+ _tag : "workspace-file" ,
731+ threadId : ThreadId . make ( "thread-1" ) ,
732+ path : filePath ,
733+ } ,
734+ workspaceRoot : root ,
735+ } ) ;
736+ const suffix = result . relativeUrl . slice ( `${ ASSET_ROUTE_PREFIX } /` . length ) ;
737+ const token = suffix . slice ( 0 , suffix . indexOf ( "/" ) ) ;
738+
739+ expect ( yield * resolveAsset ( token , name ) ) . toEqual ( { kind : "file" , path : canonicalFile } ) ;
740+ if ( name . endsWith ( ".png" ) ) {
741+ expect ( yield * resolveAsset ( token , "other.png" ) ) . toBeNull ( ) ;
742+ }
743+ }
744+
745+ const disguisedPath = path . join ( root , "image.png#notes.txt" ) ;
746+ yield * fileSystem . writeFileString ( disguisedPath , "not an image" ) ;
747+ const error = yield * issueAssetUrl ( {
748+ resource : {
749+ _tag : "workspace-file" ,
750+ threadId : ThreadId . make ( "thread-1" ) ,
751+ path : disguisedPath ,
752+ } ,
753+ workspaceRoot : root ,
754+ } ) . pipe ( Effect . flip ) ;
755+ expect ( error ) . toBeInstanceOf ( AssetPreviewTypeValidationError ) ;
756+ } ) . pipe ( Effect . provide ( testLayer ) ) ,
757+ ) ;
758+
716759 it . effect ( "issues exact attachment capabilities by attachment id" , ( ) =>
717760 Effect . gen ( function * ( ) {
718761 const config = yield * ServerConfig . ServerConfig ;
0 commit comments