language-operator 0.1.66 → 0.1.70

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9121bdf48b4ee7bad4c9918d68ddf554966acd1c264cd8e1a1cadc13e5c6459
4
- data.tar.gz: cf90195c887a60165e1aee1990e2dafe2b69a37c736362d1bcbf341dd21dfb3f
3
+ metadata.gz: d6a8a654ac7b3fea9f1d176029ba86153b44cc746dacb8173054c6c2e0740def
4
+ data.tar.gz: d67180ae9aa7e99ad55b0764936028348039359367320a7e76afad95d5cd84a6
5
5
  SHA512:
6
- metadata.gz: f533c69e38c4bc604b939e54b743228a4640611292d5afbe7cbaa79f0b4f05436c8e1360cb64a8f1de623acddc08d291d39a4381817a530bd4b96f4408699913
7
- data.tar.gz: 1511bba1d7471abaa63e1029fe9b229414dd9f2b745fb2f38b83d073ac529506b00a913fd56418c4a461c06bf061a0526973a5213574ed2cc70332a0249d8d00
6
+ metadata.gz: 7244d148d067fb2733a23c193c499bb13bc336891cdd5fbbb932cc1ecf40111cf2bfb8f3e25ac9cd290b655915a3e2ab5e3c88bfb133063ba47991835d7e485e
7
+ data.tar.gz: d11fa46700dd377f76804c3808848b4ee321982db18c25611834b660c60babbffb80fbcfe26abc8e32d21e01b26776fdb97f699b7e769d6a7a2337fadea591ba
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- language-operator (0.1.66)
4
+ language-operator (0.1.70)
5
5
  faraday (~> 2.0)
6
+ json-schema (~> 5.0)
6
7
  k8s-ruby (~> 0.17)
7
8
  lru_redux (~> 1.1)
8
9
  mcp (~> 0.4)
@@ -27,14 +28,14 @@ PATH
27
28
  GEM
28
29
  remote: https://rubygems.org/
29
30
  specs:
30
- addressable (2.8.7)
31
- public_suffix (>= 2.0.2, < 7.0)
31
+ addressable (2.8.8)
32
+ public_suffix (>= 2.0.2, < 8.0)
32
33
  ast (2.4.3)
33
34
  base64 (0.3.0)
34
35
  benchmark (0.5.0)
35
36
  bigdecimal (3.3.1)
36
37
  coderay (1.1.3)
37
- concurrent-ruby (1.3.5)
38
+ concurrent-ruby (1.3.6)
38
39
  crack (1.0.1)
39
40
  bigdecimal
40
41
  rexml
@@ -72,24 +73,24 @@ GEM
72
73
  logger
73
74
  faraday-multipart (1.1.1)
74
75
  multipart-post (~> 2.0)
75
- faraday-net_http (3.4.1)
76
- net-http (>= 0.5.0)
76
+ faraday-net_http (3.4.2)
77
+ net-http (~> 0.5)
77
78
  faraday-retry (2.3.2)
78
79
  faraday (~> 2.0)
79
- google-protobuf (4.33.0)
80
+ google-protobuf (4.33.2)
80
81
  bigdecimal
81
82
  rake (>= 13)
82
- google-protobuf (4.33.0-x86_64-linux-gnu)
83
+ google-protobuf (4.33.2-x86_64-linux-gnu)
83
84
  bigdecimal
84
85
  rake (>= 13)
85
86
  googleapis-common-protos-types (1.22.0)
86
87
  google-protobuf (~> 4.26)
87
88
  hashdiff (1.2.1)
88
89
  http-2 (1.1.1)
89
- httpx (1.6.3)
90
+ httpx (1.7.0)
90
91
  http-2 (>= 1.0.0)
91
92
  ice_nine (0.11.2)
92
- json (2.15.2)
93
+ json (2.18.0)
93
94
  json-schema (5.2.2)
94
95
  addressable (~> 2.8)
95
96
  bigdecimal (~> 3.1)
@@ -117,10 +118,10 @@ GEM
117
118
  json_rpc_handler (~> 0.1)
118
119
  memory_profiler (1.1.0)
119
120
  method_source (1.1.0)
120
- multi_json (1.17.0)
121
+ multi_json (1.18.0)
121
122
  multipart-post (2.4.1)
