prescient 0.6.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +21 -268
  3. data/CHANGELOG.md +59 -0
  4. data/INTEGRATION_GUIDE.md +19 -1
  5. data/README.md +369 -21
  6. data/Steepfile +12 -12
  7. data/db/migrate/001_create_prescient_tables.rb +15 -16
  8. data/docker-compose.yml +22 -0
  9. data/examples/README.md +36 -1
  10. data/examples/custom_contexts.rb +4 -4
  11. data/examples/web_search.rb +34 -0
  12. data/exe/prescient +2 -2
  13. data/exe/prescient-mcp +7 -0
  14. data/lib/prescient/agent/audit_log.rb +37 -0
  15. data/lib/prescient/agent/cli_adapter.rb +29 -0
  16. data/lib/prescient/agent/configuration.rb +57 -0
  17. data/lib/prescient/agent/context.rb +56 -0
  18. data/lib/prescient/agent/error_serializer.rb +47 -0
  19. data/lib/prescient/agent/errors.rb +25 -0
  20. data/lib/prescient/agent/parser.rb +49 -0
  21. data/lib/prescient/agent/prompt_builder.rb +31 -0
  22. data/lib/prescient/agent/result.rb +36 -0
  23. data/lib/prescient/agent/runtime.rb +175 -0
  24. data/lib/prescient/agent/schema_validator.rb +215 -0
  25. data/lib/prescient/agent/tool_registry.rb +89 -0
  26. data/lib/prescient/agent.rb +22 -0
  27. data/lib/prescient/api.rb +346 -231
  28. data/lib/prescient/base.rb +370 -372
  29. data/lib/prescient/cli.rb +591 -402
  30. data/lib/prescient/client.rb +31 -4
  31. data/lib/prescient/configuration_loader.rb +511 -336
  32. data/lib/prescient/document_source.rb +114 -0
  33. data/lib/prescient/errors.rb +13 -3
  34. data/lib/prescient/mcp/authentication.rb +39 -0
  35. data/lib/prescient/mcp/configuration.rb +38 -0
  36. data/lib/prescient/mcp/rack.rb +243 -0
  37. data/lib/prescient/mcp/server.rb +202 -0
  38. data/lib/prescient/mcp/stdio.rb +42 -0
  39. data/lib/prescient/mcp.rb +8 -0
  40. data/lib/prescient/pgvector.rb +193 -189
  41. data/lib/prescient/provider/anthropic.rb +129 -125
  42. data/lib/prescient/provider/deepseek.rb +122 -118
  43. data/lib/prescient/provider/gemini.rb +153 -149
  44. data/lib/prescient/provider/huggingface.rb +191 -187
  45. data/lib/prescient/provider/mistral.rb +151 -147
  46. data/lib/prescient/provider/ollama.rb +168 -165
  47. data/lib/prescient/provider/openai.rb +174 -171
  48. data/lib/prescient/provider/xai.rb +122 -118
  49. data/lib/prescient/tool/search_api.rb +130 -0
  50. data/lib/prescient/tool/searxng.rb +128 -0
  51. data/lib/prescient/tool.rb +125 -0
  52. data/lib/prescient/version.rb +1 -1
  53. data/lib/prescient.rb +129 -55
  54. data/schema/prescient.configuration.schema.json +119 -0
  55. data/searxng/settings.yml +18 -0
  56. data/sig/prescient.rbs +228 -1
  57. metadata +33 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 167f50351b78b35d1ae63d3487285db48c07799ad015b5d49f46dd3c451afa49
4
- data.tar.gz: 91e1895635015120c75b0b461fea017d8ec7c4b5ebd81f1d2b0c86ba37690e1d
3
+ metadata.gz: e272a00a9f7baaee44c4ad7b9827da6c1e5b930a98228e8d58718474d3090214
4
+ data.tar.gz: a7ac75b948c326d0829db56e0ab297561d178fa4643a6a4bbd5b4dc11cff150b
5
5
  SHA512:
6
- metadata.gz: 6cdf4ed9b05525692898cdd88153f092c23f5caac1d422962bdc768055bb225e960e45a9fb877adb17a7c686e8bf608db09dea1b3e24ebc15767071255910285
7
- data.tar.gz: ecec27b8c215dfe5fb92e00f68fd6a5ae66c8284342525c9ae635214318032fc4970a72d2944679e455915f2ba8de8425a07706530ca6c309bedc5d5d4ff114a
6
+ metadata.gz: 1e4ff77f5dd524e7bc3217b4f8fc1b8045f43d188b751f81dc2964dcf2d15dbfd3ed58efe8598ba40bd875e19a3597de1308e32c066466713b06af8e79fea55a
7
+ data.tar.gz: 3f5f8e5f78bc8db0566102f686ce1b66e752f9f81faba9dae09adfa49883aaa67c621b108b9a60cb573d695cae4874567e2ebf1c69b90a3971a6686f0316c288
data/.rubocop.yml CHANGED
@@ -25,7 +25,8 @@ AllCops:
25
25
  - 'Rakefile'
26
26
  - 'examples/**/*'
27
27
 
28
- # === LAYOUT & FORMATTING ===
28
+ Metrics/ParameterLists:
29
+ CountKeywordArgs: false
29
30
 
30
31
  Layout/LineLength:
31
32
  Max: 120
@@ -38,291 +39,43 @@ Layout/LineLength:
38
39
  - '^\s*context\s' # Test contexts
39
40
  - '^\s*describe\s' # Test descriptions
40
41
 
41
- Layout/MultilineMethodCallIndentation:
42
- EnforcedStyle: indented
43
-
44
- Layout/FirstHashElementIndentation:
45
- EnforcedStyle: consistent
46
-
47
- Layout/FirstArrayElementIndentation:
48
- EnforcedStyle: consistent
49
-
50
- Layout/HashAlignment:
51
- EnforcedHashRocketStyle: table
52
- EnforcedColonStyle: table
53
-
54
- Layout/SpaceInsideHashLiteralBraces:
55
- EnforcedStyle: space
56
-
57
- Layout/EmptyLinesAroundModuleBody:
58
- Enabled: false
59
-
60
- Layout/EmptyLinesAroundClassBody:
61
- Enabled: false
62
-
63
- # === STYLE ===
64
-
65
42
  Style/StringLiterals:
66
- EnforcedStyle: single_quotes
43
+ EnforcedStyle: double_quotes
67
44
 
68
45
  Style/StringLiteralsInInterpolation:
69
- EnforcedStyle: single_quotes
70
-
71
- Style/FrozenStringLiteralComment:
72
- Enabled: true
73
- EnforcedStyle: always
74
- Exclude:
75
- - 'examples/**/*'
76
-
77
- Style/Documentation:
78
- Enabled: false
79
-
80
- Style/ClassAndModuleChildren:
81
- EnforcedStyle: compact
82
-
83
- Style/TrailingCommaInArguments:
84
- EnforcedStyleForMultiline: comma
85
-
86
- Style/TrailingCommaInArrayLiteral:
87
- EnforcedStyleForMultiline: comma
88
-
89
- Style/TrailingCommaInHashLiteral:
90
- EnforcedStyleForMultiline: comma
91
-
92
- Style/HashSyntax:
93
- EnforcedStyle: ruby19_no_mixed_keys
94
-
95
- Style/Lambda:
96
- EnforcedStyle: literal
97
-
98
- Style/NumericLiterals:
99
- MinDigits: 6
100
-
101
- Style/BlockDelimiters:
102
- EnforcedStyle: semantic
103
- AllowedMethods:
104
- - expect
105
- - let
106
- - subject
107
-
108
- Style/WordArray:
109
- EnforcedStyle: brackets
110
-
111
- Style/SymbolArray:
112
- EnforcedStyle: brackets
113
-
114
- Style/FormatString:
115
- EnforcedStyle: percent
116
-
117
- Style/CollectionMethods:
118
- PreferredMethods:
119
- collect: map
120
- collect!: map!
121
- detect: find
122
- find_all: select
123
- reduce: inject
124
-
125
- Style/Alias:
126
- EnforcedStyle: prefer_alias_method
127
-
128
- Style/AccessorGrouping:
129
- EnforcedStyle: separated
130
-
131
- Style/BisectedAttrAccessor:
132
- Enabled: true
133
-
134
- Style/RedundantAssignment:
135
- Enabled: true
136
-
137
- Style/RedundantFetchBlock:
138
- Enabled: true
139
-
140
- Style/RedundantFileExtensionInRequire:
141
- Enabled: true
142
-
143
- Style/RedundantRegexpCharacterClass:
144
- Enabled: true
145
-
146
- Style/RedundantRegexpEscape:
147
- Enabled: true
148
-
149
- Style/SlicingWithRange:
150
- Enabled: true
151
-
152
- Style/ExponentialNotation:
153
- Enabled: true
154
-
155
- Style/HashTransformKeys:
156
- Enabled: true
157
-
158
- Style/HashTransformValues:
159
- Enabled: true
160
-
161
- Style/RedundantReturn:
162
- AllowMultipleReturnValues: true
163
-
164
- # === METRICS ===
165
-
166
- Metrics/ModuleLength:
167
- Max: 150
46
+ EnforcedStyle: double_quotes
168
47
 
