summaryrefslogtreecommitdiff
path: root/internal/task/task.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/task/task.go')
-rw-r--r--internal/task/task.go51
1 files changed, 29 insertions, 22 deletions
diff --git a/internal/task/task.go b/internal/task/task.go
index 9968b15..2c57922 100644
--- a/internal/task/task.go
+++ b/internal/task/task.go
@@ -48,6 +48,14 @@ type RetryConfig struct {
Backoff string `yaml:"backoff" json:"backoff"` // "linear", "exponential"
}
+// Interaction records a single question/answer exchange between an agent and the user.
+type Interaction struct {
+ QuestionText string `json:"question_text"`
+ Options []string `json:"options,omitempty"`
+ Answer string `json:"answer,omitempty"`
+ AskedAt time.Time `json:"asked_at"`
+}
+
type Task struct {
ID string `yaml:"id" json:"id"`
ParentTaskID string `yaml:"parent_task_id" json:"parent_task_id"`
@@ -59,11 +67,13 @@ type Task struct {
Priority Priority `yaml:"priority" json:"priority"`
Tags []string `yaml:"tags" json:"tags"`
DependsOn []string `yaml:"depends_on" json:"depends_on"`
- State State `yaml:"-" json:"state"`
- RejectionComment string `yaml:"-" json:"rejection_comment,omitempty"`
- QuestionJSON string `yaml:"-" json:"question,omitempty"`
- CreatedAt time.Time `yaml:"-" json:"created_at"`
- UpdatedAt time.Time `yaml:"-" json:"updated_at"`
+ State State `yaml:"-" json:"state"`
+ RejectionComment string `yaml:"-" json:"rejection_comment,omitempty"`
+ QuestionJSON string `yaml:"-" json:"question,omitempty"`
+ Summary string `yaml:"-" json:"summary,omitempty"`
+ Interactions []Interaction `yaml:"-" json:"interactions,omitempty"`
+ CreatedAt time.Time `yaml:"-" json:"created_at"`
+ UpdatedAt time.Time `yaml:"-" json:"updated_at"`
}
// Duration wraps time.Duration for YAML unmarshaling from strings like "30m".
@@ -94,27 +104,24 @@ type BatchFile struct {
}
// validTransitions maps each state to the set of states it may transition into.
-// Terminal state COMPLETED has no outgoing edges.
+// COMPLETED is the only true terminal state (no outgoing edges).
// CANCELLED, FAILED, TIMED_OUT, and BUDGET_EXCEEDED all allow re-entry at QUEUED
// (restart or retry).
-var validTransitions = map[State][]State{
- StatePending: {StateQueued, StateCancelled},
- StateQueued: {StateRunning, StateCancelled},
- StateRunning: {StateReady, StateCompleted, StateFailed, StateTimedOut, StateCancelled, StateBudgetExceeded, StateBlocked},
- StateReady: {StateCompleted, StatePending},
- StateFailed: {StateQueued}, // retry
- StateTimedOut: {StateQueued}, // retry or resume
- StateCancelled: {StateQueued}, // restart
- StateBudgetExceeded: {StateQueued}, // retry
- StateBlocked: {StateQueued, StateReady},
+// READY may go back to PENDING on user rejection.
+// BLOCKED may advance to READY when all subtasks complete, or back to QUEUED on user answer.
+var validTransitions = map[State]map[State]bool{
+ StatePending: {StateQueued: true, StateCancelled: true},
+ StateQueued: {StateRunning: true, StateCancelled: true},
+ StateRunning: {StateReady: true, StateCompleted: true, StateFailed: true, StateTimedOut: true, StateCancelled: true, StateBudgetExceeded: true, StateBlocked: true},
+ StateReady: {StateCompleted: true, StatePending: true},
+ StateFailed: {StateQueued: true}, // retry
+ StateTimedOut: {StateQueued: true}, // retry or resume
+ StateCancelled: {StateQueued: true}, // restart
+ StateBudgetExceeded: {StateQueued: true}, // retry
+ StateBlocked: {StateQueued: true, StateReady: true},
}
// ValidTransition returns true if moving from the current state to next is allowed.
func ValidTransition(from, to State) bool {
- for _, allowed := range validTransitions[from] {
- if allowed == to {
- return true
- }
- }
- return false
+ return validTransitions[from][to]
}