122
- net-http (0.7.0)
123
- uri
123
+ net-http (0.9.1)
124
+ uri (>= 0.11.1)
124
125
  nio4r (2.7.5)
125
126
  opentelemetry-api (1.7.0)
126
127
  opentelemetry-common (0.23.0)
@@ -136,7 +137,7 @@ GEM
136
137
  opentelemetry-api (~> 1.7)
137
138
  opentelemetry-common (~> 0.21)
138
139
  opentelemetry-registry (~> 0.1)
139
- opentelemetry-instrumentation-http (0.27.0)
140
+ opentelemetry-instrumentation-http (0.27.1)
140
141
  opentelemetry-instrumentation-base (~> 0.25)
141
142
  opentelemetry-instrumentation-rack (0.29.0)
142
143
  opentelemetry-instrumentation-base (~> 0.25)
@@ -158,18 +159,18 @@ GEM
158
159
  racc
159
160
  pastel (0.8.0)
160
161
  tty-color (~> 0.5)
161
- prism (1.6.0)
162
+ prism (1.7.0)
162
163
  pry (0.15.2)
163
164
  coderay (~> 1.1)
164
165
  method_source (~> 1.0)
165
- public_suffix (6.0.2)
166
+ public_suffix (7.0.0)
166
167
  puma (6.6.1)
167
168
  nio4r (~> 2.0)
168
169
  racc (1.8.1)
169
170
  rack (3.2.4)
170
171
  rack-test (2.2.0)
171
172
  rack (>= 1.3)
172
- rackup (2.2.1)
173
+ rackup (2.3.1)
173
174
  rack (>= 3)
174
175
  rainbow (3.1.1)
175
176
  rake (13.3.1)
@@ -191,7 +192,7 @@ GEM
191
192
  diff-lcs (>= 1.2.0, < 2.0)
192
193
  rspec-support (~> 3.13.0)
193
194
  rspec-support (3.13.6)
194
- rubocop (1.81.7)
195
+ rubocop (1.82.1)
195
196
  json (~> 2.3)
196
197
  language_server-protocol (~> 3.17.0.2)
197
198
  lint_roller (~> 1.1.0)
@@ -199,10 +200,10 @@ GEM
199
200
  parser (>= 3.3.0.2)
200
201
  rainbow (>= 2.2.2, < 4.0)
201
202
  regexp_parser (>= 2.9.3, < 3.0)
202
- rubocop-ast (>= 1.47.1, < 2.0)
203
+ rubocop-ast (>= 1.48.0, < 2.0)
203
204
  ruby-progressbar (~> 1.7)
204
205
  unicode-display_width (>= 2.4.0, < 4.0)
205
- rubocop-ast (1.47.1)
206
+ rubocop-ast (1.48.0)
206
207
  parser (>= 3.3.7.2)
207
208
  prism (~> 1.4)
208
209
  rubocop-performance (1.26.1)
@@ -220,12 +221,12 @@ GEM
220
221
  marcel (~> 1.0)
221
222
  ruby_llm-schema (~> 0.2.1)
222
223
  zeitwerk (~> 2)
223
- ruby_llm-mcp (0.7.0)
224
+ ruby_llm-mcp (0.8.0)
224
225
  httpx (~> 1.4)
225
226
  json-schema (~> 5.0)
226
227
  ruby_llm (~> 1.9)
227
228
  zeitwerk (~> 2)
228
- ruby_llm-schema (0.2.1)
229
+ ruby_llm-schema (0.2.5)
229
230
  strings (0.2.1)
230
231
  strings-ansi (~> 0.2)
231
232
  unicode-display_width (>= 1.5, < 3.0)
@@ -262,8 +263,8 @@ GEM
262
263
  wisper (2.0.1)
263
264
  yajl-ruby (1.4.3)
264
265
  yaml-safe_load_stream3 (0.1.2)
265
- yard (0.9.37)
266
- zeitwerk (2.7.3)
266
+ yard (0.9.38)
267
+ zeitwerk (2.7.4)
267
268
 
268
269
  PLATFORMS
