From 048e3f22d8e073a5b47b0a4bc2704d7eccd04abd Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Fri, 6 Mar 2026 11:56:10 +0000 Subject: dashboard/app: remember syz-agent names For now, use a dashboard client name. In a prod deployment, that would be a persistent name of the machine where the syz-agent is hosted. This information be used later for restarting the aborted jobs. --- dashboard/app/ai.go | 2 ++ dashboard/app/ai_test.go | 4 ++++ dashboard/app/aidb/crud.go | 1 + dashboard/app/aidb/entities.go | 1 + dashboard/app/aidb/migrations/7_add_agent_name.down.sql | 1 + dashboard/app/aidb/migrations/7_add_agent_name.up.sql | 1 + dashboard/app/local_ui_test.go | 1 + dashboard/app/templates/ai_job.html | 4 ++++ dashboard/dashapi/ai.go | 1 + syz-agent/agent.go | 2 ++ 10 files changed, 18 insertions(+) create mode 100644 dashboard/app/aidb/migrations/7_add_agent_name.down.sql create mode 100644 dashboard/app/aidb/migrations/7_add_agent_name.up.sql diff --git a/dashboard/app/ai.go b/dashboard/app/ai.go index 13f6f24db..4f3c13fe5 100644 --- a/dashboard/app/ai.go +++ b/dashboard/app/ai.go @@ -56,6 +56,7 @@ type uiAIJob struct { Workflow string Description string DescriptionLink string + AgentName string Created time.Time Started time.Time Finished time.Time @@ -302,6 +303,7 @@ func makeUIAIJob(job *aidb.Job) *uiAIJob { Workflow: job.Workflow, Description: job.Description, DescriptionLink: job.Link, + AgentName: nullString(job.AgentName), Created: job.Created, Started: nullTime(job.Started), Finished: nullTime(job.Finished), diff --git a/dashboard/app/ai_test.go b/dashboard/app/ai_test.go index 5802274da..fed84c9ba 100644 --- a/dashboard/app/ai_test.go +++ b/dashboard/app/ai_test.go @@ -70,6 +70,7 @@ func TestAIBugWorkflows(t *testing.T) { requireWorkflows(kasanBug, nil) _, err := c.agentClient.AIJobPoll(&dashapi.AIJobPollReq{ + AgentName: "agent-test-bug-workflow", CodeRevision: prog.GitRevision, Workflows: []dashapi.AIWorkflow{ {Type: "patching", Name: "patching"}, @@ -198,6 +199,7 @@ func TestAIJob(t *testing.T) { c.aiClient.pollEmailBug() resp, err := c.agentClient.AIJobPoll(&dashapi.AIJobPollReq{ + AgentName: "agent-test-job", CodeRevision: prog.GitRevision, Workflows: []dashapi.AIWorkflow{ {Type: "assessment-kcsan", Name: "assessment-kcsan"}, @@ -342,6 +344,7 @@ func TestAIAssessmentKCSAN(t *testing.T) { extID := c.aiClient.pollEmailExtID() resp, err := c.agentClient.AIJobPoll(&dashapi.AIJobPollReq{ + AgentName: "agent-test-assessment", CodeRevision: prog.GitRevision, Workflows: []dashapi.AIWorkflow{ {Type: ai.WorkflowAssessmentKCSAN, Name: string(ai.WorkflowAssessmentKCSAN)}, @@ -482,6 +485,7 @@ func TestAIJobAutoCreate(t *testing.T) { c.aiClient.pollEmailExtID() pollReq := &dashapi.AIJobPollReq{ + AgentName: "agent-test-auto-create", CodeRevision: prog.GitRevision, Workflows: []dashapi.AIWorkflow{ {Type: ai.WorkflowAssessmentKCSAN, Name: string(ai.WorkflowAssessmentKCSAN)}, diff --git a/dashboard/app/aidb/crud.go b/dashboard/app/aidb/crud.go index 6ed1c611a..4e90db351 100644 --- a/dashboard/app/aidb/crud.go +++ b/dashboard/app/aidb/crud.go @@ -129,6 +129,7 @@ func StartJob(ctx context.Context, req *dashapi.AIJobPollReq) (*Job, error) { } job.Started = spanner.NullTime{Time: TimeNow(ctx), Valid: true} job.CodeRevision = req.CodeRevision + job.AgentName = toNullString(req.AgentName) mut, err := spanner.InsertOrUpdateStruct("Jobs", job) if err != nil { return err diff --git a/dashboard/app/aidb/entities.go b/dashboard/app/aidb/entities.go index f256cdda6..7b6edd222 100644 --- a/dashboard/app/aidb/entities.go +++ b/dashboard/app/aidb/entities.go @@ -38,6 +38,7 @@ type Job struct { Finished spanner.NullTime CodeRevision string // syzkaller revision, filled when the job is started Error string // for finished jobs + AgentName spanner.NullString Args spanner.NullJSON Results spanner.NullJSON Correct spanner.NullBool diff --git a/dashboard/app/aidb/migrations/7_add_agent_name.down.sql b/dashboard/app/aidb/migrations/7_add_agent_name.down.sql new file mode 100644 index 000000000..f512f1166 --- /dev/null +++ b/dashboard/app/aidb/migrations/7_add_agent_name.down.sql @@ -0,0 +1 @@ +ALTER TABLE Jobs DROP COLUMN AgentName; diff --git a/dashboard/app/aidb/migrations/7_add_agent_name.up.sql b/dashboard/app/aidb/migrations/7_add_agent_name.up.sql new file mode 100644 index 000000000..117a97a46 --- /dev/null +++ b/dashboard/app/aidb/migrations/7_add_agent_name.up.sql @@ -0,0 +1 @@ +ALTER TABLE Jobs ADD COLUMN AgentName STRING(512); diff --git a/dashboard/app/local_ui_test.go b/dashboard/app/local_ui_test.go index 9a2900489..f1d10ea5e 100644 --- a/dashboard/app/local_ui_test.go +++ b/dashboard/app/local_ui_test.go @@ -284,6 +284,7 @@ func populateLocalUIDB(t *testing.T, c *Ctx) { } t.Logf("done populating DB") resp, _ := globalClient.AIJobPoll(&dashapi.AIJobPollReq{ + AgentName: "agent-local-ui", CodeRevision: "xxx", Workflows: []dashapi.AIWorkflow{ {Type: ai.WorkflowPatching, Name: string(ai.WorkflowPatching)}, diff --git a/dashboard/app/templates/ai_job.html b/dashboard/app/templates/ai_job.html index 2ff4ce975..21ef1fdd3 100644 --- a/dashboard/app/templates/ai_job.html +++ b/dashboard/app/templates/ai_job.html @@ -153,6 +153,10 @@ Detailed info on a single AI job execution. {{template "header" .Header}} {{template "ai_job_list" .Jobs}} + {{if .Job.AgentName}} + Agent: {{.Job.AgentName}}

+ {{end}} + {{if .Header.AIActions}} {{if and (ne .Job.Correct "⏳") (ne .Job.Correct "💥")}}
diff --git a/dashboard/dashapi/ai.go b/dashboard/dashapi/ai.go index dfa410402..a0ac7739c 100644 --- a/dashboard/dashapi/ai.go +++ b/dashboard/dashapi/ai.go @@ -9,6 +9,7 @@ import ( ) type AIJobPollReq struct { + AgentName string CodeRevision string // git commit of the syz-agent server Workflows []AIWorkflow } diff --git a/syz-agent/agent.go b/syz-agent/agent.go index 5d398cced..6ef2669d4 100644 --- a/syz-agent/agent.go +++ b/syz-agent/agent.go @@ -212,7 +212,9 @@ type Server struct { func (s *Server) poll(ctx context.Context) (bool, error) { s.resetModelQuota() + agentName := s.cfg.DashboardClient req := &dashapi.AIJobPollReq{ + AgentName: agentName, CodeRevision: prog.GitRevision, } for _, flow := range aflow.Flows { -- cgit mrf-deployment