riffer-rig 0.7.0 → 0.9.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +13 -3
  4. data/lib/riffer/rig/cli/flags.rb +16 -2
  5. data/lib/riffer/rig/cli.rb +2 -1
  6. data/lib/riffer/rig/commands/auth.rb +79 -0
  7. data/lib/riffer/rig/commands/model.rb +70 -21
  8. data/lib/riffer/rig/commands/reload.rb +23 -0
  9. data/lib/riffer/rig/credentials.rb +13 -1
  10. data/lib/riffer/rig/extension.rb +12 -0
  11. data/lib/riffer/rig/loader.rb +327 -23
  12. data/lib/riffer/rig/provider_setup.rb +36 -5
  13. data/lib/riffer/rig/providers.rb +48 -0
  14. data/lib/riffer/rig/registrar.rb +8 -0
  15. data/lib/riffer/rig/runtime.rb +110 -21
  16. data/lib/riffer/rig/sdk.rb +62 -0
  17. data/lib/riffer/rig/settings/document.rb +9 -1
  18. data/lib/riffer/rig/settings.rb +5 -4
  19. data/lib/riffer/rig/stores/jsonl.rb +115 -0
  20. data/lib/riffer/rig/stores/recorder.rb +119 -0
  21. data/lib/riffer/rig/terminal/renderer.rb +86 -13
  22. data/lib/riffer/rig/terminal/wrapper.rb +103 -0
  23. data/lib/riffer/rig/trust.rb +37 -0
  24. data/lib/riffer/rig/version.rb +1 -1
  25. data/lib/riffer/rig.rb +7 -1
  26. data/sig/generated/riffer/rig/cli/flags.rbs +5 -2
  27. data/sig/generated/riffer/rig/commands/auth.rbs +35 -0
  28. data/sig/generated/riffer/rig/commands/model.rbs +21 -9
  29. data/sig/generated/riffer/rig/commands/reload.rbs +12 -0
  30. data/sig/generated/riffer/rig/credentials.rbs +8 -0
  31. data/sig/generated/riffer/rig/extension.rbs +4 -0
  32. data/sig/generated/riffer/rig/loader.rbs +142 -5
  33. data/sig/generated/riffer/rig/provider_setup.rbs +15 -4
  34. data/sig/generated/riffer/rig/providers.rbs +28 -0
  35. data/sig/generated/riffer/rig/registrar.rbs +6 -0
  36. data/sig/generated/riffer/rig/runtime.rbs +63 -9
  37. data/sig/generated/riffer/rig/sdk.rbs +33 -0
  38. data/sig/generated/riffer/rig/settings/document.rbs +7 -1
  39. data/sig/generated/riffer/rig/settings.rbs +2 -3
  40. data/sig/generated/riffer/rig/stores/jsonl.rbs +64 -0
  41. data/sig/generated/riffer/rig/stores/recorder.rbs +67 -0
  42. data/sig/generated/riffer/rig/terminal/renderer.rbs +41 -1
  43. data/sig/generated/riffer/rig/terminal/wrapper.rbs +43 -0
  44. data/sig/generated/riffer/rig/trust.rbs +20 -0
  45. data/sig/generated/riffer/rig.rbs +4 -0
  46. data/sig/manual/riffer/rig/commands/auth.rbs +6 -0
  47. data/sig/manual/riffer/rig/commands/reload.rbs +6 -0
  48. data/sig/manual/riffer/rig/providers.rbs +6 -0
  49. data/sig/manual/riffer/rig/sdk.rbs +6 -0
  50. data/sig/manual/riffer/rig/stores.rbs +11 -0
  51. data/sig/manual/riffer/rig/trust.rbs +6 -0
  52. metadata +23 -29
@@ -4,11 +4,23 @@ class Riffer::Rig::Loader
4
4
  class ConfigurationError < StandardError
5
5
  end
6
6
 
7
- PROVIDER_LIST: String
7
+ # Raised by a strict load: the reload abandons instead of continuing.
8
+ class AbandonedError < StandardError
9
+ end
10
+
11
+ EXTENSION_FEATURE: String
12
+
13
+ @file_state: Hash[String, Time?]?
14
+
15
+ @gem_extensions: Array[Riffer::Rig::Extension]
16
+
17
+ @extensions_enabled: bool
18
+
19
+ @stripped: Array[Symbol]
8
20
 
9
- ONBOARDING_QUESTION: String
21
+ @tracked_files: Array[String]
10
22
 
11
- NO_MODEL: String
23
+ @store: Riffer::Rig::Stores::_Store | nil
12
24
 
13
25
  @riffer_config: Riffer::Config
14
26
 
@@ -20,6 +32,9 @@ class Riffer::Rig::Loader
20
32
 
21
33
  @cwd: String
22
34
 
35
+ # @dynamic tracked_files
36
+ attr_reader tracked_files: Array[String]
37
+
23
38
  # @rbs cwd: String