269
270
  ruby
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Chat Endpoint Agent Example
5
+ #
6
+ # This example demonstrates how to create an agent that exposes
7
+ # an OpenAI-compatible chat completion endpoint.
8
+ #
9
+ # Usage:
10
+ # ruby examples/chat_endpoint_agent.rb
11
+ #
12
+ # Then test with curl:
13
+ # curl -X POST http://localhost:8080/v1/chat/completions \
14
+ # -H "Content-Type: application/json" \
15
+ # -d '{
16
+ # "model": "github-expert-v1",
17
+ # "messages": [
18
+ # {"role": "user", "content": "How do I create a pull request?"}
19
+ # ]
20
+ # }'
21
+
22
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
23
+
24
+ require 'language_operator'
25
+
26
+ # Define an agent with chat endpoint capabilities
27
+ LanguageOperator::Dsl.define do
28
+ agent "github-expert" do
29
+ description "GitHub API and workflow expert"
30
+ mode :reactive
31
+
32
+ # This is the key - expose the agent as an OpenAI-compatible chat endpoint
33
+ as_chat_endpoint do
34
+ system_prompt <<~PROMPT
35
+ You are a GitHub expert assistant with deep knowledge of:
36
+ - GitHub API and workflows
37
+ - Pull requests, issues, and code review
38
+ - GitHub Actions and CI/CD
39
+ - Repository management and best practices
40
+
41
+ Provide helpful, accurate answers about GitHub topics.
42
+ Keep responses concise but informative.
43
+ PROMPT
44
+
45
+ # Configure the endpoint parameters
46
+ model "github-expert-v1" # Model name returned in API responses
47
+ temperature 0.7 # Balanced creativity and consistency
48
+ max_tokens 2000 # Limit response length
49
+ end
50
+
51
+ # Optional: Add constraints for safety and cost management
52
+ constraints do
53
+ timeout '30s'
54
+ requests_per_minute 30
55
+ daily_budget 1000 # $10/day
56
+ end
57
+ end
58
+ end
59
+
60
+ # Start the agent
61
+ if __FILE__ == $PROGRAM_NAME
62
+ puts "Starting GitHub Expert Chat Endpoint Agent..."
63
+ puts "Server will be available at http://localhost:8080"
64
+ puts ""
65
+ puts "Endpoints available:"
66
+ puts " POST /v1/chat/completions - Chat completion (OpenAI-compatible)"
67
+ puts " GET /v1/models - List available models"
68
+ puts " GET /health - Health check"
69
+ puts " GET /ready - Readiness check"
70
+ puts ""
71
+ puts "Test with curl:"
72
+ puts ' curl -X POST http://localhost:8080/v1/chat/completions \\'
73
+ puts ' -H "Content-Type: application/json" \\'
74
+ puts ' -d \'{"model": "github-expert-v1", "messages": [{"role": "user", "content": "How do I create a pull request?"}]}\''
75
+ puts ""
76
+
77
+ LanguageOperator::Agent.run
78
+ end
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Hybrid Agent Example
5
+ #
6
+ # This demonstrates an agent that runs BOTH:
7
+ # 1. Continuous autonomous work (background monitoring)
8
+ # 2. Chat endpoint for interactive queries
9
+ #
10
+ # The agent will:
11
+ # - Monitor system status every 30 seconds (autonomous mode)
12
+ # - Expose chat endpoint at /v1/chat/completions (web server)
13
+ # - Handle webhooks for alerts (reactive features)
14
+ #
15
+ # Usage:
16
+ # ruby examples/hybrid_agent.rb
17
+ #
18
+ # Test chat endpoint:
19
+ # curl -X POST http://localhost:8080/v1/chat/completions \
20
+ # -H "Content-Type: application/json" \
21
+ # -d '{
22
+ # "model": "system-monitor-v1",
23
+ # "messages": [
24
+ # {"role": "user", "content": "What is the current system status?"}
25
+ # ]
26
+ # }'
27
+
28
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
29
+
30
+ require 'language_operator'
31
+
32
+ # Define a hybrid agent
33
+ LanguageOperator::Dsl.define do
34
+ agent "system-monitor" do
35
+ description "Autonomous system monitor with chat interface"
36
+
37
+ # This agent runs in autonomous mode (continuous loop)
38
+ mode :autonomous
39
+
40
+ # Define the main autonomous work
41
+ task :check_system_status,
42
+ instructions: "Check current system status (CPU, memory, disk, network)",
43
+ inputs: {},
44
+ outputs: {
45
+ status: 'string',
46
+ cpu_usage: 'number',
47
+ memory_usage: 'number',
48
+ disk_usage: 'number',
49
+ timestamp: 'string'
50
+ }
51
+
52
+ task :analyze_trends,
53
+ instructions: "Analyze system trends and identify potential issues",
54
+ inputs: {
55
+ status: 'string',
56
+ cpu_usage: 'number',
57
+ memory_usage: 'number',
58
+ disk_usage: 'number'
59
+ },
60
+ outputs: {
61
+ analysis: 'string',
62
+ alerts: 'array'
63
+ }
64
+
65
+ task :log_status,
66
+ instructions: "Log the system status and analysis",
67
+ inputs: {
68
+ status: 'string',
69
+ analysis: 'string',
70
+ alerts: 'array',
71
+ timestamp: 'string'
72
+ },
73
+ outputs: { logged: 'boolean' }
74
+
75
+ # Main autonomous loop - runs continuously
76
+ main do |inputs|
77
+ puts "🔄 Running system monitoring cycle..."
78
+
79
+ # Check system status
80
+ status_data = execute_task(:check_system_status)
81
+ puts "📊 System status: #{status_data[:status]} (CPU: #{status_data[:cpu_usage]}%)"
82
+
83
+ # Analyze trends
84
+ analysis_data = execute_task(:analyze_trends, inputs: status_data)
85
+
86
+ # Log results
87
+ execute_task(:log_status, inputs: status_data.merge(analysis_data))
88
+
89
+ if analysis_data[:alerts].any?
90
+ puts "⚠️ Alerts: #{analysis_data[:alerts].join(', ')}"
91
+ end
92
+
93
+ puts "😴 Sleeping for 30 seconds..."
94
+ sleep 30
95
+
96
+ # Return data for next cycle
97
+ status_data.merge(analysis_data)
98
+ end
99
+
100
+ # Chat endpoint for interactive queries
101
+ as_chat_endpoint do
102
+ system_prompt <<~PROMPT
103
+ You are a system monitoring assistant with real-time access to system metrics.
104
+
105
+ You can help with:
106
+ - Current system status and performance metrics
107
+ - Historical trends and analysis
108
+ - Performance optimization recommendations
109
+ - Alert investigation and troubleshooting
110
+ - System health assessments
111
+
112
+ Provide clear, actionable insights about system performance.
113
+ Use technical terminology appropriately but explain complex concepts.
114
+ PROMPT
115
+
116
+ model "system-monitor-v1"
117
+ temperature 0.3 # More factual for system data
118
+ max_tokens 1500
119
+ end
120
+
121
+ # Webhook for external alerts
122
+ webhook "/alert" do
123
+ method :post
124
+
125
+ on_request do |context|
126
+ alert_data = JSON.parse(context[:body])
127
+ puts "🚨 Received alert: #{alert_data['message']}"
128
+
129
+ # Could trigger immediate system check or escalation
130
+ {
131
+ status: 'received',
132
+ alert_id: alert_data['id'],
133
+ processed_at: Time.now.iso8601
134
+ }
135
+ end
136
+ rescue JSON::ParserError => e
137
+ {
138
+ error: 'Invalid JSON in alert payload',
139
+ message: e.message
140
+ }
141
+ end
142
+
143
+ # MCP tools for system operations
144
+ as_mcp_server do
145
+ tool "get_current_metrics" do
146
+ description "Get real-time system metrics"
147
+
148
+ execute do |params|
149
+ # Simulate system metrics collection
150
+ {
151
+ cpu_percent: rand(0.0..100.0).round(1),
152
+ memory_percent: rand(0.0..100.0).round(1),
153
+ disk_percent: rand(0.0..100.0).round(1),
154
+ load_average: [rand(0.0..4.0), rand(0.0..4.0), rand(0.0..4.0)].map { |x| x.round(2) },
155
+ uptime_seconds: rand(3600..2_592_000),
156
+ timestamp: Time.now.iso8601
157
+ }
158
+ end
159
+ end
160
+
161
+ tool "restart_service" do
162
+ description "Restart a system service"
163
+ parameter "service_name", type: :string, required: true, description: "Name of service to restart"
164
+
165
+ execute do |params|
166
+ service_name = params["service_name"]
167
+ puts "🔄 Restarting service: #{service_name}"
168
+
169
+ # Simulate service restart
170
+ success = rand > 0.1 # 90% success rate
171
+
172
+ {
173
+ service: service_name,
174
+ action: 'restart',
175
+ success: success,
176
+ message: success ? "Service restarted successfully" : "Failed to restart service",
177
+ timestamp: Time.now.iso8601
178
+ }
179
+ end
180
+ end
181
+ end
182
+
183
+ # Constraints for safety and resource management
184
+ constraints do
185
+ timeout '60s'
186
+ max_iterations 999999 # Run indefinitely
187
+ requests_per_minute 60 # For chat/webhook endpoints
188
+ daily_budget 2000 # $20/day
189
+ end
190
+ end
191
+ end
192
+
193
+ # Start the hybrid agent
194
+ if __FILE__ == $PROGRAM_NAME
195
+ puts "🚀 Starting Hybrid System Monitor Agent"
196
+ puts ""
197
+ puts "This agent will:"
198
+ puts " ✅ Run autonomous system monitoring every 30 seconds"
199
+ puts " ✅ Expose chat endpoint at http://localhost:8080/v1/chat/completions"
200
+ puts " ✅ Handle alerts via POST /alert webhook"
201
+ puts " ✅ Provide MCP tools for system operations"
202
+ puts ""
203
+ puts "Available endpoints:"
204
+ puts " POST /v1/chat/completions - Chat with the monitoring assistant"
205
+ puts " GET /v1/models - List available models"
206
+ puts " POST /alert - Receive system alerts"
207
+ puts " POST /mcp - MCP protocol endpoint"
208
+ puts " GET /health - Health check"
209
+ puts " GET /ready - Readiness check"
210
+ puts ""
211
+ puts "Test commands:"
212
+ puts ""
213
+ puts "# Chat with the agent"
214
+ puts "curl -X POST http://localhost:8080/v1/chat/completions \\"
215
+ puts ' -H "Content-Type: application/json" \\'
216
+ puts ' -d \'{"model": "system-monitor-v1", "messages": [{"role": "user", "content": "What is the system status?"}]}\''
217
+ puts ""
218
+ puts "# Send an alert"
219
+ puts "curl -X POST http://localhost:8080/alert \\"
220
+ puts ' -H "Content-Type: application/json" \\'
221
+ puts ' -d \'{"id": "alert-001", "message": "High CPU usage detected", "severity": "warning"}\''
222
+ puts ""
223
+ puts "Press Ctrl+C to stop"
224
+ puts "=" * 80
225
+
226
+ LanguageOperator::Agent.run
227
+ end
@@ -0,0 +1,26 @@
1
+ # Pure Agent Definition (no Ruby setup code)
2
+ # This demonstrates that agents automatically get chat endpoints by default
3
+
4
+ agent "test-basic" do
5
+ description "Simple test agent to verify default chat endpoints"
6
+ mode :autonomous
7
+
8
+ # Simple task
9
+ task :do_work,
10
+ instructions: "Perform some basic work",
11
+ inputs: {},
12
+ outputs: {
13
+ message: 'string',
14
+ timestamp: 'string'
15
+ }
16
+
17
+ main do |inputs|
18
+ work_result = execute_task(:do_work)
19
+ work_result
20
+ end
21
+
22
+ constraints do
23
+ max_iterations 5 # Just run a few times for testing
24
+ timeout '10s'
25
+ end
26
+ end
@@ -433,8 +433,11 @@ module LanguageOperator
433
433
  # Build prompt from messages
