ollama-client 0.2.7 → 1.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.cursor/.gitignore +1 -0
  3. data/.rubocop_todo.yml +66 -0
  4. data/API_CONTRACT.md +166 -0
  5. data/CHANGELOG.md +26 -40
  6. data/CLAUDE.md +56 -0
  7. data/README.md +223 -1383
  8. data/SECURITY.md +17 -0
  9. data/devagent_proper.rb +430 -0
  10. data/docs/API_GAPS.md +143 -0
  11. data/docs/AREAS_FOR_CONSIDERATION.md +3 -3
  12. data/docs/CONSOLE_IMPROVEMENTS.md +1 -1
  13. data/docs/GETTING_STARTED.md +25 -7
  14. data/docs/INTEGRATION_TESTING.md +9 -9
  15. data/docs/PRODUCTION_FIXES.md +1 -1
  16. data/docs/QUICK_START.md +2 -2
  17. data/examples/agent_loop.rb +120 -0
  18. data/examples/failure_modes/invalid_json_repair.rb +42 -0
  19. data/examples/production/rails_agent.rb +62 -0
  20. data/examples/timeout_retry.rb +40 -0
  21. data/exe/ollama-client +187 -110
  22. data/lib/ollama/capabilities.rb +60 -0
  23. data/lib/ollama/client/chat.rb +140 -0
  24. data/lib/ollama/client/generate.rb +389 -0
  25. data/lib/ollama/client/model_management.rb +206 -0
  26. data/lib/ollama/client.rb +51 -804
  27. data/lib/ollama/config.rb +51 -7
  28. data/lib/ollama/embeddings.rb +25 -6
  29. data/lib/ollama/errors.rb +3 -0
  30. data/lib/ollama/options.rb +93 -15
  31. data/lib/ollama/response.rb +89 -7
  32. data/lib/ollama/version.rb +1 -1
  33. data/lib/ollama_client.rb +0 -9
  34. data/market.jpg +0 -0
  35. data/print_capabilities.rb +20 -0
  36. data/schema.json +1 -0
  37. data/test_tool.rb +26 -0
  38. metadata +26 -44
  39. data/examples/README.md +0 -91
  40. data/examples/basic_chat.rb +0 -33
  41. data/examples/basic_generate.rb +0 -29
  42. data/examples/mcp_executor.rb +0 -39
  43. data/examples/mcp_http_executor.rb +0 -45
  44. data/examples/tool_calling_parsing.rb +0 -59
  45. data/examples/tool_dto_example.rb +0 -94
  46. data/lib/ollama/agent/executor.rb +0 -258
  47. data/lib/ollama/agent/messages.rb +0 -31
  48. data/lib/ollama/agent/planner.rb +0 -52
  49. data/lib/ollama/chat_session.rb +0 -101
  50. data/lib/ollama/document_loader.rb +0 -163
  51. data/lib/ollama/mcp/http_client.rb +0 -149
  52. data/lib/ollama/mcp/stdio_client.rb +0 -146
  53. data/lib/ollama/mcp/tools_bridge.rb +0 -72
  54. data/lib/ollama/mcp.rb +0 -31
  55. data/lib/ollama/personas.rb +0 -287
  56. data/lib/ollama/streaming_observer.rb +0 -22
  57. data/lib/ollama/tool/function/parameters/property.rb +0 -72
  58. data/lib/ollama/tool/function/parameters.rb +0 -101
  59. data/lib/ollama/tool/function.rb +0 -78
  60. data/lib/ollama/tool.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53bd3c1ff3323d004a7ba3549317ef49d3ce9698d41133a1d2150d0a5135fa80
4
- data.tar.gz: 4c726b2a7fabf164c91cd51206266d250de836986d1a36726556cbefb47a6e8e
3
+ metadata.gz: 35dd7d6fe83f10045ed0ea1efa14f5ffc7547b8f132a5a504ad5fcbad40843ec
4
+ data.tar.gz: ca238782d4431c3c0beeee0615dca25699d479a66fe44c88509f8905803656a6
5
5
  SHA512:
6
- metadata.gz: 1cdcc10b54d2fa318daefc2736d338715b65f03cacf94c7c9303c07ec745ea510e6de0ac73c0c668b0301481663989af1368d86727ebfa1252a43edab9d7d711
7
- data.tar.gz: aead7b8ae703d436866cf796e91b102fbcc21ff47e6528c2edf62b13a1bac1f98f36d1146ba3e56a7fa0792bd0aff0880be65450c05b2352336cd20b39b3f9ab
6
+ metadata.gz: 51ece11f047b2ed872a0860b04d3e0cc2cfbbf443259deef5edddbf8511ac94318d8e7ea3ccfb6251945e1d38abe96fc31b366d6905c9ed45cc452530ad01b61
7
+ data.tar.gz: c5f8cf9f1296768c13740e4462abe3bbe0aaa48e936da720a061c55f6c9456362e32b7a1aa5fcaac09c630e0e4beac36b3990e6673367434defb234eb2895dc4
@@ -0,0 +1 @@
1
+ plans/
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,66 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2026-02-22 07:05:15 UTC using RuboCop version 1.82.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
11
+ # AllowedMethods: refine
12
+ Metrics/BlockLength:
13
+ Max: 26
14
+
15
+ # Offense count: 0 (resolved via module extraction in lib/ollama/client/)
16
+ # Metrics/ClassLength - no longer needed
17
+
18
+ # Offense count: 1
19
+ # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
20
+ Metrics/MethodLength:
21
+ Exclude:
22
+ - 'spec/**/*'
23
+ - 'examples/**/*'
24
+ - 'devagent_proper.rb'
25
+
26
+ # Offense count: 1
27
+ # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
28
+ Metrics/ParameterLists:
29
+ Max: 6
30
+
31
+ # Offense count: 1
32
+ # This cop supports unsafe autocorrection (--autocorrect-all).
33
+ # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
34
+ # SupportedStyles: described_class, explicit
35
+ RSpec/DescribedClass:
36
+ Exclude:
37
+ - 'spec/ollama/errors_spec.rb'
38
+ - 'spec/integration/client_integration_spec.rb'
39
+
40
+ # Offense count: 1
41
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
42
+ # SupportedInflectors: default, active_support
43
+ RSpec/SpecFilePathFormat:
44
+ Exclude:
45
+ - 'spec/ollama/client_model_suggestions_spec.rb'
46
+ - 'spec/integration/client_integration_spec.rb'
47
+
48
+ # Offense count: 4
49
+ # Configuration parameters: AllowedConstants.
50
+ Style/Documentation:
51
+ Exclude:
52
+ - 'examples/**/*'
53
+ - 'devagent_proper.rb'
54
+
55
+ # Offense count: 2
56
+ # This cop supports safe autocorrection (--autocorrect).
57
+ Style/IfUnlessModifier:
58
+ Exclude:
59
+ - 'lib/ollama/schema_validator.rb'
60
+
61
+ # Offense count: 2
62
+ # This cop supports safe autocorrection (--autocorrect).
63
+ # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
64
+ # URISchemes: http, https
65
+ Layout/LineLength:
66
+ Max: 136
data/API_CONTRACT.md ADDED
@@ -0,0 +1,166 @@
1
+ # API Contract — v1.0.0
2
+
3
+ This document defines the **public API surface** of `ollama-client` v1.0.
4
+ Everything listed here is guaranteed stable until `v2.0.0`.
5
+
6
+ ## Public Methods
7
+
8
+ ### `Ollama::Client`
9
+
10
+ ```ruby
11
+ client = Ollama::Client.new(config: Ollama::Config.new)
12
+ ```
13
+
14
+ #### Chat
15
+
16
+ | Method | Signature | Returns |
17
+ |---|---|---|
18
+ | `chat` | `(messages:, model: nil, format: nil, tools: nil, stream: nil, think: nil, keep_alive: nil, options: nil, logprobs: nil, top_logprobs: nil, hooks: {})` | `Ollama::Response` |
19
+
20
+ #### Generate
21
+
22
+ | Method | Signature | Returns |
23
+ |---|---|---|
24
+ | `generate` | `(prompt:, schema: nil, model: nil, strict: config.strict_json, return_meta: false, system: nil, images: nil, think: nil, return_reasoning: false, keep_alive: nil, suffix: nil, raw: nil, options: nil, hooks: {})` | `String` (no schema) or `Hash` (with schema) |
25
+
26
+ When `think: true` and `return_reasoning: true`, the return value is a `Hash` with:
27
+
28
+ - `"reasoning"` — the extracted reasoning text (may be empty string)
29
+ - `"final"` — either a `String` (no schema) or a `Hash` (when `schema:` is provided)
30
+
31
+ #### Model Management
32
+
33
+ | Method | Signature | Returns |
34
+ |---|---|---|
35
+ | `list_models` | `()` | `Array<Hash>` |
36
+ | `list_model_names` | `()` | `Array<String>` |
37
+ | `list_running` / `ps` | `()` | `Array<Hash>` |
38
+ | `show_model` | `(model:, verbose: false)` | `Hash` |
39
+ | `pull` | `(model_name)` | `true` |
40
+ | `delete_model` | `(model:)` | `true` |
41
+ | `copy_model` | `(source:, destination:)` | `true` |
42
+ | `create_model` | `(model:, from:, system: nil, template: nil, license: nil, parameters: nil, messages: nil, quantize: nil, stream: false)` | `Hash` |
43
+ | `push_model` | `(model:, insecure: false, stream: false)` | `Hash` |
44
+ | `version` | `()` | `String` |
45
+ | `embeddings` | _(attr_reader)_ | `Ollama::Embeddings` instance |
46
+
47
+ ### `Ollama::Embeddings`
48
+
49
+ ```ruby
50
+ client.embeddings.embed(model: "nomic-embed-text:latest", input: "text")
51
+ ```
52
+
53
+ | Method | Signature | Returns |
54
+ |---|---|---|
55
+ | `embed` | `(model:, input:, truncate: nil, dimensions: nil, keep_alive: nil, options: nil)` | `Array<Float>` (single) or `Array<Array<Float>>` (batch) |
56
+
57
+ ### `Ollama::Response`
58
+
59
+ Returned by `chat`. Wraps the API response with accessor methods:
60
+
61
+ | Method | Returns | Description |
62
+ |---|---|---|
63
+ | `message` | `Ollama::Response::Message` | Message wrapper |
64
+ | `content` | `String` | Shorthand for `message.content` |
65
+ | `done?` | `Boolean` | Whether generation finished |
66
+ | `done_reason` | `String` | Why generation stopped (`"stop"`, etc.) |
67
+ | `model` | `String` | Model name used |
68
+ | `total_duration` | `Integer` | Total time (nanoseconds) |
69
+ | `load_duration` | `Integer` | Model load time |
70
+ | `prompt_eval_count` | `Integer` | Prompt token count |
71
+ | `eval_count` | `Integer` | Response token count |
72
+ | `logprobs` | `Array` | Log probabilities (when enabled) |
73
+
74
+ #### `Ollama::Response::Message`
75
+
76
+ | Method | Returns | Description |
77
+ |---|---|---|
78
+ | `content` | `String` | Message content |
79
+ | `thinking` | `String` | Thinking output (when `think: true`) |
80
+ | `role` | `String` | `"assistant"` |
81
+ | `tool_calls` | `Array<ToolCall>` | Function calls |
82
+ | `images` | `Array<String>` | Base64 images |
83
+
84
+ ### `Ollama::Options`
85
+
86
+ Type-safe runtime options passed via `options:` parameter:
87
+
88
+ ```ruby
89
+ Ollama::Options.new(temperature: 0.7, num_predict: 256)
90
+ ```
91
+
92
+ Valid keys: `temperature`, `top_p`, `top_k`, `num_ctx`, `repeat_penalty`, `seed`, `num_predict`, `stop`, `tfs_z`, `mirostat`, `mirostat_tau`, `mirostat_eta`, `num_gpu`, `num_thread`, `num_keep`, `typical_p`, `presence_penalty`, `frequency_penalty`.
93
+
94
+ ### `Ollama::Config`
95
+
96
+ All attributes are read/write via `attr_accessor`:
97
+
98
+ | Attribute | Type | Default | Description |
99
+ |---|---|---|---|
100
+ | `base_url` | `String` | `"http://localhost:11434"` | Ollama server URL |
101
+ | `api_key` | `String, nil` | `nil` | Optional Bearer token for Ollama Cloud (`https://ollama.com`) |
102
+ | `model` | `String` | `"llama3.2:3b"` | Default model for generation |
103
+ | `timeout` | `Integer` | `30` | HTTP read/open timeout in seconds |
104
+ | `retries` | `Integer` | `2` | Max retry attempts |
105
+ | `strict_json` | `Boolean` | `true` | Enable JSON validation + repair |
106
+ | `temperature` | `Float` | `0.2` | Sampling temperature |
107
+ | `top_p` | `Float` | `0.9` | Nucleus sampling |
108
+ | `num_ctx` | `Integer` | `8192` | Context window size |
109
+ | `on_response` | `Proc/nil` | `nil` | Global response callback |
110
+
111
+ ## Error Classes
112
+
113
+ All errors inherit from `Ollama::Error < StandardError`.
114
+
115
+ | Error | Raised When | Retryable? |
116
+ |---|---|---|
117
+ | `Ollama::Error` | Base class / connection failures | **No** — fast fail |
118
+ | `Ollama::TimeoutError` | `Net::ReadTimeout` / `Net::OpenTimeout` | **Yes** — exponential backoff |
119
+ | `Ollama::InvalidJSONError` | Response cannot be parsed as JSON | **Yes** — repair prompt retry |
120
+ | `Ollama::SchemaViolationError` | Parsed JSON fails schema validation | **Yes** — repair prompt retry |
121
+ | `Ollama::RetryExhaustedError` | All retry attempts exhausted | **No** — terminal |
122
+ | `Ollama::HTTPError` | Non-200 HTTP response | Depends on status code |
123
+ | `Ollama::NotFoundError` | HTTP 404 (model not found) | **Auto-handled** — triggers pull |
124
+ | `Ollama::StreamError` | `{"error": "..."}` in NDJSON stream | **No** — immediate |
125
+
126
+ ## Recovery Behaviors (Guaranteed)
127
+
128
+ | Scenario | Behavior |
129
+ |---|---|
130
+ | Model missing (404) | Auto-pull once → retry original request |
131
+ | Timeout | Exponential backoff: `sleep(2 ** attempt)` |
132
+ | Invalid JSON (strict mode) | Append repair prompt → retry |
133
+ | Schema violation (strict mode) | Append repair prompt → retry |
134
+ | Server unreachable (ECONNREFUSED) | Immediate `Ollama::Error` — no retries |
135
+ | All retries exhausted | `Ollama::RetryExhaustedError` |
136
+ | Streaming error | `Ollama::StreamError` with server message |
137
+
138
+ ## Streaming Hooks
139
+
140
+ Passed via `hooks:` parameter on `generate` and `chat`:
141
+
142
+ ```ruby
143
+ hooks: {
144
+ on_token: ->(token) { ... }, # Called per token chunk
145
+ on_error: ->(error) { ... }, # Called on stream error
146
+ on_complete: -> { ... } # Called when stream finishes
147
+ }
148
+ ```
149
+
150
+ Hooks are **observer-only** — they cannot modify the response. Streaming is auto-enabled when any hook is present.
151
+
152
+ ## What Will NOT Change Before v2.0
153
+
154
+ 1. Method signatures listed above
155
+ 2. Error class hierarchy
156
+ 3. Default config values
157
+ 4. Recovery behaviors (auto-pull, backoff, repair)
158
+ 5. JSON schema validation via `json-schema` gem
159
+ 6. Observer-style hooks interface
160
+
161
+ ## What MAY Change (Minor Versions)
162
+
163
+ - New optional keyword arguments on existing methods
164
+ - New error subclasses (always inheriting from existing hierarchy)
165
+ - Additional config attributes (always with backwards-compatible defaults)
166
+ - Performance improvements to retry/backoff timing
data/CHANGELOG.md CHANGED
@@ -1,49 +1,35 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
- ## [0.2.7] - 2026-02-04
3
+ All notable changes to this project will be documented in this file.
4
4
 
