summarize-ruby 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4dd0f9c27d9fb176432ad18feb629895241b2b10bf284729855e27707e5c928b
4
+ data.tar.gz: e302af7631889e3543f4540b7359be06b6ca99d8ee30c7b87fc69ec5ec3ff2d3
5
+ SHA512:
6
+ metadata.gz: 886c4ac651c3adf6a9df027460ef03c0ee7fb1deb25b6ad46a5b812380158c7edc5da968a2806df820fd96d32419c0ac268480b01fd7f8a324e08f244b361c50
7
+ data.tar.gz: d41851b8bf030bab1c2856950cfac67554b1eecc15419f7fd714c11bfcab8ee91c50eb41c572379169f0ca4f10293636cb120931690b5a0482483e4a3f185307
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-02-19
9
+
10
+ ### Added
11
+
12
+ - Ruby wrapper for the `summarize` CLI tool
13
+ - `Summarize.call` for summarizing URLs and file paths
14
+ - `Summarize.from_text` for summarizing text content
15
+ - `Summarize.extract` for content extraction without LLM summarization
16
+ - Streaming support via block syntax
17
+ - Global configuration with `Summarize.configure`
18
+ - Support for all `summarize` CLI options including model, length, language, format, video mode, slides, and more
19
+ - `Summarize::Result` object with accessors for summary, extracted content, LLM metadata, and token metrics
20
+ - Custom error hierarchy: `BinaryNotFoundError`, `TimeoutError`, `CommandError`, etc.
21
+ - Environment variable passthrough for API keys
22
+ - Automatic binary detection
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Martiano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # summarize-ruby
2
+
3
+ Ruby wrapper for the [`summarize`](https://github.com/steipete/summarize) CLI tool. Summarize web pages, files, videos, and text using LLMs from OpenAI, Anthropic, Google, xAI, and more.
4
+
5
+ ## Installation
6
+
7
+ First, install the `summarize` CLI:
8
+
9
+ ```bash
10
+ npm i -g @steipete/summarize
11
+ ```
12
+
13
+ Then add the gem to your Gemfile:
14
+
15
+ ```ruby
16
+ gem "summarize-ruby"
17
+ ```
18
+
19
+ Or install directly:
20
+
21
+ ```bash
22
+ gem install summarize-ruby
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ```ruby
28
+ require "summarize"
29
+
30
+ # Summarize a URL
31
+ result = Summarize.call("https://example.com/article")
32
+ puts result.summary
33
+
34
+ # Summarize a local file
35
+ result = Summarize.call("/path/to/document.pdf")
36
+
37
+ # Summarize text
38
+ result = Summarize.from_text("Long article text here...")
39
+
40
+ # Extract content without summarization
41
+ result = Summarize.extract("https://example.com", format: :md)
42
+ puts result.content
43
+ ```
44
+
45
+ ### Options
46
+
47
+ Pass any option as a keyword argument:
48
+
49
+ ```ruby
50
+ result = Summarize.call("https://example.com",
51
+ model: "anthropic/claude-sonnet-4-5",
52
+ length: :short,
53
+ language: "es",
54
+ prompt: "Focus on technical details"
55
+ )
56
+ ```
57
+
58
+ All supported options:
59
+
60
+ | Ruby option | CLI flag | Example values |
61
+ |---|---|---|
62
+ | `model` | `--model` | `"openai/gpt-5-mini"`, `"anthropic/claude-sonnet-4-5"`, `"auto"` |
63
+ | `length` | `--length` | `:short`, `:medium`, `:long`, `:xl`, `:xxl`, `5000` |
64
+ | `language` | `--lang` | `"en"`, `"es"`, `"de"`, `"auto"` |
65
+ | `prompt` | `--prompt` | `"Focus on key takeaways"` |
66
+ | `prompt_file` | `--prompt-file` | `"/path/to/prompt.txt"` |
67
+ | `format` | `--format` | `:text`, `:md` |
68
+ | `timeout` | `--timeout` | `"3m"`, `"30s"` |
69
+ | `retries` | `--retries` | `2` |
70
+ | `cli` | `--cli` | `"claude"`, `"gemini"`, `"codex"` |
71
+ | `video_mode` | `--video-mode` | `:auto`, `:transcript`, `:understand` |
72
+ | `markdown_mode` | `--markdown-mode` | `:off`, `:auto`, `:llm`, `:readability` |
73
+ | `max_output_tokens` | `--max-output-tokens` | `2000` |
74
+ | `max_extract_characters` | `--max-extract-characters` | `10000` |
75
+ | `youtube` | `--youtube` | `"auto"`, `"web"`, `"yt-dlp"` |
76
+ | `transcriber` | `--transcriber` | `"auto"`, `"whisper"`, `"parakeet"` |
77
+ | `firecrawl` | `--firecrawl` | `"off"`, `"auto"`, `"always"` |
78
+ | `preprocess` | `--preprocess` | `"off"`, `"auto"`, `"always"` |
79
+ | `theme` | `--theme` | `"aurora"`, `"ember"`, `"moss"`, `"mono"` |
80
+ | `metrics` | `--metrics` | `"off"`, `"on"`, `"detailed"` |
81
+ | `slides_dir` | `--slides-dir` | `"./my-slides"` |
82
+ | `slides_max` | `--slides-max` | `10` |
83
+ | `slides_min_duration` | `--slides-min-duration` | `5` |
84
+ | `slides_scene_threshold` | `--slides-scene-threshold` | `0.5` |
85
+
86
+ Boolean flags (pass `true` to enable):
87
+
88
+ | Ruby option | CLI flag |
89
+ |---|---|
90
+ | `force_summary` | `--force-summary` |
91
+ | `timestamps` | `--timestamps` |
92
+ | `no_cache` | `--no-cache` |
93
+ | `no_media_cache` | `--no-media-cache` |
94
+ | `slides` | `--slides` |
95
+ | `slides_debug` | `--slides-debug` |
96
+ | `slides_ocr` | `--slides-ocr` |
97
+ | `verbose` | `--verbose` |
98
+ | `debug` | `--debug` |
99
+ | `no_color` | `--no-color` |
100
+ | `plain` | `--plain` |
101
+
102
+ ### Streaming
103
+
104
+ Pass a block to stream output as it arrives:
105
+
106
+ ```ruby
107
+ Summarize.call("https://example.com") do |chunk|
108
+ print chunk
109
+ end
110
+ ```
111
+
112
+ ### Result object
113
+
114
+ The `Result` object provides structured access to the response:
115
+
116
+ ```ruby
117
+ result = Summarize.call("https://example.com")
118
+
119
+ # Summary
120
+ result.summary # => "## Key Points\n..."
121
+ result.success? # => true
122
+
123
+ # Extracted content
124
+ result.title # => "Article Title"
125
+ result.description # => "Article description"
126
+ result.content # => "Full extracted content..."
127
+ result.site_name # => "Example"
128
+ result.media_type # => "text/html"
129
+
130
+ # LLM info
131
+ result.model # => "gpt-5-mini"
132
+ result.provider # => "openai"
133
+
134
+ # Token usage
135
+ result.total_tokens # => 1550
136
+ result.prompt_tokens # => 1200
137
+ result.completion_tokens # => 350
138
+
139
+ # Raw JSON
140
+ result.to_h # => { "summary" => "...", "extracted" => { ... }, ... }
141
+ ```
142
+
143
+ ### Configuration
144
+
145
+ Set global defaults:
146
+
147
+ ```ruby
148
+ Summarize.configure do |c|
149
+ c.default_model = "anthropic/claude-sonnet-4-5"
150
+ c.default_length = :medium
151
+ c.default_language = "en"
152
+ c.timeout = "3m"
153
+ c.retries = 2
154
+ c.default_cli = "claude"
155
+
156
+ # Pass API keys to the CLI process
157
+ c.env = {
158
+ "ANTHROPIC_API_KEY" => ENV["ANTHROPIC_API_KEY"],
159
+ "OPENAI_API_KEY" => ENV["OPENAI_API_KEY"]
160
+ }
161
+
162
+ # Custom binary path (auto-detected by default)
163
+ c.binary_path = "/usr/local/bin/summarize"
164
+ end
165
+ ```
166
+
167
+ Per-call options override configuration defaults:
168
+
169
+ ```ruby
170
+ Summarize.configure { |c| c.default_model = "anthropic/claude-sonnet-4-5" }
171
+
172
+ # This uses gpt-5-mini, not the configured default
173
+ result = Summarize.call("https://example.com", model: "openai/gpt-5-mini")
174
+ ```
175
+
176
+ ### Error handling
177
+
178
+ ```ruby
179
+ begin
180
+ result = Summarize.call("https://example.com")
181
+ rescue Summarize::BinaryNotFoundError
182
+ # summarize CLI not installed
183
+ rescue Summarize::CommandError => e
184
+ e.exit_code # => 1
185
+ e.stderr # => "error message"
186
+ rescue Summarize::SummarizationError => e
187
+ # JSON parsing failed
188
+ rescue Summarize::Error => e
189
+ # catch-all for any summarize error
190
+ end
191
+ ```
192
+
193
+ ## Requirements
194
+
195
+ - Ruby >= 3.1
196
+ - [`summarize`](https://github.com/steipete/summarize) CLI (`npm i -g @steipete/summarize`)
197
+ - At least one LLM provider API key (OpenAI, Anthropic, Google, etc.)
198
+
199
+ ## Development
200
+
201
+ ```bash
202
+ bundle install
203
+ bundle exec rspec
204
+ ```
205
+
206
+ ## License
207
+
208
+ MIT
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "json"
5
+ require "tempfile"
6
+
7
+ module Summarize
8
+ class Client
9
+ attr_reader :config
10
+
11
+ def initialize(config = Summarize.configuration)
12
+ @config = config
13
+ end
14
+
15
+ # Summarize a URL or file path.
16
+ #
17
+ # client.call("https://example.com", length: :short, model: "openai/gpt-5-mini")
18
+ # client.call("/path/to/file.pdf", language: "es")
19
+ #
20
+ # With a block, streams chunks as they arrive:
21
+ #
22
+ # client.call("https://example.com") { |chunk| print chunk }
23
+ #
24
+ def call(input, **opts, &block)
25
+ if block_given?
26
+ stream(input, **opts, &block)
27
+ else
28
+ run_json(input, **opts)
29
+ end
30
+ end
31
+
32
+ # Summarize text content by writing to a temp file.
33
+ #
34
+ # client.from_text("Long article text...", length: :medium)
35
+ #
36
+ def from_text(text, **opts, &block)
37
+ with_temp_file(text) do |path|
38
+ if block_given?
39
+ stream(path, **opts, &block)
40
+ else
41
+ run_json(path, **opts)
42
+ end
43
+ end
44
+ end
45
+
46
+ # Extract content without LLM summarization.
47
+ #
48
+ # result = client.extract("https://example.com", format: :md)
49
+ # result.content # => extracted markdown
50
+ #
51
+ def extract(input, **opts)
52
+ run_json(input, extract: true, **opts)
53
+ end
54
+
55
+ private
56
+
57
+ def run_json(input, extract: false, **opts)
58
+ args = build_args(input, extract: extract, stream: false, json: true, **opts)
59
+
60
+ stdout, stderr, status = execute(args)
61
+
62
+ handle_error!(status, stderr) unless status.success?
63
+
64
+ parsed = JSON.parse(stdout)
65
+ Result.new(parsed)
66
+ rescue JSON::ParserError => e
67
+ raise SummarizationError, "Failed to parse JSON output: #{e.message}\nOutput: #{stdout&.slice(0, 500)}"
68
+ end
69
+
70
+ def stream(input, **opts, &block)
71
+ args = build_args(input, stream: true, json: false, **opts)
72
+
73
+ full_output = +""
74
+
75
+ Open3.popen3(command_env, *args) do |stdin, stdout, stderr, wait_thread|
76
+ stdin.close
77
+
78
+ stdout.each_line do |line|
79
+ full_output << line
80
+ block.call(line)
81
+ end
82
+
83
+ status = wait_thread.value
84
+ handle_error!(status, stderr.read) unless status.success?
85
+ end
86
+
87
+ full_output
88
+ end
89
+
90
+ def with_temp_file(text)
91
+ file = Tempfile.new(["summarize-input", ".txt"])
92
+ file.write(text)
93
+ file.flush
94
+ file.close
95
+ yield file.path
96
+ ensure
97
+ file&.unlink
98
+ end
99
+
100
+ def build_args(input, extract: false, stream: nil, json: false, **opts)
101
+ merged = apply_defaults(opts)
102
+
103
+ args = [config.binary_path]
104
+ args << input
105
+
106
+ args << "--json" if json
107
+ args << "--stream" << "off" if stream == false
108
+ args << "--stream" << "on" if stream == true
109
+ args << "--extract" if extract
110
+ args << "--metrics" << "on" if json
111
+
112
+ args.concat(Options.new(merged).to_args)
113
+
114
+ args
115
+ end
116
+
117
+ def apply_defaults(opts)
118
+ defaults = {}
119
+ defaults[:model] = config.default_model if config.default_model && config.default_model != "auto"
120
+ defaults[:cli] = config.default_cli if config.default_cli
121
+ defaults[:length] = config.default_length if config.default_length
122
+ defaults[:language] = config.default_language if config.default_language
123
+ defaults[:timeout] = config.timeout if config.timeout
124
+ defaults[:retries] = config.retries if config.retries
125
+
126
+ defaults.merge(opts)
127
+ end
128
+
129
+ def command_env
130
+ env = {}
131
+ config.env.each { |k, v| env[k.to_s] = v.to_s }
132
+ env
133
+ end
134
+
135
+ def execute(args)
136
+ validate_binary!
137
+
138
+ Open3.capture3(command_env, *args)
139
+ end
140
+
141
+ def validate_binary!
142
+ path = config.binary_path
143
+ return if path == "summarize" # rely on PATH
144
+ return if File.executable?(path)
145
+
146
+ raise BinaryNotFoundError, path
147
+ end
148
+
149
+ def handle_error!(status, stderr)
150
+ case status.exitstatus
151
+ when 130
152
+ raise Error, "Interrupted (SIGINT)"
153
+ when 143
154
+ raise Error, "Terminated (SIGTERM)"
155
+ else
156
+ raise CommandError.new(status.exitstatus, stderr&.strip || "")
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Summarize
4
+ class Configuration
5
+ attr_accessor :default_model, :default_length, :default_language,
6
+ :default_cli, :timeout, :retries, :env
7
+ attr_writer :binary_path
8
+
9
+ def initialize
10
+ @binary_path = nil
11
+ @default_model = "auto"
12
+ @default_cli = nil
13
+ @default_length = nil
14
+ @default_language = nil
15
+ @timeout = nil
16
+ @retries = nil
17
+ @env = {}
18
+ end
19
+
20
+ def binary_path
21
+ @binary_path ||= find_binary
22
+ end
23
+
24
+ private
25
+
26
+ def find_binary
27
+ path = `which summarize 2>/dev/null`.strip
28
+ return path unless path.empty?
29
+
30
+ ["/usr/local/bin/summarize", "/opt/homebrew/bin/summarize"].find { |p| File.executable?(p) } || "summarize"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Summarize
4
+ class Error < StandardError; end
5
+
6
+ class BinaryNotFoundError < Error
7
+ def initialize(path)
8
+ super("summarize binary not found at '#{path}'. Install via: npm i -g @steipete/summarize")
9
+ end
10
+ end
11
+
12
+ class TimeoutError < Error
13
+ def initialize(timeout)
14
+ super("summarize timed out after #{timeout}")
15
+ end
16
+ end
17
+
18
+ class ExtractionError < Error; end
19
+
20
+ class SummarizationError < Error; end
21
+
22
+ class CommandError < Error
23
+ attr_reader :exit_code, :stderr
24
+
25
+ def initialize(exit_code, stderr)
26
+ @exit_code = exit_code
27
+ @stderr = stderr
28
+ super("summarize exited with code #{exit_code}: #{stderr}")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Summarize
4
+ class Options
5
+ LENGTHS = %i[short medium long xl xxl s m l].freeze
6
+ VIDEO_MODES = %i[auto transcript understand].freeze
7
+ FORMATS = %i[text md].freeze
8
+ MARKDOWN_MODES = %i[off auto llm readability].freeze
9
+ METRICS_MODES = %i[off on detailed].freeze
10
+
11
+ OPTION_MAP = {
12
+ model: "--model",
13
+ length: "--length",
14
+ language: "--lang",
15
+ timeout: "--timeout",
16
+ retries: "--retries",
17
+ prompt: "--prompt",
18
+ prompt_file: "--prompt-file",
19
+ format: "--format",
20
+ video_mode: "--video-mode",
21
+ markdown_mode: "--markdown-mode",
22
+ max_output_tokens: "--max-output-tokens",
23
+ max_extract_characters: "--max-extract-characters",
24
+ youtube: "--youtube",
25
+ transcriber: "--transcriber",
26
+ firecrawl: "--firecrawl",
27
+ preprocess: "--preprocess",
28
+ theme: "--theme",
29
+ metrics: "--metrics",
30
+ cli: "--cli",
31
+ slides_dir: "--slides-dir",
32
+ slides_scene_threshold: "--slides-scene-threshold",
33
+ slides_max: "--slides-max",
34
+ slides_min_duration: "--slides-min-duration"
35
+ }.freeze
36
+
37
+ BOOLEAN_FLAGS = {
38
+ force_summary: "--force-summary",
39
+ timestamps: "--timestamps",
40
+ no_cache: "--no-cache",
41
+ no_media_cache: "--no-media-cache",
42
+ verbose: "--verbose",
43
+ debug: "--debug",
44
+ no_color: "--no-color",
45
+ plain: "--plain",
46
+ slides: "--slides",
47
+ slides_debug: "--slides-debug",
48
+ slides_ocr: "--slides-ocr"
49
+ }.freeze
50
+
51
+ def initialize(opts = {})
52
+ @opts = opts
53
+ end
54
+
55
+ def to_args
56
+ args = []
57
+
58
+ OPTION_MAP.each do |key, flag|
59
+ value = @opts[key]
60
+ next if value.nil?
61
+
62
+ args << flag << value.to_s
63
+ end
64
+
65
+ BOOLEAN_FLAGS.each do |key, flag|
66
+ args << flag if @opts[key]
67
+ end
68
+
69
+ args
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Summarize
4
+ class Result
5
+ attr_reader :raw
6
+
7
+ def initialize(json)
8
+ @raw = json
9
+ end
10
+
11
+ def summary
12
+ raw["summary"]
13
+ end
14
+
15
+ def title
16
+ dig("extracted", "title")
17
+ end
18
+
19
+ def description
20
+ dig("extracted", "description")
21
+ end
22
+
23
+ def site_name
24
+ dig("extracted", "siteName")
25
+ end
26
+
27
+ def content
28
+ dig("extracted", "content")
29
+ end
30
+
31
+ def content_length
32
+ dig("extracted", "contentLength")
33
+ end
34
+
35
+ def media_type
36
+ dig("extracted", "mediaType")
37
+ end
38
+
39
+ def source
40
+ dig("extracted", "source")
41
+ end
42
+
43
+ def model
44
+ dig("llm", "model")
45
+ end
46
+
47
+ def provider
48
+ dig("llm", "provider")
49
+ end
50
+
51
+ def prompt
52
+ raw["prompt"]
53
+ end
54
+
55
+ def metrics
56
+ raw["metrics"]
57
+ end
58
+
59
+ def llm_metrics
60
+ dig("metrics", "llm") || []
61
+ end
62
+
63
+ def total_tokens
64
+ llm_metrics.sum { |m| m["totalTokens"] || 0 }
65
+ end
66
+
67
+ def prompt_tokens
68
+ llm_metrics.sum { |m| m["promptTokens"] || 0 }
69
+ end
70
+
71
+ def completion_tokens
72
+ llm_metrics.sum { |m| m["completionTokens"] || 0 }
73
+ end
74
+
75
+ def input_kind
76
+ dig("input", "kind")
77
+ end
78
+
79
+ def slides
80
+ raw["slides"]
81
+ end
82
+
83
+ def success?
84
+ !summary.nil?
85
+ end
86
+
87
+ def extract_only?
88
+ summary.nil? && !content.nil?
89
+ end
90
+
91
+ def to_h
92
+ raw
93
+ end
94
+
95
+ private
96
+
97
+ def dig(*keys)
98
+ keys.reduce(raw) { |hash, key| hash.is_a?(Hash) ? hash[key] : nil }
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Summarize
4
+ VERSION = "0.1.0"
5
+ end
data/lib/summarize.rb ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "summarize/version"
4
+ require_relative "summarize/configuration"
5
+ require_relative "summarize/errors"
6
+ require_relative "summarize/options"
7
+ require_relative "summarize/result"
8
+ require_relative "summarize/client"
9
+
10
+ module Summarize
11
+ class << self
12
+ attr_writer :configuration
13
+
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def configure
19
+ yield(configuration)
20
+ end
21
+
22
+ def reset_configuration!
23
+ @configuration = Configuration.new
24
+ end
25
+
26
+ # Convenience method: summarize a URL or file path.
27
+ #
28
+ # Summarize.call("https://example.com", length: :short)
29
+ #
30
+ def call(input, **opts, &block)
31
+ Client.new.call(input, **opts, &block)
32
+ end
33
+
34
+ # Convenience method: summarize text content.
35
+ #
36
+ # Summarize.from_text("Long text...", length: :medium)
37
+ #
38
+ def from_text(text, **opts, &block)
39
+ Client.new.from_text(text, **opts, &block)
40
+ end
41
+
42
+ # Convenience method: extract content without summarization.
43
+ #
44
+ # Summarize.extract("https://example.com", format: :md)
45
+ #
46
+ def extract(input, **opts)
47
+ Client.new.extract(input, **opts)
48
+ end
49
+ end
50
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: summarize-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Martiano
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description: A Ruby gem that wraps the summarize CLI tool, providing a clean Ruby
28
+ API for summarizing URLs, files, and text using various LLM providers.
29
+ email:
30
+ - hello@martiano.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - CHANGELOG.md
36
+ - LICENSE
37
+ - README.md
38
+ - lib/summarize.rb
39
+ - lib/summarize/client.rb
40
+ - lib/summarize/configuration.rb
41
+ - lib/summarize/errors.rb
42
+ - lib/summarize/options.rb
43
+ - lib/summarize/result.rb
44
+ - lib/summarize/version.rb
45
+ homepage: https://github.com/martiano/summarize-ruby
46
+ licenses:
47
+ - MIT
48
+ metadata:
49
+ homepage_uri: https://github.com/martiano/summarize-ruby
50
+ source_code_uri: https://github.com/martiano/summarize-ruby
51
+ changelog_uri: https://github.com/martiano/summarize-ruby/blob/main/CHANGELOG.md
52
+ bug_tracker_uri: https://github.com/martiano/summarize-ruby/issues
53
+ documentation_uri: https://rubydoc.info/gems/summarize-ruby
54
+ rubygems_mfa_required: 'true'
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 3.1.0
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.3.27
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Ruby wrapper for the summarize CLI
74
+ test_files: []