diff options
| author | soryu <soryu@soryu.co> | 2026-02-13 19:19:39 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-13 19:19:39 +0000 |
| commit | a6677bafe52d9988c9948df34c1635e4411c9591 (patch) | |
| tree | a3d05924fe6ff1a06c1abdfe1fa165e0d0546406 /makima/src | |
| parent | 5edaf1228b4e48a441b98c49f58de312b7924ed6 (diff) | |
| download | soryu-a6677bafe52d9988c9948df34c1635e4411c9591.tar.gz soryu-a6677bafe52d9988c9948df34c1635e4411c9591.zip | |
Fix worktree branching for directive tasks and remove memories
Diffstat (limited to 'makima/src')
| -rw-r--r-- | makima/src/bin/makima.rs | 44 | ||||
| -rw-r--r-- | makima/src/daemon/api/directive.rs | 199 | ||||
| -rw-r--r-- | makima/src/daemon/cli/directive.rs | 47 | ||||
| -rw-r--r-- | makima/src/daemon/cli/mod.rs | 18 | ||||
| -rw-r--r-- | makima/src/daemon/task/manager.rs | 144 | ||||
| -rw-r--r-- | makima/src/daemon/worktree/manager.rs | 79 | ||||
| -rw-r--r-- | makima/src/db/models.rs | 45 | ||||
| -rw-r--r-- | makima/src/db/repository.rs | 143 | ||||
| -rw-r--r-- | makima/src/orchestration/directive.rs | 84 | ||||
| -rw-r--r-- | makima/src/server/handlers/directives.rs | 394 | ||||
| -rw-r--r-- | makima/src/server/mod.rs | 4 | ||||
| -rw-r--r-- | makima/src/server/openapi.rs | 19 |
12 files changed, 194 insertions, 1026 deletions
diff --git a/makima/src/bin/makima.rs b/makima/src/bin/makima.rs index d4af878..c2c9beb 100644 --- a/makima/src/bin/makima.rs +++ b/makima/src/bin/makima.rs @@ -825,50 +825,6 @@ async fn run_directive( .await?; println!("{}", serde_json::to_string(&result.0)?); } - DirectiveCommand::MemorySet(args) => { - let client = ApiClient::new(args.common.api_url, args.common.api_key)?; - let result = client - .directive_memory_set(args.common.directive_id, &args.key, &args.value) - .await?; - println!("{}", serde_json::to_string(&result.0)?); - } - DirectiveCommand::MemoryGet(args) => { - let client = ApiClient::new(args.common.api_url, args.common.api_key)?; - let result = client - .directive_memory_get(args.common.directive_id, &args.key) - .await?; - println!("{}", serde_json::to_string(&result.0)?); - } - DirectiveCommand::MemoryList(args) => { - let client = ApiClient::new(args.api_url, args.api_key)?; - let result = client - .directive_memory_list(args.directive_id) - .await?; - println!("{}", serde_json::to_string(&result.0)?); - } - DirectiveCommand::MemoryDelete(args) => { - let client = ApiClient::new(args.common.api_url, args.common.api_key)?; - client - .directive_memory_delete(args.common.directive_id, &args.key) - .await?; - println!(r#"{{"success": true}}"#); - } - DirectiveCommand::MemoryClear(args) => { - let client = ApiClient::new(args.api_url, args.api_key)?; - client - .directive_memory_clear(args.directive_id) - .await?; - println!(r#"{{"success": true}}"#); - } - DirectiveCommand::MemoryBatchSet(args) => { - let client = ApiClient::new(args.common.api_url, args.common.api_key)?; - let entries: serde_json::Value = serde_json::from_str(&args.json) - .map_err(|e| format!("Invalid JSON: {}", e))?; - let result = client - .directive_memory_batch_set(args.common.directive_id, entries) - .await?; - println!("{}", serde_json::to_string(&result.0)?); - } } Ok(()) diff --git a/makima/src/daemon/api/directive.rs b/makima/src/daemon/api/directive.rs index fcc2ca5..a0cdab0 100644 --- a/makima/src/daemon/api/directive.rs +++ b/makima/src/daemon/api/directive.rs @@ -30,54 +30,6 @@ pub struct UpdateStepDepsRequest { pub depends_on: Vec<Uuid>, } -/// Percent-encode a string for use as a URL path segment. -/// -/// Encodes all characters except unreserved characters (alphanumeric, `-`, `.`, `_`, `~`). -fn percent_encode_path(s: &str) -> String { - let mut encoded = String::with_capacity(s.len()); - for byte in s.bytes() { - match byte { - b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'.' | b'_' | b'~' => { - encoded.push(byte as char); - } - _ => { - encoded.push_str(&format!("%{:02X}", byte)); - } - } - } - encoded -} - -/// Request body for setting a single memory entry. -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct SetMemoryRequest { - pub key: String, - pub value: String, -} - -/// A single entry within a batch set request. -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BatchMemoryEntry { - pub key: String, - pub value: String, -} - -/// Request body for setting multiple memory entries at once. -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct BatchSetMemoryRequest { - pub entries: Vec<BatchMemoryEntry>, -} - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct MemorySetRequest { - pub value: String, -} - - impl ApiClient { /// List all directives. pub async fn list_directives(&self) -> Result<JsonValue, ApiError> { @@ -194,157 +146,6 @@ impl ApiClient { self.put(&format!("/api/v1/directives/{}", directive_id), &req).await } - // ── Directive Memory ────────────────────────────────────────────── - - /// List all memory entries for a directive. - pub async fn list_memories(&self, directive_id: Uuid) -> Result<JsonValue, ApiError> { - self.get(&format!("/api/v1/directives/{}/memory", directive_id)) - .await - } - - /// Get a single memory entry by key. - pub async fn get_memory( - &self, - directive_id: Uuid, - key: &str, - ) -> Result<JsonValue, ApiError> { - self.get(&format!( - "/api/v1/directives/{}/memory/{}", - directive_id, - percent_encode_path(key) - )) - .await - } - - /// Set (create or update) a single memory entry. - pub async fn set_memory( - &self, - directive_id: Uuid, - key: &str, - value: &str, - ) -> Result<JsonValue, ApiError> { - let req = SetMemoryRequest { - key: key.to_string(), - value: value.to_string(), - }; - self.put(&format!("/api/v1/directives/{}/memory", directive_id), &req) - .await - } - - /// Set multiple memory entries in a single request. - pub async fn batch_set_memories( - &self, - directive_id: Uuid, - entries: Vec<(String, String)>, - ) -> Result<JsonValue, ApiError> { - let req = BatchSetMemoryRequest { - entries: entries - .into_iter() - .map(|(key, value)| BatchMemoryEntry { key, value }) - .collect(), - }; - self.post( - &format!("/api/v1/directives/{}/memory/batch", directive_id), - &req, - ) - .await - } - - /// Delete a single memory entry by key. - pub async fn delete_memory( - &self, - directive_id: Uuid, - key: &str, - ) -> Result<(), ApiError> { - self.delete(&format!( - "/api/v1/directives/{}/memory/{}", - directive_id, - percent_encode_path(key) - )) - .await - } - - /// Clear all memory entries for a directive. - pub async fn clear_memories(&self, directive_id: Uuid) -> Result<(), ApiError> { - self.delete(&format!("/api/v1/directives/{}/memory", directive_id)) - .await - } - - // ── CLI-facing Directive Memory aliases ────────────────────────── - - /// Set a memory key-value pair for a directive (CLI-facing). - pub async fn directive_memory_set( - &self, - directive_id: Uuid, - key: &str, - value: &str, - ) -> Result<JsonValue, ApiError> { - let req = MemorySetRequest { - value: value.to_string(), - }; - self.put( - &format!("/api/v1/directives/{}/memory/{}", directive_id, key), - &req, - ) - .await - } - - /// Get a memory value by key for a directive (CLI-facing). - pub async fn directive_memory_get( - &self, - directive_id: Uuid, - key: &str, - ) -> Result<JsonValue, ApiError> { - self.get(&format!( - "/api/v1/directives/{}/memory/{}", - directive_id, key - )) - .await - } - - /// List all memory key-value pairs for a directive (CLI-facing). - pub async fn directive_memory_list( - &self, - directive_id: Uuid, - ) -> Result<JsonValue, ApiError> { - self.get(&format!("/api/v1/directives/{}/memory", directive_id)) - .await - } - - /// Delete a memory key for a directive (CLI-facing). - pub async fn directive_memory_delete( - &self, - directive_id: Uuid, - key: &str, - ) -> Result<(), ApiError> { - self.delete(&format!( - "/api/v1/directives/{}/memory/{}", - directive_id, key - )) - .await - } - - /// Clear all memory for a directive (CLI-facing). - pub async fn directive_memory_clear( - &self, - directive_id: Uuid, - ) -> Result<(), ApiError> { - self.delete(&format!("/api/v1/directives/{}/memory", directive_id)) - .await - } - - /// Batch set multiple memory key-value pairs for a directive (CLI-facing). - pub async fn directive_memory_batch_set( - &self, - directive_id: Uuid, - entries: serde_json::Value, - ) -> Result<JsonValue, ApiError> { - self.post( - &format!("/api/v1/directives/{}/memory/batch", directive_id), - &entries, - ) - .await - } } #[derive(Serialize)] diff --git a/makima/src/daemon/cli/directive.rs b/makima/src/daemon/cli/directive.rs index 8eded77..7c50c42 100644 --- a/makima/src/daemon/cli/directive.rs +++ b/makima/src/daemon/cli/directive.rs @@ -126,50 +126,3 @@ pub struct UpdateArgs { pub pr_branch: Option<String>, } -/// Arguments for memory-set command. -#[derive(Args, Debug)] -pub struct MemorySetArgs { - #[command(flatten)] - pub common: DirectiveArgs, - - /// Memory key - pub key: String, - - /// Memory value - pub value: String, -} - -/// Arguments for memory-get command. -#[derive(Args, Debug)] -pub struct MemoryGetArgs { - #[command(flatten)] - pub common: DirectiveArgs, - - /// Memory key - pub key: String, -} - -/// Arguments for memory-list command (uses DirectiveArgs directly). - -/// Arguments for memory-delete command. -#[derive(Args, Debug)] -pub struct MemoryDeleteArgs { - #[command(flatten)] - pub common: DirectiveArgs, - - /// Memory key to delete - pub key: String, -} - -/// Arguments for memory-clear command (uses DirectiveArgs directly). - -/// Arguments for memory-batch-set command. -#[derive(Args, Debug)] -pub struct MemoryBatchSetArgs { - #[command(flatten)] - pub common: DirectiveArgs, - - /// JSON object of key-value pairs: {"key1":"value1","key2":"value2"} - #[arg(long)] - pub json: String, -} diff --git a/makima/src/daemon/cli/mod.rs b/makima/src/daemon/cli/mod.rs index a78e5f8..bcaaa70 100644 --- a/makima/src/daemon/cli/mod.rs +++ b/makima/src/daemon/cli/mod.rs @@ -249,24 +249,6 @@ pub enum DirectiveCommand { /// Update directive metadata (PR URL, etc.) Update(directive::UpdateArgs), - - /// Set a memory key-value pair for the directive - MemorySet(directive::MemorySetArgs), - - /// Get a memory value by key - MemoryGet(directive::MemoryGetArgs), - - /// List all memory key-value pairs - MemoryList(DirectiveArgs), - - /// Delete a memory key - MemoryDelete(directive::MemoryDeleteArgs), - - /// Clear all memory for the directive - MemoryClear(DirectiveArgs), - - /// Batch set multiple memory key-value pairs from JSON - MemoryBatchSet(directive::MemoryBatchSetArgs), } impl Cli { diff --git a/makima/src/daemon/task/manager.rs b/makima/src/daemon/task/manager.rs index 22b41d9..ce5a580 100644 --- a/makima/src/daemon/task/manager.rs +++ b/makima/src/daemon/task/manager.rs @@ -20,7 +20,7 @@ use crate::daemon::error::{DaemonError, TaskError, TaskResult}; use crate::daemon::process::{ClaudeInputMessage, ProcessManager}; use crate::daemon::storage; use crate::daemon::temp::TempManager; -use crate::daemon::worktree::{is_new_repo_request, ConflictResolution, WorktreeInfo, WorktreeManager}; +use crate::daemon::worktree::{is_new_repo_request, ConflictResolution, WorktreeError, WorktreeInfo, WorktreeManager}; use crate::daemon::db::local::LocalDb; use crate::daemon::ws::{BranchInfo, DaemonCommand, DaemonMessage}; @@ -4406,8 +4406,14 @@ impl TaskManagerInner { // Create worktree - either from scratch or copying from another task let task_name = format!("task-{}", &task_id.to_string()[..8]); let worktree_info = if let Some(from_task_id) = continue_from_task_id { - // Try to find the source task's worktree path - match self.find_worktree_for_task(from_task_id).await { + // Fallback chain for continuing from a previous task: + // 1. Try copying from existing worktree (fastest, preserves uncommitted changes) + // 2. Try creating from pushed branch (branch was pushed to remote) + // 3. Try restoring from saved patch data + // 4. Fail if none available + + // Step 1: Try copying from existing worktree + let copy_result = match self.find_worktree_for_task(from_task_id).await { Ok(source_worktree) => { let msg = DaemonMessage::task_output( task_id, @@ -4416,66 +4422,112 @@ impl TaskManagerInner { ); let _ = self.ws_tx.send(msg).await; - // Create worktree by copying from source task self.worktree_manager .create_worktree_from_task(&source_worktree, task_id, &task_name) .await - .map_err(|e| DaemonError::Task(TaskError::SetupFailed(e.to_string())))? } - Err(worktree_err) => { - // Source worktree not found - try to recover using patch data - if let (Some(patch_str), Some(base_sha)) = (&patch_data, &patch_base_sha) { - tracing::info!( - task_id = %task_id, - from_task_id = %from_task_id, - base_sha = %base_sha, - patch_len = patch_str.len(), - "Source worktree not found, attempting to restore from patch" - ); + Err(e) => Err(crate::daemon::worktree::WorktreeError::RepoNotFound(e.to_string())), + }; - let msg = DaemonMessage::task_output( - task_id, - format!("Source worktree unavailable, restoring from checkpoint patch...\n"), - false, - ); - let _ = self.ws_tx.send(msg).await; + match copy_result { + Ok(info) => info, + Err(copy_err) => { + tracing::warn!( + task_id = %task_id, + from_task_id = %from_task_id, + error = %copy_err, + "Failed to copy from source worktree, trying branch fallback" + ); + + // Step 2: Try creating from pushed branch + let msg = DaemonMessage::task_output( + task_id, + format!("Source worktree unavailable, checking for pushed branch...\n"), + false, + ); + let _ = self.ws_tx.send(msg).await; + + match self.worktree_manager + .create_worktree_from_task_branch(&source_repo, from_task_id, task_id, &task_name) + .await + { + Ok(info) => { + tracing::info!( + task_id = %task_id, + from_task_id = %from_task_id, + branch = %info.branch, + "Successfully created worktree from pushed branch" + ); + let msg = DaemonMessage::task_output( + task_id, + format!("Restored from pushed branch {}\n", info.branch), + false, + ); + let _ = self.ws_tx.send(msg).await; + info + } + Err(branch_err) => { + tracing::warn!( + task_id = %task_id, + from_task_id = %from_task_id, + error = %branch_err, + "No pushed branch found, trying patch fallback" + ); + + // Step 3: Try restoring from saved patch data + if let (Some(patch_str), Some(base_sha)) = (&patch_data, &patch_base_sha) { + tracing::info!( + task_id = %task_id, + from_task_id = %from_task_id, + base_sha = %base_sha, + patch_len = patch_str.len(), + "Attempting to restore from checkpoint patch" + ); - // Decode base64 patch data - match base64::Engine::decode(&base64::engine::general_purpose::STANDARD, patch_str) { - Ok(patch_bytes) => { - match self.worktree_manager.restore_from_patch( - source, + let msg = DaemonMessage::task_output( task_id, - &task_name, - base_sha, - &patch_bytes, - ).await { - Ok(worktree_info) => { - tracing::info!( - task_id = %task_id, - path = %worktree_info.path.display(), - "Successfully restored worktree from patch" - ); - worktree_info + format!("Restoring from checkpoint patch...\n"), + false, + ); + let _ = self.ws_tx.send(msg).await; + + match base64::Engine::decode(&base64::engine::general_purpose::STANDARD, patch_str) { + Ok(patch_bytes) => { + match self.worktree_manager.restore_from_patch( + source, + task_id, + &task_name, + base_sha, + &patch_bytes, + ).await { + Ok(worktree_info) => { + tracing::info!( + task_id = %task_id, + path = %worktree_info.path.display(), + "Successfully restored worktree from patch" + ); + worktree_info + } + Err(e) => { + return Err(DaemonError::Task(TaskError::SetupFailed( + format!("Cannot continue from task {}: worktree copy failed ({}), branch not found ({}), patch restore failed ({})", from_task_id, copy_err, branch_err, e) + ))); + } + } } Err(e) => { return Err(DaemonError::Task(TaskError::SetupFailed( - format!("Cannot continue from task {}: {} (patch restore also failed: {})", from_task_id, worktree_err, e) + format!("Cannot continue from task {}: worktree copy failed ({}), branch not found ({}), patch decode failed ({})", from_task_id, copy_err, branch_err, e) ))); } } - } - Err(e) => { + } else { + // Step 4: No fallback available return Err(DaemonError::Task(TaskError::SetupFailed( - format!("Cannot continue from task {}: {} (patch decode failed: {})", from_task_id, worktree_err, e) + format!("Cannot continue from task {}: worktree copy failed ({}), branch not found ({}), no patch data available", from_task_id, copy_err, branch_err) ))); } } - } else { - // No patch data available - fail with original error - return Err(DaemonError::Task(TaskError::SetupFailed( - format!("Cannot continue from task {}: {}", from_task_id, worktree_err) - ))); } } } diff --git a/makima/src/daemon/worktree/manager.rs b/makima/src/daemon/worktree/manager.rs index 20c93b1..04180b8 100644 --- a/makima/src/daemon/worktree/manager.rs +++ b/makima/src/daemon/worktree/manager.rs @@ -692,6 +692,85 @@ impl WorktreeManager { }) } + /// Find and create a worktree from a previously pushed branch for a task. + /// + /// Searches local and remote branches for ones matching the task's UUID, + /// then creates a new worktree based on that branch. + pub async fn create_worktree_from_task_branch( + &self, + source_repo: &Path, + from_task_id: Uuid, + new_task_id: Uuid, + new_task_name: &str, + ) -> Result<WorktreeInfo, WorktreeError> { + let from_short_id = short_uuid(from_task_id); + let from_full_id = from_task_id.to_string(); + + tracing::info!( + from_task_id = %from_task_id, + new_task_id = %new_task_id, + "Searching for pushed branch to continue from" + ); + + // Fetch latest from remote first + let _ = Command::new("git") + .args(["fetch", "--all", "--prune"]) + .current_dir(source_repo) + .output() + .await; + + // Search for branches matching the task ID (both local and remote) + let output = Command::new("git") + .args(["branch", "-a", "--format=%(refname:short)"]) + .current_dir(source_repo) + .output() + .await?; + + if !output.status.success() { + return Err(WorktreeError::GitCommand( + "Failed to list branches".to_string(), + )); + } + + let branches_output = String::from_utf8_lossy(&output.stdout); + let mut found_branch: Option<String> = None; + + for line in branches_output.lines() { + let b = line.trim(); + if b.is_empty() { + continue; + } + // Match branches containing the full UUID or short UUID + if b.contains(&from_full_id) || b.contains(&from_short_id) { + // Prefer local branches, but accept remote + if let Some(remote_branch) = b.strip_prefix("origin/") { + if found_branch.is_none() { + found_branch = Some(remote_branch.to_string()); + } + } else { + found_branch = Some(b.to_string()); + } + } + } + + let from_branch = found_branch.ok_or_else(|| { + WorktreeError::GitCommand(format!( + "No branch found for task {} in repository", + from_short_id + )) + })?; + + tracing::info!( + from_task_id = %from_task_id, + from_branch = %from_branch, + "Found pushed branch, creating worktree from it" + ); + + // Create a worktree using the found branch as the base + self.create_worktree(source_repo, new_task_id, new_task_name, &from_branch) + .await + } + /// Remove a worktree and optionally its branch. pub async fn remove_worktree( &self, diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index 66c0a30..131dffc 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -2714,7 +2714,6 @@ pub struct Directive { pub pr_url: Option<String>, pub pr_branch: Option<String>, pub completion_task_id: Option<Uuid>, - pub memory_enabled: bool, pub goal_updated_at: DateTime<Utc>, pub started_at: Option<DateTime<Utc>>, pub version: i32, @@ -2764,7 +2763,6 @@ pub struct DirectiveSummary { pub orchestrator_task_id: Option<Uuid>, pub pr_url: Option<String>, pub completion_task_id: Option<Uuid>, - pub memory_enabled: bool, pub version: i32, pub created_at: DateTime<Utc>, pub updated_at: DateTime<Utc>, @@ -2791,8 +2789,6 @@ pub struct CreateDirectiveRequest { pub repository_url: Option<String>, pub local_path: Option<String>, pub base_branch: Option<String>, - #[serde(default)] - pub memory_enabled: bool, } /// Request to update a directive. @@ -2808,7 +2804,6 @@ pub struct UpdateDirectiveRequest { pub orchestrator_task_id: Option<Uuid>, pub pr_url: Option<String>, pub pr_branch: Option<String>, - pub memory_enabled: Option<bool>, pub version: Option<i32>, } @@ -2853,43 +2848,3 @@ pub struct UpdateDirectiveStepRequest { pub order_index: Option<i32>, } -// ============================================================================= -// Directive Memory Types -// ============================================================================= - -/// A memory entry for a directive — key-value context that persists across tasks. -#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct DirectiveMemory { - pub id: Uuid, - pub directive_id: Uuid, - pub key: String, - pub value: String, - pub category: Option<String>, - pub created_at: DateTime<Utc>, - pub updated_at: DateTime<Utc>, -} - -/// Request to set a memory entry (upsert by key). -#[derive(Debug, Deserialize, ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct SetDirectiveMemoryRequest { - pub key: String, - pub value: String, - pub category: Option<String>, -} - -/// Request to batch set memory entries. -#[derive(Debug, Deserialize, ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct BatchSetDirectiveMemoryRequest { - pub entries: Vec<SetDirectiveMemoryRequest>, -} - -/// Response for listing memories. -#[derive(Debug, Serialize, ToSchema)] -#[serde(rename_all = "camelCase")] -pub struct DirectiveMemoryListResponse { - pub memories: Vec<DirectiveMemory>, - pub total: i64, -} diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 51f49cd..8923f97 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -11,10 +11,9 @@ use super::models::{ ContractTypeTemplateRecord, ConversationMessage, ConversationSnapshot, CreateContractRequest, CreateFileRequest, CreateTaskRequest, CreateTemplateRequest, Daemon, DaemonTaskAssignment, DaemonWithCapacity, - DeliverableDefinition, Directive, DirectiveMemory, DirectiveStep, DirectiveSummary, + DeliverableDefinition, Directive, DirectiveStep, DirectiveSummary, CreateDirectiveRequest, CreateDirectiveStepRequest, UpdateDirectiveRequest, - UpdateDirectiveStepRequest, SetDirectiveMemoryRequest, - BatchSetDirectiveMemoryRequest, DirectiveMemoryListResponse, + UpdateDirectiveStepRequest, File, FileSummary, FileVersion, HistoryEvent, HistoryQueryFilters, MeshChatConversation, MeshChatMessageRecord, PhaseChangeResult, PhaseConfig, PhaseDefinition, SupervisorHeartbeatRecord, SupervisorState, @@ -4930,8 +4929,8 @@ pub async fn create_directive_for_owner( ) -> Result<Directive, sqlx::Error> { sqlx::query_as::<_, Directive>( r#" - INSERT INTO directives (owner_id, title, goal, repository_url, local_path, base_branch, memory_enabled) - VALUES ($1, $2, $3, $4, $5, $6, $7) + INSERT INTO directives (owner_id, title, goal, repository_url, local_path, base_branch) + VALUES ($1, $2, $3, $4, $5, $6) RETURNING * "#, ) @@ -4941,7 +4940,6 @@ pub async fn create_directive_for_owner( .bind(&req.repository_url) .bind(&req.local_path) .bind(&req.base_branch) - .bind(req.memory_enabled) .fetch_one(pool) .await } @@ -4994,7 +4992,7 @@ pub async fn list_directives_for_owner( SELECT d.id, d.owner_id, d.title, d.goal, d.status, d.repository_url, d.orchestrator_task_id, d.pr_url, d.completion_task_id, - d.memory_enabled, d.version, d.created_at, d.updated_at, + d.version, d.created_at, d.updated_at, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id), 0) as total_steps, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'completed'), 0) as completed_steps, COALESCE((SELECT COUNT(*) FROM directive_steps WHERE directive_id = d.id AND status = 'running'), 0) as running_steps, @@ -5048,13 +5046,12 @@ pub async fn update_directive_for_owner( let orchestrator_task_id = req.orchestrator_task_id.or(current.orchestrator_task_id); let pr_url = req.pr_url.as_deref().or(current.pr_url.as_deref()); let pr_branch = req.pr_branch.as_deref().or(current.pr_branch.as_deref()); - let memory_enabled = req.memory_enabled.unwrap_or(current.memory_enabled); let result = sqlx::query_as::<_, Directive>( r#" UPDATE directives SET title = $3, goal = $4, status = $5, repository_url = $6, local_path = $7, - base_branch = $8, orchestrator_task_id = $9, pr_url = $10, pr_branch = $11, memory_enabled = $12, + base_branch = $8, orchestrator_task_id = $9, pr_url = $10, pr_branch = $11, version = version + 1, updated_at = NOW() WHERE id = $1 AND owner_id = $2 RETURNING * @@ -5071,7 +5068,6 @@ pub async fn update_directive_for_owner( .bind(orchestrator_task_id) .bind(pr_url) .bind(pr_branch) - .bind(memory_enabled) .fetch_optional(pool) .await .map_err(RepositoryError::Database)?; @@ -5609,7 +5605,6 @@ pub struct StepForDispatch { pub directive_title: String, pub repository_url: Option<String>, pub base_branch: Option<String>, - pub memory_enabled: bool, /// The directive's PR branch (if a PR has already been created from previous steps). pub pr_branch: Option<String>, } @@ -5633,7 +5628,6 @@ pub async fn get_ready_steps_for_dispatch( d.title AS directive_title, d.repository_url, d.base_branch, - d.memory_enabled, d.pr_branch FROM directive_steps ds JOIN directives d ON d.id = ds.directive_id @@ -5895,128 +5889,3 @@ pub async fn get_directive_max_generation( Ok(row.0.unwrap_or(0)) } -// ============================================================================= -// Directive Memory CRUD -// ============================================================================= - -/// List all memories for a directive, optionally filtered by category. -pub async fn list_directive_memories( - pool: &PgPool, - directive_id: Uuid, - category: Option<&str>, -) -> Result<Vec<DirectiveMemory>, sqlx::Error> { - match category { - Some(cat) => { - sqlx::query_as::<_, DirectiveMemory>( - r#" - SELECT * FROM directive_memories - WHERE directive_id = $1 AND category = $2 - ORDER BY key - "#, - ) - .bind(directive_id) - .bind(cat) - .fetch_all(pool) - .await - } - None => { - sqlx::query_as::<_, DirectiveMemory>( - r#" - SELECT * FROM directive_memories - WHERE directive_id = $1 - ORDER BY key - "#, - ) - .bind(directive_id) - .fetch_all(pool) - .await - } - } -} - -/// Get a single memory entry by directive ID and key. -pub async fn get_directive_memory( - pool: &PgPool, - directive_id: Uuid, - key: &str, -) -> Result<Option<DirectiveMemory>, sqlx::Error> { - sqlx::query_as::<_, DirectiveMemory>( - r#" - SELECT * FROM directive_memories - WHERE directive_id = $1 AND key = $2 - "#, - ) - .bind(directive_id) - .bind(key) - .fetch_optional(pool) - .await -} - -/// Set (upsert) a memory entry for a directive. -pub async fn set_directive_memory( - pool: &PgPool, - directive_id: Uuid, - req: &SetDirectiveMemoryRequest, -) -> Result<DirectiveMemory, sqlx::Error> { - sqlx::query_as::<_, DirectiveMemory>( - r#" - INSERT INTO directive_memories (directive_id, key, value, category) - VALUES ($1, $2, $3, $4) - ON CONFLICT (directive_id, key) - DO UPDATE SET value = EXCLUDED.value, - category = EXCLUDED.category, - updated_at = NOW() - RETURNING * - "#, - ) - .bind(directive_id) - .bind(&req.key) - .bind(&req.value) - .bind(&req.category) - .fetch_one(pool) - .await -} - -/// Batch set memory entries for a directive. -pub async fn batch_set_directive_memories( - pool: &PgPool, - directive_id: Uuid, - memories: &[SetDirectiveMemoryRequest], -) -> Result<Vec<DirectiveMemory>, sqlx::Error> { - let mut results = Vec::with_capacity(memories.len()); - for mem in memories { - let result = set_directive_memory(pool, directive_id, mem).await?; - results.push(result); - } - Ok(results) -} - -/// Delete a single memory entry by key. -pub async fn delete_directive_memory( - pool: &PgPool, - directive_id: Uuid, - key: &str, -) -> Result<bool, sqlx::Error> { - let result = sqlx::query( - r#"DELETE FROM directive_memories WHERE directive_id = $1 AND key = $2"#, - ) - .bind(directive_id) - .bind(key) - .execute(pool) - .await?; - Ok(result.rows_affected() > 0) -} - -/// Delete all memory entries for a directive. -pub async fn clear_directive_memories( - pool: &PgPool, - directive_id: Uuid, -) -> Result<u64, sqlx::Error> { - let result = sqlx::query( - r#"DELETE FROM directive_memories WHERE directive_id = $1"#, - ) - .bind(directive_id) - .execute(pool) - .await?; - Ok(result.rows_affected()) -} diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs index 344bdf5..bb573d4 100644 --- a/makima/src/orchestration/directive.rs +++ b/makima/src/orchestration/directive.rs @@ -9,7 +9,7 @@ use sqlx::PgPool; use uuid::Uuid; -use crate::db::models::{CreateTaskRequest, DirectiveMemory, UpdateTaskRequest}; +use crate::db::models::{CreateTaskRequest, UpdateTaskRequest}; use crate::db::repository; use crate::server::state::{DaemonCommand, SharedState}; @@ -44,24 +44,7 @@ impl DirectiveOrchestrator { "Directive needs planning — spawning planning task" ); - // Load memories if memory is enabled for this directive - let memories = if directive.memory_enabled { - match repository::list_directive_memories(&self.pool, directive.id, None).await { - Ok(m) => m, - Err(e) => { - tracing::warn!( - directive_id = %directive.id, - error = %e, - "Failed to load directive memories for planning — continuing without" - ); - vec![] - } - } - } else { - vec![] - }; - - let plan = build_planning_prompt(&directive, &[], 1, &memories); + let plan = build_planning_prompt(&directive, &[], 1); if let Err(e) = self .spawn_orchestrator_task( @@ -143,27 +126,6 @@ impl DirectiveOrchestrator { .as_deref() .unwrap_or("Execute the step described below."); - // Load memories if memory is enabled for this directive - let memory_context = if step.memory_enabled { - match repository::list_directive_memories(&self.pool, step.directive_id, None).await { - Ok(memories) if !memories.is_empty() => { - format!("\n\nMEMORY CONTEXT (from previous planning/execution cycles):\n{}\n", - format_memories_for_prompt(&memories)) - } - Ok(_) => String::new(), - Err(e) => { - tracing::warn!( - directive_id = %step.directive_id, - error = %e, - "Failed to load directive memories for execution — continuing without" - ); - String::new() - } - } - } else { - String::new() - }; - // Build merge instructions for additional dependencies (beyond the first) let merge_preamble = if dep_tasks.len() > 1 { use crate::daemon::worktree::{sanitize_name, short_uuid}; @@ -196,7 +158,6 @@ impl DirectiveOrchestrator { DESCRIPTION: {description}\n\n\ {merge_preamble}\ INSTRUCTIONS:\n{task_plan}\n\ - {memory_context}\ When done, the system will automatically mark this step as completed.\n\ If you cannot complete the task, report the failure clearly.", directive_title = step.directive_title, @@ -204,7 +165,6 @@ impl DirectiveOrchestrator { description = step.step_description.as_deref().unwrap_or("(none)"), merge_preamble = merge_preamble, task_plan = task_plan, - memory_context = memory_context, ); match self @@ -348,24 +308,7 @@ impl DirectiveOrchestrator { let generation = repository::get_directive_max_generation(&self.pool, directive.id).await? + 1; - // Load memories if memory is enabled for this directive - let memories = if directive.memory_enabled { - match repository::list_directive_memories(&self.pool, directive.id, None).await { - Ok(m) => m, - Err(e) => { - tracing::warn!( - directive_id = %directive.id, - error = %e, - "Failed to load directive memories for re-planning — continuing without" - ); - vec![] - } - } - } else { - vec![] - }; - - let plan = build_planning_prompt(&directive, &existing_steps, generation, &memories); + let plan = build_planning_prompt(&directive, &existing_steps, generation); if let Err(e) = self .spawn_orchestrator_task( @@ -747,35 +690,14 @@ impl DirectiveOrchestrator { } } -/// Format memory entries into a readable prompt section. -fn format_memories_for_prompt(memories: &[DirectiveMemory]) -> String { - let mut out = String::new(); - for memory in memories { - let cat = memory.category.as_deref().unwrap_or("other"); - out.push_str(&format!( - "- [{}] {}: {}\n", - cat, memory.key, memory.value - )); - } - out -} - /// Build the planning prompt for a directive. fn build_planning_prompt( directive: &crate::db::models::Directive, existing_steps: &[crate::db::models::DirectiveStep], generation: i32, - memories: &[DirectiveMemory], ) -> String { let mut prompt = String::new(); - // Include memory context if available - if !memories.is_empty() { - prompt.push_str("MEMORY CONTEXT (insights and decisions from previous cycles):\n"); - prompt.push_str(&format_memories_for_prompt(memories)); - prompt.push_str("\nUse these memories to inform your planning. Avoid repeating past mistakes and build on prior insights.\n\n"); - } - if !existing_steps.is_empty() { prompt.push_str(&format!( "EXISTING STEPS (generation {}):\n", diff --git a/makima/src/server/handlers/directives.rs b/makima/src/server/handlers/directives.rs index 9314031..25b2dc4 100644 --- a/makima/src/server/handlers/directives.rs +++ b/makima/src/server/handlers/directives.rs @@ -1,18 +1,17 @@ //! HTTP handlers for directive CRUD and DAG progression. use axum::{ - extract::{Path, Query, State}, + extract::{Path, State}, http::StatusCode, response::IntoResponse, Json, }; -use serde::Deserialize; use uuid::Uuid; use crate::db::models::{ - BatchSetDirectiveMemoryRequest, CleanupTasksResponse, CreateDirectiveRequest, - CreateDirectiveStepRequest, Directive, DirectiveListResponse, DirectiveMemory, - DirectiveMemoryListResponse, DirectiveStep, DirectiveWithSteps, SetDirectiveMemoryRequest, + CleanupTasksResponse, CreateDirectiveRequest, + CreateDirectiveStepRequest, Directive, DirectiveListResponse, + DirectiveStep, DirectiveWithSteps, UpdateDirectiveRequest, UpdateDirectiveStepRequest, UpdateGoalRequest, }; use crate::db::repository; @@ -20,12 +19,6 @@ use crate::server::auth::Authenticated; use crate::server::messages::ApiError; use crate::server::state::SharedState; -/// Query parameters for the memory list endpoint. -#[derive(Debug, Deserialize)] -pub struct MemoryListQuery { - pub category: Option<String>, -} - // ============================================================================= // Directive CRUD // ============================================================================= @@ -849,385 +842,6 @@ pub async fn update_goal( } // ============================================================================= -// Directive Memory CRUD -// ============================================================================= - -/// List all memories for a directive, optionally filtered by category. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}/memories", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("category" = Option<String>, Query, description = "Filter by category"), - ), - responses( - (status = 200, description = "List of memories", body = DirectiveMemoryListResponse), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn list_memories( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, - Query(query): Query<MemoryListQuery>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::list_directive_memories(pool, id, query.category.as_deref()).await { - Ok(memories) => { - let total = memories.len() as i64; - Json(DirectiveMemoryListResponse { memories, total }).into_response() - } - Err(e) => { - tracing::error!("Failed to list memories: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("LIST_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -/// Get a single memory entry by key. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}/memories/{key}", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("key" = String, Path, description = "Memory key"), - ), - responses( - (status = 200, description = "Memory entry", body = DirectiveMemory), - (status = 404, description = "Not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn get_memory( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path((id, key)): Path<(Uuid, String)>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::get_directive_memory(pool, id, &key).await { - Ok(Some(memory)) => Json(memory).into_response(), - Ok(None) => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Memory entry not found")), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to get memory: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -/// Set (upsert) a single memory entry. -#[utoipa::path( - post, - path = "/api/v1/directives/{id}/memories", - params(("id" = Uuid, Path, description = "Directive ID")), - request_body = SetDirectiveMemoryRequest, - responses( - (status = 200, description = "Memory entry set", body = DirectiveMemory), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn set_memory( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, - Json(req): Json<SetDirectiveMemoryRequest>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::set_directive_memory(pool, id, &req).await { - Ok(memory) => Json(memory).into_response(), - Err(e) => { - tracing::error!("Failed to set memory: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("SET_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -/// Batch set multiple memory entries. -#[utoipa::path( - post, - path = "/api/v1/directives/{id}/memories/batch", - params(("id" = Uuid, Path, description = "Directive ID")), - request_body = BatchSetDirectiveMemoryRequest, - responses( - (status = 200, description = "Memory entries set", body = Vec<DirectiveMemory>), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn batch_set_memories( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, - Json(req): Json<BatchSetDirectiveMemoryRequest>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::batch_set_directive_memories(pool, id, &req.entries).await { - Ok(memories) => Json(memories).into_response(), - Err(e) => { - tracing::error!("Failed to batch set memories: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("SET_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -/// Delete a single memory entry by key. -#[utoipa::path( - delete, - path = "/api/v1/directives/{id}/memories/{key}", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("key" = String, Path, description = "Memory key"), - ), - responses( - (status = 204, description = "Deleted"), - (status = 404, description = "Not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn delete_memory( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path((id, key)): Path<(Uuid, String)>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::delete_directive_memory(pool, id, &key).await { - Ok(true) => StatusCode::NO_CONTENT.into_response(), - Ok(false) => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Memory entry not found")), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to delete memory: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DELETE_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -/// Clear all memories for a directive. -#[utoipa::path( - delete, - path = "/api/v1/directives/{id}/memories", - params(("id" = Uuid, Path, description = "Directive ID")), - responses( - (status = 204, description = "All memories cleared"), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - ), - security(("bearer_auth" = []), ("api_key" = [])), - tag = "Directives" -)] -pub async fn clear_memories( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive ownership - match repository::get_directive_for_owner(pool, auth.owner_id, id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("GET_FAILED", &e.to_string())), - ) - .into_response(); - } - } - - match repository::clear_directive_memories(pool, id).await { - Ok(_) => StatusCode::NO_CONTENT.into_response(), - Err(e) => { - tracing::error!("Failed to clear memories: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("CLEAR_FAILED", &e.to_string())), - ) - .into_response() - } - } -} - -// ============================================================================= // Task Cleanup // ============================================================================= diff --git a/makima/src/server/mod.rs b/makima/src/server/mod.rs index 7110ef8..c1e1309 100644 --- a/makima/src/server/mod.rs +++ b/makima/src/server/mod.rs @@ -238,10 +238,6 @@ pub fn make_router(state: SharedState) -> Router { .route("/directives/{id}/steps/{step_id}/skip", post(directives::skip_step)) .route("/directives/{id}/goal", put(directives::update_goal)) .route("/directives/{id}/cleanup-tasks", post(directives::cleanup_tasks)) - // Directive memory endpoints - .route("/directives/{id}/memories", get(directives::list_memories).post(directives::set_memory).delete(directives::clear_memories)) - .route("/directives/{id}/memories/batch", post(directives::batch_set_memories)) - .route("/directives/{id}/memories/{key}", get(directives::get_memory).delete(directives::delete_memory)) // Timeline endpoint (unified history for user) .route("/timeline", get(history::get_timeline)) // Contract type templates (built-in only) diff --git a/makima/src/server/openapi.rs b/makima/src/server/openapi.rs index f28b105..e68286e 100644 --- a/makima/src/server/openapi.rs +++ b/makima/src/server/openapi.rs @@ -3,7 +3,7 @@ use utoipa::OpenApi; use crate::db::models::{ - AddLocalRepositoryRequest, AddRemoteRepositoryRequest, BatchSetDirectiveMemoryRequest, + AddLocalRepositoryRequest, AddRemoteRepositoryRequest, BranchInfo, BranchListResponse, BranchTaskRequest, BranchTaskResponse, ChangePhaseRequest, Contract, ContractChatHistoryResponse, ContractChatMessageRecord, ContractEvent, @@ -11,14 +11,14 @@ use crate::db::models::{ CleanupTasksResponse, CreateContractRequest, CreateDirectiveRequest, CreateDirectiveStepRequest, CreateFileRequest, CreateManagedRepositoryRequest, CreateTaskRequest, Daemon, DaemonDirectoriesResponse, - DaemonDirectory, DaemonListResponse, Directive, DirectiveListResponse, DirectiveMemory, - DirectiveMemoryListResponse, DirectiveStep, DirectiveSummary, DirectiveWithSteps, + DaemonDirectory, DaemonListResponse, Directive, DirectiveListResponse, + DirectiveStep, DirectiveSummary, DirectiveWithSteps, File, FileListResponse, FileSummary, MergeCommitRequest, MergeCompleteCheckResponse, MergeResolveRequest, MergeResultResponse, MergeSkipRequest, MergeStartRequest, MergeStatusResponse, MeshChatConversation, MeshChatHistoryResponse, MeshChatMessageRecord, RepositoryHistoryEntry, RepositoryHistoryListResponse, RepositorySuggestionsQuery, SendMessageRequest, - SetDirectiveMemoryRequest, Task, + Task, TaskEventListResponse, TaskListResponse, TaskSummary, TaskWithSubtasks, TranscriptEntry, UpdateContractRequest, UpdateDirectiveRequest, UpdateDirectiveStepRequest, UpdateFileRequest, UpdateGoalRequest, UpdateTaskRequest, @@ -125,13 +125,6 @@ use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage directives::skip_step, directives::update_goal, directives::cleanup_tasks, - // Directive memory endpoints - directives::list_memories, - directives::get_memory, - directives::set_memory, - directives::batch_set_memories, - directives::delete_memory, - directives::clear_memories, // Repository history/settings endpoints repository_history::list_repository_history, repository_history::get_repository_suggestions, @@ -229,10 +222,6 @@ use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage CreateDirectiveStepRequest, UpdateDirectiveStepRequest, CleanupTasksResponse, - DirectiveMemory, - DirectiveMemoryListResponse, - SetDirectiveMemoryRequest, - BatchSetDirectiveMemoryRequest, // Repository history schemas RepositoryHistoryEntry, RepositoryHistoryListResponse, |