24
39
  # @rbs host: Riffer::Rig::Hosts::_Host
25
40
  # @rbs env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid
@@ -31,16 +46,18 @@ class Riffer::Rig::Loader
31
46
  # @rbs agents_md: bool
32
47
  # @rbs tools: Array[String]?
33
48
  # @rbs max_steps: Integer?
49
+ # @rbs store: Riffer::Rig::Stores::_Store | nil
34
50
  # @rbs return: Riffer::Rig::Runtime
35
- def self.runtime: (cwd: String, host: Riffer::Rig::Hosts::_Host, ?env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid, ?home: String, ?riffer_config: Riffer::Config, ?model: String?, ?extensions: bool, ?skills: bool, ?agents_md: bool, ?tools: Array[String]?, ?max_steps: Integer?) -> Riffer::Rig::Runtime
51
+ def self.runtime: (cwd: String, host: Riffer::Rig::Hosts::_Host, ?env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid, ?home: String, ?riffer_config: Riffer::Config, ?model: String?, ?extensions: bool, ?skills: bool, ?agents_md: bool, ?tools: Array[String]?, ?max_steps: Integer?, ?store: Riffer::Rig::Stores::_Store | nil) -> Riffer::Rig::Runtime
36
52
 
37
53
  # @rbs cwd: String
38
54
  # @rbs host: Riffer::Rig::Hosts::_Host
39
55
  # @rbs env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid
40
56
  # @rbs home: String
41
57
  # @rbs riffer_config: Riffer::Config
58
+ # @rbs store: Riffer::Rig::Stores::_Store | nil
42
59
  # @rbs return: void
43
- def initialize: (cwd: String, host: Riffer::Rig::Hosts::_Host, ?env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid, ?home: String, ?riffer_config: Riffer::Config) -> void
60
+ def initialize: (cwd: String, host: Riffer::Rig::Hosts::_Host, ?store: Riffer::Rig::Stores::_Store | nil, ?env: Riffer::Rig::Env | Riffer::Rig::Env::Invalid, ?home: String, ?riffer_config: Riffer::Config) -> void
44
61
 
45
62
  # @rbs model: String?
46
63
  # @rbs extensions: bool
@@ -51,8 +68,109 @@ class Riffer::Rig::Loader
51
68
  # @rbs return: Riffer::Rig::Runtime
52
69
  def runtime: (?model: String?, ?extensions: bool, ?skills: bool, ?agents_md: bool, ?tools: Array[String]?, ?max_steps: Integer?) -> Riffer::Rig::Runtime
53
70
 
71
+ # Without force, a no-op while the tracked file set and the two rig.rb paths
72
+ # look as the last discovery left them — the entry point the automatic
73
+ # trigger (#133) calls. The snapshot advances on every attempt, failed ones
74
+ # included, so a failure does not retry every request. Failures are notified
75
+ # once and reported as the message, the way Settings.rejection reports a
76
+ # rejection; the Runtime is the success value.
77
+ # @rbs runtime: Riffer::Rig::Runtime
78
+ # @rbs force: bool
79
+ # @rbs return: (Riffer::Rig::Runtime | String)
80
+ def reload: (Riffer::Rig::Runtime runtime, ?force: bool) -> (Riffer::Rig::Runtime | String)
81
+
54
82
  private
55
83
 
