ollama-client 0.2.5 → 0.2.7

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +336 -91
  4. data/RELEASE_NOTES_v0.2.6.md +41 -0
  5. data/docs/AREAS_FOR_CONSIDERATION.md +325 -0
  6. data/docs/EXAMPLE_REORGANIZATION.md +412 -0
  7. data/docs/FEATURES_ADDED.md +12 -1
  8. data/docs/GETTING_STARTED.md +361 -0
  9. data/docs/INTEGRATION_TESTING.md +170 -0
  10. data/docs/NEXT_STEPS_SUMMARY.md +114 -0
  11. data/docs/PERSONAS.md +383 -0
  12. data/docs/QUICK_START.md +195 -0
  13. data/docs/TESTING.md +392 -170
  14. data/docs/TEST_CHECKLIST.md +450 -0
  15. data/examples/README.md +62 -63
  16. data/examples/basic_chat.rb +33 -0
  17. data/examples/basic_generate.rb +29 -0
  18. data/examples/mcp_executor.rb +39 -0
  19. data/examples/mcp_http_executor.rb +45 -0
  20. data/examples/tool_calling_parsing.rb +59 -0
  21. data/examples/tool_dto_example.rb +0 -0
  22. data/exe/ollama-client +128 -1
  23. data/lib/ollama/agent/planner.rb +7 -2
  24. data/lib/ollama/chat_session.rb +101 -0
  25. data/lib/ollama/client.rb +41 -35
  26. data/lib/ollama/config.rb +9 -4
  27. data/lib/ollama/document_loader.rb +1 -1
  28. data/lib/ollama/embeddings.rb +61 -28
  29. data/lib/ollama/errors.rb +1 -0
  30. data/lib/ollama/mcp/http_client.rb +149 -0
  31. data/lib/ollama/mcp/stdio_client.rb +146 -0
  32. data/lib/ollama/mcp/tools_bridge.rb +72 -0
  33. data/lib/ollama/mcp.rb +31 -0
  34. data/lib/ollama/options.rb +3 -1
  35. data/lib/ollama/personas.rb +287 -0
  36. data/lib/ollama/version.rb +1 -1
  37. data/lib/ollama_client.rb +17 -5
  38. metadata +22 -48
  39. data/examples/advanced_complex_schemas.rb +0 -366
  40. data/examples/advanced_edge_cases.rb +0 -241
  41. data/examples/advanced_error_handling.rb +0 -200
  42. data/examples/advanced_multi_step_agent.rb +0 -341
  43. data/examples/advanced_performance_testing.rb +0 -186
  44. data/examples/chat_console.rb +0 -143
  45. data/examples/complete_workflow.rb +0 -245
  46. data/examples/dhan_console.rb +0 -843
  47. data/examples/dhanhq/README.md +0 -236
  48. data/examples/dhanhq/agents/base_agent.rb +0 -74
  49. data/examples/dhanhq/agents/data_agent.rb +0 -66
  50. data/examples/dhanhq/agents/orchestrator_agent.rb +0 -120
  51. data/examples/dhanhq/agents/technical_analysis_agent.rb +0 -252
  52. data/examples/dhanhq/agents/trading_agent.rb +0 -81
  53. data/examples/dhanhq/analysis/market_structure.rb +0 -138
  54. data/examples/dhanhq/analysis/pattern_recognizer.rb +0 -192
  55. data/examples/dhanhq/analysis/trend_analyzer.rb +0 -88
  56. data/examples/dhanhq/builders/market_context_builder.rb +0 -67
  57. data/examples/dhanhq/dhanhq_agent.rb +0 -829
  58. data/examples/dhanhq/indicators/technical_indicators.rb +0 -158
  59. data/examples/dhanhq/scanners/intraday_options_scanner.rb +0 -492
  60. data/examples/dhanhq/scanners/swing_scanner.rb +0 -247
  61. data/examples/dhanhq/schemas/agent_schemas.rb +0 -61
  62. data/examples/dhanhq/services/base_service.rb +0 -46
  63. data/examples/dhanhq/services/data_service.rb +0 -118
  64. data/examples/dhanhq/services/trading_service.rb +0 -59
  65. data/examples/dhanhq/technical_analysis_agentic_runner.rb +0 -411
  66. data/examples/dhanhq/technical_analysis_runner.rb +0 -420
  67. data/examples/dhanhq/test_tool_calling.rb +0 -538
  68. data/examples/dhanhq/test_tool_calling_verbose.rb +0 -251
  69. data/examples/dhanhq/utils/instrument_helper.rb +0 -32
  70. data/examples/dhanhq/utils/parameter_cleaner.rb +0 -28
  71. data/examples/dhanhq/utils/parameter_normalizer.rb +0 -45
  72. data/examples/dhanhq/utils/rate_limiter.rb +0 -23
  73. data/examples/dhanhq/utils/trading_parameter_normalizer.rb +0 -72
  74. data/examples/dhanhq_agent.rb +0 -964
  75. data/examples/dhanhq_tools.rb +0 -1663
  76. data/examples/multi_step_agent_with_external_data.rb +0 -368
  77. data/examples/structured_outputs_chat.rb +0 -72
  78. data/examples/structured_tools.rb +0 -89
  79. data/examples/test_dhanhq_tool_calling.rb +0 -375
  80. data/examples/test_tool_calling.rb +0 -160
  81. data/examples/tool_calling_direct.rb +0 -124
  82. data/examples/tool_calling_pattern.rb +0 -269
  83. data/exe/dhan_console +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 687a8a4fbb73c24bbc408a902cbc94312923dd5c9a42823a2a5e13111977a6b9
