From 461ef4c43589c6ca68176c180fd04f2755c9f036 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 23 Apr 2026 13:43:01 -0700 Subject: feat: Add skill discovery, loading, and invocation (#3444) Adds a skills system that lets users define reusable LLM instructions as `SKILL.md` files with YAML frontmatter. --- crates/atuin-ai/src/fsm/mod.rs | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'crates/atuin-ai/src/fsm/mod.rs') diff --git a/crates/atuin-ai/src/fsm/mod.rs b/crates/atuin-ai/src/fsm/mod.rs index 25de41f3..3d72a3ae 100644 --- a/crates/atuin-ai/src/fsm/mod.rs +++ b/crates/atuin-ai/src/fsm/mod.rs @@ -309,6 +309,33 @@ impl AgentFsm { vec![] } + ( + AgentState::Idle { .. }, + Event::SkillLoaded { + name, + arguments, + content, + }, + ) => { + self.ctx.events.push(ConversationEvent::SkillInvocation { + name, + arguments, + content, + }); + self.ctx.current_response.clear(); + self.ctx.current_turn_tool_ids.clear(); + + let messages = self.build_messages(); + let session_id = self.ctx.session_id.clone(); + self.state = AgentState::Turn { + stream: StreamPhase::Connecting, + }; + vec![Effect::StartStream { + messages, + session_id, + }] + } + // ================================================================ // Turn — stream lifecycle // ================================================================ @@ -584,6 +611,29 @@ impl AgentFsm { vec![] } + // RequestSkillLoad during non-idle: still emit the effect + (_, Event::RequestSkillLoad { name, arguments }) => { + vec![Effect::LoadSkill { name, arguments }] + } + + // SkillLoaded during non-idle: queue so it's visible + // in context for the next turn. + ( + _, + Event::SkillLoaded { + name, + arguments, + content, + }, + ) => { + self.ctx.events.push(ConversationEvent::SkillInvocation { + name, + arguments, + content, + }); + vec![] + } + _ => vec![], } } -- cgit v1.3.1