84
+ # @rbs return: Hash[Symbol, untyped]
85
+ def merged_settings: () -> Hash[Symbol, untyped]
86
+
87
+ # Notifies every failure once and reports its message; a rebuilt Runtime is
88
+ # the success value.
89
+ # @rbs runtime: Riffer::Rig::Runtime
90
+ # @rbs return: (Riffer::Rig::Runtime | String)
91
+ def perform_reload: (Riffer::Rig::Runtime runtime) -> (Riffer::Rig::Runtime | String)
92
+
93
+ # @rbs message: String
94
+ # @rbs return: String
95
+ def notify_failure: (String message) -> String
96
+
97
+ # @rbs document: Riffer::Rig::Settings::Document
98
+ # @rbs settings: Hash[Symbol, untyped]
99
+ # @rbs return: Array[Riffer::Rig::Extension]
100
+ def reload_extensions: (Riffer::Rig::Settings::Document document, Hash[Symbol, untyped] settings) -> Array[Riffer::Rig::Extension]
101
+
102
+ # @rbs return: Array[Riffer::Rig::Extension]
103
+ def rig_recordings: () -> Array[Riffer::Rig::Extension]
104
+
105
+ # @rbs path: String
106
+ # @rbs confirm_trust: bool
107
+ # @rbs return: Array[Riffer::Rig::Extension]
108
+ def load_rig_file: (String path, confirm_trust: bool) -> Array[Riffer::Rig::Extension]
109
+
110
+ # @rbs return: void
111
+ def scrub_tracked_features: () -> void
112
+
113
+ # Runs each extension against a throwaway registrar so that a failing block
114
+ # is skipped and reported instead of aborting the rebuild.
115
+ # @rbs extensions: Array[Riffer::Rig::Extension]
116
+ # @rbs settings: Hash[Symbol, untyped]
117
+ # @rbs return: Array[Riffer::Rig::Extension]
118
+ def validated: (Array[Riffer::Rig::Extension] extensions, Hash[Symbol, untyped] settings) -> Array[Riffer::Rig::Extension]
119
+
120
+ # @rbs runtime: Riffer::Rig::Runtime
121
+ # @rbs return: String?
122
+ def reload_credentials: (Riffer::Rig::Runtime runtime) -> String?
123
+
124
+ # @rbs return: Hash[String, Time?]
125
+ def file_state: () -> Hash[String, Time?]
126
+
127
+ # @rbs return: Array[String]
128
+ def rig_paths: () -> Array[String]
129
+
130
+ # @rbs path: String
131
+ # @rbs return: Time?
132
+ def stamp: (String path) -> Time?
133
+
134
+ # @rbs return: String
135
+ def home_rig_path: () -> String
136
+
137
+ # @rbs return: String
138
+ def project_rig_path: () -> String
139
+
140
+ # @rbs autoload: bool
141
+ # @rbs return: Array[Riffer::Rig::Extension]
142
+ def load_rig_files: (bool autoload) -> Array[Riffer::Rig::Extension]
143
+
144
+ # @rbs autoload: bool
145
+ # @rbs return: Array[String]
146
+ def gem_extension_files: (bool autoload) -> Array[String]
147
+
148
+ # @rbs path: String
149
+ # @rbs return: bool
150
+ def trusted?: (String path) -> bool
151
+
152
+ # @rbs return: String
153
+ def trust_path: () -> String
154
+
155
+ # Loads one file and returns the extensions it recorded. A tracked load adds
156
+ # the features the load added to the tracked file set. A failure is reported
157
+ # to the host and yields nothing, unless strict: then it propagates as
158
+ # AbandonedError for the reload to abandon on.
159
+ # @rbs path: String
160
+ # @rbs track: bool
161
+ # @rbs strict: bool
162
+ # @rbs return: Array[Riffer::Rig::Extension]
163
+ def load_file: (String path, track: bool, ?strict: bool) -> Array[Riffer::Rig::Extension]
164
+
165
+ # @rbs before_features: Array[String]
166
+ # @rbs path: String
167
+ # @rbs return: void
168
+ def track_loaded: (Array[String] before_features, String path) -> void
169
+
170
+ # @rbs feature: String
171
+ # @rbs return: bool
172
+ def local?: (String feature) -> bool
173
+
56
174
  # @rbs configured: String?
57
175
  # @rbs return: String
58
176
  def select_model: (String? configured) -> String
@@ -60,6 +178,19 @@ class Riffer::Rig::Loader
60
178
  # @rbs return: String
61
179
  def ask_for_model: () -> String
62
180
 
181
+ # @rbs return: String
182
+ def onboarding_question: () -> String
183
+
184
+ # @rbs return: String
185
+ def no_model: () -> String
186
+
187
+ # @rbs return: String
188
+ def provider_list: () -> String
189
+
190
+ # @rbs provider: String
191
+ # @rbs return: void
192
+ def ensure_sdk: (String provider) -> void
193
+
63
194
  # @rbs provider: String
64
195
  # @rbs return: Hash[Symbol, String]
65
196
  def credentials_for: (String provider) -> Hash[Symbol, String]
@@ -74,4 +205,10 @@ class Riffer::Rig::Loader
74
205
 
75
206
  # @rbs return: String
76
207
  def home_settings_path: () -> String
208
+
209
+ # The store records unless it was declined with store: nil or globally with
210
+ # "sessions": {"save": false}.
211
+ # @rbs document: Riffer::Rig::Settings::Document
212
+ # @rbs return: Riffer::Rig::Stores::Recorder?
213
+ def recorder_for: (Riffer::Rig::Settings::Document document) -> Riffer::Rig::Stores::Recorder?
77
214
  end
@@ -1,25 +1,36 @@
1
1
  # Generated from lib/riffer/rig/provider_setup.rb with RBS::Inline
2
2
 
3
3
  class Riffer::Rig::ProviderSetup
4
- # @dynamic url, chain, fields
4
+ # @dynamic url, chain, sdk, fields
5
5
  attr_reader url: String?
6
6
 
7
7
  attr_reader chain: bool
8
8
 
9
+ attr_reader sdk: [ String, String ]?
10
+
9
11
  attr_reader fields: Array[Riffer::Rig::ProviderSetup::Field]
10
12
 
11
13
  # @rbs fields: Array[Riffer::Rig::ProviderSetup::Field]
12
14
  # @rbs url: String?
13
15
  # @rbs chain: bool
16
+ # @rbs sdk: [String, String]?
14
17
  # @rbs return: void