4
- data.tar.gz: 6c7992774151468a99a855671d2e2e17058a613377de970f5647411c9f627b81
3
+ metadata.gz: 53bd3c1ff3323d004a7ba3549317ef49d3ce9698d41133a1d2150d0a5135fa80
4
+ data.tar.gz: 4c726b2a7fabf164c91cd51206266d250de836986d1a36726556cbefb47a6e8e
5
5
  SHA512:
6
- metadata.gz: c52ad58ee08f15b0014500ac9285c0d7a446447e72ec0df1da17b815ae249103adbf5f3a64ec66e83fc1c821e64d7297b84cd7e19d808c914c862fc3263e52ae
7
- data.tar.gz: fad07b8161e7e1442ecfc203b4774e23ceb5075fe660adc1636a1fe81a8ac4a8e27fad80c91bcc20964a9a13e6733a1cb88612cb6d6de2b4c01b5bbbeba6eaf2
6
+ metadata.gz: 1cdcc10b54d2fa318daefc2736d338715b65f03cacf94c7c9303c07ec745ea510e6de0ac73c0c668b0301481663989af1368d86727ebfa1252a43edab9d7d711
7
+ data.tar.gz: aead7b8ae703d436866cf796e91b102fbcc21ff47e6528c2edf62b13a1bac1f98f36d1146ba3e56a7fa0792bd0aff0880be65450c05b2352336cd20b39b3f9ab
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.7] - 2026-02-04
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
11
+
12
+ ## [0.2.6] - 2026-01-26
13
+
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
24
+
3
25
  ## [0.2.5] - 2026-01-22
4
26
 
5
27
  - Add `Ollama::DocumentLoader` for loading files as context in queries
data/README.md CHANGED
@@ -26,11 +26,15 @@ Domain tools and application logic live **outside** this gem. For convenience, i
26
26
 
27
27
  ## 🚫 What This Gem IS NOT
28
28
 
29
- * Domain tool implementations
30
- * ❌ Domain logic
31
- * ❌ Memory store
32
- * ❌ Chat UI
33
- * ❌ A promise of full Ollama API coverage (it focuses on agent workflows)
29
+ This gem is **NOT**:
30
+ * ❌ A chatbot UI framework
31
+ * ❌ A domain-specific agent implementation
32
+ * ❌ A tool execution engine
33
+ * ❌ A memory store
34
+ * ❌ A promise of full Ollama API coverage (focuses on agent workflows)
35
+ * ❌ An agent runtime (it provides transport + protocol, not agent logic)
36
+
37
+ **Domain tools and application logic live outside this gem.**
34
38
 
35
39
  This keeps it **clean and future-proof**.
36
40
 
@@ -68,13 +72,115 @@ Or install it yourself as:
68
72
  gem install ollama-client
