mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
remove get_task_result, remove bool defaults, RECIPE_TASK_TYPE constant, cloneable RecipeFile
This commit is contained in:
@@ -57,15 +57,13 @@ fn create_tasks_from_params(
|
||||
sub_recipe: &SubRecipe,
|
||||
command_params: &[std::collections::HashMap<String, String>],
|
||||
) -> Result<Vec<Task>> {
|
||||
let recipe_file = load_local_recipe_file(&sub_recipe.path)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to load recipe {}: {}", sub_recipe.path, e))?;
|
||||
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
for task_command_param in command_params {
|
||||
// Load the recipe file for each task (can't clone RecipeFile)
|
||||
let recipe_file = load_local_recipe_file(&sub_recipe.path)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to load recipe {}: {}", sub_recipe.path, e))?;
|
||||
|
||||
let recipe = build_recipe_from_template(
|
||||
recipe_file.content,
|
||||
recipe_file.content.clone(),
|
||||
&recipe_file.parent_dir,
|
||||
task_command_param
|
||||
.iter()
|
||||
|
||||
@@ -17,6 +17,8 @@ use crate::agents::subagent_execution_tool::utils::{count_by_status, get_task_na
|
||||
use crate::utils::is_token_cancelled;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
const RECIPE_TASK_TYPE: &str = "recipe";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum DisplayMode {
|
||||
MultipleTasksOutput,
|
||||
@@ -148,13 +150,15 @@ impl TaskExecutionTracker {
|
||||
async fn format_line(&self, task_info: Option<&TaskInfo>, line: &str) -> String {
|
||||
if let Some(task_info) = task_info {
|
||||
let task_name = get_task_name(task_info);
|
||||
let task_type = "recipe";
|
||||
let metadata = format_task_metadata(task_info);
|
||||
|
||||
if metadata.is_empty() {
|
||||
format!("[{} ({})] {}", task_name, task_type, line)
|
||||
format!("[{} ({})] {}", task_name, RECIPE_TASK_TYPE, line)
|
||||
} else {
|
||||
format!("[{} ({}) {}] {}", task_name, task_type, metadata, line)
|
||||
format!(
|
||||
"[{} ({}) {}] {}",
|
||||
task_name, RECIPE_TASK_TYPE, metadata, line
|
||||
)
|
||||
}
|
||||
} else {
|
||||
line.to_string()
|
||||
@@ -229,7 +233,7 @@ impl TaskExecutionTracker {
|
||||
}
|
||||
}),
|
||||
current_output: task_info.current_output.clone(),
|
||||
task_type: "recipe".to_string(),
|
||||
task_type: RECIPE_TASK_TYPE.to_string(),
|
||||
task_name: get_task_name(task_info).to_string(),
|
||||
task_metadata: format_task_metadata(task_info),
|
||||
error: task_info.error().cloned(),
|
||||
|
||||
@@ -20,9 +20,7 @@ pub enum ExecutionMode {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TaskPayload {
|
||||
pub recipe: Recipe,
|
||||
#[serde(default)]
|
||||
pub return_last_only: bool,
|
||||
#[serde(default)]
|
||||
pub sequential_when_repeated: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parameter_values: Option<HashMap<String, String>>,
|
||||
|
||||
@@ -8,18 +8,11 @@ use crate::agents::subagent_task_config::TaskConfig;
|
||||
|
||||
pub async fn process_task(
|
||||
task: &Task,
|
||||
task_execution_tracker: Arc<TaskExecutionTracker>,
|
||||
_task_execution_tracker: Arc<TaskExecutionTracker>,
|
||||
task_config: TaskConfig,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> TaskResult {
|
||||
match get_task_result(
|
||||
task.clone(),
|
||||
task_execution_tracker,
|
||||
task_config,
|
||||
cancellation_token,
|
||||
)
|
||||
.await
|
||||
{
|
||||
match handle_recipe_task(task.clone(), task_config, cancellation_token).await {
|
||||
Ok(data) => TaskResult {
|
||||
task_id: task.id.clone(),
|
||||
status: TaskStatus::Completed,
|
||||
@@ -35,15 +28,6 @@ pub async fn process_task(
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_task_result(
|
||||
task: Task,
|
||||
_task_execution_tracker: Arc<TaskExecutionTracker>,
|
||||
task_config: TaskConfig,
|
||||
cancellation_token: CancellationToken,
|
||||
) -> Result<Value, String> {
|
||||
handle_recipe_task(task, task_config, cancellation_token).await
|
||||
}
|
||||
|
||||
async fn handle_recipe_task(
|
||||
task: Task,
|
||||
mut task_config: TaskConfig,
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::collections::HashMap;
|
||||
use crate::agents::subagent_execution_tool::task_types::{TaskInfo, TaskStatus};
|
||||
|
||||
pub fn get_task_name(task_info: &TaskInfo) -> &str {
|
||||
// Return the recipe title (always present as it's a required field)
|
||||
&task_info.task.payload.recipe.title
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use tracing::{debug, info};
|
||||
|
||||
// Type alias for the complex return type
|
||||
type AgentMessagesFuture =
|
||||
Pin<Box<dyn Future<Output = Result<(Conversation, Option<String>)>> + Send>>;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RecipeFile {
|
||||
pub content: String,
|
||||
pub parent_dir: PathBuf,
|
||||
|
||||
@@ -14,11 +14,11 @@ use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{Mutex, OnceCell};
|
||||
use tokio::sync::OnceCell;
|
||||
use tracing::{info, warn};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
const CURRENT_SCHEMA_VERSION: i32 = 3;
|
||||
const CURRENT_SCHEMA_VERSION: i32 = 2;
|
||||
|
||||
static SESSION_STORAGE: OnceCell<Arc<SessionStorage>> = OnceCell::const_new();
|
||||
|
||||
@@ -245,7 +245,6 @@ impl SessionManager {
|
||||
|
||||
pub struct SessionStorage {
|
||||
pool: Pool<Sqlite>,
|
||||
create_session_mutex: Arc<Mutex<()>>,
|
||||
}
|
||||
|
||||
pub fn ensure_session_dir() -> Result<PathBuf> {
|
||||
@@ -354,7 +353,8 @@ impl SessionStorage {
|
||||
let options = SqliteConnectOptions::new()
|
||||
.filename(db_path)
|
||||
.create_if_missing(create_if_missing)
|
||||
.busy_timeout(std::time::Duration::from_secs(5));
|
||||
.busy_timeout(std::time::Duration::from_secs(5))
|
||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal);
|
||||
|
||||
sqlx::SqlitePool::connect_with(options).await.map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
@@ -368,10 +368,7 @@ impl SessionStorage {
|
||||
async fn open(db_path: &Path) -> Result<Self> {
|
||||
let pool = Self::get_pool(db_path, false).await?;
|
||||
|
||||
let storage = Self {
|
||||
pool,
|
||||
create_session_mutex: Arc::new(Mutex::new(())),
|
||||
};
|
||||
let storage = Self { pool };
|
||||
storage.run_migrations().await?;
|
||||
Ok(storage)
|
||||
}
|
||||
@@ -428,8 +425,7 @@ impl SessionStorage {
|
||||
content_json TEXT NOT NULL,
|
||||
created_timestamp INTEGER NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
tokens INTEGER,
|
||||
metadata_json TEXT
|
||||
tokens INTEGER
|
||||
)
|
||||
"#,
|
||||
)
|
||||
@@ -446,10 +442,7 @@ impl SessionStorage {
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
|
||||
Ok(Self {
|
||||
pool,
|
||||
create_session_mutex: Arc::new(Mutex::new(())),
|
||||
})
|
||||
Ok(Self { pool })
|
||||
}
|
||||
|
||||
async fn import_legacy(&self, session_dir: &PathBuf) -> Result<()> {
|
||||
@@ -617,15 +610,6 @@ impl SessionStorage {
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
}
|
||||
3 => {
|
||||
sqlx::query(
|
||||
r#"
|
||||
ALTER TABLE messages ADD COLUMN metadata_json TEXT
|
||||
"#,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
}
|
||||
_ => {
|
||||
anyhow::bail!("Unknown migration version: {}", version);
|
||||
}
|
||||
@@ -635,9 +619,6 @@ impl SessionStorage {
|
||||
}
|
||||
|
||||
async fn create_session(&self, working_dir: PathBuf, description: String) -> Result<Session> {
|
||||
// Mutex to prevent concurrent session creation race conditions
|
||||
let _guard = self.create_session_mutex.lock().await;
|
||||
|
||||
let today = chrono::Utc::now().format("%Y%m%d").to_string();
|
||||
Ok(sqlx::query_as(
|
||||
r#"
|
||||
@@ -787,15 +768,15 @@ impl SessionStorage {
|
||||
}
|
||||
|
||||
async fn get_conversation(&self, session_id: &str) -> Result<Conversation> {
|
||||
let rows = sqlx::query_as::<_, (String, String, i64, Option<String>)>(
|
||||
"SELECT role, content_json, created_timestamp, metadata_json FROM messages WHERE session_id = ? ORDER BY timestamp",
|
||||
let rows = sqlx::query_as::<_, (String, String, i64)>(
|
||||
"SELECT role, content_json, created_timestamp FROM messages WHERE session_id = ? ORDER BY timestamp",
|
||||
)
|
||||
.bind(session_id)
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
|
||||
let mut messages = Vec::new();
|
||||
for (role_str, content_json, created_timestamp, metadata_json) in rows {
|
||||
for (role_str, content_json, created_timestamp) in rows {
|
||||
let role = match role_str.as_str() {
|
||||
"user" => Role::User,
|
||||
"assistant" => Role::Assistant,
|
||||
@@ -803,12 +784,7 @@ impl SessionStorage {
|
||||
};
|
||||
|
||||
let content = serde_json::from_str(&content_json)?;
|
||||
let metadata = metadata_json
|
||||
.and_then(|json| serde_json::from_str(&json).ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut message = Message::new(role, created_timestamp, content);
|
||||
message.metadata = metadata;
|
||||
let message = Message::new(role, created_timestamp, content);
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
@@ -816,19 +792,16 @@ impl SessionStorage {
|
||||
}
|
||||
|
||||
async fn add_message(&self, session_id: &str, message: &Message) -> Result<()> {
|
||||
let metadata_json = serde_json::to_string(&message.metadata)?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO messages (session_id, role, content_json, created_timestamp, metadata_json)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO messages (session_id, role, content_json, created_timestamp)
|
||||
VALUES (?, ?, ?, ?)
|
||||
"#,
|
||||
)
|
||||
.bind(session_id)
|
||||
.bind(role_to_string(&message.role))
|
||||
.bind(serde_json::to_string(&message.content)?)
|
||||
.bind(message.created)
|
||||
.bind(metadata_json)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
|
||||
@@ -853,19 +826,16 @@ impl SessionStorage {
|
||||
.await?;
|
||||
|
||||
for message in conversation.messages() {
|
||||
let metadata_json = serde_json::to_string(&message.metadata)?;
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO messages (session_id, role, content_json, created_timestamp, metadata_json)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO messages (session_id, role, content_json, created_timestamp)
|
||||
VALUES (?, ?, ?, ?)
|
||||
"#,
|
||||
)
|
||||
.bind(session_id)
|
||||
.bind(role_to_string(&message.role))
|
||||
.bind(serde_json::to_string(&message.content)?)
|
||||
.bind(message.created)
|
||||
.bind(metadata_json)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user