15
- def initialize: (fields: Array[Riffer::Rig::ProviderSetup::Field], ?url: String?, ?chain: bool) -> void
18
+ def initialize: (fields: Array[Riffer::Rig::ProviderSetup::Field], ?url: String?, ?chain: bool, ?sdk: [ String, String ]?) -> void
16
19
 
17
20
  AWS_SHARED_CONFIG_REGION: ^() -> String?
18
21
 
19
- # Upstream candidate: each riffer provider could declare its own credential
20
- # fields, and this table would go.
22
+ # Upstream candidate: riffer's providers could declare their own SDK gem and
23
+ # credential fields, and this table would go.
21
24
  TABLE: Hash[Symbol, Riffer::Rig::ProviderSetup]
22
25
 
26
+ # @rbs missing: Array[Symbol]
27
+ # @rbs return: String
28
+ def missing_fields: (Array[Symbol] missing) -> String
29
+
30
+ # @rbs hash: Hash[Symbol, untyped]
31
+ # @rbs return: Riffer::Rig::ProviderSetup
32
+ def self.from: (Hash[Symbol, untyped] hash) -> Riffer::Rig::ProviderSetup
33
+
23
34
  # @rbs identifier: String | Symbol
24
35
  # @rbs return: Riffer::Rig::ProviderSetup?
25
36
  def self.[]: (String | Symbol identifier) -> Riffer::Rig::ProviderSetup?
@@ -0,0 +1,28 @@
1
+ # Generated from lib/riffer/rig/providers.rb with RBS::Inline
2
+
3
+ module Riffer::Rig::Providers
4
+ @setups: Hash[Symbol, Riffer::Rig::ProviderSetup?]
5
+
6
+ # @rbs identifier: String | Symbol
7
+ # @rbs setup: Riffer::Rig::ProviderSetup | Hash[Symbol, untyped]?
8
+ # @rbs &block: () -> singleton(::Riffer::Providers::Base)
9
+ # @rbs return: void
10
+ def register: (String | Symbol identifier, ?setup: Riffer::Rig::ProviderSetup | Hash[Symbol, untyped]?) { () -> singleton(::Riffer::Providers::Base) } -> void
11
+
12
+ # @rbs identifier: String | Symbol
13
+ # @rbs return: void
14
+ def unregister: (String | Symbol identifier) -> void
15
+
16
+ # @rbs identifier: String | Symbol
17
+ # @rbs return: Riffer::Rig::ProviderSetup?
18
+ def setup: (String | Symbol identifier) -> Riffer::Rig::ProviderSetup?
19
+
20
+ # @rbs return: Array[Symbol]
21
+ def identifiers: () -> Array[Symbol]
22
+
23
+ private
24
+
25
+ # @rbs setup: Riffer::Rig::ProviderSetup | Hash[Symbol, untyped]
26
+ # @rbs return: Riffer::Rig::ProviderSetup
27
+ def normalize: (Riffer::Rig::ProviderSetup | Hash[Symbol, untyped] setup) -> Riffer::Rig::ProviderSetup
28
+ end
@@ -65,6 +65,12 @@ class Riffer::Rig::Registrar
65
65
  # @rbs return: void
66
66
  def mcp: (String name, url: String, ?headers: Hash[String, String]) -> void
67
67
 
68
+ # @rbs prefix: String | Symbol
69
+ # @rbs setup: Riffer::Rig::ProviderSetup | Hash[Symbol, untyped]?
70
+ # @rbs &block: () -> singleton(::Riffer::Providers::Base)
71
+ # @rbs return: void
72
+ def provider: (String | Symbol prefix, ?setup: Riffer::Rig::ProviderSetup | Hash[Symbol, untyped]?) { () -> singleton(::Riffer::Providers::Base) } -> void
73
+
68
74
  # @rbs event: Symbol
69
75
  # @rbs &block: (Riffer::Rig::Events::_Event | ::Riffer::StreamEvents::Base) -> untyped
70
76
  # @rbs return: void
@@ -19,6 +19,17 @@ class Riffer::Rig::Runtime
19
19
 
20
20
  INTERRUPT_CANCELLED: Symbol
21
21
 
22
+ # Upstream candidate: riffer's Anthropic, OpenAI and Azure OpenAI classes read
23
+ # the web_search option and OpenRouter passes unknown options through to its
24
+ # API, but the provider seam cannot yet answer which provider takes which
25
+ # option, so rig keeps the mapping until it can. Mock consumes web_search, so
26
+ # tests and embedders can exercise the switches.
27
+ NATIVE_TOOLS_BY_PROVIDER: Hash[Symbol, Hash[Symbol, bool]]
28
+
29
+ @message_observers: Array[^(Riffer::Messages::Base) -> void]
30
+
31
+ @model_override: String?
32
+
22
33
  @session_start_reason: Symbol
23
34
 
