charai 0.1.0 → 0.2.0.beta2
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/README.md +3 -0
- data/lib/charai/agent.rb +1 -1
- data/lib/charai/browsing_context.rb +103 -6
- data/lib/charai/driver.rb +44 -9
- data/lib/charai/injectedScriptSource.js +34 -0
- data/lib/charai/injected_script.rb +40 -0
- data/lib/charai/input_tool.rb +61 -1
- data/lib/charai/openai_configuration.rb +20 -0
- data/lib/charai/version.rb +1 -1
- data/lib/charai.rb +1 -0
- metadata +4 -2
@@ -0,0 +1,40 @@
|
|
1
|
+
module Charai
|
2
|
+
class InjectedScript
|
3
|
+
def initialize(realm, handle)
|
4
|
+
@realm = realm
|
5
|
+
@handle = handle
|
6
|
+
end
|
7
|
+
|
8
|
+
def e(value)
|
9
|
+
@realm.script_evaluate(value, as_handle: false)
|
10
|
+
end
|
11
|
+
|
12
|
+
def h(value)
|
13
|
+
@realm.script_evaluate(value, as_handle: true)
|
14
|
+
end
|
15
|
+
|
16
|
+
def getprop(name, as_handle: false)
|
17
|
+
c(
|
18
|
+
function_declaration: "(injected) => injected.#{name}",
|
19
|
+
as_handle: as_handle,
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(name, *args, as_handle: false)
|
24
|
+
c(
|
25
|
+
function_declaration: "(injected, ...args) => injected.#{name}(...args)",
|
26
|
+
args: args,
|
27
|
+
as_handle: as_handle,
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def c(function_declaration:, args: [], as_handle: false)
|
34
|
+
@realm.script_call_function(
|
35
|
+
function_declaration,
|
36
|
+
arguments: [@handle, *args],
|
37
|
+
as_handle: as_handle)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/charai/input_tool.rb
CHANGED
@@ -31,11 +31,37 @@ module Charai
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
def aria_snapshot(root_locator: 'document.body', ref: false)
|
35
|
+
trigger_callback(:on_action_start, 'aria_snapshot', { root_locator: root_locator, ref: ref })
|
36
|
+
|
37
|
+
current_url = @browsing_context.url
|
38
|
+
snapshot = @browsing_context.default_realm._with_injected_script do |script|
|
39
|
+
if ref
|
40
|
+
body_handle = script.getprop("document.body", as_handle: true)
|
41
|
+
result = script.call(:ariaSnapshot, body_handle, { mode: 'ai' })
|
42
|
+
result.split("\n")
|
43
|
+
else
|
44
|
+
not_found = script.e("!#{root_locator}")
|
45
|
+
if not_found
|
46
|
+
raise ArgumentError, "Element not found: #{root_locator}"
|
47
|
+
end
|
48
|
+
result = script.call(:ariaSnapshot, script.h(root_locator), { mode: 'autoexpect' })
|
49
|
+
result.split("\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if @message_sender
|
54
|
+
message = Agent::Message.new(text: "ARIA snapshot of #{current_url}\n\n#{snapshot}")
|
55
|
+
@message_sender.call(message)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
34
59
|
def capture_screenshot
|
35
60
|
trigger_callback(:on_action_start, 'capture_screenshot', {})
|
36
61
|
|
37
62
|
current_url = @browsing_context.url
|
38
|
-
|
63
|
+
binding.irb
|
64
|
+
@browsing_context.capture_screenshot(format: { type: 'png' }).tap do |binary|
|
39
65
|
if @message_sender
|
40
66
|
message = Agent::Message.new(
|
41
67
|
text: "Capture of #{current_url}",
|
@@ -73,6 +99,23 @@ module Charai
|
|
73
99
|
result
|
74
100
|
end
|
75
101
|
|
102
|
+
def execute_script_with_ref(ref, element_function_declaration)
|
103
|
+
resolved = resolve_selector_for_ref(ref)
|
104
|
+
trigger_callback(:on_action_start, 'execute_script_with_ref', { script: element_function_declaration, ref: ref, selector: resolved[:selector] })
|
105
|
+
|
106
|
+
begin
|
107
|
+
result = @browsing_context.default_realm.script_call_function(
|
108
|
+
element_function_declaration,
|
109
|
+
arguments: [resolved[:element_handle]])
|
110
|
+
rescue BrowsingContext::Realm::ScriptEvaluationError => e
|
111
|
+
result = e.message
|
112
|
+
end
|
113
|
+
|
114
|
+
notify_to_sender(result) unless "#{result}" == ''
|
115
|
+
|
116
|
+
result
|
117
|
+
end
|
118
|
+
|
76
119
|
def on_pressing_key(key, &block)
|
77
120
|
trigger_callback(:on_action_start, 'key_down', { key: key })
|
78
121
|
|
@@ -175,6 +218,23 @@ module Charai
|
|
175
218
|
end
|
176
219
|
end
|
177
220
|
|
221
|
+
def resolve_selector_for_ref(ref)
|
222
|
+
@browsing_context.default_realm._with_injected_script do |script|
|
223
|
+
parsed = script.call(:parseSelector, "aria-ref=#{ref}")
|
224
|
+
|
225
|
+
# ensure ref is attached.
|
226
|
+
body_handle = script.getprop("document.body", as_handle: true)
|
227
|
+
script.call(:ariaSnapshot, body_handle, { mode: 'ai' })
|
228
|
+
|
229
|
+
document_handle = script.getprop('document', as_handle: true)
|
230
|
+
element_handle = script.call(:querySelector, parsed, document_handle, false, as_handle: true)
|
231
|
+
|
232
|
+
selector = script.call(:generateSelectorSimple, element_handle, { omitInternalEngines: true })
|
233
|
+
|
234
|
+
{ selector: selector, element_handle: element_handle }
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
178
238
|
# ref: https://github.com/puppeteer/puppeteer/blob/puppeteer-v23.5.3/packages/puppeteer-core/src/bidi/Input.ts#L52
|
179
239
|
# Converted using ChatGPT 4o
|
180
240
|
def convert_key(key)
|
@@ -19,6 +19,26 @@ module Charai
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
class GeminiOpenaiConfiguration
|
23
|
+
def initialize(model:, api_key:)
|
24
|
+
@endpoint_url = 'https://generativelanguage.googleapis.com/v1beta/openai/'
|
25
|
+
@model = model
|
26
|
+
@api_key = api_key
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :endpoint_url
|
30
|
+
|
31
|
+
def add_auth_header(headers)
|
32
|
+
headers['Authorization'] = "Bearer #{@api_key}"
|
33
|
+
headers
|
34
|
+
end
|
35
|
+
|
36
|
+
def decorate_body(payload)
|
37
|
+
payload[:model] = @model
|
38
|
+
payload
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
22
42
|
class AzureOpenaiConfiguration
|
23
43
|
def initialize(endpoint_url:, api_key:)
|
24
44
|
@endpoint_url = endpoint_url
|
data/lib/charai/version.rb
CHANGED
data/lib/charai.rb
CHANGED
@@ -10,6 +10,7 @@ require 'charai/browser_launcher'
|
|
10
10
|
require 'charai/browser_process'
|
11
11
|
require 'charai/browsing_context'
|
12
12
|
require 'charai/driver'
|
13
|
+
require 'charai/injected_script'
|
13
14
|
require 'charai/input_tool'
|
14
15
|
require 'charai/openai_chat'
|
15
16
|
require 'charai/openai_configuration'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: charai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YusukeIwaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -75,6 +75,8 @@ files:
|
|
75
75
|
- lib/charai/browser_process.rb
|
76
76
|
- lib/charai/browsing_context.rb
|
77
77
|
- lib/charai/driver.rb
|
78
|
+
- lib/charai/injectedScriptSource.js
|
79
|
+
- lib/charai/injected_script.rb
|
78
80
|
- lib/charai/input_tool.rb
|
79
81
|
- lib/charai/openai_chat.rb
|
80
82
|
- lib/charai/openai_configuration.rb
|