5
- - Add MCP (Model Context Protocol) support for local and remote servers
6
- - Add `Ollama::MCP::StdioClient` for local MCP servers over stdio (e.g. `npx @modelcontextprotocol/server-filesystem`)
7
- - Add `Ollama::MCP::HttpClient` for remote MCP servers over HTTP (e.g. [gitmcp.io](https://gitmcp.io)/owner/repo)
8
- - Add `Ollama::MCP::ToolsBridge` to expose MCP tools to `Ollama::Agent::Executor` (`client:` or `stdio_client:`)
9
- - Add examples: `examples/mcp_executor.rb` (stdio), `examples/mcp_http_executor.rb` (URL)
10
- - Document MCP usage and GitMCP URL in README; fix RuboCop offenses in MCP code
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
7
 
12
- ## [0.2.6] - 2026-01-26
8
+ ## [1.1.0] - 2026-03-17
13
9
 
14
- - Reorganize examples: move agent examples to separate repository, keep minimal client examples
15
- - Add comprehensive test coverage (increased from 65.66% to 79.59%)
16
- - Add test suite for `Ollama::DocumentLoader` (file loading, context building)
17
- - Add test suite for `Ollama::Embeddings` (API calls, error handling)
18
- - Add test suite for `Ollama::ChatSession` (session management)
19
- - Add test suite for tool classes (`Tool`, `Function`, `Parameters`, `Property`)
20
- - Rewrite testing documentation to focus on client-only testing (transport/protocol)
21
- - Add test checklist with specific test categories (G1-G3, C1-C3, A1-A2, F1-F3)
22
- - Update README with enhanced "What This Gem IS NOT" section
23
- - Fix RuboCop offenses and improve code quality
10
+ ### Added
11
+ - Ollama Cloud support via `Ollama::Config#api_key` and HTTPS `base_url` (e.g. `https://ollama.com`).
12
+ - `Ollama::Config#http_connection_options` to centralize Net::HTTP connection options (including SSL and timeouts).
13
+ - `Ollama::Config#inspect` now redacts `api_key` while keeping other attributes visible.
24
14
 
25
- ## [0.2.5] - 2026-01-22
15
+ ### Changed
16
+ - Chat, generate, embeddings, and model management HTTP calls now share connection-option logic but keep existing behavior.
26
17
 
27
- - Add `Ollama::DocumentLoader` for loading files as context in queries
28
- - Enhance README with context provision methods and examples
29
- - Improve embeddings error handling and model usage guidance
30
- - Add comprehensive Ruby guide documentation
31
- - Update `generate()` method with enhanced functionality and usage examples
32
- - Improve error handling across client and embeddings modules
18
+ ## [1.0.0] - 2026-02-22
33
19
 
34
- ## [0.2.3] - 2026-01-17
20
+ ### Changed
21
+ - **Massive surface area reduction:** Removed `chat`, `chat_raw`, `call_chat_api`, `call_chat_api_raw`, and related endpoints.
22
+ - **Architectural Shift:** Removed all chatbot UI logic (`ChatSession`, `Personas`), abstract Agent implementations (`Planner`, `Executor`), and `DocumentLoader` to enforce strict low-level determinism.
23
+ - **API Contracts:** `Client#generate` now handles strict JSON schemas directly and implements resilient auto-recovery.
24
+ - **Defaults:** Opinionated defaults out-of-the-box (`timeout: 30`, `retries: 2`, `strict_json: true`).
25
+ - **Streaming Hooks:** Deprecated raw SSE streaming over `chat` in favor of safe observer callbacks (`on_token`, `on_error`, `on_complete`) on `generate`.
26
+ - **Model Auto-Pulling:** If `generate` receives a 404 Model Not Found, it attempts to synchronously `/pull` the model once, and then automatically retries generation.
27
+ - **JSON Repair Loop:** Provided `strict_json: true`, if a model hallucinates malformed JSON formatting (like wrapping in markdown code blocks), the client automatically loops a retry with a CRITICAL repair prompt to seamlessly fix the output.
28
+ - **Backoff:** Encountering a `Net::ReadTimeout` now triggers an exponential backoff sleep (`2 ** attempt`) between retries rather than immediately re-hammering the server.
35
29
 
36
- - Add per-call `model:` override for `Ollama::Client#generate`.
37
- - Document `generate` model override usage in README.
38
- - Add spec to cover per-call `model:` in 404 error path.
30
+ ### Security
31
+ - **Strict Error Boundaries:** Malformed payloads can no longer leak into application state due to strict `SchemaViolationError` bounding.
32
+ - **Fast-fail Networking:** Encountering `Errno::ECONNREFUSED` fast-fails immediately.
39
33
 
40
- ## [0.2.0] - 2026-01-12
41
-
42
- - Add `Ollama::Agent::Planner` (stateless `/api/generate`)
43
- - Add `Ollama::Agent::Executor` (stateful `/api/chat` tool loop)
44
- - Add `Ollama::StreamingObserver` + disciplined streaming support (Executor only)
45
- - Add `Ollama::Client#chat_raw` (full response body, supports tool calls)
46
-
47
- ## [0.1.0] - 2026-01-04
48
-
49
- - Initial release
34
+ ### Rationale
35
+ Version `1.0.0` repositions `ollama-client` away from a bloated general-purpose wrapper toward a production-safe, failure-aware adapter intentionally crafted for Headless Rails Jobs and Agent Systems. By severing chat tools and abstractions, the gem commits to a strictly deterministic API that doesn't collapse under back-pressure, missing models, or temporary JSON formatting hallucinations.
data/CLAUDE.md ADDED
@@ -0,0 +1,56 @@
1
+ # ollama-client
2
+
3
+ Ruby gem — Ollama HTTP client for agent-grade usage. Provides `chat`, `generate`, embeddings, and full model management. Stable public API defined in `API_CONTRACT.md`.
4
+
5
+ ## Stack
6
+
7
+ - Ruby gem (no Rails)
8
+ - Zeitwerk autoloader
9
+ - RSpec + WebMock + Timecop + SimpleCov
10
+ - RuboCop
11
+
12
+ ## Commands
13
+
14
+ ```bash
15
+ bundle exec rspec
16
+ COVERAGE=true bundle exec rspec
17
+ bundle exec rubocop
18
+ bundle exec rake
19
+ ```
20
+
21
+ ## Architecture
22
+
23
+ ```
24
+ lib/ollama/
25
+ client.rb # Top-level entry point
26
+ client/
27
+ chat.rb # chat() method
28
+ generate.rb # generate() method
29
+ model_management.rb # list, pull, delete, copy, create, push, version
30
+ config.rb # Ollama::Config (base_url, model, timeout, retries, strict_json, etc.)
31
+ response.rb # Ollama::Response wrapper
32
+ embeddings.rb # client.embeddings.embed()
33
+ options.rb # Model options (temperature, top_p, num_ctx)
34
+ dto.rb # Data transfer objects
35
+ schema_validator.rb # JSON schema validation for structured output
36
+ schemas/ # Built-in JSON schemas
37
+ capabilities.rb # Model capability detection
38
+ errors.rb # Error hierarchy
39
+ version.rb
40
+ ```
41
+
42
+ ## Public API (stable — see API_CONTRACT.md)
43
+
44
+ - `client.chat(messages:, model:, tools:, stream:, think:, ...)` → `Ollama::Response`
45
+ - `client.generate(prompt:, schema:, model:, strict:, ...)` → `String` or `Hash`
46
+ - `client.embeddings.embed(model:, input:)` → `Array<Float>`
47
+ - Model management: `list_models`, `pull`, `delete_model`, `copy_model`, `create_model`, `push_model`, `version`
48
+
49
+ ## Key rules
50
+
51
+ - **Never break the public API** — changes to method signatures require a version bump and API_CONTRACT.md update
52
+ - All HTTP calls must be mockable with WebMock — never require live Ollama in tests
53
+ - `Ollama::Config` defaults to `localhost:11434` — config is per-client, not global (thread-safe)
54
+ - `generate` with `schema:` returns a parsed Hash; without `schema:` returns raw String — never mix
55
+ - `strict_json: true` (default) — do not disable in production code
56
+ - Thread safety: per-client config is safe; modifying global config while clients are active is not