smith-agents 0.4.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 (115) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +139 -0
  3. data/CODE_OF_CONDUCT.md +128 -0
  4. data/LICENSE +21 -0
  5. data/README.md +226 -0
  6. data/Rakefile +14 -0
  7. data/UPSTREAM_PROPOSAL.md +141 -0
  8. data/docs/CONFIGURATION.md +123 -0
  9. data/docs/PATTERNS.md +492 -0
  10. data/docs/PERSISTENCE.md +169 -0
  11. data/docs/TOOLS_AND_GUARDRAILS.md +140 -0
  12. data/docs/workflow_claim.md +58 -0
  13. data/exe/smith +7 -0
  14. data/lib/generators/smith/install/install_generator.rb +22 -0
  15. data/lib/generators/smith/install/templates/smith.rb.tt +44 -0
  16. data/lib/smith/agent/lifecycle.rb +264 -0
  17. data/lib/smith/agent/registry.rb +128 -0
  18. data/lib/smith/agent.rb +259 -0
  19. data/lib/smith/artifacts/file.rb +59 -0
  20. data/lib/smith/artifacts/memory.rb +75 -0
  21. data/lib/smith/artifacts/scoped_store.rb +29 -0
  22. data/lib/smith/artifacts.rb +5 -0
  23. data/lib/smith/budget/ledger.rb +42 -0
  24. data/lib/smith/budget.rb +5 -0
  25. data/lib/smith/cli.rb +82 -0
  26. data/lib/smith/context/observation_masking.rb +19 -0
  27. data/lib/smith/context/session.rb +42 -0
  28. data/lib/smith/context/state_injection.rb +24 -0
  29. data/lib/smith/context.rb +61 -0
  30. data/lib/smith/doctor/check.rb +12 -0
  31. data/lib/smith/doctor/checks/baseline.rb +84 -0
  32. data/lib/smith/doctor/checks/configuration.rb +56 -0
  33. data/lib/smith/doctor/checks/durability.rb +103 -0
  34. data/lib/smith/doctor/checks/live.rb +55 -0
  35. data/lib/smith/doctor/checks/models_registry.rb +66 -0
  36. data/lib/smith/doctor/checks/openai_api_mode.rb +51 -0
  37. data/lib/smith/doctor/checks/persistence.rb +99 -0
  38. data/lib/smith/doctor/checks/persistence_capabilities.rb +60 -0
  39. data/lib/smith/doctor/checks/persistence_registry.rb +82 -0
  40. data/lib/smith/doctor/checks/rails.rb +39 -0
  41. data/lib/smith/doctor/checks/serialization.rb +78 -0
  42. data/lib/smith/doctor/installer.rb +103 -0
  43. data/lib/smith/doctor/printer.rb +62 -0
  44. data/lib/smith/doctor/report.rb +39 -0
  45. data/lib/smith/doctor.rb +53 -0
  46. data/lib/smith/errors.rb +191 -0
  47. data/lib/smith/event.rb +11 -0
  48. data/lib/smith/events/.keep +0 -0
  49. data/lib/smith/events/bus.rb +60 -0
  50. data/lib/smith/events/step_completed.rb +11 -0
  51. data/lib/smith/events/subscription.rb +24 -0
  52. data/lib/smith/events.rb +5 -0
  53. data/lib/smith/guardrails/runner.rb +44 -0
  54. data/lib/smith/guardrails/url_verifier.rb +7 -0
  55. data/lib/smith/guardrails.rb +35 -0
  56. data/lib/smith/models/inference.rb +199 -0
  57. data/lib/smith/models/normalizer.rb +186 -0
  58. data/lib/smith/models/profile.rb +39 -0
  59. data/lib/smith/models.rb +132 -0
  60. data/lib/smith/persistence_adapters/active_record_store.rb +99 -0
  61. data/lib/smith/persistence_adapters/cache_store.rb +79 -0
  62. data/lib/smith/persistence_adapters/memory.rb +105 -0
  63. data/lib/smith/persistence_adapters/rails_cache.rb +20 -0
  64. data/lib/smith/persistence_adapters/redis_store.rb +136 -0
  65. data/lib/smith/persistence_adapters/retry.rb +42 -0
  66. data/lib/smith/persistence_adapters.rb +112 -0
  67. data/lib/smith/pricing.rb +65 -0
  68. data/lib/smith/providers/openai/responses.rb +315 -0
  69. data/lib/smith/providers/openai/routing.rb +67 -0
  70. data/lib/smith/providers/openai/tools_extensions.rb +106 -0
  71. data/lib/smith/railtie.rb +9 -0
  72. data/lib/smith/tasks/doctor.rake +38 -0
  73. data/lib/smith/tool/budget_enforcement.rb +33 -0
  74. data/lib/smith/tool/capability_builder.rb +18 -0
  75. data/lib/smith/tool/capture.rb +22 -0
  76. data/lib/smith/tool/compatibility.rb +72 -0
  77. data/lib/smith/tool/policy.rb +40 -0
  78. data/lib/smith/tool.rb +171 -0
  79. data/lib/smith/tools/think.rb +25 -0
  80. data/lib/smith/tools/url_fetcher.rb +16 -0
  81. data/lib/smith/tools/web_search.rb +17 -0
  82. data/lib/smith/tools.rb +5 -0
  83. data/lib/smith/trace/logger.rb +46 -0
  84. data/lib/smith/trace/memory.rb +53 -0
  85. data/lib/smith/trace/open_telemetry.rb +57 -0
  86. data/lib/smith/trace.rb +89 -0
  87. data/lib/smith/types.rb +16 -0
  88. data/lib/smith/version.rb +5 -0
  89. data/lib/smith/workflow/artifact_integration.rb +41 -0
  90. data/lib/smith/workflow/budget_integration.rb +105 -0
  91. data/lib/smith/workflow/claim.rb +118 -0
  92. data/lib/smith/workflow/data_volume_policy.rb +36 -0
  93. data/lib/smith/workflow/deadline_enforcement.rb +100 -0
  94. data/lib/smith/workflow/deterministic_execution.rb +53 -0
  95. data/lib/smith/workflow/deterministic_step.rb +57 -0
  96. data/lib/smith/workflow/dsl.rb +223 -0
  97. data/lib/smith/workflow/durability.rb +369 -0
  98. data/lib/smith/workflow/evaluator_optimizer.rb +220 -0
  99. data/lib/smith/workflow/event_integration.rb +24 -0
  100. data/lib/smith/workflow/execution.rb +127 -0
  101. data/lib/smith/workflow/execution_frame.rb +166 -0
  102. data/lib/smith/workflow/guardrail_integration.rb +40 -0
  103. data/lib/smith/workflow/nested_execution.rb +69 -0
  104. data/lib/smith/workflow/orchestrator_worker.rb +145 -0
  105. data/lib/smith/workflow/parallel.rb +50 -0
  106. data/lib/smith/workflow/parallel_execution.rb +75 -0
  107. data/lib/smith/workflow/persistence.rb +358 -0
  108. data/lib/smith/workflow/pipeline.rb +117 -0
  109. data/lib/smith/workflow/router.rb +53 -0
  110. data/lib/smith/workflow/transition.rb +208 -0
  111. data/lib/smith/workflow.rb +555 -0
  112. data/lib/smith.rb +254 -0
  113. data/script/profile_tool_results.rb +94 -0
  114. data/sig/smith.rbs +4 -0
  115. metadata +258 -0
