rails_ai 0.2.4 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +143 -186
- data/lib/rails_ai/version.rb +1 -1
- data/lib/rails_ai.rb +168 -390
- data/setup_wiki.sh +55 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c840d854535a0a9d4ecd6d2feab11eaf3b41d57774e95f1ea4106d4e85273c6b
|
4
|
+
data.tar.gz: a60c7e6aa407e2b81758209862b13a368716dd271131745657527adb67d0df89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ca12e397057425ff91739697b1ee75249aa19bc5db807e6181cd43514257750eeb372a4c25172575943bc6e7aa98cf61da24f5e674b5b97d3d200d232255fa1
|
7
|
+
data.tar.gz: 0b00092ed6b79d49c4bae8ae22eabc49f83386bed45ad18d1c8b72fdc85e2c3d3156438612df900fc3266c37a78b9734a1dd0a03619e9416e3dd4756c6db305c
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,41 @@ All notable changes to the Rails AI gem will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.2.5] - 2024-09-21
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
- Fixed critical syntax error with unmatched `end` statements in `lib/rails_ai.rb`
|
12
|
+
- Resolved `SyntaxError: unexpected 'end'` that was preventing gem loading
|
13
|
+
- Properly structured module and method definitions within correct scope
|
14
|
+
- Fixed gem loading issues that were causing Rails applications to fail
|
15
|
+
|
16
|
+
### Added
|
17
|
+
- `clean_response` utility method for automatic UTF-8 encoding and character cleaning
|
18
|
+
- `chat_clean` method that automatically cleans AI responses
|
19
|
+
- `chat_with_web_search_clean` method with automatic response cleaning
|
20
|
+
- Enhanced error handling for malformed responses
|
21
|
+
|
22
|
+
### Changed
|
23
|
+
- Improved response handling to prevent encoding issues
|
24
|
+
- Better UTF-8 character replacement for invalid characters
|
25
|
+
- Enhanced error handling for character encoding problems
|
26
|
+
|
27
|
+
## [0.2.4] - 2024-09-21
|
28
|
+
|
29
|
+
### Fixed
|
30
|
+
- Fixed character encoding issues in AI responses
|
31
|
+
- Resolved `JSON::GeneratorError` in agent functionality
|
32
|
+
- Fixed garbled character display in agent responses
|
33
|
+
|
34
|
+
### Added
|
35
|
+
- Response cleaning utility methods
|
36
|
+
- Enhanced UTF-8 encoding handling
|
37
|
+
- Better error handling for malformed responses
|
38
|
+
|
39
|
+
### Changed
|
40
|
+
- Improved response processing to handle compressed and encoded data
|
41
|
+
- Enhanced character encoding validation
|
42
|
+
|
8
43
|
## [0.2.3] - 2024-09-21
|
9
44
|
|
10
45
|
### Fixed
|
@@ -50,261 +85,183 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
50
85
|
## [0.2.0] - 2024-09-21
|
51
86
|
|
52
87
|
### Added
|
53
|
-
-
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
- Custom security scanner with vulnerability detection
|
59
|
-
- CI/CD security monitoring with multiple security tools
|
60
|
-
|
61
|
-
### Fixed
|
62
|
-
- Fixed syntax error with extra `end` keyword in main module
|
63
|
-
- Resolved character encoding issues with UTF-8 conversion
|
64
|
-
- Fixed method visibility and file loading conflicts
|
65
|
-
|
66
|
-
### Security
|
67
|
-
- Implemented input validation for text, file paths, URLs, and Base64 data
|
68
|
-
- Added rate limiting per user and endpoint
|
69
|
-
- Content sanitization to prevent XSS and injection attacks
|
70
|
-
- Secure file handling with path validation and size limits
|
71
|
-
- API security with SSL/TLS enforcement and error handling
|
72
|
-
- SSRF protection with URL validation and host blocking
|
73
|
-
|
74
|
-
## [0.1.9] - 2024-09-21
|
75
|
-
|
76
|
-
### Fixed
|
77
|
-
- Fixed CI validation errors by excluding `.gem` files from gemspec
|
78
|
-
- Resolved `NoMethodError: undefined method 'megabytes'` by adding ActiveSupport dependency
|
79
|
-
- Fixed method visibility issues with `validate_messages` method
|
80
|
-
|
81
|
-
### Changed
|
82
|
-
- Updated gemspec to exclude generated files and security reports
|
83
|
-
- Added `activesupport` dependency for numeric extensions
|
84
|
-
- Improved error handling and method accessibility
|
85
|
-
|
86
|
-
## [0.1.8] - 2024-09-21
|
87
|
-
|
88
|
-
### Fixed
|
89
|
-
- Fixed `NoMethodError: undefined method 'validate_messages'` by making method public
|
90
|
-
- Resolved method visibility conflicts in security module
|
91
|
-
- Fixed file loading order issues
|
92
|
-
|
93
|
-
### Changed
|
94
|
-
- Updated security module to properly load input validator
|
95
|
-
- Improved method accessibility and error handling
|
96
|
-
|
97
|
-
## [0.1.7] - 2024-09-21
|
88
|
+
- Web search integration with Google Search and DuckDuckGo providers
|
89
|
+
- `WebSearch` module with `GoogleSearch` and `DuckDuckGoSearch` classes
|
90
|
+
- `chat_with_web_search` method for real-time information retrieval
|
91
|
+
- Support for current events, news, weather, and time-sensitive queries
|
92
|
+
- Web search fallback to regular chat if search fails
|
98
93
|
|
99
94
|
### Fixed
|
100
|
-
- Fixed `
|
101
|
-
- Resolved
|
102
|
-
- Fixed
|
95
|
+
- Fixed `SyntaxError: unexpected 'end'` in `lib/rails_ai.rb`
|
96
|
+
- Resolved `ArgumentError: unknown keyword: :num_results` in web search
|
97
|
+
- Fixed method parameter passing in `WebSearch.search` method
|
103
98
|
|
104
99
|
### Changed
|
105
|
-
-
|
106
|
-
- Improved error handling
|
100
|
+
- Enhanced chat functionality with web search capabilities
|
101
|
+
- Improved error handling for web search failures
|
102
|
+
- Updated demo application with web search integration
|
107
103
|
|
108
104
|
## [0.1.6] - 2024-09-21
|
109
105
|
|
110
106
|
### Fixed
|
111
|
-
- Fixed `NoMethodError: undefined method '
|
112
|
-
- Resolved
|
113
|
-
- Fixed
|
107
|
+
- Fixed `NoMethodError: undefined method 'megabytes'` by adding ActiveSupport dependency
|
108
|
+
- Resolved gem loading issues in demo application
|
109
|
+
- Fixed `ArgumentError: unknown keyword: :collaboration_strategy` in agent team creation
|
114
110
|
|
115
111
|
### Changed
|
116
|
-
- Updated
|
117
|
-
-
|
112
|
+
- Updated `rails_ai.gemspec` to include `activesupport` dependency
|
113
|
+
- Enhanced agent team creation with proper parameter handling
|
114
|
+
- Improved error handling for missing ActiveSupport extensions
|
118
115
|
|
119
116
|
## [0.1.5] - 2024-09-21
|
120
117
|
|
121
118
|
### Fixed
|
122
|
-
- Fixed
|
123
|
-
- Resolved method
|
124
|
-
- Fixed file loading
|
119
|
+
- Fixed method visibility issues with `validate_messages` method
|
120
|
+
- Resolved `NoMethodError: undefined method 'validate_messages'` in security validation
|
121
|
+
- Fixed file loading conflicts between duplicate `InputValidator` classes
|
125
122
|
|
126
123
|
### Changed
|
127
|
-
- Updated security
|
128
|
-
-
|
124
|
+
- Updated `lib/rails_ai/security.rb` to properly require input validator
|
125
|
+
- Removed duplicate `InputValidator` class definition
|
126
|
+
- Enhanced security validation method availability
|
129
127
|
|
130
128
|
## [0.1.4] - 2024-09-21
|
131
129
|
|
132
130
|
### Fixed
|
133
131
|
- Fixed `NoMethodError: undefined method 'validate_messages'` by making method public
|
134
|
-
- Resolved
|
135
|
-
- Fixed
|
132
|
+
- Resolved security validation issues in demo application
|
133
|
+
- Fixed method visibility in `InputValidator` class
|
136
134
|
|
137
135
|
### Changed
|
138
|
-
-
|
139
|
-
-
|
136
|
+
- Moved `validate_messages` method above `private` keyword in `InputValidator`
|
137
|
+
- Enhanced security validation method accessibility
|
140
138
|
|
141
139
|
## [0.1.3] - 2024-09-21
|
142
140
|
|
143
141
|
### Fixed
|
144
|
-
- Fixed `NoMethodError: undefined method 'validate_messages'`
|
145
|
-
- Resolved method
|
146
|
-
- Fixed
|
142
|
+
- Fixed `NoMethodError: undefined method 'validate_messages'` in security validation
|
143
|
+
- Resolved method availability issues in demo application
|
144
|
+
- Fixed security validation method calls
|
147
145
|
|
148
146
|
### Changed
|
149
|
-
- Updated security
|
150
|
-
-
|
147
|
+
- Updated security validation method definitions
|
148
|
+
- Enhanced error handling for security validation
|
151
149
|
|
152
150
|
## [0.1.2] - 2024-09-21
|
153
151
|
|
154
152
|
### Fixed
|
155
|
-
- Fixed CI
|
156
|
-
- Resolved
|
157
|
-
- Fixed
|
153
|
+
- Fixed CI failure with `rails_ai-0.1.1 contains itself` error
|
154
|
+
- Resolved gemspec file inclusion issues
|
155
|
+
- Fixed `.gem` file inclusion in `s.files` list
|
158
156
|
|
159
157
|
### Changed
|
160
|
-
- Updated gemspec to exclude generated files
|
161
|
-
- Added `
|
162
|
-
-
|
158
|
+
- Updated `rails_ai.gemspec` to exclude generated `.gem` files
|
159
|
+
- Added `*.gem` to `.gitignore`
|
160
|
+
- Enhanced gemspec file filtering
|
163
161
|
|
164
162
|
## [0.1.1] - 2024-09-21
|
165
163
|
|
166
164
|
### Fixed
|
167
165
|
- Fixed `NoMethodError: undefined method 'megabytes'` by adding ActiveSupport dependency
|
168
|
-
- Resolved
|
169
|
-
- Fixed
|
166
|
+
- Resolved gem loading issues in demo application
|
167
|
+
- Fixed `ArgumentError: unknown keyword: :collaboration_strategy` in agent team creation
|
170
168
|
|
171
169
|
### Changed
|
172
|
-
-
|
173
|
-
-
|
174
|
-
- Improved
|
170
|
+
- Updated `rails_ai.gemspec` to include `activesupport` dependency
|
171
|
+
- Enhanced agent team creation with proper parameter handling
|
172
|
+
- Improved error handling for missing ActiveSupport extensions
|
175
173
|
|
176
174
|
## [0.1.0] - 2024-09-21
|
177
175
|
|
178
176
|
### Added
|
179
177
|
- Initial release of Rails AI gem
|
180
|
-
- Multi-provider support
|
178
|
+
- Multi-provider support (OpenAI, Anthropic, Gemini)
|
181
179
|
- Direct API integration without external gem dependencies
|
182
|
-
-
|
183
|
-
-
|
184
|
-
-
|
185
|
-
-
|
186
|
-
-
|
187
|
-
-
|
188
|
-
-
|
189
|
-
-
|
190
|
-
- Agent teams with various collaboration strategies
|
191
|
-
- Agent Manager for centralized system management
|
192
|
-
- Comprehensive security framework
|
193
|
-
- Input validation and sanitization
|
194
|
-
- Rate limiting and content filtering
|
195
|
-
- Secure file handling and API security
|
196
|
-
- SSRF protection and API key management
|
197
|
-
- Audit logging and error handling
|
198
|
-
- Custom security scanner
|
199
|
-
- CI/CD security monitoring
|
200
|
-
- Legal protection framework for Canadian jurisdiction
|
201
|
-
- Commercial license template and monitoring system
|
202
|
-
- Comprehensive documentation and wiki
|
203
|
-
- Rails 5.2+ compatibility with Ruby 3+ support
|
204
|
-
- MIT License with non-commercial use restrictions
|
180
|
+
- Multimodal capabilities (text, image, video, audio)
|
181
|
+
- Agent system with specialized agents and collaboration
|
182
|
+
- Context awareness with user and window context
|
183
|
+
- Security features including input validation and rate limiting
|
184
|
+
- Performance optimizations with connection pooling and caching
|
185
|
+
- Web search integration for real-time information
|
186
|
+
- Comprehensive demo Rails application
|
187
|
+
- Extensive documentation and wiki pages
|
205
188
|
|
206
189
|
### Features
|
207
|
-
- **Text Generation**: Support for GPT-4o, GPT-4, GPT-3.5-turbo
|
208
|
-
- **Image
|
209
|
-
- **Image
|
210
|
-
- **Video
|
211
|
-
- **Audio Processing**:
|
212
|
-
- **
|
213
|
-
- **
|
214
|
-
- **
|
215
|
-
- **
|
216
|
-
- **
|
217
|
-
- **Security**: Comprehensive security framework with multiple protection layers
|
218
|
-
- **Performance**: Optimized for speed with connection pooling and batch processing
|
219
|
-
- **Monitoring**: Continuous monitoring for security and unauthorized use
|
220
|
-
- **Legal Protection**: Canadian legal framework with commercial licensing
|
221
|
-
|
222
|
-
### Technical Details
|
223
|
-
- **Rails Compatibility**: Rails 5.2, 6.x, 7.x, 8.x
|
224
|
-
- **Ruby Compatibility**: Ruby 3.0+
|
225
|
-
- **Dependencies**: Minimal external dependencies for maximum compatibility
|
226
|
-
- **Performance**: Optimized for speed with caching and connection pooling
|
227
|
-
- **Security**: Multiple security layers with input validation and sanitization
|
228
|
-
- **Monitoring**: Continuous monitoring with CI/CD integration
|
229
|
-
- **Documentation**: Comprehensive documentation and wiki
|
230
|
-
- **Legal**: Non-commercial license with commercial licensing available
|
231
|
-
|
232
|
-
### Breaking Changes
|
233
|
-
- None in initial release
|
234
|
-
|
235
|
-
### Deprecated
|
236
|
-
- None in initial release
|
237
|
-
|
238
|
-
### Removed
|
239
|
-
- None in initial release
|
190
|
+
- **Text Generation**: Support for GPT-4o, GPT-4, GPT-3.5-turbo models
|
191
|
+
- **Image Analysis**: Vision models for image understanding
|
192
|
+
- **Image Generation**: DALL-E 3 and DALL-E 2 integration
|
193
|
+
- **Video Analysis**: Frame extraction and analysis capabilities
|
194
|
+
- **Audio Processing**: Whisper integration for speech-to-text
|
195
|
+
- **Agent System**: Multi-agent collaboration with specialized roles
|
196
|
+
- **Context Awareness**: User preferences and window context integration
|
197
|
+
- **Security**: Input validation, rate limiting, content sanitization
|
198
|
+
- **Performance**: Connection pooling, smart caching, request deduplication
|
199
|
+
- **Web Search**: Real-time information retrieval with Google and DuckDuckGo
|
240
200
|
|
241
201
|
### Security
|
242
|
-
- Comprehensive security framework implemented
|
243
202
|
- Input validation and sanitization
|
244
|
-
- Rate limiting and
|
245
|
-
-
|
246
|
-
-
|
247
|
-
-
|
248
|
-
-
|
249
|
-
- CI/CD security monitoring
|
203
|
+
- Rate limiting and abuse prevention
|
204
|
+
- Content filtering and safety checks
|
205
|
+
- API key management and security
|
206
|
+
- SSRF protection and secure HTTP client
|
207
|
+
- Comprehensive error handling
|
250
208
|
|
251
209
|
### Performance
|
252
|
-
-
|
253
|
-
-
|
210
|
+
- Connection pooling for concurrent requests
|
211
|
+
- Smart caching with TTL support
|
212
|
+
- Request deduplication to prevent duplicate API calls
|
213
|
+
- Performance monitoring and metrics
|
254
214
|
- Batch processing capabilities
|
255
|
-
-
|
256
|
-
- Performance monitoring and optimization
|
257
|
-
- Memory management and optimization
|
215
|
+
- Memory optimization
|
258
216
|
|
259
217
|
### Documentation
|
260
218
|
- Comprehensive README with usage examples
|
261
|
-
-
|
262
|
-
-
|
263
|
-
-
|
264
|
-
-
|
265
|
-
-
|
266
|
-
- Commercial license template
|
267
|
-
- GitHub wiki with detailed documentation
|
219
|
+
- API documentation with all methods and parameters
|
220
|
+
- Architecture overview and design decisions
|
221
|
+
- Security guide and best practices
|
222
|
+
- Contributing guidelines and development setup
|
223
|
+
- Wiki pages with detailed feature explanations
|
268
224
|
|
269
225
|
### Legal
|
270
|
-
-
|
271
|
-
-
|
272
|
-
-
|
273
|
-
-
|
274
|
-
-
|
275
|
-
|
226
|
+
- Non-commercial license with commercial licensing available
|
227
|
+
- Legal protection guide for Canadian jurisdiction
|
228
|
+
- Monitoring system for unauthorized commercial use
|
229
|
+
- Cease and desist template for enforcement
|
230
|
+
- Commercial license template ($999/year)
|
231
|
+
|
232
|
+
### Demo Application
|
233
|
+
- Complete Rails demo application (`rails_ai_demo`)
|
234
|
+
- All features demonstrated with working examples
|
235
|
+
- Modern UI with responsive design
|
236
|
+
- Real-time streaming chat
|
237
|
+
- Image analysis and generation demos
|
238
|
+
- Agent system demonstration
|
239
|
+
- Context awareness examples
|
276
240
|
|
277
|
-
|
241
|
+
### Breaking Changes
|
242
|
+
- None (initial release)
|
278
243
|
|
279
|
-
|
280
|
-
|
281
|
-
- **0.2.3**: Fixed agent team creation and improved task execution
|
282
|
-
- **0.2.2**: Fixed streaming demo and cookie overflow issues
|
283
|
-
- **0.2.1**: Added web search integration and real-time information
|
284
|
-
- **0.2.0**: Added comprehensive security framework
|
285
|
-
- **0.1.9**: Fixed CI validation and ActiveSupport dependencies
|
286
|
-
- **0.1.8**: Fixed method visibility and file loading issues
|
287
|
-
- **0.1.7**: Fixed validate_messages method accessibility
|
288
|
-
- **0.1.6**: Updated security module and method accessibility
|
289
|
-
- **0.1.5**: Fixed method visibility and file loading conflicts
|
290
|
-
- **0.1.4**: Made validate_messages method public
|
291
|
-
- **0.1.3**: Fixed method visibility issues
|
292
|
-
- **0.1.2**: Fixed CI validation and added ActiveSupport dependency
|
293
|
-
- **0.1.1**: Fixed megabytes method and added ActiveSupport dependency
|
294
|
-
- **0.1.0**: Initial release with comprehensive AI capabilities
|
244
|
+
### Deprecations
|
245
|
+
- None (initial release)
|
295
246
|
|
296
|
-
|
247
|
+
### Removals
|
248
|
+
- None (initial release)
|
297
249
|
|
298
|
-
|
250
|
+
---
|
299
251
|
|
300
|
-
##
|
252
|
+
## Contributing
|
301
253
|
|
302
|
-
|
254
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
303
255
|
|
304
256
|
## Support
|
305
257
|
|
306
|
-
For support
|
258
|
+
For support and questions:
|
259
|
+
- Create an issue on GitHub
|
260
|
+
- Check the wiki documentation
|
261
|
+
- Review the API documentation
|
262
|
+
|
263
|
+
## License
|
307
264
|
|
308
|
-
|
265
|
+
This project is licensed under the PolyForm-Noncommercial-1.0.0 License - see the [LICENSE](LICENSE) file for details.
|
309
266
|
|
310
|
-
For commercial use, please contact
|
267
|
+
For commercial use, please contact the author for licensing terms.
|
data/lib/rails_ai/version.rb
CHANGED
data/lib/rails_ai.rb
CHANGED
@@ -48,169 +48,58 @@ module RailsAi
|
|
48
48
|
class << self
|
49
49
|
# Version compatibility helpers
|
50
50
|
def rails_version
|
51
|
-
Rails.version.
|
51
|
+
Rails.version.to_f
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
55
|
-
|
54
|
+
def ruby_version
|
55
|
+
RUBY_VERSION.to_f
|
56
56
|
end
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
# Configuration
|
59
|
+
def config
|
60
|
+
@config ||= Config.new
|
60
61
|
end
|
61
62
|
|
62
|
-
def
|
63
|
-
|
63
|
+
def configure
|
64
|
+
yield(config)
|
64
65
|
end
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
case config.provider.to_sym
|
74
|
-
when :openai then Providers::SecureOpenAIAdapter.new
|
75
|
-
when :anthropic then Providers::SecureAnthropicAdapter.new
|
76
|
-
when :gemini then Providers::GeminiAdapter.new
|
77
|
-
when :dummy then Providers::DummyAdapter.new
|
78
|
-
else Providers::DummyAdapter.new
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Agent management
|
84
|
-
def agent_manager
|
85
|
-
@agent_manager ||= Agents::AgentManager.new
|
86
|
-
end
|
87
|
-
|
88
|
-
def create_agent(name:, role:, capabilities: [], **opts)
|
89
|
-
agent = Agents::BaseAgent.new(
|
90
|
-
name: name,
|
91
|
-
role: role,
|
92
|
-
capabilities: capabilities,
|
93
|
-
**opts
|
67
|
+
# Performance optimizations
|
68
|
+
def connection_pool
|
69
|
+
@connection_pool ||= Concurrent::ThreadPoolExecutor.new(
|
70
|
+
min_threads: 2,
|
71
|
+
max_threads: 10,
|
72
|
+
max_queue: 100,
|
73
|
+
auto_terminate: true
|
94
74
|
)
|
95
|
-
agent_manager.register_agent(agent)
|
96
|
-
agent
|
97
|
-
end
|
98
|
-
|
99
|
-
def create_research_agent(name: "ResearchAgent", **opts)
|
100
|
-
agent = Agents::ResearchAgent.new(name: name, **opts)
|
101
|
-
agent_manager.register_agent(agent)
|
102
|
-
agent
|
103
|
-
end
|
104
|
-
|
105
|
-
def create_creative_agent(name: "CreativeAgent", **opts)
|
106
|
-
agent = Agents::CreativeAgent.new(name: name, **opts)
|
107
|
-
agent_manager.register_agent(agent)
|
108
|
-
agent
|
109
|
-
end
|
110
|
-
|
111
|
-
def create_technical_agent(name: "TechnicalAgent", **opts)
|
112
|
-
agent = Agents::TechnicalAgent.new(name: name, **opts)
|
113
|
-
agent_manager.register_agent(agent)
|
114
|
-
agent
|
115
|
-
end
|
116
|
-
|
117
|
-
def create_coordinator_agent(name: "CoordinatorAgent", **opts)
|
118
|
-
agent = Agents::CoordinatorAgent.new(name: name, **opts)
|
119
|
-
agent_manager.register_agent(agent)
|
120
|
-
agent
|
121
|
-
end
|
122
|
-
|
123
|
-
def get_agent(name)
|
124
|
-
agent_manager.get_agent(name)
|
125
|
-
end
|
126
|
-
|
127
|
-
def list_agents
|
128
|
-
agent_manager.list_agents
|
129
|
-
end
|
130
|
-
|
131
|
-
def start_agents!
|
132
|
-
agent_manager.start!
|
133
|
-
end
|
134
|
-
|
135
|
-
def stop_agents!
|
136
|
-
agent_manager.stop!
|
137
|
-
end
|
138
|
-
|
139
|
-
# Task management
|
140
|
-
def submit_task(task)
|
141
|
-
agent_manager.submit_task(task)
|
142
|
-
end
|
143
|
-
|
144
|
-
def assign_task(task, agent_name)
|
145
|
-
agent_manager.assign_task_to_agent(task, agent_name)
|
146
75
|
end
|
147
76
|
|
148
|
-
def
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
156
|
-
|
157
|
-
def orchestrate_collaboration(task, agent_names)
|
158
|
-
agent_manager.orchestrate_collaboration(task, agent_names)
|
159
|
-
end
|
160
|
-
|
161
|
-
# Agent communication
|
162
|
-
def send_agent_message(from_agent, to_agent, message)
|
163
|
-
agent_manager.send_message(from_agent, to_agent, message)
|
164
|
-
end
|
165
|
-
|
166
|
-
def broadcast_agent_message(from_agent, message, exclude: [])
|
167
|
-
agent_manager.broadcast_message(from_agent, message, exclude: exclude)
|
77
|
+
def batch_processor
|
78
|
+
@batch_processor ||= Concurrent::ThreadPoolExecutor.new(
|
79
|
+
min_threads: 1,
|
80
|
+
max_threads: 5,
|
81
|
+
max_queue: 50,
|
82
|
+
auto_terminate: true
|
83
|
+
)
|
168
84
|
end
|
169
85
|
|
170
|
-
|
171
|
-
|
172
|
-
agent_manager.system_status
|
86
|
+
def smart_cache
|
87
|
+
@smart_cache ||= Cache.new
|
173
88
|
end
|
174
89
|
|
175
|
-
def
|
176
|
-
|
90
|
+
def request_deduplicator
|
91
|
+
@request_deduplicator ||= Performance::RequestDeduplicator.new
|
177
92
|
end
|
178
93
|
|
179
|
-
# Performance monitoring
|
180
94
|
def performance_monitor
|
181
95
|
@performance_monitor ||= Performance::PerformanceMonitor.new
|
182
96
|
end
|
183
97
|
|
184
|
-
def
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
|
-
# Connection pool for HTTP requests
|
189
|
-
def connection_pool
|
190
|
-
@connection_pool ||= Performance::ConnectionPool.new(size: config.connection_pool_size)
|
191
|
-
end
|
192
|
-
|
193
|
-
# Smart caching with compression
|
194
|
-
def smart_cache
|
195
|
-
@smart_cache ||= Performance::SmartCache.new(
|
196
|
-
compression_threshold: config.compression_threshold
|
197
|
-
)
|
198
|
-
end
|
199
|
-
|
200
|
-
# Request deduplication
|
201
|
-
def request_deduplicator
|
202
|
-
@request_deduplicator ||= Performance::RequestDeduplicator.new
|
203
|
-
end
|
204
|
-
|
205
|
-
# Batch processor for multiple operations
|
206
|
-
def batch_processor
|
207
|
-
@batch_processor ||= Performance::BatchProcessor.new(
|
208
|
-
batch_size: config.batch_size,
|
209
|
-
flush_interval: config.flush_interval
|
210
|
-
)
|
98
|
+
def agent_manager
|
99
|
+
@agent_manager ||= Agents::AgentManager.new
|
211
100
|
end
|
212
101
|
|
213
|
-
#
|
102
|
+
# Core AI methods
|
214
103
|
def chat(prompt_or_messages, model: config.default_model, **opts)
|
215
104
|
performance_monitor.measure(:chat) do
|
216
105
|
messages = normalize_messages(prompt_or_messages)
|
@@ -235,331 +124,220 @@ module RailsAi
|
|
235
124
|
end
|
236
125
|
end
|
237
126
|
|
238
|
-
def embed(texts, model:
|
127
|
+
def embed(texts, model: "text-embedding-3-small", **opts)
|
239
128
|
performance_monitor.measure(:embed) do
|
240
|
-
|
241
|
-
cache_key = [:embed, model,
|
129
|
+
texts_array = Array(texts)
|
130
|
+
cache_key = [:embed, model, texts_array.hash]
|
242
131
|
|
243
132
|
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
244
133
|
request_deduplicator.deduplicate(cache_key) do
|
245
|
-
provider.embed!(texts:
|
134
|
+
provider.embed!(texts: texts_array, model: model, **opts)
|
246
135
|
end
|
247
136
|
end
|
248
137
|
end
|
249
138
|
end
|
250
139
|
|
251
|
-
#
|
252
|
-
def
|
253
|
-
performance_monitor.measure(:
|
254
|
-
|
255
|
-
|
256
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
257
|
-
request_deduplicator.deduplicate(cache_key) do
|
258
|
-
provider.generate_image!(prompt: prompt, model: model, size: size, quality: quality, **opts)
|
259
|
-
end
|
260
|
-
end
|
140
|
+
# Multimodal capabilities
|
141
|
+
def analyze_image(image, prompt, model: "gpt-4o", **opts)
|
142
|
+
performance_monitor.measure(:analyze_image) do
|
143
|
+
provider.analyze_image!(image: image, prompt: prompt, model: model, **opts)
|
261
144
|
end
|
262
145
|
end
|
263
146
|
|
264
|
-
def
|
265
|
-
performance_monitor.measure(:
|
266
|
-
|
267
|
-
|
268
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
269
|
-
request_deduplicator.deduplicate(cache_key) do
|
270
|
-
provider.edit_image!(image: image, prompt: prompt, mask: mask, size: size, **opts)
|
271
|
-
end
|
272
|
-
end
|
147
|
+
def generate_image(prompt, model: "dall-e-3", **opts)
|
148
|
+
performance_monitor.measure(:generate_image) do
|
149
|
+
provider.generate_image!(prompt: prompt, model: model, **opts)
|
273
150
|
end
|
274
151
|
end
|
275
152
|
|
276
|
-
def
|
277
|
-
performance_monitor.measure(:
|
278
|
-
|
279
|
-
|
280
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
281
|
-
request_deduplicator.deduplicate(cache_key) do
|
282
|
-
provider.create_variation!(image: image, size: size, **opts)
|
283
|
-
end
|
284
|
-
end
|
153
|
+
def analyze_video(video, prompt, model: "gpt-4o", **opts)
|
154
|
+
performance_monitor.measure(:analyze_video) do
|
155
|
+
provider.analyze_video!(video: video, prompt: prompt, model: model, **opts)
|
285
156
|
end
|
286
157
|
end
|
287
158
|
|
288
|
-
|
289
|
-
def generate_video(prompt, model: "sora", duration: 5, **opts)
|
159
|
+
def generate_video(prompt, model: "runway-gen-3", **opts)
|
290
160
|
performance_monitor.measure(:generate_video) do
|
291
|
-
|
292
|
-
|
293
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
294
|
-
request_deduplicator.deduplicate(cache_key) do
|
295
|
-
provider.generate_video!(prompt: prompt, model: model, duration: duration, **opts)
|
296
|
-
end
|
297
|
-
end
|
161
|
+
provider.generate_video!(prompt: prompt, model: model, **opts)
|
298
162
|
end
|
299
163
|
end
|
300
164
|
|
301
|
-
def
|
302
|
-
performance_monitor.measure(:
|
303
|
-
|
304
|
-
|
305
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
306
|
-
request_deduplicator.deduplicate(cache_key) do
|
307
|
-
provider.edit_video!(video: video, prompt: prompt, **opts)
|
308
|
-
end
|
309
|
-
end
|
165
|
+
def analyze_audio(audio, prompt, model: "whisper-1", **opts)
|
166
|
+
performance_monitor.measure(:analyze_audio) do
|
167
|
+
provider.analyze_audio!(audio: audio, prompt: prompt, model: model, **opts)
|
310
168
|
end
|
311
169
|
end
|
312
170
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
cache_key = [:speech, model, text.hash, voice]
|
317
|
-
|
318
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
319
|
-
request_deduplicator.deduplicate(cache_key) do
|
320
|
-
provider.generate_speech!(text: text, model: model, voice: voice, **opts)
|
321
|
-
end
|
322
|
-
end
|
171
|
+
def generate_audio(prompt, model: "tts-1", **opts)
|
172
|
+
performance_monitor.measure(:generate_audio) do
|
173
|
+
provider.generate_audio!(prompt: prompt, model: model, **opts)
|
323
174
|
end
|
324
175
|
end
|
325
176
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
provider.transcribe_audio!(audio: audio, model: model, **opts)
|
333
|
-
end
|
334
|
-
end
|
177
|
+
# Context awareness
|
178
|
+
def chat_with_context(prompt, context_objects = [], model: config.default_model, **opts)
|
179
|
+
performance_monitor.measure(:chat_with_context) do
|
180
|
+
context_analyzer = ContextAnalyzer.new
|
181
|
+
enhanced_prompt = context_analyzer.enhance_prompt(prompt, context_objects)
|
182
|
+
chat(enhanced_prompt, model: model, **opts)
|
335
183
|
end
|
336
184
|
end
|
337
185
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
344
|
-
request_deduplicator.deduplicate(cache_key) do
|
345
|
-
provider.analyze_image!(image: image, prompt: prompt, model: model, **opts)
|
346
|
-
end
|
347
|
-
end
|
186
|
+
def analyze_window_context(url, referrer, user_agent, **opts)
|
187
|
+
performance_monitor.measure(:analyze_window_context) do
|
188
|
+
window_context = WindowContext.new(url: url, referrer: referrer, user_agent: user_agent)
|
189
|
+
window_context.analyze(**opts)
|
348
190
|
end
|
349
191
|
end
|
350
192
|
|
351
|
-
def
|
352
|
-
performance_monitor.measure(:
|
353
|
-
|
354
|
-
|
355
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
356
|
-
request_deduplicator.deduplicate(cache_key) do
|
357
|
-
provider.analyze_video!(video: video, prompt: prompt, model: model, **opts)
|
358
|
-
end
|
359
|
-
end
|
193
|
+
def analyze_image_context(image, **opts)
|
194
|
+
performance_monitor.measure(:analyze_image_context) do
|
195
|
+
image_context = ImageContext.new(image)
|
196
|
+
image_context.analyze(**opts)
|
360
197
|
end
|
361
198
|
end
|
362
199
|
|
363
|
-
#
|
364
|
-
def
|
365
|
-
|
366
|
-
requests.map do |request|
|
367
|
-
batch_processor.add_operation(-> { chat(request[:prompt], **request.except(:prompt)) })
|
368
|
-
end
|
369
|
-
end
|
200
|
+
# Agent system
|
201
|
+
def create_agent(name, type: :general, **opts)
|
202
|
+
agent_manager.create_agent(name, type: type, **opts)
|
370
203
|
end
|
371
204
|
|
372
|
-
def
|
373
|
-
|
374
|
-
texts_array.map do |texts|
|
375
|
-
batch_processor.add_operation(-> { embed(texts) })
|
376
|
-
end
|
377
|
-
end
|
205
|
+
def create_research_agent(name: "Research Agent", **opts)
|
206
|
+
agent_manager.create_agent(name, type: :research, **opts)
|
378
207
|
end
|
379
208
|
|
380
|
-
|
381
|
-
|
382
|
-
performance_monitor.measure(:analyze_image_with_context) do
|
383
|
-
cache_key = [:context_image_analysis, prompt.hash, image.hash, user_context.hash, window_context.hash, image_context.hash]
|
384
|
-
|
385
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
386
|
-
analyzer = ContextAnalyzer.new(
|
387
|
-
user_context: user_context,
|
388
|
-
window_context: window_context,
|
389
|
-
image_context: image_context
|
390
|
-
)
|
391
|
-
analyzer.analyze_with_context(image, prompt, **opts)
|
392
|
-
end
|
393
|
-
end
|
209
|
+
def create_creative_agent(name: "Creative Agent", **opts)
|
210
|
+
agent_manager.create_agent(name, type: :creative, **opts)
|
394
211
|
end
|
395
212
|
|
396
|
-
def
|
397
|
-
|
398
|
-
cache_key = [:context_generate, prompt.hash, user_context.hash, window_context.hash]
|
399
|
-
|
400
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
401
|
-
analyzer = ContextAnalyzer.new(
|
402
|
-
user_context: user_context,
|
403
|
-
window_context: window_context
|
404
|
-
)
|
405
|
-
analyzer.generate_with_context(prompt, **opts)
|
406
|
-
end
|
407
|
-
end
|
213
|
+
def create_technical_agent(name: "Technical Agent", **opts)
|
214
|
+
agent_manager.create_agent(name, type: :technical, **opts)
|
408
215
|
end
|
409
216
|
|
410
|
-
def
|
411
|
-
|
412
|
-
cache_key = [:context_image_generate, prompt.hash, user_context.hash, window_context.hash]
|
413
|
-
|
414
|
-
smart_cache.fetch(cache_key, expires_in: config.cache_ttl) do
|
415
|
-
analyzer = ContextAnalyzer.new(
|
416
|
-
user_context: user_context,
|
417
|
-
window_context: window_context
|
418
|
-
)
|
419
|
-
analyzer.generate_image_with_context(prompt, **opts)
|
420
|
-
end
|
421
|
-
end
|
217
|
+
def create_agent_team(name, agents, strategy: :round_robin, **opts)
|
218
|
+
agent_manager.create_agent_team(name, agents, collaboration_strategy: strategy, **opts)
|
422
219
|
end
|
423
220
|
|
424
|
-
|
425
|
-
|
426
|
-
|
221
|
+
def submit_task(task, agent_team = nil)
|
222
|
+
if agent_team
|
223
|
+
agent_team.assign_task(task)
|
224
|
+
else
|
225
|
+
agent_manager.submit_task(task)
|
226
|
+
end
|
427
227
|
end
|
428
228
|
|
429
|
-
|
430
|
-
|
229
|
+
# Provider management
|
230
|
+
def provider
|
231
|
+
case config.provider.to_sym
|
232
|
+
when :openai then Providers::SecureOpenAIAdapter.new
|
233
|
+
when :anthropic then Providers::SecureAnthropicAdapter.new
|
234
|
+
when :gemini then Providers::GeminiAdapter.new
|
235
|
+
when :dummy then Providers::DummyAdapter.new
|
236
|
+
else Providers::DummyAdapter.new
|
237
|
+
end
|
431
238
|
end
|
432
239
|
|
433
|
-
def
|
434
|
-
|
240
|
+
def provider=(new_provider)
|
241
|
+
config.provider = new_provider
|
435
242
|
end
|
436
243
|
|
437
|
-
|
438
|
-
|
244
|
+
# Utility methods
|
245
|
+
def normalize_messages(prompt_or_messages)
|
246
|
+
if prompt_or_messages.is_a?(String)
|
247
|
+
[{ role: "user", content: prompt_or_messages }]
|
248
|
+
else
|
249
|
+
prompt_or_messages
|
250
|
+
end
|
439
251
|
end
|
440
252
|
|
441
|
-
def
|
442
|
-
|
253
|
+
def redact_sensitive_data(text)
|
254
|
+
Redactor.call(text)
|
443
255
|
end
|
444
256
|
|
445
|
-
def
|
446
|
-
|
257
|
+
def log_event(kind:, name:, payload: {}, latency_ms: nil)
|
258
|
+
Events.log!(kind: kind, name: name, payload: payload, latency_ms: latency_ms)
|
447
259
|
end
|
448
260
|
|
449
|
-
#
|
450
|
-
def
|
451
|
-
|
452
|
-
provider
|
453
|
-
connection_pool
|
454
|
-
smart_cache
|
455
|
-
request_deduplicator
|
456
|
-
batch_processor
|
457
|
-
agent_manager
|
261
|
+
# Security methods
|
262
|
+
def validate_input(input, type: :text)
|
263
|
+
Security::InputValidator.validate(input, type: type)
|
458
264
|
end
|
459
265
|
|
460
|
-
def
|
461
|
-
|
266
|
+
def sanitize_content(content)
|
267
|
+
Security::ContentSanitizer.sanitize(content)
|
462
268
|
end
|
463
269
|
|
464
|
-
def
|
465
|
-
|
270
|
+
def check_rate_limit(identifier, limit: 100, window: 1.hour)
|
271
|
+
Security::RateLimiter.check(identifier, limit: limit, window: window)
|
466
272
|
end
|
467
273
|
|
468
|
-
|
469
|
-
|
470
|
-
def normalize_messages(prompt_or_messages)
|
471
|
-
messages = prompt_or_messages.is_a?(Array) ? prompt_or_messages : [{role: "user", content: prompt_or_messages}]
|
472
|
-
text = RailsAi::Redactor.call(messages.last[:content])
|
473
|
-
messages[-1] = messages.last.merge(content: text)
|
474
|
-
messages
|
274
|
+
def scan_for_vulnerabilities
|
275
|
+
Security::VulnerabilityScanner.scan
|
475
276
|
end
|
476
|
-
end
|
477
277
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
end
|
482
|
-
|
483
|
-
def self.sanitize_content(content)
|
484
|
-
Security::ContentSanitizer.sanitize_content(content)
|
485
|
-
end
|
278
|
+
def handle_security_error(error, context = {})
|
279
|
+
Security::ErrorHandler.handle_security_error(error, context)
|
280
|
+
end
|
486
281
|
|
487
|
-
|
488
|
-
|
489
|
-
|
282
|
+
# Response cleaning utility
|
283
|
+
def clean_response(raw_response)
|
284
|
+
return nil if raw_response.nil?
|
490
285
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
286
|
+
# Convert to string
|
287
|
+
response = raw_response.to_s
|
288
|
+
|
289
|
+
# Ensure UTF-8 encoding
|
290
|
+
response = response.encode('UTF-8', 'UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
291
|
+
|
292
|
+
# Remove any control characters that might cause issues
|
293
|
+
response = response.gsub(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/, '')
|
294
|
+
|
295
|
+
response
|
296
|
+
end
|
498
297
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
298
|
+
# Enhanced chat method with automatic response cleaning
|
299
|
+
def chat_clean(prompt_or_messages, model: config.default_model, **opts)
|
300
|
+
raw_response = chat(prompt_or_messages, model: model, **opts)
|
301
|
+
clean_response(raw_response)
|
302
|
+
end
|
503
303
|
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
# Check if the prompt needs web search
|
509
|
-
web_keywords = ['current', 'latest', 'today', 'now', 'recent', 'weather', 'news', 'stock', 'price']
|
510
|
-
needs_web_search = web_keywords.any? { |keyword| prompt.downcase.include?(keyword) }
|
511
|
-
|
512
|
-
if needs_web_search
|
513
|
-
begin
|
514
|
-
# Perform web search
|
515
|
-
search_results = WebSearch.search(prompt, num_results: 3)
|
516
|
-
|
517
|
-
# Enhance the prompt with web results
|
518
|
-
web_context = "\n\nRecent web search results:\n"
|
519
|
-
search_results.each_with_index do |result, index|
|
520
|
-
web_context += "#{index + 1}. #{result[:title]}\n #{result[:snippet]}\n Source: #{result[:link]}\n\n"
|
521
|
-
end
|
522
|
-
|
523
|
-
enhanced_prompt = "#{prompt}\n\nPlease use the following web search results to provide current, up-to-date information:#{web_context}"
|
524
|
-
|
525
|
-
# Get AI response with web context
|
526
|
-
chat(enhanced_prompt, model: model, **opts)
|
527
|
-
rescue WebSearch::SearchError => e
|
528
|
-
# Fallback to regular chat if web search fails
|
529
|
-
chat(prompt, model: model, **opts)
|
530
|
-
end
|
531
|
-
else
|
532
|
-
# Regular chat for non-time-sensitive queries
|
533
|
-
chat(prompt, model: model, **opts)
|
304
|
+
# Enhanced web search chat with automatic response cleaning
|
305
|
+
def chat_with_web_search_clean(prompt, model: config.default_model, **opts)
|
306
|
+
raw_response = chat_with_web_search(prompt, model: model, **opts)
|
307
|
+
clean_response(raw_response)
|
534
308
|
end
|
535
309
|
end
|
536
310
|
end
|
537
311
|
|
538
|
-
|
539
|
-
def self.clean_response(raw_response)
|
540
|
-
return nil if raw_response.nil?
|
541
|
-
|
542
|
-
# Convert to string
|
543
|
-
response = raw_response.to_s
|
544
|
-
|
545
|
-
# Ensure UTF-8 encoding
|
546
|
-
response = response.encode('UTF-8', 'UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
547
|
-
|
548
|
-
# Remove any control characters that might cause issues
|
549
|
-
response = response.gsub(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/, '')
|
550
|
-
|
551
|
-
response
|
552
|
-
end
|
553
|
-
|
554
|
-
# Enhanced chat method with automatic response cleaning
|
555
|
-
def self.chat_clean(prompt_or_messages, model: config.default_model, **opts)
|
556
|
-
raw_response = chat(prompt_or_messages, model: model, **opts)
|
557
|
-
clean_response(raw_response)
|
558
|
-
end
|
312
|
+
require_relative "rails_ai/web_search"
|
559
313
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
314
|
+
# Web-enhanced chat with real-time information
|
315
|
+
def RailsAi.chat_with_web_search(prompt, model: RailsAi.config.default_model, **opts)
|
316
|
+
# Check if the prompt needs web search
|
317
|
+
web_keywords = ['current', 'latest', 'today', 'now', 'recent', 'weather', 'news', 'stock', 'price']
|
318
|
+
needs_web_search = web_keywords.any? { |keyword| prompt.downcase.include?(keyword) }
|
319
|
+
|
320
|
+
if needs_web_search
|
321
|
+
begin
|
322
|
+
# Perform web search
|
323
|
+
search_results = WebSearch.search(prompt, num_results: 3)
|
324
|
+
|
325
|
+
# Enhance the prompt with web results
|
326
|
+
web_context = "\n\nRecent web search results:\n"
|
327
|
+
search_results.each_with_index do |result, index|
|
328
|
+
web_context += "#{index + 1}. #{result[:title]}\n #{result[:snippet]}\n Source: #{result[:link]}\n\n"
|
329
|
+
end
|
330
|
+
|
331
|
+
enhanced_prompt = "#{prompt}\n\nPlease use the following web search results to provide current, up-to-date information:#{web_context}"
|
332
|
+
|
333
|
+
# Get AI response with web context
|
334
|
+
RailsAi.chat(enhanced_prompt, model: model, **opts)
|
335
|
+
rescue WebSearch::SearchError => e
|
336
|
+
# Fallback to regular chat if web search fails
|
337
|
+
RailsAi.chat(prompt, model: model, **opts)
|
338
|
+
end
|
339
|
+
else
|
340
|
+
# Regular chat for non-time-sensitive queries
|
341
|
+
RailsAi.chat(prompt, model: model, **opts)
|
564
342
|
end
|
565
343
|
end
|
data/setup_wiki.sh
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Setup GitHub Wiki for Rails AI Gem
|
4
|
+
echo "Setting up GitHub Wiki for Rails AI Gem..."
|
5
|
+
|
6
|
+
# Check if we're in the right directory
|
7
|
+
if [ ! -d "wiki" ]; then
|
8
|
+
echo "Error: wiki directory not found. Please run this script from the rails_ai root directory."
|
9
|
+
exit 1
|
10
|
+
fi
|
11
|
+
|
12
|
+
# Clone the wiki repository
|
13
|
+
echo "Cloning wiki repository..."
|
14
|
+
git clone https://github.com/DanielAmah/rails_ai.wiki.git wiki_repo
|
15
|
+
|
16
|
+
if [ $? -ne 0 ]; then
|
17
|
+
echo "Error: Could not clone wiki repository. Make sure the wiki is enabled on GitHub."
|
18
|
+
echo "To enable wiki:"
|
19
|
+
echo "1. Go to https://github.com/DanielAmah/rails_ai"
|
20
|
+
echo "2. Click on 'Settings' tab"
|
21
|
+
echo "3. Scroll down to 'Features' section"
|
22
|
+
echo "4. Check 'Wikis' to enable it"
|
23
|
+
echo "5. Run this script again"
|
24
|
+
exit 1
|
25
|
+
fi
|
26
|
+
|
27
|
+
# Copy wiki files
|
28
|
+
echo "Copying wiki files..."
|
29
|
+
cp wiki/*.md wiki_repo/
|
30
|
+
|
31
|
+
# Navigate to wiki repo
|
32
|
+
cd wiki_repo
|
33
|
+
|
34
|
+
# Add and commit files
|
35
|
+
echo "Adding wiki files to git..."
|
36
|
+
git add .
|
37
|
+
git commit -m "Add comprehensive wiki documentation for Rails AI Gem"
|
38
|
+
|
39
|
+
# Push to GitHub
|
40
|
+
echo "Pushing wiki to GitHub..."
|
41
|
+
git push origin master
|
42
|
+
|
43
|
+
if [ $? -eq 0 ]; then
|
44
|
+
echo "✅ Wiki successfully set up!"
|
45
|
+
echo "You can now view it at: https://github.com/DanielAmah/rails_ai/wiki"
|
46
|
+
else
|
47
|
+
echo "❌ Error pushing wiki to GitHub"
|
48
|
+
exit 1
|
49
|
+
fi
|
50
|
+
|
51
|
+
# Clean up
|
52
|
+
cd ..
|
53
|
+
rm -rf wiki_repo
|
54
|
+
|
55
|
+
echo "Wiki setup complete!"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_ai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Amah
|
@@ -349,6 +349,7 @@ files:
|
|
349
349
|
- rails_ai.gemspec
|
350
350
|
- scripts/security_scanner.rb
|
351
351
|
- setup_monitoring.sh
|
352
|
+
- setup_wiki.sh
|
352
353
|
- wiki/API-Documentation.md
|
353
354
|
- wiki/Architecture-Overview.md
|
354
355
|
- wiki/Contributing-Guide.md
|