slidict 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72ffe395b54c50043126018602fe50cde4e7e9ffdc666dd4c403b76b0fc97753
4
- data.tar.gz: 1f8fd030ddb53433a334af861bcb1bf4fdb2a191de50657d900a74936e4ca767
3
+ metadata.gz: 829a5806efaa7c29d773818f0683fa3c0525bebfe883bd32261ba29f5a649a5e
4
+ data.tar.gz: e45e42541ba0940a883f470f7d03941df71b5825c0c9b93471fe3b1c991b0de5
5
5
  SHA512:
6
- metadata.gz: b33d3e8fde16b58ace800bc590edd63cd67bdb20f595dff60367182c440b8f57fa779632a8da4f72a885061bd400a576b888f4c555684fd2e2c615e14fb589f6
7
- data.tar.gz: 61cc90648bd97afd6dbda04aed0406f7f7601553852319f05a05905187752057d951805f03facac2003efebadbf97625092e814b952ec347c08000130c3ddf37
6
+ metadata.gz: ff04a4475b51083d1c8ed884ad10f924000bb6c47adb0947d6c365fa3dd81d83eb09b94b280794bed9d2ef1001b559589c9241d92b0ccc005a7969065a814eb1
7
+ data.tar.gz: a0385b86027802eb018c4c9bda5fc26ee8030df9eee449879bd5dc299faa32382df90e5b8c707b528c846018d1fa8f28b3861ce299ed8d58f7d5ad125bc29b15
@@ -28,6 +28,8 @@ module Slidict
28
28
  return lint(options[:args]) if options[:command] == "lint"
29
29
 
30
30
  config = build_config(options)
31
+ return print_available_models(config) if config.llm_enabled? && config.model.nil?
32
+
31
33
  client = llm_client_for(config)
32
34
  return 1 if client && !verify_connection(client)
33
35
 
@@ -155,6 +157,21 @@ module Slidict
155
157
  )
156
158
  end
157
159
 
160
+ def print_available_models(config)
161
+ client = Llm::Client.new(base_url: config.base_url, api_key: config.api_key, model: nil)
162
+ models = client.list_models
163
+ if models.empty?
164
+ @output.puts "No models available at #{config.base_url}"
165
+ else
166
+ @output.puts "Available models (specify one with --llm-model NAME or SLIDICT_LLM_MODEL=NAME):"
167
+ models.each { |m| @output.puts " #{m}" }
168
+ end
169
+ 0
170
+ rescue Llm::Client::Error => e
171
+ @output.puts "Error: LLM request failed (#{e.message})"
172
+ 1
173
+ end
174
+
158
175
  def llm_client_for(config)
159
176
  return nil unless config.llm_enabled?
160
177
 
@@ -284,7 +301,7 @@ module Slidict
284
301
  --llm-base-url URL OpenAI Compatible API base URL (env: SLIDICT_LLM_BASE_URL).
285
302
  When omitted, the built-in slide template is used instead.
286
303
  --llm-api-key KEY API key for the LLM endpoint (env: SLIDICT_LLM_API_KEY)
287
- --llm-model NAME Model name to request (env: SLIDICT_LLM_MODEL, default: gpt-4o-mini)
304
+ --llm-model NAME Model name to request (env: SLIDICT_LLM_MODEL); omit to list available models
288
305
  --no-llm Skip the LLM call and use the built-in slide template
289
306
  --publish Publish the generated slides to slidict.io as a draft
