ollama-client 0.2.5 → 0.2.6

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +138 -76
  4. data/docs/EXAMPLE_REORGANIZATION.md +412 -0
  5. data/docs/GETTING_STARTED.md +361 -0
  6. data/docs/INTEGRATION_TESTING.md +170 -0
  7. data/docs/NEXT_STEPS_SUMMARY.md +114 -0
  8. data/docs/PERSONAS.md +383 -0
  9. data/docs/QUICK_START.md +195 -0
  10. data/docs/TESTING.md +392 -170
  11. data/docs/TEST_CHECKLIST.md +450 -0
  12. data/examples/README.md +51 -66
  13. data/examples/basic_chat.rb +33 -0
  14. data/examples/basic_generate.rb +29 -0
  15. data/examples/tool_calling_parsing.rb +59 -0
  16. data/exe/ollama-client +128 -1
  17. data/lib/ollama/agent/planner.rb +7 -2
  18. data/lib/ollama/chat_session.rb +101 -0
  19. data/lib/ollama/client.rb +41 -35
  20. data/lib/ollama/config.rb +4 -1
  21. data/lib/ollama/document_loader.rb +1 -1
  22. data/lib/ollama/embeddings.rb +41 -26
  23. data/lib/ollama/errors.rb +1 -0
  24. data/lib/ollama/personas.rb +287 -0
  25. data/lib/ollama/version.rb +1 -1
  26. data/lib/ollama_client.rb +7 -0
  27. metadata +14 -48
  28. data/examples/advanced_complex_schemas.rb +0 -366
  29. data/examples/advanced_edge_cases.rb +0 -241
  30. data/examples/advanced_error_handling.rb +0 -200
  31. data/examples/advanced_multi_step_agent.rb +0 -341
  32. data/examples/advanced_performance_testing.rb +0 -186
  33. data/examples/chat_console.rb +0 -143
  34. data/examples/complete_workflow.rb +0 -245
  35. data/examples/dhan_console.rb +0 -843
  36. data/examples/dhanhq/README.md +0 -236
  37. data/examples/dhanhq/agents/base_agent.rb +0 -74
  38. data/examples/dhanhq/agents/data_agent.rb +0 -66
  39. data/examples/dhanhq/agents/orchestrator_agent.rb +0 -120
  40. data/examples/dhanhq/agents/technical_analysis_agent.rb +0 -252
  41. data/examples/dhanhq/agents/trading_agent.rb +0 -81
  42. data/examples/dhanhq/analysis/market_structure.rb +0 -138
  43. data/examples/dhanhq/analysis/pattern_recognizer.rb +0 -192
  44. data/examples/dhanhq/analysis/trend_analyzer.rb +0 -88
  45. data/examples/dhanhq/builders/market_context_builder.rb +0 -67
  46. data/examples/dhanhq/dhanhq_agent.rb +0 -829
  47. data/examples/dhanhq/indicators/technical_indicators.rb +0 -158
  48. data/examples/dhanhq/scanners/intraday_options_scanner.rb +0 -492
  49. data/examples/dhanhq/scanners/swing_scanner.rb +0 -247
  50. data/examples/dhanhq/schemas/agent_schemas.rb +0 -61
  51. data/examples/dhanhq/services/base_service.rb +0 -46
  52. data/examples/dhanhq/services/data_service.rb +0 -118
  53. data/examples/dhanhq/services/trading_service.rb +0 -59
  54. data/examples/dhanhq/technical_analysis_agentic_runner.rb +0 -411
  55. data/examples/dhanhq/technical_analysis_runner.rb +0 -420
  56. data/examples/dhanhq/test_tool_calling.rb +0 -538
  57. data/examples/dhanhq/test_tool_calling_verbose.rb +0 -251
  58. data/examples/dhanhq/utils/instrument_helper.rb +0 -32
  59. data/examples/dhanhq/utils/parameter_cleaner.rb +0 -28
  60. data/examples/dhanhq/utils/parameter_normalizer.rb +0 -45
  61. data/examples/dhanhq/utils/rate_limiter.rb +0 -23
  62. data/examples/dhanhq/utils/trading_parameter_normalizer.rb +0 -72
  63. data/examples/dhanhq_agent.rb +0 -964
  64. data/examples/dhanhq_tools.rb +0 -1663
  65. data/examples/multi_step_agent_with_external_data.rb +0 -368
  66. data/examples/structured_outputs_chat.rb +0 -72
  67. data/examples/structured_tools.rb +0 -89
  68. data/examples/test_dhanhq_tool_calling.rb +0 -375
  69. data/examples/test_tool_calling.rb +0 -160
  70. data/examples/tool_calling_direct.rb +0 -124
  71. data/examples/tool_calling_pattern.rb +0 -269
  72. data/exe/dhan_console +0 -4
