Files
Assistant/cmd/task-verifier/main.go
m 3d9a5bccba
CI / test (push) Successful in 47s
CI / test (pull_request) Successful in 51s
feat: extend task verifier and unresolved case builder
2026-08-23 14:30:45 +03:00

77 lines
3.2 KiB
Go

package main
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"git.cin.su/m/Assistant/contracts/capability"
)
const verifierIdentity = "deterministic-task-verifier-v1"
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"runtime":"task-verifier","status":"ok"}`))
})
mux.HandleFunc("POST /v1/task-evaluations/verify", verifyHandler)
addr := ":8091"
if value := strings.TrimSpace(os.Getenv("LISTEN_ADDR")); value != "" {
addr = value
}
if err := http.ListenAndServe(addr, mux); err != nil {
panic(err)
}
}
func verifyHandler(w http.ResponseWriter, r *http.Request) {
var request capability.TaskCaseVerificationRequest
decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&request); err != nil || request.CaseID == "" || request.ResponseText == "" || request.EvidenceArtifactRef == "" || request.LatencyMicros < 0 || (request.Verification.Mode != capability.TaskCaseVerificationExactText && request.Verification.Mode != capability.TaskCaseVerificationJSONFieldEquals) || (request.Verification.Mode == capability.TaskCaseVerificationJSONFieldEquals && request.Verification.FieldPath == "") || request.Verification.ExpectedText == "" || request.Verification.MinimumQualityMillis < 0 || request.Verification.MinimumQualityMillis > 1000 {
http.Error(w, "invalid task verification request", http.StatusBadRequest)
return
}
matched := matches(request)
quality := int64(0)
result := capability.EvaluationUnsupported
if matched {
quality = request.Verification.MinimumQualityMillis
if quality == 0 {
quality = 1000
}
result = capability.EvaluationSupported
}
evidence := verificationEvidence(request, matched)
writeJSON(w, capability.TaskCaseVerificationResponse{CaseID: request.CaseID, Result: result, QualityScoreMillis: quality, LatencyMicros: request.LatencyMicros, EvidenceArtifactRef: request.EvidenceArtifactRef, VerificationEvidenceRef: evidence, VerifierIdentity: verifierIdentity})
}
func verificationEvidence(request capability.TaskCaseVerificationRequest, matched bool) string {
payload := fmt.Sprintf("%s|%s|%s|%s|%s|%t", verifierIdentity, request.CaseID, request.EvidenceArtifactRef, request.Verification.Mode, request.Verification.FieldPath, matched)
digest := sha256.Sum256([]byte(payload))
return "verification:" + hex.EncodeToString(digest[:])
}
func matches(request capability.TaskCaseVerificationRequest) bool {
if request.Verification.Mode == capability.TaskCaseVerificationExactText {
return strings.TrimSpace(request.ResponseText) == strings.TrimSpace(request.Verification.ExpectedText)
}
var document map[string]json.RawMessage
if json.Unmarshal([]byte(request.ResponseText), &document) != nil {
return false
}
value, ok := document[request.Verification.FieldPath]
return ok && strings.TrimSpace(string(value)) == strings.TrimSpace(request.Verification.ExpectedText)
}
func writeJSON(w http.ResponseWriter, value any) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(value)
}