riffer 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/.agents/architecture.md +113 -0
- data/.agents/code-style.md +42 -0
- data/.agents/providers.md +46 -0
- data/.agents/rdoc.md +51 -0
- data/.agents/testing.md +56 -0
- data/.release-please-manifest.json +1 -1
- data/AGENTS.md +21 -308
- data/CHANGELOG.md +10 -0
- data/README.md +21 -112
- data/Rakefile +1 -1
- data/docs/01_OVERVIEW.md +106 -0
- data/docs/02_GETTING_STARTED.md +128 -0
- data/docs/03_AGENTS.md +226 -0
- data/docs/04_TOOLS.md +251 -0
- data/docs/05_MESSAGES.md +173 -0
- data/docs/06_STREAM_EVENTS.md +191 -0
- data/docs/07_CONFIGURATION.md +195 -0
- data/docs_providers/01_PROVIDERS.md +168 -0
- data/docs_providers/02_AMAZON_BEDROCK.md +196 -0
- data/docs_providers/03_ANTHROPIC.md +211 -0
- data/docs_providers/04_OPENAI.md +157 -0
- data/docs_providers/05_TEST_PROVIDER.md +163 -0
- data/docs_providers/06_CUSTOM_PROVIDERS.md +304 -0
- data/lib/riffer/agent.rb +97 -43
- data/lib/riffer/config.rb +20 -12
- data/lib/riffer/core.rb +7 -7
- data/lib/riffer/helpers/class_name_converter.rb +6 -3
- data/lib/riffer/helpers/dependencies.rb +18 -0
- data/lib/riffer/helpers/validations.rb +9 -0
- data/lib/riffer/messages/assistant.rb +23 -1
- data/lib/riffer/messages/base.rb +15 -0
- data/lib/riffer/messages/converter.rb +15 -5
- data/lib/riffer/messages/system.rb +8 -1
- data/lib/riffer/messages/tool.rb +45 -2
- data/lib/riffer/messages/user.rb +8 -1
- data/lib/riffer/messages.rb +7 -0
- data/lib/riffer/providers/amazon_bedrock.rb +8 -4
- data/lib/riffer/providers/anthropic.rb +209 -0
- data/lib/riffer/providers/base.rb +17 -12
- data/lib/riffer/providers/open_ai.rb +7 -1
- data/lib/riffer/providers/repository.rb +9 -4
- data/lib/riffer/providers/test.rb +25 -7
- data/lib/riffer/providers.rb +6 -0
- data/lib/riffer/stream_events/base.rb +13 -1
- data/lib/riffer/stream_events/reasoning_delta.rb +15 -1
- data/lib/riffer/stream_events/reasoning_done.rb +15 -1
- data/lib/riffer/stream_events/text_delta.rb +14 -1
- data/lib/riffer/stream_events/text_done.rb +14 -1
- data/lib/riffer/stream_events/tool_call_delta.rb +18 -11
- data/lib/riffer/stream_events/tool_call_done.rb +22 -12
- data/lib/riffer/stream_events.rb +9 -0
- data/lib/riffer/tool.rb +57 -25
- data/lib/riffer/tools/param.rb +19 -16
- data/lib/riffer/tools/params.rb +28 -22
- data/lib/riffer/tools.rb +5 -0
- data/lib/riffer/version.rb +1 -1
- data/lib/riffer.rb +21 -21
- metadata +34 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ace7d52275897dc91ce42de1acc67db3de289c55953a56fa833a0f92f9c48c7c
|
|
4
|
+
data.tar.gz: ddee9798fb18502bd0e0e14e61d899a3cb24b240a6e6f9ab95b00199f03f7b59
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c32731c0ac374bcc90fddd3c1cf071e3e2a1a2e2ae197ffcf98aace5acc4402c38d24657b2d3c211dfbf8d951a48ab9e94087a4b3accb2e763eb6202fa07312
|
|
7
|
+
data.tar.gz: da8b8ba45b0a5e08e4f2c7b212ddba5761fd2673d1c89fea695b1cb2d60e9ba1f7a01d9138f0eed33b406a7c7e116eb219e1f7a4919a7a4183cfe2dc97f59622
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Core Components
|
|
4
|
+
|
|
5
|
+
### Agent (`lib/riffer/agent.rb`)
|
|
6
|
+
|
|
7
|
+
Base class for AI agents. Subclass and use DSL methods `model` and `instructions` to configure. Orchestrates message flow, LLM calls, and tool execution via a generate/stream loop.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
class EchoAgent < Riffer::Agent
|
|
11
|
+
model 'openai/gpt-5-mini' # provider/model
|
|
12
|
+
instructions 'You are an assistant that repeats what the user says.'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
agent = EchoAgent.new
|
|
16
|
+
puts agent.generate('Hello world')
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Providers (`lib/riffer/providers/`)
|
|
20
|
+
|
|
21
|
+
Adapters for LLM APIs. Each provider extends `Riffer::Providers::Base` and implements:
|
|
22
|
+
|
|
23
|
+
- `perform_generate_text(messages, model:)` - returns `Riffer::Messages::Assistant`
|
|
24
|
+
- `perform_stream_text(messages, model:)` - returns an `Enumerator` yielding stream events
|
|
25
|
+
|
|
26
|
+
Providers are registered in `Riffer::Providers::Repository::REPO` with identifiers (e.g., `openai`, `amazon_bedrock`).
|
|
27
|
+
|
|
28
|
+
### Messages (`lib/riffer/messages/`)
|
|
29
|
+
|
|
30
|
+
Typed message objects that extend `Riffer::Messages::Base`:
|
|
31
|
+
|
|
32
|
+
- `System` - system instructions
|
|
33
|
+
- `User` - user input
|
|
34
|
+
- `Assistant` - AI responses
|
|
35
|
+
- `Tool` - tool execution results
|
|
36
|
+
|
|
37
|
+
The `Converter` module handles hash-to-object conversion.
|
|
38
|
+
|
|
39
|
+
### StreamEvents (`lib/riffer/stream_events/`)
|
|
40
|
+
|
|
41
|
+
Structured events for streaming responses:
|
|
42
|
+
|
|
43
|
+
- `TextDelta` - incremental text chunks
|
|
44
|
+
- `TextDone` - completion signals
|
|
45
|
+
- `ReasoningDelta` - reasoning process chunks
|
|
46
|
+
- `ReasoningDone` - reasoning completion
|
|
47
|
+
|
|
48
|
+
## Key Patterns
|
|
49
|
+
|
|
50
|
+
- Model strings use `provider/model` format (e.g., `openai/gpt-4`)
|
|
51
|
+
- Configuration via `Riffer.configure { |c| c.openai.api_key = "..." }`
|
|
52
|
+
- Providers use `depends_on` helper for runtime dependency checking
|
|
53
|
+
- Zeitwerk for autoloading - file structure must match module/class names
|
|
54
|
+
|
|
55
|
+
## Project Structure
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
lib/
|
|
59
|
+
riffer.rb # Main entry point, uses Zeitwerk for autoloading
|
|
60
|
+
riffer/
|
|
61
|
+
version.rb # VERSION constant
|
|
62
|
+
config.rb # Configuration class
|
|
63
|
+
core.rb # Core functionality
|
|
64
|
+
agent.rb # Agent class
|
|
65
|
+
messages.rb # Messages namespace/module
|
|
66
|
+
providers.rb # Providers namespace/module
|
|
67
|
+
stream_events.rb # Stream events namespace/module
|
|
68
|
+
helpers/
|
|
69
|
+
class_name_converter.rb # Class name conversion utilities
|
|
70
|
+
dependencies.rb # Dependency management
|
|
71
|
+
validations.rb # Validation helpers
|
|
72
|
+
messages/
|
|
73
|
+
base.rb # Base message class
|
|
74
|
+
assistant.rb # Assistant message
|
|
75
|
+
converter.rb # Message converter
|
|
76
|
+
system.rb # System message
|
|
77
|
+
user.rb # User message
|
|
78
|
+
tool.rb # Tool message
|
|
79
|
+
providers/
|
|
80
|
+
base.rb # Base provider class
|
|
81
|
+
open_ai.rb # OpenAI provider
|
|
82
|
+
amazon_bedrock.rb # Amazon Bedrock provider
|
|
83
|
+
repository.rb # Provider registry
|
|
84
|
+
test.rb # Test provider
|
|
85
|
+
stream_events/
|
|
86
|
+
base.rb # Base stream event
|
|
87
|
+
text_delta.rb # Text delta event
|
|
88
|
+
text_done.rb # Text done event
|
|
89
|
+
reasoning_delta.rb # Reasoning delta event
|
|
90
|
+
reasoning_done.rb # Reasoning done event
|
|
91
|
+
test/
|
|
92
|
+
test_helper.rb # Minitest configuration with VCR
|
|
93
|
+
riffer_test.rb # Main module tests
|
|
94
|
+
riffer/
|
|
95
|
+
[feature]_test.rb # Feature tests mirror lib/riffer/ structure
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Configuration Example
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
Riffer.configure do |config|
|
|
102
|
+
config.openai.api_key = ENV['OPENAI_API_KEY']
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Streaming Example
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
agent = EchoAgent.new
|
|
110
|
+
agent.stream('Tell me a story').each do |event|
|
|
111
|
+
print event.content
|
|
112
|
+
end
|
|
113
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Code Style
|
|
2
|
+
|
|
3
|
+
## Formatting
|
|
4
|
+
|
|
5
|
+
- Use StandardRB for linting and formatting
|
|
6
|
+
- Custom rules are defined in `.standard.yml`
|
|
7
|
+
- Run `bundle exec rake standard` to check, `bundle exec rake standard:fix` to auto-fix
|
|
8
|
+
|
|
9
|
+
## Required Header
|
|
10
|
+
|
|
11
|
+
All Ruby files must include:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
# frozen_string_literal: true
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Error Handling
|
|
18
|
+
|
|
19
|
+
Define custom errors as subclasses of `Riffer::Error`:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
class MyCustomError < Riffer::Error
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Comments
|
|
27
|
+
|
|
28
|
+
- Only add comments when the code is ambiguous or not semantically obvious
|
|
29
|
+
- Explain **why** something is done, not **what** is being done
|
|
30
|
+
- Comments should add value beyond what the code already expresses
|
|
31
|
+
|
|
32
|
+
## Module Structure
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
# frozen_string_literal: true
|
|
36
|
+
|
|
37
|
+
module Riffer::Feature
|
|
38
|
+
class MyClass
|
|
39
|
+
# Implementation
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Adding a New Provider
|
|
2
|
+
|
|
3
|
+
## Steps
|
|
4
|
+
|
|
5
|
+
1. Create `lib/riffer/providers/your_provider.rb` extending `Riffer::Providers::Base`
|
|
6
|
+
2. Implement required methods (see below)
|
|
7
|
+
3. Register in `Riffer::Providers::Repository::REPO`
|
|
8
|
+
4. Add provider config to `Riffer::Config` if needed
|
|
9
|
+
5. Create tests in `test/riffer/providers/your_provider_test.rb`
|
|
10
|
+
|
|
11
|
+
## Required Methods
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
# frozen_string_literal: true
|
|
15
|
+
|
|
16
|
+
module Riffer
|
|
17
|
+
module Providers
|
|
18
|
+
class YourProvider < Base
|
|
19
|
+
# Returns Riffer::Messages::Assistant
|
|
20
|
+
def perform_generate_text(messages, model:)
|
|
21
|
+
# Implementation
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns Enumerator yielding stream events
|
|
25
|
+
def perform_stream_text(messages, model:)
|
|
26
|
+
# Implementation
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Registration
|
|
34
|
+
|
|
35
|
+
Add to `Riffer::Providers::Repository::REPO`:
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
REPO = {
|
|
39
|
+
# ... existing providers
|
|
40
|
+
your_provider: -> { YourProvider }
|
|
41
|
+
}.freeze
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Dependencies
|
|
45
|
+
|
|
46
|
+
Use `depends_on` helper for runtime dependency checking if your provider requires external gems.
|
data/.agents/rdoc.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# RDoc Documentation
|
|
2
|
+
|
|
3
|
+
Use pure RDoc comments for public APIs (not YARD).
|
|
4
|
+
|
|
5
|
+
## Parameters
|
|
6
|
+
|
|
7
|
+
Use definition list syntax (`::`):
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# Creates a new agent.
|
|
11
|
+
#
|
|
12
|
+
# name:: String - the agent name
|
|
13
|
+
# options:: Hash - optional configuration
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Return Values
|
|
17
|
+
|
|
18
|
+
Document with prose:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
# Returns String - the agent identifier.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Exceptions
|
|
25
|
+
|
|
26
|
+
Document with prose:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
# Raises Riffer::ArgumentError if the name is invalid.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
Include usage examples as indented code blocks:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# Creates a new agent.
|
|
38
|
+
#
|
|
39
|
+
# agent = MyAgent.new
|
|
40
|
+
# agent.generate('Hello')
|
|
41
|
+
#
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Internal APIs
|
|
45
|
+
|
|
46
|
+
Mark internal APIs with `:nodoc:` to exclude from documentation:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
def internal_method # :nodoc:
|
|
50
|
+
end
|
|
51
|
+
```
|
data/.agents/testing.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
## Framework
|
|
4
|
+
|
|
5
|
+
Use Minitest with the spec DSL for all tests.
|
|
6
|
+
|
|
7
|
+
## Test Structure
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# frozen_string_literal: true
|
|
11
|
+
|
|
12
|
+
require "test_helper"
|
|
13
|
+
|
|
14
|
+
describe Riffer::Feature do
|
|
15
|
+
describe "#method_name" do
|
|
16
|
+
before do
|
|
17
|
+
# setup code
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "does something expected" do
|
|
21
|
+
result = Riffer::Feature.method_name(args)
|
|
22
|
+
assert_equal expected, result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "handles edge case" do
|
|
26
|
+
result = Riffer::Feature.method_name(edge_case_args)
|
|
27
|
+
assert_equal edge_case_expected, result
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Guidelines
|
|
34
|
+
|
|
35
|
+
- Test files go in `test/` directory with `*_test.rb` suffix
|
|
36
|
+
- Use `before`/`after` blocks for setup and cleanup
|
|
37
|
+
- Stick to the single assertion rule where possible
|
|
38
|
+
- Test edge cases and error conditions
|
|
39
|
+
- Use Minitest assertions: `assert_equal`, `assert_instance_of`, `refute_nil`, etc.
|
|
40
|
+
|
|
41
|
+
## VCR Cassettes
|
|
42
|
+
|
|
43
|
+
Record external API interactions in `test/fixtures/vcr_cassettes/`.
|
|
44
|
+
|
|
45
|
+
## Running Tests
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Run all tests
|
|
49
|
+
bundle exec rake test
|
|
50
|
+
|
|
51
|
+
# Run a single test file
|
|
52
|
+
bundle exec ruby -Ilib:test test/riffer/agent_test.rb
|
|
53
|
+
|
|
54
|
+
# Run a specific test by name
|
|
55
|
+
bundle exec ruby -Ilib:test test/riffer/agent_test.rb --name "test_something"
|
|
56
|
+
```
|
data/AGENTS.md
CHANGED
|
@@ -1,315 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Riffer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ruby gem framework for building AI-powered agents with LLM provider adapters.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Reference
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Ruby**: 3.2.0+
|
|
8
|
+
- **Lint + Test**: `bundle exec rake`
|
|
9
|
+
- **Autoloading**: Zeitwerk (file paths must match module/class names)
|
|
10
|
+
- **Model format**: `provider/model` (e.g., `openai/gpt-4`)
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
## Topic Guides
|
|
10
13
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
14
|
+
- [Architecture](.agents/architecture.md) - Core components and project structure
|
|
15
|
+
- [Testing](.agents/testing.md) - Minitest spec DSL and VCR cassettes
|
|
16
|
+
- [Code Style](.agents/code-style.md) - StandardRB and comment conventions
|
|
17
|
+
- [RDoc](.agents/rdoc.md) - Documentation format for public APIs
|
|
18
|
+
- [Providers](.agents/providers.md) - Adding new LLM provider adapters
|
|
15
19
|
|
|
16
|
-
##
|
|
20
|
+
## Commands
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```ruby
|
|
27
|
-
class EchoAgent < Riffer::Agent
|
|
28
|
-
model 'openai/gpt-5-mini' # provider/model
|
|
29
|
-
instructions 'You are an assistant that repeats what the user says.'
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
agent = EchoAgent.new
|
|
33
|
-
puts agent.generate('Hello world')
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
#### Providers (`lib/riffer/providers/`)
|
|
37
|
-
|
|
38
|
-
Adapters for LLM APIs. Each provider extends `Riffer::Providers::Base` and implements:
|
|
39
|
-
|
|
40
|
-
- `perform_generate_text(messages, model:)` – returns `Riffer::Messages::Assistant`
|
|
41
|
-
- `perform_stream_text(messages, model:)` – returns an `Enumerator` yielding stream events
|
|
42
|
-
|
|
43
|
-
Providers are registered in `Riffer::Providers::Repository::REPO` with identifiers (e.g., `openai`, `amazon_bedrock`).
|
|
44
|
-
|
|
45
|
-
#### Messages (`lib/riffer/messages/`)
|
|
46
|
-
|
|
47
|
-
Typed message objects that extend `Riffer::Messages::Base`:
|
|
48
|
-
|
|
49
|
-
- `System` – system instructions
|
|
50
|
-
- `User` – user input
|
|
51
|
-
- `Assistant` – AI responses
|
|
52
|
-
- `Tool` – tool execution results
|
|
53
|
-
|
|
54
|
-
The `Converter` module handles hash-to-object conversion.
|
|
55
|
-
|
|
56
|
-
#### StreamEvents (`lib/riffer/stream_events/`)
|
|
57
|
-
|
|
58
|
-
Structured events for streaming responses:
|
|
59
|
-
|
|
60
|
-
- `TextDelta` – incremental text chunks
|
|
61
|
-
- `TextDone` – completion signals
|
|
62
|
-
- `ReasoningDelta` – reasoning process chunks
|
|
63
|
-
- `ReasoningDone` – reasoning completion
|
|
64
|
-
|
|
65
|
-
### Key Patterns
|
|
66
|
-
|
|
67
|
-
- Model strings use `provider/model` format (e.g., `openai/gpt-4`)
|
|
68
|
-
- Configuration via `Riffer.configure { |c| c.openai.api_key = "..." }`
|
|
69
|
-
- Providers use `depends_on` helper for runtime dependency checking
|
|
70
|
-
- Tests use VCR cassettes in `test/fixtures/vcr_cassettes/`
|
|
71
|
-
- Zeitwerk for autoloading – file structure must match module/class names
|
|
72
|
-
|
|
73
|
-
## Code Style & Standards
|
|
74
|
-
|
|
75
|
-
### Ruby Version
|
|
76
|
-
|
|
77
|
-
- Minimum Ruby version: 3.2.0
|
|
78
|
-
- Use modern Ruby 3.x features and syntax
|
|
79
|
-
|
|
80
|
-
### Code Formatting
|
|
81
|
-
|
|
82
|
-
- Use StandardRB for linting and formatting
|
|
83
|
-
- All Ruby files must include `# frozen_string_literal: true` at the top
|
|
84
|
-
- Follow StandardRB conventions (2-space indentation, double quotes for strings)
|
|
85
|
-
- Custom RuboCop rules are defined in `.standard.yml`
|
|
86
|
-
|
|
87
|
-
### Testing
|
|
88
|
-
|
|
89
|
-
- Use Minitest for all tests with the spec DSL
|
|
90
|
-
- Test files go in `test/` directory with `*_test.rb` suffix
|
|
91
|
-
- Tests must pass before committing
|
|
92
|
-
- Use Minitest assertions: `assert_equal`, `assert_instance_of`, `refute_nil`, etc.
|
|
93
|
-
- Prefer using `setup` and `teardown` methods for test setup/cleanup
|
|
94
|
-
|
|
95
|
-
#### Test Structure
|
|
96
|
-
|
|
97
|
-
```ruby
|
|
98
|
-
# frozen_string_literal: true
|
|
99
|
-
|
|
100
|
-
require "test_helper"
|
|
101
|
-
|
|
102
|
-
describe Riffer::Feature do
|
|
103
|
-
describe "#method_name" do
|
|
104
|
-
before do
|
|
105
|
-
# setup code
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "does something expected" do
|
|
109
|
-
result = Riffer::Feature.method_name(args)
|
|
110
|
-
assert_equal expected, result
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
it "handles edge case" do
|
|
114
|
-
result = Riffer::Feature.method_name(edge_case_args)
|
|
115
|
-
assert_equal edge_case_expected, result
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
#### Test Coverage
|
|
122
|
-
|
|
123
|
-
- Test public APIs thoroughly
|
|
124
|
-
- Test edge cases and error conditions
|
|
125
|
-
- Mock external dependencies
|
|
126
|
-
- Keep tests fast and isolated
|
|
127
|
-
- Stick to the single assertion rule where possible
|
|
128
|
-
|
|
129
|
-
### Documentation
|
|
130
|
-
|
|
131
|
-
- Use YARD-style comments for public APIs
|
|
132
|
-
- Document parameters with `@param`
|
|
133
|
-
- Document return values with `@return`
|
|
134
|
-
- Document raised errors with `@raise`
|
|
135
|
-
|
|
136
|
-
### Comments
|
|
137
|
-
|
|
138
|
-
- Only add comments when the code is ambiguous or not semantically obvious
|
|
139
|
-
- Avoid stating what the code does if it's clear from reading the code itself
|
|
140
|
-
- Use comments to explain **why** something is done, not **what** is being done
|
|
141
|
-
- Comments should add value beyond what the code already expresses
|
|
142
|
-
|
|
143
|
-
### Error Handling
|
|
144
|
-
|
|
145
|
-
- Define custom errors as subclasses of `Riffer::Error`
|
|
146
|
-
- Use descriptive error messages
|
|
147
|
-
- Document errors that can be raised
|
|
148
|
-
|
|
149
|
-
## Project Structure
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
lib/
|
|
153
|
-
riffer.rb # Main entry point, uses Zeitwerk for autoloading
|
|
154
|
-
riffer/
|
|
155
|
-
version.rb # VERSION constant
|
|
156
|
-
config.rb # Configuration class
|
|
157
|
-
core.rb # Core functionality
|
|
158
|
-
agent.rb # Agent class
|
|
159
|
-
messages.rb # Messages namespace/module
|
|
160
|
-
providers.rb # Providers namespace/module
|
|
161
|
-
stream_events.rb # Stream events namespace/module
|
|
162
|
-
helpers/
|
|
163
|
-
class_name_converter.rb # Class name conversion utilities
|
|
164
|
-
dependencies.rb # Dependency management
|
|
165
|
-
validations.rb # Validation helpers
|
|
166
|
-
messages/
|
|
167
|
-
base.rb # Base message class
|
|
168
|
-
assistant.rb # Assistant message
|
|
169
|
-
converter.rb # Message converter
|
|
170
|
-
system.rb # System message
|
|
171
|
-
user.rb # User message
|
|
172
|
-
tool.rb # Tool message
|
|
173
|
-
providers/
|
|
174
|
-
base.rb # Base provider class
|
|
175
|
-
open_ai.rb # OpenAI provider
|
|
176
|
-
amazon_bedrock.rb # Amazon Bedrock provider
|
|
177
|
-
repository.rb # Provider registry
|
|
178
|
-
test.rb # Test provider
|
|
179
|
-
stream_events/
|
|
180
|
-
base.rb # Base stream event
|
|
181
|
-
text_delta.rb # Text delta event
|
|
182
|
-
text_done.rb # Text done event
|
|
183
|
-
reasoning_delta.rb # Reasoning delta event
|
|
184
|
-
reasoning_done.rb # Reasoning done event
|
|
185
|
-
test/
|
|
186
|
-
test_helper.rb # Minitest configuration with VCR
|
|
187
|
-
riffer_test.rb # Main module tests
|
|
188
|
-
riffer/
|
|
189
|
-
[feature]_test.rb # Feature tests mirror lib/riffer/ structure
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## Development Workflow
|
|
193
|
-
|
|
194
|
-
### Autoloading with Zeitwerk
|
|
195
|
-
|
|
196
|
-
- The project uses Zeitwerk for autoloading
|
|
197
|
-
- File structure must match module/class names
|
|
198
|
-
- No explicit `require` statements needed for lib files
|
|
199
|
-
- Special inflections are configured in `lib/riffer.rb` (e.g., `open_ai.rb` → `OpenAI`)
|
|
200
|
-
|
|
201
|
-
### Adding New Features
|
|
202
|
-
|
|
203
|
-
1. Create feature files under `lib/riffer/` following Zeitwerk conventions
|
|
204
|
-
2. File names should be snake_case, class names should be PascalCase
|
|
205
|
-
3. Create corresponding tests in `test/riffer/` mirroring the lib structure
|
|
206
|
-
4. Run tests: `rake test`
|
|
207
|
-
5. Check code style: `rake standard`
|
|
208
|
-
|
|
209
|
-
### Adding a New Provider
|
|
210
|
-
|
|
211
|
-
1. Create `lib/riffer/providers/your_provider.rb` extending `Riffer::Providers::Base`
|
|
212
|
-
2. Implement `perform_generate_text(messages, model:)` returning `Riffer::Messages::Assistant`
|
|
213
|
-
3. Implement `perform_stream_text(messages, model:)` returning an `Enumerator` yielding stream events
|
|
214
|
-
4. Register in `Riffer::Providers::Repository::REPO`
|
|
215
|
-
5. Add provider config to `Riffer::Config` if needed
|
|
216
|
-
6. Create corresponding test file in `test/riffer/providers/`
|
|
217
|
-
|
|
218
|
-
### Dependencies
|
|
219
|
-
|
|
220
|
-
- Add runtime dependencies in `riffer.gemspec` using `spec.add_dependency`
|
|
221
|
-
- Add development dependencies in `Gemfile`
|
|
222
|
-
- Document significant dependencies in README
|
|
223
|
-
|
|
224
|
-
### Version Management
|
|
225
|
-
|
|
226
|
-
- Update version in `lib/riffer/version.rb`
|
|
227
|
-
- Follow Semantic Versioning (MAJOR.MINOR.PATCH)
|
|
228
|
-
- Update CHANGELOG.md with changes
|
|
229
|
-
|
|
230
|
-
## AI/Agent Development Context
|
|
231
|
-
|
|
232
|
-
Since Riffer is an AI framework, when working on AI-related features:
|
|
233
|
-
|
|
234
|
-
- Consider integration with common AI APIs (OpenAI, Anthropic, Amazon Bedrock, etc.)
|
|
235
|
-
- Design for extensibility and plugin architecture
|
|
236
|
-
- Handle API rate limiting and retries
|
|
237
|
-
- Implement proper error handling for external services
|
|
238
|
-
- Consider streaming responses where applicable
|
|
239
|
-
- Think about token counting and cost management
|
|
240
|
-
- Support async/concurrent operations where beneficial
|
|
241
|
-
|
|
242
|
-
## Commands Reference
|
|
243
|
-
|
|
244
|
-
```bash
|
|
245
|
-
# Install dependencies
|
|
246
|
-
bin/setup
|
|
247
|
-
|
|
248
|
-
# Run tests
|
|
249
|
-
bundle exec rake test
|
|
250
|
-
|
|
251
|
-
# Run a single test file
|
|
252
|
-
bundle exec ruby -Ilib:test test/riffer/agent_test.rb
|
|
253
|
-
|
|
254
|
-
# Run a specific test by name
|
|
255
|
-
bundle exec ruby -Ilib:test test/riffer/agent_test.rb --name "test_something"
|
|
256
|
-
|
|
257
|
-
# Check code style
|
|
258
|
-
bundle exec rake standard
|
|
259
|
-
|
|
260
|
-
# Auto-fix style issues
|
|
261
|
-
bundle exec rake standard:fix
|
|
262
|
-
|
|
263
|
-
# Run both tests and linting (default task)
|
|
264
|
-
bundle exec rake
|
|
265
|
-
|
|
266
|
-
# Interactive console
|
|
267
|
-
bin/console
|
|
268
|
-
|
|
269
|
-
# Generate documentation
|
|
270
|
-
bundle exec rake docs
|
|
271
|
-
|
|
272
|
-
# Install gem locally
|
|
273
|
-
bundle exec rake install
|
|
274
|
-
|
|
275
|
-
# Release new version (maintainers only)
|
|
276
|
-
bundle exec rake release
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
## Code Patterns
|
|
280
|
-
|
|
281
|
-
### Module Structure
|
|
282
|
-
|
|
283
|
-
```ruby
|
|
284
|
-
# frozen_string_literal: true
|
|
285
|
-
|
|
286
|
-
module Riffer::Feature
|
|
287
|
-
class MyClass
|
|
288
|
-
# Implementation
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
### Configuration Example
|
|
294
|
-
|
|
295
|
-
```ruby
|
|
296
|
-
Riffer.configure do |config|
|
|
297
|
-
config.openai.api_key = ENV['OPENAI_API_KEY']
|
|
298
|
-
end
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
### Streaming Example
|
|
302
|
-
|
|
303
|
-
```ruby
|
|
304
|
-
agent = EchoAgent.new
|
|
305
|
-
agent.stream('Tell me a story').each do |event|
|
|
306
|
-
print event.content
|
|
307
|
-
end
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
## Important Notes
|
|
311
|
-
|
|
312
|
-
- Always run `rake` (runs both test and standard) before committing
|
|
313
|
-
- Keep the README updated with new features
|
|
314
|
-
- Follow the Code of Conduct in all interactions
|
|
315
|
-
- This gem is MIT licensed – keep license headers consistent
|
|
22
|
+
| Command | Description |
|
|
23
|
+
|---------|-------------|
|
|
24
|
+
| `bundle exec rake` | Run tests + lint (default) |
|
|
25
|
+
| `bundle exec rake test` | Run tests only |
|
|
26
|
+
| `bundle exec rake standard` | Check code style |
|
|
27
|
+
| `bundle exec rake standard:fix` | Auto-fix style issues |
|
|
28
|
+
| `bin/console` | Interactive console |
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.0](https://github.com/janeapp/riffer/compare/riffer/v0.7.0...riffer/v0.8.0) (2026-01-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add anthropic provider support ([#89](https://github.com/janeapp/riffer/issues/89)) ([338674e](https://github.com/janeapp/riffer/commit/338674e794535b2559ce4dca5d36e09e9512b94c))
|
|
14
|
+
* add on_message callback for real-time message emission ([#87](https://github.com/janeapp/riffer/issues/87)) ([92e6f91](https://github.com/janeapp/riffer/commit/92e6f919b9facee9a2fb6234c1bdd69b525dbf21))
|
|
15
|
+
* add timeout functionality to tools ([#86](https://github.com/janeapp/riffer/issues/86)) ([3b7d9af](https://github.com/janeapp/riffer/commit/3b7d9afeed829001de0f6524694c193d54f1e7af))
|
|
16
|
+
* better docs ([#84](https://github.com/janeapp/riffer/issues/84)) ([630580a](https://github.com/janeapp/riffer/commit/630580ae08a86dfa5ab1f75ebb229db7cff6344d))
|
|
17
|
+
|
|
8
18
|
## [0.7.0](https://github.com/janeapp/riffer/compare/riffer/v0.6.1...riffer/v0.7.0) (2026-01-21)
|
|
9
19
|
|
|
10
20
|
|