crawlberg 1.1.4 → 1.2.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.
@@ -1,5 +1,5 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:899a9b0b3964b8cc10628ac686b74140e934aa910533d6b9333c2acf97f2773b
2
+ # alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify --exit-code
5
5
  # frozen_string_literal: true
@@ -561,3 +561,112 @@ module Crawlberg
561
561
  end
562
562
  end
563
563
  end
564
+
565
+ module Crawlberg
566
+ # Hostname/IP allowlist matcher for SSRF policy.
567
+ #
568
+ # Serializes as an internally-tagged object so each variant is distinguishable on the
569
+ # wire and round-trips losslessly:
570
+ #
571
+ # ```json
572
+ # {"type": "exact", "value": "api.example.com"}
573
+ # {"type": "suffix", "value": ".example.com"}
574
+ # {"type": "cidr", "value": "10.0.0.0/8"}
575
+ # ```
576
+ #
577
+ # A bare JSON string is still accepted on deserialization and resolves to [`Exact`],
578
+ # preserving configs written against the previous untagged representation.
579
+ #
580
+ # [`Exact`]: HostMatcher::Exact
581
+ module HostMatcher
582
+ extend T::Helpers
583
+ extend T::Sig
584
+
585
+ interface!
586
+
587
+ # Dispatch from a Hash to the appropriate variant constructor.
588
+ # @param hash [Hash] with discriminator field and variant-specific fields
589
+ # @return [variant_class] an instance of the appropriate variant
590
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.untyped) }
591
+ def self.from_hash(hash)
592
+ discriminator = hash[:type] || hash["type"]
593
+ case discriminator
594
+ when "exact"
595
+ HostMatcherExact.from_hash(hash)
596
+ when "suffix"
597
+ HostMatcherSuffix.from_hash(hash)
598
+ when "cidr"
599
+ HostMatcherCidr.from_hash(hash)
600
+ else
601
+ raise "Unknown discriminator: #{discriminator}"
602
+ end
603
+ end
604
+ end
605
+ ## Exact hostname match (case-insensitive).
606
+ HostMatcherExact = Data.define(:value) do
607
+ include HostMatcher
608
+ extend T::Sig
609
+
610
+ # The hostname to match.
611
+ sig { returns(String) }
612
+ # rubocop:disable Lint/UselessMethodDefinition
613
+ def value = super
614
+ sig { returns(T::Boolean) }
615
+ def exact? = true
616
+ sig { returns(T::Boolean) }
617
+ def suffix? = false
618
+ sig { returns(T::Boolean) }
619
+ def cidr? = false
620
+ # @param hash [Hash] deserialized from the native extension
621
+ # @return [self]
622
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
623
+ def self.from_hash(hash)
624
+ new(value: hash[:value] || hash["value"])
625
+ end
626
+ end
627
+ ## Suffix match: ".xberg.io" matches "api.xberg.io" and "xberg.io".
628
+ HostMatcherSuffix = Data.define(:value) do
629
+ include HostMatcher
630
+ extend T::Sig
631
+
632
+ # The dot-prefixed suffix to match. A leading dot is optional.
633
+ sig { returns(String) }
634
+ # rubocop:disable Lint/UselessMethodDefinition
635
+ def value = super
636
+ sig { returns(T::Boolean) }
637
+ def exact? = false
638
+ sig { returns(T::Boolean) }
639
+ def suffix? = true
640
+ sig { returns(T::Boolean) }
641
+ def cidr? = false
642
+ # @param hash [Hash] deserialized from the native extension
643
+ # @return [self]
644
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
645
+ def self.from_hash(hash)
646
+ new(value: hash[:value] || hash["value"])
647
+ end
648
+ end
649
+ ## CIDR match: "10.0.0.0/8" matches IP addresses in that range.
650
+ HostMatcherCidr = Data.define(:value) do
651
+ include HostMatcher
652
+ extend T::Sig
653
+
654
+ # The CIDR block. Validated when built through [`HostMatcher::cidr`] or
655
+ # deserialization.
656
+ sig { returns(String) }
657
+ # rubocop:disable Lint/UselessMethodDefinition
658
+ def value = super
659
+ sig { returns(T::Boolean) }
660
+ def exact? = false
661
+ sig { returns(T::Boolean) }
662
+ def suffix? = false
663
+ sig { returns(T::Boolean) }
664
+ def cidr? = true
665
+ # @param hash [Hash] deserialized from the native extension
666
+ # @return [self]
667
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.attached_class) }
668
+ def self.from_hash(hash)
669
+ new(value: hash[:value] || hash["value"])
670
+ end
671
+ end
672
+ end
@@ -1,10 +1,10 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:899a9b0b3964b8cc10628ac686b74140e934aa910533d6b9333c2acf97f2773b
2
+ # alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify --exit-code
5
5
  # frozen_string_literal: true