434
434
  prompt = build_prompt_from_messages(messages)
435
435
 
436
- # Execute agent
437
- result = @chat_agent.execute(prompt)
436
+ # Execute agent using the correct method
437
+ result = @chat_agent.execute_goal(prompt)
438
+
439
+ # Extract content from result (handle both String and Message objects)
440
+ result_content = result.is_a?(String) ? result : result.content
438
441
 
439
442
  # Build OpenAI-compatible response
440
443
  {
@@ -447,15 +450,15 @@ module LanguageOperator
447
450
  index: 0,
448
451
  message: {
449
452
  role: 'assistant',
450
- content: result
453
+ content: result_content
451
454
  },
452
455
  finish_reason: 'stop'
453
456
  }
454
457
  ],
455
458
  usage: {
456
459
  prompt_tokens: estimate_tokens(prompt),
457
- completion_tokens: estimate_tokens(result),
458
- total_tokens: estimate_tokens(prompt) + estimate_tokens(result)
460
+ completion_tokens: estimate_tokens(result_content),
461
+ total_tokens: estimate_tokens(prompt) + estimate_tokens(result_content)
459
462
  }
460
463
  }
461
464
  end
@@ -159,11 +159,40 @@ module LanguageOperator
159
159
 
160
160
  case agent.mode