69
73
  ```
70
74
 
75
+ ## Quick Start
76
+
77
+ ### Step 1: Simple Text Generation
78
+
79
+ ```ruby
80
+ require "ollama_client"
81
+
82
+ client = Ollama::Client.new
83
+
84
+ # Get plain text response (no schema = plain text)
85
+ response = client.generate(
86
+ prompt: "Explain Ruby blocks in one sentence"
87
+ )
88
+
89
+ puts response
90
+ # => "Ruby blocks are anonymous functions passed to methods..."
91
+ ```
92
+
93
+ ### Step 2: Structured Outputs (Recommended for Agents)
94
+
95
+ ```ruby
96
+ require "ollama_client"
97
+
98
+ client = Ollama::Client.new
99
+
100
+ # Define JSON schema
101
+ schema = {
102
+ "type" => "object",
103
+ "required" => ["action", "reasoning"],
104
+ "properties" => {
105
+ "action" => { "type" => "string", "enum" => ["search", "calculate", "finish"] },
106
+ "reasoning" => { "type" => "string" }
107
+ }
108
+ }
109
+
110
+ # Get structured decision
111
+ result = client.generate(
112
+ prompt: "User wants weather in Paris. What should I do?",
113
+ schema: schema
114
+ )
115
+
116
+ puts result["action"] # => "search"
117
+ puts result["reasoning"] # => "Need to fetch weather data..."
118
+ ```
119
+
120
+ ### Step 3: Agent Planning (Stateless)
121
+
122
+ ```ruby
123
+ require "ollama_client"
124
+
125
+ client = Ollama::Client.new
126
+ planner = Ollama::Agent::Planner.new(client)
127
+
128
+ decision_schema = {
129
+ "type" => "object",
130
+ "required" => ["action"],
131
+ "properties" => {
132
+ "action" => { "type" => "string", "enum" => ["search", "calculate", "finish"] }
133
+ }
134
+ }
135
+
136
+ plan = planner.run(
137
+ prompt: "Decide the next action",
138
+ schema: decision_schema
139
+ )
140
+
141
+ # Use the structured decision
142
+ case plan["action"]
143
+ when "search"
144
+ # Execute search
145
+ when "calculate"
146
+ # Execute calculation
147
+ when "finish"
148
+ # Task complete
149
+ end
150
+ ```
151
+
152
+ ### Step 4: Tool Calling (Stateful)
153
+
154
+ ```ruby
155
+ require "ollama_client"
156
+
157
+ client = Ollama::Client.new
158
+
159
+ # Define tools
160
+ tools = {
161
+ "get_weather" => ->(city:) { { city: city, temp: 22, condition: "sunny" } }
162
+ }
163
+
164
+ executor = Ollama::Agent::Executor.new(client, tools: tools)
165
+
166
+ answer = executor.run(
167
+ system: "You are a helpful assistant. Use tools when needed.",
168
+ user: "What's the weather in Paris?"
169
+ )
170
+
171
+ puts answer
172
+ # => "The weather in Paris is 22°C and sunny."
173
+ ```
174
+
175
+ **Next Steps:** See [Choosing the Correct API](#choosing-the-correct-api-generate-vs-chat) below for guidance on when to use each method.
176
+
71
177
  ## Usage
72
178
 
73
179
  **Note:** You can use `require "ollama_client"` (recommended) or `require "ollama/client"` directly. The client works with or without the global `OllamaClient` configuration module.
74
180
 
75
181
  ### Primary API: `generate()`
76
182
 
77
- **`generate(prompt:, schema: nil)`** is the **primary and recommended method** for agent-grade usage:
183
+ **`generate(prompt:, schema: nil, model: nil, strict: false, return_meta: false)`** is the **primary and recommended method** for agent-grade usage:
78
184
 
79
185
  - ✅ Stateless, explicit state injection
80
186
  - ✅ Uses `/api/generate` endpoint
@@ -85,11 +191,46 @@ gem install ollama-client
85
191
  **This is the method you should use for hybrid agents.**
86
192
 
87
193
  **Usage:**
88
- - **With schema** (structured JSON): `generate(prompt: "...", schema: {...})`
89
- - **Without schema** (plain text): `generate(prompt: "...")` - returns plain text/markdown
194
+ - **With schema** (structured JSON): `generate(prompt: "...", schema: {...})` - returns Hash
195
+ - **Without schema** (plain text): `generate(prompt: "...")` - returns String (plain text/markdown)
90
196
 
91
197
  ### Choosing the Correct API (generate vs chat)
92
198
 
199
+ **Decision Tree:**
200
+
201
+ ```
202
+ Need structured JSON output?
203
+ ├─ Yes → Use generate() with schema
204
+ │ └─ Need conversation history?
205
+ │ ├─ No → Use generate() directly
206
+ │ └─ Yes → Include context in prompt (generate() is stateless)
207
+
208
+ └─ No → Need plain text/markdown?
209
+ ├─ Yes → Use generate() without schema
210
+ │ └─ Need conversation history?
211
+ │ ├─ No → Use generate() directly
212
+ │ └─ Yes → Include context in prompt
213
+
214
+ └─ Need tool calling?
215
+ ├─ Yes → Use Executor (chat API with tools)
216
+ │ └─ Multi-step workflow with tool loops
217
+
218
+ └─ No → Use ChatSession (chat API for UI)
219
+ └─ Human-facing chat interface
220
+ ```
221
+
222
+ **Quick Reference:**
223
+
224
+ | Use Case | Method | API Endpoint | State |
225
+ |----------|--------|--------------|-------|
226
+ | Agent planning/routing | `generate()` | `/api/generate` | Stateless |
227
+ | Structured extraction | `generate()` | `/api/generate` | Stateless |
228
+ | Simple text generation | `generate()` | `/api/generate` | Stateless |
229
+ | Tool-calling loops | `Executor` | `/api/chat` | Stateful |
230
+ | UI chat interface | `ChatSession` | `/api/chat` | Stateful |
231
+
232
+ **Detailed Guidance:**
233
+
93
234
  - **Use `/api/generate`** (via `Ollama::Client#generate` or `Ollama::Agent::Planner`) for **stateless planner/router** steps where you want strict, deterministic structured outputs.
94
235
  - **Use `/api/chat`** (via `Ollama::Agent::Executor`) for **stateful tool-using** workflows where the model may request tool calls across multiple turns.
95
236
 
@@ -260,13 +401,13 @@ require "ollama_client"
260
401
 
261
402
  client = Ollama::Client.new
262
403
 
263
- # Get plain text/markdown response (no schema required)
404
+ # Get plain text/markdown response (omit schema for plain text)
264
405
  text_response = client.generate(
265
406
  prompt: "Explain Ruby in simple terms"
266
407
  )
267
408
 
268
409
  puts text_response
269
- # Output: Plain text or markdown explanation
410
+ # Output: Plain text or markdown explanation (String)
270
411
  ```
271
412
 
272
413
  **Option 2: Using `chat_raw()` (for multi-turn conversations)**
@@ -289,8 +430,8 @@ puts text_response
289
430
  ```
290
431
 
291
432
  **When to use which:**
292
- - **`generate()` without schema** - Simple one-shot queries, explanations, text generation
293
- - **`generate()` with schema** - Structured JSON outputs for agents
433
+ - **`generate()` without schema** - Simple one-shot queries, explanations, text generation (returns plain text)
434
+ - **`generate()` with schema** - Structured JSON outputs for agents (recommended for agents)
294
435
  - **`chat_raw()` without format** - Multi-turn conversations with plain text
295
436
  - **`chat_raw()` with format** - Multi-turn conversations with structured outputs
296
437
 
@@ -298,7 +439,7 @@ puts text_response
298
439
 
299
440
  This gem intentionally focuses on **agent building blocks**:
300
441
 
301
- - **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`, `/api/embeddings`
442
+ - **Supported**: `/api/generate`, `/api/chat`, `/api/tags`, `/api/ping`, `/api/embed`
302
443
  - **Not guaranteed**: full endpoint parity with every Ollama release (advanced model mgmt, etc.)
303
444
 
304
445
  ### Agent endpoint mapping (unambiguous)
@@ -315,6 +456,40 @@ Within `Ollama::Agent`:
315
456
  ```ruby
316
457
  require "ollama_client"
317
458
 
459
+ client = Ollama::Client.new
460
+
461
+ # Option 1: With schema (recommended for structured outputs)
462
+ DECISION_SCHEMA = {
463
+ "type" => "object",
464
+ "required" => ["action", "reasoning"],
465
+ "properties" => {
466
+ "action" => {
467
+ "type" => "string",
468
+ "enum" => ["search", "calculate", "store", "retrieve", "finish"]
469
+ },
470
+ "reasoning" => {
471
+ "type" => "string"
472
+ }
473
+ }
474
+ }
475
+
476
+ planner = Ollama::Agent::Planner.new(client)
477
+
478
+ plan = planner.run(
479
+ prompt: "Given the user request, decide the next action.",
480
+ schema: DECISION_SCHEMA,
481
+ context: { user_request: "Plan a weekend trip to Rome" }
482
+ )
483
+
484
+ puts plan["action"] # => "search" (or one of the enum values)
485
+ puts plan["reasoning"] # => Explanation string
486
+ ```
487
+
488
+ **Option 2: Without schema (returns any JSON)**
489
+
490
+ ```ruby
491
+ require "ollama_client"
492
+
318
493
  client = Ollama::Client.new
319
494
  planner = Ollama::Agent::Planner.new(client)
320
495
 
@@ -326,7 +501,7 @@ plan = planner.run(
326
501
  context: { user_request: "Plan a weekend trip to Rome" }
327
502
  )
328
503
 
329
- puts plan
504
+ puts plan # => Any valid JSON structure
330
505
  ```
331
506
 
332
507
  ### Executor Agent (tool loop, /api/chat)
@@ -669,6 +844,61 @@ result2 = client.chat(messages: messages, format: decision_schema, allow_chat: t
669
844
  # Harder to reason about state in agent systems
670
845
  ```
671
846
 
847
+ ### Decision Table: `generate()` vs `chat()` vs `ChatSession`
848
+
849
+ > **Use `generate()` for systems. Use `chat()` or `ChatSession` for humans.**
850
+
851
+ | Use Case | Method | Schema Guarantees | Streaming | Memory | When to Use |
852
+ |----------|--------|-------------------|-----------|--------|-------------|
853
+ | **Agent planning/routing** | `generate()` | ✅ Strong | ❌ No | ❌ Stateless | Default for agents |
854
+ | **Structured extraction** | `generate()` | ✅ Strong | ❌ No | ❌ Stateless | Data extraction, classification |
855
+ | **Tool-calling loops** | `chat_raw()` | ⚠️ Weaker | ✅ Yes | ✅ Stateful | Executor agent internals |
856
+ | **UI chat interface** | `ChatSession` | ⚠️ Best-effort | ✅ Yes | ✅ Stateful | Human-facing assistants |
857
+ | **Multi-turn conversations** | `ChatSession` | ⚠️ Best-effort | ✅ Yes | ✅ Stateful | Interactive chat |
858
+
859
+ **Core Rule:** Chat must be a feature flag, not default behavior.
860
+
861
+ ### Using `ChatSession` for Human-Facing Chat
862
+
863
+ For UI assistants and interactive chat, use `ChatSession` to manage conversation state:
864
+
865
+ ```ruby
866
+ require "ollama_client"
867
+
868
+ # Enable chat in config
869
+ config = Ollama::Config.new
870
+ config.allow_chat = true
871
+ config.streaming_enabled = true
872
+
873
+ client = Ollama::Client.new(config: config)
874
+
875
+ # Create streaming observer for presentation
876
+ observer = Ollama::StreamingObserver.new do |event|
877
+ case event.type
878
+ when :token
879
+ print event.text
880
+ when :final
881
+ puts "\n--- DONE ---"
882
+ end
883
+ end
884
+
885
+ # Create chat session with system message
886
+ chat = Ollama::ChatSession.new(
887
+ client,
888
+ system: "You are a helpful assistant",
889
+ stream: observer
890
+ )
891
+
892
+ # Send messages (history is managed automatically)
893
+ chat.say("Hello")
894
+ chat.say("Explain Ruby blocks")
895
+
896
+ # Clear history if needed (keeps system message)
897
+ chat.clear
898
+ ```
899
+
900
+ **Important:** Schema validation in chat is **best-effort** for formatting, not correctness. Never use chat+schema for agent control flow.
901
+
672
902
  ### Example: Chat API (Advanced Use Case)
673
903
 
674
904
  ```ruby
@@ -790,6 +1020,58 @@ end
790
1020
  - Both methods accept `tools:` parameter (Tool object, array of Tool objects, or array of hashes)
791
1021
  - For agent tool loops, use `Ollama::Agent::Executor` instead (handles tool execution automatically)
792
1022
 
1023
+ ### MCP support (local and remote servers)
1024
+
1025
+ You can connect to [Model Context Protocol](https://modelcontextprotocol.io) (MCP) servers and use their tools with the Executor.
1026
+
1027
+ **Remote MCP server (HTTP URL, e.g. [GitMCP](https://gitmcp.io)):**
1028
+
1029
+ ```ruby
1030
+ require "ollama_client"
1031
+
1032
+ client = Ollama::Client.new
1033
+
1034
+ # Remote MCP server URL (e.g. GitMCP: https://gitmcp.io/owner/repo)
1035
+ mcp_client = Ollama::MCP::HttpClient.new(
1036
+ url: "https://gitmcp.io/shubhamtaywade82/agent-runtime",
1037
+ timeout_seconds: 60
1038
+ )
1039
+
1040
+ bridge = Ollama::MCP::ToolsBridge.new(client: mcp_client)
1041
+ tools = bridge.tools_for_executor
1042
+
1043
+ executor = Ollama::Agent::Executor.new(client, tools: tools)
1044
+ answer = executor.run(
1045
+ system: "You have access to the agent-runtime docs. Use tools when the user asks about the repo.",
1046
+ user: "What does this repo do?"
1047
+ )
1048
+
1049
+ puts answer
1050
+ mcp_client.close
1051
+ ```
1052
+
1053
+ **Local MCP server (stdio, e.g. filesystem server):**
1054
+
1055
+ ```ruby
1056
+ # Local MCP server via stdio (requires Node.js/npx)
1057
+ mcp_client = Ollama::MCP::StdioClient.new(
1058
+ command: "npx",
1059
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
1060
+ timeout_seconds: 60
1061
+ )
1062
+
1063
+ bridge = Ollama::MCP::ToolsBridge.new(stdio_client: mcp_client) # or client: mcp_client
1064
+ tools = bridge.tools_for_executor
1065
+ # ... same executor usage
1066
+ mcp_client.close
1067
+ ```
1068
+
1069
+ - **Stdio**: `Ollama::MCP::StdioClient` — spawns a subprocess; use for local servers (e.g. `npx @modelcontextprotocol/server-filesystem`).
1070
+ - **HTTP**: `Ollama::MCP::HttpClient` — POSTs JSON-RPC to a URL; use for remote servers (e.g. [gitmcp.io/owner/repo](https://gitmcp.io)).
1071
+ - **Bridge**: `Ollama::MCP::ToolsBridge.new(client: mcp_client)` or `stdio_client: mcp_client`; then `tools_for_executor` for the Executor.
1072
+ - No extra gem; implementation is self-contained.
1073
+ - See [examples/mcp_executor.rb](examples/mcp_executor.rb) (stdio) and [examples/mcp_http_executor.rb](examples/mcp_http_executor.rb) (URL).
1074
+
793
1075
  ### Example: Data Analysis with Validation
794
1076
 
795
1077
  ```ruby
@@ -958,42 +1240,37 @@ client = Ollama::Client.new
958
1240
  # Note: You need an embedding model installed in Ollama
959
1241
  # Common models: nomic-embed-text, all-minilm, mxbai-embed-large
960
1242
  # Check available models: client.list_models
1243
+ # The client uses /api/embed endpoint internally
961
1244
 
962
1245
  begin
963
1246
  # Single text embedding
964
- # Note: Use the full model name with tag if needed (e.g., "nomic-embed-text:latest")
1247
+ # Note: Model name can be with or without tag (e.g., "nomic-embed-text" or "nomic-embed-text:latest")
965
1248
  embedding = client.embeddings.embed(
966
- model: "nomic-embed-text:latest", # Use an available embedding model
1249
+ model: "nomic-embed-text", # Use an available embedding model
967
1250
  input: "What is Ruby programming?"
968
1251
  )
969
1252
  # Returns: [0.123, -0.456, ...] (array of floats)
970
- if embedding.empty?
971
- puts "Warning: Empty embedding returned. Check model compatibility."
972
- else
973
- puts "Embedding dimension: #{embedding.length}"
974
- puts "First few values: #{embedding.first(5).map { |v| v.round(4) }}"
975
- end
1253
+ # For nomic-embed-text, dimension is typically 768
1254
+ puts "Embedding dimension: #{embedding.length}"
1255
+ puts "First few values: #{embedding.first(5).map { |v| v.round(4) }}"
976
1256
 
977
1257
  # Multiple texts
978
1258
  embeddings = client.embeddings.embed(
979
- model: "nomic-embed-text:latest",
1259
+ model: "nomic-embed-text",
980
1260
  input: ["What is Ruby?", "What is Python?", "What is JavaScript?"]
981
1261
  )
982
1262
  # Returns: [[...], [...], [...]] (array of embedding arrays)
983
- if embeddings.is_a?(Array) && embeddings.first.is_a?(Array)
984
- puts "Number of embeddings: #{embeddings.length}"
985
- puts "Each embedding dimension: #{embeddings.first.length}"
986
- else
987
- puts "Unexpected response format: #{embeddings.class}"
988
- end
1263
+ # Each inner array is an embedding vector for the corresponding input text
1264
+ puts "Number of embeddings: #{embeddings.length}"
1265
+ puts "Each embedding dimension: #{embeddings.first.length}"
989
1266
 
990
1267
  rescue Ollama::NotFoundError => e
991
1268
  puts "Model not found. Install an embedding model first:"
992
1269
  puts " ollama pull nomic-embed-text"
993
1270
  puts "Or check available models: client.list_models"
994
- puts "Note: Use the full model name with tag (e.g., 'nomic-embed-text:latest')"
995
1271
  rescue Ollama::Error => e
996
1272
  puts "Error: #{e.message}"
1273
+ # Error message includes helpful troubleshooting steps
997
1274
  end
998
1275
 
999
1276
  # Use for semantic similarity in agents
@@ -1204,67 +1481,35 @@ end
1204
1481
 
1205
1482
  This keeps the `ollama-client` gem **domain-agnostic** and **reusable** across any project.
1206
1483
 
1207
- **See `examples/tool_calling_pattern.rb` for a working implementation of this pattern.**
1208
-
1209
- ## Advanced Examples
1210
-
1211
- The `examples/` directory contains advanced examples demonstrating production-grade patterns:
1212
-
1213
- ### `tool_calling_pattern.rb`
1214
- **Working implementation of the ToolRouter pattern from the Architecture section:**
1215
- - Tool registry and routing
1216
- - LLM outputs intent, agent executes tools
1217
- - Demonstrates the correct separation of concerns
1218
- - Matches the pattern shown in README.md lines 430-500
1219
-
1220
- ### `dhanhq_trading_agent.rb`
1221
- **Real-world integration: Ollama (reasoning) + DhanHQ (execution):**
1222
- - Ollama analyzes market data and makes trading decisions
1223
- - DhanHQ executes trades (place orders, check positions, etc.)
1224
- - Demonstrates proper separation: LLM = reasoning, DhanHQ = execution
1225
- - Shows risk management with super orders (SL/TP)
1226
- - Perfect example of agent-grade tool calling pattern
1227
-
1228
- ### `advanced_multi_step_agent.rb`
1229
- Multi-step agent workflow with:
1230
- - Complex nested schemas
1231
- - State management across steps
1232
- - Confidence thresholds
1233
- - Risk assessment
1234
- - Error recovery
1235
-
1236
- ### `advanced_error_handling.rb`
1237
- Comprehensive error handling patterns:
1238
- - All error types (NotFoundError, HTTPError, TimeoutError, etc.)
1239
- - Retry strategies with exponential backoff
1240
- - Fallback mechanisms
1241
- - Error statistics and observability
1242
-
1243
- ### `advanced_complex_schemas.rb`
1244
- Real-world complex schemas:
1245
- - Financial analysis (nested metrics, recommendations, risk factors)
1246
- - Code review (issues, suggestions, effort estimation)
1247
- - Research paper analysis (findings, methodology, citations)
1248
-
1249
- ### `advanced_performance_testing.rb`
1250
- Performance and observability:
1251
- - Latency measurement (min, max, avg, p95, p99)
1252
- - Throughput testing
1253
- - Error rate tracking
1254
- - Metrics export
1255
-
1256
- ### `advanced_edge_cases.rb`
1257
- Boundary and edge case testing:
1258
- - Empty/long prompts
1259
- - Special characters and unicode
1260
- - Minimal/strict schemas
1261
- - Deeply nested structures
1262
- - Enum constraints
1263
-
1264
- Run any example:
1265
- ```bash
1266
- ruby examples/advanced_multi_step_agent.rb
1267
- ```
1484
+ **See the [ollama-agent-examples](https://github.com/shubhamtaywade82/ollama-agent-examples) repository for working implementations of this pattern.**
1485
+
1486
+ ## 📚 Examples
1487
+
1488
+ ### Minimal Examples (In This Repo)
1489
+
1490
+ The `examples/` directory contains minimal examples demonstrating **client usage only**:
1491
+
1492
+ - **`basic_generate.rb`** - Basic `/generate` usage with schema validation
1493
+ - **`basic_chat.rb`** - Basic `/chat` usage
1494
+ - **`tool_calling_parsing.rb`** - Tool-call parsing (no execution)
1495
+ - **`tool_dto_example.rb`** - Tool DTO serialization
1496
+
1497
+ These examples focus on **transport and protocol correctness**, not agent behavior.
1498
+
1499
+ ### Full Agent Examples (Separate Repository)
1500
+
1501
+ For complete agent examples (trading agents, coding agents, RAG agents, multi-step workflows, tool execution patterns, etc.), see:
1502
+
1503
+ **[ollama-agent-examples](https://github.com/shubhamtaywade82/ollama-agent-examples)**
1504
+
1505
+ This separation keeps `ollama-client` focused on the transport layer while providing comprehensive examples for agent developers.
1506
+
1507
+ **Why this separation?**
1508
+ - Examples rot faster than APIs
1509
+ - Agent examples pull in domain-specific dependencies
1510
+ - Tool examples imply opinions about tool design
1511
+ - The client stays clean and maintainable
1512
+ - Users don't confuse client vs agent responsibilities
1268
1513
 
1269
1514
  ## Development
1270
1515
 
@@ -0,0 +1,41 @@
1
+ # Release v0.2.6
2
+
3
+ ## 🎯 Major Changes
4
+
5
+ ### Test Coverage & Quality
6
+ - **Increased test coverage from 65.66% to 79.59%**
7
+ - Added comprehensive test suites for:
8
+ - `Ollama::DocumentLoader` (file loading, context building)
9
+ - `Ollama::Embeddings` (API calls, error handling)
10
+ - `Ollama::ChatSession` (session management)
11
+ - Tool classes (`Tool`, `Function`, `Parameters`, `Property`)
12
+
13
+ ### Documentation & Examples
14
+ - **Reorganized examples**: Moved agent examples to separate repository (`ollama-agent-examples`)
15
+ - Kept minimal client-focused examples in this repository
16
+ - Rewrote testing documentation to focus on client-only testing (transport/protocol)
17
+ - Added test checklist with specific test categories (G1-G3, C1-C3, A1-A2, F1-F3)
18
+ - Updated README with enhanced "What This Gem IS NOT" section
19
+
20
+ ### Code Quality
21
+ - Fixed all RuboCop offenses
22
+ - Improved code quality and consistency
23
+ - Aligned workflow with agent-runtime repository
24
+
25
+ ## 📦 Installation
26
+
27
+ ```bash
28
+ gem install ollama-client
29
+ ```
30
+
31
+ Or add to your Gemfile:
32
+
33
+ ```ruby
34
+ gem 'ollama-client', '~> 0.2.6'
35
+ ```
36
+
37
+ ## 🔗 Links
38
+
39
+ - [Full Changelog](https://github.com/shubhamtaywade82/ollama-client/blob/main/CHANGELOG.md)
40
+ - [Documentation](https://github.com/shubhamtaywade82/ollama-client#readme)
41
+ - [Examples Repository](https://github.com/shubhamtaywade82/ollama-agent-examples)