Files
ARTEX/server/task_resolution.go
BaaRai e233c02314 Translate all Chinese text to English
Comments, doc comments, UI labels, log and error messages, LLM prompt
strings, markdown docs, test data and assertions. Identifiers, enum
keys, routes, placeholders and code structure are unchanged.

Notes:
- docs/漏洞流量证据.md renamed to docs/vulnerability-traffic-evidence.md
- tests that exercised CJK specific handling (GBK zip names, Chinese
  full text search) now use ASCII equivalents; go build passes and the
  test suite matches the pre translation baseline (remaining failures
  need a PostgreSQL DSN and fail identically on the original)
- frontend mention syntax now uses English kinds (finding, asset, ...)
  matching the backend, chat mentions tests pass
2026-10-08 23:14:34 +02:00

124 lines
3.4 KiB
Go

package server
import (
"fmt"
"net/http"
"github.com/Autumn-27/artex/db"
)
type taskLLMResolution struct {
ProfileID *int64 `json:"profile_id,omitempty"`
Name string `json:"name"`
Format string `json:"format"`
Model string `json:"model"`
Source string `json:"source"`
Available bool `json:"available"`
Reason string `json:"reason,omitempty"`
}
func (s *Server) resolutionFromProfile(p *db.LLMProfile, source string) taskLLMResolution {
if p == nil {
return taskLLMResolution{Source: source, Reason: "LLM profile does not exist"}
}
id := p.ID
result := taskLLMResolution{
ProfileID: &id,
Name: p.Name,
Format: p.Format,
Model: p.Model,
Source: source,
}
if p.APIKey == "" {
result.Reason = "LLM profile has no API Key set"
return result
}
if _, _, ok := s.providerForProfile(p.ID); !ok {
result.Reason = "LLM profile format or parameters are invalid"
return result
}
result.Available = true
return result
}
// resolveTaskRoleLLM mirrors taskLLMRuntime.current without creating a provider:
// role Agent binding -> explicit task chain -> active/global environment config.
// Database failures are returned rather than represented as an unavailable model.
func (s *Server) resolveTaskRoleLLM(t *Task, agentKey string) (taskLLMResolution, error) {
if s == nil || s.m == nil || s.m.pg == nil {
return taskLLMResolution{}, fmt.Errorf("database unavailable")
}
a, err := s.m.pg.GetAgentByKey(agentKey)
if err != nil {
return taskLLMResolution{}, fmt.Errorf("load agent %q: %w", agentKey, err)
}
if a != nil && a.LLMProfileID != nil {
p, err := s.m.pg.ProfileByID(*a.LLMProfileID)
if err != nil {
return taskLLMResolution{}, fmt.Errorf("load agent LLM profile: %w", err)
}
if p != nil {
resolved := s.resolutionFromProfile(p, "agent_binding")
if resolved.Available {
return resolved, nil
}
}
}
state := t.llmStateSnapshot()
if len(state.ProfileIDs) > 0 {
if state.ActiveID == nil {
return taskLLMResolution{Source: "task_chain", Reason: "task LLM profile chain quota exhausted"}, nil
}
p, err := s.m.pg.ProfileByID(*state.ActiveID)
if err != nil {
return taskLLMResolution{}, fmt.Errorf("load task LLM profile: %w", err)
}
return s.resolutionFromProfile(p, "task_chain"), nil
}
p, err := s.m.pg.ActiveProfile()
if err != nil {
return taskLLMResolution{}, fmt.Errorf("load global LLM profile: %w", err)
}
if p != nil {
resolved := s.resolutionFromProfile(p, "global_profile")
if resolved.Available {
return resolved, nil
}
}
s.cfgMu.Lock()
on, name, cfg := s.llmOn, s.llmProf, s.llmCfg
s.cfgMu.Unlock()
if on {
if name == "" {
name = "global configuration"
}
return taskLLMResolution{
Name: name, Format: cfg.Provider(), Model: cfg.Model,
Source: "environment", Available: true,
}, nil
}
return taskLLMResolution{Source: "global", Reason: "no available LLM profile"}, nil
}
func (s *Server) taskLLMResolutionHandler(w http.ResponseWriter, r *http.Request) {
t, ok := s.m.Task(r.PathValue("id"))
if !ok {
writeErr(w, 404, "task not found")
return
}
roles := map[string]taskLLMResolution{}
for responseKey, agentKey := range map[string]string{
"mainagent": "mainagent",
"planner": "planner",
"worker": "worker",
} {
resolved, err := s.resolveTaskRoleLLM(t, agentKey)
if err != nil {
writeErr(w, http.StatusInternalServerError, err.Error())
return
}
roles[responseKey] = resolved
}
writeJSON(w, http.StatusOK, roles)
}