161
161
  when 'autonomous', 'interactive'
162
+ # Hybrid mode: All agents now run main work AND web server (chat endpoints always enabled)
163
+ logger.info('Starting hybrid agent (autonomous + web server)',
164
+ agent_name: agent_def.name,
165
+ chat_endpoint_enabled: true, # Always true now
166
+ has_webhooks: agent_def.webhooks.any?,
167
+ has_mcp_tools: !!(agent_def.mcp_server&.tools?))
168
+
169
+ # Start web server in background thread
170
+ web_server = LanguageOperator::Agent::WebServer.new(agent)
171
+ agent_def.webhooks.each { |webhook_def| webhook_def.register(web_server) }
172
+ web_server.register_mcp_tools(agent_def.mcp_server) if agent_def.mcp_server&.tools?
173
+ web_server.register_chat_endpoint(agent_def.chat_endpoint, agent) # Always register chat endpoint
174
+
175
+ web_thread = Thread.new do
176
+ web_server.start
177
+ rescue StandardError => e
178
+ logger.error('Web server error', error: e.message, backtrace: e.backtrace[0..5])
179
+ raise
180
+ end
181
+
182
+ # Set up signal handlers for graceful shutdown
183
+ %w[INT TERM].each do |signal|
184
+ Signal.trap(signal) do
185
+ logger.info('Received shutdown signal, stopping hybrid agent')
186
+ web_server.cleanup if web_server.respond_to?(:cleanup)
187
+ web_thread.kill if web_thread&.alive?
188
+ exit 0
189
+ end
190
+ end
191
+
192
+ # Run main work in foreground
162
193
  if uses_dsl_v1