@@ -0,0 +1,450 @@
1
+ # Test Checklist: `ollama-client` Client-Only Testing
2
+
3
+ This checklist ensures comprehensive testing of the `ollama-client` transport layer without leaking agent concerns.
4
+
5
+ ## Category A: `/generate` Mode Tests (Stateless, Deterministic)
6
+
7
+ ### ✅ G1 — Basic Generate
8
+ - [ ] Response is a Hash
9
+ - [ ] JSON is parsed correctly
10
+ - [ ] No `tool_calls` present
11
+ - [ ] No streaming artifacts
12
+ - [ ] Schema validation passes (if schema provided)
13
+
14
+ **Test File:** `spec/ollama/client_generate_spec.rb`
15
+
16
+ **Example Test:**
17
+ ```ruby
18
+ it "parses JSON response from generate endpoint" do
19
+ stub_request(:post, "http://localhost:11434/api/generate")
20
+ .to_return(
21
+ status: 200,
22
+ body: { response: '{"status":"ok"}' }.to_json
23
+ )
24
+
25
+ result = client.generate(
26
+ prompt: "Output a JSON object with a single key 'status' and value 'ok'.",
27
+ schema: { "type" => "object", "required" => ["status"] }
28
+ )
29
+
30
+ expect(result).to be_a(Hash)
31
+ expect(result["status"]).to eq("ok")
32
+ expect(result).not_to have_key("tool_calls")
33
+ end
34
+ ```
35
+
36
+ ---
37
+
38
+ ### ✅ G2 — Strict Schema Enforcement
39
+ - [ ] Raises error if schema violated
40
+ - [ ] Rejects extra fields (if strict mode enabled)
41
+ - [ ] Validates required fields
42
+ - [ ] Validates type constraints
43
+ - [ ] Validates enum constraints
44
+ - [ ] Validates number min/max
45
+ - [ ] Validates string minLength/maxLength
46
+
47
+ **Test File:** `spec/ollama/client_generate_spec.rb` or `spec/ollama/schema_validator_spec.rb`
48
+
49
+ **Example Test:**
50
+ ```ruby
51
+ it "rejects responses that violate schema" do
52
+ stub_request(:post, "http://localhost:11434/api/generate")
53
+ .to_return(
54
+ status: 200,
55
+ body: { response: '{"count":"not-a-number"}' }.to_json
56
+ )
57
+
58
+ schema = {
59
+ "type" => "object",
60
+ "required" => ["count"],
61
+ "properties" => {
62
+ "count" => { "type" => "number" }
63
+ }
64
+ }
65
+
66
+ expect do
67
+ client.generate(prompt: "Output JSON with key 'count' as a number.", schema: schema)
68
+ end.to raise_error(Ollama::SchemaViolationError)
69
+ end
70
+ ```
71
+
72
+ ---
73
+
74
+ ### ❌ G3 — Tool Attempt in Generate (Must Fail)
75
+ - [ ] No `tool_calls` parsed
76
+ - [ ] No silent acceptance of tool intent
77
+ - [ ] Either ignored or explicit error
78
+ - [ ] `/generate` remains non-agentic
79
+
80
+ **Test File:** `spec/ollama/client_generate_spec.rb`
81
+
82
+ **Example Test:**
83
+ ```ruby
84
+ it "ignores tool calls in generate mode" do
85
+ stub_request(:post, "http://localhost:11434/api/generate")
86
+ .to_return(
87
+ status: 200,
88
+ body: { response: '{"action":"call read_file tool on foo.rb"}' }.to_json
89
+ )
90
+
91
+ result = client.generate(
92
+ prompt: "Call the read_file tool on foo.rb",
93
+ schema: { "type" => "object" }
94
+ )
95
+
96
+ expect(result).not_to have_key("tool_calls")
97
+ expect(result).not_to have_key("tool_use")
98
+ end
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Category B: `/chat` Mode Tests (Stateful, Tool-Aware)
104
+
105
+ ### ✅ C1 — Simple Chat
106
+ - [ ] Response contains assistant message
107
+ - [ ] Message history preserved in request
108
+ - [ ] Role is correct
109
+ - [ ] Content is parsed correctly
110
+
111
+ **Test File:** `spec/ollama/client_chat_spec.rb` or `spec/ollama/client_chat_raw_spec.rb`
112
+
113
+ **Example Test:**
114
+ ```ruby
115
+ it "handles simple chat messages" do
116
+ stub_request(:post, "http://localhost:11434/api/chat")
117
+ .to_return(
118
+ status: 200,
119
+ body: {
120
+ message: { role: "assistant", content: "Hello!" }
121
+ }.to_json
122
+ )
123
+
124
+ response = client.chat_raw(
125
+ messages: [{ role: "user", content: "Say hello." }],
126
+ allow_chat: true
127
+ )
128
+
129
+ expect(response.message.content).to eq("Hello!")
130
+ expect(response.message.role).to eq("assistant")
131
+ end
132
+ ```
133
+
134
+ ---
135
+
136
+ ### ✅ C2 — Tool-Call Parsing (Critical)
137
+ - [ ] `tool_calls` extracted correctly
138
+ - [ ] Tool name parsed
139
+ - [ ] Arguments parsed as hash
140
+ - [ ] **No execution happens** (client must not execute tools)
141
+ - [ ] Multiple tool calls handled
142
+ - [ ] Tool call ID preserved (if present)
143
+
144
+ **Test File:** `spec/ollama/client_chat_raw_spec.rb`
145
+
146
+ **Example Test:**
147
+ ```ruby
148
+ it "extracts tool calls from chat response" do
149
+ stub_request(:post, "http://localhost:11434/api/chat")
150
+ .to_return(
151
+ status: 200,
152
+ body: {
153
+ message: {
154
+ role: "assistant",
155
+ content: "I'll call the ping tool.",
156
+ tool_calls: [
157
+ {
158
+ type: "function",
159
+ function: {
160
+ name: "ping",
161
+ arguments: { "x" => 1 }.to_json
162
+ }
163
+ }
164
+ ]
165
+ }
166
+ }.to_json
167
+ )
168
+
169
+ response = client.chat_raw(
170
+ messages: [{ role: "user", content: "If a tool named 'ping' exists, call it with { 'x': 1 }." }],
171
+ tools: [tool_definition],
172
+ allow_chat: true
173
+ )
174
+
175
+ tool_calls = response.message.tool_calls
176
+ expect(tool_calls).not_to be_empty
177
+ expect(tool_calls.first["function"]["name"]).to eq("ping")
178
+ expect(JSON.parse(tool_calls.first["function"]["arguments"])).to eq("x" => 1)
179
+ end
180
+ ```
181
+
182
+ ---
183
+
184
+ ### ✅ C3 — Tool Result Round-Trip Formatting
185
+ - [ ] Client serializes tool message correctly
186
+ - [ ] Ollama accepts tool result message
187
+ - [ ] Response parsed cleanly after tool result
188
+ - [ ] Tool name preserved
189
+ - [ ] Tool content serialized as JSON string
190
+
191
+ **Test File:** `spec/ollama/client_chat_raw_spec.rb`
192
+
193
+ **Example Test:**
194
+ ```ruby
195
+ it "serializes tool result messages correctly" do
196
+ messages = [
197
+ { role: "user", content: "Call ping tool" },
198
+ { role: "assistant", content: "", tool_calls: [...] },
199
+ { role: "tool", name: "ping", content: { ok: true }.to_json }
200
+ ]
201
+
202
+ stub_request(:post, "http://localhost:11434/api/chat")
203
+ .with(body: hash_including(messages: messages))
204
+ .to_return(
205
+ status: 200,
206
+ body: { message: { role: "assistant", content: "Done!" } }.to_json
207
+ )
208
+
209
+ response = client.chat_raw(messages: messages, allow_chat: true)
210
+ expect(response.message.content).to eq("Done!")
211
+ end
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Category C: Protocol Adapters (Anthropic / Native)
217
+
218
+ ### ✅ A1 — Anthropic Message Shape
219
+ - [ ] Messages serialized as content blocks
220
+ - [ ] Tool calls emitted as `tool_use` (if Anthropic mode)
221
+ - [ ] Tool results serialized as `tool_result`
222
+ - [ ] Request payload matches Anthropic format
223
+
224
+ **Test File:** `spec/ollama/client_chat_raw_spec.rb` or new `spec/ollama/protocol_adapter_spec.rb`
225
+
226
+ **Example Test:**
227
+ ```ruby
228
+ it "serializes messages in Anthropic format" do
229
+ stub_request(:post, "http://localhost:11434/api/chat")
230
+ .with do |req|
231
+ body = JSON.parse(req.body)
232
+ expect(body["messages"]).to be_an(Array)
233
+ expect(body["messages"].first).to include("role", "content")
234
+ end
235
+ .to_return(status: 200, body: { message: {} }.to_json)
236
+
237
+ client.chat_raw(
238
+ messages: [{ role: "user", content: "Test" }],
239
+ allow_chat: true
240
+ )
241
+ end
242
+ ```
243
+
244
+ ---
245
+
246
+ ### ✅ A2 — Anthropic Response Parsing
247
+ - [ ] Client normalizes Anthropic format into internal `tool_calls`
248
+ - [ ] Protocol adapter correctness
249
+ - [ ] Tool use ID preserved
250
+ - [ ] Tool input parsed correctly
251
+
252
+ **Test File:** `spec/ollama/client_chat_raw_spec.rb` or new `spec/ollama/protocol_adapter_spec.rb`
253
+
254
+ **Example Test:**
255
+ ```ruby
256
+ it "normalizes Anthropic-style responses into internal format" do
257
+ anthropic_response = {
258
+ content: [
259
+ {
260
+ type: "tool_use",
261
+ id: "call_123",
262
+ name: "search",
263
+ input: { q: "foo" }
264
+ }
265
+ ]
266
+ }
267
+
268
+ stub_request(:post, "http://localhost:11434/api/chat")
269
+ .to_return(status: 200, body: anthropic_response.to_json)
270
+
271
+ response = client.chat_raw(
272
+ messages: [{ role: "user", content: "Search for foo" }],
273
+ allow_chat: true
274
+ )
275
+
276
+ tool_calls = response.message.tool_calls
277
+ expect(tool_calls).not_to be_empty
278
+ expect(tool_calls.first["function"]["name"]).to eq("search")
279
+ end
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Category D: Failure Modes (Non-Negotiable)
285
+
286
+ ### ✅ F1 — Ollama Down
287
+ - [ ] Connection refused raises correct exception
288
+ - [ ] No hangs
289
+ - [ ] Retries handled correctly (if retryable)
290
+ - [ ] Error message is clear
291
+
292
+ **Test File:** `spec/ollama/errors_spec.rb` or `spec/ollama/client_spec.rb`
293
+
294
+ **Example Test:**
295
+ ```ruby
296
+ it "handles connection refused gracefully" do
297
+ stub_request(:post, "http://localhost:11434/api/generate")
298
+ .to_raise(Errno::ECONNREFUSED)
299
+
300
+ start_time = Time.now
301
+ expect do
302
+ client.generate(prompt: "test", schema: schema)
303
+ end.to raise_error(Ollama::Error)
304
+
305
+ # Verify no hangs
306
+ expect(Time.now - start_time).to be < 5
307
+ end
308
+ ```
309
+
310
+ ---
311
+
312
+ ### ✅ F2 — Invalid JSON from Model
313
+ - [ ] Client raises parse error
314
+ - [ ] Does not silently continue
315
+ - [ ] Retries handled (if retryable)
316
+ - [ ] Error message includes context
317
+
318
+ **Test File:** `spec/ollama/errors_spec.rb`
319
+
320
+ **Example Test:**
321
+ ```ruby
322
+ it "raises error on invalid JSON response" do
323
+ stub_request(:post, "http://localhost:11434/api/generate")
324
+ .to_return(status: 200, body: { response: "not json at all" }.to_json)
325
+
326
+ expect do
327
+ client.generate(prompt: "test", schema: schema)
328
+ end.to raise_error(Ollama::InvalidJSONError)
329
+ end
330
+ ```
331
+
332
+ ---
333
+
334
+ ### ✅ F3 — Streaming Interruption
335
+ - [ ] Partial stream handled
336
+ - [ ] Client terminates cleanly
337
+ - [ ] No corrupted state
338
+ - [ ] Error raised appropriately
339
+
340
+ **Test File:** `spec/ollama/client_chat_raw_spec.rb` (if streaming tests exist)
341
+
342
+ **Example Test:**
343
+ ```ruby
344
+ it "handles partial stream gracefully" do
345
+ stub_request(:post, "http://localhost:11434/api/chat")
346
+ .to_return(
347
+ status: 200,
348
+ body: "data: {\"message\":{\"content\":\"partial\"}}\n",
349
+ headers: { "Content-Type" => "text/event-stream" }
350
+ )
351
+
352
+ # Simulate stream interruption
353
+ expect do
354
+ client.chat_raw(messages: [{ role: "user", content: "test" }], allow_chat: true)
355
+ end.to raise_error(Ollama::Error)
356
+ end
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Additional Test Areas
362
+
363
+ ### Retry Logic
364
+ - [ ] Retries up to `config.retries` times
365
+ - [ ] Only retries retryable errors (5xx, 408, 429)
366
+ - [ ] Raises `RetryExhaustedError` after max retries
367
+ - [ ] Succeeds if retry succeeds
368
+ - [ ] Non-retryable errors (400, 404) fail immediately
369
+
370
+ ### Error Handling
371
+ - [ ] **404 (NotFoundError)**: Model not found, no retries, includes suggestions
372
+ - [ ] **500 (HTTPError)**: Retryable, retries up to config limit
373
+ - [ ] **400 (HTTPError)**: Non-retryable, fails immediately
374
+ - [ ] **TimeoutError**: Retries on timeout
375
+ - [ ] **InvalidJSONError**: Retries on JSON parse errors
376
+ - [ ] **SchemaViolationError**: Retries on schema validation failures
377
+ - [ ] **Connection Errors**: Retries on network failures
378
+
379
+ ### Edge Cases
380
+ - [ ] JSON wrapped in markdown code blocks
381
+ - [ ] Plain JSON responses
382
+ - [ ] Empty model lists
383
+ - [ ] Missing response fields
384
+ - [ ] Malformed JSON
385
+ - [ ] Empty prompts
386
+ - [ ] Very long prompts
387
+ - [ ] Special characters in prompts
388
+
389
+ ### Model Suggestions
390
+ - [ ] Suggests similar models on 404
391
+ - [ ] Fuzzy matching on model names
392
+ - [ ] Limits suggestions to 5 models
393
+ - [ ] Handles model listing failures gracefully
394
+
395
+ ---
396
+
397
+ ## What NOT to Test (Agent Concerns)
398
+
399
+ ❌ **Do not test:**
400
+ - Infinite loops
401
+ - Retries based on content
402
+ - Agent stopping behavior
403
+ - Tool side effects
404
+ - Correctness of answers
405
+ - Agent convergence logic
406
+ - Policy decisions
407
+ - Tool execution
408
+ - Agent state management
409
+
410
+ **Those belong to `agent-runtime` and app repos.**
411
+
412
+ ---
413
+
414
+ ## Test Coverage Goals
415
+
416
+ - **Transport layer**: 100% coverage
417
+ - **Protocol parsing**: 100% coverage
418
+ - **Error handling**: 100% coverage
419
+ - **Schema validation**: 100% coverage
420
+ - **Tool-call parsing**: 100% coverage
421
+
422
+ **Note:** We don't aim for 100% line coverage of agent logic because agent logic doesn't belong in this gem.
423
+
424
+ ---
425
+
426
+ ## Running the Checklist
427
+
428
+ 1. Review each category
429
+ 2. Mark tests as complete when implemented
430
+ 3. Add test file references
431
+ 4. Update this checklist as new test categories are identified
432
+ 5. Remove tests that leak agent concerns
433
+
434
+ ---
435
+
436
+ ## Test File Organization
437
+
438
+ ```
439
+ spec/
440
+ ├── ollama/
441
+ │ ├── client_spec.rb # Basic initialization, config
442
+ │ ├── client_generate_spec.rb # Category A (G1-G3)
443
+ │ ├── client_chat_spec.rb # Category B (C1-C3) - basic chat
444
+ │ ├── client_chat_raw_spec.rb # Category B (C1-C3) - tool calls
445
+ │ ├── protocol_adapter_spec.rb # Category C (A1-A2) - if needed
446
+ │ ├── errors_spec.rb # Category D (F1-F3)
447
+ │ ├── schema_validator_spec.rb # Category A (G2)
448
+ │ ├── client_list_models_spec.rb # Model listing
449
+ │ └── client_model_suggestions_spec.rb # Model suggestions
450
+ ```
data/examples/README.md CHANGED
@@ -1,92 +1,77 @@
1
1
  # Examples
