Files
ki.sagidullin 6c0b903794
Some checks failed
CI / test (push) Failing after 1m52s
CI / build-and-package (amd64, linux) (push) Failing after 1m3s
CI / build-and-package (amd64, windows) (push) Successful in 30s
feat(analyst): этапы задачи — аналитик раскладывает на steps с критериями готовности, dev идёт по ним
2026-08-24 18:05:06 +05:00

147 lines
5.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package storage
import (
"encoding/json"
"github.com/kamelion/ratatoskr-go/internal/model"
)
// Status — алиас доменного статуса задачи.
//
// Совместимый мост: весь внешний код продолжает использовать storage.Status
// (например «storage.StatusRunning»), но единый источник истины — model.Status.
type Status = model.Status
// Статусы задачи — re-export из model.
const (
StatusDraft = model.StatusDraft
StatusCollecting = model.StatusCollecting
StatusReady = model.StatusReady
StatusApproved = model.StatusApproved
StatusRunning = model.StatusRunning
StatusSuccess = model.StatusSuccess
StatusFailed = model.StatusFailed
StatusTimeout = model.StatusTimeout
StatusCancelled = model.StatusCancelled
StatusAborted = model.StatusAborted
StatusClosed = model.StatusClosed
)
// AllStatuses — все возможные статусы для валидации.
var AllStatuses = model.AllStatuses
// IsValidTransition проверяет, допустим ли переход from → to.
func IsValidTransition(from, to Status) bool {
return model.IsValidTransition(from, to)
}
// IsTerminal возвращает true, если статус терминальный.
func IsTerminal(s Status) bool {
return model.IsTerminal(s)
}
// Step — этап задачи с собственным критерием готовности.
type Step struct {
Title string `json:"title"`
AC string `json:"ac"` // acceptance criterion этапа
}
// Task — запись задачи в БД.
type Task struct {
ID int64 `json:"id"`
ChatID string `json:"chat_id"` // tg://<id>
Title string `json:"title"`
Goal string `json:"goal"`
Repo string `json:"repo"` // обратная совместимость: одиночный репозиторий
Repos []string `json:"repos"` // список репозиториев (основной)
Why string `json:"why"`
AC string `json:"ac"` // acceptance criteria
Steps []Step `json:"steps"` // этапы задачи (опционально)
TaskTag string `json:"task_tag"` // UUID, стабильный на всю жизнь
Status Status `json:"status"`
CreatedAt SQLiteTime `json:"created_at"`
UpdatedAt SQLiteTime `json:"updated_at"`
}
// ReposJoined возвращает repos как одну строку (JSON-массив) для хранения в БД.
// Пустой список → пустая строка.
func (t *Task) ReposJoined() string {
if len(t.Repos) == 0 {
return ""
}
b, _ := json.Marshal(t.Repos)
return string(b)
}
// EffectiveRepos возвращает сам репо: если Repos пуст, но Repo задан —
// подтягивает одиночный (обратная совместимость).
func (t *Task) EffectiveRepos() []string {
if len(t.Repos) > 0 {
return t.Repos
}
if t.Repo != "" {
return []string{t.Repo}
}
return nil
}
// SetReposFromDB заполняет Repos из сохранённой строки (JSON), либо
// из одиночного repo (обратная совместимость).
func (t *Task) SetReposFromDB(repos string) {
if repos == "" {
t.Repos = nil
return
}
_ = json.Unmarshal([]byte(repos), &t.Repos)
}
// StepsJoined возвращает steps как одну строку (JSON-массив) для хранения в БД.
// Пустой список → пустая строка.
func (t *Task) StepsJoined() string {
if len(t.Steps) == 0 {
return ""
}
b, _ := json.Marshal(t.Steps)
return string(b)
}
// SetStepsFromDB заполняет Steps из сохранённой строки (JSON).
func (t *Task) SetStepsFromDB(steps string) {
if steps == "" {
t.Steps = nil
return
}
_ = json.Unmarshal([]byte(steps), &t.Steps)
}
// TraceStatus — алиас доменного статуса трассировки.
type TraceStatus = model.TraceStatus
const (
TraceRunning TraceStatus = model.TraceRunning
TraceSuccess TraceStatus = model.TraceSuccess
TraceFailed TraceStatus = model.TraceFailed
TraceTimeout TraceStatus = model.TraceTimeout
)
// Trace — лог одного субагента.
type Trace struct {
ID int64 `json:"id"`
TaskID int64 `json:"task_id"`
Agent string `json:"agent"` // analyst | researcher | dev | reviewer
SessionID string `json:"session_id"` // opencode session_id
Prompt string `json:"prompt"`
Output string `json:"output"` // полный NDJSON или summary
Status TraceStatus `json:"status"`
StartedAt SQLiteTime `json:"started_at"`
FinishedAt NullSQLiteTime `json:"finished_at,omitempty"`
}
// TaskFilter — параметры фильтрации списка задач.
type TaskFilter struct {
ChatID string
Status Status
Limit int
Offset int
}