prescient 0.8.0 → 0.8.2
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/.rubocop.yml +3 -3
- data/CHANGELOG.md +17 -0
- data/CONTRIBUTING.md +192 -0
- data/INTEGRATION_GUIDE.md +1 -1
- data/README.md +1 -1
- data/lib/prescient/agent/parser.rb +88 -6
- data/lib/prescient/agent.rb +1 -1
- data/lib/prescient/client.rb +6 -6
- data/lib/prescient/document_source.rb +6 -6
- data/lib/prescient/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3dc5e5bb3c441f18ba241696a3b37e2bd127b1cdbf312f5ec80adb6717f84b69
|
|
4
|
+
data.tar.gz: 361bdbe883a03971f796491ff19a30c514e6a105702f3f19cc251ab6eb1feaeb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b46cf882af6fb5810c320ef5ec5276e7f89c7df6050fa9dd3f953ce6264264c160a9347a91cf79dfc443d882fc1c1304dd26e6a63ae6bd4ae91a18fe8274635
|
|
7
|
+
data.tar.gz: 7efc84dbb4acbc637914c4839f0ae269d132d3e91aec48253d09f7ae6efd9b44fa7692a4feed86ec36fdbd303e461533f31fbefe66243c683daa4f5f2857ab45
|
data/.rubocop.yml
CHANGED
|
@@ -9,8 +9,8 @@ plugins:
|
|
|
9
9
|
- rubocop-rake
|
|
10
10
|
|
|
11
11
|
AllCops:
|
|
12
|
-
# Target Ruby 3.
|
|
13
|
-
TargetRubyVersion: 3.
|
|
12
|
+
# Target Ruby 3.2+ (matches gemspec requirement)
|
|
13
|
+
TargetRubyVersion: 3.2
|
|
14
14
|
# Use new cops by default
|
|
15
15
|
NewCops: enable
|
|
16
16
|
# Exclude common directories
|
|
@@ -78,4 +78,4 @@ Metrics/CyclomaticComplexity:
|
|
|
78
78
|
Max: 10
|
|
79
79
|
|
|
80
80
|
Style/DirectiveScope:
|
|
81
|
-
Enabled: false
|
|
81
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## [0.8.2] - 2026-11-09
|
|
6
|
+
|
|
7
|
+
### Breaking changes
|
|
8
|
+
|
|
9
|
+
- Dropped support for Ruby 3.1. Ruby 3.2 or newer is now required.
|
|
10
|
+
|
|
11
|
+
## [0.8.1] - 2025-09-10
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Fixed the Agent audit-log load path to avoid a circular-require warning while
|
|
16
|
+
preserving lazy loading of the optional Agent implementation.
|
|
17
|
+
- Replaced the Agent parser's polynomial-time fenced-JSON regular expression
|
|
18
|
+
with a linear scanner to prevent ReDoS behavior on untrusted provider output.
|
|
19
|
+
- Added Agent parser regression coverage for nested objects, escaped string
|
|
20
|
+
values, malformed fences, and repeated unterminated action prefixes.
|
|
21
|
+
|
|
5
22
|
## [0.8.0] - 2025-08-31
|
|
6
23
|
|
|
7
24
|
### Added
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Contributing to Prescient
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Prescient! Prescient is a Ruby gem that provides a unified, predictable gateway to multiple AI providers, including Ollama, OpenAI, Anthropic, Google Gemini, Mistral, Hugging Face, DeepSeek, and xAI.
|
|
4
|
+
|
|
5
|
+
Prescient is designed as a reusable library rather than an application. The library values explicit provider boundaries, predictable error handling, modern idiomatic Ruby, and stable public APIs.
|
|
6
|
+
|
|
7
|
+
This guide explains how to set up your local development environment, run tests, follow coding standards, and submit pull requests.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Code of conduct
|
|
12
|
+
|
|
13
|
+
By participating in this project, you agree to follow the project's [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Development setup
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
Ensure you have the following installed on your local system:
|
|
22
|
+
|
|
23
|
+
- **Ruby**: Version 3.2 or higher (the CI matrix tests Ruby 3.2, 3.3, 3.4, and 4.0).
|
|
24
|
+
- **Bundler**: Version 2.0 or higher.
|
|
25
|
+
- **Docker & Docker Compose** *(optional, for local service testing)*: Required if you test against local instances of Ollama, SearXNG, or PostgreSQL with pgvector.
|
|
26
|
+
|
|
27
|
+
### Setting up the workspace
|
|
28
|
+
|
|
29
|
+
1. Fork and clone the repository:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/kanutocd/prescient.git
|
|
33
|
+
cd prescient
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Install development dependencies:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bundle install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
3. *(Optional)* Start local services using Docker Compose:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
docker compose up -d ollama postgres searxng
|
|
46
|
+
docker compose run --rm ollama-init
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Running tests and checks
|
|
52
|
+
|
|
53
|
+
Prescient uses Minitest for unit and integration testing, RuboCop for code linting, and RBS/Steep for type checking. Establish a green test baseline before making changes.
|
|
54
|
+
|
|
55
|
+
### Running unit and integration tests
|
|
56
|
+
|
|
57
|
+
Run the complete test suite:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
bundle exec rake test
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To run a single test file during development, execute:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bundle exec ruby -Itest test/prescient/client_test.rb
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
To run a specific test by name, pass the line or name filter:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
bundle exec ruby -Itest test/prescient/client_test.rb -n /generate_response/
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Running code linter
|
|
76
|
+
|
|
77
|
+
Prescient enforces RuboCop styling rules:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
bundle exec rubocop
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Fix safe auto-correctable offenses with:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
bundle exec rubocop -A
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Type validation with RBS and Steep
|
|
90
|
+
|
|
91
|
+
Validate core API type signatures with:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
bundle exec rake rbs:validate
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
To inspect generated RBS prototypes or differences:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
bundle exec rake rbs:prototype
|
|
101
|
+
bundle exec rake rbs:diff
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Opt-in live provider smoke tests
|
|
105
|
+
|
|
106
|
+
The default test suite uses WebMock and VCR to mock external HTTP requests. Tests never execute against live cloud providers by default.
|
|
107
|
+
|
|
108
|
+
To test against live provider APIs, set `PRESCIENT_LIVE_SMOKE=1` and specify the target providers in `PRESCIENT_LIVE_PROVIDERS`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
PRESCIENT_LIVE_SMOKE=1 \
|
|
112
|
+
PRESCIENT_LIVE_PROVIDERS=openai \
|
|
113
|
+
OPENAI_API_KEY=your_actual_key \
|
|
114
|
+
bundle exec ruby -Itest test/prescient/live_provider_smoke_test.rb
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Supported live provider keys are `ollama`, `openai`, `anthropic`, `gemini`, `mistral`, `huggingface`, `deepseek`, and `xai`.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Architecture guidelines
|
|
122
|
+
|
|
123
|
+
### Provider abstraction
|
|
124
|
+
|
|
125
|
+
Provider-specific behavior belongs in provider adapters (`lib/prescient/provider/`). Common behavior belongs in base abstractions (`lib/prescient/base.rb`).
|
|
126
|
+
|
|
127
|
+
When creating or updating a provider adapter:
|
|
128
|
+
|
|
129
|
+
1. **Inherit from `Prescient::Base`**: Subclass `Prescient::Base` and define required methods: `#generate_response`, `#generate_embedding` (if supported), and `#health_check`.
|
|
130
|
+
2. **Isolate HTTP details**: Use HTTParty or standard-library HTTP tools inside the adapter. Keep raw network details out of caller code.
|
|
131
|
+
3. **Normalize Responses**: Return standard response shapes from `#generate_response`:
|
|
132
|
+
```ruby
|
|
133
|
+
{
|
|
134
|
+
response: "Generated text response",
|
|
135
|
+
model: "configured-model-name",
|
|
136
|
+
provider: "provider_name",
|
|
137
|
+
processing_time: nil,
|
|
138
|
+
metadata: { ... }
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
4. **Enforce embedding dimensions**: Validate vectors with `validate_embedding_dimensions`. Never pad or truncate vectors silently.
|
|
142
|
+
5. **Map Provider Errors**: Wrap raw HTTP or API errors into standard Prescient exception classes.
|
|
143
|
+
|
|
144
|
+
### Error mapping hierarchy
|
|
145
|
+
|
|
146
|
+
All gem exceptions inherit from `Prescient::Error`. Map provider-specific failures into the appropriate exception category:
|
|
147
|
+
|
|
148
|
+
| Exception Class | Primary Cause | Retryable by Fallback? |
|
|
149
|
+
| :--- | :--- | :--- |
|
|
150
|
+
| `Prescient::ConnectionError` | Network failures, HTTP timeouts, DNS resolution failures | Yes |
|
|
151
|
+
| `Prescient::RateLimitError` | Provider HTTP 429 status | Yes |
|
|
152
|
+
| `Prescient::ModelNotAvailableError` | Provider HTTP 404 status or unavailable model | Yes |
|
|
153
|
+
| `Prescient::ProviderError` | Provider HTTP 5xx server errors | Yes |
|
|
154
|
+
| `Prescient::AuthenticationError` | Provider HTTP 401/403 invalid API keys | No |
|
|
155
|
+
| `Prescient::InvalidResponseError` | Malformed JSON responses or vector dimension mismatches | No |
|
|
156
|
+
| `Prescient::ToolError` | Base class for external search tool adapter failures | Varies |
|
|
157
|
+
|
|
158
|
+
### Retry vs fallback semantics
|
|
159
|
+
|
|
160
|
+
- **Retries**: Retries apply to transient network errors (`ConnectionError`, `RateLimitError`) within a single provider, governed by `config.retry_attempts` and `config.retry_delay`.
|
|
161
|
+
- **Fallback**: Provider fallback triggers when a provider encounters a persistent or service-side failure (`ConnectionError`, `RateLimitError`, `ModelNotAvailableError`, `ProviderError`). Fallback cascades in configured provider order. Caller misuse (invalid parameters, authentication failures) is never retried with fallback.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Public API compatibility
|
|
166
|
+
|
|
167
|
+
Treat the following items as public API contracts:
|
|
168
|
+
|
|
169
|
+
- Methods on `Prescient`: `.configure`, `.client`, `.generate_embedding`, `.generate_response`, `.search_and_generate`, `.health_check`, `.load_configuration`.
|
|
170
|
+
- Configuration options: `Configuration` class properties (`default_provider`, `timeout`, `retry_attempts`, `retry_delay`, `fallback_providers`, `sensitive_keys`).
|
|
171
|
+
- Standard return shapes for generation, embeddings, health checks, and tool search results.
|
|
172
|
+
|
|
173
|
+
If your changes modify a public API contract:
|
|
174
|
+
|
|
175
|
+
1. Update the corresponding unit and integration tests in `test/`.
|
|
176
|
+
2. Update example scripts in `examples/`.
|
|
177
|
+
3. Update documentation files (`README.md`, `INTEGRATION_GUIDE.md`, `VECTOR_SEARCH_GUIDE.md`).
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Submitting pull requests
|
|
182
|
+
|
|
183
|
+
Before opening a pull request:
|
|
184
|
+
|
|
185
|
+
1. Ensure all tests pass: `bundle exec rake test`.
|
|
186
|
+
2. Ensure RuboCop checks pass: `bundle exec rubocop`.
|
|
187
|
+
3. Inspect your diff to ensure no sensitive credentials, VCR tokens, or temporary files are included:
|
|
188
|
+
```bash
|
|
189
|
+
git diff
|
|
190
|
+
```
|
|
191
|
+
4. Write clear, imperative commit messages (for example, `Add Google Gemini model listing support`).
|
|
192
|
+
5. Open a pull request against the `main` branch with a clear description of your changes and motivation.
|
data/INTEGRATION_GUIDE.md
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Prescient
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/prescient)
|
|
4
|
-
[](https://www.ruby-lang.org/)
|
|
5
5
|
[](https://github.com/kanutocd/prescient/pkgs/container/prescient)
|
|
6
6
|
[](https://github.com/kanutocd/prescient/actions/workflows/ci.yml)
|
|
7
7
|
[](https://github.com/kanutocd/prescient/actions/workflows/security.yml)
|
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
module Prescient::Agent
|
|
5
5
|
# Extracts and validates one tool action from provider text.
|
|
6
6
|
class Parser
|
|
7
|
-
# @return [
|
|
8
|
-
|
|
7
|
+
# @return [String] Opening fenced JSON marker
|
|
8
|
+
JSON_FENCE = "```json".b.freeze
|
|
9
|
+
# @return [String] Closing fenced JSON marker
|
|
10
|
+
CLOSING_FENCE = "```".b.freeze
|
|
11
|
+
# @return [Array<Integer>] JSON whitespace byte values
|
|
12
|
+
WHITESPACE_BYTES = [9, 10, 11, 12, 13, 32].freeze
|
|
9
13
|
|
|
10
14
|
# Parse one optional action from provider output.
|
|
11
15
|
# @param text [String] Provider response text
|
|
@@ -23,11 +27,11 @@ module Prescient::Agent
|
|
|
23
27
|
# @param text [String] Provider response text
|
|
24
28
|
# @return [Hash, nil] Parsed action or nil for a final response
|
|
25
29
|
def parse(text)
|
|
26
|
-
|
|
27
|
-
return nil unless
|
|
28
|
-
raise MalformedActionError, "agent action exceeds configured size limit" if
|
|
30
|
+
action_json = extract_action_json(text.to_s)
|
|
31
|
+
return nil unless action_json
|
|
32
|
+
raise MalformedActionError, "agent action exceeds configured size limit" if action_json.bytesize > @max_bytes
|
|
29
33
|
|
|
30
|
-
payload = JSON.parse(
|
|
34
|
+
payload = JSON.parse(action_json)
|
|
31
35
|
validate_payload(payload)
|
|
32
36
|
{ name: payload.fetch("action").to_sym, arguments: payload.fetch("args") }
|
|
33
37
|
rescue JSON::ParserError => e
|
|
@@ -36,6 +40,84 @@ module Prescient::Agent
|
|
|
36
40
|
|
|
37
41
|
private
|
|
38
42
|
|
|
43
|
+
def extract_action_json(text)
|
|
44
|
+
source = text.b
|
|
45
|
+
cursor = 0
|
|
46
|
+
|
|
47
|
+
while (fence_start = source.index(JSON_FENCE, cursor))
|
|
48
|
+
content_start = skip_whitespace(source, fence_start + JSON_FENCE.bytesize)
|
|
49
|
+
unless source.getbyte(content_start) == 123
|
|
50
|
+
cursor = content_start
|
|
51
|
+
next
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
action_json, next_cursor = scan_json_object(source, content_start)
|
|
55
|
+
return action_json if action_json
|
|
56
|
+
|
|
57
|
+
cursor = next_cursor
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def scan_json_object(source, start)
|
|
64
|
+
depth = 0
|
|
65
|
+
escaped = false
|
|
66
|
+
in_string = false
|
|
67
|
+
index = start
|
|
68
|
+
|
|
69
|
+
while index < source.bytesize
|
|
70
|
+
byte = source.getbyte(index)
|
|
71
|
+
if in_string
|
|
72
|
+
in_string, escaped = string_state(byte, escaped)
|
|
73
|
+
elsif fence_at?(source, index)
|
|
74
|
+
return [nil, index]
|
|
75
|
+
else
|
|
76
|
+
in_string = byte == 34
|
|
77
|
+
depth = depth_after(byte, depth)
|
|
78
|
+
return completed_action(source, start, index) if byte == 125 && depth.zero?
|
|
79
|
+
end
|
|
80
|
+
index += 1
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
[nil, source.bytesize]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def string_state(byte, escaped)
|
|
87
|
+
return [true, false] if escaped
|
|
88
|
+
return [true, true] if byte == 92
|
|
89
|
+
return [false, false] if byte == 34
|
|
90
|
+
|
|
91
|
+
[true, false]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def fence_at?(source, index)
|
|
95
|
+
byte = source.getbyte(index)
|
|
96
|
+
byte == 96 && source.byteslice(index, JSON_FENCE.bytesize) == JSON_FENCE
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def depth_after(byte, depth)
|
|
100
|
+
case byte
|
|
101
|
+
when 123 then depth + 1
|
|
102
|
+
when 125 then depth - 1
|
|
103
|
+
else depth
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def completed_action(source, start, index)
|
|
108
|
+
closing_start = skip_whitespace(source, index + 1)
|
|
109
|
+
return [nil, closing_start] unless source.byteslice(closing_start, CLOSING_FENCE.bytesize) == CLOSING_FENCE
|
|
110
|
+
|
|
111
|
+
length = index + 1 - start
|
|
112
|
+
[source.byteslice(start, length).force_encoding(Encoding::UTF_8), index + 1]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def skip_whitespace(source, start)
|
|
116
|
+
index = start
|
|
117
|
+
index += 1 while index < source.bytesize && WHITESPACE_BYTES.include?(source.getbyte(index))
|
|
118
|
+
index
|
|
119
|
+
end
|
|
120
|
+
|
|
39
121
|
def validate_payload(payload)
|
|
40
122
|
unless payload.is_a?(Hash) && payload.keys.sort == %w[action args]
|
|
41
123
|
raise MalformedActionError, "agent action must contain only action and args"
|
data/lib/prescient/agent.rb
CHANGED
|
@@ -5,11 +5,11 @@ require "json"
|
|
|
5
5
|
module Prescient
|
|
6
6
|
# Optional bounded agent orchestration over Prescient Core.
|
|
7
7
|
module Agent
|
|
8
|
+
autoload :AuditLog, "prescient/agent/audit_log"
|
|
8
9
|
end
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
require_relative "agent/configuration"
|
|
12
|
-
require_relative "agent/audit_log"
|
|
13
13
|
require_relative "agent/errors"
|
|
14
14
|
require_relative "agent/error_serializer"
|
|
15
15
|
require_relative "agent/schema_validator"
|
data/lib/prescient/client.rb
CHANGED
|
@@ -232,8 +232,8 @@ module Prescient
|
|
|
232
232
|
# @param provider [Symbol, nil] Provider to use
|
|
233
233
|
# @param enable_fallback [Boolean] Whether provider fallback is enabled
|
|
234
234
|
# @return [Array<Float>] Embedding vector
|
|
235
|
-
def self.generate_embedding(text, provider: nil, enable_fallback: true, **
|
|
236
|
-
client(provider, enable_fallback: enable_fallback).generate_embedding(text, **
|
|
235
|
+
def self.generate_embedding(text, provider: nil, enable_fallback: true, **)
|
|
236
|
+
client(provider, enable_fallback: enable_fallback).generate_embedding(text, **)
|
|
237
237
|
end
|
|
238
238
|
|
|
239
239
|
# Generate a response through a configured provider.
|
|
@@ -244,8 +244,8 @@ module Prescient
|
|
|
244
244
|
# @param enable_fallback [Boolean] Whether provider fallback is enabled
|
|
245
245
|
# @return [Hash] Normalized provider response with :response, :model, :provider
|
|
246
246
|
# and optional metadata
|
|
247
|
-
def self.generate_response(prompt, context_items = [], provider: nil, enable_fallback: true, **
|
|
248
|
-
client(provider, enable_fallback: enable_fallback).generate_response(prompt, context_items, **
|
|
247
|
+
def self.generate_response(prompt, context_items = [], provider: nil, enable_fallback: true, **)
|
|
248
|
+
client(provider, enable_fallback: enable_fallback).generate_response(prompt, context_items, **)
|
|
249
249
|
end
|
|
250
250
|
|
|
251
251
|
# Search with an explicit external tool and optionally use the normalized
|
|
@@ -259,7 +259,7 @@ module Prescient
|
|
|
259
259
|
# @param provider_options [Hash] Temporary provider configuration overrides
|
|
260
260
|
# @return [Hash] Normalized provider response
|
|
261
261
|
def self.search_and_generate(query, tool: :web_search, provider: nil, limit: nil,
|
|
262
|
-
enable_fallback: true, provider_options: {}, **
|
|
262
|
+
enable_fallback: true, provider_options: {}, **)
|
|
263
263
|
search_tool = self.tool(tool)
|
|
264
264
|
raise Prescient::ToolConfigurationError, "tool not configured: #{tool}" unless search_tool
|
|
265
265
|
|
|
@@ -270,7 +270,7 @@ module Prescient
|
|
|
270
270
|
client(provider, enable_fallback:, provider_options:).generate_response(
|
|
271
271
|
query,
|
|
272
272
|
context_items,
|
|
273
|
-
**
|
|
273
|
+
**
|
|
274
274
|
)
|
|
275
275
|
end
|
|
276
276
|
|
|
@@ -53,8 +53,8 @@ module Prescient
|
|
|
53
53
|
# Validate and bound application-provided JSON documents.
|
|
54
54
|
class Memory < Base
|
|
55
55
|
# @param documents [Array<Hash>, Hash] Documents to validate
|
|
56
|
-
def initialize(documents:, **
|
|
57
|
-
super(**
|
|
56
|
+
def initialize(documents:, **)
|
|
57
|
+
super(**)
|
|
58
58
|
@documents = documents
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -67,8 +67,8 @@ module Prescient
|
|
|
67
67
|
# Read JSON documents from a local file.
|
|
68
68
|
class JsonFile < Base
|
|
69
69
|
# @param path [String] JSON file path
|
|
70
|
-
def initialize(path:, **
|
|
71
|
-
super(**
|
|
70
|
+
def initialize(path:, **)
|
|
71
|
+
super(**)
|
|
72
72
|
@path = path
|
|
73
73
|
return if @path.is_a?(String) && !@path.empty?
|
|
74
74
|
|
|
@@ -91,8 +91,8 @@ module Prescient
|
|
|
91
91
|
class RedisJson < Base
|
|
92
92
|
# @param client [#get] Redis-compatible client
|
|
93
93
|
# @param key [String] Redis key containing a JSON document or array
|
|
94
|
-
def initialize(client:, key:, **
|
|
95
|
-
super(**
|
|
94
|
+
def initialize(client:, key:, **)
|
|
95
|
+
super(**)
|
|
96
96
|
@client = client
|
|
97
97
|
@key = key
|
|
98
98
|
return if @key.is_a?(String) && !@key.empty?
|
data/lib/prescient/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prescient
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ken C. Demanawa
|
|
@@ -41,6 +41,7 @@ files:
|
|
|
41
41
|
- ".yardopts"
|
|
42
42
|
- CHANGELOG.md
|
|
43
43
|
- CODE_OF_CONDUCT.md
|
|
44
|
+
- CONTRIBUTING.md
|
|
44
45
|
- Dockerfile
|
|
45
46
|
- Dockerfile.example
|
|
46
47
|
- INTEGRATION_GUIDE.md
|
|
@@ -125,14 +126,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
125
126
|
requirements:
|
|
126
127
|
- - ">="
|
|
127
128
|
- !ruby/object:Gem::Version
|
|
128
|
-
version: 3.
|
|
129
|
+
version: '3.2'
|
|
129
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
131
|
requirements:
|
|
131
132
|
- - ">="
|
|
132
133
|
- !ruby/object:Gem::Version
|
|
133
134
|
version: '0'
|
|
134
135
|
requirements: []
|
|
135
|
-
rubygems_version: 4.0.
|
|
136
|
+
rubygems_version: 4.0.20
|
|
136
137
|
specification_version: 4
|
|
137
138
|
summary: A boring AI provider gateway for Ruby
|
|
138
139
|
test_files: []
|