ox-ai-workers 0.8.6 → 0.9.1
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/.cursorrules +88 -2
- data/CHANGELOG.md +20 -8
- data/README.md +135 -38
- data/config/locales/en.oxaiworkers.assistant.yml +39 -5
- data/config/locales/en.oxaiworkers.iterator.yml +1 -9
- data/config/locales/en.oxaiworkers.tool.yml +16 -1
- data/config/locales/ru.oxaiworkers.assistant.yml +39 -5
- data/config/locales/ru.oxaiworkers.iterator.yml +2 -11
- data/config/locales/ru.oxaiworkers.tool.yml +16 -1
- data/lib/ox-ai-workers.rb +16 -6
- data/lib/oxaiworkers/assistant/coder.rb +16 -8
- data/lib/oxaiworkers/assistant/localizer.rb +16 -9
- data/lib/oxaiworkers/assistant/module_base.rb +14 -5
- data/lib/oxaiworkers/assistant/orchestrator.rb +44 -0
- data/lib/oxaiworkers/assistant/painter.rb +37 -0
- data/lib/oxaiworkers/assistant/sysop.rb +15 -7
- data/lib/oxaiworkers/delayed_request.rb +2 -2
- data/lib/oxaiworkers/image_iterator.rb +41 -0
- data/lib/oxaiworkers/iterator.rb +34 -54
- data/lib/oxaiworkers/models/deepseek_max.rb +16 -0
- data/lib/oxaiworkers/models/module_base.rb +17 -0
- data/lib/oxaiworkers/models/openai_max.rb +15 -0
- data/lib/oxaiworkers/models/openai_mini.rb +12 -0
- data/lib/oxaiworkers/models/openai_nano.rb +12 -0
- data/lib/oxaiworkers/module_request.rb +50 -45
- data/lib/oxaiworkers/tool/eval.rb +19 -8
- data/lib/oxaiworkers/tool/file_system.rb +30 -15
- data/lib/oxaiworkers/tool/pipeline.rb +106 -0
- data/lib/oxaiworkers/tool/pixels.rb +76 -0
- data/lib/oxaiworkers/version.rb +1 -1
- data/template/start +4 -6
- metadata +11 -1
@@ -2,23 +2,19 @@
|
|
2
2
|
|
3
3
|
module OxAiWorkers
|
4
4
|
class ModuleRequest
|
5
|
-
attr_accessor :result, :client, :messages, :model, :
|
6
|
-
:tool_calls_raw, :tool_calls, :is_truncated, :finish_reason, :
|
5
|
+
attr_accessor :result, :client, :messages, :model, :custom_id, :tools, :errors,
|
6
|
+
:tool_calls_raw, :tool_calls, :is_truncated, :finish_reason, :on_stream_proc
|
7
7
|
|
8
|
-
def initialize_requests(model
|
9
|
-
@max_tokens = max_tokens || OxAiWorkers.configuration.max_tokens
|
8
|
+
def initialize_requests(model:, on_stream: nil)
|
10
9
|
@custom_id = SecureRandom.uuid
|
11
|
-
@model = model
|
12
|
-
@temperature = temperature || OxAiWorkers.configuration.temperature
|
13
|
-
@uri_base = uri_base
|
10
|
+
@model = model
|
14
11
|
@client = nil
|
15
12
|
@is_truncated = false
|
16
13
|
@finish_reason = nil
|
17
14
|
@on_stream_proc = on_stream
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
error_text = 'OpenAi access token missing!'
|
16
|
+
if @model.api_key.nil?
|
17
|
+
error_text = "#{@model.model} access token missing!"
|
22
18
|
raise OxAiWorkers::ConfigurationError, error_text
|
23
19
|
end
|
24
20
|
|
@@ -27,8 +23,8 @@ module OxAiWorkers
|
|
27
23
|
|
28
24
|
def cleanup
|
29
25
|
@client ||= OpenAI::Client.new(
|
30
|
-
access_token:
|
31
|
-
uri_base: @
|
26
|
+
access_token: @model.api_key,
|
27
|
+
uri_base: @model.uri_base,
|
32
28
|
log_errors: true # Highly recommended in development, so you can see what errors OpenAI is returning. Not recommended in production because it could leak private data to your logs.
|
33
29
|
)
|
34
30
|
@result = nil
|
@@ -47,10 +43,10 @@ module OxAiWorkers
|
|
47
43
|
|
48
44
|
def params
|
49
45
|
parameters = {
|
50
|
-
model: @model,
|
46
|
+
model: @model.model,
|
51
47
|
messages: @messages,
|
52
|
-
temperature: @temperature,
|
53
|
-
max_tokens: @max_tokens
|
48
|
+
temperature: @model.temperature,
|
49
|
+
max_tokens: @model.max_tokens
|
54
50
|
}
|
55
51
|
if @tools.present?
|
56
52
|
parameters[:tools] = @tools
|
@@ -81,53 +77,62 @@ module OxAiWorkers
|
|
81
77
|
return if choices.nil? || choices.empty?
|
82
78
|
|
83
79
|
choices.each do |choice|
|
80
|
+
# Parse basic info and accumulate raw tool calls
|
84
81
|
parse_one_choice(choice)
|
85
82
|
end
|
86
83
|
|
87
|
-
#
|
88
|
-
|
84
|
+
# Only parse tool calls if the response wasn't truncated
|
85
|
+
_parse_tool_calls unless @is_truncated || @tool_calls_raw.empty?
|
89
86
|
end
|
90
87
|
|
91
88
|
def parse_one_choice(choice)
|
92
89
|
message = choice['message']
|
93
90
|
return unless message # Skip if there's no message in this choice
|
94
91
|
|
95
|
-
# Accumulate raw tool calls
|
96
|
-
if message['tool_calls']
|
97
|
-
@tool_calls_raw.concat(message['tool_calls'])
|
98
|
-
message['tool_calls'].each do |tool_call|
|
99
|
-
next unless tool_call['type'] == 'function' # Ensure it's a function call
|
100
|
-
|
101
|
-
function = tool_call['function']
|
102
|
-
next unless function && function['name'] && function['arguments']
|
103
|
-
|
104
|
-
begin
|
105
|
-
# Attempt to parse arguments, handle potential JSON errors
|
106
|
-
args = JSON.parse(function['arguments'], symbolize_names: true)
|
107
|
-
rescue JSON::ParserError => e
|
108
|
-
OxAiWorkers.logger.error("Failed to parse tool call arguments: #{e.message}", for: self.class)
|
109
|
-
OxAiWorkers.logger.debug("Raw arguments: #{function['arguments']}", for: self.class)
|
110
|
-
args = {} # Assign empty args or handle error as appropriate
|
111
|
-
end
|
112
|
-
|
113
|
-
# Accumulate parsed tool calls
|
114
|
-
@tool_calls << {
|
115
|
-
class: function['name'].split('__').first,
|
116
|
-
name: function['name'].split('__').last,
|
117
|
-
args: args
|
118
|
-
}
|
119
|
-
end
|
120
|
-
end
|
92
|
+
# Accumulate raw tool calls if present
|
93
|
+
@tool_calls_raw.concat(message['tool_calls']) if message['tool_calls']
|
121
94
|
|
122
95
|
# Update result with the content if present
|
123
96
|
current_result = message['content']
|
124
97
|
@result = current_result if current_result.present?
|
125
98
|
|
126
|
-
# Update finish reason and truncation status
|
99
|
+
# Update finish reason and truncation status based on the *last* choice's reason
|
127
100
|
current_finish_reason = choice['finish_reason']
|
128
101
|
if current_finish_reason.present?
|
129
102
|
@finish_reason = current_finish_reason
|
130
|
-
@is_truncated = @finish_reason == 'length'
|
103
|
+
@is_truncated = (@finish_reason == 'length')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# Parses the accumulated raw tool calls into the structured @tool_calls array.
|
110
|
+
# This should only be called after confirming the response is not truncated.
|
111
|
+
def _parse_tool_calls
|
112
|
+
@tool_calls = [] # Ensure it's clean before parsing
|
113
|
+
@tool_calls_raw.each do |tool_call|
|
114
|
+
next unless tool_call['type'] == 'function' # Ensure it's a function call
|
115
|
+
|
116
|
+
function = tool_call['function']
|
117
|
+
next unless function && function['name'] && function['arguments']
|
118
|
+
|
119
|
+
begin
|
120
|
+
# Attempt to parse arguments, handle potential JSON errors
|
121
|
+
args = JSON.parse(function['arguments'], symbolize_names: true)
|
122
|
+
rescue JSON::ParserError => e
|
123
|
+
OxAiWorkers.logger.error("Failed to parse tool call arguments: #{e.message}", for: self.class)
|
124
|
+
OxAiWorkers.logger.debug("Raw arguments: #{function['arguments']}", for: self.class)
|
125
|
+
# Decide how to handle parsing errors, e.g., skip this call or add with empty args
|
126
|
+
# Skipping for now, as partial args are likely useless.
|
127
|
+
next
|
128
|
+
end
|
129
|
+
|
130
|
+
# Accumulate parsed tool calls
|
131
|
+
@tool_calls << {
|
132
|
+
class: function['name'].split('__').first,
|
133
|
+
name: function['name'].split('__').last,
|
134
|
+
args: args
|
135
|
+
}
|
131
136
|
end
|
132
137
|
end
|
133
138
|
end
|
@@ -9,10 +9,13 @@ module OxAiWorkers
|
|
9
9
|
include OxAiWorkers::DependencyHelper
|
10
10
|
include OxAiWorkers::LoadI18n
|
11
11
|
|
12
|
-
|
12
|
+
attr_accessor :current_dir
|
13
|
+
|
14
|
+
def initialize(only: nil, current_dir: nil)
|
13
15
|
store_locale
|
14
16
|
|
15
17
|
init_white_list_with only
|
18
|
+
@current_dir = current_dir
|
16
19
|
|
17
20
|
define_function :ruby, description: I18n.t('oxaiworkers.tool.eval.ruby.description') do
|
18
21
|
property :input, type: 'string', description: I18n.t('oxaiworkers.tool.eval.ruby.input'), required: true
|
@@ -25,20 +28,28 @@ module OxAiWorkers
|
|
25
28
|
|
26
29
|
def ruby(input:)
|
27
30
|
OxAiWorkers.logger.info("Executing ruby: \"#{input}\"", for: self.class)
|
28
|
-
eval(input)
|
31
|
+
execute_in_directory { eval(input) }
|
29
32
|
end
|
30
33
|
|
31
34
|
def sh(input:)
|
32
35
|
OxAiWorkers.logger.info("Executing sh: \"#{input}\"", for: self.class)
|
33
|
-
|
36
|
+
execute_in_directory do
|
34
37
|
stdout_and_stderr_s, status = Open3.capture2e(input)
|
35
|
-
|
38
|
+
stdout_and_stderr_s.present? ? stdout_and_stderr_s : status.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
def execute_in_directory(&block)
|
45
|
+
if @current_dir.present?
|
46
|
+
Dir.chdir(@current_dir, &block)
|
47
|
+
else
|
48
|
+
yield
|
41
49
|
end
|
50
|
+
rescue StandardError => e
|
51
|
+
OxAiWorkers.logger.debug(e.message, for: self.class)
|
52
|
+
e.message
|
42
53
|
end
|
43
54
|
end
|
44
55
|
end
|
@@ -15,7 +15,9 @@ module OxAiWorkers
|
|
15
15
|
include OxAiWorkers::DependencyHelper
|
16
16
|
include OxAiWorkers::LoadI18n
|
17
17
|
|
18
|
-
|
18
|
+
attr_accessor :current_dir
|
19
|
+
|
20
|
+
def initialize(current_dir: nil, only: nil)
|
19
21
|
depends_on 'ptools'
|
20
22
|
|
21
23
|
store_locale
|
@@ -40,38 +42,51 @@ module OxAiWorkers
|
|
40
42
|
property :content, type: 'string', description: I18n.t('oxaiworkers.tool.file_system.write_to_file.content'),
|
41
43
|
required: true
|
42
44
|
end
|
45
|
+
|
46
|
+
@current_dir = current_dir
|
43
47
|
end
|
44
48
|
|
45
49
|
def list_directory(directory_path:)
|
46
|
-
|
47
|
-
|
50
|
+
path = full_path(directory_path)
|
51
|
+
OxAiWorkers.logger.info("Listing directory: #{path}", for: self.class)
|
52
|
+
list = Dir.entries(path)
|
48
53
|
list.delete_if { |f| f.start_with?('.') }
|
49
54
|
if list.present?
|
50
|
-
|
55
|
+
"Contents of directory \"#{path}\":\n #{list.join("\n")}"
|
51
56
|
else
|
52
|
-
|
57
|
+
"Directory is empty: #{path}"
|
53
58
|
end
|
54
59
|
rescue Errno::ENOENT
|
55
|
-
|
60
|
+
"No such directory: #{path}"
|
56
61
|
end
|
57
62
|
|
58
63
|
def read_file(file_path:)
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
path = full_path(file_path)
|
65
|
+
OxAiWorkers.logger.info("Reading file: #{path}", for: self.class)
|
66
|
+
if File.binary?(path)
|
67
|
+
"File is binary: #{path}"
|
62
68
|
else
|
63
|
-
File.read(
|
69
|
+
File.read(path).to_s
|
64
70
|
end
|
65
71
|
rescue Errno::ENOENT
|
66
|
-
|
72
|
+
"No such file: #{path}"
|
67
73
|
end
|
68
74
|
|
69
75
|
def write_to_file(file_path:, content:)
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
path = full_path(file_path)
|
77
|
+
OxAiWorkers.logger.info("Writing to file: #{path}", for: self.class)
|
78
|
+
# Ensure directory exists if using current_dir
|
79
|
+
FileUtils.mkdir_p(File.dirname(path)) if @current_dir.present? && !Dir.exist?(File.dirname(path))
|
80
|
+
File.write(path, content)
|
81
|
+
"Content was successfully written to the file: #{path}"
|
73
82
|
rescue Errno::EACCES
|
74
|
-
|
83
|
+
"Permission denied: #{path}"
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def full_path(path)
|
89
|
+
@current_dir.present? ? File.join(@current_dir, path) : path
|
75
90
|
end
|
76
91
|
end
|
77
92
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module OxAiWorkers
|
2
|
+
module Tool
|
3
|
+
class Pipeline
|
4
|
+
include OxAiWorkers::ToolDefinition
|
5
|
+
include OxAiWorkers::DependencyHelper
|
6
|
+
include OxAiWorkers::LoadI18n
|
7
|
+
|
8
|
+
attr_accessor :assistants, :messages
|
9
|
+
|
10
|
+
def initialize(only: nil, on_message: nil)
|
11
|
+
store_locale
|
12
|
+
|
13
|
+
init_white_list_with only
|
14
|
+
|
15
|
+
define_function :send_message, description: I18n.t('oxaiworkers.tool.pipeline.send_message.description') do
|
16
|
+
property :message, type: 'string', description: I18n.t('oxaiworkers.tool.pipeline.send_message.message'),
|
17
|
+
required: true
|
18
|
+
property :result, type: 'string', description: I18n.t('oxaiworkers.tool.pipeline.send_message.result'),
|
19
|
+
required: true
|
20
|
+
property :example, type: 'string', description: I18n.t('oxaiworkers.tool.pipeline.send_message.example')
|
21
|
+
property :to_id, type: 'string', description: I18n.t('oxaiworkers.tool.pipeline.send_message.to_id'),
|
22
|
+
required: true
|
23
|
+
end
|
24
|
+
|
25
|
+
@messages = []
|
26
|
+
@on_message = on_message
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_message(message:, result:, example:, to_id:)
|
30
|
+
puts "send_message to #{to_id}: #{message}".colorize(:red)
|
31
|
+
puts " Result: #{result}"
|
32
|
+
puts " Example: #{example}"
|
33
|
+
context = context_for(to_id)
|
34
|
+
@assistants[to_id].replace_context(context)
|
35
|
+
@assistants[to_id].add_task message
|
36
|
+
@assistants[to_id].add_task "#{I18n.t('oxaiworkers.tool.pipeline.send_message.result')}: #{result}"
|
37
|
+
@assistants[to_id].add_task "#{I18n.t('oxaiworkers.tool.pipeline.send_message.example')}: #{example}"
|
38
|
+
@assistants[to_id].execute
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_assistant(assistant)
|
43
|
+
unless assistant.id.present? &&
|
44
|
+
assistant.title.present? &&
|
45
|
+
assistant.role.present? &&
|
46
|
+
assistant.description.present? &&
|
47
|
+
assistant.capabilities.present?
|
48
|
+
raise 'Assistant is not valid: id, title, role, description and capabilities are required'
|
49
|
+
end
|
50
|
+
|
51
|
+
assistant.iterator.on_inner_monologue = ->(text:) { recive_monologue(from_id: assistant.id, message: text) }
|
52
|
+
assistant.iterator.on_outer_voice = ->(text:) { recive_voice(from_id: assistant.id, message: text) }
|
53
|
+
|
54
|
+
@assistants ||= {}
|
55
|
+
@assistants[assistant.id] = assistant
|
56
|
+
end
|
57
|
+
|
58
|
+
def recive_monologue(from_id:, message:)
|
59
|
+
recive_message(id: from_id, type: 'monologue', message:, color: :yellow)
|
60
|
+
end
|
61
|
+
|
62
|
+
def recive_voice(from_id:, message:)
|
63
|
+
recive_message(id: from_id, type: 'voice', message:, color: :green)
|
64
|
+
end
|
65
|
+
|
66
|
+
def recive_message(id:, type:, message:, color: :grey)
|
67
|
+
puts "#{id} [#{type}]: #{message}".colorize(color)
|
68
|
+
@messages ||= []
|
69
|
+
m = { id:, type:, message: }
|
70
|
+
@messages << m
|
71
|
+
@on_message.call(text: format_message(m)) if !@on_message.nil? && @assistants.key?(id)
|
72
|
+
# @assistants.each_value do |assistant|
|
73
|
+
# assistant.iterator.add_queue format_message(m), role: :system if assistant.id != id
|
74
|
+
# end
|
75
|
+
end
|
76
|
+
|
77
|
+
def context_for(id)
|
78
|
+
array = @messages.select { |message| message[:id] == id || message[:type] == 'voice' }
|
79
|
+
array.map { |m| format_message(m) }.join("\n\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
def context
|
83
|
+
"#{assistants_info}\n\n#{@messages.map { |m| format_message(m) }.join("\n\n")}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def assistants_info
|
87
|
+
@assistants.values.map { |assistant| format_assistant(assistant) }.join("\n\n")
|
88
|
+
end
|
89
|
+
|
90
|
+
def format_message(message)
|
91
|
+
"**#{message[:id]}**\n: #{message[:message]}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def format_assistant(assistant)
|
95
|
+
with_locale do
|
96
|
+
I18n.t('oxaiworkers.tool.pipeline.assistant_info',
|
97
|
+
id: assistant.id,
|
98
|
+
title: assistant.title,
|
99
|
+
role: assistant.role,
|
100
|
+
description: assistant.description,
|
101
|
+
capabilities: assistant.capabilities.join(', '))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module OxAiWorkers
|
5
|
+
module Tool
|
6
|
+
class Pixels
|
7
|
+
include OxAiWorkers::ToolDefinition
|
8
|
+
include OxAiWorkers::DependencyHelper
|
9
|
+
include OxAiWorkers::LoadI18n
|
10
|
+
|
11
|
+
attr_accessor :worker, :url, :current_dir
|
12
|
+
|
13
|
+
def initialize(worker:, current_dir: nil, only: nil)
|
14
|
+
store_locale
|
15
|
+
|
16
|
+
init_white_list_with only
|
17
|
+
|
18
|
+
define_function :generate_image, description: I18n.t('oxaiworkers.tool.pixels.generate_image.description') do
|
19
|
+
property :prompt, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.prompt'),
|
20
|
+
required: true
|
21
|
+
property :size, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.size'),
|
22
|
+
enum: %w[1024x1792 1792x1024 1024x1024]
|
23
|
+
if current_dir.present?
|
24
|
+
property :file_name, type: 'string',
|
25
|
+
description: I18n.t('oxaiworkers.tool.pixels.generate_image.file_name'),
|
26
|
+
required: true
|
27
|
+
end
|
28
|
+
property :quality, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.quality'),
|
29
|
+
enum: %w[standard hd]
|
30
|
+
end
|
31
|
+
|
32
|
+
@worker = worker
|
33
|
+
@current_dir = current_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_image(prompt:, file_name: nil, size: '1024x1792', quality: 'standard')
|
37
|
+
puts "generate_image: #{prompt}"
|
38
|
+
|
39
|
+
response = @worker.client.images.generate(
|
40
|
+
parameters: {
|
41
|
+
prompt:,
|
42
|
+
model: 'dall-e-3',
|
43
|
+
size:,
|
44
|
+
quality:
|
45
|
+
}
|
46
|
+
)
|
47
|
+
|
48
|
+
@url = response.dig('data', 0, 'url')
|
49
|
+
revised_prompt = response.dig('data', 0, 'revised_prompt')
|
50
|
+
if file_name.present?
|
51
|
+
path = save_generated_image(file_name:)
|
52
|
+
"url: #{@url}\nfile_name: #{path}\n\nrevised_prompt: #{revised_prompt}"
|
53
|
+
else
|
54
|
+
"url: #{@url}\n\nrevised_prompt: #{revised_prompt}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def save_generated_image(file_name:)
|
59
|
+
unless @current_dir.present?
|
60
|
+
return 'Current directory not set for OxAiWorkers::Tool::Pixels. Please set current directory first.'
|
61
|
+
end
|
62
|
+
|
63
|
+
# Ensure current_dir exists
|
64
|
+
FileUtils.mkdir_p(@current_dir) unless Dir.exist?(@current_dir)
|
65
|
+
|
66
|
+
path = File.join(@current_dir, file_name)
|
67
|
+
|
68
|
+
File.open(path, 'wb') do |file|
|
69
|
+
file.write(URI.open(@url).read)
|
70
|
+
end
|
71
|
+
|
72
|
+
file_name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/oxaiworkers/version.rb
CHANGED
data/template/start
CHANGED
@@ -18,18 +18,16 @@ puts "OxAiWorkers #{OxAiWorkers::VERSION}"
|
|
18
18
|
|
19
19
|
# Configure
|
20
20
|
OxAiWorkers.configure do |config|
|
21
|
-
config.
|
22
|
-
config.model = 'gpt-4o-mini'
|
23
|
-
# config.auto_execute = false
|
21
|
+
config.access_token_openai = ENV.fetch('OPENAI')
|
24
22
|
end
|
25
23
|
|
24
|
+
OxAiWorkers.default_model = OxAiWorkers::Models::OpenaiMini.new
|
25
|
+
|
26
26
|
# OxAiWorkers.logger.level = :debug
|
27
27
|
|
28
28
|
# Main algorithm
|
29
29
|
@assistant = MyAssistant.new
|
30
30
|
@assistant.task = '2 + 2 is ?'
|
31
|
-
|
32
|
-
# Uncomment this if auto_execute is false
|
33
|
-
# @assistant.execute
|
31
|
+
@assistant.execute
|
34
32
|
|
35
33
|
IRB.start(__FILE__)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox-ai-workers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Smolev
|
@@ -143,14 +143,22 @@ files:
|
|
143
143
|
- lib/oxaiworkers/assistant/coder.rb
|
144
144
|
- lib/oxaiworkers/assistant/localizer.rb
|
145
145
|
- lib/oxaiworkers/assistant/module_base.rb
|
146
|
+
- lib/oxaiworkers/assistant/orchestrator.rb
|
147
|
+
- lib/oxaiworkers/assistant/painter.rb
|
146
148
|
- lib/oxaiworkers/assistant/sysop.rb
|
147
149
|
- lib/oxaiworkers/compatibility.rb
|
148
150
|
- lib/oxaiworkers/contextual_logger.rb
|
149
151
|
- lib/oxaiworkers/delayed_request.rb
|
150
152
|
- lib/oxaiworkers/dependency_helper.rb
|
151
153
|
- lib/oxaiworkers/engine.rb
|
154
|
+
- lib/oxaiworkers/image_iterator.rb
|
152
155
|
- lib/oxaiworkers/iterator.rb
|
153
156
|
- lib/oxaiworkers/load_i18n.rb
|
157
|
+
- lib/oxaiworkers/models/deepseek_max.rb
|
158
|
+
- lib/oxaiworkers/models/module_base.rb
|
159
|
+
- lib/oxaiworkers/models/openai_max.rb
|
160
|
+
- lib/oxaiworkers/models/openai_mini.rb
|
161
|
+
- lib/oxaiworkers/models/openai_nano.rb
|
154
162
|
- lib/oxaiworkers/module_request.rb
|
155
163
|
- lib/oxaiworkers/present_compat.rb
|
156
164
|
- lib/oxaiworkers/request.rb
|
@@ -161,6 +169,8 @@ files:
|
|
161
169
|
- lib/oxaiworkers/tool/database.rb
|
162
170
|
- lib/oxaiworkers/tool/eval.rb
|
163
171
|
- lib/oxaiworkers/tool/file_system.rb
|
172
|
+
- lib/oxaiworkers/tool/pipeline.rb
|
173
|
+
- lib/oxaiworkers/tool/pixels.rb
|
164
174
|
- lib/oxaiworkers/tool_definition.rb
|
165
175
|
- lib/oxaiworkers/version.rb
|
166
176
|
- lib/ruby/ox-ai-workers.rb
|