2
2
 
3
- This directory contains working examples demonstrating various features of the ollama-client gem.
3
+ This directory contains **minimal examples** demonstrating `ollama-client` usage. These examples focus on **transport and protocol correctness**, not agent behavior.
4
4
 
5
- ## Quick Start Examples
5
+ ## Minimal Examples
6
6
 
7
- ### Basic Tool Calling
8
- - **[test_tool_calling.rb](test_tool_calling.rb)** - Simple tool calling demo with weather tool
9
- - **[tool_calling_pattern.rb](tool_calling_pattern.rb)** - Recommended patterns for tool calling
10
- - **[tool_calling_direct.rb](tool_calling_direct.rb)** - Direct tool calling without Executor
7
+ ### Basic Client Usage
11
8
 
12
- ### DhanHQ Market Data
13
- - **[test_dhanhq_tool_calling.rb](test_dhanhq_tool_calling.rb)** - DhanHQ tools with updated intraday & indicators
14
- - **[dhanhq_tools.rb](dhanhq_tools.rb)** - DhanHQ API wrapper tools
15
- - **[dhan_console.rb](dhan_console.rb)** - Interactive DhanHQ console with planning
9
+ - **[basic_generate.rb](basic_generate.rb)** - Basic `/generate` usage with schema validation
10
+ - Demonstrates stateless, deterministic JSON output
11
+ - Shows schema enforcement
12
+ - No agent logic
16
13
 
