Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions crates/goose-server/src/routes/config_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,19 +427,13 @@ pub async fn get_slash_commands(

let working_dir = query.working_dir.map(std::path::PathBuf::from);
for source in
goose::agents::platform_extensions::summon::list_installed_sources(working_dir.as_deref())
goose::agents::platform_extensions::skills::list_installed_skills(working_dir.as_deref())
{
if matches!(
source.kind,
goose::agents::platform_extensions::summon::SourceKind::Skill
| goose::agents::platform_extensions::summon::SourceKind::BuiltinSkill
) {
commands.push(SlashCommand {
command: source.name,
help: source.description,
command_type: CommandType::Skill,
});
}
commands.push(SlashCommand {
command: source.name,
help: source.description,
command_type: CommandType::Skill,
});
}

Ok(Json(SlashCommandsResponse { commands }))
Expand Down
5 changes: 3 additions & 2 deletions crates/goose/src/agents/execute_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ impl Agent {
}

async fn handle_skills_command(&self, session_id: &str) -> Result<Option<Message>> {
use super::platform_extensions::summon::{list_installed_sources, SourceKind};
use super::platform_extensions::skills::list_installed_skills;
use super::platform_extensions::SourceKind;

let working_dir = self
.config
Expand All @@ -149,7 +150,7 @@ impl Agent {
.await
.ok()
.map(|s| s.working_dir);
let sources = list_installed_sources(working_dir.as_deref());
let sources = list_installed_skills(working_dir.as_deref());
let skills: Vec<_> = sources
.iter()
.filter(|s| matches!(s.kind, SourceKind::Skill | SourceKind::BuiltinSkill))
Expand Down
76 changes: 76 additions & 0 deletions crates/goose/src/agents/platform_extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,79 @@ pub mod code_execution;
pub mod developer;
pub mod ext_manager;
pub mod orchestrator;
pub mod skills;
pub mod summarize;
pub mod summon;
pub mod todo;
pub mod tom;

use std::collections::HashMap;
use std::path::PathBuf;

use crate::agents::mcp_client::McpClientTrait;
use crate::session::Session;
use once_cell::sync::Lazy;
use serde::Deserialize;
use tracing::warn;

#[derive(Debug, Clone)]
pub struct Source {
pub name: String,
pub kind: SourceKind,
pub description: String,
pub path: PathBuf,
pub content: String,
pub supporting_files: Vec<PathBuf>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SourceKind {
Subrecipe,
Recipe,
Skill,
Agent,
BuiltinSkill,
}

impl std::fmt::Display for SourceKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SourceKind::Subrecipe => write!(f, "subrecipe"),
SourceKind::Recipe => write!(f, "recipe"),
SourceKind::Skill => write!(f, "skill"),
SourceKind::Agent => write!(f, "agent"),
SourceKind::BuiltinSkill => write!(f, "builtin skill"),
}
}
}

impl Source {
pub fn to_load_text(&self) -> String {
format!(
"## {} ({})\n\n{}\n\n### Content\n\n{}",
self.name, self.kind, self.description, self.content
)
}
}

pub fn parse_frontmatter<T: for<'de> Deserialize<'de>>(content: &str) -> Option<(T, String)> {
let parts: Vec<&str> = content.split("---").collect();
if parts.len() < 3 {
return None;
}

let yaml_content = parts[1].trim();
let metadata: T = match serde_yaml::from_str(yaml_content) {
Ok(m) => m,
Err(e) => {
warn!("Failed to parse frontmatter: {}", e);
return None;
}
};

let body = parts[2..].join("---").trim().to_string();
Some((metadata, body))
}

pub use ext_manager::MANAGE_EXTENSIONS_TOOL_NAME_COMPLETE;

Expand Down Expand Up @@ -189,6 +252,19 @@ pub static PLATFORM_EXTENSIONS: Lazy<HashMap<&'static str, PlatformExtensionDef>
},
);

map.insert(
skills::EXTENSION_NAME,
PlatformExtensionDef {
name: skills::EXTENSION_NAME,
display_name: "Skills",
description: "Discover and provide skill instructions from filesystem and builtins",
default_enabled: true,
unprefixed_tools: true,
hidden: false,
client_factory: |ctx| Box::new(skills::SkillsClient::new(ctx).unwrap()),
},
);

map
},
);
Expand Down
Loading
Loading