138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
package workflow
|
|
|
|
import "fmt"
|
|
|
|
type Stage string
|
|
|
|
const (
|
|
StageClarification Stage = "clarification"
|
|
StageFreeze Stage = "freeze"
|
|
StagePlan Stage = "plan"
|
|
StageReview Stage = "review"
|
|
StageExecution Stage = "execution"
|
|
StageVerification Stage = "verification"
|
|
)
|
|
|
|
type RunStatus string
|
|
|
|
const (
|
|
RunStatusRunning RunStatus = "running"
|
|
RunStatusSucceeded RunStatus = "succeeded"
|
|
RunStatusFailed RunStatus = "failed"
|
|
RunStatusCancelled RunStatus = "cancelled"
|
|
)
|
|
|
|
type LogStream string
|
|
|
|
const (
|
|
LogStreamStdout LogStream = "stdout"
|
|
LogStreamStderr LogStream = "stderr"
|
|
LogStreamSystem LogStream = "system"
|
|
)
|
|
|
|
var stageTransitions = map[Stage][]Stage{
|
|
StageClarification: {StagePlan, StageFreeze},
|
|
StageFreeze: {StageExecution},
|
|
StagePlan: {StageReview, StageExecution},
|
|
StageReview: {StageExecution},
|
|
StageExecution: {StageVerification},
|
|
StageVerification: {},
|
|
}
|
|
|
|
func ValidateRunStatus(status RunStatus) error {
|
|
switch status {
|
|
case RunStatusRunning, RunStatusSucceeded, RunStatusFailed, RunStatusCancelled:
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("invalid run status %q", status)
|
|
}
|
|
}
|
|
|
|
func CanTransition(from, to Stage) bool {
|
|
for _, candidate := range stageTransitions[from] {
|
|
if candidate == to {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func ValidateStage(stage Stage) error {
|
|
switch stage {
|
|
case StageClarification, StageFreeze, StagePlan, StageReview, StageExecution, StageVerification:
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("invalid workflow stage %q", stage)
|
|
}
|
|
}
|
|
|
|
type Run struct {
|
|
ID string `json:"id"`
|
|
WorkspaceID string `json:"workspace_id"`
|
|
TopicID string `json:"topic_id"`
|
|
RoleName string `json:"role_name"`
|
|
Stage Stage `json:"stage"`
|
|
Mode string `json:"mode"`
|
|
Status RunStatus `json:"status"`
|
|
RequestMessageID string `json:"request_message_id,omitempty"`
|
|
ConfigSnapshotJSON string `json:"config_snapshot_json"`
|
|
CommandJSON string `json:"command_json"`
|
|
ReplyMessageID string `json:"reply_message_id,omitempty"`
|
|
ExitCode int `json:"exit_code"`
|
|
StartedAt string `json:"started_at"`
|
|
CompletedAt string `json:"completed_at,omitempty"`
|
|
ErrorMessage string `json:"error_message,omitempty"`
|
|
}
|
|
|
|
func (r Run) Validate() error {
|
|
if r.WorkspaceID == "" {
|
|
return fmt.Errorf("workspace id is required")
|
|
}
|
|
if r.TopicID == "" {
|
|
return fmt.Errorf("topic id is required")
|
|
}
|
|
if r.RoleName == "" {
|
|
return fmt.Errorf("role name is required")
|
|
}
|
|
if err := ValidateStage(r.Stage); err != nil {
|
|
return err
|
|
}
|
|
if err := ValidateRunStatus(r.Status); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type RunLog struct {
|
|
RunID string `json:"run_id"`
|
|
Seq int `json:"seq"`
|
|
Stream LogStream `json:"stream"`
|
|
Content string `json:"content"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
func ValidateLogStream(stream LogStream) error {
|
|
switch stream {
|
|
case LogStreamStdout, LogStreamStderr, LogStreamSystem:
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("invalid log stream %q", stream)
|
|
}
|
|
}
|
|
|
|
func (l RunLog) Validate() error {
|
|
if l.RunID == "" {
|
|
return fmt.Errorf("run id is required")
|
|
}
|
|
if err := ValidateLogStream(l.Stream); err != nil {
|
|
return err
|
|
}
|
|
if l.Content == "" {
|
|
return fmt.Errorf("log content is required")
|
|
}
|
|
if l.Seq < 0 {
|
|
return fmt.Errorf("log seq must be >= 0")
|
|
}
|
|
return nil
|
|
}
|