17
- ### Multi-Step Agents
18
- - **[multi_step_agent_e2e.rb](multi_step_agent_e2e.rb)** - End-to-end multi-step agent example
19
- - **[multi_step_agent_with_external_data.rb](multi_step_agent_with_external_data.rb)** - Agent with external data integration
14
+ - **[basic_chat.rb](basic_chat.rb)** - Basic `/chat` usage
15
+ - Demonstrates stateful message handling
16
+ - Shows multi-turn conversation structure
17
+ - No agent loops
20
18
 
21
- ### Structured Data
22
- - **[structured_outputs_chat.rb](structured_outputs_chat.rb)** - Structured outputs with schemas
23
- - **[structured_tools.rb](structured_tools.rb)** - Structured tool definitions
24
- - **[tool_dto_example.rb](tool_dto_example.rb)** - Using DTOs for tool definitions
19
+ - **[tool_calling_parsing.rb](tool_calling_parsing.rb)** - Tool-call parsing (no execution)
20
+ - Demonstrates tool-call detection and extraction
21
+ - Shows how to parse tool calls from LLM response
22
+ - **Does NOT execute tools** - that's agent responsibility
25
23
 
26
- ### Advanced Features
27
- - **[advanced_multi_step_agent.rb](advanced_multi_step_agent.rb)** - Complex multi-step workflows
28
- - **[advanced_error_handling.rb](advanced_error_handling.rb)** - Error handling patterns
29
- - **[advanced_edge_cases.rb](advanced_edge_cases.rb)** - Edge case handling
30
- - **[advanced_complex_schemas.rb](advanced_complex_schemas.rb)** - Complex schema definitions
31
- - **[advanced_performance_testing.rb](advanced_performance_testing.rb)** - Performance testing
32
-
33
- ### Interactive Consoles
34
- - **[chat_console.rb](chat_console.rb)** - Simple chat console with streaming
35
- - **[dhan_console.rb](dhan_console.rb)** - DhanHQ market data console with formatted tool results
36
-
37
- ### Complete Workflows
38
- - **[complete_workflow.rb](complete_workflow.rb)** - Complete agent workflow example
39
-
40
- ## DhanHQ Examples
41
-
42
- The `dhanhq/` subdirectory contains more specialized DhanHQ examples:
43
- - Technical analysis agents
44
- - Market scanners (intraday options, swing trading)
45
- - Pattern recognition and trend analysis
46
- - Multi-agent orchestration
47
-
48
- See [dhanhq/README.md](dhanhq/README.md) for details.
24
+ - **[tool_dto_example.rb](tool_dto_example.rb)** - Tool DTO serialization
25
+ - Demonstrates Tool class serialization/deserialization
26
+ - Shows DTO functionality
49
27
 