169
48
  Metrics/ClassLength:
170
- Enabled: false
171
- Max: 150
49
+ Enabled: true
50
+ Max: 145
172
51
  Exclude:
173
52
  - 'test/**/*'
174
53
 
175
54
  Metrics/MethodLength:
176
- Enabled: false
177
- Max: 25
55
+ Max: 37
178
56
  Exclude:
179
- - 'test/**/*'
180
- - 'db/**/*'
181
- - 'lib/prescient/provider/*.rb'
182
-
183
- Metrics/BlockLength:
184
- Enabled: false
185
- Max: 25
186
- Exclude:
187
- - 'test/**/*'
188
- - 'lib/prescient.rb' # Configuration block
57
+ - "test/**/*"
58
+ - "db/migrate/**/*"
189
59
 
190
60
  Metrics/AbcSize:
191
- Max: 20
61
+ Enabled: true
62
+ Max: 55
192
63
  Exclude:
193
- - 'test/**/*'
194
- - 'db/**/*'
195
- - 'lib/prescient/provider/*.rb'
64
+ - "test/**/*"
65
+ - "db/migrate/**/*"
196
66
 
197
- Metrics/CyclomaticComplexity:
198
- Max: 8
199
- Exclude:
200
- - 'lib/prescient/provider/*.rb'
67
+ Minitest/MultipleAssertions:
68
+ Max: 20
201
69
 
202
70
  Metrics/PerceivedComplexity:
203
- Enabled: false
204
- Max: 8
205
- Exclude:
206
- - 'lib/prescient/provider/*.rb'
207
-
208
- Metrics/ParameterLists:
209
- Max: 5
210
- CountKeywordArgs: false
211
-
212
- # === LINT ===
213
-
214
- Lint/RaiseException:
215
- Enabled: true
216
-
217
- Lint/StructNewOverride:
218
- Enabled: true
219
-
220
- Lint/DeprecatedOpenSSLConstant:
221
- Enabled: true
222
-
223
- Lint/MixedRegexpCaptureTypes:
224
- Enabled: true
225
-
226
- Lint/DuplicateElsifCondition:
227
- Enabled: true
228
-
229
- Lint/BinaryOperatorWithIdenticalOperands:
230
- Enabled: true
231
-
232
- Lint/DuplicateRescueException:
233
- Enabled: true
234
-
235
- Lint/EmptyConditionalBody:
236
- Enabled: true
237
-
238
- Lint/FloatComparison:
239
- Enabled: true
240
-
241
- Lint/MissingSuper:
242
- Enabled: true
243
-
244
- Lint/OutOfRangeRegexpRef:
245
- Enabled: true
246
-
247
- Lint/SelfAssignment:
248
- Enabled: true
249
-
250
- Lint/TopLevelReturnWithArgument:
251
- Enabled: true
252
-
253
- Lint/UnreachableLoop:
254
- Enabled: true
255
-
256
- # === NAMING ===
257
-
258
- Naming/PredicatePrefix:
259
- ForbiddenPrefixes:
260
- - is_
261
- AllowedMethods:
262
- - is_a?
263
-
264
- Naming/MemoizedInstanceVariableName:
265
- EnforcedStyleForLeadingUnderscores: required
266
-
267
- Naming/VariableNumber:
268
- EnforcedStyle: snake_case
269
-
270
- # === SECURITY ===
271
-
272
- Security/Open:
273
- Enabled: true
274
-
275
- Security/YAMLLoad:
276
- Enabled: true
277
-
278
- Security/JSONLoad:
279
- Enabled: true
280
-
281
- # === PERFORMANCE ===
282
-
283
- Performance/AncestorsInclude:
284
- Enabled: true
285
-
286
- Performance/BigDecimalWithNumericArgument:
287
- Enabled: true
288
-
289
- Performance/RedundantSortBlock:
290
- Enabled: true
291
-
292
- Performance/RedundantStringChars:
293
- Enabled: true
294
-
295
- Performance/ReverseFirst:
296
- Enabled: true
297
-
298
- Performance/SortReverse:
299
- Enabled: true
300
-
301
- Performance/Squeeze:
302
- Enabled: true
303
-
304
- Performance/StringInclude:
305
- Enabled: true
306
-
307
- Performance/Sum:
308
- Enabled: true
309
-
310
- # === MINITEST ===
311
-
312
- Minitest/MultipleAssertions:
313
71
  Max: 10