24
35
  @session_start_pending: bool
@@ -43,14 +54,18 @@ class Riffer::Rig::Runtime
43
54
 
44
55
  @agent: Riffer::Agent
45
56
 
46
- @model_override: String?
47
-
48
- @message_observers: Array[^(Riffer::Messages::Base) -> void]
57
+ @model_observers: Array[^(String) -> void]
49
58
 
50
59
  @prompts: Hash[Symbol, ^(Riffer::Rig::Runtime) -> String?]
51
60
 
52
61
  @commands: Hash[String, Riffer::Rig::Command]
53
62
 
63
+ @core_commands: Array[Riffer::Rig::Command]
64
+
65
+ @claim_depth: Integer
66
+
67
+ @claim_thread: Thread?
68
+
54
69
  @declared_settings: Hash[String, Hash[Symbol, untyped]]
55
70
 
56
71
  @errors: Array[Riffer::Rig::Extension::Failure]
@@ -65,6 +80,8 @@ class Riffer::Rig::Runtime
65
80
 
66
81
  @model_options: Hash[Symbol, untyped]
67
82
 
83
+ @native_tools: Hash[Symbol, untyped]
84
+
68
85
  # @dynamic agent, credentials, cwd, host, id, settings, declared_settings
69
86
  attr_reader agent: Riffer::Agent
70
87
 
@@ -94,9 +111,10 @@ class Riffer::Rig::Runtime
94
111
  # @rbs mcp_registry: Riffer::Rig::Mcp::_Registry
95
112
  # @rbs max_steps: Integer?
96
113
  # @rbs model_options: Hash[Symbol, untyped]
114
+ # @rbs native_tools: Hash[Symbol, untyped]
97
115
  # @rbs snapshot: Hash[Symbol, untyped]?
98
116
  # @rbs return: void
99
- def initialize: (String model, ?extensions: Array[Riffer::Rig::Extension], ?tools: Array[String]?, ?settings: Hash[Symbol, untyped], ?host: Riffer::Rig::Hosts::_Host, ?cwd: String?, ?name: String, ?instructions: String?, ?credentials: Hash[Symbol, Hash[Symbol, String]], ?pricing: Hash[String, Riffer::Rig::Settings::Pricing], ?riffer_config: Riffer::Config, ?mcp_registry: Riffer::Rig::Mcp::_Registry, ?max_steps: Integer?, ?model_options: Hash[Symbol, untyped], ?snapshot: Hash[Symbol, untyped]?) -> void
117
+ def initialize: (String model, ?extensions: Array[Riffer::Rig::Extension], ?tools: Array[String]?, ?settings: Hash[Symbol, untyped], ?host: Riffer::Rig::Hosts::_Host, ?cwd: String?, ?name: String, ?instructions: String?, ?credentials: Hash[Symbol, Hash[Symbol, String]], ?pricing: Hash[String, Riffer::Rig::Settings::Pricing], ?riffer_config: Riffer::Config, ?mcp_registry: Riffer::Rig::Mcp::_Registry, ?max_steps: Integer?, ?model_options: Hash[Symbol, untyped], ?native_tools: Hash[Symbol, untyped], ?snapshot: Hash[Symbol, untyped]?) -> void
100
118
 
101
119
  # @rbs text: String
102
120
  # @rbs &block: ?(::Riffer::StreamEvents::Base | Riffer::Rig::Events::_Event) -> void
@@ -110,6 +128,12 @@ class Riffer::Rig::Runtime
110
128
  # @rbs return: Array[Riffer::Rig::Command]
111
129
  def commands: () -> Array[Riffer::Rig::Command]
112
130
 
131
+ # Installs a host-of-the-runtime command (the Loader's /reload) so it
132
+ # survives every rebuild; an extension command of the same name replaces it.
133
+ # @rbs command: Riffer::Rig::Command
134
+ # @rbs return: nil
135
+ def install_command: (Riffer::Rig::Command command) -> nil
136
+
113
137
  # @rbs name: String
114
138
  # @rbs args: String
115
139
  # @rbs &block: ?(::Riffer::StreamEvents::Base | Riffer::Rig::Events::_Event) -> void
@@ -126,6 +150,11 @@ class Riffer::Rig::Runtime
126
150
  # @rbs return: void
127
151
  def model=: (String model) -> void
128
152
 
153
+ # @rbs provider: Symbol
154
+ # @rbs values: Hash[Symbol, String]
155
+ # @rbs return: void
156
+ def merge_credentials: (Symbol provider, Hash[Symbol, String] values) -> void
157
+
129
158
  # @rbs extensions: Array[Riffer::Rig::Extension]
130
159
  # @rbs settings: Hash[Symbol, untyped]
131
160
  # @rbs return: nil
@@ -138,6 +167,10 @@ class Riffer::Rig::Runtime
138
167
  # @rbs return: nil
139
168
  def on_message: () { (Riffer::Messages::Base) -> void } -> nil