50
28
  ## Running Examples
51
29
 
52
- Most examples are standalone and can be run directly:
30
+ All examples are standalone and can be run directly:
53
31
 
54
32
  ```bash
55
- # Basic tool calling
56
- ruby examples/test_tool_calling.rb
33
+ # Basic generate
34
+ ruby examples/basic_generate.rb
35
+
36
+ # Basic chat
37
+ ruby examples/basic_chat.rb
57
38
 
58
- # DhanHQ with intraday data
59
- ruby examples/test_dhanhq_tool_calling.rb
39
+ # Tool calling parsing
40
+ ruby examples/tool_calling_parsing.rb
60
41
 
61
- # Interactive console
62
- ruby examples/chat_console.rb
42
+ # Tool DTO
43
+ ruby examples/tool_dto_example.rb
63
44
  ```
64
45
 
65
46
  ### Requirements
66
47
 
67
- Some examples require additional setup:
68
-
69
- **DhanHQ Examples:**
70
- - Set `DHANHQ_CLIENT_ID` and `DHANHQ_ACCESS_TOKEN` environment variables
71
- - Or create `.env` file with credentials
72
-
73
- **Ollama:**
74
48
  - Ollama server running (default: `http://localhost:11434`)
75
49
  - Set `OLLAMA_BASE_URL` if using a different URL
