Slash commands (#5718)

Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
Douwe Osinga
2025-11-20 21:14:15 +01:00
committed by GitHub
parent 6e511d1e8a
commit bdf68bb4f5
28 changed files with 1675 additions and 1048 deletions
+31 -10
View File
@@ -59,14 +59,15 @@ use super::final_output_tool::FinalOutputTool;
use super::platform_tools;
use super::tool_execution::{ToolCallResult, CHAT_MODE_TOOL_SKIPPED_RESPONSE, DECLINED_RESPONSE};
use crate::agents::subagent_task_config::TaskConfig;
use crate::conversation::message::{Message, MessageContent, SystemNotificationType, ToolRequest};
use crate::conversation::message::{Message, SystemNotificationType, ToolRequest};
use crate::scheduler_trait::SchedulerTrait;
use crate::session::extension_data::{EnabledExtensionsState, ExtensionState};
use crate::session::{Session, SessionManager};
const DEFAULT_MAX_TURNS: u32 = 1000;
const COMPACTION_THINKING_TEXT: &str = "goose is compacting the conversation...";
pub const MANUAL_COMPACT_TRIGGER: &str = "Please compact this conversation";
pub const MANUAL_COMPACT_TRIGGERS: &[&str] =
&["Please compact this conversation", "/compact", "/summarize"];
/// Context needed for the reply function
pub struct ReplyContext {
@@ -776,15 +777,35 @@ impl Agent {
session_config: SessionConfig,
cancel_token: Option<CancellationToken>,
) -> Result<BoxStream<'_, Result<AgentEvent>>> {
let is_manual_compact = user_message.content.iter().any(|c| {
if let MessageContent::Text(text) = c {
text.text.trim() == MANUAL_COMPACT_TRIGGER
} else {
false
}
});
let message_text = user_message.as_concat_text();
let is_manual_compact = MANUAL_COMPACT_TRIGGERS.contains(&message_text.trim());
let slash_command_recipe = if message_text.trim().starts_with('/') {
let command = message_text.split_whitespace().next();
command.and_then(crate::slash_commands::resolve_slash_command)
} else {
None
};
if let Some(recipe) = slash_command_recipe {
let prompt = [recipe.instructions.as_deref(), recipe.prompt.as_deref()]
.into_iter()
.flatten()
.collect::<Vec<_>>()
.join("\n\n");
let prompt_message = Message::user()
.with_text(prompt)
.with_visibility(false, true);
SessionManager::add_message(&session_config.id, &prompt_message).await?;
SessionManager::add_message(
&session_config.id,
&user_message.with_visibility(true, false),
)
.await?;
} else {
SessionManager::add_message(&session_config.id, &user_message).await?;
}
SessionManager::add_message(&session_config.id, &user_message).await?;
let session = SessionManager::get_session(&session_config.id, true).await?;
let conversation = session
+1 -1
View File
@@ -26,7 +26,7 @@ mod tool_route_manager;
mod tool_router_index_manager;
pub mod types;
pub use agent::{Agent, AgentEvent, MANUAL_COMPACT_TRIGGER};
pub use agent::{Agent, AgentEvent, MANUAL_COMPACT_TRIGGERS};
pub use extension::ExtensionConfig;
pub use extension_manager::ExtensionManager;
pub use prompt_manager::PromptManager;
+2 -2
View File
@@ -164,7 +164,7 @@ impl Agent {
process_start_time: None,
};
match scheduler.add_scheduled_job(job).await {
match scheduler.add_scheduled_job(job, true).await {
Ok(()) => Ok(vec![Content::text(format!(
"Successfully created scheduled job '{}' for recipe '{}' with cron expression '{}' in {} mode",
job_id, recipe_path, cron_expression, execution_mode
@@ -284,7 +284,7 @@ impl Agent {
)
})?;
match scheduler.remove_scheduled_job(job_id).await {
match scheduler.remove_scheduled_job(job_id, true).await {
Ok(()) => Ok(vec![Content::text(format!(
"Successfully deleted job '{}'",
job_id