140
169
 
170
+ # @rbs &block: (String) -> void
171
+ # @rbs return: nil
172
+ def on_model_change: () { (String) -> void } -> nil
173
+
141
174
  # @rbs return: nil
142
175
  def cancel: () -> nil
143
176
 
@@ -152,6 +185,16 @@ class Riffer::Rig::Runtime
152
185
  # @rbs return: void
153
186
  def claim: () -> void
154
187
 
188
+ # Rebuild is a configuration swap at a quiet boundary, not a turn entry, so
189
+ # it may run nested under the thread that holds the Runtime — the /reload
190
+ # command and the automatic reload check both do. Another thread is still
191
+ # refused while work runs.
192
+ # @rbs return: void
193
+ def claim_rebuild: () -> void
194
+
195
+ # @rbs return: void
196
+ def release: () -> void
197
+
155
198
  # @rbs model: String
156
199
  # @rbs config: Riffer::Agent::Config
157
200
  # @rbs session: Riffer::Agent::Session?
@@ -163,6 +206,22 @@ class Riffer::Rig::Runtime
163
206
  # @rbs return: Riffer::Agent
164
207
  def successor: (String model, Riffer::Agent::Config config) -> Riffer::Agent
165
208
 
209
+ # The options the settings built for the starting model are provider-shaped
210
+ # (cache control, per-provider reasoning levels), so a switch re-derives them.
211
+ # Runs after the successor is built, so a failed build leaves the running
212
+ # agent's options alone; riffer reads config.model_options per request, so the
213
+ # swap still reaches the new agent through the shared config.
214
+ # @rbs model: String
215
+ # @rbs return: void
216
+ def rederive_options: (String model) -> void
217
+
218
+ # The switches are on/off settings, so what the agent can do stays a function
219
+ # of the current provider: a switch whose provider cannot take the option
220
+ # contributes nothing, and a switch to such a provider drops it, both silently.
221
+ # @rbs model: String
222
+ # @rbs return: Hash[Symbol, untyped]
223
+ def native_options: (String model) -> Hash[Symbol, untyped]
224
+
166
225
  # @rbs registrars: Array[Riffer::Rig::Registrar]
167
226
  # @rbs hooks: Riffer::Rig::Runtime::Hooks
168
227
  # @rbs max_steps: Numeric?
@@ -264,11 +323,6 @@ class Riffer::Rig::Runtime
264
323
  # @rbs return: Array[Riffer::Rig::Registrar]
265
324
  def build_registrars: (Array[Riffer::Rig::Extension] extensions, Hash[Symbol, untyped] settings) { (Riffer::Rig::Extension, StandardError) -> void } -> Array[Riffer::Rig::Registrar]
266
325
 
267
- # @rbs extension: Riffer::Rig::Extension
268
- # @rbs registrar: Riffer::Rig::Registrar
269
- # @rbs return: StandardError?
270
- def load_extension: (Riffer::Rig::Extension extension, Riffer::Rig::Registrar registrar) -> StandardError?
271
-
272
326
  # @rbs extension: Riffer::Rig::Extension
273
327
  # @rbs error: StandardError
274
328
  # @rbs return: void
@@ -0,0 +1,33 @@
1
+ # Generated from lib/riffer/rig/sdk.rb with RBS::Inline
2
+
3
+ module Riffer::Rig::SDK
4
+ CONFIRM_QUESTION: String
5
+
6
+ PROGRESS_LABEL: String
7
+
8
+ BUNDLER_MESSAGE: String
9
+
10
+ DECLINED_MESSAGE: String
11
+
12
+ FAILED_MESSAGE: String
13
+
14
+ # @rbs gem: String
15
+ # @rbs requirement: String
16
+ # @rbs host: Riffer::Rig::Hosts::_Host
17
+ # @rbs return: String?
18
+ def ensure: (String gem, String requirement, host: Riffer::Rig::Hosts::_Host) -> String?
19
+
20
+ private
21
+
22
+ # @rbs gem: String
23
+ # @rbs requirement: String
24
+ # @rbs return: bool
25
+ def installed?: (String gem, String requirement) -> bool
26
+
27
+ # @rbs gem: String
28
+ # @rbs return: bool
29
+ def require_gem: (String gem) -> bool
30
+
31
+ # @rbs return: bool
32
+ def bundler?: () -> bool
33
+ end
@@ -1,7 +1,7 @@
1
1
  # Generated from lib/riffer/rig/settings/document.rb with RBS::Inline
2
2
 
3
3
  class Riffer::Rig::Settings::Document
4
- # @dynamic model, reasoning, models, providers, disabled
4
+ # @dynamic model, reasoning, models, providers, disabled, autoload, native_tools, save
5
5
  attr_reader model: String?
6
6
 
7
7
  attr_reader reasoning: String?
@@ -12,6 +12,12 @@ class Riffer::Rig::Settings::Document
12
12
 