6
6
 
7
7
  module Crawlberg
8
8
  ## The version string for this package.
9
- VERSION = "1.1.4"
9
+ VERSION = "1.2.1"
10
10
  end
data/lib/crawlberg.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:899a9b0b3964b8cc10628ac686b74140e934aa910533d6b9333c2acf97f2773b
2
+ # alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify --exit-code
5
5
  # frozen_string_literal: true
data/lib/crawlberg_rb.so CHANGED
Binary file
data/sig/types.rbs CHANGED
@@ -1,5 +1,5 @@
1
1
  # This file is auto-generated by alef — DO NOT EDIT.
2
- # alef:hash:899a9b0b3964b8cc10628ac686b74140e934aa910533d6b9333c2acf97f2773b
2
+ # alef:hash:0ce4d753fdb4854e44358639dcbaebee3449a4afa142dbc4f0a72aa72c214648
3
3
  # To regenerate: alef generate
4
4
  # To verify freshness: alef verify --exit-code
5
5
 
@@ -67,6 +67,7 @@ def initialize: (?mode: BrowserMode, ?backend: BrowserBackend, ?endpoint: String
67
67
  class CrawlConfig
68
68
  attr_accessor max_depth: Integer?
69
69
  attr_accessor max_pages: Integer?
70
+ attr_accessor max_links_per_page: Integer?
70
71
  attr_accessor max_concurrent: Integer?
71
72
  attr_accessor respect_robots_txt: bool?
72
73
  attr_accessor soft_http_errors: bool?
@@ -100,12 +101,15 @@ def initialize: (?mode: BrowserMode, ?backend: BrowserBackend, ?endpoint: String
100
101
  attr_accessor download_documents: bool?
101
102
  attr_accessor document_max_size: Integer?
102
103
  attr_accessor document_mime_types: Array[String]?
104
+ attr_accessor document_output_dir: String?
105
+ attr_accessor document_content_encoding: DocumentContentEncoding?
103
106
  attr_accessor warc_output: String?
104
107
  attr_accessor browser_profile: String?
105
108
  attr_accessor save_browser_profile: bool?
106
109
  attr_accessor ssrf: SsrfPolicy?
110
+ attr_accessor ssrf_deny_private_explicit: bool?
107
111
 
108
- def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_concurrent: Integer, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy) -> void
112
+ def initialize: (?max_depth: Integer, ?max_pages: Integer, ?max_links_per_page: Integer, ?max_concurrent: Integer, ?respect_robots_txt: bool, ?soft_http_errors: bool, ?user_agent: String, ?stay_on_domain: bool, ?allow_subdomains: bool, ?include_paths: Array[String], ?exclude_paths: Array[String], ?custom_headers: Hash[String, String], ?request_timeout: Integer, ?rate_limit_ms: Integer, ?max_redirects: Integer, ?retry_count: Integer, ?retry_codes: Array[Integer], ?cookies_enabled: bool, ?auth: AuthConfig, ?max_body_size: Integer, ?remove_tags: Array[String], ?content: ContentConfig, ?map_limit: Integer, ?map_search: String, ?download_assets: bool, ?asset_types: Array[AssetCategory], ?max_asset_size: Integer, ?browser: BrowserConfig, ?proxy: ProxyConfig, ?user_agents: Array[String], ?capture_screenshot: bool, ?follow_document_urls: bool, ?document_url_depth: Integer, ?download_documents: bool, ?document_max_size: Integer, ?document_mime_types: Array[String], ?document_output_dir: String, ?document_content_encoding: DocumentContentEncoding, ?warc_output: String, ?browser_profile: String, ?save_browser_profile: bool, ?ssrf: SsrfPolicy, ?ssrf_deny_private_explicit: bool) -> void
109
113
  def validate: () -> void
110
114
  def self.default: () -> CrawlConfig
111
115
  end
@@ -125,16 +129,20 @@ def initialize: (?eval_result: json_value, ?network_events: Array[ResponseMeta],
125
129
  attr_accessor filename: String?
126
130
  attr_accessor content_hash: String?
127
131
  attr_accessor headers: Hash[String, String]?
132
+ attr_accessor truncated: bool?
133
+ attr_accessor content_path: String?
134
+ attr_accessor content_base64: String?
128
135
 
129
- def initialize: (?url: String, ?mime_type: String, ?size: Integer, ?filename: String, ?content_hash: String, ?headers: Hash[String, String]) -> void
136
+ def initialize: (?url: String, ?mime_type: String, ?size: Integer, ?filename: String, ?content_hash: String, ?headers: Hash[String, String], ?truncated: bool, ?content_path: String, ?content_base64: String) -> void
130
137
  end
131
138
 
132
139
  class InteractionResult
133
140
  attr_accessor action_results: Array[ActionResult]?
134
141
  attr_accessor final_html: String?
135
142
  attr_accessor final_url: String?
143
+ attr_accessor screenshot_base64: String?
136
144
 
137
- def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?final_url: String) -> void
145
+ def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?final_url: String, ?screenshot_base64: String) -> void
138
146
  end
