brainzlab 0.1.2 → 0.1.3
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/LICENSE +6 -21
- data/README.md +16 -2
- data/lib/brainzlab/beacon/client.rb +38 -40
- data/lib/brainzlab/beacon/provisioner.rb +1 -1
- data/lib/brainzlab/beacon.rb +15 -15
- data/lib/brainzlab/configuration.rb +92 -90
- data/lib/brainzlab/context.rb +2 -3
- data/lib/brainzlab/cortex/client.rb +29 -31
- data/lib/brainzlab/cortex/provisioner.rb +1 -1
- data/lib/brainzlab/cortex.rb +7 -11
- data/lib/brainzlab/dendrite/client.rb +42 -44
- data/lib/brainzlab/dendrite/provisioner.rb +1 -1
- data/lib/brainzlab/dendrite.rb +4 -4
- data/lib/brainzlab/devtools/data/collector.rb +22 -22
- data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
- data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
- data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
- data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
- data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
- data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
- data/lib/brainzlab/devtools.rb +11 -11
- data/lib/brainzlab/flux/buffer.rb +3 -3
- data/lib/brainzlab/flux/client.rb +14 -16
- data/lib/brainzlab/flux/provisioner.rb +13 -13
- data/lib/brainzlab/flux.rb +8 -8
- data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
- data/lib/brainzlab/instrumentation/active_record.rb +13 -15
- data/lib/brainzlab/instrumentation/aws.rb +43 -39
- data/lib/brainzlab/instrumentation/dalli.rb +20 -20
- data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
- data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
- data/lib/brainzlab/instrumentation/excon.rb +27 -27
- data/lib/brainzlab/instrumentation/faraday.rb +3 -4
- data/lib/brainzlab/instrumentation/good_job.rb +28 -28
- data/lib/brainzlab/instrumentation/grape.rb +24 -24
- data/lib/brainzlab/instrumentation/graphql.rb +24 -23
- data/lib/brainzlab/instrumentation/httparty.rb +13 -14
- data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
- data/lib/brainzlab/instrumentation/net_http.rb +6 -6
- data/lib/brainzlab/instrumentation/redis.rb +14 -21
- data/lib/brainzlab/instrumentation/resque.rb +23 -24
- data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
- data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
- data/lib/brainzlab/instrumentation/stripe.rb +36 -37
- data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
- data/lib/brainzlab/instrumentation.rb +20 -20
- data/lib/brainzlab/nerve/client.rb +38 -40
- data/lib/brainzlab/nerve/provisioner.rb +1 -1
- data/lib/brainzlab/nerve.rb +6 -6
- data/lib/brainzlab/pulse/client.rb +15 -11
- data/lib/brainzlab/pulse/instrumentation.rb +61 -57
- data/lib/brainzlab/pulse/propagation.rb +28 -28
- data/lib/brainzlab/pulse/provisioner.rb +12 -12
- data/lib/brainzlab/pulse/tracer.rb +3 -3
- data/lib/brainzlab/pulse.rb +13 -13
- data/lib/brainzlab/rails/log_formatter.rb +127 -121
- data/lib/brainzlab/rails/log_subscriber.rb +70 -76
- data/lib/brainzlab/rails/railtie.rb +66 -89
- data/lib/brainzlab/recall/buffer.rb +1 -1
- data/lib/brainzlab/recall/client.rb +14 -10
- data/lib/brainzlab/recall/logger.rb +16 -18
- data/lib/brainzlab/recall/provisioner.rb +16 -16
- data/lib/brainzlab/recall.rb +11 -13
- data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
- data/lib/brainzlab/reflex/client.rb +14 -10
- data/lib/brainzlab/reflex/provisioner.rb +12 -12
- data/lib/brainzlab/reflex.rb +29 -29
- data/lib/brainzlab/sentinel/client.rb +40 -42
- data/lib/brainzlab/sentinel/provisioner.rb +1 -1
- data/lib/brainzlab/sentinel.rb +5 -5
- data/lib/brainzlab/signal/client.rb +12 -14
- data/lib/brainzlab/signal/provisioner.rb +12 -12
- data/lib/brainzlab/signal.rb +7 -7
- data/lib/brainzlab/synapse/client.rb +42 -44
- data/lib/brainzlab/synapse/provisioner.rb +1 -1
- data/lib/brainzlab/synapse.rb +6 -6
- data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
- data/lib/brainzlab/utilities/health_check.rb +53 -55
- data/lib/brainzlab/utilities/log_formatter.rb +38 -40
- data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
- data/lib/brainzlab/utilities.rb +4 -4
- data/lib/brainzlab/vault/cache.rb +1 -1
- data/lib/brainzlab/vault/client.rb +39 -41
- data/lib/brainzlab/vault/provisioner.rb +1 -1
- data/lib/brainzlab/vault.rb +19 -25
- data/lib/brainzlab/version.rb +1 -1
- data/lib/brainzlab/vision/client.rb +20 -20
- data/lib/brainzlab/vision/provisioner.rb +21 -21
- data/lib/brainzlab/vision.rb +17 -19
- data/lib/brainzlab-sdk.rb +1 -1
- data/lib/brainzlab.rb +22 -24
- data/lib/generators/brainzlab/install/install_generator.rb +29 -27
- metadata +1 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'uri'
|
|
6
6
|
|
|
7
7
|
module BrainzLab
|
|
8
8
|
module Vault
|
|
9
9
|
class Client
|
|
10
10
|
def initialize(config)
|
|
11
11
|
@config = config
|
|
12
|
-
@base_url = config.vault_url ||
|
|
12
|
+
@base_url = config.vault_url || 'https://vault.brainzlab.ai'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def get(key, environment:)
|
|
16
16
|
response = request(
|
|
17
17
|
:get,
|
|
18
18
|
"/api/v1/secrets/#{CGI.escape(key)}",
|
|
19
|
-
headers: {
|
|
19
|
+
headers: { 'X-Vault-Environment' => environment }
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
return nil unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -24,7 +24,7 @@ module BrainzLab
|
|
|
24
24
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
25
25
|
data[:value]
|
|
26
26
|
rescue StandardError => e
|
|
27
|
-
log_error(
|
|
27
|
+
log_error('get', e)
|
|
28
28
|
nil
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -38,22 +38,22 @@ module BrainzLab
|
|
|
38
38
|
|
|
39
39
|
response = request(
|
|
40
40
|
:post,
|
|
41
|
-
|
|
42
|
-
headers: {
|
|
41
|
+
'/api/v1/secrets',
|
|
42
|
+
headers: { 'X-Vault-Environment' => environment },
|
|
43
43
|
body: body
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPCreated)
|
|
47
47
|
rescue StandardError => e
|
|
48
|
-
log_error(
|
|
48
|
+
log_error('set', e)
|
|
49
49
|
false
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def list(environment:)
|
|
53
53
|
response = request(
|
|
54
54
|
:get,
|
|
55
|
-
|
|
56
|
-
headers: {
|
|
55
|
+
'/api/v1/secrets',
|
|
56
|
+
headers: { 'X-Vault-Environment' => environment }
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
return [] unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -61,7 +61,7 @@ module BrainzLab
|
|
|
61
61
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
62
62
|
data[:secrets] || []
|
|
63
63
|
rescue StandardError => e
|
|
64
|
-
log_error(
|
|
64
|
+
log_error('list', e)
|
|
65
65
|
[]
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -69,7 +69,7 @@ module BrainzLab
|
|
|
69
69
|
response = request(:delete, "/api/v1/secrets/#{CGI.escape(key)}")
|
|
70
70
|
response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPNoContent)
|
|
71
71
|
rescue StandardError => e
|
|
72
|
-
log_error(
|
|
72
|
+
log_error('delete', e)
|
|
73
73
|
false
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -77,8 +77,8 @@ module BrainzLab
|
|
|
77
77
|
params = { format: format }
|
|
78
78
|
response = request(
|
|
79
79
|
:get,
|
|
80
|
-
|
|
81
|
-
headers: {
|
|
80
|
+
'/api/v1/sync/export',
|
|
81
|
+
headers: { 'X-Vault-Environment' => environment },
|
|
82
82
|
params: params
|
|
83
83
|
)
|
|
84
84
|
|
|
@@ -92,28 +92,28 @@ module BrainzLab
|
|
|
92
92
|
response.body
|
|
93
93
|
end
|
|
94
94
|
rescue StandardError => e
|
|
95
|
-
log_error(
|
|
96
|
-
format == :json ? {} :
|
|
95
|
+
log_error('export', e)
|
|
96
|
+
format == :json ? {} : ''
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
def provision(project_id:, app_name:)
|
|
100
100
|
response = request(
|
|
101
101
|
:post,
|
|
102
|
-
|
|
102
|
+
'/api/v1/projects/provision',
|
|
103
103
|
body: { project_id: project_id, app_name: app_name },
|
|
104
104
|
use_service_key: true
|
|
105
105
|
)
|
|
106
106
|
|
|
107
107
|
response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPCreated)
|
|
108
108
|
rescue StandardError => e
|
|
109
|
-
log_error(
|
|
109
|
+
log_error('provision', e)
|
|
110
110
|
false
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
# Get all provider keys for the current project
|
|
114
114
|
# Returns a hash of provider => decrypted_key
|
|
115
115
|
def get_provider_keys
|
|
116
|
-
response = request(:get,
|
|
116
|
+
response = request(:get, '/api/v1/provider_keys/bulk')
|
|
117
117
|
|
|
118
118
|
return {} unless response.is_a?(Net::HTTPSuccess)
|
|
119
119
|
|
|
@@ -125,15 +125,15 @@ module BrainzLab
|
|
|
125
125
|
end
|
|
126
126
|
keys
|
|
127
127
|
rescue StandardError => e
|
|
128
|
-
log_error(
|
|
128
|
+
log_error('get_provider_keys', e)
|
|
129
129
|
{}
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
# Get a specific provider key
|
|
133
|
-
def get_provider_key(provider:, model_type:
|
|
133
|
+
def get_provider_key(provider:, model_type: 'llm')
|
|
134
134
|
response = request(
|
|
135
135
|
:get,
|
|
136
|
-
|
|
136
|
+
'/api/v1/provider_keys/resolve',
|
|
137
137
|
params: { provider: provider, model_type: model_type }
|
|
138
138
|
)
|
|
139
139
|
|
|
@@ -142,7 +142,7 @@ module BrainzLab
|
|
|
142
142
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
143
143
|
data[:key]
|
|
144
144
|
rescue StandardError => e
|
|
145
|
-
log_error(
|
|
145
|
+
log_error('get_provider_key', e)
|
|
146
146
|
nil
|
|
147
147
|
end
|
|
148
148
|
|
|
@@ -151,35 +151,33 @@ module BrainzLab
|
|
|
151
151
|
def request(method, path, headers: {}, body: nil, params: nil, use_service_key: false)
|
|
152
152
|
uri = URI.parse("#{@base_url}#{path}")
|
|
153
153
|
|
|
154
|
-
if params
|
|
155
|
-
uri.query = URI.encode_www_form(params)
|
|
156
|
-
end
|
|
154
|
+
uri.query = URI.encode_www_form(params) if params
|
|
157
155
|
|
|
158
156
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
159
|
-
http.use_ssl = uri.scheme ==
|
|
157
|
+
http.use_ssl = uri.scheme == 'https'
|
|
160
158
|
http.open_timeout = 10
|
|
161
159
|
http.read_timeout = 30
|
|
162
160
|
|
|
163
161
|
request = case method
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
162
|
+
when :get
|
|
163
|
+
Net::HTTP::Get.new(uri)
|
|
164
|
+
when :post
|
|
165
|
+
Net::HTTP::Post.new(uri)
|
|
166
|
+
when :put
|
|
167
|
+
Net::HTTP::Put.new(uri)
|
|
168
|
+
when :delete
|
|
169
|
+
Net::HTTP::Delete.new(uri)
|
|
170
|
+
end
|
|
173
171
|
|
|
174
172
|
# Set headers
|
|
175
|
-
request[
|
|
176
|
-
request[
|
|
173
|
+
request['Content-Type'] = 'application/json'
|
|
174
|
+
request['Accept'] = 'application/json'
|
|
177
175
|
|
|
178
176
|
if use_service_key
|
|
179
|
-
request[
|
|
177
|
+
request['X-Service-Key'] = @config.vault_master_key || @config.secret_key
|
|
180
178
|
else
|
|
181
179
|
auth_key = @config.vault_api_key || @config.secret_key
|
|
182
|
-
request[
|
|
180
|
+
request['Authorization'] = "Bearer #{auth_key}" if auth_key
|
|
183
181
|
end
|
|
184
182
|
|
|
185
183
|
headers.each { |k, v| request[k] = v }
|
|
@@ -39,7 +39,7 @@ module BrainzLab
|
|
|
39
39
|
|
|
40
40
|
def detect_project_id
|
|
41
41
|
# Try environment variable first
|
|
42
|
-
return ENV[
|
|
42
|
+
return ENV['BRAINZLAB_PROJECT_ID'] if ENV['BRAINZLAB_PROJECT_ID']
|
|
43
43
|
|
|
44
44
|
# Could also detect from Platform API if we have a secret key
|
|
45
45
|
nil
|
data/lib/brainzlab/vault.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
3
|
+
require_relative 'vault/client'
|
|
4
|
+
require_relative 'vault/cache'
|
|
5
|
+
require_relative 'vault/provisioner'
|
|
6
6
|
|
|
7
7
|
module BrainzLab
|
|
8
8
|
module Vault
|
|
@@ -35,11 +35,11 @@ module BrainzLab
|
|
|
35
35
|
secrets = export(environment: env, format: :json)
|
|
36
36
|
secrets.each do |key, value|
|
|
37
37
|
key_str = key.to_s
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
next unless overwrite || !ENV.key?(key_str)
|
|
39
|
+
|
|
40
|
+
ENV[key_str] = value.to_s
|
|
41
|
+
loaded[key_str] = value
|
|
42
|
+
BrainzLab.debug_log("[Vault] Loaded #{key_str}")
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Load provider keys (OpenAI, Anthropic, etc.)
|
|
@@ -67,11 +67,11 @@ module BrainzLab
|
|
|
67
67
|
|
|
68
68
|
provider_keys.each do |provider, key|
|
|
69
69
|
env_var = "#{provider.to_s.upcase}_API_KEY"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
next unless overwrite || !ENV.key?(env_var)
|
|
71
|
+
|
|
72
|
+
ENV[env_var] = key
|
|
73
|
+
loaded[env_var] = key
|
|
74
|
+
BrainzLab.debug_log("[Vault] Loaded provider key: #{env_var}")
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
loaded
|
|
@@ -84,7 +84,7 @@ module BrainzLab
|
|
|
84
84
|
# @param provider [String, Symbol] Provider name (openai, anthropic, etc.)
|
|
85
85
|
# @param model_type [String] Model type (llm, embedding, etc.)
|
|
86
86
|
# @return [String, nil] The API key
|
|
87
|
-
def provider_key(provider, model_type:
|
|
87
|
+
def provider_key(provider, model_type: 'llm')
|
|
88
88
|
return nil unless enabled?
|
|
89
89
|
|
|
90
90
|
ensure_provisioned!
|
|
@@ -113,9 +113,7 @@ module BrainzLab
|
|
|
113
113
|
cache_key = "#{env}:#{key}"
|
|
114
114
|
|
|
115
115
|
# Check cache first
|
|
116
|
-
if BrainzLab.configuration.vault_cache_enabled && cache.has?(cache_key)
|
|
117
|
-
return cache.get(cache_key)
|
|
118
|
-
end
|
|
116
|
+
return cache.get(cache_key) if BrainzLab.configuration.vault_cache_enabled && cache.has?(cache_key)
|
|
119
117
|
|
|
120
118
|
value = client.get(key, environment: env)
|
|
121
119
|
|
|
@@ -144,9 +142,7 @@ module BrainzLab
|
|
|
144
142
|
result = client.set(key, value, environment: env, description: description, note: note)
|
|
145
143
|
|
|
146
144
|
# Invalidate cache
|
|
147
|
-
if result && BrainzLab.configuration.vault_cache_enabled
|
|
148
|
-
cache.delete("#{env}:#{key}")
|
|
149
|
-
end
|
|
145
|
+
cache.delete("#{env}:#{key}") if result && BrainzLab.configuration.vault_cache_enabled
|
|
150
146
|
|
|
151
147
|
result
|
|
152
148
|
end
|
|
@@ -176,9 +172,7 @@ module BrainzLab
|
|
|
176
172
|
result = client.delete(key)
|
|
177
173
|
|
|
178
174
|
# Invalidate all environment caches for this key
|
|
179
|
-
if result && BrainzLab.configuration.vault_cache_enabled
|
|
180
|
-
cache.delete_pattern("*:#{key}")
|
|
181
|
-
end
|
|
175
|
+
cache.delete_pattern("*:#{key}") if result && BrainzLab.configuration.vault_cache_enabled
|
|
182
176
|
|
|
183
177
|
result
|
|
184
178
|
end
|
|
@@ -207,9 +201,9 @@ module BrainzLab
|
|
|
207
201
|
|
|
208
202
|
# Fall back to environment variable
|
|
209
203
|
if env_var
|
|
210
|
-
ENV
|
|
204
|
+
ENV.fetch(env_var, nil)
|
|
211
205
|
else
|
|
212
|
-
ENV
|
|
206
|
+
ENV.fetch(key, nil)
|
|
213
207
|
end
|
|
214
208
|
end
|
|
215
209
|
|
data/lib/brainzlab/version.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'json'
|
|
6
6
|
|
|
7
7
|
module BrainzLab
|
|
8
8
|
module Vision
|
|
@@ -22,7 +22,7 @@ module BrainzLab
|
|
|
22
22
|
payload[:model] = model if model
|
|
23
23
|
payload[:browser_provider] = browser_provider if browser_provider
|
|
24
24
|
|
|
25
|
-
post(
|
|
25
|
+
post('/mcp/tools/vision_task', payload)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Create a browser session
|
|
@@ -32,7 +32,7 @@ module BrainzLab
|
|
|
32
32
|
payload[:viewport] = viewport if viewport
|
|
33
33
|
payload[:browser_provider] = browser_provider if browser_provider
|
|
34
34
|
|
|
35
|
-
post(
|
|
35
|
+
post('/mcp/tools/vision_session_create', payload)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# Perform an AI-powered action
|
|
@@ -43,7 +43,7 @@ module BrainzLab
|
|
|
43
43
|
}
|
|
44
44
|
payload[:model] = model if model
|
|
45
45
|
|
|
46
|
-
post(
|
|
46
|
+
post('/mcp/tools/vision_ai_action', payload)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
# Perform a direct browser action
|
|
@@ -55,7 +55,7 @@ module BrainzLab
|
|
|
55
55
|
payload[:selector] = selector if selector
|
|
56
56
|
payload[:value] = value if value
|
|
57
57
|
|
|
58
|
-
post(
|
|
58
|
+
post('/mcp/tools/vision_perform', payload)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# Extract structured data
|
|
@@ -66,20 +66,20 @@ module BrainzLab
|
|
|
66
66
|
}
|
|
67
67
|
payload[:instruction] = instruction if instruction
|
|
68
68
|
|
|
69
|
-
post(
|
|
69
|
+
post('/mcp/tools/vision_extract', payload)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
# Close a session
|
|
73
73
|
def close_session(session_id:)
|
|
74
|
-
post(
|
|
74
|
+
post('/mcp/tools/vision_session_close', { session_id: session_id })
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
# Take a screenshot
|
|
78
78
|
def screenshot(session_id:, full_page: true)
|
|
79
|
-
post(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
post('/mcp/tools/vision_screenshot', {
|
|
80
|
+
session_id: session_id,
|
|
81
|
+
full_page: full_page
|
|
82
|
+
})
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
private
|
|
@@ -87,9 +87,9 @@ module BrainzLab
|
|
|
87
87
|
def post(path, payload)
|
|
88
88
|
uri = URI.parse("#{@config.vision_url}#{path}")
|
|
89
89
|
request = Net::HTTP::Post.new(uri)
|
|
90
|
-
request[
|
|
91
|
-
request[
|
|
92
|
-
request[
|
|
90
|
+
request['Content-Type'] = 'application/json'
|
|
91
|
+
request['Authorization'] = "Bearer #{auth_key}"
|
|
92
|
+
request['User-Agent'] = "brainzlab-sdk-ruby/#{BrainzLab::VERSION}"
|
|
93
93
|
request.body = JSON.generate(payload)
|
|
94
94
|
|
|
95
95
|
response = execute(uri, request)
|
|
@@ -98,9 +98,9 @@ module BrainzLab
|
|
|
98
98
|
when Net::HTTPSuccess
|
|
99
99
|
JSON.parse(response.body, symbolize_names: true)
|
|
100
100
|
when Net::HTTPUnauthorized
|
|
101
|
-
{ error:
|
|
101
|
+
{ error: 'Unauthorized: Invalid API key' }
|
|
102
102
|
when Net::HTTPForbidden
|
|
103
|
-
{ error:
|
|
103
|
+
{ error: 'Forbidden: Vision is not enabled for this project' }
|
|
104
104
|
when Net::HTTPNotFound
|
|
105
105
|
{ error: "Not found: #{path}" }
|
|
106
106
|
else
|
|
@@ -118,9 +118,9 @@ module BrainzLab
|
|
|
118
118
|
|
|
119
119
|
def execute(uri, request)
|
|
120
120
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
121
|
-
http.use_ssl = uri.scheme ==
|
|
121
|
+
http.use_ssl = uri.scheme == 'https'
|
|
122
122
|
http.open_timeout = 10
|
|
123
|
-
http.read_timeout = 300
|
|
123
|
+
http.read_timeout = 300 # Long timeout for AI tasks
|
|
124
124
|
http.request(request)
|
|
125
125
|
end
|
|
126
126
|
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'fileutils'
|
|
7
7
|
|
|
8
8
|
module BrainzLab
|
|
9
9
|
module Vision
|
|
10
10
|
class Provisioner
|
|
11
|
-
CACHE_DIR = ENV.fetch(
|
|
11
|
+
CACHE_DIR = ENV.fetch('BRAINZLAB_CACHE_DIR') { File.join(Dir.home, '.brainzlab') }
|
|
12
12
|
|
|
13
13
|
def initialize(config)
|
|
14
14
|
@config = config
|
|
@@ -38,21 +38,21 @@ module BrainzLab
|
|
|
38
38
|
|
|
39
39
|
def should_provision?
|
|
40
40
|
if @config.debug
|
|
41
|
-
log_debug(
|
|
41
|
+
log_debug('Checking Vision provision conditions:')
|
|
42
42
|
log_debug(" vision_auto_provision: #{@config.vision_auto_provision}")
|
|
43
43
|
log_debug(" app_name: '#{@config.app_name}'")
|
|
44
|
-
log_debug(" vision_api_key set: #{@config.vision_api_key.to_s.strip.length
|
|
45
|
-
log_debug(" vision_ingest_key set: #{@config.vision_ingest_key.to_s.strip.length
|
|
46
|
-
log_debug(" vision_master_key set: #{@config.vision_master_key.to_s.strip.length
|
|
44
|
+
log_debug(" vision_api_key set: #{@config.vision_api_key.to_s.strip.length.positive?}")
|
|
45
|
+
log_debug(" vision_ingest_key set: #{@config.vision_ingest_key.to_s.strip.length.positive?}")
|
|
46
|
+
log_debug(" vision_master_key set: #{@config.vision_master_key.to_s.strip.length.positive?}")
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
return false unless @config.vision_auto_provision
|
|
50
|
-
return false unless @config.app_name.to_s.strip.length
|
|
51
|
-
return false if @config.vision_api_key.to_s.strip.length
|
|
52
|
-
return false if @config.vision_ingest_key.to_s.strip.length
|
|
53
|
-
return false unless @config.vision_master_key.to_s.strip.length
|
|
50
|
+
return false unless @config.app_name.to_s.strip.length.positive?
|
|
51
|
+
return false if @config.vision_api_key.to_s.strip.length.positive?
|
|
52
|
+
return false if @config.vision_ingest_key.to_s.strip.length.positive?
|
|
53
|
+
return false unless @config.vision_master_key.to_s.strip.length.positive?
|
|
54
54
|
|
|
55
|
-
log_debug(
|
|
55
|
+
log_debug('Will provision Vision project') if @config.debug
|
|
56
56
|
true
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -67,13 +67,13 @@ module BrainzLab
|
|
|
67
67
|
def provision_project
|
|
68
68
|
uri = URI.parse("#{@config.vision_url}/api/v1/projects/provision")
|
|
69
69
|
request = Net::HTTP::Post.new(uri)
|
|
70
|
-
request[
|
|
71
|
-
request[
|
|
72
|
-
request[
|
|
70
|
+
request['Content-Type'] = 'application/json'
|
|
71
|
+
request['X-Master-Key'] = @config.vision_master_key
|
|
72
|
+
request['User-Agent'] = "brainzlab-sdk-ruby/#{BrainzLab::VERSION}"
|
|
73
73
|
request.body = JSON.generate({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
name: @config.app_name,
|
|
75
|
+
environment: @config.environment
|
|
76
|
+
})
|
|
77
77
|
|
|
78
78
|
response = execute(uri, request)
|
|
79
79
|
return nil unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -120,7 +120,7 @@ module BrainzLab
|
|
|
120
120
|
|
|
121
121
|
def execute(uri, request)
|
|
122
122
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
123
|
-
http.use_ssl = uri.scheme ==
|
|
123
|
+
http.use_ssl = uri.scheme == 'https'
|
|
124
124
|
http.open_timeout = 5
|
|
125
125
|
http.read_timeout = 10
|
|
126
126
|
http.request(request)
|
data/lib/brainzlab/vision.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
3
|
+
require_relative 'vision/client'
|
|
4
|
+
require_relative 'vision/provisioner'
|
|
5
5
|
|
|
6
6
|
module BrainzLab
|
|
7
7
|
module Vision
|
|
@@ -16,10 +16,10 @@ module BrainzLab
|
|
|
16
16
|
# @return [Hash] Task result with extracted data
|
|
17
17
|
def execute_task(instruction:, start_url:, model: nil, browser_provider: nil, max_steps: 50, timeout: 300)
|
|
18
18
|
config = BrainzLab.configuration
|
|
19
|
-
return { error:
|
|
19
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
20
20
|
|
|
21
21
|
ensure_provisioned!
|
|
22
|
-
return { error:
|
|
22
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
23
23
|
|
|
24
24
|
client.execute_task(
|
|
25
25
|
instruction: instruction,
|
|
@@ -38,10 +38,10 @@ module BrainzLab
|
|
|
38
38
|
# @return [Hash] Session info with session_id
|
|
39
39
|
def create_session(url: nil, viewport: nil, browser_provider: nil)
|
|
40
40
|
config = BrainzLab.configuration
|
|
41
|
-
return { error:
|
|
41
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
42
42
|
|
|
43
43
|
ensure_provisioned!
|
|
44
|
-
return { error:
|
|
44
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
45
45
|
|
|
46
46
|
client.create_session(
|
|
47
47
|
url: url,
|
|
@@ -57,8 +57,8 @@ module BrainzLab
|
|
|
57
57
|
# @return [Hash] Action result
|
|
58
58
|
def ai_action(session_id:, instruction:, model: nil)
|
|
59
59
|
config = BrainzLab.configuration
|
|
60
|
-
return { error:
|
|
61
|
-
return { error:
|
|
60
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
61
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
62
62
|
|
|
63
63
|
client.ai_action(
|
|
64
64
|
session_id: session_id,
|
|
@@ -75,8 +75,8 @@ module BrainzLab
|
|
|
75
75
|
# @return [Hash] Action result
|
|
76
76
|
def perform(session_id:, action:, selector: nil, value: nil)
|
|
77
77
|
config = BrainzLab.configuration
|
|
78
|
-
return { error:
|
|
79
|
-
return { error:
|
|
78
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
79
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
80
80
|
|
|
81
81
|
client.perform(
|
|
82
82
|
session_id: session_id,
|
|
@@ -93,8 +93,8 @@ module BrainzLab
|
|
|
93
93
|
# @return [Hash] Extracted data
|
|
94
94
|
def extract(session_id:, schema:, instruction: nil)
|
|
95
95
|
config = BrainzLab.configuration
|
|
96
|
-
return { error:
|
|
97
|
-
return { error:
|
|
96
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
97
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
98
98
|
|
|
99
99
|
client.extract(
|
|
100
100
|
session_id: session_id,
|
|
@@ -108,8 +108,8 @@ module BrainzLab
|
|
|
108
108
|
# @return [Hash] Close result
|
|
109
109
|
def close_session(session_id:)
|
|
110
110
|
config = BrainzLab.configuration
|
|
111
|
-
return { error:
|
|
112
|
-
return { error:
|
|
111
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
112
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
113
113
|
|
|
114
114
|
client.close_session(session_id: session_id)
|
|
115
115
|
end
|
|
@@ -120,8 +120,8 @@ module BrainzLab
|
|
|
120
120
|
# @return [Hash] Screenshot data
|
|
121
121
|
def screenshot(session_id:, full_page: true)
|
|
122
122
|
config = BrainzLab.configuration
|
|
123
|
-
return { error:
|
|
124
|
-
return { error:
|
|
123
|
+
return { error: 'Vision is not enabled' } unless config.vision_enabled
|
|
124
|
+
return { error: 'Vision credentials not configured' } unless config.vision_valid?
|
|
125
125
|
|
|
126
126
|
client.screenshot(session_id: session_id, full_page: full_page)
|
|
127
127
|
end
|
|
@@ -129,9 +129,7 @@ module BrainzLab
|
|
|
129
129
|
# Ensure project is auto-provisioned
|
|
130
130
|
def ensure_provisioned!
|
|
131
131
|
config = BrainzLab.configuration
|
|
132
|
-
if config.debug
|
|
133
|
-
puts "[BrainzLab::Debug] Vision.ensure_provisioned! called, @provisioned=#{@provisioned}"
|
|
134
|
-
end
|
|
132
|
+
puts "[BrainzLab::Debug] Vision.ensure_provisioned! called, @provisioned=#{@provisioned}" if config.debug
|
|
135
133
|
|
|
136
134
|
return if @provisioned
|
|
137
135
|
|
data/lib/brainzlab-sdk.rb
CHANGED