13
13
  attr_reader disabled: Array[String]
14
14
 
15
+ attr_reader autoload: bool
16
+
17
+ attr_reader native_tools: Hash[Symbol, bool | Hash[Symbol, untyped]]
18
+
19
+ attr_reader save: bool
20
+
15
21
  # @rbs source: Hash[Symbol, untyped]
16
22
  # @rbs return: void
17
23
  def initialize: (Hash[Symbol, untyped] source) -> void
@@ -7,9 +7,8 @@ module Riffer::Rig::Settings
7
7
 
8
8
  MODEL_STRING: Regexp
9
9
 
10
- # Upstream candidate: riffer's Repository keeps extension registrations
11
- # private and lists no identifiers, so the list names riffer's built-ins.
12
- PROVIDERS: Array[Symbol]
10
+ # @rbs return: Array[Symbol]
11
+ def providers: () -> Array[Symbol]
13
12
 
14
13
  # @rbs path: String
15
14
  # @rbs return: Hash[Symbol, untyped]
@@ -0,0 +1,64 @@
1
+ # Generated from lib/riffer/rig/stores/jsonl.rb with RBS::Inline
2
+
3
+ class Riffer::Rig::Stores::JSONL
4
+ HEADER_VERSION: Integer
5
+
6
+ @home: String
7
+
8
+ @paths: Hash[String, String]
9
+
10
+ # @rbs home: String
11
+ # @rbs return: void
12
+ def initialize: (?home: String) -> void
13
+
14
+ # @rbs id: String
15
+ # @rbs entry: Hash[Symbol, untyped]
16
+ # @rbs return: void
17
+ def append: (String id, Hash[Symbol, untyped] entry) -> void
18
+
19
+ # @rbs id: String
20
+ # @rbs return: Array[Hash[Symbol, untyped]]
21
+ def read: (String id) -> Array[Hash[Symbol, untyped]]
22
+
23
+ # @rbs cwd: String?
24
+ # @rbs return: Array[Hash[Symbol, untyped]]
25
+ def list: (?cwd: String?) -> Array[Hash[Symbol, untyped]]
26
+
27
+ # @rbs id: String
28
+ # @rbs return: void
29
+ def delete: (String id) -> void
30
+
31
+ private
32
+
33
+ # @rbs return: String
34
+ def root: () -> String
35
+
36
+ # @rbs id: String
37
+ # @rbs entry: Hash[Symbol, untyped]
38
+ # @rbs return: String
39
+ def path_for: (String id, Hash[Symbol, untyped] entry) -> String
40
+
41
+ # @rbs id: String
42
+ # @rbs cwd: String
43
+ # @rbs return: String
44
+ def new_path: (String id, String cwd) -> String
45
+
46
+ # @rbs path: String
47
+ # @rbs return: Hash[Symbol, untyped]?
48
+ def header_of: (String path) -> Hash[Symbol, untyped]?
49
+
50
+ # @rbs id: String
51
+ # @rbs return: String?
52
+ def find: (String id) -> String?
53
+
54
+ # The slug groups a cwd's sessions for listing; it is not the truth — the
55
+ # header's cwd is, so two cwd strings that slug alike share a directory. A
56
+ # bare "." or ".." is collapsed so the file stays inside the sessions tree.
57
+ # @rbs cwd: String
58
+ # @rbs return: String
59
+ def slug: (String cwd) -> String
60
+
61
+ # @rbs line: String
62
+ # @rbs return: Hash[Symbol, untyped]?
63
+ def parse: (String line) -> Hash[Symbol, untyped]?
64
+ end
@@ -0,0 +1,67 @@
1
+ # Generated from lib/riffer/rig/stores/recorder.rb with RBS::Inline
2
+
3
+ class Riffer::Rig::Stores::Recorder
4
+ EXTENSION_NAME: String
5
+
6
+ @title: String?
7
+
8
+ @pending: Array[Hash[Symbol, untyped]]
9
+
10
+ @header_written: bool
11
+
12
+ @runtime: Riffer::Rig::Runtime?
13
+
14
+ @store: Riffer::Rig::Stores::_Store
15
+
16
+ # Records one Loader-built session into the store: the header on the first
17
+ # message (its title needs the first prompt), one entry per message, one per
18
+ # model switch and one per skill activation. Entries that land before the
19
+ # first message (a /model before the first prompt) wait for the header.
20
+ # @rbs store: Riffer::Rig::Stores::_Store
21
+ # @rbs return: void
22
+ def initialize: (store: Riffer::Rig::Stores::_Store) -> void
23
+
24
+ # @rbs runtime: Riffer::Rig::Runtime
25
+ # @rbs return: void
26
+ def attach: (Riffer::Rig::Runtime runtime) -> void
27
+
28
+ # @rbs event: Riffer::StreamEvents::SkillActivation
29
+ # @rbs return: void
30
+ def skill: (Riffer::StreamEvents::SkillActivation event) -> void
31
+
32
+ # @rbs message: Riffer::Messages::Base
33
+ # @rbs return: void
34
+ def message: (Riffer::Messages::Base message) -> void
35
+
36
+ # @rbs model: String
37
+ # @rbs return: void
38
+ def switched: (String model) -> void
39
+
40
+ # The extension rides the build as its last extension, so its :stream hook
41
+ # sees the model's skill activations. Per build, unlike the extensions in
42
+ # the process registry: the hook closes over this build's recorder.
43
+ # @rbs recorder: Riffer::Rig::Stores::Recorder
44
+ # @rbs return: Riffer::Rig::Extension
45
+ def self.extension: (Riffer::Rig::Stores::Recorder recorder) -> Riffer::Rig::Extension
46
+
47
+ private
48
+
49
+ # @rbs entry: Hash[Symbol, untyped]
50
+ # @rbs return: void
51
+ def record: (Hash[Symbol, untyped] entry) -> void
52
+
53
+ # @rbs return: void
54
+ def write_header: () -> void
55
+
56
+ # @rbs return: Hash[Symbol, untyped]
57
+ def header_entry: () -> Hash[Symbol, untyped]
58
+
59
+ # @rbs content: String
60
+ # @rbs return: String
61
+ def one_line: (String content) -> String
62
+
63
+ # The recorder is built before the Runtime it records; every entry arrives
64
+ # after attach, so the runtime is always there by then.
65
+ # @rbs return: Riffer::Rig::Runtime
66
+ def runtime: () -> Riffer::Rig::Runtime
67
+ end
@@ -3,6 +3,18 @@
3
3
  class Riffer::Rig::Terminal::Renderer
