package main import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "git.cin.su/m/Assistant/contracts/capability" "git.cin.su/m/Assistant/contracts/cognitive" "git.cin.su/m/Assistant/contracts/work" ) func TestBridgeWaitsForUnsupportedIntent(t *testing.T) { b := bridge{client: http.DefaultClient} result, err := b.execute(context.Background(), work.AgentExecutionRequest{Intent: work.AgentDispatchIntent{DispatchID: "dispatch-unsupported"}}) if err != nil { t.Fatal(err) } if result.State != work.AgentExecutionWaiting || result.ObservedAtUnixMillis < 1 { t.Fatalf("result=%+v", result) } } func TestHealthHandlerExposesBoundedCapability(t *testing.T) { recorder := httptest.NewRecorder() request := httptest.NewRequest(http.MethodGet, "/healthz", nil) healthHandler(recorder, request) if recorder.Code != http.StatusOK || recorder.Body.String() == "" { t.Fatalf("status=%d body=%q", recorder.Code, recorder.Body.String()) } } func TestBridgeRunsTaskEvaluationThroughVerifierAndCallback(t *testing.T) { profile := capability.TaskEvaluationProfile{ID: "profile-1", Revision: 1, CapabilityID: "capability-1", Stage: capability.TaskEvaluationGeneral, BenchmarkVersion: "general-v1", RequiredCaseIDs: []string{"case-1"}, QualityWeightMillis: 600, ReliabilityWeightMillis: 300, LatencyWeightMillis: 100} verification := capability.TaskCaseVerification{Mode: capability.TaskCaseVerificationExactText, ExpectedText: "answer", MinimumQualityMillis: 900} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/v1/task-evaluations/execute": _ = json.NewEncoder(w).Encode(capability.TaskEvaluationExecutionResponse{ProfileID: profile.ID, BindingID: "binding-1", BindingRevision: 3, Responses: []capability.TaskCaseResponse{{CaseID: "case-1", ResponseText: "answer", LatencyMicros: 2, EvidenceArtifactRef: "artifact-1"}}, ObservedAtUnixMillis: 10}) case "/v1/task-evaluations/verify": _ = json.NewEncoder(w).Encode(capability.TaskCaseVerificationResponse{CaseID: "case-1", Result: capability.EvaluationSupported, QualityScoreMillis: 900, LatencyMicros: 2, EvidenceArtifactRef: "artifact-1", VerificationEvidenceRef: "verify-1", VerifierIdentity: "verifier-1"}) case "/v1/work-graphs/task-evaluations/callback": w.WriteHeader(http.StatusNoContent) default: http.NotFound(w, r) } })) defer server.Close() b := bridge{cognitiveURL: server.URL, callbackURL: server.URL, verifierURL: server.URL, client: server.Client()} result, err := b.execute(context.Background(), work.AgentExecutionRequest{Intent: work.AgentDispatchIntent{DispatchID: "dispatch-1", TaskEvaluationBindingID: "binding-1", TaskEvaluationProfile: &profile, TaskEvaluationCases: []capability.TaskEvaluationCase{{CaseID: "case-1", Prompt: "answer", EvidenceArtifactRef: "artifact-1", Verification: verification}}, TaskEvaluationExecution: &work.TaskEvaluationDispatchContext{GraphID: "graph-1", GraphRevision: 1, NodeID: "node-1", BindingRevision: 3, ActorID: "actor-1", PrincipalID: "principal-1", ScopeID: "scope-1"}}}) if err != nil || result.State != work.AgentExecutionCompleted || result.OutcomeRef == "" { t.Fatalf("result=%+v err=%v", result, err) } } func TestBridgeRunsGenericCognitiveWorkAsUnverifiedGraphCandidate(t *testing.T) { var callback work.GraphResultCallback server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/v1/advisories": var request cognitive.GatewayAdvisoryRequest if err := json.NewDecoder(r.Body).Decode(&request); err != nil || request.Message != "find the bounded solution" { t.Fatalf("unexpected advisory request: %+v err=%v", request, err) } _ = json.NewEncoder(w).Encode(cognitive.GatewayAdvisoryResponse{Version: cognitive.CreatorAdvisoryV1, RequestID: request.RequestID, AdvisoryText: "candidate answer", FinishReason: cognitive.FinishCompleted}) case "/v1/work-graphs/result-callback": if err := json.NewDecoder(r.Body).Decode(&callback); err != nil { t.Fatal(err) } w.WriteHeader(http.StatusNoContent) case "/v1/work-graphs/candidates/verify": _ = json.NewEncoder(w).Encode(work.GenericCandidateVerificationResponse{Verified: true, VerificationEvidenceRef: "verification:generic-1", VerifierIdentity: "deterministic-generic-envelope-verifier-v1", Summary: "envelope verified"}) default: http.NotFound(w, r) } })) defer server.Close() b := bridge{cognitiveURL: server.URL, callbackURL: server.URL, verifierURL: server.URL, client: server.Client()} result, err := b.execute(context.Background(), work.AgentExecutionRequest{Intent: work.AgentDispatchIntent{ DispatchID: "dispatch-generic", RunID: "run-generic", TaskEvaluationExecution: &work.TaskEvaluationDispatchContext{GraphID: "graph-1", GraphRevision: 2, NodeID: "node-1", ActorID: "actor-1", PrincipalID: "principal-1", ScopeID: "scope-1", GenericMessage: "find the bounded solution", GenericPurpose: "investigate", GenericDataPolicy: string(capability.DataPolicyLocalOnly)}, }}) if err != nil || result.State != work.AgentExecutionCompleted || callback.Candidate.Summary != "candidate answer" || callback.Candidate.AuthorRunID != "run-generic" || len(callback.Candidate.ArtifactRefs) != 2 { t.Fatalf("result=%+v callback=%+v err=%v", result, callback, err) } }