314
72
 
315
- Minitest/AssertTruthy:
316
- Enabled: true
317
-
318
- Minitest/AssertWithExpectedArgument:
319
- Enabled: true
73
+ Metrics/BlockLength:
74
+ Max: 35
320
75
 
321
- Minitest/RefuteFalse:
322
- Enabled: true
323
76
 
324
- Minitest/RefuteNil:
325
- Enabled: true
77
+ Metrics/CyclomaticComplexity:
78
+ Max: 10
326
79
 
327
- Minitest/TestMethodName:
328
- Enabled: true
80
+ Style/DirectiveScope:
81
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -2,6 +2,65 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## [0.8.0] - 2025-08-31
6
+
7
+ ### Added
8
+
9
+ - Added an optional, bounded Ruby agent runtime with strict single-action tool
10
+ execution, provider routing through `Prescient::Client`, and safe loop limits.
11
+ - Added deterministic agent context compaction and safe serialization of tool
12
+ failures before they are returned to the model.
13
+ - Added generic callable agent tools, request-scoped authorization and bounded
14
+ telemetry hooks, the `prescient agent` CLI command, and `POST /v1/agent`.
15
+ - Added a dedicated `Prescient::Agent::CLIAdapter`, schema validation for
16
+ generic callable tools, and independent task and response byte limits.
17
+ - Added structured failure telemetry, principal propagation, and an
18
+ authenticated, bounded MCP Rack transport backed by shared JSON-RPC dispatch.
19
+ - Added valid UTF-8, JSON-safe observation truncation for bounded Agent context.
20
+ - Extended the MCP Rack transport with authenticated sessions, lifecycle
21
+ termination, notifications, one-shot SSE responses, Origin checks, and a
22
+ reusable bearer-token authentication policy.
23
+ - Documented the host-owned tenant/principal authorization contract and aligned
24
+ the Agent implementation plan with the shipped REST and MCP surfaces.
25
+ - Added an opt-in thread-safe JSONL Agent audit sink for durable safe telemetry.
26
+ - Added an optional lazy MCP adapter with capability discovery, safe core
27
+ operations, agent invocation, resources, and newline-delimited JSON-RPC stdio.
28
+
29
+ ### Fixed
30
+
31
+ - Fixed Agent tool validation to enforce richer JSON Schema constraints,
32
+ composition, and local references.
33
+ - Fixed request-scoped Agent authorization context handling for concurrent API
34
+ requests and added regression coverage for principal isolation.
35
+ - Tightened generic callable Agent tools to require explicit object schemas
36
+ instead of accepting unconstrained arguments.
37
+ - Added structured Agent failure telemetry for initialization failures and
38
+ propagated telemetry configuration through CLI and REST Agent execution.
39
+
40
+ ## [0.7.0] - 2025-08-17
41
+
42
+ ### Added
43
+
44
+ - Added an explicit external-tool contract with a configurable SearXNG web-search adapter.
45
+ - Added YAML/schema configuration for tool registration, environment references, bounded requests, and normalized search results.
46
+ - Added `prescient search` and an annotated `web_search` configuration example.
47
+ - Added an optional development SearXNG service to `docker-compose.yml` for runnable web-search examples.
48
+ - Added opt-in search-to-provider context assembly through `Prescient.search_and_generate` and `prescient search --generate`.
49
+ - Added `POST /v1/search/generate` for REST API consumers to opt in to search-result context.
50
+ - Added `POST /v1/search` for normalized raw external-tool results without AI generation.
51
+ - Added SearchApi as a hosted web-search adapter with engine, location, language,
52
+ country, API-key, timeout, and result-limit configuration.
53
+ - Added capability groups for ordered tool-adapter fallback on transient
54
+ connection and rate-limit failures.
55
+ - Added bounded JSON document sources for Ruby, CLI, and REST generation context,
56
+ including local files, in-memory documents, and injected Redis clients.
57
+ - Documented SearXNG and SearchApi setup and CLI usage side by side.
58
+ - Added explicit `--generate` opt-in behavior to the web-search example.
59
+ - Added `SEARXNG_URL` environment defaults for automatic `web_search` registration.
60
+ - Expanded `prescient config example` with documented SearXNG settings,
61
+ environment references, custom tool names, and direct-versus-generated usage.
62
+ - Organized CLI help into global and search-specific option sections.
63
+
5
64
  ## [0.6.0] - 2025-08-15