data/lib/smith.rb ADDED
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-configurable"
4
+
5
+ require_relative "smith/version"
6
+
7
+ module Smith
8
+ class Error < StandardError; end
9
+
10
+ extend Dry::Configurable
11
+
12
+ # Artifact store (§4.7)
13
+ setting :artifact_store
14
+ setting :artifact_retention
15
+ setting :artifact_encryption, default: :none
16
+ setting :artifact_tenant_isolation, default: false
17
+
18
+ # Trace adapters (§4.8)
19
+ setting :trace_adapter
20
+ setting :trace_transitions, default: true
21
+ setting :trace_tool_calls, default: true
22
+ setting :trace_token_usage, default: true
23
+ setting :trace_cost, default: true
24
+ setting :trace_fields
25
+ setting :trace_content, default: false
26
+ setting :trace_retention
27
+ setting :trace_tenant_isolation, default: false
28
+
29
+ # Pricing (§4.5 — model-call cost computation)
30
+ setting :pricing, default: nil
31
+
32
+ # Persistence adapter for host durability verification (§doctor)
33
+ setting :persistence_adapter, default: nil
34
+ setting :persistence_options, default: {}.freeze
35
+
36
+ # Persistence TTL in Integer seconds. nil (default) means workflows
37
+ # persist indefinitely. Adapters that natively support TTL (Redis,
38
+ # CacheStore, Memory) pass this through; ActiveRecordStore TTL is
39
+ # deferred (would need an `expires_at` column + sweeper).
40
+ # Per-workflow `Workflow.persistence_ttl 1.day.to_i` DSL overrides this.
41
+ setting :persistence_ttl, default: nil
42
+
43
+ # Retry policy for transient persistence I/O failures.
44
+ # attempts: total attempts (including the first)
45
+ # base_delay: initial sleep between attempts, doubled each retry
46
+ # max_delay: cap on per-retry sleep
47
+ setting :persistence_retry_policy, default: { attempts: 3, base_delay: 0.1, max_delay: 1.0 }
48
+
49
+ # Test isolation: when true AND persistence_adapter is nil, Smith
50
+ # auto-selects the in-process Memory adapter. Lets specs avoid wiring
51
+ # Redis/Rails.cache in spec_helper.rb.
52
+ setting :test_mode, default: false
53
+
54
+ # RubyLLM model registry mode: nil/:bundled (default) or :database (§doctor)
55
+ setting :ruby_llm_model_registry, default: nil
56
+
57
+ # OpenAI API mode controls Smith's vendored /v1/responses routing
58
+ # for gpt-5 family + tools + reasoning_effort. :auto routes
59
+ # automatically when the combo is detected; :off disables routing
60
+ # (Smith's normalizer falls back to dropping incompatible tools).
61
+ #
62
+ # Default :auto reflects the "use both when possible" design intent.
63
+ # Smith ships the Responses adapter vendored from crmne/ruby_llm PR #770
64
+ # at a pinned SHA, so the routing path is operational for sync
65
+ # completions. Streaming over /v1/responses is not yet supported and
66
+ # raises NotImplementedError; hosts who need streaming with the
67
+ # (gpt-5 + tools + thinking) combo should set openai_api_mode = :off
68
+ # for graceful tool-dropping via chat-completions.
69
+ setting :openai_api_mode, default: :auto, constructor: lambda { |value|
70
+ unless %i[off auto].include?(value)
71
+ raise ArgumentError, "Smith.config.openai_api_mode must be :off or :auto, got #{value.inspect}"
72
+ end
73
+ value
74
+ }
75
+
76
+ # Trace gating for normalizer decision events. Hosts can opt out
77
+ # of the per-mutation event stream (the normalizer can emit several
78
+ # events per chat construction if multiple capabilities translate).
79
+ setting :trace_normalizer, default: true
80
+
81
+ # Logger (§7 — Ruby Logger, not Rails.logger)
82
+ setting :logger, default: nil
83
+
84
+ def self.artifacts
85
+ scoped_artifacts || config.artifact_store || (@_default_artifacts ||= Artifacts::Memory.new)
86
+ end
87
+
88
+ def self.artifacts=(store)
89
+ config.artifact_store = store
90
+ end
91
+
92
+ def self.scoped_artifacts
93
+ Thread.current[:smith_scoped_artifacts]
94
+ end
95
+
96
+ def self.scoped_artifacts=(store)
97
+ Thread.current[:smith_scoped_artifacts] = store
98
+ end
99
+
100
+ def self.persistence_adapter
101
+ raw_adapter = config.persistence_adapter
102
+ raw_options = config.persistence_options || {}
103
+ signature = persistence_signature(raw_adapter, raw_options, config.test_mode)
104
+
105
+ if defined?(@_persistence_adapter_signature) && @_persistence_adapter_signature == signature
106
+ return @_persistence_adapter
107
+ end
108
+
109
+ @_persistence_adapter_signature = signature
110
+ @_persistence_adapter = resolve_persistence_adapter(raw_adapter, raw_options)
111
+ end
112
+
113
+ # Test isolation auto-detect: when no adapter is configured AND
114
+ # test_mode is on, fall back to the in-process Memory adapter so spec
115
+ # suites don't need to wire Redis/Rails.cache in spec_helper.rb.
116
+ # Explicit adapter config always wins over this auto-detect.
117
+ def self.resolve_persistence_adapter(raw_adapter, raw_options)
118
+ return PersistenceAdapters.resolve(raw_adapter, **raw_options) if raw_adapter
119
+ return PersistenceAdapters::Memory.new if config.test_mode
120
+
121
+ nil
122
+ end
123
+ private_class_method :resolve_persistence_adapter
124
+
125
+ def self.persistence_signature(adapter, options, test_mode)
126
+ [snapshot_value(adapter), snapshot_value(options), test_mode]
127
+ end
128
+ private_class_method :persistence_signature
129
+
130
+ def self.snapshot_value(value)
131
+ case value
132
+ when Hash
133
+ value.each_with_object({}) do |(key, nested), copy|
134
+ copy[snapshot_value(key)] = snapshot_value(nested)
135
+ end.freeze
136
+ when Array
137
+ value.map { |nested| snapshot_value(nested) }.freeze
138
+ when String
139
+ value.dup.freeze
140
+ else
141
+ value
142
+ end
143
+ end
144
+ private_class_method :snapshot_value
145
+ end
146
+
147
+ # Leaf modules (no internal dependencies)
148
+ require_relative "smith/types"
149
+ require_relative "smith/errors"
150
+
151
+ # Event system (depends on Types)
152
+ require_relative "smith/event"
153
+ require_relative "smith/events"
154
+ require_relative "smith/events/subscription"
155
+ require_relative "smith/events/bus"
156
+ require_relative "smith/events/step_completed"
157
+
158
+ # Budget (depends on Errors)
159
+ require_relative "smith/budget"
160
+ require_relative "smith/budget/ledger"
161
+
162
+ # Pricing (depends on Smith config)
163
+ require_relative "smith/pricing"
164
+
165
+ # Model capability registry + pattern-based inference (depends on Errors).
166
+ # Smith ships NO specific model_id declarations. Inference rules describe
167
+ # PROVIDER FAMILIES (Anthropic Opus 4.7+ adaptive, gpt-5 family
168
+ # responses-route, Gemini 2.5+ budget_tokens). Applications register
169
+ # Smith::Models.register(Profile.new(...)) overrides only for custom
170
+ # models. Loaded BEFORE Tool so Tools that declare `compatible_with` can
171
+ # resolve capability semantics, AND before Agent so the chat override
172
+ # can call Smith::Models.find_or_infer on first construction.
173
+ require_relative "smith/models/profile"
174
+ require_relative "smith/models"
175
+ require_relative "smith/models/inference"
176
+ require_relative "smith/models/normalizer"
177
+
178
+ # OpenAI /v1/responses routing prepend. Dormant until
179
+ # Smith.config.openai_api_mode = :auto (default :off). Full
180
+ # payload assembly (Smith::Providers::OpenAI::Responses) and tool
181
+ # format helpers (Smith::Providers::OpenAI::ToolsExtensions) are
182
+ # vendored from crmne/ruby_llm PR #770 at pinned SHA. They retire when
183
+ # the PR merges upstream (Smith bumps the ruby_llm dep + deletes the
184
+ # vendored files). The require order must keep the helpers (ToolsExtensions)
185
+ # loaded BEFORE Responses since Responses calls into ToolsExtensions,
186
+ # and BOTH must load before Routing since Routing dispatches to
187
+ # Responses.complete via `defined?(...)` guard.
188
+ require_relative "smith/providers/openai/tools_extensions"
189
+ require_relative "smith/providers/openai/responses"
190
+ require_relative "smith/providers/openai/routing"
191
+
192
+ # Trace adapters (no internal deps)
193
+ require_relative "smith/trace"
194
+ require_relative "smith/trace/memory"
195
+ require_relative "smith/trace/logger"
196
+ require_relative "smith/trace/open_telemetry"
197
+
198
+ # Artifact store (no internal deps)
199
+ require_relative "smith/artifacts"
200
+ require_relative "smith/artifacts/memory"
201
+ require_relative "smith/artifacts/file"
202
+ require_relative "smith/artifacts/scoped_store"
203
+
204
+ # Host persistence adapters (no internal deps)
205
+ require_relative "smith/persistence_adapters"
206
+
207
+ # Tool (depends on RubyLLM::Tool)
208
+ require_relative "smith/tool"
209
+ require_relative "smith/tools"
210
+ require_relative "smith/tools/web_search"
211
+ require_relative "smith/tools/url_fetcher"
212
+ require_relative "smith/tools/think"
213
+
214
+ # Guardrails and Context (no internal deps)
215
+ require_relative "smith/guardrails"
216
+ require_relative "smith/guardrails/runner"
217
+ require_relative "smith/guardrails/url_verifier"
218
+ require_relative "smith/context"
219
+ require_relative "smith/context/observation_masking"
220
+ require_relative "smith/context/state_injection"
221
+ require_relative "smith/context/session"
222
+
223
+ # Agent (depends on RubyLLM::Agent)
224
+ require_relative "smith/agent"
225
+ require_relative "smith/agent/lifecycle"
226
+ require_relative "smith/agent/registry"
227
+
228
+ # Workflow (Transition, DSL, Persistence, and Execution must load before Workflow)
229
+ require_relative "smith/workflow/transition"
230
+ require_relative "smith/workflow/dsl"
231
+ require_relative "smith/workflow/persistence"
232
+ require_relative "smith/workflow/durability"
233
+ require_relative "smith/workflow/guardrail_integration"
234
+ require_relative "smith/workflow/budget_integration"
235
+ require_relative "smith/workflow/event_integration"
236
+ require_relative "smith/workflow/artifact_integration"
237
+ require_relative "smith/workflow/data_volume_policy"
238
+ require_relative "smith/workflow/deadline_enforcement"
239
+ require_relative "smith/workflow/nested_execution"
240
+ require_relative "smith/workflow/evaluator_optimizer"
241
+ require_relative "smith/workflow/orchestrator_worker"
242
+ require_relative "smith/workflow/parallel_execution"
243
+ require_relative "smith/workflow/deterministic_step"
244
+ require_relative "smith/workflow/deterministic_execution"
245
+ require_relative "smith/workflow/execution"
246
+ require_relative "smith/workflow"
247
+ require_relative "smith/workflow/claim"
248
+ require_relative "smith/workflow/execution_frame"
249
+ require_relative "smith/workflow/pipeline"
250
+ require_relative "smith/workflow/router"
251
+ require_relative "smith/workflow/parallel"
252
+
253
+ # Conditional Rails integration
254
+ require_relative "smith/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Usage: bundle exec ruby script/profile_tool_results.rb
5
+ #
6
+ # Profiles tool_results handling at various scales:
7
+ # - snapshot cost (build_run_result deep copy)
8
+ # - JSON persistence round-trip (serialize + restore)
9
+ # - parallel collector contention
10
+
11
+ require "smith"
12
+ require "json"
13
+
14
+ def measure
15
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
16
+ yield
17
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
18
+ end
19
+
20
+ def build_workflow_with_entries(count, payload_size: 100)
21
+ klass = Class.new(Smith::Workflow) do
22
+ initial_state :idle
23
+ state :done
24
+ transition :finish, from: :idle, to: :done
25
+ end
26
+
27
+ workflow = klass.new
28
+ payload = { "data" => "x" * payload_size, "urls" => Array.new(5) { "https://example.com/#{_1}" } }
29
+ count.times { |i| workflow.instance_variable_get(:@tool_results) << { tool: "tool_#{i}", captured: payload.dup } }
30
+ [klass, workflow]
31
+ end
32
+
33
+ puts "=" * 70
34
+ puts "Smith tool_results Performance Profile"
35
+ puts "=" * 70
36
+
37
+ # 1. Snapshot cost
38
+ puts "\n--- Snapshot Cost (build_run_result deep copy) ---"
39
+ [100, 1_000, 5_000].each do |count|
40
+ _klass, workflow = build_workflow_with_entries(count)
41
+
42
+ before_gc = GC.stat[:total_allocated_objects]
43
+ time = measure { workflow.run! }
44
+ after_gc = GC.stat[:total_allocated_objects]
45
+
46
+ printf " %5d entries: %.4fs, ~%d allocations\n", count, time, (after_gc - before_gc)
47
+ end
48
+
49
+ # 2. JSON persistence round-trip
50
+ puts "\n--- JSON Persistence Round-Trip ---"
51
+ json = nil
52
+ [100, 1_000, 5_000].each do |count|
53
+ klass, workflow = build_workflow_with_entries(count)
54
+
55
+ serialize_time = measure { json = JSON.generate(workflow.to_state) }
56
+ restore_time = measure { klass.from_state(JSON.parse(json)) }
57
+
58
+ printf " %5d entries: serialize=%.4fs restore=%.4fs json_bytes=%d\n",
59
+ count, serialize_time, restore_time, json.bytesize
60
+ end
61
+
62
+ # 3. Parallel collector contention
63
+ puts "\n--- Parallel Collector Contention ---"
64
+ [10, 50, 100].each do |branch_count|
65
+ klass = Class.new(Smith::Workflow) do
66
+ initial_state :idle
67
+ state :done
68
+ transition :finish, from: :idle, to: :done
69
+ end
70
+
71
+ workflow = klass.new
72
+ collector = workflow.send(:tool_result_collector)
73
+ threads = []
74
+
75
+ time = measure do
76
+ branch_count.times do |i|
77
+ threads << Thread.new do
78
+ 5.times do |j|
79
+ collector.call({ tool: "branch_#{i}_call_#{j}", captured: { index: i, call: j } })
80
+ end
81
+ end
82
+ end
83
+ threads.each(&:join)
84
+ end
85
+
86
+ total = workflow.instance_variable_get(:@tool_results).length
87
+ expected = branch_count * 5
88
+
89
+ status = total == expected ? "OK" : "LOSS (#{expected - total} missing)"
90
+ printf " %3d branches x 5 calls: %.4fs, %d/%d entries [%s]\n",
91
+ branch_count, time, total, expected, status
92
+ end
93
+
94
+ puts "\n#{"=" * 70}\nDone."
data/sig/smith.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Smith
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,258 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smith-agents
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Ralak
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ruby_llm
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.15'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.15'
26
+ - !ruby/object:Gem::Dependency
27
+ name: dry-types
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.7'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.7'
40
+ - !ruby/object:Gem::Dependency
41
+ name: dry-struct
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.6'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ - !ruby/object:Gem::Dependency
55
+ name: dry-initializer
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.1'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.1'
68
+ - !ruby/object:Gem::Dependency
69
+ name: dry-configurable
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: dry-container
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.11'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.11'
96
+ - !ruby/object:Gem::Dependency
97
+ name: concurrent-ruby
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.2'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.2'
110
+ description: Smith is a workflow-first multi-agent orchestration library built on
111
+ RubyLLM. It provides state machine modeling, typed contracts, budget enforcement,
112
+ guardrails, and observability for agent workflows.
113
+ email:
114
+ - thesamuelralak@gmail.com
115
+ executables:
116
+ - smith
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - CHANGELOG.md
121
+ - CODE_OF_CONDUCT.md
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - UPSTREAM_PROPOSAL.md
126
+ - docs/CONFIGURATION.md
127
+ - docs/PATTERNS.md
128
+ - docs/PERSISTENCE.md
129
+ - docs/TOOLS_AND_GUARDRAILS.md
130
+ - docs/workflow_claim.md
131
+ - exe/smith
132
+ - lib/generators/smith/install/install_generator.rb
133
+ - lib/generators/smith/install/templates/smith.rb.tt
134
+ - lib/smith.rb
135
+ - lib/smith/agent.rb
136
+ - lib/smith/agent/lifecycle.rb
137
+ - lib/smith/agent/registry.rb
138
+ - lib/smith/artifacts.rb
139
+ - lib/smith/artifacts/file.rb
140
+ - lib/smith/artifacts/memory.rb
141
+ - lib/smith/artifacts/scoped_store.rb
142
+ - lib/smith/budget.rb
143
+ - lib/smith/budget/ledger.rb
144
+ - lib/smith/cli.rb
145
+ - lib/smith/context.rb
146
+ - lib/smith/context/observation_masking.rb
147
+ - lib/smith/context/session.rb
148
+ - lib/smith/context/state_injection.rb
149
+ - lib/smith/doctor.rb
150
+ - lib/smith/doctor/check.rb
151
+ - lib/smith/doctor/checks/baseline.rb
152
+ - lib/smith/doctor/checks/configuration.rb
153
+ - lib/smith/doctor/checks/durability.rb
154
+ - lib/smith/doctor/checks/live.rb
155
+ - lib/smith/doctor/checks/models_registry.rb
156
+ - lib/smith/doctor/checks/openai_api_mode.rb
157
+ - lib/smith/doctor/checks/persistence.rb
158
+ - lib/smith/doctor/checks/persistence_capabilities.rb
159
+ - lib/smith/doctor/checks/persistence_registry.rb
160
+ - lib/smith/doctor/checks/rails.rb
161
+ - lib/smith/doctor/checks/serialization.rb
162
+ - lib/smith/doctor/installer.rb
163
+ - lib/smith/doctor/printer.rb
164
+ - lib/smith/doctor/report.rb
165
+ - lib/smith/errors.rb
166
+ - lib/smith/event.rb
167
+ - lib/smith/events.rb
168
+ - lib/smith/events/.keep
169
+ - lib/smith/events/bus.rb
170
+ - lib/smith/events/step_completed.rb
171
+ - lib/smith/events/subscription.rb
172
+ - lib/smith/guardrails.rb
173
+ - lib/smith/guardrails/runner.rb
174
+ - lib/smith/guardrails/url_verifier.rb
175
+ - lib/smith/models.rb
176
+ - lib/smith/models/inference.rb
177
+ - lib/smith/models/normalizer.rb
178
+ - lib/smith/models/profile.rb
179
+ - lib/smith/persistence_adapters.rb
180
+ - lib/smith/persistence_adapters/active_record_store.rb
181
+ - lib/smith/persistence_adapters/cache_store.rb
182
+ - lib/smith/persistence_adapters/memory.rb
183
+ - lib/smith/persistence_adapters/rails_cache.rb
184
+ - lib/smith/persistence_adapters/redis_store.rb
185
+ - lib/smith/persistence_adapters/retry.rb
186
+ - lib/smith/pricing.rb
187
+ - lib/smith/providers/openai/responses.rb
188
+ - lib/smith/providers/openai/routing.rb
189
+ - lib/smith/providers/openai/tools_extensions.rb
190
+ - lib/smith/railtie.rb
191
+ - lib/smith/tasks/doctor.rake
192
+ - lib/smith/tool.rb
193
+ - lib/smith/tool/budget_enforcement.rb
194
+ - lib/smith/tool/capability_builder.rb
195
+ - lib/smith/tool/capture.rb
196
+ - lib/smith/tool/compatibility.rb
197
+ - lib/smith/tool/policy.rb
198
+ - lib/smith/tools.rb
199
+ - lib/smith/tools/think.rb
200
+ - lib/smith/tools/url_fetcher.rb
201
+ - lib/smith/tools/web_search.rb
202
+ - lib/smith/trace.rb
203
+ - lib/smith/trace/logger.rb
204
+ - lib/smith/trace/memory.rb
205
+ - lib/smith/trace/open_telemetry.rb
206
+ - lib/smith/types.rb
207
+ - lib/smith/version.rb
208
+ - lib/smith/workflow.rb
209
+ - lib/smith/workflow/artifact_integration.rb
210
+ - lib/smith/workflow/budget_integration.rb
211
+ - lib/smith/workflow/claim.rb
212
+ - lib/smith/workflow/data_volume_policy.rb
213
+ - lib/smith/workflow/deadline_enforcement.rb
214
+ - lib/smith/workflow/deterministic_execution.rb
215
+ - lib/smith/workflow/deterministic_step.rb
216
+ - lib/smith/workflow/dsl.rb
217
+ - lib/smith/workflow/durability.rb
218
+ - lib/smith/workflow/evaluator_optimizer.rb
219
+ - lib/smith/workflow/event_integration.rb
220
+ - lib/smith/workflow/execution.rb
221
+ - lib/smith/workflow/execution_frame.rb
222
+ - lib/smith/workflow/guardrail_integration.rb
223
+ - lib/smith/workflow/nested_execution.rb
224
+ - lib/smith/workflow/orchestrator_worker.rb
225
+ - lib/smith/workflow/parallel.rb
226
+ - lib/smith/workflow/parallel_execution.rb
227
+ - lib/smith/workflow/persistence.rb
228
+ - lib/smith/workflow/pipeline.rb
229
+ - lib/smith/workflow/router.rb
230
+ - lib/smith/workflow/transition.rb
231
+ - script/profile_tool_results.rb
232
+ - sig/smith.rbs
233
+ homepage: https://github.com/samuelralak/smith
234
+ licenses:
235
+ - MIT
236
+ metadata:
237
+ source_code_uri: https://github.com/samuelralak/smith
238
+ changelog_uri: https://github.com/samuelralak/smith/blob/main/CHANGELOG.md
239
+ bug_tracker_uri: https://github.com/samuelralak/smith/issues
240
+ rubygems_mfa_required: 'true'
241
+ rdoc_options: []
242
+ require_paths:
243
+ - lib
244
+ required_ruby_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: 3.2.0
249
+ required_rubygems_version: !ruby/object:Gem::Requirement
250
+ requirements:
251
+ - - ">="
252
+ - !ruby/object:Gem::Version
253
+ version: '0'
254
+ requirements: []
255
+ rubygems_version: 4.0.3
256
+ specification_version: 4
257
+ summary: Workflow-first multi-agent orchestration for Ruby
258
+ test_files: []