okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
87a6f95
main
1//// Fit composition and legacy backfill faults require packed database fixtures 2//// and exact source bounds that the HTTP E2E API does not expose. 3 4import albedo/daemon/conversation 5import albedo/daemon/family 6import albedo/daemon/history 7import albedo/daemon/image_fit 8import albedo/daemon/migrations/transcript_classes 9import albedo/daemon/store 10import albedo/daemon/transcript 11import albedo/harness/runtime 12import albedo/openai_api/types 13import gleam/bit_array 14import gleam/crypto 15import gleam/dynamic/decode 16import gleam/list 17import gleam/option .{ None , Some } 18import gleam/string 19import gleeunit/should 20 21@external ( erlang , "albedo_runtime_test_support" , "temporary_database" ) 22fn temporary_database () -> String 23 24@external ( erlang , "albedo_runtime_test_support" , "cleanup" ) 25fn cleanup ( path : String ) -> Nil 26 27fn picture ( hash : String ) -> types . Image { 28let assert Ok ( image ) = 29types . stored_image ( "image/png" , hash , 32 , fn () { Error ( Nil ) }, 2 , 3 , 24 ) 30image 31} 32 33fn fit ( source : String , replacement : types . Image ) -> transcript . ImageFit { 34transcript . ImageFit ( "fit" , source , replacement ) 35} 36 37pub fn reverse_fits_preserve_chains_repeated_sources_and_reuse_test () -> Nil { 38let original = picture ( "A" ) 39let second = picture ( "B" ) 40let third = picture ( "C" ) 41let input = types . UserImage ( "look" , [ original ]) 42let later = image_fit . add ( image_fit . replacements (), fit ( "A" , third )) 43image_fit . apply_replacements ( input , later ) 44|> should . equal ( types . UserImage ( "look" , [ third ])) 45let earlier = image_fit . add ( later , fit ( "A" , second )) 46image_fit . apply_replacements ( input , earlier ) 47|> should . equal ( types . UserImage ( "look" , [ second ])) 48let chain = 49image_fit . add ( 50image_fit . add ( image_fit . replacements (), fit ( "B" , third )), 51fit ( "A" , second ), 52) 53image_fit . apply_replacements ( input , chain ) 54|> should . equal ( types . UserImage ( "look" , [ third ])) 55} 56 57fn session () -> conversation . Info { 58conversation . Info ( 59"session" , 60"new session" , 61"/tmp" , 62"provider" , 63"model" , 64types . Responses , 65conversation . Idle , 66None , 67None , 68) 69} 70 71pub fn metadata_range_and_backfill_resume_test () -> Nil { 72let path = temporary_database () 73let assert Ok ( host ) = runtime . start ( path ) 74let ledger = runtime . ledger ( host ) 75let assert Ok ( _ ) = conversation . initialise ( ledger ) 76let assert Ok ( _ ) = conversation . create ( ledger , session ()) 77let inputs = list . repeat ( types . User ( "[note] daemon boundary" ), 260 ) 78let assert Ok ( _ ) = 79conversation . commit ( ledger , "session" , inputs , conversation . Idle ) 80let assert Ok ( _ ) = 81store . write ( ledger , "UPDATE transcript SET row_class=NULL" , []) 82// A corrupt row in the third batch is healed into a user-role note and 83// classified with it; its bytes are kept, and every batch completes. 84let assert Ok ( _ ) = 85store . write ( ledger , "UPDATE transcript SET payload=X'00' WHERE seq=260" , []) 86let assert Ok ( _ ) = transcript_classes . run ( ledger ) 87let assert Ok ([ pending ]) = 88store . read ( 89ledger , 90"SELECT COUNT(*) FROM transcript WHERE row_class IS NULL" , 91[], 92decode . field ( 0 , decode . int , decode . success ), 93) 94pending |> should . equal ( 0 ) 95let assert Ok ( quarantined ) = 96store . read ( ledger , "SELECT seq,payload FROM transcript_quarantine" , [], { 97use seq <- decode . field ( 0 , decode . int ) 98use payload <- decode . field ( 1 , decode . bit_array ) 99decode . success (#( seq , payload )) 100}) 101quarantined |> should . equal ([#( 260 , << 0 >>)]) 102let assert Ok ( snapshot ) = conversation . snapshot ( ledger , "session" ) 103let assert Ok ( stats ) = conversation . source_stats ( ledger , snapshot , 128 ) 104stats |> should . equal ( conversation . SourceStats ( Some ( 260 ), True , 132 )) 105let assert Ok ( selected ) = 106conversation . fold_sources ( ledger , snapshot , 128 , 132 , [], fn ( acc , row ) { 107conversation . Continue ([ row . source . seq , .. acc ]) 108}) 109selected |> should . equal ([ 132 , 131 , 130 , 129 , 128 ]) 110let assert Ok ( first ) = 111conversation . fold_sources ( ledger , snapshot , 1 , 260 , 0 , fn ( _ , row ) { 112conversation . Stop ( row . source . seq ) 113}) 114first |> should . equal ( 1 ) 115runtime . stop ( host ) 116cleanup ( path ) 117} 118 119pub fn ranged_images_equal_full_history_with_later_fits_test () -> Nil { 120let path = temporary_database () 121let assert Ok ( host ) = runtime . start ( path ) 122let ledger = runtime . ledger ( host ) 123let assert Ok ( _ ) = conversation . initialise ( ledger ) 124let assert Ok ( _ ) = family . initialise ( ledger ) 125let assert Ok ( _ ) = conversation . create ( ledger , session ()) 126let data = "iVBORw0KGgoAAAANSUhEUgAAAAIAAAAD" 127let assert Ok ( original ) = types . image ( "image/png" , data , 2 , 3 , 24 ) 128let assert Ok ( second ) = types . image ( "image/png" , data <> "AAAA" , 2 , 3 , 27 ) 129let assert Ok ( third ) = types . image ( "image/png" , data <> "BBBB" , 2 , 3 , 27 ) 130let source = 131crypto . hash ( crypto . Sha256 , bit_array . from_string ( data )) 132|> bit_array . base16_encode 133|> string . lowercase 134let assert Ok ( _ ) = 135conversation . commit ( 136ledger , 137"session" , 138[ types . UserImage ( "before" , [ original ])], 139conversation . Idle , 140) 141let assert Ok ( _ ) = 142conversation . commit_fits ( 143ledger , 144"session" , 145[ fit ( source , second )], 146"provider" , 147) 148let assert Ok ( _ ) = 149conversation . commit ( 150ledger , 151"session" , 152[ types . UserImage ( "reuse" , [ original ])], 153conversation . Idle , 154) 155let assert Ok ( before_last_fit ) = conversation . snapshot ( ledger , "session" ) 156let assert Ok ( _ ) = 157conversation . commit_fits ( 158ledger , 159"session" , 160[ fit ( source , third )], 161"provider" , 162) 163let assert Ok ( snapshot ) = conversation . snapshot ( ledger , "session" ) 164let assert Ok ( stats ) = conversation . source_stats ( ledger , snapshot , 0 ) 165stats . uncovered_users |> should . equal ( 4 ) 166let assert Ok ( full ) = conversation . load_sources ( ledger , "session" ) 167let assert Ok ( range ) = 168conversation . fold_sources ( ledger , snapshot , 1 , 3 , [], fn ( acc , row ) { 169conversation . Continue ([ row , .. acc ]) 170}) 171// Image reader functions are fresh closures, so compare content fingerprints. 172list . reverse ( range ) 173|> list . map ( fn ( row ) { fingerprint ( row . entry . input ) }) 174|> should . equal ( 175list . take ( full , 3 ) |> list . map ( fn ( row ) { fingerprint ( row . entry . input ) }), 176) 177let assert Ok ( reused ) = 178conversation . fold_sources ( ledger , snapshot , 3 , 3 , [], fn ( acc , row ) { 179conversation . Continue ([ fingerprint ( row . entry . input ), .. acc ]) 180}) 181reused |> should . equal ([ fingerprint ( types . UserImage ( "reuse" , [ third ]))]) 182let assert Ok ( before ) = 183conversation . fold_sources ( ledger , before_last_fit , 3 , 3 , [], fn ( acc , row ) { 184conversation . Continue ([ fingerprint ( row . entry . input ), .. acc ]) 185}) 186before |> should . equal ([ fingerprint ( types . UserImage ( "reuse" , [ original ]))]) 187let assert Ok ( _ ) = history . fork ( ledger , "session" , "branch" , 2 ) 188let assert Ok ( branch ) = conversation . snapshot ( ledger , "branch" ) 189let assert Ok ( branch_stats ) = conversation . source_stats ( ledger , branch , 0 ) 190branch_stats . uncovered_users |> should . equal ( 2 ) 191let assert Ok ( branch_rows ) = conversation . load_sources ( ledger , "branch" ) 192let assert [ first , ..] = branch_rows 193fingerprint ( first . entry . input ) 194|> should . equal ( fingerprint ( types . UserImage ( "before" , [ second ]))) 195runtime . stop ( host ) 196cleanup ( path ) 197} 198 199@external ( erlang , "albedo_compaction" , "fingerprint" ) 200fn fingerprint ( value : a) -> String