diff options
| author | soryu <soryu@soryu.co> | 2026-01-21 16:09:34 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-21 16:09:34 +0000 |
| commit | 3b3734e9c8cd889e6f7369d284ec530413821919 (patch) | |
| tree | 14d04fb436737e9a5cf900b0f2540f4698302153 | |
| parent | 3bbb7ac92f0a480f9275c9b29b6a4e07e8e0ff45 (diff) | |
| download | soryu-3b3734e9c8cd889e6f7369d284ec530413821919.tar.gz soryu-3b3734e9c8cd889e6f7369d284ec530413821919.zip | |
Add task branching models and update CreateTaskRequest
- Add branched_from_task_id field to Task struct
- Make contract_id optional in CreateTaskRequest for anonymous tasks
- Add branched_from_task_id and conversation_history to CreateTaskRequest
- Add BranchTaskRequest struct for branching API
- Add BranchTaskResponse struct with task, message_count, daemon_id
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| -rw-r--r-- | makima/src/db/models.rs | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index 291fad7..bf95a3a 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -519,6 +519,12 @@ pub struct Task { /// When the task was last interrupted due to daemon disconnect #[serde(skip_serializing_if = "Option::is_none")] pub interrupted_at: Option<DateTime<Utc>>, + + // Task branching + /// Source task ID when this task was branched from another task's conversation. + /// Used to track the origin of "what if" explorations. + #[serde(skip_serializing_if = "Option::is_none")] + pub branched_from_task_id: Option<Uuid>, } impl Task { @@ -598,8 +604,8 @@ pub struct TaskListResponse { #[derive(Debug, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct CreateTaskRequest { - /// Contract this task belongs to (required) - pub contract_id: Uuid, + /// Contract this task belongs to (optional for branched/anonymous tasks) + pub contract_id: Option<Uuid>, /// Name of the task pub name: String, /// Optional description @@ -633,6 +639,10 @@ pub struct CreateTaskRequest { pub copy_files: Option<Vec<String>>, /// Checkpoint SHA to branch from (optional) pub checkpoint_sha: Option<String>, + /// Source task ID when branching from another task's conversation + pub branched_from_task_id: Option<Uuid>, + /// Conversation history to initialize the task with (JSON array of messages) + pub conversation_history: Option<serde_json::Value>, } /// Request payload for updating a task @@ -681,6 +691,37 @@ pub struct SendMessageRequest { pub message: String, } +/// Default for include_conversation field in BranchTaskRequest +fn default_include_conversation() -> bool { + true +} + +/// Request to branch a task from an existing task's conversation. +/// Creates a new anonymous task that continues from the source task's state. +#[derive(Debug, Deserialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct BranchTaskRequest { + /// The initial message/instructions for the branched task + pub message: String, + /// Optional name for the branched task (auto-generated if not provided) + pub name: Option<String>, + /// Whether to include conversation history from the source task (default: true) + #[serde(default = "default_include_conversation")] + pub include_conversation: bool, +} + +/// Response from branching a task. +#[derive(Debug, Serialize, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct BranchTaskResponse { + /// The newly created branched task + pub task: Task, + /// Number of conversation messages included from source task + pub message_count: usize, + /// Daemon ID if the task was started (None if no daemon available) + pub daemon_id: Option<Uuid>, +} + // ============================================================================= // Daemon Types // ============================================================================= |