4
4
  RESULT_PREVIEW_LIMIT: Integer
5
5
 
6
+ ARGUMENT_PREVIEW_LIMIT: Integer
7
+
8
+ PROSE_INDENT: Integer
9
+
10
+ TOOL_CALL_INDENT: Integer
11
+
12
+ TOOL_RESULT_INDENT: Integer
13
+
14
+ @wrapper: Riffer::Rig::Terminal::Wrapper
15
+
16
+ @width: Integer?
17
+
6
18
  @prose_gap_pending: bool
7
19
 
8
20
  @cursor: Riffer::Rig::Terminal::Cursor
@@ -17,8 +29,9 @@ class Riffer::Rig::Terminal::Renderer
17
29
  # @rbs theme: Riffer::Rig::Terminal::Theme
18
30
  # @rbs smoother: Riffer::Rig::Terminal::Smoother | PassThroughSmoother
19
31
  # @rbs cursor: Riffer::Rig::Terminal::Cursor
32
+ # @rbs width: Integer?
20
33
  # @rbs return: void
21
- def initialize: (?io: IO, ?theme: Riffer::Rig::Terminal::Theme, ?smoother: Riffer::Rig::Terminal::Smoother | PassThroughSmoother, ?cursor: Riffer::Rig::Terminal::Cursor) -> void
34
+ def initialize: (?io: IO, ?theme: Riffer::Rig::Terminal::Theme, ?smoother: Riffer::Rig::Terminal::Smoother | PassThroughSmoother, ?cursor: Riffer::Rig::Terminal::Cursor, ?width: Integer?) -> void
22
35
 
23
36
  # @rbs event: Riffer::StreamEvents::TextDelta | Riffer::StreamEvents::ToolCallDone | Riffer::StreamEvents::Interrupt
24
37
  # @rbs return: void
@@ -123,4 +136,31 @@ class Riffer::Rig::Terminal::Renderer
123
136
  # @rbs content: String
124
137
  # @rbs return: String
125
138
  def preview: (String content) -> String
139
+
140
+ # @rbs text: String
141
+ # @rbs limit: Integer
142
+ # @rbs return: String
143
+ def elide: (String text, Integer limit) -> String
144
+
145
+ # Truncation is what keeps an indented line from wrapping: a wrapped
146
+ # continuation starts at column zero and destroys the prose > tool nesting.
147
+ # @rbs text: String
148
+ # @rbs indent: Integer
149
+ # @rbs return: String
150
+ def fit: (String text, Integer indent) -> String
151
+
152
+ # @rbs return: void
153
+ def flush_prose: () -> void
154
+
155
+ # @rbs return: Riffer::Rig::Terminal::Wrapper
156
+ def new_wrapper: () -> Riffer::Rig::Terminal::Wrapper
157
+
158
+ # @rbs return: Integer?
159
+ def detect_width: () -> Integer?
160
+
161
+ # winsize raises on ttys with no queryable window size and some pty
162
+ # wrappers report zero columns; either way the real width is unknowable,
163
+ # and nil leaves every consumer un-fitted rather than mis-fitted.
164
+ # @rbs return: Integer?
165
+ def detected_width: () -> Integer?
126
166
  end