package taskrun import ( "context" "sync" "time" "chat-agent-system/internal/stream" ) // CreateRequest 创建后台任务运行实例。 type CreateRequest struct { SessionID string ProjectID int64 UserID int64 ClientTurnID string TaskKey string Stage string WorkDir string UserMessage string AssistantMsgID int64 IncludeDetails bool TaskReq any // *server task payload converted to bizdev request at execution layer } // RunRecord 运行实例状态。 // JSON 键与前端约定及 task_runs 列名一致;缺标签时 encoding/json 会输出 PascalCase, // 前端读 status/error_message 会得到 undefined,断线恢复分支全部失效。 type RunRecord struct { RunID string `json:"run_id"` SessionID string `json:"session_id"` ProjectID int64 `json:"project_id"` UserID int64 `json:"user_id"` ClientTurnID string `json:"client_turn_id"` IdempotencyKey string `json:"idempotency_key"` TaskKey string `json:"task_key"` Stage string `json:"stage"` WorkflowInstanceID int64 `json:"workflow_instance_id"` StageInstanceID int64 `json:"stage_instance_id"` WorkflowStageKey string `json:"workflow_stage_key"` Status string `json:"status"` // pending | running | completed | failed | cancelled | pending_author_confirmation | blocked_pending_governance | … WorkspaceID string `json:"workspace_id"` AssistantMsgID int64 `json:"assistant_message_id"` WorkerID string `json:"worker_id"` LeaseExpiresAt *time.Time `json:"lease_expires_at"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` ErrorMessage string `json:"error_message"` Attempt int `json:"attempt"` } // BuildTaskRunIdempotencyKey 新创建用稳定幂等键;空 client_turn 不设键。 func BuildTaskRunIdempotencyKey(sessionID, clientTurnID string) string { if sessionID == "" || clientTurnID == "" { return "" } return "turn:" + sessionID + ":" + clientTurnID } // StoredEvent 持久化 SSE 事件(支持重连重放)。 type StoredEvent struct { Seq int64 Event stream.StreamEvent } type activeRun struct { record *RunRecord events []StoredEvent nextSeq int64 subs map[int]chan StoredEvent subSeq int cancel context.CancelFunc done chan struct{} mu sync.RWMutex }