nitro_intelligence 3.1.0 → 4.1.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/Rakefile +21 -1
  4. data/docs/ASSISTANTS.md +594 -0
  5. data/docs/CHANGELOG.md +243 -0
  6. data/docs/README.md +190 -12
  7. data/lib/nitro_intelligence/assistant.rb +82 -3
  8. data/lib/nitro_intelligence/assistant_registry.rb +18 -0
  9. data/lib/nitro_intelligence/assistants.rb +340 -102
  10. data/lib/nitro_intelligence/client/base.rb +88 -8
  11. data/lib/nitro_intelligence/client/client.rb +22 -2
  12. data/lib/nitro_intelligence/client/factory.rb +12 -3
  13. data/lib/nitro_intelligence/client/handlers/audio_transcription_handler.rb +3 -1
  14. data/lib/nitro_intelligence/client/handlers/base_handler.rb +17 -2
  15. data/lib/nitro_intelligence/client/handlers/chat_handler.rb +3 -1
  16. data/lib/nitro_intelligence/client/handlers/decision_handler.rb +75 -0
  17. data/lib/nitro_intelligence/client/handlers/image_handler.rb +6 -2
  18. data/lib/nitro_intelligence/client/handlers/observed/audio_transcription_handler.rb +30 -12
  19. data/lib/nitro_intelligence/client/handlers/observed/chat_handler.rb +16 -3
  20. data/lib/nitro_intelligence/client/handlers/observed/decision_handler.rb +72 -0
  21. data/lib/nitro_intelligence/client/handlers/observed/image_handler.rb +20 -5
  22. data/lib/nitro_intelligence/client/handlers/observed/text_to_speech_handler.rb +27 -9
  23. data/lib/nitro_intelligence/client/handlers/text_to_speech_handler.rb +3 -1
  24. data/lib/nitro_intelligence/client/observed.rb +8 -0
  25. data/lib/nitro_intelligence/client/observers/langfuse_observer.rb +35 -7
  26. data/lib/nitro_intelligence/configuration.rb +48 -0
  27. data/lib/nitro_intelligence/decision.rb +105 -0
  28. data/lib/nitro_intelligence/deprecator.rb +10 -0
  29. data/lib/nitro_intelligence/langfuse_extension.rb +1 -0
  30. data/lib/nitro_intelligence/langfuse_tracer_provider.rb +7 -6
  31. data/lib/nitro_intelligence/media/audio.rb +6 -0
  32. data/lib/nitro_intelligence/media/image.rb +14 -1
  33. data/lib/nitro_intelligence/media/image_generation.rb +14 -2
  34. data/lib/nitro_intelligence/media/media.rb +4 -0
  35. data/lib/nitro_intelligence/models/model.rb +7 -0
  36. data/lib/nitro_intelligence/models/model_catalog.rb +3 -0
  37. data/lib/nitro_intelligence/models/model_factory.rb +2 -0
  38. data/lib/nitro_intelligence/null_cache.rb +2 -0
  39. data/lib/nitro_intelligence/observability/project.rb +41 -2
  40. data/lib/nitro_intelligence/observability/project_client.rb +10 -1
  41. data/lib/nitro_intelligence/observability/project_client_registry.rb +18 -0
  42. data/lib/nitro_intelligence/observability/prompt.rb +4 -3
  43. data/lib/nitro_intelligence/observability/prompt_resolver.rb +2 -0
  44. data/lib/nitro_intelligence/observability/prompt_store.rb +9 -0
  45. data/lib/nitro_intelligence/observability/upload_handler.rb +3 -1
  46. data/lib/nitro_intelligence/pending_review.rb +257 -0
  47. data/lib/nitro_intelligence/railtie.rb +10 -0
  48. data/lib/nitro_intelligence/reporter.rb +29 -0
  49. data/lib/nitro_intelligence/review_decision.rb +36 -0
  50. data/lib/nitro_intelligence/run_result.rb +160 -0
  51. data/lib/nitro_intelligence/tool_call_review_interrupt.rb +9 -13
  52. data/lib/nitro_intelligence/tool_call_review_validator.rb +6 -8
  53. data/lib/nitro_intelligence/trace.rb +8 -0
  54. data/lib/nitro_intelligence/version.rb +2 -1
  55. data/lib/nitro_intelligence.rb +40 -0
  56. metadata +12 -1