290
307
  (requires `slidict auth`; creates a new slide, or edits
@@ -31,6 +31,7 @@ module Slidict
31
31
  def run_lint(options)
32
32
  config = build_config(options)
33
33
  return llm_required unless config.llm_enabled?
34
+ return print_available_models(config) if config.model.nil?
34
35
 
35
36
  print_findings(lint(options, config))
36
37
  end
@@ -112,6 +113,20 @@ module Slidict
112
113
  1
113
114
  end
114
115
 
116
+ def print_available_models(config)
117
+ client = Llm::Client.new(base_url: config.base_url, api_key: config.api_key, model: nil)
118
+ models = client.list_models
119
+ if models.empty?
120
+ @output.puts "No models available at #{config.base_url}"
121
+ else
122
+ @output.puts "Available models (specify one with --llm-model NAME or SLIDICT_LLM_MODEL=NAME):"
123
+ models.each { |m| @output.puts " #{m}" }
124
+ end
125
+ 0
126
+ rescue Llm::Client::Error => e
127
+ print_error(e)
128
+ end
129
+
115
130
  def llm_required
116
131
  @output.puts "Error: lint requires an LLM endpoint (--llm-base-url or SLIDICT_LLM_BASE_URL)"
117
132
  1
@@ -124,7 +139,7 @@ module Slidict
124
139
  --format FORMAT markdown or asciidoc (default: auto-detected from extension)
125
140
  --llm-base-url URL OpenAI Compatible API base URL (env: SLIDICT_LLM_BASE_URL)
126
141
  --llm-api-key KEY API key for the LLM endpoint (env: SLIDICT_LLM_API_KEY)
127
- --llm-model NAME Model name to request (env: SLIDICT_LLM_MODEL, default: gpt-4o-mini)
142
+ --llm-model NAME Model name to request (env: SLIDICT_LLM_MODEL); omit to list available models
128
143
  --translate LANG Translate findings into the given language (e.g. Japanese)
129
144
  -h, --help Show this help
130
145
  HELP
@@ -6,7 +6,7 @@ module Slidict
6
6
 
7
7
  attr_reader :base_url, :api_key, :model
8
8
 
9
- def initialize(base_url: nil, api_key: nil, model: DEFAULT_MODEL, enabled: true)
9
+ def initialize(base_url: nil, api_key: nil, model: nil, enabled: true)
10
10
  @base_url = base_url
11
11
  @api_key = api_key
12
12
  @model = model
@@ -17,7 +17,7 @@ module Slidict
17
17
  new(
18
18
  base_url: env["SLIDICT_LLM_BASE_URL"],
19
19
  api_key: env["SLIDICT_LLM_API_KEY"],
20
- model: env["SLIDICT_LLM_MODEL"] || DEFAULT_MODEL
20
+ model: env["SLIDICT_LLM_MODEL"]
21
21
  )
22
22
  end
23
23
 
@@ -21,12 +21,18 @@ module Slidict
21
21
  # Checks that the endpoint is reachable before the (slower, more
22
22
  # expensive) chat completion request is made. Raises Error on failure.
23
23
  def verify_connection!
24
- uri = endpoint_uri("models")
25
- request = Net::HTTP::Get.new(uri)
26
- request["Authorization"] = "Bearer #{@api_key}"
27
- response = perform_request(uri, request)
24
+ response = get_models_response
25
+ raise Error, "#{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
26
+ end
28
27
 
28
+ # Returns a sorted array of model IDs available at the endpoint.
29
+ def list_models
30
+ response = get_models_response
29
31
  raise Error, "#{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
32
+
33
+ Array(JSON.parse(response.body)["data"]).map { |m| m["id"] }.sort
34
+ rescue JSON::ParserError => e
35
+ raise Error, "could not parse models response: #{e.message}"
30
36
  end
31
37
 
32
38
  def generate_slides(deck)
@@ -44,6 +50,13 @@ module Slidict
44
50
 
45
51
  private
46
52
 
53
+ def get_models_response
54
+ uri = endpoint_uri("models")
55
+ request = Net::HTTP::Get.new(uri)
56
+ request["Authorization"] = "Bearer #{@api_key}"
57
+ perform_request(uri, request)
58
+ end
59
+
47
60
  def prompt_for(deck)
48
61
  <<~PROMPT
49
62
  You are an assistant that designs presentation slide outlines.
@@ -191,7 +204,7 @@ module Slidict
191
204
  return candidate if candidate
192
205
  end
193
206
 
194
- raise Error, "no JSON array found in model response"
207
+ raise Error, "no JSON array found in model response\nThe model may be too small to follow the required output format. Try using a larger model."
195
208
  end
196
209
 
197
210
  def json_array_from(content, start)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Slidict
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slidict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Abe