char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
e21152dc9
char/aliceai-t5-moe
1import { abbreviateHome , lastPathSegment } from './path-display' ; 2import { 3DIRECTORY_PATH_SUFFIX , 4FILE_URI_PREFIX , 5MENTION_BADGE_FILE_ICON_PATHS , 6MENTION_BADGE_FOLDER_ICON_PATHS , 7MENTION_LINK_SCAN_FLAGS 8} from '$lib/constants' ; 9import { FileMentionEntryType } from '$lib/enums' ; 10import type { FileMentionEntry } from '$lib/types' ; 11 12export { 13MENTION_BADGE_CLASSNAME , 14MENTION_BADGE_ICON_CLASSNAME , 15MENTION_BADGE_SVG_ATTRIBUTES , 16MENTION_BADGE_FILE_ICON_PATHS , 17MENTION_BADGE_FOLDER_ICON_PATHS 18} from '$lib/constants' ; 19 20// `)` is allowed in a path only when not followed by whitespace or `[`, 21// so macOS paths parse while adjacent badges still terminate the match. 22const FILE_MENTION_LINK_SOURCE = String . raw `\[([^\]\n]+?)\]\(file:\/\/((?:[^)\n]|\)(?![\s[]))+)\)` ; 23 24export function fileMentionLinkRe ( flags = '' ) :RegExp { 25return new RegExp ( FILE_MENTION_LINK_SOURCE , flags ); 26} 27 28export function containsFileMentionLink ( value :string ) :boolean { 29return fileMentionLinkRe (). test ( value ); 30} 31 32// Escape each path segment for a markdown link destination (spaces/parens 33// break CommonMark); keeps the trailing slash that marks a directory. 34export function encodeFileLinkPath ( path :string ) :string { 35return path 36. split ( '/' ) 37. map (( segment ) => encodeURIComponent ( segment )) 38. join ( '/' ); 39} 40 41// Malformed escape sequences fall back to the input unchanged. 42export function decodeFileLinkPath ( path :string ) :string { 43try { 44return path 45. split ( '/' ) 46. map (( segment ) => decodeURIComponent ( segment )) 47. join ( '/' ); 48} catch { 49return path ; 50} 51} 52 53export interface MentionTextSegment { 54text :string ; 55mention :{ name :string ; path :string } | null ; 56} 57 58/** 59* Split raw text into plain runs and `[name](file://path)` mentions. 60* The raw-text renderers walk these segments to draw badges without 61* handing the message to the markdown parser, so a `#` stays a `#`. 62*/ 63export function splitMentionSegments ( value :string ) :MentionTextSegment [] { 64const linkRe = fileMentionLinkRe ( MENTION_LINK_SCAN_FLAGS ); 65const segments :MentionTextSegment [] = []; 66 67let cursor = 0 ; 68let match :RegExpExecArray | null ; 69 70while (( match = linkRe . exec ( value )) !== null ) { 71if ( match . index > cursor ) { 72segments . push ({ mention :null , text :value . slice ( cursor , match . index ) }); 73} 74 75segments . push ({ 76mention :{ name :match [ 1 ], path :decodeFileLinkPath ( match [ 2 ]) }, 77text :match [ 0 ] 78}); 79 80cursor = match . index + match [ 0 ]. length ; 81} 82 83if ( cursor < value . length ) segments . push ({ mention :null , text :value . slice ( cursor ) }); 84 85return segments ; 86} 87 88export function getMentionBadgeIconPaths ( path :string ) :readonly string [] { 89return path . endsWith ( DIRECTORY_PATH_SUFFIX ) 90 ?MENTION_BADGE_FOLDER_ICON_PATHS 91 :MENTION_BADGE_FILE_ICON_PATHS ; 92} 93 94export function getMentionBadgeLabel ( 95name :string , 96path :string , 97showFullPath :boolean , 98home ?:string | null 99) :string { 100if ( ! showFullPath ) return name ; 101 102const decoded = decodeFileLinkPath ( path . replace ( / \/+$ / , '' )); 103 104if ( ! decoded ) return name ; 105 106return abbreviateHome ( decoded , home ); 107} 108 109/** 110* Build the markdown link that replaces a mention token. Entry `path` is 111* already rooted, so `file://` + `/abs` yields the canonical `file:///`. 112* Null when the token is invalid. 113*/ 114export function buildMentionInsertion ( 115entry :FileMentionEntry , 116value :string , 117token :{ start :number ; end :number } 118) :{ newValue :string ; caretOffset :number } | null { 119if ( token . start < 0 || token . end > value . length || token . start > token . end ) return null ; 120 121// Strip the entry's directory marker so it is not doubled below. 122const cleanedPath = entry . path . replace ( / \/+$ / , '' ); 123const pathWithSeparator = 124entry . type === FileMentionEntryType . DIRECTORY ?` ${ cleanedPath } /` :cleanedPath ; 125const basename = lastPathSegment ( cleanedPath ) || entry . name ; 126const insertion = `[ ${ basename } ]( ${ FILE_URI_PREFIX } ${ encodeFileLinkPath ( pathWithSeparator )} ) ` ; 127const newValue = value . slice ( 0 , token . start ) + insertion + value . slice ( token . end ); 128 129return { caretOffset :token . start + insertion . length , newValue}; 130}