fix(analyst): repos как строка или массив — устойчивый парсинг вердикта
This commit is contained in:
@@ -50,16 +50,40 @@ func (a *Analyst) publish(e events.Event) {
|
||||
|
||||
// AnalystResponse — структура JSON-ответа аналитика.
|
||||
type AnalystResponse struct {
|
||||
Phase string `json:"phase"`
|
||||
Title string `json:"title"`
|
||||
Goal string `json:"goal"`
|
||||
Repo string `json:"repo"` // одиночный репо (обратная совместимость)
|
||||
Repos []string `json:"repos"` // список репо (основной)
|
||||
Why string `json:"why"`
|
||||
AC string `json:"ac"`
|
||||
Questions []string `json:"questions"`
|
||||
ChatReply string `json:"chat_reply"`
|
||||
AbortReason string `json:"abort_reason"`
|
||||
Phase string `json:"phase"`
|
||||
Title string `json:"title"`
|
||||
Goal string `json:"goal"`
|
||||
Repo string `json:"repo"` // одиночный репо (обратная совместимость)
|
||||
Repos json.RawMessage `json:"repos"` // список репо (основной); устойчив к строке
|
||||
Why string `json:"why"`
|
||||
AC string `json:"ac"`
|
||||
Questions []string `json:"questions"`
|
||||
ChatReply string `json:"chat_reply"`
|
||||
AbortReason string `json:"abort_reason"`
|
||||
}
|
||||
|
||||
// reposList нормализует поле repos: модель может вернуть либо массив
|
||||
// ["a","b"], либо строку "a,b" (иногда с пробелами). Пустое значение → nil.
|
||||
func (r *AnalystResponse) reposList() []string {
|
||||
if r.Repos == nil {
|
||||
return nil
|
||||
}
|
||||
var arr []string
|
||||
if err := json.Unmarshal(r.Repos, &arr); err == nil {
|
||||
return arr
|
||||
}
|
||||
var s string
|
||||
if err := json.Unmarshal(r.Repos, &s); err != nil {
|
||||
return nil
|
||||
}
|
||||
var out []string
|
||||
for _, p := range strings.Split(s, ",") {
|
||||
p = strings.TrimSpace(p)
|
||||
if p != "" {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Decide реализует core.Decider через открытый код.
|
||||
@@ -141,10 +165,10 @@ func (a *Analyst) Decide(ctx context.Context, history []core.Message, draft stor
|
||||
if ar.Repo != "" {
|
||||
dec.Draft.Repo = ar.Repo
|
||||
}
|
||||
if len(ar.Repos) > 0 {
|
||||
dec.Draft.Repos = ar.Repos
|
||||
if repos := ar.reposList(); len(repos) > 0 {
|
||||
dec.Draft.Repos = repos
|
||||
// Синхронизируем одиночный repo для старых потребителей.
|
||||
dec.Draft.Repo = strings.Join(ar.Repos, ",")
|
||||
dec.Draft.Repo = strings.Join(repos, ",")
|
||||
}
|
||||
if ar.Why != "" {
|
||||
dec.Draft.Why = ar.Why
|
||||
@@ -220,9 +244,9 @@ func formatVerdict(ar *AnalystResponse) string {
|
||||
b.WriteString(", repo=")
|
||||
b.WriteString(ar.Repo)
|
||||
}
|
||||
if len(ar.Repos) > 0 {
|
||||
if repos := ar.reposList(); len(repos) > 0 {
|
||||
b.WriteString(", repos=[")
|
||||
b.WriteString(strings.Join(ar.Repos, ", "))
|
||||
b.WriteString(strings.Join(repos, ", "))
|
||||
b.WriteString("]")
|
||||
}
|
||||
if ar.Why != "" {
|
||||
|
||||
Reference in New Issue
Block a user