ruby_llm-browser 0.1.0 → 0.2.0
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/CHANGELOG.md +15 -0
- data/CONTRIBUTING.md +8 -1
- data/README.md +25 -96
- data/docs/API.md +5 -172
- data/docs/RAILS.md +5 -162
- data/docs/README.md +22 -12
- data/docs/RELEASE_ACTION_PLAN.md +28 -13
- data/docs/RELEASE_AUDIT.md +19 -0
- data/docs/RELEASING.md +13 -6
- data/docs/SECURITY_MODEL.md +1 -1
- data/docs/WORK.md +22 -0
- data/docs/_advanced/development-and-testing.md +100 -0
- data/docs/_advanced/live-backend-qualification.md +5 -0
- data/docs/_advanced/rails-integration.md +143 -29
- data/docs/_config.yml +8 -4
- data/docs/_core_features/diagnostics.md +68 -0
- data/docs/_core_features/inspect-extract.md +18 -2
- data/docs/_data/navigation.yml +2 -0
- data/docs/_getting_started/getting-started.md +11 -1
- data/docs/_getting_started/whats-new-in-0-2.md +47 -0
- data/docs/_plugins/versioned_docs.rb +3 -3
- data/docs/_reference/api-and-configuration.md +188 -0
- data/docs/_reference/api-reference.md +3 -2
- data/docs/_reference/release-history.md +2 -1
- data/docs/_reference/roadmap.md +163 -0
- data/docs/_reference/upgrading.md +44 -13
- data/docs/index.md +2 -3
- data/examples/plain_ruby.rb +7 -4
- data/lib/ruby_llm/browser/doctor.rb +25 -10
- data/lib/ruby_llm/browser/version.rb +1 -1
- data/lib/ruby_llm/browser.rb +11 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20b730312da9ae14b8e3a17d386ecaa0034a38b1ac87515e89d2c6a4aa29e8d7
|
|
4
|
+
data.tar.gz: 7f27467a067bbf8e8712cfffe1a855ce85a21e563765658a142ca7c468297929
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec5d0517a3b4fa4b4fbd2a440fd52d59b173b2f2adb4674c96f9e667bbaa57276984f09f1292865adb662fc1595f9f73b63c32509b9bd9269a058366bfa24ce0
|
|
7
|
+
data.tar.gz: 13fea67455f9bdd9b49864752e69731b527958fbf06bd7ca0325a167345eaf115190cff9778247e8e526518fdef0b17c1fcb46f60346ab5c09508ca490f8cb35
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project aims to
|
|
5
5
|
follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.2.0] - 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `RubyLLM::Browser.tools(context:, schema:)` builds fresh Inspect and Extract
|
|
12
|
+
instances for `chat.with_tools(*tools)`. It never includes Act or dispatches work.
|
|
13
|
+
- Agent validation commands, an offline development workbench, and desktop/mobile
|
|
14
|
+
Chrome workflows with fixture screenshots. Browser libraries are development-only.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Doctor reports `mode: :offline`, `:live`, or `:unconfigured`. FakeBackend checks
|
|
19
|
+
skip Stagehand SDK and provider environment checks. Custom backends no longer
|
|
20
|
+
receive unrelated Stagehand credential warnings. Stagehand remains blocked.
|
|
21
|
+
|
|
7
22
|
## [0.1.0] - 2026-10-18
|
|
8
23
|
|
|
9
24
|
### Fixed
|
data/CONTRIBUTING.md
CHANGED
|
@@ -19,17 +19,24 @@ Thanks for helping. This is an unofficial community extension for
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
bin/setup # bundle install
|
|
22
|
+
bin/check # offline suite, lint, alternate bundles, and examples
|
|
22
23
|
bundle exec rake # specs + rubocop
|
|
23
24
|
bundle exec rspec # specs only
|
|
24
25
|
bundle exec bundle-audit check --update
|
|
25
26
|
bundle exec rubocop -A # autocorrect style
|
|
26
27
|
```
|
|
27
28
|
|
|
29
|
+
For the offline workbench, real Chrome tests, screenshots, and installed-package
|
|
30
|
+
checks, follow [development and testing](docs/_advanced/development-and-testing.md).
|
|
31
|
+
|
|
28
32
|
## Changing behaviour
|
|
29
33
|
|
|
30
34
|
- Add a failing spec first, including the negative/denial case.
|
|
31
35
|
- Update `CHANGELOG.md` under `Unreleased`.
|
|
32
|
-
- Update
|
|
36
|
+
- Update the relevant site guide in `docs/` when a boundary or public API changes.
|
|
37
|
+
Record breaking changes in `docs/_reference/upgrading.md`. Keep the README brief;
|
|
38
|
+
use [the documentation index](docs/README.md) for source locations and
|
|
39
|
+
[the roadmap](docs/_reference/roadmap.md) for proposed release scope.
|
|
33
40
|
- Keep runnable examples and the package's local links green in
|
|
34
41
|
`spec/integration/documentation_spec.rb`.
|
|
35
42
|
- Run both alternate bundles in `gemfiles/` when changing Tool or Rails integration.
|
data/README.md
CHANGED
|
@@ -1,41 +1,31 @@
|
|
|
1
1
|
# ruby_llm-browser
|
|
2
2
|
|
|
3
|
-
An
|
|
4
|
-
|
|
5
|
-
It provides read-only `Inspect` and schema-pinned `Extract` tools, operation bookkeeping,
|
|
6
|
-
and an optional Rails 8 adapter. It does not implement a browser engine.
|
|
3
|
+
An unofficial [RubyLLM](https://rubyllm.com) extension for read-only browser inspection
|
|
4
|
+
and schema-checked extraction, with an optional Rails 8 adapter.
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
**0.2.0 supports offline use only.** `FakeBackend` runs without credentials or network
|
|
7
|
+
requests. The experimental Stagehand adapter refuses live operations; `Act` is an
|
|
8
|
+
offline simulation. This project is not maintained or endorsed by RubyLLM or Browserbase.
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
> maintained or endorsed by RubyLLM or Browserbase.
|
|
10
|
+
[Documentation](https://rubyllm-browser.wangyaodi.com/) ·
|
|
11
|
+
[Getting started](https://rubyllm-browser.wangyaodi.com/getting-started/) ·
|
|
12
|
+
[Roadmap to 1.0](docs/_reference/roadmap.md)
|
|
16
13
|
|
|
17
14
|
## Install
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
Use Ruby 3.2+ and RubyLLM 2.x. Add to your Gemfile, then run `bundle install`:
|
|
20
17
|
|
|
21
18
|
```ruby
|
|
22
|
-
gem "ruby_llm-browser", "~> 0.
|
|
19
|
+
gem "ruby_llm-browser", "~> 0.2.0"
|
|
23
20
|
```
|
|
24
21
|
|
|
25
|
-
The core requires Ruby 3.2+, RubyLLM `>= 2.0, < 3`, `json_schemer ~> 2.5`, and
|
|
26
|
-
`stagehand ~> 3.21.0`, plus patched DNS/URL/CGI/compression gems (see the
|
|
27
|
-
[dependency reference](docs/API.md)). Requiring `ruby_llm/browser` loads neither Rails nor the Stagehand
|
|
28
|
-
client, discovers no provider credentials, and opens no browser session.
|
|
29
|
-
|
|
30
22
|
## Try it offline
|
|
31
23
|
|
|
32
|
-
This complete example makes no network request and requires no API key:
|
|
33
|
-
|
|
34
24
|
```ruby
|
|
35
25
|
# smoke-test: offline
|
|
36
26
|
require "ruby_llm/browser"
|
|
37
27
|
|
|
38
|
-
#
|
|
28
|
+
# Test resolver for this offline example only.
|
|
39
29
|
class OfflineResolver
|
|
40
30
|
def getaddresses(_host) = [ "93.184.216.34" ]
|
|
41
31
|
end
|
|
@@ -49,91 +39,30 @@ context = RubyLLM::Browser::Context.new(
|
|
|
49
39
|
operation_store: RubyLLM::Browser::InMemoryOperationStore.new
|
|
50
40
|
)
|
|
51
41
|
schema = {
|
|
52
|
-
"type" => "object",
|
|
53
|
-
"properties" => { "title" => { "type" => "string" } },
|
|
42
|
+
"type" => "object", "properties" => { "title" => { "type" => "string" } },
|
|
54
43
|
"required" => [ "title" ], "additionalProperties" => false
|
|
55
44
|
}
|
|
56
|
-
|
|
57
|
-
inspect_tool = RubyLLM::Browser::Inspect.new(context: context)
|
|
58
|
-
extract_tool = RubyLLM::Browser::Extract.new(context: context, schema: schema)
|
|
45
|
+
inspect_tool, extract_tool = RubyLLM::Browser.tools(context: context, schema: schema)
|
|
59
46
|
puts inspect_tool.execute(url: "https://docs.example.com/")[:status] # => ok
|
|
60
47
|
puts extract_tool.execute(url: "https://docs.example.com/")[:data] # => {"title"=>"Example"}
|
|
61
48
|
```
|
|
62
49
|
|
|
63
|
-
Register these
|
|
64
|
-
`chat.with_tools(inspect_tool, extract_tool)`.
|
|
65
|
-
|
|
66
|
-
the pinned extraction schema, budgets, and the backend.
|
|
67
|
-
|
|
68
|
-
The tools return a **Hash**, not a `Result` object. Direct `Engine` calls return a
|
|
69
|
-
`Result`. Check `status` and `error`; page data is untrusted evidence, not verified truth.
|
|
70
|
-
|
|
71
|
-
## Safety boundaries
|
|
72
|
-
|
|
73
|
-
- URL policy checks hosts, schemes, ports, and public DNS/IP addresses. It cannot
|
|
74
|
-
sandbox a remote browser or control page-triggered requests.
|
|
75
|
-
- No built-in live backend is supported in this release. `StagehandBackend` always
|
|
76
|
-
reports egress as unverified and refuses live operations. A host assertion cannot
|
|
77
|
-
enable it.
|
|
78
|
-
- The model cannot increase the host's output limit. Results are redacted, schema-checked
|
|
79
|
-
for extraction, and bounded by the policy and remaining operation bytes.
|
|
80
|
-
- A durable operation is claimed before start. Duplicate jobs cannot start it again.
|
|
81
|
-
SDK retries are disabled; uncertain outcomes are never automatically replayed.
|
|
82
|
-
- Cancellation fences workers but cannot undo an in-flight request. Dispatched operations
|
|
83
|
-
retain quota until cleanup is confirmed. Run a reaper independently of job workers.
|
|
84
|
-
- `max_cost_usd` is advisory metadata, not an enforced billing cap. Provider timeouts and
|
|
85
|
-
cleanup are also not a promise of zero future charges.
|
|
86
|
-
- `Act` is an offline simulation only. The full same-session live approval protocol is
|
|
87
|
-
deferred to a later version. Candidate-list hashes and selector keyword filters are
|
|
88
|
-
not proof of target identity or action safety.
|
|
89
|
-
|
|
90
|
-
## Rails integration
|
|
91
|
-
|
|
92
|
-
Add Rails 8's `activerecord` and `activejob` to your host application, then opt in:
|
|
50
|
+
Register these tools on your configured chat with
|
|
51
|
+
`chat.with_tools(inspect_tool, extract_tool)`. The host owns identity, authorization,
|
|
52
|
+
source policy, schema, and budgets. Tool calls return hashes; page data remains untrusted.
|
|
93
53
|
|
|
94
|
-
|
|
95
|
-
require "ruby_llm/browser/rails"
|
|
96
|
-
```
|
|
54
|
+
## Learn more
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```
|
|
56
|
+
Use the [documentation site](https://rubyllm-browser.wangyaodi.com/) for configuration,
|
|
57
|
+
Rails jobs, API details, and security boundaries. The same guides ship as Markdown in
|
|
58
|
+
the gem; [docs/README.md](docs/README.md) indexes their source files.
|
|
102
59
|
|
|
103
|
-
|
|
104
|
-
and a reaper. Follow the [Rails guide](docs/RAILS.md) for the context factory, matching
|
|
105
|
-
budgets, status access, scheduling, and upgrading an earlier development database.
|
|
106
|
-
Only SQLite concurrency is tested locally; PostgreSQL requires its own qualification.
|
|
107
|
-
|
|
108
|
-
## Documentation
|
|
109
|
-
|
|
110
|
-
- [Documentation website](https://rubyllm-browser.wangyaodi.com) (GitHub Pages)
|
|
111
|
-
- [Documentation index](docs/README.md)
|
|
112
|
-
- [API, configuration, and result reference](docs/API.md)
|
|
113
|
-
- [Rails jobs and recovery](docs/RAILS.md)
|
|
114
|
-
- [Security model and live qualification](docs/SECURITY_MODEL.md)
|
|
115
|
-
- [Compatibility and release checklist](docs/RELEASING.md)
|
|
116
|
-
- [Audit findings and unresolved blockers](docs/RELEASE_AUDIT.md)
|
|
117
|
-
- [Requirement evidence](docs/WORK.md)
|
|
118
|
-
- [Offline scripts](examples/)
|
|
119
|
-
|
|
120
|
-
These documents and examples are included in the built gem.
|
|
121
|
-
|
|
122
|
-
## Development
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
bin/setup
|
|
126
|
-
bundle exec rake
|
|
127
|
-
bundle exec bundle-audit check --update
|
|
128
|
-
bundle exec ruby examples/plain_ruby.rb
|
|
129
|
-
bundle exec ruby examples/rails_adapter.rb
|
|
130
|
-
bundle exec rake build
|
|
131
|
-
bundle exec ruby bin/verify-package --rails --audit
|
|
132
|
-
```
|
|
60
|
+
## Contributing
|
|
133
61
|
|
|
134
|
-
Tests block unmocked network requests.
|
|
135
|
-
|
|
62
|
+
Run `bin/setup`, then `bundle exec rake`. Tests block unmocked network requests.
|
|
63
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development and
|
|
64
|
+
[the roadmap](docs/_reference/roadmap.md) for the next iterations.
|
|
136
65
|
|
|
137
66
|
## License
|
|
138
67
|
|
|
139
|
-
MIT
|
|
68
|
+
[MIT](LICENSE.txt). See [third-party notices](NOTICE.md).
|
data/docs/API.md
CHANGED
|
@@ -1,177 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
description: Configure trusted host objects and interpret bounded untrusted results.
|
|
2
|
+
title: API Guide Location
|
|
3
|
+
description: Find the canonical API and configuration guide.
|
|
4
|
+
guide: false
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# API and configuration
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
After reading this guide, you will know:
|
|
13
|
-
|
|
14
|
-
- How to register read-only tools.
|
|
15
|
-
- Which inputs belong to the host and which belong to the model.
|
|
16
|
-
- How to configure budgets, schemas, backends, and error handling.
|
|
17
|
-
|
|
18
|
-
## Creating a context
|
|
19
|
-
|
|
20
|
-
Use the complete offline example in [Getting Started]({% link _getting_started/getting-started.md %}). `Context.new` requires:
|
|
21
|
-
|
|
22
|
-
| Keyword | Type and meaning |
|
|
23
|
-
| --- | --- |
|
|
24
|
-
| `actor_id`, `run_id` | Nonempty strings from authenticated host records. Convert numeric database IDs with `to_s`. |
|
|
25
|
-
| `backend` | A `Backend` instance. Use `FakeBackend` for offline tests. |
|
|
26
|
-
| `source_policy` | A host-created `Policy`. |
|
|
27
|
-
| `operation_store` | An `OperationStore`; durable storage is required across restarts or workers. |
|
|
28
|
-
| `approval_store` | Optional `ApprovalStore`, needed only for experimental Act. |
|
|
29
|
-
| `budget` | Optional `Budget`; defaults listed below. |
|
|
30
|
-
| `clock` | Optional callable returning a UTC `Time`. |
|
|
31
|
-
| `logger` | Optional host logger. Do not enable raw provider or tool payload logging. |
|
|
32
|
-
| `consent` | Optional host consent record. The gem records its presence; it does not collect or authenticate consent. |
|
|
33
|
-
| `metadata` | Optional host metadata. Never supply credentials here. |
|
|
34
|
-
|
|
35
|
-
The host must reauthorize actor/run access when building a context, including background
|
|
36
|
-
jobs. Passing IDs alone is not authentication. The model must never choose a backend,
|
|
37
|
-
credential, schema, source allowlist, consent record, or budget.
|
|
38
|
-
|
|
39
|
-
## Registering tools
|
|
40
|
-
|
|
41
|
-
```ruby
|
|
42
|
-
inspect_tool = RubyLLM::Browser::Inspect.new(context: context)
|
|
43
|
-
extract_tool = RubyLLM::Browser::Extract.new(context: context, schema: schema)
|
|
44
|
-
chat.with_tools(inspect_tool, extract_tool)
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Both tools expose `url`, optional `instruction`, and optional positive integer
|
|
48
|
-
`max_bytes`. `max_bytes` can only tighten the policy and operation ceilings.
|
|
49
|
-
`Extract` takes its schema in the constructor, not in model arguments.
|
|
50
|
-
|
|
51
|
-
`Inspect` returns **candidate interactions**, not a screenshot or arbitrary page dump.
|
|
52
|
-
Neither read-only tool dispatches candidates automatically. Pages may still run scripts
|
|
53
|
-
and initiate requests; read-only does not mean browsing has no external effects.
|
|
54
|
-
|
|
55
|
-
`Tool#execute` and RubyLLM `Tool#call` return a Hash. If you need a `Result` object, use:
|
|
56
|
-
|
|
57
|
-
```ruby
|
|
58
|
-
engine = RubyLLM::Browser::Engine.new(context: context)
|
|
59
|
-
result = engine.inspect(url: url)
|
|
60
|
-
result = engine.extract(url: url, schema: schema, instruction: "Find the title")
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
The optional `operation:` Engine keyword accepts a host-reserved operation with the
|
|
64
|
-
same actor/run and budget. Starting it is an atomic reserved-to-starting claim. It is
|
|
65
|
-
not a resume or retry API for active, unknown, or closed operations.
|
|
66
|
-
|
|
67
|
-
## Source policy
|
|
68
|
-
|
|
69
|
-
`Policy.new(allowed_hosts: [...])` accepts exact hosts and `*.example.com` subdomains.
|
|
70
|
-
A wildcard does not allow the bare domain. Defaults are HTTP/HTTPS and ports 80/443.
|
|
71
|
-
Keep `verify_dns: true`; `resolver:` is injectable for offline fixtures.
|
|
72
|
-
|
|
73
|
-
Other options are `allowed_schemes`, `allowed_ports`, `max_result_bytes` (65,536),
|
|
74
|
-
`max_schema_depth` (8), `max_schema_properties` (64 root properties), and
|
|
75
|
-
`max_schema_bytes` (16,384). Browser-side enforcement must also cover explicitly
|
|
76
|
-
approved asset origins, redirects, frames, popups, WebSockets, and subresources.
|
|
77
|
-
|
|
78
|
-
## Extraction schemas
|
|
79
|
-
|
|
80
|
-
Schemas must be bounded object JSON Schemas, passed as a Hash, JSON object string, or
|
|
81
|
-
an object/class supporting `to_json_schema`. Supported keywords are `type`,
|
|
82
|
-
`description`, `properties`, `required`, `items`, `enum`, `additionalProperties`,
|
|
83
|
-
`title`, `minimum`, `maximum`, `minLength`, `maxLength`, `minItems`, `maxItems`,
|
|
84
|
-
`format`, and `default`. Remote references and arbitrary schema extensions are refused.
|
|
85
|
-
|
|
86
|
-
Use `required` and `additionalProperties: false` when an exact shape matters. Provider
|
|
87
|
-
data must satisfy the schema before redaction or truncation. Invalid data returns
|
|
88
|
-
`PROVIDER_ERROR`; it is not returned as a successful extraction. A truncated preview
|
|
89
|
-
or redacted field need not retain the original schema's type. Always check the status.
|
|
90
|
-
|
|
91
|
-
## Results and errors
|
|
92
|
-
|
|
93
|
-
`Result#to_h` contains symbol keys: `status`, `operation_id`, `final_url`,
|
|
94
|
-
`captured_at` (UTC ISO 8601), `locator`, `digest`, `truncated`, `data`, and optional
|
|
95
|
-
`error: { code:, message: }`. Locator/data objects use string keys. JSON encodes all
|
|
96
|
-
keys as strings. Credential-like query values are redacted in URL provenance.
|
|
97
|
-
|
|
98
|
-
Statuses are `ok`, `truncated`, `error`, `unknown`, and `cleanup_pending`.
|
|
99
|
-
`Result#ok?` accepts `ok` and `truncated`; it makes no factual verification claim.
|
|
100
|
-
`digest` is SHA-256 of canonical JSON of the returned, sanitized data. Very small byte
|
|
101
|
-
limits can produce an empty string or scalar preview; `truncated` is authoritative.
|
|
102
|
-
|
|
103
|
-
Engine preflight denials raise typed errors. Tools convert them into error Hashes.
|
|
104
|
-
After a session starts, the Engine attempts cleanup and returns a failure result.
|
|
105
|
-
Cleanup failure can supersede the original result with `cleanup_pending`; inspect the
|
|
106
|
-
durable operation's `error_code` and arrange host review for unknown effects.
|
|
107
|
-
|
|
108
|
-
Safe error codes: `INVALID_INPUT`, `NOT_AUTHORIZED`, `UNSUPPORTED_SECURITY_CAPABILITY`,
|
|
109
|
-
`BUDGET_EXHAUSTED`, `SESSION_UNKNOWN`, `CLEANUP_PENDING`, `APPROVAL_REQUIRED`,
|
|
110
|
-
`APPROVAL_STALE`, and `PROVIDER_ERROR`.
|
|
111
|
-
|
|
112
|
-
## Budgets
|
|
113
|
-
|
|
114
|
-
`Budget.new` defaults to `max_seconds: 60`, `max_steps: 12`, `max_bytes: 262_144`,
|
|
115
|
-
`max_concurrent: 1`, and `max_cost_usd: nil`.
|
|
116
|
-
|
|
117
|
-
`RubyLLM::Browser.configure` sets process defaults for `default_budget`,
|
|
118
|
-
`max_result_bytes`, `clock`, and `logger`. New contexts/policies use those defaults;
|
|
119
|
-
existing objects do not change. `configuration.backend` is only a reserved host slot:
|
|
120
|
-
contexts always require an explicitly supplied backend and never use a fallback.
|
|
121
|
-
|
|
122
|
-
- Steps count navigation, observation, extraction, and action calls, not start/cleanup.
|
|
123
|
-
- Bytes count retained sanitized result data, not all bytes the remote browser receives.
|
|
124
|
-
- Wall-clock checks refuse new calls after expiry. Stagehand request timeouts are bounded
|
|
125
|
-
by remaining time. Cleanup has a separate timeout and may outlive this budget.
|
|
126
|
-
- Concurrency is scoped to the actor across runs. Unknown/pending cleanup holds a slot.
|
|
127
|
-
- `max_cost_usd` is **advisory only**. There is no cost ledger or provider hard spending
|
|
128
|
-
cap in this release. Enforce billing limits in the provider/host.
|
|
129
|
-
|
|
130
|
-
## Stagehand backend status
|
|
131
|
-
|
|
132
|
-
`StagehandBackend` is unsupported for live operations in this release. It always reports
|
|
133
|
-
`egress_isolation: :unverified` and `act_supported?: false`. `Engine` refuses it before
|
|
134
|
-
the first provider request, and direct start, navigation, observation, extraction, and
|
|
135
|
-
Act calls also fail closed. No constructor option or injected client enables live use.
|
|
136
|
-
|
|
137
|
-
The adapter remains in the source for future qualification. Its client pins credentials
|
|
138
|
-
and base URL, disables retries, self-healing, CAPTCHA solving, session recording and
|
|
139
|
-
session logging, and requests a provider timeout. These controls do not prove egress,
|
|
140
|
-
TTL, billing, final-URL reporting, or cleanup. `end_session` sends no request in this
|
|
141
|
-
release and returns `false`; the operation remains `cleanup_pending`.
|
|
142
|
-
|
|
143
|
-
The constructor accepts `server: :remote`, `base_url:`, `timeout: 60.0`,
|
|
144
|
-
`custom_headers_approved: false`, `env: ENV`, and an injected `client:` for internal
|
|
145
|
-
contract tests. A future live implementation must verify all relevant environment
|
|
146
|
-
settings, egress across every browser request path, TTL and closure status, and provider
|
|
147
|
-
billing controls before it can advertise support.
|
|
148
|
-
|
|
149
|
-
## Dependency security floors
|
|
150
|
-
|
|
151
|
-
Old Ruby installations can supply vulnerable default gems even when a developer's
|
|
152
|
-
lockfile audit passes. Runtime requirements explicitly exclude those versions:
|
|
153
|
-
`cgi >= 0.4.2, < 1`, `resolv >= 0.7.2, < 1`, `uri >= 1.0.4, < 2`, and
|
|
154
|
-
`zlib >= 3.2.3, < 4`. A fresh install may build native extensions for these gems.
|
|
155
|
-
Use a supported, patched Ruby interpreter as well; these floors do not patch Ruby or
|
|
156
|
-
system libraries. Audit the versions actually activated by your application, including
|
|
157
|
-
default gems, not just a development lockfile.
|
|
158
|
-
|
|
159
|
-
## Experimental Act
|
|
160
|
-
|
|
161
|
-
`Act.new(context:)` declares RubyLLM `requires_approval`. Its arguments are `url`,
|
|
162
|
-
`approval_id`, `method`, `selector`, optional `description`, and optional `arguments`.
|
|
163
|
-
The resolver reads the host store without consuming. Consumption immediately before
|
|
164
|
-
dispatch checks actor/run, exact URL/action digest, expiry, and any supplied
|
|
165
|
-
page/operation/session bindings. Revocation and consumption are atomic in the stores.
|
|
166
|
-
|
|
167
|
-
**Do not use this as a production authorization protocol yet.** Bindings are currently
|
|
168
|
-
optional; a candidate-list digest is not a DOM/target revision, and each Engine action
|
|
169
|
-
opens a fresh session. The same-session host approval flow required by the specification
|
|
170
|
-
is deferred to a later version. The Engine refuses all non-fake Act calls before starting
|
|
171
|
-
a session. Selector/description keyword filters are defense in depth, not semantic proof
|
|
172
|
-
that a click is harmless. The Stagehand adapter does not support Act in this release.
|
|
173
|
-
|
|
174
|
-
## Next steps
|
|
175
|
-
|
|
176
|
-
- Read [Rails integration]({% link RAILS.md %}) for durable workers and recovery.
|
|
177
|
-
- Read [security boundaries]({% link SECURITY_MODEL.md %}) before qualifying a live backend.
|
|
9
|
+
The [API and configuration reference](_reference/api-and-configuration.md) is the
|
|
10
|
+
canonical guide. Read it on the [documentation site](https://rubyllm-browser.wangyaodi.com/api-and-configuration/).
|
data/docs/RAILS.md
CHANGED
|
@@ -1,167 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
title: Rails Guide Location
|
|
3
|
+
description: Find the canonical Rails jobs and recovery guide.
|
|
4
|
+
guide: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Rails jobs and recovery
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
After reading this guide, you will know:
|
|
12
|
-
|
|
13
|
-
- How to install the adapter's tables.
|
|
14
|
-
- How to build a freshly authorized job context with matching budgets.
|
|
15
|
-
- How to inspect status, cancel work, and recover orphaned sessions.
|
|
16
|
-
|
|
17
|
-
## Installing the adapter
|
|
18
|
-
|
|
19
|
-
Your application supplies Rails 8, Active Record, Active Job, and a database adapter.
|
|
20
|
-
They are not runtime dependencies of the plain-Ruby gem.
|
|
21
|
-
|
|
22
|
-
```ruby
|
|
23
|
-
require "ruby_llm/browser/rails"
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
bin/rails generate ruby_llm:browser:install
|
|
28
|
-
bin/rails db:migrate
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
The generator creates operations, approvals, and per-actor reservation-lock tables.
|
|
32
|
-
SQLite and PostgreSQL are accepted by the store, but only SQLite concurrency is tested
|
|
33
|
-
locally. MySQL is not supported by this adapter's partial indexes/locking contract.
|
|
34
|
-
Use a database timeout appropriate to your workload. Database lock failures fail closed;
|
|
35
|
-
they must not be handled by retrying a browser call with a new operation ID.
|
|
36
|
-
|
|
37
|
-
`Schema.create!` is for disposable fixtures, not production migrations or schema upgrades.
|
|
38
|
-
The [offline Rails example](https://github.com/yorzi/ruby_llm-browser/blob/main/examples/rails_adapter.rb) requires no full Rails app.
|
|
39
|
-
|
|
40
|
-
## Configuring the trusted context factory
|
|
41
|
-
|
|
42
|
-
```ruby
|
|
43
|
-
# config/initializers/ruby_llm_browser.rb
|
|
44
|
-
require "ruby_llm/browser/rails"
|
|
45
|
-
|
|
46
|
-
browser_budget = RubyLLM::Browser::Budget.new(max_seconds: 30, max_steps: 6)
|
|
47
|
-
RubyLLM::Browser::Rails.context_factory = lambda do |actor_id:, run_id:|
|
|
48
|
-
# Resolve authenticated host records and recheck authorization, consent and revocation.
|
|
49
|
-
# Build policy/backend from those records, never from job or model-supplied credentials.
|
|
50
|
-
RubyLLM::Browser::Context.new(
|
|
51
|
-
actor_id: actor_id, run_id: run_id,
|
|
52
|
-
backend: qualified_backend, source_policy: policy,
|
|
53
|
-
operation_store: RubyLLM::Browser::Rails.operation_store,
|
|
54
|
-
budget: browser_budget
|
|
55
|
-
)
|
|
56
|
-
end
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
`qualified_backend` and `policy` above are host objects, not global APIs supplied by the
|
|
60
|
-
gem. The factory must use the **same operation-store instance and budget limits** as
|
|
61
|
-
the queued reservation. Construct different budgets per run only from trusted records
|
|
62
|
-
that the factory can retrieve again. An optional approval store does not enable Act in
|
|
63
|
-
jobs; `OperationJob` accepts only `inspect` and `extract`.
|
|
64
|
-
|
|
65
|
-
## Enqueuing a read-only operation
|
|
66
|
-
|
|
67
|
-
```ruby
|
|
68
|
-
operation = RubyLLM::Browser::Rails::OperationJob.enqueue(
|
|
69
|
-
actor_id: current_user.id.to_s, run_id: research_run.id.to_s,
|
|
70
|
-
kind: :inspect, url: "https://docs.example.com/",
|
|
71
|
-
budget: browser_budget, idempotency_key: "research-#{research_run.id}"
|
|
72
|
-
)
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
For extraction, pass `kind: :extract` and a host-pinned JSON `schema:`. Optional
|
|
76
|
-
`instruction:` and `max_bytes:` have the same meaning as on the tools.
|
|
77
|
-
|
|
78
|
-
One actor/run/key identifies one exact payload and budget. A changed payload using the
|
|
79
|
-
same key is rejected. Repeated enqueue calls may add duplicate queue deliveries, but
|
|
80
|
-
they attach to the same durable operation. Starting is atomically claimed once. A job
|
|
81
|
-
that sees a started, unknown, pending-cleanup, or terminal operation cannot start it
|
|
82
|
-
again. No automatic browser retry is configured.
|
|
83
|
-
|
|
84
|
-
Reservation and queue insertion are separate transactions. If enqueueing fails, retain
|
|
85
|
-
the returned operation identity when available and use the same idempotency key after
|
|
86
|
-
investigation. Schedule the reaper to reclaim expired reservations that never started.
|
|
87
|
-
|
|
88
|
-
Configure `RubyLLM::Browser::Rails.job_queue = :browser` if you need a separate queue.
|
|
89
|
-
Jobs suppress argument logging, but queues still persist URLs, instructions and schemas.
|
|
90
|
-
Protect queue access, storage, retention and encryption in the host application.
|
|
91
|
-
|
|
92
|
-
## Reading status and progress
|
|
93
|
-
|
|
94
|
-
```ruby
|
|
95
|
-
store = RubyLLM::Browser::Rails.operation_store
|
|
96
|
-
operation = store.fetch!(operation_id)
|
|
97
|
-
# Authorize this read against the authenticated actor/run before returning anything.
|
|
98
|
-
summary = operation.summary
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
`summary` omits provider session IDs and budget internals. It reports state, steps,
|
|
102
|
-
bytes, fence, timestamps, error code and cancellation flag. It is coarse progress,
|
|
103
|
-
not a percentage-complete promise. No result body is durably stored by the job; the
|
|
104
|
-
host must explicitly implement authorized result storage/delivery if needed. Do not
|
|
105
|
-
rely on an Active Job return value after asynchronous execution.
|
|
106
|
-
|
|
107
|
-
The stores are trusted server APIs, not tenant-safe controllers. They expose unscoped
|
|
108
|
-
fetch/sweep methods for workers; never expose them directly to model arguments or HTTP.
|
|
109
|
-
Tool progress callbacks are feature-detected on RubyLLM 2.1+, and contain no raw URL.
|
|
110
|
-
|
|
111
|
-
## Cancelling and reaping
|
|
112
|
-
|
|
113
|
-
```ruby
|
|
114
|
-
store.cancel(operation_id, actor_id: current_user.id.to_s,
|
|
115
|
-
run_id: research_run.id.to_s, now: Time.now.utc)
|
|
116
|
-
RubyLLM::Browser::Rails::Reaper.new(backend: qualified_backend).sweep
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Cancellation of a never-started reservation is terminal immediately. Otherwise it sets
|
|
120
|
-
`cancel_requested`, fences stale workers, and remains `cleanup_pending` with quota held.
|
|
121
|
-
It cannot undo an in-flight provider request. A returned session ID is persisted even
|
|
122
|
-
if cancellation raced with session creation.
|
|
123
|
-
|
|
124
|
-
Run a reaper regularly in an independent scheduler, not only in the operation worker's
|
|
125
|
-
ensure block. A reaper fences workers **before** reconciliation/cleanup, tries to end
|
|
126
|
-
known sessions even when provider reconciliation is unavailable, and reports `failed`
|
|
127
|
-
rather than claiming a database write succeeded. `ttl_seconds:` is an optional positive
|
|
128
|
-
idle threshold, not proof that the provider's billable session has expired.
|
|
129
|
-
|
|
130
|
-
Stagehand exposes no correlation endpoint here. An unknown start without a session ID
|
|
131
|
-
remains unknown and holds quota until the host supplies provider-confirmed evidence.
|
|
132
|
-
Alert on unknown/pending/failed entries. Never free quota just because enough local time
|
|
133
|
-
passed. An unknown action outcome remains in the result/error code even if session
|
|
134
|
-
cleanup succeeds; do not replay it.
|
|
135
|
-
|
|
136
|
-
One reaper/backend instance must cover only operations belonging to that provider
|
|
137
|
-
configuration. The current table has no backend credential-configuration binding.
|
|
138
|
-
Multi-provider/multi-credential deployments need a host-scoped store or a future schema
|
|
139
|
-
extension before a global sweep is safe.
|
|
140
|
-
|
|
141
|
-
## Upgrading an earlier development snapshot
|
|
142
|
-
|
|
143
|
-
Nothing has been publicly released. If you already ran the earlier generator, preserve
|
|
144
|
-
your data and add an explicit migration for these new fields instead of rerunning
|
|
145
|
-
`create_table` or dropping the database:
|
|
146
|
-
|
|
147
|
-
```ruby
|
|
148
|
-
class HardenBrowserBookkeeping < ActiveRecord::Migration[8.1]
|
|
149
|
-
def change
|
|
150
|
-
create_table :ruby_llm_browser_actors, id: :string do |t|
|
|
151
|
-
t.integer :sequence, null: false, default: 0
|
|
152
|
-
end
|
|
153
|
-
add_column :ruby_llm_browser_operations, :cancel_requested, :boolean, default: false, null: false
|
|
154
|
-
add_column :ruby_llm_browser_operations, :request_digest, :string
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
Adapt this migration if any additions already exist. Drain workers during the upgrade.
|
|
160
|
-
Legacy rows without request digests are not payload-bound, so do not reuse their
|
|
161
|
-
idempotency keys for new work. Inspect earlier terminal cancellations for sessions that
|
|
162
|
-
may not have been confirmed closed before reclaiming them.
|
|
163
|
-
|
|
164
|
-
## Next steps
|
|
165
|
-
|
|
166
|
-
- Review [the API]({% link API.md %}) for result interpretation and budget semantics.
|
|
167
|
-
- Review [release blockers]({% link RELEASE_AUDIT.md %}) before production deployment.
|
|
9
|
+
The [Rails integration guide](_advanced/rails-integration.md) is the canonical guide.
|
|
10
|
+
Read it on the [documentation site](https://rubyllm-browser.wangyaodi.com/rails-integration/).
|
data/docs/README.md
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
# Documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Read the [documentation site](https://rubyllm-browser.wangyaodi.com/) for the latest
|
|
4
|
+
stable release. The [next-version site](https://rubyllm-browser.wangyaodi.com/next/)
|
|
5
|
+
follows `main`. The Markdown files below are the source for those guides and ship in
|
|
6
|
+
the gem.
|
|
4
7
|
|
|
5
|
-
- [
|
|
6
|
-
- [
|
|
7
|
-
- [
|
|
8
|
-
- [
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [Specification baseline](SPEC_BASELINE.md): product intent and governance boundaries.
|
|
8
|
+
- [Getting started](_getting_started/getting-started.md): installation and an offline example.
|
|
9
|
+
- [Configuration](_getting_started/configuration.md): host inputs and process defaults.
|
|
10
|
+
- [Inspect and Extract](_core_features/inspect-extract.md): tools and result handling.
|
|
11
|
+
- [Rails jobs and recovery](_advanced/rails-integration.md): installation, workers, and cleanup.
|
|
12
|
+
- [API and configuration reference](_reference/api-and-configuration.md): parameters and errors.
|
|
13
|
+
- [Security model](SECURITY_MODEL.md): guarantees and limits.
|
|
14
|
+
- [Roadmap to 1.0](_reference/roadmap.md): proposed versions and acceptance criteria.
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
## Maintaining these docs
|
|
17
|
+
|
|
18
|
+
Keep the root README to installation, one example, and links. Put usage and API details
|
|
19
|
+
in the site guides, editing each topic in one place. Link to those source files when
|
|
20
|
+
writing repository Markdown; use Jekyll link tags between site pages. Keep
|
|
21
|
+
[CHANGELOG.md](../CHANGELOG.md) to shipped changes.
|
|
22
|
+
|
|
23
|
+
Preview with `docs/bin/serve.sh`; build with `docs/bin/build.sh`. See
|
|
24
|
+
[releasing](RELEASING.md) for package checks. The [0.1.0 audit](RELEASE_AUDIT.md),
|
|
25
|
+
[release record](RELEASE_ACTION_PLAN.md), [evidence ledger](WORK.md), and
|
|
26
|
+
[specification baseline](SPEC_BASELINE.md) preserve historical evidence.
|