130 lines
4.2 KiB
Go
130 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type workerStatusResponse struct {
|
|
Runtime string `json:"runtime"`
|
|
ExecutorConfigured bool `json:"executor_configured"`
|
|
Mode string `json:"mode"`
|
|
Ready bool `json:"ready"`
|
|
Reason string `json:"reason"`
|
|
LocalFallback bool `json:"local_fallback"`
|
|
LocalExecutor bool `json:"local_executor"`
|
|
Capabilities []string `json:"capabilities,omitempty"`
|
|
StartedAt time.Time `json:"started_at,omitempty"`
|
|
LastCycleAt time.Time `json:"last_cycle_at,omitempty"`
|
|
LastCompletedAt time.Time `json:"last_completed_at,omitempty"`
|
|
LastRecoveredClaims int64 `json:"last_recovered_claims"`
|
|
TotalRecoveredClaims int64 `json:"total_recovered_claims"`
|
|
LastDispatchID string `json:"last_dispatch_id,omitempty"`
|
|
LastResult string `json:"last_result,omitempty"`
|
|
LastError string `json:"last_error,omitempty"`
|
|
}
|
|
|
|
type agentWorkerRuntimeStatus struct {
|
|
mu sync.RWMutex
|
|
startedAt time.Time
|
|
lastCycleAt time.Time
|
|
lastCompletedAt time.Time
|
|
lastRecoveredClaims int64
|
|
totalRecoveredClaims int64
|
|
lastDispatchID string
|
|
lastResult string
|
|
lastError string
|
|
}
|
|
|
|
func newAgentWorkerRuntimeStatus() *agentWorkerRuntimeStatus {
|
|
return &agentWorkerRuntimeStatus{startedAt: time.Now().UTC()}
|
|
}
|
|
|
|
func (s *agentWorkerRuntimeStatus) cycleStarted(at time.Time) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.lastCycleAt = at.UTC()
|
|
s.lastResult = "running"
|
|
s.lastError = ""
|
|
}
|
|
|
|
func (s *agentWorkerRuntimeStatus) cycleFinished(at time.Time, recoveredClaims int64, dispatchID string, result string) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.lastCompletedAt = at.UTC()
|
|
s.lastRecoveredClaims = recoveredClaims
|
|
s.totalRecoveredClaims += recoveredClaims
|
|
s.lastDispatchID = dispatchID
|
|
s.lastResult = result
|
|
s.lastError = ""
|
|
}
|
|
|
|
func (s *agentWorkerRuntimeStatus) cycleFailed(at time.Time, err error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.lastCompletedAt = at.UTC()
|
|
s.lastResult = "failed"
|
|
s.lastError = err.Error()
|
|
}
|
|
|
|
func workerStatusHandler(executorConfigured bool, localFallback ...interface{}) http.Handler {
|
|
local := false
|
|
var runtime *agentWorkerRuntimeStatus
|
|
for _, argument := range localFallback {
|
|
switch value := argument.(type) {
|
|
case bool:
|
|
local = value
|
|
case *agentWorkerRuntimeStatus:
|
|
runtime = value
|
|
}
|
|
}
|
|
if runtime == nil {
|
|
runtime = newAgentWorkerRuntimeStatus()
|
|
}
|
|
baseStatus := workerStatusResponse{
|
|
Runtime: "agent-worker",
|
|
ExecutorConfigured: executorConfigured,
|
|
Mode: "recovery-only",
|
|
Ready: false,
|
|
Reason: "protected agent execution bridge URL is not configured",
|
|
LocalFallback: local,
|
|
LocalExecutor: local,
|
|
}
|
|
if local {
|
|
baseStatus.Mode = "local-executor"
|
|
baseStatus.Ready = true
|
|
baseStatus.Reason = "bounded local task-evaluation capability is ready; unsupported work remains durably waiting"
|
|
baseStatus.Capabilities = []string{"task-evaluation"}
|
|
}
|
|
if executorConfigured {
|
|
baseStatus.Mode = "execution"
|
|
baseStatus.Ready = true
|
|
baseStatus.Reason = "typed agent execution bridge configured"
|
|
baseStatus.Capabilities = []string{"task-evaluation", "generic-cognitive-work"}
|
|
}
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet || (r.URL.Path != "/healthz" && r.URL.Path != "/readyz" && r.URL.Path != "/status") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/readyz" && !baseStatus.Ready {
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
}
|
|
response := baseStatus
|
|
runtime.mu.RLock()
|
|
response.StartedAt = runtime.startedAt
|
|
response.LastCycleAt = runtime.lastCycleAt
|
|
response.LastCompletedAt = runtime.lastCompletedAt
|
|
response.LastRecoveredClaims = runtime.lastRecoveredClaims
|
|
response.TotalRecoveredClaims = runtime.totalRecoveredClaims
|
|
response.LastDispatchID = runtime.lastDispatchID
|
|
response.LastResult = runtime.lastResult
|
|
response.LastError = runtime.lastError
|
|
runtime.mu.RUnlock()
|
|
_ = json.NewEncoder(w).Encode(response)
|
|
})
|
|
}
|