language-operator 0.1.30 → 0.1.35

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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -8
  3. data/CHANGELOG.md +49 -0
  4. data/CI_STATUS.md +56 -0
  5. data/Gemfile.lock +2 -2
  6. data/Makefile +28 -7
  7. data/Rakefile +29 -0
  8. data/docs/dsl/SCHEMA_VERSION.md +250 -0
  9. data/docs/dsl/agent-reference.md +13 -0
  10. data/lib/language_operator/agent/base.rb +10 -6
  11. data/lib/language_operator/agent/executor.rb +19 -97
  12. data/lib/language_operator/agent/safety/ast_validator.rb +62 -43
  13. data/lib/language_operator/agent/safety/safe_executor.rb +39 -2
  14. data/lib/language_operator/agent/scheduler.rb +60 -0
  15. data/lib/language_operator/agent/task_executor.rb +548 -0
  16. data/lib/language_operator/agent.rb +90 -27
  17. data/lib/language_operator/cli/base_command.rb +117 -0
  18. data/lib/language_operator/cli/commands/agent.rb +351 -466
  19. data/lib/language_operator/cli/commands/cluster.rb +276 -256
  20. data/lib/language_operator/cli/commands/install.rb +110 -119
  21. data/lib/language_operator/cli/commands/model.rb +284 -184
  22. data/lib/language_operator/cli/commands/persona.rb +220 -289
  23. data/lib/language_operator/cli/commands/quickstart.rb +4 -5
  24. data/lib/language_operator/cli/commands/status.rb +36 -53
  25. data/lib/language_operator/cli/commands/system.rb +760 -0
  26. data/lib/language_operator/cli/commands/tool.rb +356 -422
  27. data/lib/language_operator/cli/commands/use.rb +19 -22
  28. data/lib/language_operator/cli/formatters/code_formatter.rb +3 -7
  29. data/lib/language_operator/cli/formatters/log_formatter.rb +3 -5
  30. data/lib/language_operator/cli/formatters/progress_formatter.rb +3 -7
  31. data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
  32. data/lib/language_operator/cli/formatters/table_formatter.rb +10 -26
  33. data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
  34. data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +0 -18
  35. data/lib/language_operator/cli/main.rb +4 -0
  36. data/lib/language_operator/cli/wizards/quickstart_wizard.rb +0 -1
  37. data/lib/language_operator/client/config.rb +20 -21
  38. data/lib/language_operator/config.rb +115 -3
  39. data/lib/language_operator/constants.rb +54 -0
  40. data/lib/language_operator/dsl/agent_context.rb +7 -7
  41. data/lib/language_operator/dsl/agent_definition.rb +111 -26
  42. data/lib/language_operator/dsl/config.rb +30 -66
  43. data/lib/language_operator/dsl/main_definition.rb +114 -0
  44. data/lib/language_operator/dsl/schema.rb +1143 -0
  45. data/lib/language_operator/dsl/task_definition.rb +315 -0
  46. data/lib/language_operator/dsl.rb +1 -1
  47. data/lib/language_operator/instrumentation/task_tracer.rb +285 -0
  48. data/lib/language_operator/logger.rb +4 -4
  49. data/lib/language_operator/synthesis_test_harness.rb +324 -0
  50. data/lib/language_operator/templates/README.md +23 -0
  51. data/lib/language_operator/templates/examples/agent_synthesis.tmpl +133 -0
  52. data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
  53. data/lib/language_operator/templates/schema/.gitkeep +0 -0
  54. data/lib/language_operator/templates/schema/CHANGELOG.md +119 -0
  55. data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
  56. data/lib/language_operator/templates/schema/agent_dsl_schema.json +494 -0
  57. data/lib/language_operator/type_coercion.rb +250 -0
  58. data/lib/language_operator/ux/base.rb +81 -0
  59. data/lib/language_operator/ux/concerns/README.md +155 -0
  60. data/lib/language_operator/ux/concerns/headings.rb +90 -0
  61. data/lib/language_operator/ux/concerns/input_validation.rb +146 -0
  62. data/lib/language_operator/ux/concerns/provider_helpers.rb +167 -0
  63. data/lib/language_operator/ux/create_agent.rb +252 -0
  64. data/lib/language_operator/ux/create_model.rb +267 -0
  65. data/lib/language_operator/ux/quickstart.rb +594 -0
  66. data/lib/language_operator/version.rb +1 -1
  67. data/lib/language_operator.rb +2 -0
  68. data/requirements/ARCHITECTURE.md +1 -0
  69. data/requirements/SCRATCH.md +153 -0
  70. data/requirements/dsl.md +0 -0
  71. data/requirements/features +1 -0
  72. data/requirements/personas +1 -0
  73. data/requirements/proposals +1 -0
  74. data/requirements/tasks/iterate.md +14 -15
  75. data/requirements/tasks/optimize.md +13 -4
  76. data/synth/001/Makefile +90 -0
  77. data/synth/001/agent.rb +26 -0
  78. data/synth/001/agent.yaml +7 -0
  79. data/synth/001/output.log +44 -0
  80. data/synth/Makefile +39 -0
  81. data/synth/README.md +342 -0
  82. metadata +49 -18
  83. data/examples/README.md +0 -569
  84. data/examples/agent_example.rb +0 -86
  85. data/examples/chat_endpoint_agent.rb +0 -118
  86. data/examples/github_webhook_agent.rb +0 -171
  87. data/examples/mcp_agent.rb +0 -158
  88. data/examples/oauth_callback_agent.rb +0 -296
  89. data/examples/stripe_webhook_agent.rb +0 -219
  90. data/examples/webhook_agent.rb +0 -80
  91. data/lib/language_operator/dsl/workflow_definition.rb +0 -259
  92. data/test_agent_dsl.rb +0 -108
