Class: Xeno::AgentDefinition
- Inherits:
-
Object
- Object
- Xeno::AgentDefinition
- Defined in:
- lib/xeno/agent_definition.rb
Overview
The resolved agent: everything discovered under the app's agent/ directory, plus diagnostics for
anything misplaced or broken. Discovery never raises — a broken agent directory yields a
definition whose diagnostics say exactly what is wrong (surfaced by rake xeno:info).
Defined Under Namespace
Classes: Diagnostic, InstructionContext, Schedule
Constant Summary collapse
- SLOT_DIRS =
%w[tools skills channels schedules hooks lib].freeze
- TOOL_SLUG =
/\A[a-z][a-z0-9_]*\z/
Instance Attribute Summary collapse
-
#channels ⇒ Object
readonly
Returns the value of attribute channels.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#diagnostics ⇒ Object
readonly
Returns the value of attribute diagnostics.
-
#dynamic_instructions ⇒ Object
readonly
Returns the value of attribute dynamic_instructions.
-
#hooks ⇒ Object
readonly
Returns the value of attribute hooks.
-
#instructions ⇒ Object
readonly
Returns the value of attribute instructions.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#schedules ⇒ Object
readonly
Returns the value of attribute schedules.
-
#tools ⇒ Object
readonly
Returns the value of attribute tools.
Class Method Summary collapse
-
.load(root, name:, resolver: nil) ⇒ Object
Builds the definition for the app's agent root.
Instance Method Summary collapse
- #discover ⇒ Object
- #dynamic_instructions? ⇒ Boolean
- #errors? ⇒ Boolean
-
#initialize(root:, name:, resolver: nil) ⇒ AgentDefinition
constructor
A new instance of AgentDefinition.
-
#instructions_for(session: nil) ⇒ Object
The system prompt for one turn: static markdown first, then the dynamic block's return, resolved fresh at every turn stage with the session context.
- #tool_classes ⇒ Object
Constructor Details
#initialize(root:, name:, resolver: nil) ⇒ AgentDefinition
Returns a new instance of AgentDefinition.
30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/xeno/agent_definition.rb', line 30 def initialize(root:, name:, resolver: nil) @root = Pathname(root) @name = name @resolver = resolver || method(:resolve_tool_constant) @config = AgentConfig.new @instructions = nil @dynamic_instructions = nil @tools = {} @schedules = {} @channels = {} @hooks = {} @diagnostics = [] end |
Instance Attribute Details
#channels ⇒ Object (readonly)
Returns the value of attribute channels.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def channels @channels end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def config @config end |
#diagnostics ⇒ Object (readonly)
Returns the value of attribute diagnostics.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def diagnostics @diagnostics end |
#dynamic_instructions ⇒ Object (readonly)
Returns the value of attribute dynamic_instructions.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def dynamic_instructions @dynamic_instructions end |
#hooks ⇒ Object (readonly)
Returns the value of attribute hooks.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def hooks @hooks end |
#instructions ⇒ Object (readonly)
Returns the value of attribute instructions.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def instructions @instructions end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def name @name end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def root @root end |
#schedules ⇒ Object (readonly)
Returns the value of attribute schedules.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def schedules @schedules end |
#tools ⇒ Object (readonly)
Returns the value of attribute tools.
20 21 22 |
# File 'lib/xeno/agent_definition.rb', line 20 def tools @tools end |
Class Method Details
.load(root, name:, resolver: nil) ⇒ Object
Builds the definition for the app's agent root. resolver maps a tool file's camelized
basename to its constant; the default asks Zeitwerk (via const_get on Xeno::Tools) and is only
overridden in tests.
26 27 28 |
# File 'lib/xeno/agent_definition.rb', line 26 def self.load(root, name:, resolver: nil) new(root: root, name: name, resolver: resolver).tap(&:discover) end |
Instance Method Details
#discover ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/xeno/agent_definition.rb', line 44 def discover unless root.directory? error "no agent/ directory at #{root} — run `rails g xeno:install`" return self end load_agent_config load_instructions discover_tools discover_schedules discover_channels discover_hooks report_misplaced_files self end |
#dynamic_instructions? ⇒ Boolean
64 |
# File 'lib/xeno/agent_definition.rb', line 64 def dynamic_instructions? = !@dynamic_instructions.nil? |
#errors? ⇒ Boolean
85 |
# File 'lib/xeno/agent_definition.rb', line 85 def errors? = diagnostics.any?(&:error?) |
#instructions_for(session: nil) ⇒ Object
The system prompt for one turn: static markdown first, then the dynamic block's return, resolved fresh at every turn stage with the session context. A raising block never bricks the session — the turn proceeds on the static instructions and the failure is logged.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/xeno/agent_definition.rb', line 69 def instructions_for(session: nil) parts = [ instructions ] if @dynamic_instructions context = InstructionContext.new(session: session, principal: session&.principal) begin parts << @dynamic_instructions.call(context).to_s rescue StandardError => e Rails.logger.warn( "xeno: agent/instructions.rb raised #{e.class}: #{e.} — using static instructions only" ) end end combined = parts.compact.map(&:strip).reject(&:empty?).join("\n\n") combined.empty? ? nil : combined end |
#tool_classes ⇒ Object
60 61 62 |
# File 'lib/xeno/agent_definition.rb', line 60 def tool_classes tools.values end |