139
147
 
140
148
  class ActionResult
@@ -174,10 +182,11 @@ def initialize: (?action_results: Array[ActionResult], ?final_html: String, ?fin
174
182
  attr_accessor markdown: MarkdownResult?
175
183
  attr_accessor extracted_data: json_value?
176
184
  attr_accessor extraction_meta: ExtractionMeta?
185
+ attr_accessor screenshot_base64: String?
177
186
  attr_accessor downloaded_document: DownloadedDocument?
178
187
  attr_accessor browser: BrowserExtras?
179
188
 
180
- def initialize: (?status_code: Integer, ?final_url: String, ?content_type: String, ?html: String, ?body_size: Integer, ?metadata: PageMetadata, ?links: Array[LinkInfo], ?images: Array[ImageInfo], ?feeds: Array[FeedInfo], ?json_ld: Array[JsonLdEntry], ?is_allowed: bool, ?crawl_delay: Integer, ?noindex_detected: bool, ?nofollow_detected: bool, ?x_robots_tag: String, ?is_pdf: bool, ?was_skipped: bool, ?detected_charset: String, ?auth_header_sent: bool, ?response_meta: ResponseMeta, ?assets: Array[DownloadedAsset], ?js_render_hint: bool, ?browser_used: bool, ?markdown: MarkdownResult, ?extracted_data: json_value, ?extraction_meta: ExtractionMeta, ?downloaded_document: DownloadedDocument, ?browser: BrowserExtras) -> void
189
+ def initialize: (?status_code: Integer, ?final_url: String, ?content_type: String, ?html: String, ?body_size: Integer, ?metadata: PageMetadata, ?links: Array[LinkInfo], ?images: Array[ImageInfo], ?feeds: Array[FeedInfo], ?json_ld: Array[JsonLdEntry], ?is_allowed: bool, ?crawl_delay: Integer, ?noindex_detected: bool, ?nofollow_detected: bool, ?x_robots_tag: String, ?is_pdf: bool, ?was_skipped: bool, ?detected_charset: String, ?auth_header_sent: bool, ?response_meta: ResponseMeta, ?assets: Array[DownloadedAsset], ?js_render_hint: bool, ?browser_used: bool, ?markdown: MarkdownResult, ?extracted_data: json_value, ?extraction_meta: ExtractionMeta, ?screenshot_base64: String, ?downloaded_document: DownloadedDocument, ?browser: BrowserExtras) -> void
181
190
  end
182
191
 
183
192
  class CrawlPageResult
@@ -463,9 +472,10 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
463
472
 
464
473
  class SsrfPolicy
465
474
  attr_accessor deny_private: bool?
475
+ attr_accessor allowlist: Array[HostMatcher]?
466
476
  attr_accessor max_redirects: Integer?
467
477
 
468
- def initialize: (?deny_private: bool, ?max_redirects: Integer) -> void
478
+ def initialize: (?deny_private: bool, ?allowlist: Array[HostMatcher], ?max_redirects: Integer) -> void
469
479
  def self.default: () -> SsrfPolicy
470
480
  def self.from_env: () -> SsrfPolicy
471
481
  end
@@ -482,6 +492,10 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
482
492
  type value = :chromiumoxide | :native
483
493
  end
484
494
 
495
+ class DocumentContentEncoding
496
+ type value = :base64
497
+ end
498
+
485
499
  class AuthConfig
486
500
  end
487
501
 
@@ -511,6 +525,9 @@ def initialize: (?results: Array[BatchCrawlResult], ?total_count: Integer, ?comp
511
525
  type value = :up | :down
512
526
  end
513
527
 
528
+ class HostMatcher
529
+ end
530
+
514
531
  def self.generate_citations: (String markdown) -> CitationResult
515
532
 
516
533
  def self.create_engine: (?CrawlConfig config) -> CrawlEngineHandle
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crawlberg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xberg Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-05 00:00:00.000000000 Z
11
+ date: 2026-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys