patient_llm 0.5.1 → 0.6.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/CHANGELOG.md +6 -0
- data/README.md +17 -0
- data/VERSION +1 -1
- data/lib/patient_llm/agent.rb +31 -0
- data/lib/patient_llm/request_preview.rb +15 -0
- data/lib/patient_llm.rb +142 -56
- 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: a477a6fc932f1ad07d9dae5c06bc71e3ebac003a10b155400076172a7f0a67fc
|
|
4
|
+
data.tar.gz: 6d11574edcede56eb37658e36f94fe2f45aa693fc058508c8058eeab3df6429b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eb0cde4a1466a1a885f78b0a57c3ec50124650672cee430d13818d0daa3b3ddb0baf1fe3b326165ddf43d814e6c458eceb8ff4d9b24c21d33902b861bcd1f3f3
|
|
7
|
+
data.tar.gz: 881b6d03088e1d3880597fb3fecb87b5e53885846d39f61548394ef2cd68ced822f3dd7e6514061d522942ed7fe084f0e8c86ec8752d9233cb206218fe783a28
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 0.6.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added `PatientLLM.preview_request` and `PatientLLM::Agent.preview_request` to build the request that `ask` would send without sending it. Both return a `PatientLLM::RequestPreview` with the resolved `url`, `headers`, and JSON `payload`, produced by the same resolution logic dispatch uses. Nothing is enqueued or executed, header values that reference registered secrets are replaced with placeholders, and request preprocessors (which run at send time) are not applied. `Agent.preview_request` accepts the same options as `ask`, ignoring `context:` and `callback:` since they do not affect the request.
|
|
12
|
+
|
|
7
13
|
## 0.5.1
|
|
8
14
|
|
|
9
15
|
### Added
|
data/README.md
CHANGED
|
@@ -364,6 +364,16 @@ response = ResearchAgent.ask!("What is the capital of France?")
|
|
|
364
364
|
response.text # => "Paris."
|
|
365
365
|
```
|
|
366
366
|
|
|
367
|
+
### Previewing requests
|
|
368
|
+
|
|
369
|
+
`preview_request` builds the request that `ask` would send — through the same resolution logic — without sending anything. It returns a `PatientLLM::RequestPreview` with the resolved `url`, `headers`, and JSON `payload`. Header values that reference registered secrets are replaced with placeholders, and request preprocessors (which run at send time) are not applied:
|
|
370
|
+
|
|
371
|
+
```ruby
|
|
372
|
+
preview = ResearchAgent.preview_request("What is the capital of France?")
|
|
373
|
+
preview.url # => "https://api.openai.com/v1/chat/completions"
|
|
374
|
+
preview.payload # => {"model" => "gpt-4o", "messages" => [...], ...}
|
|
375
|
+
```
|
|
376
|
+
|
|
367
377
|
## The low-level API
|
|
368
378
|
|
|
369
379
|
Agents compile down to this API; use it directly when you need full control.
|
|
@@ -451,6 +461,13 @@ PatientLLM.ask(session,
|
|
|
451
461
|
|
|
452
462
|
`headers` and `params` are merged on top of the provider's configured values, while the other options replace the provider defaults. All overrides are preserved across automatic tool-loop iterations.
|
|
453
463
|
|
|
464
|
+
`PatientLLM.preview_request` accepts the same arguments (minus `callback:`) and returns the request that `ask` would send — a `PatientLLM::RequestPreview` with the resolved `url`, `headers` (secret values redacted), and JSON `payload` — without enqueuing or executing anything:
|
|
465
|
+
|
|
466
|
+
```ruby
|
|
467
|
+
preview = PatientLLM.preview_request(session, provider: :openai)
|
|
468
|
+
preview.payload # => {"model" => "gpt-4o", "messages" => [...]}
|
|
469
|
+
```
|
|
470
|
+
|
|
454
471
|
### Tool calling with the registry
|
|
455
472
|
|
|
456
473
|
Tools can also be registered on the global `PromptBuilder.tool_registry` with their handler, then attached to sessions by name — no schema duplication:
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.6.0
|
data/lib/patient_llm/agent.rb
CHANGED
|
@@ -353,6 +353,37 @@ module PatientLLM
|
|
|
353
353
|
capture[:response] || raise("No response was captured; the request did not complete")
|
|
354
354
|
end
|
|
355
355
|
|
|
356
|
+
# Build the request that {ask} would send without sending it. The
|
|
357
|
+
# session is built from the agent's declarations exactly as {ask} builds
|
|
358
|
+
# it (including any per-request session options and the user message,
|
|
359
|
+
# which is appended to a passed session), and the request is resolved
|
|
360
|
+
# through the same logic as a dispatched request. Nothing is enqueued or
|
|
361
|
+
# executed. See {PatientLLM.preview_request} for details on what the
|
|
362
|
+
# preview does and does not reflect.
|
|
363
|
+
#
|
|
364
|
+
# @param message [String, Array, Hash, nil] the user message to add
|
|
365
|
+
# @param session [PromptBuilder::Session, nil] an existing session to use
|
|
366
|
+
# instead of building a new one
|
|
367
|
+
# @param context [Hash, nil] accepted for parity with {ask} and ignored;
|
|
368
|
+
# the context does not affect the request
|
|
369
|
+
# @param callback [Class, String, nil] accepted for parity with {ask} and
|
|
370
|
+
# ignored; the callback does not affect the request
|
|
371
|
+
# @param options [Hash] the same per-request overrides accepted by {ask}
|
|
372
|
+
# @return [PatientLLM::RequestPreview] the url, headers, and JSON payload
|
|
373
|
+
def preview_request(message = nil, session: nil, context: nil, callback: nil, **options)
|
|
374
|
+
session_options = options.slice(*PromptBuilder::Session::INITIALIZE_OPTIONS)
|
|
375
|
+
raise ArgumentError.new("session options cannot be passed when a session is provided") if session && session_options.any?
|
|
376
|
+
|
|
377
|
+
session ||= build_session(**session_options)
|
|
378
|
+
session.user(message) if message
|
|
379
|
+
|
|
380
|
+
PatientLLM.preview_request(
|
|
381
|
+
session,
|
|
382
|
+
provider: provider_name!,
|
|
383
|
+
**options.except(*PromptBuilder::Session::INITIALIZE_OPTIONS)
|
|
384
|
+
)
|
|
385
|
+
end
|
|
386
|
+
|
|
356
387
|
# Build a new session from the agent's declarations. Options passed by
|
|
357
388
|
# the caller take precedence over the agent's declarations for the same
|
|
358
389
|
# fields (pass an explicit nil to unset a declared value for one request).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PatientLLM
|
|
4
|
+
# The request that {PatientLLM.ask} would send, as returned by
|
|
5
|
+
# {PatientLLM.preview_request} and {Agent.preview_request}. Header values
|
|
6
|
+
# that reference registered secrets are replaced with placeholder strings.
|
|
7
|
+
#
|
|
8
|
+
# @!attribute [r] url
|
|
9
|
+
# @return [String] The fully resolved request URL
|
|
10
|
+
# @!attribute [r] headers
|
|
11
|
+
# @return [Hash] The request headers, with secret values redacted
|
|
12
|
+
# @!attribute [r] payload
|
|
13
|
+
# @return [Hash] The JSON request payload
|
|
14
|
+
RequestPreview = Data.define(:url, :headers, :payload)
|
|
15
|
+
end
|
data/lib/patient_llm.rb
CHANGED
|
@@ -16,6 +16,7 @@ module PatientLLM
|
|
|
16
16
|
autoload :HaltError, File.expand_path("patient_llm/halt_error", __dir__)
|
|
17
17
|
autoload :MaxToolIterationsError, File.expand_path("patient_llm/max_tool_iterations_error", __dir__)
|
|
18
18
|
autoload :Presets, File.expand_path("patient_llm/presets", __dir__)
|
|
19
|
+
autoload :RequestPreview, File.expand_path("patient_llm/request_preview", __dir__)
|
|
19
20
|
autoload :Schema, File.expand_path("patient_llm/schema", __dir__)
|
|
20
21
|
autoload :StructuredOutputError, File.expand_path("patient_llm/structured_output_error", __dir__)
|
|
21
22
|
|
|
@@ -157,24 +158,65 @@ module PatientLLM
|
|
|
157
158
|
# {Callback::MAX_TOOL_ITERATIONS}.
|
|
158
159
|
# @return [Object] Handler-specific identifier for the enqueued request
|
|
159
160
|
def ask(session, provider:, callback:, callback_args: {}, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil)
|
|
160
|
-
request_options =
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
# The request options travel through the job queue in the callback args,
|
|
171
|
-
# which only permit JSON-native values; convert Symbols (e.g. serializer
|
|
172
|
-
# names, preprocessor names, header/param values) to Strings up front.
|
|
173
|
-
request_options = PromptBuilder.jsonify(request_options)
|
|
161
|
+
request_options = build_request_options(
|
|
162
|
+
url: url,
|
|
163
|
+
serializer: serializer,
|
|
164
|
+
path: path,
|
|
165
|
+
headers: headers,
|
|
166
|
+
params: params,
|
|
167
|
+
preprocessors: preprocessors,
|
|
168
|
+
timeout: timeout,
|
|
169
|
+
max_tool_iterations: max_tool_iterations
|
|
170
|
+
)
|
|
174
171
|
|
|
175
172
|
dispatch(session, provider: provider, callback: callback, callback_args: callback_args, request_options: request_options)
|
|
176
173
|
end
|
|
177
174
|
|
|
175
|
+
# Build the request that {.ask} would send without sending it. The same
|
|
176
|
+
# resolution logic as {.ask} is applied: per-request overrides are merged
|
|
177
|
+
# over the provider configuration, the session is serialized with the
|
|
178
|
+
# resolved serializer, and provider params are merged into the payload.
|
|
179
|
+
#
|
|
180
|
+
# Nothing is enqueued or executed and no callback is required. Request
|
|
181
|
+
# preprocessors (e.g. AWS SigV4 signing) run at send time in the request
|
|
182
|
+
# processor, so their changes are not reflected in the preview. Header
|
|
183
|
+
# values that reference registered secrets are replaced with placeholders
|
|
184
|
+
# and never resolved.
|
|
185
|
+
#
|
|
186
|
+
# @param session [PromptBuilder::Session] The prompt session containing conversation state
|
|
187
|
+
# @param provider [Symbol, String] Registered provider name
|
|
188
|
+
# @param url [String, nil] Override the provider's base URL for this request
|
|
189
|
+
# @param serializer [Symbol, nil] Override the provider's serializer for this request
|
|
190
|
+
# @param path [String, nil] Override the endpoint path for this request
|
|
191
|
+
# @param headers [Hash, nil] Additional headers merged on top of provider headers
|
|
192
|
+
# @param params [Hash, nil] Additional params merged into the request payload
|
|
193
|
+
# @param preprocessors [String, Symbol, Array<String, Symbol>, nil] Accepted for
|
|
194
|
+
# parity with {.ask}; preprocessors are not applied to the preview.
|
|
195
|
+
# @param timeout [Numeric, nil] Accepted for parity with {.ask}; does not affect the preview.
|
|
196
|
+
# @param max_tool_iterations [Integer, nil] Accepted for parity with {.ask}; does not
|
|
197
|
+
# affect the preview.
|
|
198
|
+
# @return [RequestPreview] The url, headers, and JSON payload the request would send
|
|
199
|
+
def preview_request(session, provider:, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil)
|
|
200
|
+
request_options = build_request_options(
|
|
201
|
+
url: url,
|
|
202
|
+
serializer: serializer,
|
|
203
|
+
path: path,
|
|
204
|
+
headers: headers,
|
|
205
|
+
params: params,
|
|
206
|
+
preprocessors: preprocessors,
|
|
207
|
+
timeout: timeout,
|
|
208
|
+
max_tool_iterations: max_tool_iterations
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
resolved = resolve_request(session, self.provider(provider) || {}, request_options)
|
|
212
|
+
|
|
213
|
+
RequestPreview.new(
|
|
214
|
+
url: resolved.url,
|
|
215
|
+
headers: redact_secret_headers(resolved.headers),
|
|
216
|
+
payload: resolved.payload
|
|
217
|
+
)
|
|
218
|
+
end
|
|
219
|
+
|
|
178
220
|
# Internal dispatch used by {.ask} and by {Callback} to re-issue requests
|
|
179
221
|
# during the automatic tool loop. Not part of the public API.
|
|
180
222
|
#
|
|
@@ -187,45 +229,16 @@ module PatientLLM
|
|
|
187
229
|
PatientLLM::Callback.validate_callback_class!(PatientHttp::ClassHelper.resolve_class_name(callback.to_s))
|
|
188
230
|
end
|
|
189
231
|
|
|
190
|
-
|
|
191
|
-
raise ArgumentError, "No API base URL configured. Set url: or register a provider with a url." unless resolved_url
|
|
192
|
-
|
|
193
|
-
resolved_serializer = (request_options["serializer"] || provider_config[:serializer] || :chat_completion).to_sym
|
|
194
|
-
validate_serializer!(resolved_serializer)
|
|
195
|
-
|
|
196
|
-
resolved_path = request_options["path"] || provider_config[:path] || SERIALIZER_PATHS[resolved_serializer]
|
|
197
|
-
if resolved_path.include?("{model}")
|
|
198
|
-
raise ArgumentError, "The endpoint path #{resolved_path.inspect} includes a {model} placeholder but session.model is not set" if session.model.nil?
|
|
199
|
-
|
|
200
|
-
# Encode the model as a single path segment; Bedrock model ids can be
|
|
201
|
-
# ARNs containing ":" and "/" that would otherwise splice extra path
|
|
202
|
-
# segments into the URL and break SigV4 signing.
|
|
203
|
-
resolved_path = resolved_path.gsub("{model}", URI.encode_uri_component(session.model.to_s))
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
resolved_headers = (provider_config[:headers] || {}).merge(request_options["headers"] || {})
|
|
207
|
-
if resolved_serializer == :messages && !resolved_headers.key?("anthropic-version")
|
|
208
|
-
resolved_headers = {"anthropic-version" => ANTHROPIC_VERSION}.merge(resolved_headers)
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
resolved_params = (provider_config[:params] || {}).merge(request_options["params"] || {})
|
|
212
|
-
resolved_preprocessors = request_options["preprocessors"] || provider_config[:preprocessors]
|
|
213
|
-
resolved_timeout = request_options["timeout"] || provider_config[:timeout]
|
|
214
|
-
resolved_max_tool_iterations = (request_options["max_tool_iterations"] || provider_config[:max_tool_iterations] || Callback::MAX_TOOL_ITERATIONS).to_i
|
|
215
|
-
|
|
216
|
-
payload = session.request_payload(resolved_serializer)
|
|
217
|
-
payload = deep_merge(payload, deep_stringify_keys(resolved_params)) unless resolved_params.empty?
|
|
218
|
-
|
|
219
|
-
request_url = join_url(resolved_url, resolved_path)
|
|
232
|
+
resolved = resolve_request(session, provider_config, request_options)
|
|
220
233
|
|
|
221
234
|
dispatch_callback_args = {
|
|
222
235
|
session: session_payload(session),
|
|
223
236
|
provider: provider_name,
|
|
224
|
-
serializer:
|
|
237
|
+
serializer: resolved.serializer.to_s,
|
|
225
238
|
callback: callback.to_s,
|
|
226
239
|
custom: PromptBuilder.jsonify(callback_args || {}),
|
|
227
240
|
request_options: request_options,
|
|
228
|
-
max_tool_iterations:
|
|
241
|
+
max_tool_iterations: resolved.max_tool_iterations,
|
|
229
242
|
tool_iteration: tool_iteration,
|
|
230
243
|
original_request_id: original_request_id
|
|
231
244
|
}
|
|
@@ -233,11 +246,11 @@ module PatientLLM
|
|
|
233
246
|
if inline?
|
|
234
247
|
request = PatientHttp::Request.new(
|
|
235
248
|
:post,
|
|
236
|
-
|
|
237
|
-
json: payload,
|
|
238
|
-
headers:
|
|
239
|
-
preprocessors:
|
|
240
|
-
timeout:
|
|
249
|
+
resolved.url,
|
|
250
|
+
json: resolved.payload,
|
|
251
|
+
headers: resolved.headers,
|
|
252
|
+
preprocessors: resolved.preprocessors,
|
|
253
|
+
timeout: resolved.timeout
|
|
241
254
|
)
|
|
242
255
|
PatientHttp.execute_inline(
|
|
243
256
|
request: request,
|
|
@@ -247,11 +260,11 @@ module PatientLLM
|
|
|
247
260
|
)
|
|
248
261
|
else
|
|
249
262
|
PatientHttp.post(
|
|
250
|
-
|
|
251
|
-
json: payload,
|
|
252
|
-
headers:
|
|
253
|
-
preprocessors:
|
|
254
|
-
timeout:
|
|
263
|
+
resolved.url,
|
|
264
|
+
json: resolved.payload,
|
|
265
|
+
headers: resolved.headers,
|
|
266
|
+
preprocessors: resolved.preprocessors,
|
|
267
|
+
timeout: resolved.timeout,
|
|
255
268
|
raise_error_responses: true,
|
|
256
269
|
callback: PatientLLM::Callback,
|
|
257
270
|
callback_args: dispatch_callback_args
|
|
@@ -261,6 +274,79 @@ module PatientLLM
|
|
|
261
274
|
|
|
262
275
|
private
|
|
263
276
|
|
|
277
|
+
# Fully resolved request produced by merging per-request options over the
|
|
278
|
+
# provider configuration.
|
|
279
|
+
ResolvedRequest = Data.define(:url, :serializer, :headers, :payload, :preprocessors, :timeout, :max_tool_iterations)
|
|
280
|
+
private_constant :ResolvedRequest
|
|
281
|
+
|
|
282
|
+
# Normalize per-request overrides into a request options hash. The request
|
|
283
|
+
# options travel through the job queue in the callback args, which only
|
|
284
|
+
# permit JSON-native values; convert Symbols (e.g. serializer names,
|
|
285
|
+
# preprocessor names, header/param values) to Strings up front.
|
|
286
|
+
def build_request_options(url:, serializer:, path:, headers:, params:, preprocessors:, timeout:, max_tool_iterations:)
|
|
287
|
+
request_options = {}
|
|
288
|
+
request_options["url"] = url if url
|
|
289
|
+
request_options["serializer"] = serializer.to_s if serializer
|
|
290
|
+
request_options["path"] = path if path
|
|
291
|
+
request_options["headers"] = headers if headers && !headers.empty?
|
|
292
|
+
request_options["params"] = params if params && !params.empty?
|
|
293
|
+
request_options["preprocessors"] = preprocessors if preprocessors
|
|
294
|
+
request_options["timeout"] = timeout if timeout
|
|
295
|
+
request_options["max_tool_iterations"] = max_tool_iterations if max_tool_iterations
|
|
296
|
+
|
|
297
|
+
PromptBuilder.jsonify(request_options)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Resolve the request URL, headers, payload, and execution settings from
|
|
301
|
+
# the request options merged over the provider configuration. This is the
|
|
302
|
+
# single source of truth for what a request looks like; both {.dispatch}
|
|
303
|
+
# and {.preview_request} build requests through it.
|
|
304
|
+
def resolve_request(session, provider_config, request_options)
|
|
305
|
+
resolved_url = request_options["url"] || provider_config[:url]
|
|
306
|
+
raise ArgumentError, "No API base URL configured. Set url: or register a provider with a url." unless resolved_url
|
|
307
|
+
|
|
308
|
+
resolved_serializer = (request_options["serializer"] || provider_config[:serializer] || :chat_completion).to_sym
|
|
309
|
+
validate_serializer!(resolved_serializer)
|
|
310
|
+
|
|
311
|
+
resolved_path = request_options["path"] || provider_config[:path] || SERIALIZER_PATHS[resolved_serializer]
|
|
312
|
+
if resolved_path.include?("{model}")
|
|
313
|
+
raise ArgumentError, "The endpoint path #{resolved_path.inspect} includes a {model} placeholder but session.model is not set" if session.model.nil?
|
|
314
|
+
|
|
315
|
+
# Encode the model as a single path segment; Bedrock model ids can be
|
|
316
|
+
# ARNs containing ":" and "/" that would otherwise splice extra path
|
|
317
|
+
# segments into the URL and break SigV4 signing.
|
|
318
|
+
resolved_path = resolved_path.gsub("{model}", URI.encode_uri_component(session.model.to_s))
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
resolved_headers = (provider_config[:headers] || {}).merge(request_options["headers"] || {})
|
|
322
|
+
if resolved_serializer == :messages && !resolved_headers.key?("anthropic-version")
|
|
323
|
+
resolved_headers = {"anthropic-version" => ANTHROPIC_VERSION}.merge(resolved_headers)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
resolved_params = (provider_config[:params] || {}).merge(request_options["params"] || {})
|
|
327
|
+
|
|
328
|
+
payload = session.request_payload(resolved_serializer)
|
|
329
|
+
payload = deep_merge(payload, deep_stringify_keys(resolved_params)) unless resolved_params.empty?
|
|
330
|
+
|
|
331
|
+
ResolvedRequest.new(
|
|
332
|
+
url: join_url(resolved_url, resolved_path),
|
|
333
|
+
serializer: resolved_serializer,
|
|
334
|
+
headers: resolved_headers,
|
|
335
|
+
payload: payload,
|
|
336
|
+
preprocessors: request_options["preprocessors"] || provider_config[:preprocessors],
|
|
337
|
+
timeout: request_options["timeout"] || provider_config[:timeout],
|
|
338
|
+
max_tool_iterations: (request_options["max_tool_iterations"] || provider_config[:max_tool_iterations] || Callback::MAX_TOOL_ITERATIONS).to_i
|
|
339
|
+
)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Replace secret reference header values with placeholders so a preview
|
|
343
|
+
# never resolves or exposes secret values.
|
|
344
|
+
def redact_secret_headers(headers)
|
|
345
|
+
headers.transform_values do |value|
|
|
346
|
+
value.is_a?(PatientHttp::SecretReference) ? "<secret:#{value.name}>" : value
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
264
350
|
# Serialize the session for the callback args, offloading it to a payload
|
|
265
351
|
# store when session offloading is configured and the serialized session
|
|
266
352
|
# exceeds the threshold. Offloaded payloads are not deleted after use so
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: patient_llm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Durand
|
|
@@ -57,6 +57,7 @@ files:
|
|
|
57
57
|
- lib/patient_llm/halt_error.rb
|
|
58
58
|
- lib/patient_llm/max_tool_iterations_error.rb
|
|
59
59
|
- lib/patient_llm/presets.rb
|
|
60
|
+
- lib/patient_llm/request_preview.rb
|
|
60
61
|
- lib/patient_llm/schema.rb
|
|
61
62
|
- lib/patient_llm/structured_output_error.rb
|
|
62
63
|
- patient_llm.gemspec
|