language-operator 0.1.30 → 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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/Gemfile.lock +1 -1
  4. data/Makefile +7 -2
  5. data/Rakefile +29 -0
  6. data/docs/dsl/SCHEMA_VERSION.md +250 -0
  7. data/docs/dsl/agent-reference.md +13 -0
  8. data/lib/language_operator/agent/safety/safe_executor.rb +12 -0
  9. data/lib/language_operator/cli/commands/agent.rb +54 -101
  10. data/lib/language_operator/cli/commands/cluster.rb +37 -1
  11. data/lib/language_operator/cli/commands/persona.rb +2 -5
  12. data/lib/language_operator/cli/commands/status.rb +5 -18
  13. data/lib/language_operator/cli/commands/system.rb +772 -0
  14. data/lib/language_operator/cli/formatters/code_formatter.rb +3 -7
  15. data/lib/language_operator/cli/formatters/log_formatter.rb +3 -5
  16. data/lib/language_operator/cli/formatters/progress_formatter.rb +3 -7
  17. data/lib/language_operator/cli/formatters/status_formatter.rb +37 -0
  18. data/lib/language_operator/cli/formatters/table_formatter.rb +10 -26
  19. data/lib/language_operator/cli/helpers/pastel_helper.rb +24 -0
  20. data/lib/language_operator/cli/main.rb +4 -0
  21. data/lib/language_operator/dsl/schema.rb +1102 -0
  22. data/lib/language_operator/dsl.rb +1 -0
  23. data/lib/language_operator/logger.rb +4 -4
  24. data/lib/language_operator/templates/README.md +23 -0
  25. data/lib/language_operator/templates/examples/agent_synthesis.tmpl +115 -0
  26. data/lib/language_operator/templates/examples/persona_distillation.tmpl +19 -0
  27. data/lib/language_operator/templates/schema/.gitkeep +0 -0
  28. data/lib/language_operator/templates/schema/CHANGELOG.md +93 -0
  29. data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +306 -0
  30. data/lib/language_operator/templates/schema/agent_dsl_schema.json +452 -0
  31. data/lib/language_operator/version.rb +1 -1
  32. data/requirements/tasks/iterate.md +2 -2
  33. metadata +13 -9
  34. data/examples/README.md +0 -569
  35. data/examples/agent_example.rb +0 -86
  36. data/examples/chat_endpoint_agent.rb +0 -118
  37. data/examples/github_webhook_agent.rb +0 -171
  38. data/examples/mcp_agent.rb +0 -158
  39. data/examples/oauth_callback_agent.rb +0 -296
  40. data/examples/stripe_webhook_agent.rb +0 -219
  41. data/examples/webhook_agent.rb +0 -80
@@ -1,118 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Example agent that exposes an OpenAI-compatible chat completion endpoint
5
- #
6
- # This demonstrates Phase 4: Agents as Chat Completion Endpoints
7
- # The agent can be used as a drop-in replacement for OpenAI's API
8
- #
9
- # Usage:
10
- # PORT=8080 ruby examples/chat_endpoint_agent.rb
11
- #
12
- # Test non-streaming:
13
- # curl -X POST http://localhost:8080/v1/chat/completions \
14
- # -H "Content-Type: application/json" \
15
- # -d '{
16
- # "model": "github-expert",
17
- # "messages": [{"role": "user", "content": "How do I create a PR?"}]
18
- # }'
19
- #
20
- # Test streaming:
21
- # curl -X POST http://localhost:8080/v1/chat/completions \
22
- # -H "Content-Type: application/json" \
23
- # -d '{
24
- # "model": "github-expert",
25
- # "messages": [{"role": "user", "content": "How do I create a PR?"}],
26
- # "stream": true
27
- # }'
28
- #
29
- # Test with OpenAI SDK:
30
- # require 'openai'
31
- # client = OpenAI::Client.new(
32
- # access_token: "not-needed",
33
- # uri_base: "http://localhost:8080/v1/"
34
- # )
35
- # response = client.chat(
36
- # parameters: {
37
- # model: "github-expert",
38
- # messages: [{role: "user", content: "How do I create a PR?"}]
39
- # }
40
- # )
41
-
42
- require 'bundler/setup'
43
- require 'language_operator'
44
- require 'language_operator/dsl'
45
-
46
- # Define an agent that acts as a GitHub expert LLM
47
- LanguageOperator::Dsl.define do
48
- agent 'github-expert' do
49
- description 'GitHub API and workflow expert'
50
- mode :reactive
51
-
52
- # Configure as an OpenAI-compatible chat endpoint
53
- as_chat_endpoint do
54
- system_prompt <<~PROMPT
55
- You are a GitHub expert assistant with deep knowledge of:
56
- - GitHub API and workflows
57
- - Pull requests, issues, and code review
58
- - GitHub Actions and CI/CD
59
- - Repository management and best practices
60
-
61
- Provide helpful, accurate answers about GitHub topics.
62
- Keep responses concise but informative.
63
- PROMPT
64
-
65
- # Model parameters
66
- model 'github-expert-v1'
67
- temperature 0.7
68
- max_tokens 2000
69
- end
70
-
71
- # Optionally, also expose as webhook
72
- webhook '/github/webhook' do
73
- method :post
74
- on_request do |_context|
75
- {
76
- status: 'received',
77
- message: 'GitHub webhook processed',
78
- chat_endpoint: '/v1/chat/completions'
79
- }
80
- end
81
- end
82
- end
83
- end
84
- # Get the agent definition and run it
85
- agent_def = LanguageOperator::Dsl.agent_registry.get('github-expert')
86
-
87
- if agent_def
88
- puts "Starting GitHub Expert agent on port #{ENV.fetch('PORT', '8080')}"
89
- puts
90
- puts 'OpenAI-Compatible Endpoints:'
91
- puts ' POST /v1/chat/completions - Chat completion (streaming & non-streaming)'
92
- puts ' GET /v1/models - List available models'
93
- puts
94
- puts 'Additional Endpoints:'
95
- puts ' GET /health - Health check'
96
- puts ' GET /ready - Readiness check'
97
- puts ' POST /github/webhook - GitHub webhook endpoint'
98
- puts
99
- puts 'Test with curl:'
100
- puts <<~CURL
101
- curl -X POST http://localhost:8080/v1/chat/completions \\
102
- -H "Content-Type: application/json" \\
103
- -d '{"model": "github-expert-v1", "messages": [{"role": "user", "content": "How do I create a PR?"}]}'
104
- CURL
105
- puts
106
- puts 'Test streaming:'
107
- puts <<~CURL
108
- curl -N -X POST http://localhost:8080/v1/chat/completions \\
109
- -H "Content-Type: application/json" \\
110
- -d '{"model": "github-expert-v1", "messages": [{"role": "user", "content": "Explain GitHub Actions"}], "stream": true}'
111
- CURL
112
- puts "\nPress Ctrl+C to stop\n\n"
113
-
114
- agent_def.run!
115
- else
116
- puts 'Error: Agent definition not found'
117
- exit 1
118
- end
@@ -1,171 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # GitHub Webhook Agent Example
5
- #
6
- # This example shows how to create an agent that receives GitHub webhook events
7
- # with proper signature verification for security.
8
- #
9
- # Setup:
10
- # 1. Set GITHUB_WEBHOOK_SECRET environment variable
11
- # 2. Configure GitHub webhook to send events to https://<agent-url>/github/events
12
- # 3. Select events you want to receive (e.g., pull_request, issues, push)
13
- #
14
- # GitHub webhook documentation:
15
- # https://docs.github.com/en/webhooks
16
-
17
- require 'bundler/setup'
18
- require 'language_operator'
19
-
20
- LanguageOperator::Dsl.define_agents do
21
- agent 'github-pr-reviewer' do
22
- description 'Automatically reviews pull requests and provides feedback'
23
-
24
- # Set to reactive mode to receive webhooks
25
- mode :reactive
26
-
27
- # GitHub Pull Request webhook
28
- webhook '/github/pull_request' do
29
- method :post
30
-
31
- # Verify GitHub webhook signature
32
- # GitHub sends signature in X-Hub-Signature-256 header
33
- # Format: "sha256=<signature>"
34
- authenticate do
35
- verify_signature(
36
- header: 'X-Hub-Signature-256',
37
- secret: ENV.fetch('GITHUB_WEBHOOK_SECRET', nil),
38
- algorithm: :sha256,
39
- prefix: 'sha256='
40
- )
41
- end
42
-
43
- # Validate request format
44
- require_content_type 'application/json'
45
- require_headers(
46
- 'X-GitHub-Event' => nil, # Just check presence, any value OK
47
- 'X-GitHub-Delivery' => nil
48
- )
49
-
50
- on_request do |context|
51
- event = JSON.parse(context[:body])
52
- action = event['action']
53
- pr = event['pull_request']
54
-
55
- case action
56
- when 'opened'
57
- handle_pr_opened(pr, context)
58
- when 'synchronize'
59
- handle_pr_updated(pr, context)
60
- when 'closed'
61
- handle_pr_closed(pr, context)
62
- else
63
- { status: 'ignored', action: action }
64
- end
65
- end
66
- end
67
-
68
- # GitHub Issue webhook
69
- webhook '/github/issues' do
70
- method :post
71
-
72
- authenticate do
73
- verify_signature(
74
- header: 'X-Hub-Signature-256',
75
- secret: ENV.fetch('GITHUB_WEBHOOK_SECRET', nil),
76
- algorithm: :sha256,
77
- prefix: 'sha256='
78
- )
79
- end
80
-
81
- require_content_type 'application/json'
82
-
83
- on_request do |context|
84
- event = JSON.parse(context[:body])
85
- action = event['action']
86
- issue = event['issue']
87
-
88
- case action
89
- when 'opened'
90
- {
91
- status: 'processed',
92
- message: "New issue: #{issue['title']}",
93
- issue_number: issue['number']
94
- }
95
- when 'labeled'
96
- {
97
- status: 'processed',
98
- message: "Issue labeled: #{event['label']['name']}"
99
- }
100
- else
101
- { status: 'ignored', action: action }
102
- end
103
- end
104
- end
105
-
106
- # GitHub Push webhook
107
- webhook '/github/push' do
108
- method :post
109
-
110
- authenticate do
111
- verify_signature(
112
- header: 'X-Hub-Signature-256',
113
- secret: ENV.fetch('GITHUB_WEBHOOK_SECRET', nil),
114
- algorithm: :sha256,
115
- prefix: 'sha256='
116
- )
117
- end
118
-
119
- require_content_type 'application/json'
120
-
121
- on_request do |context|
122
- event = JSON.parse(context[:body])
123
- ref = event['ref']
124
- commits = event['commits']
125
-
126
- {
127
- status: 'processed',
128
- message: "Received #{commits.length} commits on #{ref}",
129
- commits: commits.map { |c| c['message'] }
130
- }
131
- end
132
- end
133
- end
134
- end
135
-
136
- # Helper methods for PR handling
137
- def handle_pr_opened(pr, _context)
138
- {
139
- status: 'processed',
140
- action: 'pr_opened',
141
- pr_number: pr['number'],
142
- pr_title: pr['title'],
143
- pr_url: pr['html_url'],
144
- message: "Reviewing PR ##{pr['number']}: #{pr['title']}"
145
- }
146
- end
147
-
148
- def handle_pr_updated(pr, _context)
149
- {
150
- status: 'processed',
151
- action: 'pr_updated',
152
- pr_number: pr['number'],
153
- message: "PR ##{pr['number']} was updated"
154
- }
155
- end
156
-
157
- def handle_pr_closed(pr, _context)
158
- {
159
- status: 'processed',
160
- action: 'pr_closed',
161
- pr_number: pr['number'],
162
- merged: pr['merged'],
163
- message: "PR ##{pr['number']} was #{pr['merged'] ? 'merged' : 'closed'}"
164
- }
165
- end
166
-
167
- # Run the agent if this file is executed directly
168
- if __FILE__ == $PROGRAM_NAME
169
- agent = LanguageOperator::Dsl.agent_registry.get('github-pr-reviewer')
170
- agent.run!
171
- end
@@ -1,158 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # Example agent that exposes tools via MCP protocol
5
- #
6
- # This demonstrates Phase 3: Agents as MCP Servers
7
- # The agent exposes tools that other agents or MCP clients can call
8
- #
9
- # Usage:
10
- # PORT=8080 ruby examples/mcp_agent.rb
11
- #
12
- # Test MCP protocol:
13
- # curl -X POST http://localhost:8080/mcp \
14
- # -H "Content-Type: application/json" \
15
- # -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'
16
- #
17
- # Test webhook:
18
- # curl -X POST http://localhost:8080/webhook \
19
- # -H "Content-Type: application/json" \
20
- # -d '{"message": "test"}'
21
-
22
- require 'bundler/setup'
23
- require 'language_operator'
24
- require 'language_operator/dsl'
25
-
26
- # Define an agent that acts as both a webhook receiver and MCP server
27
- # rubocop:disable Metrics/BlockLength
28
- LanguageOperator::Dsl.define do
29
- agent 'data-processor-mcp' do
30
- description 'Data processing agent that exposes MCP tools'
31
- mode :reactive
32
-
33
- # Define tools this agent exposes via MCP
34
- as_mcp_server do
35
- # Tool 1: Process CSV data
36
- tool 'process_csv' do
37
- description 'Process CSV data and return summary statistics'
38
-
39
- parameter :csv_data do
40
- type :string
41
- required true
42
- description 'CSV data as string'
43
- end
44
-
45
- execute do |params|
46
- # Simple CSV processing example
47
- lines = params['csv_data'].split("\n")
48
- headers = lines.first&.split(',') || []
49
- data_rows = lines[1..]
50
-
51
- {
52
- total_rows: data_rows&.length || 0,
53
- total_columns: headers.length,
54
- headers: headers,
55
- sample: data_rows&.first || ''
56
- }.to_json
57
- end
58
- end
59
-
60
- # Tool 2: Calculate statistics
61
- tool 'calculate_stats' do
62
- description 'Calculate basic statistics for a list of numbers'
63
-
64
- parameter :numbers do
65
- type :array
66
- required true
67
- description 'Array of numbers'
68
- end
69
-
70
- execute do |params|
71
- nums = params['numbers']
72
- return { error: 'Empty array' }.to_json if nums.empty?
73
-
74
- sum = nums.sum
75
- mean = sum.to_f / nums.length
76
- sorted = nums.sort
77
- median = if nums.length.odd?
78
- sorted[nums.length / 2]
79
- else
80
- (sorted[(nums.length / 2) - 1] + sorted[nums.length / 2]) / 2.0
81
- end
82
-
83
- {
84
- count: nums.length,
85
- sum: sum,
86
- mean: mean,
87
- median: median,
88
- min: nums.min,
89
- max: nums.max
90
- }.to_json
91
- end
92
- end
93
-
94
- # Tool 3: Format data
95
- tool 'format_json' do
96
- description 'Format and validate JSON data'
97
-
98
- parameter :json_string do
99
- type :string
100
- required true
101
- description 'JSON string to format'
102
- end
103
-
104
- parameter :indent do
105
- type :number
106
- required false
107
- description 'Indentation spaces (default: 2)'
108
- end
109
-
110
- execute do |params|
111
- indent = params['indent'] || 2
112
- parsed = JSON.parse(params['json_string'])
113
- JSON.pretty_generate(parsed, indent: ' ' * indent.to_i)
114
- rescue JSON::ParserError => e
115
- { error: "Invalid JSON: #{e.message}" }.to_json
116
- end
117
- end
118
- end
119
-
120
- # Also expose a webhook endpoint
121
- webhook '/process' do
122
- method :post
123
- on_request do |_context|
124
- {
125
- status: 'processed',
126
- message: 'Data received for processing',
127
- tools_available: 3,
128
- mcp_endpoint: '/mcp'
129
- }
130
- end
131
- end
132
- end
133
- end
134
- # rubocop:enable Metrics/BlockLength
135
-
136
- # Get the agent definition and run it
137
- agent_def = LanguageOperator::Dsl.agent_registry.get('data-processor-mcp')
138
-
139
- if agent_def
140
- puts "Starting MCP agent on port #{ENV.fetch('PORT', '8080')}"
141
- puts 'Available endpoints:'
142
- puts ' GET /health - Health check'
143
- puts ' GET /ready - Readiness check'
144
- puts ' POST /webhook - Webhook endpoint'
145
- puts ' POST /process - Data processing endpoint'
146
- puts ' POST /mcp - MCP protocol endpoint'
147
- puts
148
- puts 'MCP Tools:'
149
- puts ' - process_csv - Process CSV data'
150
- puts ' - calculate_stats - Calculate statistics'
151
- puts ' - format_json - Format JSON data'
152
- puts "\nPress Ctrl+C to stop\n\n"
153
-
154
- agent_def.run!
155
- else
156
- puts 'Error: Agent definition not found'
157
- exit 1
158
- end