language-operator 0.1.47 → 0.1.49
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/Gemfile.lock +1 -1
- data/lib/language_operator/agent/task_executor.rb +33 -9
- data/lib/language_operator/cli/commands/agent.rb +3 -3
- data/lib/language_operator/cli/commands/system.rb +7 -2
- data/lib/language_operator/templates/agent_synthesis.tmpl +6 -0
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +1 -1
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +1 -1
- data/lib/language_operator/version.rb +1 -1
- data/synth/002/agent.rb +3 -4
- data/synth/002/output.log +10 -10
- data/synth/README.md +5 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d89b743075960db9dd988ae5f887180b8516d195957926e51ab4b89d8a196d52
|
|
4
|
+
data.tar.gz: cc225f6a8b35c482b67f23089011cf54d52317773f6fbbfc4cd1b5c07bf4ccd2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 616074e08d5e3910920bebdcab8cc0896edc196561497864706c054ef5ffd7a3a304bdb37d163e47ce461a60f228257977e081c38de074c4a22a3ff5732d57a0
|
|
7
|
+
data.tar.gz: e24978393c2a38de8f0fecd130d3cad25507f6373a46a1e2d11db0af3d72f76e3a4d92f87c8337198cd5267c4f4fb5770f13d640019d4ac8905bceb6974e931f
|
data/Gemfile.lock
CHANGED
|
@@ -153,15 +153,23 @@ module LanguageOperator
|
|
|
153
153
|
# Build prompt for LLM
|
|
154
154
|
prompt = build_neural_prompt(task, validated_inputs)
|
|
155
155
|
|
|
156
|
+
logger.info('Sending prompt to LLM',
|
|
157
|
+
task: task.name,
|
|
158
|
+
prompt_length: prompt.length)
|
|
159
|
+
|
|
156
160
|
# Execute LLM call within traced span
|
|
157
161
|
outputs = tracer.in_span('gen_ai.chat', attributes: neural_task_attributes(task, prompt, validated_inputs)) do |span|
|
|
158
162
|
# Call LLM with full tool access
|
|
159
163
|
response = @agent.send_message(prompt)
|
|
164
|
+
|
|
165
|
+
logger.info('LLM response received, extracting content',
|
|
166
|
+
task: task.name)
|
|
167
|
+
|
|
160
168
|
response_text = response.is_a?(String) ? response : response.content
|
|
161
169
|
|
|
162
|
-
logger.
|
|
163
|
-
|
|
164
|
-
|
|
170
|
+
logger.info('Neural task response received',
|
|
171
|
+
task: task.name,
|
|
172
|
+
response_length: response_text.length)
|
|
165
173
|
|
|
166
174
|
# Record token usage and response metadata
|
|
167
175
|
record_token_usage(response, span)
|
|
@@ -169,18 +177,28 @@ module LanguageOperator
|
|
|
169
177
|
# Record tool calls if available
|
|
170
178
|
record_tool_calls(response, span)
|
|
171
179
|
|
|
180
|
+
logger.info('Parsing neural task response',
|
|
181
|
+
task: task.name)
|
|
182
|
+
|
|
172
183
|
# Parse response within child span
|
|
173
184
|
parsed_outputs = tracer.in_span('task_executor.parse_response') do |parse_span|
|
|
174
185
|
record_parse_metadata(response_text, parse_span)
|
|
175
186
|
parse_neural_response(response_text, task)
|
|
176
187
|
end
|
|
177
188
|
|
|
189
|
+
logger.info('Response parsed successfully',
|
|
190
|
+
task: task.name,
|
|
191
|
+
output_keys: parsed_outputs.keys)
|
|
192
|
+
|
|
178
193
|
# Record output metadata
|
|
179
194
|
record_output_metadata(parsed_outputs, span)
|
|
180
195
|
|
|
181
196
|
parsed_outputs
|
|
182
197
|
end
|
|
183
198
|
|
|
199
|
+
logger.info('Validating task outputs',
|
|
200
|
+
task: task.name)
|
|
201
|
+
|
|
184
202
|
# Validate outputs against schema
|
|
185
203
|
task.validate_outputs(outputs)
|
|
186
204
|
end
|
|
@@ -288,7 +306,10 @@ module LanguageOperator
|
|
|
288
306
|
end
|
|
289
307
|
prompt += "\n"
|
|
290
308
|
|
|
291
|
-
prompt +=
|
|
309
|
+
prompt += "## Response Format\n"
|
|
310
|
+
prompt += "Return ONLY valid JSON matching the output schema above.\n"
|
|
311
|
+
prompt += "Do NOT include any explanations, thinking, or text before or after the JSON.\n"
|
|
312
|
+
prompt += "Do NOT use [THINK] tags or any other markup.\n"
|
|
292
313
|
prompt += "Use available tools as needed to complete the task.\n"
|
|
293
314
|
|
|
294
315
|
prompt
|
|
@@ -301,15 +322,18 @@ module LanguageOperator
|
|
|
301
322
|
# @return [Hash] Parsed outputs
|
|
302
323
|
# @raise [RuntimeError] If parsing fails
|
|
303
324
|
def parse_neural_response(response_text, task)
|
|
325
|
+
# Strip thinking tags that some models add (e.g., [THINK]...[/THINK])
|
|
326
|
+
cleaned_text = response_text.gsub(%r{\[THINK\].*?\[/THINK\]}m, '').strip
|
|
327
|
+
|
|
304
328
|
# Try to extract JSON from response
|
|
305
329
|
# Look for JSON code blocks first
|
|
306
|
-
json_match =
|
|
330
|
+
json_match = cleaned_text.match(/```json\s*\n(.*?)\n```/m)
|
|
307
331
|
json_text = if json_match
|
|
308
332
|
json_match[1]
|
|
309
333
|
else
|
|
310
334
|
# Try to find raw JSON object
|
|
311
|
-
json_object_match =
|
|
312
|
-
json_object_match ? json_object_match[0] :
|
|
335
|
+
json_object_match = cleaned_text.match(/\{.*\}/m)
|
|
336
|
+
json_object_match ? json_object_match[0] : cleaned_text
|
|
313
337
|
end
|
|
314
338
|
|
|
315
339
|
# Parse JSON
|
|
@@ -343,8 +367,8 @@ module LanguageOperator
|
|
|
343
367
|
def default_config
|
|
344
368
|
{
|
|
345
369
|
timeout_symbolic: 30.0, # Default timeout for symbolic tasks (seconds)
|
|
346
|
-
timeout_neural:
|
|
347
|
-
timeout_hybrid:
|
|
370
|
+
timeout_neural: 240.0, # Default timeout for neural tasks (seconds)
|
|
371
|
+
timeout_hybrid: 240.0, # Default timeout for hybrid tasks (seconds)
|
|
348
372
|
max_retries: 3, # Default max retry attempts
|
|
349
373
|
retry_delay_base: 1.0, # Base delay for exponential backoff
|
|
350
374
|
retry_delay_max: 10.0 # Maximum delay between retries
|
|
@@ -292,18 +292,18 @@ module LanguageOperator
|
|
|
292
292
|
label_selector = "app.kubernetes.io/name=#{name}"
|
|
293
293
|
|
|
294
294
|
# Use kubectl logs with label selector
|
|
295
|
-
cmd = "#{ctx.kubectl_prefix} logs -l #{label_selector} #{tail_arg} #{follow_arg} --
|
|
295
|
+
cmd = "#{ctx.kubectl_prefix} logs -l #{label_selector} #{tail_arg} #{follow_arg} --all-containers"
|
|
296
296
|
|
|
297
297
|
Formatters::ProgressFormatter.info("Streaming logs for agent '#{name}'...")
|
|
298
298
|
puts
|
|
299
299
|
|
|
300
|
-
# Stream
|
|
300
|
+
# Stream raw logs in real-time without formatting
|
|
301
301
|
require 'open3'
|
|
302
302
|
Open3.popen3(cmd) do |_stdin, stdout, stderr, wait_thr|
|
|
303
303
|
# Handle stdout (logs)
|
|
304
304
|
stdout_thread = Thread.new do
|
|
305
305
|
stdout.each_line do |line|
|
|
306
|
-
puts
|
|
306
|
+
puts line
|
|
307
307
|
$stdout.flush
|
|
308
308
|
end
|
|
309
309
|
end
|
|
@@ -1078,6 +1078,11 @@ module LanguageOperator
|
|
|
1078
1078
|
# Detect available models in the cluster
|
|
1079
1079
|
model_env = detect_model_config
|
|
1080
1080
|
|
|
1081
|
+
if model_env.nil?
|
|
1082
|
+
Formatters::ProgressFormatter.warn('Could not detect model configuration from cluster')
|
|
1083
|
+
Formatters::ProgressFormatter.warn('Agent may fail without MODEL_ENDPOINTS configured')
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1081
1086
|
env_vars = [
|
|
1082
1087
|
{ 'name' => 'AGENT_NAME', 'value' => name },
|
|
1083
1088
|
{ 'name' => 'AGENT_MODE', 'value' => 'autonomous' },
|
|
@@ -1148,8 +1153,8 @@ module LanguageOperator
|
|
|
1148
1153
|
{ 'name' => 'LLM_MODEL', 'value' => model_id },
|
|
1149
1154
|
{ 'name' => 'OPENAI_API_KEY', 'value' => 'sk-dummy-key-for-local-proxy' }
|
|
1150
1155
|
]
|
|
1151
|
-
rescue StandardError
|
|
1152
|
-
|
|
1156
|
+
rescue StandardError => e
|
|
1157
|
+
Formatters::ProgressFormatter.error("Failed to detect model configuration: #{e.message}")
|
|
1153
1158
|
nil
|
|
1154
1159
|
end
|
|
1155
1160
|
|
|
@@ -86,6 +86,8 @@ Study these examples to understand the task/main model with organic functions:
|
|
|
86
86
|
|
|
87
87
|
### Example 1: Simple Scheduled Agent (Fully Neural)
|
|
88
88
|
```ruby
|
|
89
|
+
require 'language_operator'
|
|
90
|
+
|
|
89
91
|
agent "daily-report" do
|
|
90
92
|
description "Generate daily sales report"
|
|
91
93
|
mode :scheduled
|
|
@@ -115,6 +117,8 @@ end
|
|
|
115
117
|
|
|
116
118
|
### Example 2: Hybrid Neural-Symbolic Agent
|
|
117
119
|
```ruby
|
|
120
|
+
require 'language_operator'
|
|
121
|
+
|
|
118
122
|
agent "code-reviewer" do
|
|
119
123
|
description "Review pull requests"
|
|
120
124
|
|
|
@@ -148,6 +152,8 @@ end
|
|
|
148
152
|
|
|
149
153
|
### Example 3: Multi-Step Agent with Tools
|
|
150
154
|
```ruby
|
|
155
|
+
require 'language_operator'
|
|
156
|
+
|
|
151
157
|
agent "data-pipeline" do
|
|
152
158
|
description "ETL pipeline"
|
|
153
159
|
|
|
@@ -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.
|
|
6
|
+
"version": "0.1.49",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {
|
|
9
9
|
"name": {
|
data/synth/002/agent.rb
CHANGED
|
@@ -7,14 +7,13 @@ agent 'test-agent' do
|
|
|
7
7
|
mode :scheduled
|
|
8
8
|
schedule '*/10 * * * *'
|
|
9
9
|
|
|
10
|
-
task :
|
|
11
|
-
instructions: 'Generate a random fortune
|
|
10
|
+
task :tell_fortune,
|
|
11
|
+
instructions: 'Generate a random fortune message',
|
|
12
12
|
inputs: {},
|
|
13
13
|
outputs: { fortune: 'string' }
|
|
14
14
|
|
|
15
15
|
main do |_inputs|
|
|
16
|
-
|
|
17
|
-
{ fortune: fortune_data[:fortune] }
|
|
16
|
+
execute_task(:tell_fortune)
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
output do |outputs|
|
data/synth/002/output.log
CHANGED
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
[1;36m⚬[0m Chat session initialized (with_tools=false)
|
|
6
6
|
[1;36m⚬[0m Executing main block (agent=test-agent, task_count=1)
|
|
7
7
|
[1;36m⚬[0m Executing main block (inputs_keys=[])
|
|
8
|
-
[1;36m⚬[0m Executing task (task=
|
|
9
|
-
[1;33m⚠[0m Task execution timed out (task=
|
|
10
|
-
[1;31m✗[0m Task execution failed (task=
|
|
11
|
-
[1;31m✗[0m Task execution failed (task=
|
|
12
|
-
[1;31m✗[0m Main block execution failed (error=LanguageOperator::Agent::TaskTimeoutError, message=Task '
|
|
13
|
-
Error loading agent code: Task '
|
|
14
|
-
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.
|
|
15
|
-
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.
|
|
16
|
-
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.
|
|
17
|
-
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.
|
|
8
|
+
[1;36m⚬[0m Executing task (task=tell_fortune, type=neural, timeout=120.0, max_retries=3)
|
|
9
|
+
[1;33m⚠[0m Task execution timed out (task=tell_fortune, attempt=1, timeout=120.0, execution_time=120.001)
|
|
10
|
+
[1;31m✗[0m Task execution failed (task=tell_fortune, error_category=TIMEOUT, error_class=LanguageOperator::Agent::TaskTimeoutError, error_message=Task 'tell_fortune' execution failed: timed out after 120.0s, execution_time=120.001, retry_count=0, retryable=false, backtrace=["/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:481:in 'LanguageOperator::Agent::TaskExecutor#execute_single_attempt'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:414:in 'LanguageOperator::Agent::TaskExecutor#execute_with_retry'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:126:in 'block in LanguageOperator::Agent::TaskExecutor#execute_task'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/instrumentation.rb:45:in 'block in LanguageOperator::Agent::Instrumentation#with_span'", "/usr/lib/ruby/gems/3.4.0/gems/opentelemetry-api-1.7.0/lib/opentelemetry/trace/tracer.rb:37:in 'block in OpenTelemetry::Trace::Tracer#in_span'"])
|
|
11
|
+
[1;31m✗[0m Task execution failed (task=tell_fortune, error_category=SYSTEM, error_class=LanguageOperator::Agent::TaskTimeoutError, error_message=Task 'tell_fortune' execution failed: timed out after 120.0s, execution_time=120.001, retry_count=0, retryable=false, backtrace=["/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:481:in 'LanguageOperator::Agent::TaskExecutor#execute_single_attempt'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:414:in 'LanguageOperator::Agent::TaskExecutor#execute_with_retry'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:126:in 'block in LanguageOperator::Agent::TaskExecutor#execute_task'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/instrumentation.rb:45:in 'block in LanguageOperator::Agent::Instrumentation#with_span'", "/usr/lib/ruby/gems/3.4.0/gems/opentelemetry-api-1.7.0/lib/opentelemetry/trace/tracer.rb:37:in 'block in OpenTelemetry::Trace::Tracer#in_span'"])
|
|
12
|
+
[1;31m✗[0m Main block execution failed (error=LanguageOperator::Agent::TaskTimeoutError, message=Task 'tell_fortune' execution failed: timed out after 120.0s, backtrace=["/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:481:in 'LanguageOperator::Agent::TaskExecutor#execute_single_attempt'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:414:in 'LanguageOperator::Agent::TaskExecutor#execute_with_retry'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:126:in 'block in LanguageOperator::Agent::TaskExecutor#execute_task'", "/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/instrumentation.rb:45:in 'block in LanguageOperator::Agent::Instrumentation#with_span'", "/usr/lib/ruby/gems/3.4.0/gems/opentelemetry-api-1.7.0/lib/opentelemetry/trace/tracer.rb:37:in 'block in OpenTelemetry::Trace::Tracer#in_span'"])
|
|
13
|
+
Error loading agent code: Task 'tell_fortune' execution failed: timed out after 120.0s
|
|
14
|
+
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:481:in 'LanguageOperator::Agent::TaskExecutor#execute_single_attempt'
|
|
15
|
+
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:414:in 'LanguageOperator::Agent::TaskExecutor#execute_with_retry'
|
|
16
|
+
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/task_executor.rb:126:in 'block in LanguageOperator::Agent::TaskExecutor#execute_task'
|
|
17
|
+
/usr/lib/ruby/gems/3.4.0/gems/language-operator-0.1.48/lib/language_operator/agent/instrumentation.rb:45:in 'block in LanguageOperator::Agent::Instrumentation#with_span'
|
|
18
18
|
/usr/lib/ruby/gems/3.4.0/gems/opentelemetry-api-1.7.0/lib/opentelemetry/trace/tracer.rb:37:in 'block in OpenTelemetry::Trace::Tracer#in_span'
|
|
19
19
|
No fallback configured, exiting
|
|
20
20
|
[31m✗ Agent failed with exit code: 1[0m
|
data/synth/README.md
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: language-operator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.49
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Ryan
|
|
@@ -572,6 +572,7 @@ files:
|
|
|
572
572
|
- synth/002/agent.rb
|
|
573
573
|
- synth/002/agent.txt
|
|
574
574
|
- synth/002/output.log
|
|
575
|
+
- synth/README.md
|
|
575
576
|
homepage: https://github.com/language-operator/language-operator
|
|
576
577
|
licenses:
|
|
577
578
|
- FSL-1.1-Apache-2.0
|