@@ -20,6 +20,7 @@ import (
2020
2121 "telegram-agent/internal/agent"
2222 "telegram-agent/internal/config"
23+ "telegram-agent/internal/evalpack"
2324 "telegram-agent/internal/llm"
2425 "telegram-agent/internal/store"
2526)
@@ -161,7 +162,30 @@ func TestTemplatesParse(t *testing.T) {
161162 viewIndex : data ,
162163 viewRouting : data .Routing , // routing view takes uiRouting directly
163164 viewModelsBrowser : data ,
164- viewTGAdmin : tgAdminData {FullAdminURL : "https://assistant.example/admin" },
165+ viewEvals : modelOpsData {
166+ ActiveTab : "evals" ,
167+ Checks : []modelCheckStatus {{
168+ Status : "free_verified" ,
169+ Provider : "openrouter" ,
170+ ModelID : "qwen/qwen3.5-flash:free" ,
171+ CheckedAt : "2026-06-16T10:00:00Z" ,
172+ }},
173+ Evals : []modelEvalStatus {{
174+ Status : "passed" ,
175+ Provider : "openrouter" ,
176+ ModelID : "qwen/qwen3.5-flash:free" ,
177+ CheckedAt : "2026-06-16T10:00:00Z" ,
178+ FinishedAt : "2026-06-16T10:00:00Z" ,
179+ Passed : 1 ,
180+ Results : []evalpack.Result {{ID : "case-1" , Category : "smoke" , Passed : true }},
181+ }},
182+ Suite : evalpack.Suite {Version : 1 , Name : "suite" , Cases : []evalpack.Case {{
183+ ID : "case-1" ,
184+ Category : "smoke" ,
185+ Prompt : "Say ok" ,
186+ }}},
187+ },
188+ viewTGAdmin : tgAdminData {FullAdminURL : "https://assistant.example/admin" },
165189 }
166190 for v , d := range cases {
167191 t .Run (v , func (t * testing.T ) {
@@ -357,6 +381,121 @@ func TestModelEvalPaidGuard(t *testing.T) {
357381 }
358382}
359383
384+ func TestEvalsPageRendersChecksReportsAndSuite (t * testing.T ) {
385+ data := modelOpsData {
386+ ActiveTab : "evals" ,
387+ Checks : []modelCheckStatus {{
388+ Status : "checking" ,
389+ Provider : "openrouter" ,
390+ ModelID : "qwen/qwen3.5-flash:free" ,
391+ StartedAt : "2026-06-16T10:00:00Z" ,
392+ }},
393+ Evals : []modelEvalStatus {{
394+ Status : "failed" ,
395+ Provider : "openrouter" ,
396+ ModelID : "x-ai/grok-4.3" ,
397+ Suite : "personal-assistant-core-workloads" ,
398+ StartedAt : "2026-06-16T10:00:00Z" ,
399+ FinishedAt : "2026-06-16T10:00:02Z" ,
400+ Passed : 4 ,
401+ Failed : 1 ,
402+ Failures : []string {"tool-web-fetch-intent: missing tool call" },
403+ Results : []evalpack.Result {{
404+ ID : "tool-web-fetch-intent" ,
405+ Category : "web_fetch" ,
406+ Passed : false ,
407+ LatencyMS : 1200 ,
408+ ContentPreview : "I cannot open links." ,
409+ Failures : []string {"missing tool call \" web_fetch\" " },
410+ }},
411+ }},
412+ Suite : evalpack.Suite {Version : 1 , Name : "personal-assistant-core-workloads" , Cases : []evalpack.Case {{
413+ ID : "tool-web-fetch-intent" ,
414+ Category : "web_fetch" ,
415+ Prompt : "Open https://example.com" ,
416+ Expect : evalpack.Expect {ToolCall : "web_fetch" },
417+ }}},
418+ }
419+ var buf bytes.Buffer
420+ if err := render (& buf , viewEvals , data ); err != nil {
421+ t .Fatal (err )
422+ }
423+ html := buf .String ()
424+ for _ , want := range []string {"Model Operations" , "checking" , "x-ai/grok-4.3" , "tool-web-fetch-intent" , "Open https://example.com" , "missing tool call" } {
425+ if ! strings .Contains (html , want ) {
426+ t .Fatalf ("evals page missing %q: %s" , want , html )
427+ }
428+ }
429+ }
430+
431+ func TestModelChecksPersistCheckingBeforeProbe (t * testing.T ) {
432+ s , _ := newTGModelTestServer (t )
433+ settings := & fakeSettingsStore {values : map [string ]string {}}
434+ s .settings = settings
435+ s .modelProbe = func (ctx context.Context , provider , modelID string , _ llm.Capabilities ) modelCheckStatus {
436+ got := s .modelCheckStatus (ctx , provider , modelID )
437+ if got .Status != "checking" || got .StartedAt == "" {
438+ t .Fatalf ("expected checking state before probe, got %+v" , got )
439+ }
440+ return modelCheckStatus {Status : "free_verified" , CheckedAt : time .Now ().Format (time .RFC3339 ), LatencyMS : 22 }
441+ }
442+
443+ form := url.Values {}
444+ form .Set ("provider" , "openrouter" )
445+ form .Set ("model_id" , "qwen/qwen3.5-flash:free" )
446+ req := httptest .NewRequest (http .MethodPost , "/models/check" , strings .NewReader (form .Encode ()))
447+ req .Header .Set ("Content-Type" , "application/x-www-form-urlencoded" )
448+ rec := httptest .NewRecorder ()
449+ s .handleModelCheck (rec , req )
450+ if rec .Code != http .StatusOK {
451+ t .Fatalf ("status = %d, body=%s" , rec .Code , rec .Body .String ())
452+ }
453+ got := s .modelCheckStatus (context .Background (), "openrouter" , "qwen/qwen3.5-flash:free" )
454+ if got .Status != "free_verified" || got .LatencyMS != 22 {
455+ t .Fatalf ("final check state not persisted: %+v" , got )
456+ }
457+ }
458+
459+ func TestModelEvalLoadLegacyAndDetailedReports (t * testing.T ) {
460+ s := newTestServer (t )
461+ legacy := map [string ]modelEvalStatus {
462+ modelCheckKey ("openrouter" , "legacy/model" ): {
463+ CheckedAt : "2026-06-16T10:00:00Z" ,
464+ Passed : 4 ,
465+ Failed : 1 ,
466+ Failures : []string {"legacy failure" },
467+ },
468+ }
469+ data , err := json .Marshal (legacy )
470+ if err != nil {
471+ t .Fatal (err )
472+ }
473+ s .settings = & fakeSettingsStore {values : map [string ]string {settingKeyModelEvals : string (data )}}
474+ evals := s .loadModelEvals (context .Background ())
475+ got := evals [modelCheckKey ("openrouter" , "legacy/model" )]
476+ if got .Status != "failed" || got .Provider != "openrouter" || got .ModelID != "legacy/model" {
477+ t .Fatalf ("legacy eval not normalized: %+v" , got )
478+ }
479+
480+ detailed := modelEvalStatus {
481+ Status : "passed" ,
482+ Provider : "openrouter" ,
483+ ModelID : "new/model" ,
484+ Suite : "suite" ,
485+ StartedAt : "2026-06-16T10:01:00Z" ,
486+ Passed : 1 ,
487+ Results : []evalpack.Result {{ID : "case-1" , Category : "smoke" , Passed : true , ContentPreview : "ok" }},
488+ }
489+ if err := s .saveModelEval (context .Background (), "openrouter" , "new/model" , detailed ); err != nil {
490+ t .Fatal (err )
491+ }
492+ evals = s .loadModelEvals (context .Background ())
493+ got = evals [modelCheckKey ("openrouter" , "new/model" )]
494+ if got .Status != "passed" || len (got .Results ) != 1 || got .Results [0 ].ContentPreview != "ok" {
495+ t .Fatalf ("detailed eval not persisted: %+v" , got )
496+ }
497+ }
498+
360499func TestWebModelCheckPersistsFreeModelStatus (t * testing.T ) {
361500 s , _ := newTGModelTestServer (t )
362501 settings := & fakeSettingsStore {values : map [string ]string {}}
0 commit comments