76
50
  - Set `OLLAMA_MODEL` if not using default model
77
51
 
78
- ## Learning Path
52
+ ## Full Agent Examples
53
+
54
+ For complete agent examples (trading agents, coding agents, RAG agents, multi-step workflows, tool execution patterns, etc.), see:
55
+
56
+ **[ollama-agent-examples](https://github.com/shubhamtaywade82/ollama-agent-examples)**
57
+
58
+ This separation keeps `ollama-client` focused on the transport layer while providing comprehensive examples for agent developers.
59
+
60
+ ## What These Examples Demonstrate
61
+
62
+ These minimal examples prove:
63
+
64
+ ✅ **Transport layer** - HTTP requests/responses
65
+ ✅ **Protocol correctness** - Request shaping, response parsing
66
+ ✅ **Schema enforcement** - JSON validation
67
+ ✅ **Tool-call parsing** - Detecting and extracting tool calls
79
68
 
80
- 1. **Start here:** `test_tool_calling.rb` - Learn basic tool calling
81
- 2. **Structured data:** `structured_outputs_chat.rb` - Schema-based outputs
82
- 3. **Multi-step:** `multi_step_agent_e2e.rb` - Complex agent workflows
83
- 4. **Market data:** `test_dhanhq_tool_calling.rb` - Real-world API integration
84
- 5. **Interactive:** `dhan_console.rb` - Full-featured console with planning
69
+ These examples do **NOT** demonstrate:
85
70
 
86
- ## Contributing
71
+ Agent loops
72
+ ❌ Tool execution
73
+ ❌ Convergence logic
74
+ ❌ Policy decisions
75
+ ❌ Domain-specific logic
87
76
 
88
- When adding new examples:
89
- - Include clear comments explaining what the example demonstrates
90
- - Add `#!/usr/bin/env ruby` shebang at the top
91
- - Use `frozen_string_literal: true`
92
- - Update this README with a description
77
+ **Those belong in the separate agent examples repository.**
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Basic /chat usage
5
+ # Demonstrates client transport layer - stateful message handling
6
+
7
+ require_relative "../lib/ollama_client"
8
+
9
+ client = Ollama::Client.new
10
+
11
+ # Simple chat message
12
+ response = client.chat_raw(
13
+ messages: [{ role: "user", content: "Say hello." }],
14
+ allow_chat: true
15
+ )
16
+
17
+ puts "Response: #{response.message.content}"
18
+ puts "Role: #{response.message.role}"
19
+
20
+ # Multi-turn conversation
21
+ messages = [
22
+ { role: "user", content: "What is Ruby?" }
23
+ ]
24
+
25
+ response1 = client.chat_raw(messages: messages, allow_chat: true)
26
+ puts "\nFirst response: #{response1.message.content}"
27
+
28
+ # Continue conversation
29
+ messages << { role: "assistant", content: response1.message.content }
30
+ messages << { role: "user", content: "Tell me more about its use cases" }
31
+
32
+ response2 = client.chat_raw(messages: messages, allow_chat: true)
33
+ puts "\nSecond response: #{response2.message.content}"
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Basic /generate usage with schema validation
5
+ # Demonstrates client transport layer - stateless, deterministic JSON output
6
+
7
+ require_relative "../lib/ollama_client"
8
+
9
+ client = Ollama::Client.new
10
+
11
+ # Define schema for structured output
12
+ schema = {
13
+ "type" => "object",
14
+ "required" => ["status"],
15
+ "properties" => {
16
+ "status" => { "type" => "string" }
17
+ }
18
+ }
19
+
20
+ # Generate structured JSON response
21
+ result = client.generate(
22
+ prompt: "Output a JSON object with a single key 'status' and value 'ok'.",
23
+ schema: schema
24
+ )
25
+
26
+ puts "Result: #{result.inspect}"
27
+ puts "Status: #{result['status']}" # => "ok"
28
+
29
+ # The result is guaranteed to match your schema!