@@ -7,26 +7,43 @@ module NitroIntelligence
7
7
  # Credentials are supplied by the host. Where they come from is the host's business -- an
8
8
  # environment variable its deployment mounts, a secrets store, a literal in configuration --
9
9
  # so nothing here encodes one deployment's wiring.
10
+ #
11
+ # @example
12
+ # assistant = NitroIntelligence.assistants["candidate-concierge"]
13
+ # result = assistant.run(thread_id:, messages:)
10
14
  class Assistant
15
+ # Raised when an assistant's entry lacks its `api_key` or `assistant_id`, naming each one
16
+ # missing.
11
17
  class ConfigurationError < StandardError; end
12
18
 
19
+ # @api private
13
20
  DEFAULT_USER_ID = Assistants::DEFAULT_USER_ID
14
21
 
22
+ # @api private
15
23
  # `base_url` is not among them: the client defaults it, so it cannot be missing.
16
24
  REQUIRED = %w[api_key assistant_id].freeze
17
25
 
18
26
  # The key an assistant is filed and looked up under. Not its name: an entry usually carries
19
27
  # a `name` of its own, a human-readable label for the assistant's record, and the two are
20
28
  # different things.
29
+ #
30
+ # @return [String]
21
31
  attr_reader :key
22
32
 
23
- attr_reader :assistant_id, :base_url, :user_id
33
+ # @return [String] the assistant's id in Assistants
34
+ attr_reader :assistant_id
35
+ # @return [String] the Assistants deployment that serves it
36
+ attr_reader :base_url
37
+ # @return [String] the user its threads are created for
38
+ attr_reader :user_id
24
39
 
25
40
  # The key is positional so that splatting an entry cannot overwrite it, whatever the entry
26
41
  # happens to carry.
27
42
  #
28
43
  # Extra keys are accepted and ignored for the same reason: an entry carries fields the
29
44
  # application has no use for, such as the graph or the observability project it reports to.
45
+ #
46
+ # @api private
30
47
  def initialize(key, base_url: nil, api_key: nil, assistant_id: nil, user_id: nil, **_kwargs)
31
48
  @key = key.to_s
32
49
  @base_url = base_url.presence || Assistants::DEFAULT_BASE_URL
@@ -37,24 +54,86 @@ module NitroIntelligence
37
54
  validate!
38
55
  end
39
56
 
57
+ # The client the assistant's calls go through, for anything this class does not expose.
58
+ #
59
+ # @return [Assistants]
40
60
  def client
41
61
  @client ||= Assistants.new(base_url: @base_url, api_key: @api_key, user_id: @user_id)
42
62
  end
43
63
 
44
- # The two calls that identify an assistant take it from here rather than from the caller.
64
+ # The calls that identify an assistant take it from here rather than from the caller.
45
65
  # Everything else is thread-scoped and delegates untouched.
66
+ #
67
+ # {Assistants#run} for this assistant.
68
+ #
69
+ # @param thread_id [String]
70
+ # @param messages [Array<Hash>]
71
+ # @param kwargs [Hash] the rest of {Assistants#run}'s arguments, except `assistant_id`
72
+ # @return [RunResult]
73
+ # @raise [ArgumentError] when given an `assistant_id`
74
+ # @raise (see Assistants#run)
75
+ def run(thread_id:, messages:, **kwargs)
76
+ reject_assistant_id!(kwargs)
77
+ client.run(thread_id:, assistant_id:, messages:, **kwargs)
78
+ end
79
+
80
+ # {Assistants#await_run} for this assistant.
81
+ #
82
+ # @deprecated Use {#run}`(...).reply`. Removed in 5.0.
83
+ # @param (see #run)
84
+ # @return [String, nil]
85
+ # @raise (see #run)
46
86
  def await_run(thread_id:, messages:, **kwargs)
47
87
  reject_assistant_id!(kwargs)
48
88
  client.await_run(thread_id:, assistant_id:, messages:, **kwargs)
49
89
  end
50
90
 