163
- # DSL v1: Execute main block with task executor in persistent mode
164
194
  execute_main_block_persistent(agent, agent_def)
165
195
  elsif uses_dsl_v0
166
- # DSL v0: Execute workflow in autonomous mode
167
196
  executor = LanguageOperator::Agent::Executor.new(agent)
168
197
  executor.execute_workflow(agent_def)
169
198
  else
@@ -49,7 +49,7 @@ module LanguageOperator
49
49
  include LanguageOperator::Loggable
50
50
 
51
51
  attr_reader :name, :description, :persona, :schedule, :objectives, :main, :tasks,
52
- :constraints, :output_config, :execution_mode, :webhooks, :mcp_server, :chat_endpoint
52
+ :constraints, :output_config, :execution_mode, :webhooks, :mcp_server
53
53
 
54
54
  def initialize(name)
55
55
  @name = name
@@ -314,6 +314,16 @@ module LanguageOperator
314
314
  @mcp_server
315
315
  end
316
316
 
317
+ # Get chat endpoint definition (always available)
318
+ #
319
+ # Returns the chat endpoint definition. If none was explicitly configured,
320
+ # returns a default chat endpoint with basic configuration.
321
+ #
322
+ # @return [ChatEndpointDefinition] The chat endpoint definition
323
+ def chat_endpoint
324
+ @chat_endpoint ||= create_default_chat_endpoint
325
+ end
326
+
317
327
  # Define chat endpoint capabilities
318
328
  #
319
329
  # Allows this agent to respond to OpenAI-compatible chat completion requests.
@@ -324,7 +334,7 @@ module LanguageOperator
324
334
  def as_chat_endpoint(&block)
325
335
  @chat_endpoint ||= ChatEndpointDefinition.new(@name)
326
336
  @chat_endpoint.instance_eval(&block) if block
327
- @execution_mode = :reactive if @execution_mode == :autonomous
337
+ # Note: Don't force mode change - agents can be autonomous AND have chat endpoints
328
338
  @chat_endpoint
329
339
  end
