aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-14 15:48:51 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-15 10:08:05 +0000
commit82a2649e8d7d7a5cc81051c0a3520368a98cfbb2 (patch)
tree92e1ff210804f948e3e0140f0a96d00a127e35f0
parent3b7a3359989abfb9ee0c821fdc0a8be33f7e996d (diff)
dashboard/app: improve AI UI
A bag of minor assorted improvements to data formatting. + show job results in the jobs table
-rw-r--r--dashboard/app/ai.go44
-rw-r--r--dashboard/app/main.go2
-rw-r--r--dashboard/app/templates/ai_job.html12
-rw-r--r--dashboard/app/templates/templates.html18
-rw-r--r--pkg/html/pages/style.css8
5 files changed, 58 insertions, 26 deletions
diff --git a/dashboard/app/ai.go b/dashboard/app/ai.go
index 2912addea..511865da3 100644
--- a/dashboard/app/ai.go
+++ b/dashboard/app/ai.go
@@ -34,17 +34,15 @@ type uiAIJobPage struct {
Job *uiAIJob
// The slice contains the same single Job, just for HTML templates convenience.
Jobs []*uiAIJob
- Results []*uiAIResult
Trajectory []*uiAITrajectorySpan
}
type uiAIJob struct {
- ID string
- Link string
- Workflow string
- Description string
- DescriptionLink string
-
+ ID string
+ Link string
+ Workflow string
+ Description string
+ DescriptionLink string
Created time.Time
Started time.Time
Finished time.Time
@@ -53,11 +51,13 @@ type uiAIJob struct {
CodeRevisionLink string
Error string
Correct string
+ Results []*uiAIResult
}
type uiAIResult struct {
- Name string
- Value any
+ Name string
+ IsBool bool
+ Value any
}
type uiAITrajectorySpan struct {
@@ -138,21 +138,32 @@ func handleAIJobPage(ctx context.Context, w http.ResponseWriter, r *http.Request
Jobs: []*uiAIJob{uiJob},
Trajectory: makeUIAITrajectory(trajectory),
}
+ return serveTemplate(w, "ai_job.html", page)
+}
+
+func makeUIAIJob(job *aidb.Job) *uiAIJob {
+ var results []*uiAIResult
if m, ok := job.Results.Value.(map[string]any); ok && job.Results.Valid {
for name, value := range m {
- page.Results = append(page.Results, &uiAIResult{
- Name: name,
- Value: value,
+ _, isBool := value.(bool)
+ results = append(results, &uiAIResult{
+ Name: name,
+ IsBool: isBool,
+ Value: value,
})
}
}
- slices.SortFunc(page.Results, func(a, b *uiAIResult) int {
+ slices.SortFunc(results, func(a, b *uiAIResult) int {
+ // Pop up bool flags to the top.
+ if a.IsBool != b.IsBool {
+ if a.IsBool {
+ return -1
+ }
+ return 1
+ }
return strings.Compare(a.Name, b.Name)
})
- return serveTemplate(w, "ai_job.html", page)
-}
-func makeUIAIJob(job *aidb.Job) *uiAIJob {
correct := aiCorrectnessIncorrect
if !job.Finished.Valid {
correct = aiCorrectnessPending
@@ -177,6 +188,7 @@ func makeUIAIJob(job *aidb.Job) *uiAIJob {
CodeRevisionLink: vcs.LogLink(vcs.SyzkallerRepo, job.CodeRevision),
Error: job.Error,
Correct: correct,
+ Results: results,
}
}
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 30a30eb84..e9a1cf106 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -84,7 +84,7 @@ func initHTTPHandlers() {
http.Handle("/"+ns+"/backports", handlerWrapper(handleBackports))
http.Handle("/"+ns+"/s/", handlerWrapper(handleSubsystemPage))
http.Handle("/"+ns+"/manager/", handlerWrapper(handleManagerPage))
- http.Handle("/"+ns+"/ai/", handlerWrapper(handleAIJobsPage))
+ http.Handle("/"+ns+"/ai", handlerWrapper(handleAIJobsPage))
}
http.HandleFunc("/cron/cache_update", cacheUpdate)
http.HandleFunc("/cron/minute_cache_update", handleMinuteCacheUpdate)
diff --git a/dashboard/app/templates/ai_job.html b/dashboard/app/templates/ai_job.html
index 5a45654f8..34c7d39e8 100644
--- a/dashboard/app/templates/ai_job.html
+++ b/dashboard/app/templates/ai_job.html
@@ -28,11 +28,17 @@ Detailed info on a single AI job execution.
<button type="submit">Set</button>
</fieldset>
</form>
+ <br>
{{end}}
- {{range $res := .Results}}
- <br><b>{{$res.Name}}:</b><br>
- <div id="ai_result_div"><pre>{{$res.Value}}</pre></div><br>
+ {{range $res := .Job.Results}}
+ {{if $res.IsBool}}
+ <b>{{$res.Name}}:</b>
+ {{if $res.Value}}✅{{else}}❌{{end}}&nbsp;&nbsp;&nbsp;
+ {{else}}
+ <br><br><b>{{$res.Name}}:</b>
+ <br><div id="ai_result_div"><pre>{{$res.Value}}</pre></div>
+ {{end}}
{{end}}
<table class="list_table">
diff --git a/dashboard/app/templates/templates.html b/dashboard/app/templates/templates.html
index 15f50a287..dee2d1300 100644
--- a/dashboard/app/templates/templates.html
+++ b/dashboard/app/templates/templates.html
@@ -683,8 +683,9 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
<thead><tr>
<th><a onclick="return sortTable(this, 'ID', textSort)" href="#">ID</a></th>
<th><a onclick="return sortTable(this, 'Workflow', textSort)" href="#">Workflow</a></th>
+ <th><a onclick="return sortTable(this, 'Result', textSort)" href="#">Result</a></th>
<th><a onclick="return sortTable(this, 'Correct', textSort)" href="#">Correct</a></th>
- <th><a onclick="return sortTable(this, 'Description', textSort)" href="#">Description</a></th>
+ <th><a onclick="return sortTable(this, 'Bug', textSort)" href="#">Bug</a></th>
<th><a onclick="return sortTable(this, 'Created', textSort)" href="#">Created</a></th>
<th><a onclick="return sortTable(this, 'Started', textSort)" href="#">Started</a></th>
<th><a onclick="return sortTable(this, 'Finished', textSort)" href="#">Finished</a></th>
@@ -695,15 +696,22 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
<tbody>
{{range $job := .}}
<tr>
- <td>{{link $job.Link $job.ID}}</td>
+ <td class="tag">{{link $job.Link $job.ID}}</td>
<td>{{$job.Workflow}}</td>
- <td>{{$job.Correct}}</td>
- <td>{{link $job.DescriptionLink $job.Description}}</td>
+ <td>
+ {{range $res := $job.Results}}
+ {{if $res.IsBool}}
+ {{$res.Name}}: {{if $res.Value}}✅{{else}}❌{{end}}&nbsp;
+ {{end}}
+ {{end}}
+ </td>
+ <td class="ai_correct">{{$job.Correct}}</td>
+ <td class="title">{{link $job.DescriptionLink $job.Description}}</td>
<td>{{formatTime $job.Created}}</td>
<td>{{formatTime $job.Started}}</td>
<td>{{formatTime $job.Finished}}</td>
<td>{{$job.LLMModel}}</td>
- <td>{{link $job.CodeRevisionLink $job.CodeRevision}}</td>
+ <td class="tag">{{link $job.CodeRevisionLink $job.CodeRevision}}</td>
<td>{{$job.Error}}</td>
</tr>
{{end}}
diff --git a/pkg/html/pages/style.css b/pkg/html/pages/style.css
index 8bc461882..cb1766df6 100644
--- a/pkg/html/pages/style.css
+++ b/pkg/html/pages/style.css
@@ -244,6 +244,10 @@ table td, table th {
font-size: 75%;
}
+.list_table .ai_correct {
+ text-align: center;
+}
+
.list_table .status-crashed {
background-color: #FF8674;
}
@@ -388,7 +392,6 @@ aside {
#ai_result_div {
align: left;
- width: 90%;
margin: 0 0;
overflow: scroll;
border: 1px solid #777;
@@ -399,6 +402,9 @@ aside {
#ai_result_div pre {
margin: 1px;
font-family: 'Courier New', Courier, monospace;
+ max-width: 120ch;
+ white-space: pre-wrap;
+ overflow-wrap: break-word;
}
#ai_details_div pre {