ruby_llm-providers-lms 0.1.1 → 0.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -0
  3. data/README.md +467 -104
  4. data/lib/ruby_llm/providers/lms/anthropic_messages.rb +28 -0
  5. data/lib/ruby_llm/providers/lms/endpoints.rb +18 -0
  6. data/lib/ruby_llm/providers/lms/model_management.rb +59 -0
  7. data/lib/ruby_llm/providers/lms/models.rb +44 -12
  8. data/lib/ruby_llm/providers/lms/native_chat/conversation.rb +93 -0
  9. data/lib/ruby_llm/providers/lms/native_chat/streaming.rb +67 -0
  10. data/lib/ruby_llm/providers/lms/native_chat.rb +134 -0
  11. data/lib/ruby_llm/providers/lms/native_v1.rb +97 -0
  12. data/lib/ruby_llm/providers/lms/responses.rb +47 -0
  13. data/lib/ruby_llm/providers/lms/version.rb +15 -0
  14. data/lib/ruby_llm/providers/lms.rb +51 -1
  15. data/models.json +69 -454
  16. metadata +15 -40
  17. data/.flayignore +0 -1
  18. data/.github/workflows/ci.yml +0 -29
  19. data/.github/workflows/gitleaks.yml +0 -22
  20. data/.github/workflows/release.yml +0 -36
  21. data/.overcommit.yml +0 -31
  22. data/.rspec +0 -2
  23. data/.rubocop.yml +0 -29
  24. data/Archspec.rb +0 -14
  25. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_openai_gpt_oss_20b_can_handle_a_multi_turn_conversation.yml +0 -92
  26. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_openai_gpt_oss_20b_can_have_a_basic_conversation.yml +0 -45
  27. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_openai_gpt_oss_20b_can_use_tools.yml +0 -129
  28. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_openai_gpt_oss_20b_returns_the_raw_response.yml +0 -73
  29. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_openai_gpt_oss_20b_supports_streaming_responses.yml +0 -81
  30. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_qwen3_0_6b_bible_assistant_can_have_a_basic_conversation.yml +0 -73
  31. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_qwen3_0_6b_bible_assistant_returns_structured_output.yml +0 -73
  32. data/spec/fixtures/vcr_cassettes/rubyllm_chat_lms_qwen3_0_6b_bible_assistant_returns_the_raw_response.yml +0 -73
  33. data/spec/fixtures/vcr_cassettes/rubyllm_embedding_lms_text_embedding_nomic_embed_text_v1_5_embeds_one_text.yml +0 -828
  34. data/spec/fixtures/vcr_cassettes/rubyllm_embedding_lms_text_embedding_nomic_embed_text_v1_5_embeds_several_texts.yml +0 -2375
  35. data/spec/ruby_llm/chat_schema_spec.rb +0 -30
  36. data/spec/ruby_llm/chat_spec.rb +0 -35
  37. data/spec/ruby_llm/chat_streaming_spec.rb +0 -22
  38. data/spec/ruby_llm/chat_tools_spec.rb +0 -30
  39. data/spec/ruby_llm/embedding_spec.rb +0 -49
  40. data/spec/ruby_llm/image_spec.rb +0 -23
  41. data/spec/ruby_llm/models_spec.rb +0 -11
  42. data/spec/ruby_llm/moderation_spec.rb +0 -22
  43. data/spec/ruby_llm/providers/lms/connection_guard_spec.rb +0 -47
  44. data/spec/ruby_llm/providers/lms_spec.rb +0 -153
  45. data/spec/ruby_llm/rerank_spec.rb +0 -23
  46. data/spec/ruby_llm/speech_spec.rb +0 -25
  47. data/spec/ruby_llm/video_spec.rb +0 -27
  48. data/spec/spec_helper.rb +0 -26
  49. data/spec/support/models.rb +0 -29
  50. data/spec/support/rubyllm_configuration.rb +0 -14
  51. data/spec/support/vcr_configuration.rb +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdaf33f5245f3b78bcfd33a13c7f2a0838149de0998b09c7f8e4256e447cda69
4
- data.tar.gz: 285c1c5ddff4227b90b435755b8cc29b1a28bb695fa33c7f1c6510ce3a5853cb
3
+ metadata.gz: 4f9e03ee21a139367f15f9e32795a4a204a7304f9ea9b13df18e44aa69f6db6e
4
+ data.tar.gz: '016568a32db5f3be0a6fd5dee88c827ff618a2a2dac9f1e6d6117c143a94acd7'
5
5
  SHA512:
6
- metadata.gz: 548a88a50a88795f9b5b7cd11c64ee1c43e76406c7730c34c42cf90bf2e748eded77029f38f9994f5ab8820a05d7e0479118e8a43f3dbb165a3bc11e0297a892
7
- data.tar.gz: d01419d61951513cc00dcd72e546f7a56e2023fa59ff1bcadc99e0b117f1bdfab6b06c541078b0a984dede41f025e9668fd00921086b3163c5590654d1d99bc2
6
+ metadata.gz: c7f09535ee1ceb6032d2fad666dac9e7d9ae11ac544d1f1289e812005deb2103df46f9af5fb589023c6a4a4286c5001b2285b77b138e1ccbba04243a3dab67c1
7
+ data.tar.gz: 2c5160290b2f84aeca8a125c4f8f0866a0cf2da1e93a9078ac6aacb675e82026b52ff3ef5bea09632ff61ac99578fe164df2df0ac86f85cd542494ec79a81968
data/CHANGELOG.md ADDED
@@ -0,0 +1,128 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are 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.2.1] - 2026-09-18
9
+
10
+ ### Changed
11
+
12
+ - Require the released `ruby_llm >= 2.0.0` instead of the `2.0.0.rc1`
13
+ prerelease floor. Tested against RubyLLM 2.0.0.
14
+
15
+ ## [0.2.0] - 2026-09-14
16
+
17
+ ### Added
18
+
19
+ - `:native_chat` protocol for LM Studio's native chat API (`POST /api/v1/chat`).
20
+ The endpoint is stateful — LM Studio stores each response and continues from a
21
+ `response_id` — so the protocol sends only the messages newer than the last
22
+ assistant response and points `previous_response_id` at it, which makes ordinary
23
+ multi-turn `RubyLLM::Chat` work on top of it. The id rides on
24
+ `Message#raw_content`, which RubyLLM persists, so a chat reloaded from the
25
+ database continues rather than refusing to replay. Streaming included.
26
+ Native-only options reach the request through `with_provider_options`:
27
+ `integrations:` (MCP plugins or ephemeral MCP servers the server runs itself),
28
+ `context_length:`, `store: false`, and the sampling settings the native schema
29
+ accepts (`top_p`, `top_k`, `min_p`, `repeat_penalty`). The endpoint reports no
30
+ stop reason of its own, so a generation that runs into `max_output_tokens` is
31
+ reported as `finish_reason: :length` from the token counts.
32
+ - `:native_v0` protocol — LM Studio's `POST /api/v0/chat/completions`. Same wire
33
+ shape as the OpenAI-compatible endpoint, but the response carries the `stats`
34
+ block that `/v1/chat/completions` leaves empty (tokens per second, time to first
35
+ token, generation time, stop reason) plus `model_info` and `runtime`, reachable
36
+ through `Message#raw`.
37
+ - `:anthropic` protocol — LM Studio also serves Anthropic's Messages API, driven
38
+ by RubyLLM's stock Anthropic protocol with only the request path adjusted.
39
+ - Model management on the provider, backed by LM Studio's native REST API:
40
+ `native_models`, `loaded_models`, `load_model` (with an optional
41
+ `context_length:` override), `unload_model`, and `download_model`. All three
42
+ writes are sent non-idempotent: RubyLLM retries a POST that times out, and
43
+ LM Studio answers a second load of a resident model by starting a second
44
+ instance, so a replayed load would hold the weights in memory twice.
45
+ - Reasoning control across every protocol that supports it. LM Studio reports
46
+ each model's reasoning vocabulary in its own spelling (`off`, `low`, `medium`,
47
+ `high`, `xhigh`, `on`); the provider translates it into the vocabulary
48
+ RubyLLM's registry reads — `off` becomes the `none` effort, `on` becomes a
49
+ `:toggle` option — so `with_thinking`, `with_thinking(false)` and
50
+ `with_thinking(effort:)` all resolve against what the model actually supports.
51
+ The native endpoint takes a different spelling from the OpenAI ones, so
52
+ `:native_chat` translates `none` back to `off` on the way out.
53
+ - `reasoning` and `tool_choice` capabilities on listed models, alongside the
54
+ `function_calling` and `vision` already derived from the native listing.
55
+ - Model listings read LM Studio's native v1 listing (`/api/v1/models`) when the
56
+ server has one and fall back to the v0 listing otherwise, adding display name,
57
+ description, parameter count, size on disk, quantization bit width, downloaded
58
+ variants and the selected one, reasoning options, and the loaded instance's
59
+ context length and remaining idle TTL to each model's metadata.
60
+ - Embeddings always go to `POST /v1/embeddings`, whichever chat dialect
61
+ `lms_protocol` selects — LM Studio serves them nowhere else, and resolving
62
+ them through the configured chat protocol meant `:anthropic` refused them
63
+ outright.
64
+ - `RubyLLM::Providers::LMS::VERSION` and `RubyLLM::Providers::LMS.version`.
65
+ - Examples 11-15: native inference stats, the Anthropic protocol, the native chat
66
+ protocol, model management, and a protocol capability matrix.
67
+
68
+ ### Fixed
69
+
70
+ - The `:responses` protocol dropped reasoning text. OpenAI never returns raw
71
+ reasoning, only an optional summary, so RubyLLM's stock protocol reads a
72
+ reasoning item's `summary` and the matching
73
+ `response.reasoning_summary_text.delta` event. LM Studio returns the reasoning
74
+ itself in `content` as `reasoning_text`, streamed as
75
+ `response.reasoning_text.delta`, leaving `summary` empty — so the response
76
+ spent reasoning tokens and `message.thinking` came back nil. A
77
+ `LMS::Responses` subclass now reads both shapes, on the sync and streaming
78
+ paths alike.
79
+ - The published gem no longer ships `spec/` and its VCR cassettes, which are
80
+ recorded conversations with the author's own models.
81
+
82
+ ### Changed
83
+
84
+ - Models are named by their LM Studio display name when the server reports one,
85
+ falling back to the model id.
86
+ - The `:responses` protocol is now `RubyLLM::Providers::LMS::Responses` rather
87
+ than RubyLLM's stock `Protocols::Responses`. Behaviour is unchanged apart from
88
+ the reasoning fix above; code that referenced the stock class by name should
89
+ follow.
90
+ - The gemspec reads the version from `lib/ruby_llm/providers/lms/version.rb`
91
+ instead of carrying its own literal.
92
+ - A failing `:live` spec no longer deletes its cassette, which let a real
93
+ regression pass on the next run by re-recording itself green. Pass
94
+ `RERECORD=1` to re-record deliberately.
95
+
96
+ ## [0.1.1] - 2026-09-11
97
+
98
+ ### Added
99
+
100
+ - A friendly `RubyLLM::Error` when the LM Studio server is not running.
101
+ Connection refusals bypass RubyLLM's error middleware, which only maps HTTP
102
+ status codes, so the raw `Faraday::ConnectionFailed` used to surface instead.
103
+ - Examples 01-10, covering basic usage, streaming, tools, structured output,
104
+ embeddings, the model catalog, the `:responses` protocol, the connection guard,
105
+ provider options, and provider introspection.
106
+
107
+ ### Fixed
108
+
109
+ - VCR cassettes replay without `LMS_API_BASE` set, so CI can run them.
110
+
111
+ ### Changed
112
+
113
+ - CI tests only non-EOL Rubies (3.3, 3.4, 4.0).
114
+
115
+ ## [0.1.0] - 2026-09-11
116
+
117
+ ### Added
118
+
119
+ - Initial release: a `:lms` provider for RubyLLM that talks to LM Studio's local
120
+ OpenAI-compatible server (`lms server start`, default
121
+ `http://localhost:1234/v1`) with no API key or configuration required.
122
+ - `:chat_completions` and `:responses` protocols.
123
+ - Model listings enriched from LM Studio's native REST API, plus a packaged
124
+ `models.json` fallback catalog.
125
+
126
+ [0.2.0]: https://github.com/madbomber/ruby_llm-providers-lms/compare/v0.1.1...v0.2.0
127
+ [0.1.1]: https://github.com/madbomber/ruby_llm-providers-lms/compare/v0.1.0...v0.1.1
128
+ [0.1.0]: https://github.com/madbomber/ruby_llm-providers-lms/releases/tag/v0.1.0