330
340
 
@@ -353,6 +363,32 @@ module LanguageOperator
353
363
 
354
364
  private
355
365
 
366
+ # Create default chat endpoint configuration
367
+ #
368
+ # @return [ChatEndpointDefinition] Default chat endpoint
369
+ def create_default_chat_endpoint
370
+ endpoint = ChatEndpointDefinition.new(@name)
371
+
372
+ # Set default system prompt based on agent description
373
+ default_prompt = if @description
374
+ "You are #{@description.downcase}. Provide helpful assistance based on your capabilities."
375
+ else
376
+ "You are an AI agent named #{@name}. Provide helpful assistance to users."
377
+ end
378
+
379
+ endpoint.system_prompt(default_prompt)
380
+ endpoint.model(@name) # Use agent name as model name
381
+ endpoint.temperature(0.7) # Balanced default
382
+ endpoint.max_tokens(2000) # Reasonable default
383
+
384
+ logger.debug('Created default chat endpoint',
385
+ agent_name: @name,
386
+ model_name: @name,
387
+ system_prompt: default_prompt[0..100])
388
+
389
+ endpoint
390
+ end
391
+
356
392
  def logger_component
357
393
  "Agent:#{@name}"
358
394
  end
@@ -2,7 +2,7 @@
2
2
  :openapi: 3.0.3
3
3
  :info:
4
4
  :title: Language Operator Agent API
5
- :version: 0.1.65
5
+ :version: 0.1.70
6
6
  :description: HTTP API endpoints exposed by Language Operator reactive agents
7
7
  :contact:
8
8
  :name: Language Operator
@@ -3,7 +3,7 @@
3
3
  "$id": "https://github.com/language-operator/language-operator-gem/schema/agent-dsl.json",
4
4
  "title": "Language Operator Agent DSL",
5
5
  "description": "Schema for defining autonomous AI agents using the Language Operator DSL",
6
- "version": "0.1.65",
6
+ "version": "0.1.70",
7
7
  "type": "object",
8
8
  "properties": {
9
9
  "name": {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LanguageOperator
4
- VERSION = '0.1.66'
4
+ VERSION = '0.1.70'
5
5
  end
data/synth/003/Makefile CHANGED
@@ -27,17 +27,11 @@ inspect:
27
27
  learning-status:
28
28
  $(AICTL) learning status $(AGENT)
29
29
 
30
- learn:
31
- kubectl patch languageagent $(AGENT) --type='merge' -p='{"status":{"runsPendingLearning":10}}'
32
-
33
-
34
30
  logs:
35
31
  $(AICTL) logs $(AGENT)
36
32
 
37
33
  clean:
38
34
  $(AICTL) delete $(AGENT) --force
39
- kubectl delete configmaps -l app.kubernetes.io/name=$(AGENT) --ignore-not-found=true
40
- kubectl delete configmaps --field-selector metadata.name~=$(AGENT)-v --ignore-not-found=true
41
35
 
42
36
  save:
43
37
  $(AICTL) code $(AGENT) --raw > agent.rb
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: language-operator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.66
4
+ version: 0.1.70
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Ryan
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-12-09 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: mcp
@@ -65,6 +65,20 @@ dependencies:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: '1.3'
68
+ - !ruby/object:Gem::Dependency
69
+ name: json-schema
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '5.0'
68
82
  - !ruby/object:Gem::Dependency
69
83
  name: puma
70
84
  requirement: !ruby/object:Gem::Requirement
@@ -508,6 +522,9 @@ files:
508
522
  - docs/understanding-generated-code.md
509
523
  - docs/using-tools.md
510
524
  - docs/webhooks.md
525
+ - examples/chat_endpoint_agent.rb
526
+ - examples/hybrid_agent.rb
527
+ - examples/pure_agent_test.rb
511
528
  - examples/ux_helpers_demo.rb
512
529
  - lib/language_operator.rb
513
530
  - lib/language_operator/agent.rb
@@ -676,7 +693,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
676
693
  - !ruby/object:Gem::Version
677
694
  version: '0'
678
695
  requirements: []
679
- rubygems_version: 3.6.6
696
+ rubygems_version: 3.6.9
680
697
  specification_version: 4
681
698
  summary: Ruby SDK for Language Operator
682
699
  test_files: []