91
+ # {Assistants#review} for this assistant.
92
+ #
93
+ # @param thread_id [String]
94
+ # @param kwargs [Hash] the rest of {Assistants#review}'s arguments, except `assistant_id`
95
+ # @return [RunResult]
96
+ # @raise [ArgumentError] when given an `assistant_id`
97
+ # @raise (see Assistants#review)
98
+ def review(thread_id:, **kwargs)
99
+ reject_assistant_id!(kwargs)
100
+ client.review(thread_id:, assistant_id:, **kwargs)
101
+ end
102
+
103
+ # {Assistants#review_tool_calls} for this assistant.
104
+ #
105
+ # @deprecated Use {#review}`(tool_calls:, reviewer_id:, interrupt_id:)`. Removed in 5.0.
106
+ # @param thread_id [String]
107
+ # @param tool_calls [Hash, Array<Hash>]
108
+ # @param kwargs [Hash] the rest of {Assistants#review_tool_calls}'s arguments, except
109
+ # `assistant_id`
110
+ # @return [nil]
111
+ # @raise [ArgumentError] when given an `assistant_id`
112
+ # @raise (see Assistants#review_tool_calls)
51
113
  def review_tool_calls(thread_id:, tool_calls:, **kwargs)
52
114
  reject_assistant_id!(kwargs)
53
115
  client.review_tool_calls(thread_id:, assistant_id:, tool_calls:, **kwargs)
54
116
  end
55
117
 
118
+ # @!method thread_state(thread_id:)
119
+ # {Assistants#thread_state}.
120
+ # @return (see Assistants#thread_state)
121
+ # @!method thread_messages(thread_id:)
122
+ # {Assistants#thread_messages}.
123
+ # @return (see Assistants#thread_messages)
124
+ # @!method tool_calls_pending_review(thread_id:)
125
+ # {Assistants#tool_calls_pending_review}.
126
+ # @deprecated (see Assistants#tool_calls_pending_review)
127
+ # @return (see Assistants#tool_calls_pending_review)
128
+ # @!method tool_calls_under_review(thread_id:)
129
+ # {Assistants#tool_calls_under_review}.
130
+ # @deprecated (see Assistants#tool_calls_under_review)
131
+ # @return (see Assistants#tool_calls_under_review)
132
+ # @!method under_review(thread_id:)
133
+ # {Assistants#under_review}.
134
+ # @return (see Assistants#under_review)
56
135
  delegate :thread_state, :thread_messages, :tool_calls_pending_review, :tool_calls_under_review,
57
- to: :client
136
+ :under_review, to: :client
58
137
 
59
138
  private
60
139
 
@@ -17,29 +17,47 @@ module NitroIntelligence
17
17
  # },
18
18
  # }
19
19
  class AssistantRegistry
20
+ # Raised looking up a key `definitions` does not configure, listing the ones it does.
20
21
  class UnknownAssistantError < StandardError; end
21
22
 
23
+ # @api private
22
24
  DEFINITIONS_KEY = "definitions".freeze
25
+ # @api private
23
26
  SHARED_KEYS = %w[base_url user_id].freeze
24
27
 
28
+ # @api private
25
29
  def initialize(config = {})
26
30
  @config = config.to_h.deep_stringify_keys
27
31
  @assistants = {}
28
32
  end
29
33
 
34
+ # The assistant configured under `key`.
35
+ #
36
+ # @param key [String, Symbol]
37
+ # @return [Assistant]
38
+ # @raise [UnknownAssistantError] when `definitions` has no entry for `key`
39
+ # @raise [Assistant::ConfigurationError] when the entry lacks its `api_key` or `assistant_id`
30
40
  def [](key)
31
41
  fetch(key)
32
42
  end
33
43
 
44
+ # @param (see #[])
45
+ # @return (see #[])
46
+ # @raise (see #[])
34
47
  def fetch(key)
35
48
  key = key.to_s
36
49
  @assistants[key] ||= build(key)
37
50
  end
38
51
 
52
+ # Whether `definitions` has an entry for `key`.
53
+ #
54
+ # @param key [String, Symbol]
55
+ # @return [Boolean]
39
56
  def key?(key)
40
57
  definitions.key?(key.to_s)
41
58
  end
42
59
 
60
+ # @return [Array<String>] the keys `definitions` configures
43
61
  def keys
44
62
  definitions.keys
45
63
  end