6
65
 
7
66
  ### Added
data/INTEGRATION_GUIDE.md CHANGED
@@ -11,7 +11,7 @@ and [examples guide](examples/README.md).
11
11
 
12
12
  ```ruby
13
13
  # Add to your Gemfile
14
- gem 'prescient', '~> 0.6.0'
14
+ gem 'prescient', '~> 0.8.0'
15
15
  ```
16
16
 
17
17
  ### 2. Replace Existing AI Service
@@ -190,6 +190,9 @@ This makes the following routes available under `/prescient`:
190
190
  | `GET` | `/v1/capabilities` | Provider capabilities |
191
191
  | `GET` | `/v1/health` | Provider health |
192
192
  | `POST` | `/v1/generate` | Text generation |
193
+ | `POST` | `/v1/search` | Normalized external-tool search |
194
+ | `POST` | `/v1/search/generate` | Search with opt-in AI generation |
195
+ | `POST` | `/v1/agent` | Bounded allowlisted tool-calling agent |
193
196
  | `POST` | `/v1/embeddings` | Single embedding |
194
197
  | `POST` | `/v1/embeddings/batch` | Bounded batch embeddings |
195
198
 
@@ -202,6 +205,21 @@ curl -X POST http://localhost:3000/prescient/v1/generate \
202
205
  -H "Authorization: Bearer ${PRESCIENT_API_TOKEN}" \
203
206
  -H 'Content-Type: application/json' \
204
207
  -d '{"prompt":"Explain Ruby fibers"}'
208
+
209
+ curl -X POST http://localhost:3000/prescient/v1/search/generate \
210
+ -H "Authorization: Bearer ${PRESCIENT_API_TOKEN}" \
211
+ -H 'Content-Type: application/json' \
212
+ -d '{"query":"Ruby HTTP clients","provider":"openai","limit":5}'
213
+
214
+ curl -X POST http://localhost:3000/prescient/v1/search \
215
+ -H "Authorization: Bearer ${PRESCIENT_API_TOKEN}" \
216
+ -H 'Content-Type: application/json' \
217
+ -d '{"query":"Ruby HTTP clients","limit":5}'
218
+
219
+ curl -X POST http://localhost:3000/prescient/v1/agent \
220
+ -H "Authorization: Bearer ${PRESCIENT_API_TOKEN}" \
221
+ -H 'Content-Type: application/json' \
222
+ -d '{"prompt":"Summarize account status","provider":"openai","tools":[]}'
205
223
  ```
206
224
 
207
225
  Responses include a request ID. Request bodies are size-limited, batch inputs