language-operator 0.0.1 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +125 -0
- data/CHANGELOG.md +88 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +284 -0
- data/LICENSE +229 -21
- data/Makefile +82 -0
- data/README.md +3 -11
- data/Rakefile +63 -0
- data/bin/aictl +7 -0
- data/completions/_aictl +232 -0
- data/completions/aictl.bash +121 -0
- data/completions/aictl.fish +114 -0
- data/docs/architecture/agent-runtime.md +585 -0
- data/docs/dsl/SCHEMA_VERSION.md +250 -0
- data/docs/dsl/agent-reference.md +604 -0
- data/docs/dsl/best-practices.md +1078 -0
- data/docs/dsl/chat-endpoints.md +895 -0
- data/docs/dsl/constraints.md +671 -0
- data/docs/dsl/mcp-integration.md +1177 -0
- data/docs/dsl/webhooks.md +932 -0
- data/docs/dsl/workflows.md +744 -0
- data/lib/language_operator/agent/base.rb +110 -0
- data/lib/language_operator/agent/executor.rb +440 -0
- data/lib/language_operator/agent/instrumentation.rb +54 -0
- data/lib/language_operator/agent/metrics_tracker.rb +183 -0
- data/lib/language_operator/agent/safety/ast_validator.rb +272 -0
- data/lib/language_operator/agent/safety/audit_logger.rb +104 -0
- data/lib/language_operator/agent/safety/budget_tracker.rb +175 -0
- data/lib/language_operator/agent/safety/content_filter.rb +93 -0
- data/lib/language_operator/agent/safety/manager.rb +207 -0
- data/lib/language_operator/agent/safety/rate_limiter.rb +150 -0
- data/lib/language_operator/agent/safety/safe_executor.rb +127 -0
- data/lib/language_operator/agent/scheduler.rb +183 -0
- data/lib/language_operator/agent/telemetry.rb +116 -0
- data/lib/language_operator/agent/web_server.rb +610 -0
- data/lib/language_operator/agent/webhook_authenticator.rb +226 -0
- data/lib/language_operator/agent.rb +149 -0
- data/lib/language_operator/cli/commands/agent.rb +1205 -0
- data/lib/language_operator/cli/commands/cluster.rb +371 -0
- data/lib/language_operator/cli/commands/install.rb +404 -0
- data/lib/language_operator/cli/commands/model.rb +266 -0
- data/lib/language_operator/cli/commands/persona.rb +393 -0
- data/lib/language_operator/cli/commands/quickstart.rb +22 -0
- data/lib/language_operator/cli/commands/status.rb +143 -0
- data/lib/language_operator/cli/commands/system.rb +772 -0
- data/lib/language_operator/cli/commands/tool.rb +537 -0
- data/lib/language_operator/cli/commands/use.rb +47 -0
- data/lib/language_operator/cli/errors/handler.rb +180 -0
- data/lib/language_operator/cli/errors/suggestions.rb +176 -0
- data/lib/language_operator/cli/formatters/code_formatter.rb +77 -0
- data/lib/language_operator/cli/formatters/log_formatter.rb +288 -0
- data/lib/language_operator/cli/formatters/progress_formatter.rb +49 -0
- data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
- data/lib/language_operator/cli/formatters/table_formatter.rb +163 -0
- data/lib/language_operator/cli/formatters/value_formatter.rb +113 -0
- data/lib/language_operator/cli/helpers/cluster_context.rb +62 -0
- data/lib/language_operator/cli/helpers/cluster_validator.rb +101 -0
- data/lib/language_operator/cli/helpers/editor_helper.rb +58 -0
- data/lib/language_operator/cli/helpers/kubeconfig_validator.rb +167 -0
- data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
- data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +74 -0
- data/lib/language_operator/cli/helpers/schedule_builder.rb +108 -0
- data/lib/language_operator/cli/helpers/user_prompts.rb +69 -0
- data/lib/language_operator/cli/main.rb +236 -0
- data/lib/language_operator/cli/templates/tools/generic.yaml +66 -0
- data/lib/language_operator/cli/wizards/agent_wizard.rb +246 -0
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +588 -0
- data/lib/language_operator/client/base.rb +214 -0
- data/lib/language_operator/client/config.rb +136 -0
- data/lib/language_operator/client/cost_calculator.rb +37 -0
- data/lib/language_operator/client/mcp_connector.rb +123 -0
- data/lib/language_operator/client.rb +19 -0
- data/lib/language_operator/config/cluster_config.rb +101 -0
- data/lib/language_operator/config/tool_patterns.yaml +57 -0
- data/lib/language_operator/config/tool_registry.rb +96 -0
- data/lib/language_operator/config.rb +138 -0
- data/lib/language_operator/dsl/adapter.rb +124 -0
- data/lib/language_operator/dsl/agent_context.rb +90 -0
- data/lib/language_operator/dsl/agent_definition.rb +427 -0
- data/lib/language_operator/dsl/chat_endpoint_definition.rb +115 -0
- data/lib/language_operator/dsl/config.rb +119 -0
- data/lib/language_operator/dsl/context.rb +50 -0
- data/lib/language_operator/dsl/execution_context.rb +47 -0
- data/lib/language_operator/dsl/helpers.rb +109 -0
- data/lib/language_operator/dsl/http.rb +184 -0
- data/lib/language_operator/dsl/mcp_server_definition.rb +73 -0
- data/lib/language_operator/dsl/parameter_definition.rb +124 -0
- data/lib/language_operator/dsl/registry.rb +36 -0
- data/lib/language_operator/dsl/schema.rb +1102 -0
- data/lib/language_operator/dsl/shell.rb +125 -0
- data/lib/language_operator/dsl/tool_definition.rb +112 -0
- data/lib/language_operator/dsl/webhook_authentication.rb +114 -0
- data/lib/language_operator/dsl/webhook_definition.rb +106 -0
- data/lib/language_operator/dsl/workflow_definition.rb +259 -0
- data/lib/language_operator/dsl.rb +161 -0
- data/lib/language_operator/errors.rb +60 -0
- data/lib/language_operator/kubernetes/client.rb +279 -0
- data/lib/language_operator/kubernetes/resource_builder.rb +194 -0
- data/lib/language_operator/loggable.rb +47 -0
- data/lib/language_operator/logger.rb +141 -0
- data/lib/language_operator/retry.rb +123 -0
- data/lib/language_operator/retryable.rb +132 -0
- data/lib/language_operator/templates/README.md +23 -0
- data/lib/language_operator/templates/examples/agent_synthesis.tmpl +115 -0
- data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
- data/lib/language_operator/templates/schema/.gitkeep +0 -0
- data/lib/language_operator/templates/schema/CHANGELOG.md +93 -0
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +452 -0
- data/lib/language_operator/tool_loader.rb +242 -0
- data/lib/language_operator/validators.rb +170 -0
- data/lib/language_operator/version.rb +1 -1
- data/lib/language_operator.rb +65 -3
- data/requirements/tasks/challenge.md +9 -0
- data/requirements/tasks/iterate.md +36 -0
- data/requirements/tasks/optimize.md +21 -0
- data/requirements/tasks/tag.md +5 -0
- data/test_agent_dsl.rb +108 -0
- metadata +507 -20
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../logger'
|
|
4
|
+
require_relative '../loggable'
|
|
5
|
+
|
|
6
|
+
module LanguageOperator
|
|
7
|
+
module Dsl
|
|
8
|
+
# Workflow definition for agent execution
|
|
9
|
+
#
|
|
10
|
+
# Defines a series of steps that an agent executes to achieve objectives.
|
|
11
|
+
# Steps can depend on other steps, call tools, or perform LLM processing.
|
|
12
|
+
#
|
|
13
|
+
# @example Define a workflow
|
|
14
|
+
# workflow do
|
|
15
|
+
# step :search do
|
|
16
|
+
# tool "web_search"
|
|
17
|
+
# params query: "latest news"
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# step :summarize do
|
|
21
|
+
# depends_on :search
|
|
22
|
+
# prompt "Summarize: {search.output}"
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
class WorkflowDefinition
|
|
26
|
+
include LanguageOperator::Loggable
|
|
27
|
+
|
|
28
|
+
attr_reader :steps, :step_order
|
|
29
|
+
|
|
30
|
+
def initialize
|
|
31
|
+
@steps = {}
|
|
32
|
+
@step_order = []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Define a workflow step
|
|
36
|
+
#
|
|
37
|
+
# @param name [Symbol] Step name
|
|
38
|
+
# @param tool [String, nil] Tool to use (optional)
|
|
39
|
+
# @param params [Hash] Tool parameters (optional)
|
|
40
|
+
# @param depends_on [Symbol, Array<Symbol>] Dependencies (optional)
|
|
41
|
+
# @yield Step definition block
|
|
42
|
+
# @return [void]
|
|
43
|
+
def step(name, tool: nil, params: {}, depends_on: nil, &block)
|
|
44
|
+
step_def = StepDefinition.new(name, logger: @logger)
|
|
45
|
+
|
|
46
|
+
if tool
|
|
47
|
+
step_def.tool(tool)
|
|
48
|
+
step_def.params(params) unless params.empty?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
step_def.depends_on(depends_on) if depends_on
|
|
52
|
+
|
|
53
|
+
step_def.instance_eval(&block) if block
|
|
54
|
+
@steps[name] = step_def
|
|
55
|
+
@step_order << name
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Execute the workflow
|
|
59
|
+
#
|
|
60
|
+
# @param context [Object] Execution context
|
|
61
|
+
# @return [Hash] Results from each step
|
|
62
|
+
def execute(context = nil)
|
|
63
|
+
results = {}
|
|
64
|
+
|
|
65
|
+
logger.info('Executing workflow', step_count: @steps.size)
|
|
66
|
+
|
|
67
|
+
@step_order.each do |step_name|
|
|
68
|
+
step_def = @steps[step_name]
|
|
69
|
+
|
|
70
|
+
# Check dependencies
|
|
71
|
+
if step_def.dependencies.any?
|
|
72
|
+
logger.debug('Checking dependencies',
|
|
73
|
+
step: step_name,
|
|
74
|
+
dependencies: step_def.dependencies)
|
|
75
|
+
step_def.dependencies.each do |dep|
|
|
76
|
+
next if results.key?(dep)
|
|
77
|
+
|
|
78
|
+
logger.error('Dependency not satisfied',
|
|
79
|
+
step: step_name,
|
|
80
|
+
missing_dependency: dep)
|
|
81
|
+
raise "Step #{step_name} depends on #{dep}, but #{dep} has not been executed"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Execute step
|
|
86
|
+
logger.info('Executing step',
|
|
87
|
+
step: step_name,
|
|
88
|
+
tool: step_def.tool_name,
|
|
89
|
+
has_prompt: !step_def.prompt_template.nil?)
|
|
90
|
+
|
|
91
|
+
result = logger.timed('Step execution') do
|
|
92
|
+
step_def.execute(results, context)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
results[step_name] = result
|
|
96
|
+
logger.info('Step completed', step: step_name)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
logger.info('Workflow execution completed', total_steps: @steps.size)
|
|
100
|
+
results
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def logger_component
|
|
106
|
+
'Workflow'
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Individual step definition
|
|
111
|
+
class StepDefinition
|
|
112
|
+
include LanguageOperator::Loggable
|
|
113
|
+
|
|
114
|
+
attr_reader :name, :dependencies, :tool_name, :tool_params, :prompt_template
|
|
115
|
+
|
|
116
|
+
def initialize(name, logger: nil)
|
|
117
|
+
@name = name
|
|
118
|
+
@tool_name = nil
|
|
119
|
+
@tool_params = {}
|
|
120
|
+
@prompt_template = nil
|
|
121
|
+
@dependencies = []
|
|
122
|
+
@execute_block = nil
|
|
123
|
+
@parent_logger = logger
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Set the tool to use
|
|
127
|
+
#
|
|
128
|
+
# @param name [String] Tool name
|
|
129
|
+
# @return [void]
|
|
130
|
+
def tool(name = nil)
|
|
131
|
+
return @tool_name if name.nil?
|
|
132
|
+
|
|
133
|
+
@tool_name = name
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Set tool parameters
|
|
137
|
+
#
|
|
138
|
+
# @param hash [Hash] Parameters
|
|
139
|
+
# @return [Hash] Current parameters
|
|
140
|
+
def params(hash = nil)
|
|
141
|
+
return @tool_params if hash.nil?
|
|
142
|
+
|
|
143
|
+
@tool_params = hash
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Set prompt template (for LLM processing)
|
|
147
|
+
#
|
|
148
|
+
# @param template [String] Prompt template
|
|
149
|
+
# @return [String] Current prompt
|
|
150
|
+
def prompt(template = nil)
|
|
151
|
+
return @prompt_template if template.nil?
|
|
152
|
+
|
|
153
|
+
@prompt_template = template
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Declare dependencies on other steps
|
|
157
|
+
#
|
|
158
|
+
# @param steps [Symbol, Array<Symbol>] Step names this depends on
|
|
159
|
+
# @return [Array<Symbol>] Current dependencies
|
|
160
|
+
def depends_on(*steps)
|
|
161
|
+
return @dependencies if steps.empty?
|
|
162
|
+
|
|
163
|
+
@dependencies = steps.flatten
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Define custom execution logic
|
|
167
|
+
#
|
|
168
|
+
# @yield Execution block
|
|
169
|
+
# @return [void]
|
|
170
|
+
def execute(&block)
|
|
171
|
+
@execute_block = block if block
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Execute this step
|
|
175
|
+
#
|
|
176
|
+
# @param results [Hash] Results from previous steps
|
|
177
|
+
# @param context [Object] Execution context
|
|
178
|
+
# @return [Object] Step result
|
|
179
|
+
def execute_step(results, context)
|
|
180
|
+
if @execute_block
|
|
181
|
+
# Custom execution logic
|
|
182
|
+
logger.debug('Executing custom logic', step: @name)
|
|
183
|
+
@execute_block.call(results, context)
|
|
184
|
+
elsif @tool_name
|
|
185
|
+
# Tool execution
|
|
186
|
+
params = interpolate_params(@tool_params, results)
|
|
187
|
+
logger.info('Calling tool',
|
|
188
|
+
step: @name,
|
|
189
|
+
tool: @tool_name,
|
|
190
|
+
params: params)
|
|
191
|
+
# In real implementation, this would call the actual tool
|
|
192
|
+
"Tool #{@tool_name} executed with #{params.inspect}"
|
|
193
|
+
elsif @prompt_template
|
|
194
|
+
# LLM processing
|
|
195
|
+
prompt = interpolate_template(@prompt_template, results)
|
|
196
|
+
logger.debug('LLM prompt',
|
|
197
|
+
step: @name,
|
|
198
|
+
prompt: prompt[0..200])
|
|
199
|
+
# In real implementation, this would call the LLM
|
|
200
|
+
"LLM processed: #{prompt}"
|
|
201
|
+
else
|
|
202
|
+
# No-op step
|
|
203
|
+
logger.debug('No execution logic defined', step: @name)
|
|
204
|
+
nil
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
alias execute execute_step
|
|
209
|
+
|
|
210
|
+
private
|
|
211
|
+
|
|
212
|
+
def logger
|
|
213
|
+
@parent_logger || super
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def logger_component
|
|
217
|
+
"Step:#{@name}"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Interpolate parameters with results from previous steps
|
|
221
|
+
#
|
|
222
|
+
# @param params [Hash] Parameter template
|
|
223
|
+
# @param results [Hash] Previous results
|
|
224
|
+
# @return [Hash] Interpolated parameters
|
|
225
|
+
def interpolate_params(params, results)
|
|
226
|
+
params.transform_values do |value|
|
|
227
|
+
if value.is_a?(String) && value.match?(/\{(\w+)\.(\w+)\}/)
|
|
228
|
+
# Replace {step.field} with actual value
|
|
229
|
+
value.gsub(/\{(\w+)\.(\w+)\}/) do
|
|
230
|
+
step_name = Regexp.last_match(1).to_sym
|
|
231
|
+
field = Regexp.last_match(2)
|
|
232
|
+
results.dig(step_name, field) || value
|
|
233
|
+
end
|
|
234
|
+
else
|
|
235
|
+
value
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Interpolate template string with results
|
|
241
|
+
#
|
|
242
|
+
# @param template [String] Template string
|
|
243
|
+
# @param results [Hash] Previous results
|
|
244
|
+
# @return [String] Interpolated string
|
|
245
|
+
def interpolate_template(template, results)
|
|
246
|
+
template.gsub(/\{(\w+)(?:\.(\w+))?\}/) do
|
|
247
|
+
step_name = Regexp.last_match(1).to_sym
|
|
248
|
+
field = Regexp.last_match(2)
|
|
249
|
+
|
|
250
|
+
if field
|
|
251
|
+
results.dig(step_name, field)&.to_s || "{#{step_name}.#{field}}"
|
|
252
|
+
else
|
|
253
|
+
results[step_name]&.to_s || "{#{step_name}}"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'version'
|
|
4
|
+
require_relative 'dsl/tool_definition'
|
|
5
|
+
require_relative 'dsl/parameter_definition'
|
|
6
|
+
require_relative 'dsl/registry'
|
|
7
|
+
require_relative 'dsl/adapter'
|
|
8
|
+
require_relative 'dsl/config'
|
|
9
|
+
require_relative 'dsl/helpers'
|
|
10
|
+
require_relative 'dsl/http'
|
|
11
|
+
require_relative 'dsl/shell'
|
|
12
|
+
require_relative 'dsl/context'
|
|
13
|
+
require_relative 'dsl/execution_context'
|
|
14
|
+
require_relative 'dsl/agent_definition'
|
|
15
|
+
require_relative 'dsl/agent_context'
|
|
16
|
+
require_relative 'dsl/workflow_definition'
|
|
17
|
+
require_relative 'dsl/schema'
|
|
18
|
+
require_relative 'agent/safety/ast_validator'
|
|
19
|
+
require_relative 'agent/safety/safe_executor'
|
|
20
|
+
|
|
21
|
+
module LanguageOperator
|
|
22
|
+
# DSL for defining MCP tools and autonomous agents
|
|
23
|
+
#
|
|
24
|
+
# Provides a clean, Ruby-like DSL for defining tools that can be served
|
|
25
|
+
# via the Model Context Protocol (MCP) and agents that can execute autonomously.
|
|
26
|
+
#
|
|
27
|
+
# @example Define a tool
|
|
28
|
+
# LanguageOperator::Dsl.define do
|
|
29
|
+
# tool "greet" do
|
|
30
|
+
# description "Greet a user by name"
|
|
31
|
+
#
|
|
32
|
+
# parameter :name do
|
|
33
|
+
# type :string
|
|
34
|
+
# required true
|
|
35
|
+
# description "Name to greet"
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# execute do |params|
|
|
39
|
+
# "Hello, #{params['name']}!"
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# @example Access tools
|
|
45
|
+
# registry = LanguageOperator::Dsl.registry
|
|
46
|
+
# tool = registry.get("greet")
|
|
47
|
+
# result = tool.call({"name" => "Alice"})
|
|
48
|
+
module Dsl
|
|
49
|
+
class << self
|
|
50
|
+
# Global registry for tools
|
|
51
|
+
#
|
|
52
|
+
# @return [Registry] The global tool registry
|
|
53
|
+
def registry
|
|
54
|
+
@registry ||= Registry.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Global registry for agents
|
|
58
|
+
#
|
|
59
|
+
# @return [AgentRegistry] The global agent registry
|
|
60
|
+
def agent_registry
|
|
61
|
+
@agent_registry ||= AgentRegistry.new
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Define tools using the DSL
|
|
65
|
+
#
|
|
66
|
+
# @yield Block containing tool definitions
|
|
67
|
+
# @return [Registry] The global registry with defined tools
|
|
68
|
+
#
|
|
69
|
+
# @example
|
|
70
|
+
# LanguageOperator::Dsl.define do
|
|
71
|
+
# tool "example" do
|
|
72
|
+
# # ...
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
def define(&)
|
|
76
|
+
context = Context.new(registry)
|
|
77
|
+
context.instance_eval(&)
|
|
78
|
+
registry
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Define agents using the DSL
|
|
82
|
+
#
|
|
83
|
+
# @yield Block containing agent definitions
|
|
84
|
+
# @return [AgentRegistry] The global agent registry
|
|
85
|
+
#
|
|
86
|
+
# @example
|
|
87
|
+
# LanguageOperator::Dsl.define_agents do
|
|
88
|
+
# agent "news-summarizer" do
|
|
89
|
+
# # ...
|
|
90
|
+
# end
|
|
91
|
+
# end
|
|
92
|
+
def define_agents(&)
|
|
93
|
+
context = AgentContext.new(agent_registry)
|
|
94
|
+
context.instance_eval(&)
|
|
95
|
+
agent_registry
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Load tools from a file
|
|
99
|
+
#
|
|
100
|
+
# @param file_path [String] Path to the tool definition file
|
|
101
|
+
# @return [Registry] The global registry with loaded tools
|
|
102
|
+
#
|
|
103
|
+
# @example
|
|
104
|
+
# LanguageOperator::Dsl.load_file("mcp/tools.rb")
|
|
105
|
+
def load_file(file_path)
|
|
106
|
+
code = File.read(file_path)
|
|
107
|
+
context = Context.new(registry)
|
|
108
|
+
|
|
109
|
+
# Execute in sandbox with validation
|
|
110
|
+
executor = Agent::Safety::SafeExecutor.new(context)
|
|
111
|
+
executor.eval(code, file_path)
|
|
112
|
+
|
|
113
|
+
registry
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Load agents from a file
|
|
117
|
+
#
|
|
118
|
+
# @param file_path [String] Path to the agent definition file
|
|
119
|
+
# @return [AgentRegistry] The global agent registry
|
|
120
|
+
#
|
|
121
|
+
# @example
|
|
122
|
+
# LanguageOperator::Dsl.load_agent_file("agents/news-summarizer.rb")
|
|
123
|
+
def load_agent_file(file_path)
|
|
124
|
+
code = File.read(file_path)
|
|
125
|
+
context = AgentContext.new(agent_registry)
|
|
126
|
+
|
|
127
|
+
# Execute in sandbox with validation
|
|
128
|
+
executor = Agent::Safety::SafeExecutor.new(context)
|
|
129
|
+
executor.eval(code, file_path)
|
|
130
|
+
|
|
131
|
+
agent_registry
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Clear all defined tools
|
|
135
|
+
#
|
|
136
|
+
# @return [void]
|
|
137
|
+
def clear!
|
|
138
|
+
registry.clear
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Clear all defined agents
|
|
142
|
+
#
|
|
143
|
+
# @return [void]
|
|
144
|
+
def clear_agents!
|
|
145
|
+
agent_registry.clear
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Create an MCP server from the defined tools
|
|
149
|
+
#
|
|
150
|
+
# @param server_name [String] Name of the MCP server
|
|
151
|
+
# @param server_context [Hash] Additional context for the server
|
|
152
|
+
# @return [MCP::Server] The MCP server instance
|
|
153
|
+
#
|
|
154
|
+
# @example
|
|
155
|
+
# server = LanguageOperator::Dsl.create_server(server_name: "my-tools")
|
|
156
|
+
def create_server(server_name: 'langop-tools', server_context: {})
|
|
157
|
+
Adapter.create_mcp_server(registry, server_name: server_name, server_context: server_context)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LanguageOperator
|
|
4
|
+
# Standardized error formatting module for consistent error messages across tools
|
|
5
|
+
module Errors
|
|
6
|
+
# Resource not found error
|
|
7
|
+
# @param resource_type [String] Type of resource (e.g., "Pod", "LanguageAgent")
|
|
8
|
+
# @param identifier [String] Resource identifier (name, ID, etc.)
|
|
9
|
+
# @return [String] Formatted error message
|
|
10
|
+
def self.not_found(resource_type, identifier)
|
|
11
|
+
"Error: #{resource_type} not found - #{identifier}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Access denied error
|
|
15
|
+
# @param context [String] Additional context (default: "check RBAC permissions")
|
|
16
|
+
# @return [String] Formatted error message
|
|
17
|
+
def self.access_denied(context = 'check RBAC permissions')
|
|
18
|
+
"Error: Access denied - #{context}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Invalid JSON parameter error
|
|
22
|
+
# @param param_name [String] Name of the parameter
|
|
23
|
+
# @return [String] Formatted error message
|
|
24
|
+
def self.invalid_json(param_name)
|
|
25
|
+
"Error: Invalid JSON in #{param_name} parameter"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Missing configuration error
|
|
29
|
+
# @param missing_vars [String, Array<String>] Missing variable(s)
|
|
30
|
+
# @return [String] Formatted error message
|
|
31
|
+
def self.missing_config(missing_vars)
|
|
32
|
+
vars = Array(missing_vars).join(', ')
|
|
33
|
+
"Error: Missing configuration: #{vars}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Invalid parameter value error
|
|
37
|
+
# @param param_name [String] Parameter name
|
|
38
|
+
# @param value [String] Invalid value
|
|
39
|
+
# @param expected [String] Expected format/value
|
|
40
|
+
# @return [String] Formatted error message
|
|
41
|
+
def self.invalid_parameter(param_name, value, expected)
|
|
42
|
+
"Error: Invalid #{param_name} '#{value}'. Expected: #{expected}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Generic operation failed error
|
|
46
|
+
# @param operation [String] Operation that failed
|
|
47
|
+
# @param reason [String] Reason for failure
|
|
48
|
+
# @return [String] Formatted error message
|
|
49
|
+
def self.operation_failed(operation, reason)
|
|
50
|
+
"Error: #{operation} failed - #{reason}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Empty/missing required field error
|
|
54
|
+
# @param field_name [String] Name of the field
|
|
55
|
+
# @return [String] Formatted error message
|
|
56
|
+
def self.empty_field(field_name)
|
|
57
|
+
"Error: #{field_name} cannot be empty"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|