@@ -0,0 +1,324 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'json'
5
+ require 'ruby_llm'
6
+ require_relative 'agent/safety/ast_validator'
7
+
8
+ module LanguageOperator
9
+ # SynthesisTestHarness replicates the Go operator's synthesis logic for local testing.
10
+ # This allows testing agent code generation without requiring a Kubernetes cluster.
11
+ #
12
+ # Usage:
13
+ # harness = LanguageOperator::SynthesisTestHarness.new
14
+ # code = harness.synthesize('synth/001/agent.yaml', model: 'claude-3-5-sonnet-20241022')
15
+ # File.write('agent.rb', code)
16
+ #
17
+ class SynthesisTestHarness
18
+ attr_reader :template_content, :model
19
+
20
+ def initialize(model: nil)
21
+ @model = model || detect_default_model
22
+ @synthesis_endpoint = ENV.fetch('SYNTHESIS_ENDPOINT', nil)
23
+ @synthesis_api_key = ENV['SYNTHESIS_API_KEY'] || 'dummy'
24
+ @template_path = File.join(__dir__, 'templates', 'examples', 'agent_synthesis.tmpl')
25
+ load_template
26
+ end
27
+
28
+ # Synthesize agent code from a LanguageAgent YAML file
29
+ #
30
+ # @param yaml_path [String] Path to LanguageAgent YAML file
31
+ # @param model [String, nil] LLM model to use (overrides default)
32
+ # @return [String] Generated Ruby DSL code
33
+ def synthesize(yaml_path, model: nil)
34
+ agent_spec = load_agent_spec(yaml_path)
35
+
36
+ # Build synthesis request
37
+ request = build_synthesis_request(agent_spec)
38
+
39
+ # Build prompt from template
40
+ prompt = build_prompt(request)
41
+
42
+ # Call LLM
43
+ response = call_llm(prompt, model: model || @model)
44
+
45
+ # Extract code from markdown
46
+ code = extract_code_from_markdown(response)
47
+
48
+ # Validate code
49
+ validate_code(code)
50
+
51
+ code
52
+ end
53
+
54
+ private
55
+
56
+ def load_template
57
+ raise "Synthesis template not found at: #{@template_path}" unless File.exist?(@template_path)
58
+
59
+ @template_content = File.read(@template_path)
60
+ end
61
+
62
+ def load_agent_spec(yaml_path)
63
+ raise "Agent YAML file not found: #{yaml_path}" unless File.exist?(yaml_path)
64
+
65
+ yaml_content = File.read(yaml_path)
66
+ full_spec = YAML.safe_load(yaml_content, permitted_classes: [Symbol])
67
+
68
+ raise "Invalid kind: expected LanguageAgent, got #{full_spec['kind']}" unless full_spec['kind'] == 'LanguageAgent'
69
+
70
+ # Extract agent name from metadata and merge into spec
71
+ agent_spec = full_spec['spec'].dup
72
+ agent_spec['agentName'] = full_spec.dig('metadata', 'name') if full_spec.dig('metadata', 'name')
73
+
74
+ agent_spec
75
+ end
76
+
77
+ def build_synthesis_request(agent_spec)
78
+ # NOTE: agent_spec is the 'spec' section from the YAML
79
+ # The agent name comes from metadata.name, which we need to extract from the full YAML
80
+ {
81
+ instructions: agent_spec['instructions'],
82
+ agent_name: agent_spec['agentName'] || 'test-agent', # Will be overridden by metadata.name
83
+ tools: agent_spec['toolRefs'] || [],
84
+ models: agent_spec['modelRefs'] || [],
85
+ persona: agent_spec['personaRefs']&.first || nil
86
+ }
87
+ end
88
+
89
+ def build_prompt(request)
90
+ # Detect temporal intent from instructions
91
+ temporal_intent = detect_temporal_intent(request[:instructions])
92
+
93
+ # Format tools list
94
+ tools_list = format_list(request[:tools], 'No tools specified')
95
+
96
+ # Format models list
97
+ models_list = format_list(request[:models], 'No models specified')
98
+
99
+ # Build persona section
100
+ persona_section = ''
101
+ persona_section = " persona <<~PERSONA\n #{request[:persona]}\n PERSONA\n" if request[:persona]
102
+
103
+ # Build schedule section
104
+ schedule_section = ''
105
+ schedule_rules = ''
106
+
107
+ # Build constraints section
108
+ constraints_section = build_constraints_section(temporal_intent)
109
+
110
+ case temporal_intent
111
+ when :scheduled
112
+ schedule_section = "\n # Extract schedule from instructions (e.g., \"daily at noon\" -> \"0 12 * * *\")\n schedule \"CRON_EXPRESSION\""
113
+ schedule_rules = "2. Schedule detected - extract cron expression from instructions\n3. Set schedule block with appropriate cron expression\n4. Use high max_iterations for continuous scheduled operation"
114
+ when :oneshot
115
+ schedule_rules = "2. One-shot execution detected - agent will run a limited number of times\n3. Do NOT include a schedule block for one-shot agents"
116
+ when :continuous
117
+ schedule_rules = "2. No temporal intent detected - defaulting to continuous execution\n3. Do NOT include a schedule block unless explicitly mentioned\n4. Use high max_iterations for continuous operation"
118
+ end
119
+
120
+ # Render template with variable substitution
121
+ rendered = @template_content.dup
122
+
123
+ # Handle conditional sections (simple implementation for {{if .ErrorContext}})
124
+ rendered.gsub!(/\{\{if \.ErrorContext\}\}.*?\{\{else\}\}/m, '')
125
+ rendered.gsub!('{{end}}', '')
126
+
127
+ # Replace variables
128
+ rendered.gsub!('{{.Instructions}}', request[:instructions])
129
+ rendered.gsub!('{{.ToolsList}}', tools_list)
130
+ rendered.gsub!('{{.ModelsList}}', models_list)
131
+ rendered.gsub!('{{.AgentName}}', request[:agent_name])
132
+ rendered.gsub!('{{.TemporalIntent}}', temporal_intent.to_s.capitalize)
133
+ rendered.gsub!('{{.PersonaSection}}', persona_section)
134
+ rendered.gsub!('{{.ScheduleSection}}', schedule_section)
135
+ rendered.gsub!('{{.ConstraintsSection}}', constraints_section)
136
+ rendered.gsub!('{{.ScheduleRules}}', schedule_rules)
137
+
138
+ rendered
139
+ end
140
+
141
+ def detect_temporal_intent(instructions)
142
+ return :continuous if instructions.nil? || instructions.strip.empty?
143
+
144
+ lower = instructions.downcase
145
+
146
+ # One-shot indicators
147
+ oneshot_keywords = ['run once', 'one time', 'single time', 'execute once', 'just once']
148
+ return :oneshot if oneshot_keywords.any? { |keyword| lower.include?(keyword) }
149
+
150
+ # Schedule indicators
151
+ schedule_keywords = %w[every daily hourly weekly monthly cron schedule periodically]
152
+ return :scheduled if schedule_keywords.any? { |keyword| lower.include?(keyword) }
153
+
154
+ # Default to continuous
155
+ :continuous
156
+ end
157
+
158
+ def build_constraints_section(temporal_intent)
159
+ case temporal_intent
160
+ when :oneshot
161
+ <<~CONSTRAINTS.chomp
162
+ # One-shot execution detected from instructions
163
+ constraints do
164
+ max_iterations 10
165
+ timeout "10m"
166
+ end
167
+ CONSTRAINTS
168
+ when :scheduled
169
+ <<~CONSTRAINTS.chomp
170
+ # Scheduled execution - high iteration limit for continuous operation
171
+ constraints do
172
+ max_iterations 999999
173
+ timeout "10m"
174
+ end
175
+ CONSTRAINTS
176
+ when :continuous
177
+ <<~CONSTRAINTS.chomp
178
+ # Continuous execution - no specific schedule or one-shot indicator found
179
+ constraints do
180
+ max_iterations 999999
181
+ timeout "10m"
182
+ end
183
+ CONSTRAINTS
184
+ end
185
+ end
186
+
187
+ def format_list(items, default_text)
188
+ return default_text if items.nil? || items.empty?
189
+
190
+ items.map { |item| " - #{item}" }.join("\n")
191
+ end
192
+
193
+ def call_llm(prompt, model:)
194
+ # Priority 1: Use SYNTHESIS_ENDPOINT if configured (OpenAI-compatible)
195
+ return call_openai_compatible(prompt, model) if @synthesis_endpoint
196
+
197
+ # Priority 2: Detect provider from model name
198
+ provider, api_key = detect_provider(model)
199
+
200
+ unless api_key
201
+ raise "No API key found. Set either:\n " \
202
+ "SYNTHESIS_ENDPOINT (for local/OpenAI-compatible)\n " \
203
+ "ANTHROPIC_API_KEY (for Claude)\n " \
204
+ 'OPENAI_API_KEY (for GPT)'
205
+ end
206
+
207
+ # Configure RubyLLM for the provider
208
+ RubyLLM.configure do |config|
209
+ case provider
210
+ when :anthropic
211
+ config.anthropic_api_key = api_key
212
+ when :openai
213
+ config.openai_api_key = api_key
214
+ end
215
+ end
216
+
217
+ # Create chat and send message
218
+ chat = RubyLLM.chat(model: model, provider: provider)
219
+ response = chat.ask(prompt)
220
+
221
+ # Extract content
222
+ if response.respond_to?(:content)
223
+ response.content
224
+ elsif response.is_a?(Hash) && response.key?('content')
225
+ response['content']
226
+ elsif response.is_a?(String)
227
+ response
228
+ else
229
+ response.to_s
230
+ end
231
+ rescue StandardError => e
232
+ raise "LLM call failed: #{e.message}"
233
+ end
234
+
235
+ def call_openai_compatible(prompt, model)
236
+ # Configure RubyLLM for OpenAI-compatible endpoint
237
+ RubyLLM.configure do |config|
238
+ config.openai_api_key = @synthesis_api_key
239
+ config.openai_api_base = @synthesis_endpoint
240
+ config.openai_use_system_role = true # Better compatibility with local models
241
+ end
242
+
243
+ # Create chat with OpenAI provider (will use configured endpoint)
244
+ chat = RubyLLM.chat(model: model, provider: :openai, assume_model_exists: true)
245
+
246
+ # Send message
247
+ response = chat.ask(prompt)
248
+
249
+ # Extract content
250
+ if response.respond_to?(:content)
251
+ response.content
252
+ elsif response.is_a?(Hash) && response.key?('content')
253
+ response['content']
254
+ elsif response.is_a?(String)
255
+ response
256
+ else
257
+ response.to_s
258
+ end
259
+ rescue StandardError => e
260
+ raise "OpenAI-compatible endpoint call failed: #{e.message}"
261
+ end
262
+
263
+ def detect_provider(model)
264
+ if model.start_with?('claude')
265
+ [:anthropic, ENV.fetch('ANTHROPIC_API_KEY', nil)]
266
+ elsif model.start_with?('gpt')
267
+ [:openai, ENV.fetch('OPENAI_API_KEY', nil)]
268
+ else
269
+ # Default to Anthropic
270
+ [:anthropic, ENV.fetch('ANTHROPIC_API_KEY', nil)]
271
+ end
272
+ end
273
+
274
+ def detect_default_model
275
+ # Priority 1: Use SYNTHESIS_MODEL if configured
276
+ return ENV['SYNTHESIS_MODEL'] if ENV['SYNTHESIS_MODEL']
277
+
278
+ # Priority 2: Use cloud providers
279
+ if ENV['ANTHROPIC_API_KEY']
280
+ 'claude-3-5-sonnet-20241022'
281
+ elsif ENV['OPENAI_API_KEY']
282
+ 'gpt-4-turbo'
283
+ else
284
+ # Default to a reasonable model name for local endpoints
285
+ 'mistralai/magistral-small-2509'
286
+ end
287
+ end
288
+
289
+ def extract_code_from_markdown(content)
290
+ content = content.strip
291
+
292
+ # Try ```ruby first
293
+ if (match = content.match(/```ruby\n(.*?)```/m))
294
+ return match[1].strip
295
+ end
296
+
297
+ # Try generic ``` blocks
298
+ if (match = content.match(/```\n(.*?)```/m))
299
+ return match[1].strip
300
+ end
301
+
302
+ # If no code blocks, return as-is and let validation catch it
303
+ content
304
+ end
305
+
306
+ def validate_code(code)
307
+ # Basic checks
308
+ raise 'Empty code generated' if code.strip.empty?
309
+ raise "Code does not contain 'agent' definition" unless code.include?('agent ')
310
+ raise "Code does not require 'language_operator'" unless code.match?(/require ['"]language_operator['"]/)
311
+
312
+ # AST validation for security
313
+ validator = LanguageOperator::Agent::Safety::ASTValidator.new
314
+ violations = validator.validate(code, '(generated)')
315
+
316
+ unless violations.empty?
317
+ error_msgs = violations.map { |v| v[:message] }.join("\n")
318
+ raise "Security validation failed:\n#{error_msgs}"
319
+ end
320
+
321
+ true
322
+ end
323
+ end
324
+ end
@@ -0,0 +1,23 @@
1
+ # Templates Directory
2
+
3
+ This directory contains templates used by the Language Operator gem for various code generation and synthesis tasks.
4
+
5
+ ## Directory Structure
6
+
7
+ - **`examples/`** - Example synthesis templates for agent and persona generation
8
+ - `agent_synthesis.tmpl` - Template for synthesizing agent definitions
9
+ - `persona_distillation.tmpl` - Template for distilling persona configurations
10
+
11
+ - **`schema/`** - JSON Schema definitions and validation templates
12
+ - Reserved for future schema artifacts and validation templates
13
+
14
+ ## Usage
15
+
16
+ Templates in this directory are used by:
17
+ - The `aictl system synthesis-template` command for managing synthesis templates
18
+ - Agent synthesis and persona distillation features
19
+ - Schema validation and code generation tools
20
+
21
+ ## Template Format
22
+
23
+ Templates use a simple variable substitution format compatible with the synthesis engine. Variables are typically specified in the template header and replaced during synthesis.
@@ -0,0 +1,133 @@
1
+ You are generating Ruby DSL code for an autonomous agent in a Kubernetes operator.
2
+
3
+ {{if .ErrorContext}}
4
+ ## IMPORTANT: Self-Healing Synthesis - Attempt {{.AttemptNumber}}
5
+
6
+ The previous code synthesis encountered errors. Please analyze the errors below and generate CORRECTED code.
7
+
8
+ ### Previous Synthesis Failures
9
+
10
+ {{if .ErrorContext.ValidationErrors}}
11
+ **Validation Errors** (detected during code generation):
12
+ {{range .ErrorContext.ValidationErrors}}
13
+ - {{.}}
14
+ {{end}}
15
+ {{end}}
16
+
17
+ {{if .ErrorContext.RuntimeErrors}}
18
+ **Runtime Errors** (detected during execution):
19
+ {{range .ErrorContext.RuntimeErrors}}
20
+ - Time: {{.Timestamp}}
21
+ - Type: {{.ErrorType}}
22
+ - Message: {{.ErrorMessage}}
23
+ {{if .StackTrace}}
24
+ - Stack Trace:
25
+ {{range .StackTrace}}
26
+ {{.}}
27
+ {{end}}
28
+ {{end}}
29
+ - Exit Code: {{.ContainerExitCode}}
30
+ {{end}}
31
+ {{end}}
32
+
33
+ {{if .ErrorContext.LastCrashLog}}
34
+ **Last Container Logs** (before crash):
35
+ ```
36
+ {{.ErrorContext.LastCrashLog}}
37
+ ```
38
+ {{end}}
39
+
40
+ ### Your Task
41
+
42
+ 1. Carefully analyze each error above
43
+ 2. Identify the root cause of the failure
44
+ 3. Generate CORRECTED Ruby DSL code that addresses ALL errors
45
+ 4. Ensure the code:
46
+ - Fixes the specific errors mentioned
47
+ - Uses only available tools: {{.ToolsList}}
48
+ - Uses only available models: {{.ModelsList}}
49
+ - Follows the Language Operator DSL syntax exactly
50
+ - Does NOT use any dangerous Ruby methods (system, eval, etc.)
51
+
52
+ This is attempt {{.AttemptNumber}} of {{.MaxAttempts}}. The user is counting on you to get it right!
53
+
54
+ {{if .LastKnownGoodCode}}
55
+ ### Last Known Working Code (for reference)
56
+ ```ruby
57
+ {{.LastKnownGoodCode}}
58
+ ```
59
+ {{end}}
60
+
61
+ {{else}}
62
+ ## Agent Synthesis Request
63
+ {{end}}
64
+
65
+ **User Instructions:**
66
+ {{.Instructions}}
67
+
68
+ **Available Tools:**
69
+ {{.ToolsList}}
70
+
71
+ **Available Models:**
72
+ {{.ModelsList}}
73
+
74
+ **Agent Name:** {{.AgentName}}
75
+
76
+ **Detected Temporal Intent:** {{.TemporalIntent}}
77
+
78
+ **Runtime Context:**
79
+ - All agent messages and output are automatically logged to stdout
80
+ - Agents have access to a workspace directory for file operations
81
+ - LLM responses are captured and available in agent execution context
82
+
83
+ Generate Ruby DSL code using this exact format (wrapped in triple-backticks with ruby):
84
+
85
+ ```ruby
86
+ require 'language_operator'
87
+
88
+ agent "{{.AgentName}}" do
89
+ description "Brief description extracted from instructions"
90
+ {{.PersonaSection}}{{.ScheduleSection}}
91
+ # Extract objectives from instructions
92
+ objectives [
93
+ "First objective",
94
+ "Second objective"
95
+ ]
96
+
97
+ # REQUIRED: Define workflow with at least one step
98
+ workflow do
99
+ # Use tools when available
100
+ step :step_name, tool: "tool_name", params: {key: "value"}
101
+
102
+ # Or use execute blocks for custom Ruby code (simple logging, calculations, etc.)
103
+ step :custom_step do
104
+ execute do
105
+ puts "Custom output from Ruby code"
106
+ { result: "done" }
107
+ end
108
+ end
109
+
110
+ # Chain steps with dependencies if needed
111
+ step :another_step, depends_on: :step_name
112
+ end
113
+
114
+ {{.ConstraintsSection}}
115
+
116
+ # Output configuration (if workspace enabled)
117
+ output do
118
+ workspace "results/output.txt"
119
+ end
120
+ end
121
+ ```
122
+
123
+ **Rules:**
124
+ 1. Generate ONLY the Ruby code within triple-backticks, no explanations before or after
125
+ {{.ScheduleRules}}
126
+ 5. Break down instructions into clear, actionable objectives
127
+ 6. REQUIRED: Always include a workflow block with at least one step (even for simple single-action agents)
128
+ 7. For simple tasks (logging, calculations), use a single step with an execute block containing Ruby code
129
+ 8. For complex tasks, use multiple steps with tools or execute blocks
130
+ 9. Use available tools in workflow steps when tools are provided
131
+ 10. Use the agent name: "{{.AgentName}}"
132
+
133
+ Generate the code now:
@@ -0,0 +1,19 @@
1
+ Distill this persona into a single concise paragraph for an AI agent.
2
+
3
+ **Persona Details:**
4
+ Name: {{.PersonaName}}
5
+ Description: {{.PersonaDescription}}
6
+ System Prompt: {{.PersonaSystemPrompt}}
7
+ Tone: {{.PersonaTone}}
8
+ Language: {{.PersonaLanguage}}
9
+
10
+ **Agent Context:**
11
+ Goal: {{.AgentInstructions}}
12
+ Available Tools: {{.AgentTools}}
13
+
14
+ Generate a single paragraph (2-4 sentences) that captures the essence of this persona
15
+ in the context of the agent's goal. Focus on tone, expertise, and key behaviors.
16
+
17
+ Output ONLY the distilled persona paragraph, nothing else.
18
+
19
+ Distilled persona:
File without changes
@@ -0,0 +1,119 @@
1
+ # Schema Changelog
2
+
3
+ This file tracks changes to the Language Operator Agent DSL schema.
4
+
5
+ ## Schema Versioning
6
+
7
+ The schema version is tied directly to the gem version and follows [Semantic Versioning](https://semver.org/):
8
+
9
+ - **MAJOR** version: Breaking changes to DSL structure or behavior
10
+ - **MINOR** version: New features, backward-compatible additions
11
+ - **PATCH** version: Bug fixes, documentation improvements
12
+
13
+ ## Version History
14
+
15
+ ### 0.1.34 (2025-11-14)
16
+
17
+ **DSL v1: Task/Main Primitives Added**
18
+
19
+ This release adds support for the new DSL v1 pattern with task/main primitives while maintaining backward compatibility with the workflow/step pattern.
20
+
21
+ **New Features:**
22
+ - Added `task()` DSL method to AgentDefinition for defining organic functions
23
+ - Task definitions support neural (instructions), symbolic (code block), and hybrid implementations
24
+ - Tasks stored in `@tasks` hash on AgentDefinition
25
+ - Full input/output schema validation via TaskDefinition
26
+
27
+ **Improvements:**
28
+ - Added deprecation warning to `workflow()` method
29
+ - Updated schema to include task definitions
30
+ - Added comprehensive test coverage for task registration
31
+
32
+ **Deprecated:**
33
+ - `workflow` and `step` pattern (use `task` and `main` instead)
34
+ - Migration guide available in requirements/proposals/dsl-v1.md
35
+
36
+ **Backward Compatibility:**
37
+ - Existing workflow-based agents continue to work
38
+ - Both task and workflow can coexist in same agent during migration
39
+ - No breaking changes to existing code
40
+
41
+ ### 0.1.30 (2025-11-12)
42
+
43
+ **Initial schema artifact generation**
44
+
45
+ This is the first release with auto-generated schema artifacts included in the gem package.
46
+
47
+ **Schema Features:**
48
+ - Complete JSON Schema v7 for Agent DSL
49
+ - OpenAPI 3.0.3 specification for agent HTTP endpoints
50
+ - Agent configuration properties (name, description, persona, mode, schedule, objectives)
51
+ - Workflow definitions with step dependencies
52
+ - Constraint definitions (budgets, rate limits, timeouts)
53
+ - Output destinations (workspace, Slack, email)
54
+ - Webhook definitions with authentication
55
+ - MCP server configuration
56
+ - Chat endpoint configuration (OpenAI-compatible)
57
+ - Tool and parameter definitions
58
+
59
+ **API Endpoints Documented:**
60
+ - `GET /health` - Health check
61
+ - `GET /ready` - Readiness check
62
+ - `POST /v1/chat/completions` - OpenAI-compatible chat endpoint
63
+ - `GET /v1/models` - List available models
64
+
65
+ **Safe Methods:**
66
+ - Agent DSL methods validated via `Agent::Safety::ASTValidator`
67
+ - Tool DSL methods for parameter definitions
68
+ - Helper methods for HTTP, Shell, validation, and utilities
69
+
70
+ ---
71
+
72
+ ## Future Versions
73
+
74
+ ### Template for New Entries
75
+
76
+ ```markdown
77
+ ### X.Y.Z (YYYY-MM-DD)
78
+
79
+ **Summary of changes**
80
+
81
+ **Breaking Changes:**
82
+ - Description of any breaking changes
83
+
84
+ **New Features:**
85
+ - New DSL methods or capabilities added
86
+ - New endpoint specifications
87
+
88
+ **Improvements:**
89
+ - Schema validation enhancements
90
+ - Documentation updates
91
+
92
+ **Bug Fixes:**
93
+ - Schema corrections
94
+ - Type definition fixes
95
+
96
+ **Deprecated:**
97
+ - Features marked for removal in future versions
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Schema Validation
103
+
104
+ The schema can be used for:
105
+ - **Template Validation** - Ensuring synthesized agent code is valid
106
+ - **Documentation Generation** - Auto-generating reference docs
107
+ - **IDE Support** - Providing autocomplete and IntelliSense
108
+ - **CLI Introspection** - Runtime validation of agent definitions
109
+
110
+ ## Schema Artifacts
111
+
112
+ Generated artifacts are stored in this directory:
113
+ - `agent_dsl_schema.json` - JSON Schema v7 specification
114
+ - `agent_dsl_openapi.yaml` - OpenAPI 3.0.3 specification
115
+
116
+ These are regenerated automatically during the build process via:
117
+ ```bash
118
+ rake schema:generate
119
+ ```