riffer-rig 0.3.0 → 0.5.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/lib/riffer/rig/cli.rb +16 -8
  4. data/lib/riffer/rig/coding_agent.rb +31 -34
  5. data/lib/riffer/rig/credentials.rb +7 -7
  6. data/lib/riffer/rig/extension.rb +31 -0
  7. data/lib/riffer/rig/host.rb +52 -0
  8. data/lib/riffer/rig/registrar.rb +23 -0
  9. data/lib/riffer/rig/repl.rb +63 -59
  10. data/lib/riffer/rig/runtime.rb +162 -0
  11. data/lib/riffer/rig/settings/document.rb +23 -0
  12. data/lib/riffer/rig/settings/pricing.rb +11 -0
  13. data/lib/riffer/rig/settings.rb +9 -17
  14. data/lib/riffer/rig/token_tally.rb +1 -1
  15. data/lib/riffer/rig/tools/bash.rb +5 -2
  16. data/lib/riffer/rig/tools/edit.rb +11 -3
  17. data/lib/riffer/rig/tools/read.rb +2 -2
  18. data/lib/riffer/rig/ui/animator.rb +6 -6
  19. data/lib/riffer/rig/ui/cursor.rb +4 -4
  20. data/lib/riffer/rig/ui/renderer.rb +115 -36
  21. data/lib/riffer/rig/ui/smoother.rb +29 -13
  22. data/lib/riffer/rig/ui/theme.rb +2 -2
  23. data/lib/riffer/rig/version.rb +1 -1
  24. data/lib/riffer/rig.rb +31 -0
  25. data/sig/generated/riffer/rig/cli.rbs +8 -8
  26. data/sig/generated/riffer/rig/credentials.rbs +4 -3
  27. data/sig/generated/riffer/rig/extension.rbs +28 -0
  28. data/sig/generated/riffer/rig/host.rbs +42 -0
  29. data/sig/generated/riffer/rig/registrar.rbs +17 -0
  30. data/sig/generated/riffer/rig/repl.rbs +24 -23
  31. data/sig/generated/riffer/rig/runtime.rbs +101 -0
  32. data/sig/generated/riffer/rig/settings/document.rbs +20 -0
  33. data/sig/generated/riffer/rig/settings/pricing.rbs +4 -0
  34. data/sig/generated/riffer/rig/settings.rbs +5 -5
  35. data/sig/generated/riffer/rig/token_tally.rbs +2 -2
  36. data/sig/generated/riffer/rig/tools/bash.rbs +2 -2
  37. data/sig/generated/riffer/rig/tools/edit.rbs +2 -2
  38. data/sig/generated/riffer/rig/tools/read.rbs +3 -3
  39. data/sig/generated/riffer/rig/ui/animator.rbs +8 -8
  40. data/sig/generated/riffer/rig/ui/cursor.rbs +4 -4
  41. data/sig/generated/riffer/rig/ui/renderer.rbs +65 -15
  42. data/sig/generated/riffer/rig/ui/smoother.rbs +10 -5
  43. data/sig/generated/riffer/rig/ui/theme.rbs +2 -2
  44. data/sig/generated/riffer/rig.rbs +19 -0
  45. data/sig/manual/riffer/rig.rbs +11 -0
  46. metadata +24 -7
@@ -17,7 +17,7 @@ class Riffer::Rig::UI::Smoother
17
17
 
18
18
  MIN_CHARS_PER_TICK = Rational(1, 6) #: Rational
19
19
 
20
- # @rbs @io: untyped
20
+ # @rbs @io: IO
21
21
  # @rbs @theme: Riffer::Rig::UI::Theme
22
22
  # @rbs @clock: singleton(Kernel)
23
23
  # @rbs @backlog: String
@@ -25,9 +25,10 @@ class Riffer::Rig::UI::Smoother
25
25
  # @rbs @mutex: Mutex
26
26
  # @rbs @thread: Thread?
27
27
  # @rbs @stop: bool
28
+ # @rbs @newline_pending: bool
28
29
 
29
- # @rbs io: untyped
30
- # @rbs ?theme: Riffer::Rig::UI::Theme
30
+ # @rbs io: IO
31
+ # @rbs theme: Riffer::Rig::UI::Theme
31
32
  # @rbs clock: singleton(Kernel)
32
33
  # @rbs return: void
33
34
  def initialize(io: $stdout, theme: Riffer::Rig::UI::Theme.for(io), clock: Kernel)
@@ -39,6 +40,7 @@ class Riffer::Rig::UI::Smoother
39
40
  @mutex = Mutex.new
40
41
  @thread = nil
41
42
  @stop = false
43
+ @newline_pending = false
42
44
  end
43
45
 
44
46
  # @rbs return: void
@@ -58,11 +60,14 @@ class Riffer::Rig::UI::Smoother
58
60
  # @rbs content: String
59
61
  # @rbs return: self
60
62
  def <<(content)
61
- if enabled?
62
- @mutex.synchronize { @backlog << content }
63
- else
64
- @io.print(content)
65
- @io.flush
63
+ @mutex.synchronize do
64
+ if enabled?
65
+ @backlog << content
66
+ else
67
+ @io.print(content)
68
+ @io.flush
69
+ end
70
+ @newline_pending = !content.end_with?("\n")
66
71
  end
67
72
  self
68
73
  end
@@ -79,19 +84,30 @@ class Riffer::Rig::UI::Smoother
79
84
  return if count.zero?
80
85
 
81
86
  @carry -= count
82
- @io.print(@backlog.slice!(0, count))
87
+ chunk = @backlog.slice!(0, count) || ''
88
+ @newline_pending = !chunk.end_with?("\n")
89
+ @io.print(chunk)
83
90
  @io.flush
84
91
  end
85
92
  end
86
93
 
87
- # Called before non-delta output so printed order matches stream order.
94
+ # Called before non-prose output so printed order matches stream order. The
95
+ # backlog is flushed, then any partial prose block the model left without a
96
+ # trailing newline gets one, so block spacing never depends on the model's
97
+ # last character.
88
98
  #
89
99
  # @rbs return: void
90
100
  def drain
91
101
  @mutex.synchronize do
92
- return if @backlog.empty?
102
+ unless @backlog.empty?
103
+ backlog = @backlog.slice!(0, @backlog.length) || ''
104
+ @newline_pending = !backlog.end_with?("\n")
105
+ @io.print(backlog)
106
+ end
107
+ return unless @newline_pending
93
108
 
94
- @io.print(@backlog.slice!(0, @backlog.length))
109
+ @newline_pending = false
110
+ @io.print("\n")
95
111
  @io.flush
96
112
  end
97
113
  end
@@ -113,6 +129,6 @@ class Riffer::Rig::UI::Smoother
113
129
 
114
130
  # @rbs return: bool
115
131
  def enabled?
116
- @theme.enabled && @io.respond_to?(:tty?) && @io.tty?
132
+ @theme.enabled && @io.tty?
117
133
  end
118
134
  end
@@ -15,10 +15,10 @@ class Riffer::Rig::UI::Theme
15
15
  @enabled = enabled
16
16
  end
17
17
 
18
- # @rbs io: untyped
18
+ # @rbs io: IO
19
19
  # @rbs return: Riffer::Rig::UI::Theme
20
20
  def self.for(io)
21
- new(enabled: io.respond_to?(:tty?) && io.tty? && !ENV.key?('NO_COLOR'))
21
+ new(enabled: io.tty? && !ENV.key?('NO_COLOR'))
22
22
  end
23
23
 
24
24
  # @rbs text: String
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Riffer
4
4
  module Rig
5
- VERSION = '0.3.0'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
data/lib/riffer/rig.rb CHANGED
@@ -8,3 +8,34 @@ loader = Zeitwerk::Loader.for_gem_extension(Riffer)
8
8
  loader.ignore("#{__dir__}/rig/version.rb")
9
9
  loader.inflector.inflect('cli' => 'CLI', 'repl' => 'REPL', 'ui' => 'UI')
10
10
  loader.setup
11
+
12
+ module Riffer::Rig
13
+ # @rbs self.@extensions: Hash[String, Riffer::Rig::Extension]
14
+ @extensions = {} #: Hash[String, Riffer::Rig::Extension]
15
+
16
+ # Records an extension block in the process registry and returns the
17
+ # extension object. Re-recording a name replaces the block.
18
+ #
19
+ # Riffer::Rig.extension('git') do |rig|
20
+ # rig.tool GitLog
21
+ # end
22
+ #
23
+ # @rbs name: String
24
+ # @rbs requires: String?
25
+ # @rbs &block: (::Riffer::Rig::Registrar) -> void
26
+ # @rbs return: Riffer::Rig::Extension
27
+ def self.extension(name, requires: nil, &)
28
+ ext = Extension.new(name, requires: requires, &)
29
+ if ext.requires && !ext.requires.satisfied_by?(Gem::Version.new(Riffer::Rig::VERSION))
30
+ raise Riffer::ArgumentError,
31
+ "extension #{name} requires riffer-rig #{ext.requires}, found #{Riffer::Rig::VERSION}"
32
+ end
33
+
34
+ @extensions[name] = ext
35
+ end
36
+
37
+ # @rbs return: Hash[String, Riffer::Rig::Extension]
38
+ def self.extensions
39
+ @extensions.dup
40
+ end
41
+ end
@@ -3,10 +3,10 @@
3
3
  module Riffer::Rig::CLI
4
4
  PROVIDER_URLS: Hash[String, String]
5
5
 
6
- # @rbs output: untyped
7
- # @rbs input: untyped
6
+ # @rbs output: IO
7
+ # @rbs input: IO
8
8
  # @rbs return: Integer
9
- def start: (?output: untyped, ?input: untyped) -> Integer
9
+ def start: (?output: IO, ?input: IO) -> Integer
10
10
 
11
11
  private
12
12
 
@@ -17,18 +17,18 @@ module Riffer::Rig::CLI
17
17
 
18
18
  # @rbs provider: String?
19
19
  # @rbs theme: Riffer::Rig::UI::Theme
20
- # @rbs output: untyped
21
- # @rbs input: untyped
20
+ # @rbs output: IO
21
+ # @rbs input: IO
22
22
  # @rbs return: String?
23
- def onboard: (String? provider, Riffer::Rig::UI::Theme theme, output: untyped, input: untyped) -> String?
23
+ def onboard: (String? provider, Riffer::Rig::UI::Theme theme, output: IO, input: IO) -> String?
24
24
 
25
25
  # @rbs provider: String?
26
26
  # @rbs return: String
27
27
  def env_var_for: (String? provider) -> String
28
28
 
29
- # @rbs input: untyped
29
+ # @rbs input: IO
30
30
  # @rbs return: String?
31
- def read_secret: (untyped input) -> String?
31
+ def read_secret: (IO input) -> String?
32
32
 
33
33
  # @rbs theme: Riffer::Rig::UI::Theme
34
34
  # @rbs animator: Riffer::Rig::UI::Animator
@@ -47,9 +47,10 @@ module Riffer::Rig::Credentials
47
47
  def key_from_file: (String? provider, String path) -> String?
48
48
 
49
49
  # The parsed auth file, or an empty hash when the file is absent or
50
- # malformed.
50
+ # malformed. Non-string values can't be keys, so they're dropped here rather
51
+ # than re-checked by every reader.
51
52
  #
52
53
  # @rbs path: String
53
- # @rbs return: Hash[String, untyped]
54
- def read: (String path) -> Hash[String, untyped]
54
+ # @rbs return: Hash[String, String]
55
+ def read: (String path) -> Hash[String, String]
55
56
  end
@@ -0,0 +1,28 @@
1
+ # Generated from lib/riffer/rig/extension.rb with RBS::Inline
2
+
3
+ # An extension recorded by <tt>Riffer::Rig.extension</tt>: a name, an optional
4
+ # Gem::Requirement on riffer-rig, and the block that runs against a Runtime's
5
+ # registrar. The process registry holds these objects; Runtime.new runs their
6
+ # blocks.
7
+ class Riffer::Rig::Extension
8
+ @name: String
9
+
10
+ @requires: Gem::Requirement?
11
+
12
+ @block: ^(::Riffer::Rig::Registrar) -> void
13
+
14
+ # @dynamic name, requires
15
+ attr_reader name: String
16
+
17
+ attr_reader requires: Gem::Requirement?
18
+
19
+ # @rbs name: String
20
+ # @rbs requires: String?
21
+ # @rbs &block: (::Riffer::Rig::Registrar) -> void
22
+ # @rbs return: void
23
+ def initialize: (String name, ?requires: String?) { (::Riffer::Rig::Registrar) -> void } -> void
24
+
25
+ # @rbs registrar: Riffer::Rig::Registrar
26
+ # @rbs return: void
27
+ def run: (Riffer::Rig::Registrar registrar) -> void
28
+ end
@@ -0,0 +1,42 @@
1
+ # Generated from lib/riffer/rig/host.rb with RBS::Inline
2
+
3
+ # A host receives questions and out-of-band messages from a Runtime. It is
4
+ # duck-typed: any object with #ask, #confirm, #notify, #progress and
5
+ # #capabilities is a host.
6
+ #
7
+ # class HeadlessHost
8
+ # def capabilities = Set[:notify, :progress].freeze
9
+ # def ask(*) = nil
10
+ # def confirm(*) = false
11
+ # def notify(message, level:) = warn("[#{level}] #{message}")
12
+ # def progress(label) = yield
13
+ # end
14
+ #
15
+ # Callers check #capabilities before asking, so a host that declines a
16
+ # capability is never asked and the caller takes the declined path.
17
+ # The do-nothing host: the default +host:+ for a Runtime. Every capability is
18
+ # declined, so callers take the declined path without any UI attempt.
19
+ class Riffer::Rig::Host
20
+ # @rbs return: Set[Symbol]
21
+ def capabilities: () -> Set[Symbol]
22
+
23
+ # @rbs _question: String?
24
+ # @rbs options: Array[String]?
25
+ # @rbs secret: bool
26
+ # @rbs return: String?
27
+ def ask: (?untyped _question, ?options: Array[String]?, ?secret: bool) -> String?
28
+
29
+ # @rbs _question: String?
30
+ # @rbs return: bool
31
+ def confirm: (?untyped _question) -> bool
32
+
33
+ # @rbs _message: String?
34
+ # @rbs level: Symbol
35
+ # @rbs return: void
36
+ def notify: (?untyped _message, ?level: Symbol) -> void
37
+
38
+ # @rbs _label: String?
39
+ # @rbs &block: ^() -> void
40
+ # @rbs return: void
41
+ def progress: (?untyped _label) ?{ (?) -> untyped } -> void
42
+ end
@@ -0,0 +1,17 @@
1
+ # Generated from lib/riffer/rig/registrar.rb with RBS::Inline
2
+
3
+ # The per-Runtime registrar extension blocks run against. Seams are added one
4
+ # at a time; today only #tool exists.
5
+ class Riffer::Rig::Registrar
6
+ @tools: Array[singleton(Riffer::Tool)]
7
+
8
+ # @rbs return: void
9
+ def initialize: () -> void
10
+
11
+ # @rbs klass: singleton(Riffer::Tool)
12
+ # @rbs return: void
13
+ def tool: (singleton(Riffer::Tool) klass) -> void
14
+
15
+ # @rbs return: Array[singleton(Riffer::Tool)]
16
+ def tools: () -> Array[singleton(Riffer::Tool)]
17
+ end
@@ -5,11 +5,9 @@ class Riffer::Rig::REPL
5
5
 
6
6
  SKILL_COMMAND: Regexp
7
7
 
8
- @pending_tool_calls: Array[Riffer::StreamEvents::ToolCallDone]
8
+ @output: IO
9
9
 
10
- @output: untyped
11
-
12
- @input: untyped
10
+ @input: IO
13
11
 
14
12
  @theme: Riffer::Rig::UI::Theme
15
13
 
@@ -23,16 +21,16 @@ class Riffer::Rig::REPL
23
21
 
24
22
  @agent: Riffer::Agent
25
23
 
26
- # @rbs ?agent: Riffer::Agent
27
- # @rbs ?renderer: Riffer::Rig::UI::Renderer
28
- # @rbs input: untyped
29
- # @rbs output: untyped
30
- # @rbs ?theme: Riffer::Rig::UI::Theme
31
- # @rbs ?animator: Riffer::Rig::UI::Animator
32
- # @rbs ?smoother: Riffer::Rig::UI::Smoother
33
- # @rbs ?cursor: Riffer::Rig::UI::Cursor
24
+ # @rbs agent: Riffer::Agent
25
+ # @rbs renderer: Riffer::Rig::UI::Renderer
26
+ # @rbs input: IO
27
+ # @rbs output: IO
28
+ # @rbs theme: Riffer::Rig::UI::Theme
29
+ # @rbs animator: Riffer::Rig::UI::Animator
30
+ # @rbs smoother: Riffer::Rig::UI::Smoother
31
+ # @rbs cursor: Riffer::Rig::UI::Cursor
34
32
  # @rbs return: void
35
- def initialize: (agent: untyped, renderer: untyped, ?input: untyped, ?output: untyped, ?theme: untyped, ?animator: untyped, ?smoother: untyped, ?cursor: untyped) -> void
33
+ def initialize: (agent: Riffer::Agent, renderer: Riffer::Rig::UI::Renderer, ?input: IO, ?output: IO, ?theme: Riffer::Rig::UI::Theme, ?animator: Riffer::Rig::UI::Animator, ?smoother: Riffer::Rig::UI::Smoother, ?cursor: Riffer::Rig::UI::Cursor) -> void
36
34
 
37
35
  # @rbs return: Symbol
38
36
  def run: () -> Symbol
@@ -57,20 +55,23 @@ class Riffer::Rig::REPL
57
55
  # @rbs return: String
58
56
  def skill_block: (String name, String body) -> String
59
57
 
60
- # Tool call lines print below their round's stats line to reflect the actual
61
- # timeline (usage is reported when the model stream closes, after the calls
62
- # were decided). ToolCallDone events are therefore held until the stats line
63
- # or the next event forces them out. Callers must have the spinner stopped —
64
- # the flush renders between their existing stop/start pair.
58
+ # Chrome lines that never pass through the renderer (errors, exit line) end
59
+ # their line with a newline but leave the renderer's tool-group state alone —
60
+ # they can only follow prose, never mid-group.
65
61
  #
62
+ # @rbs &block: () -> String
66
63
  # @rbs return: void
67
- def flush_pending_tool_calls: () -> void
64
+ def print_block: () { () -> String } -> void
68
65
 
69
- # Tool results can land mid-animation (tool execution emits no stream events,
70
- # so the indicator is up); stop it around the line so its next frame doesn't
71
- # erase what we printed.
72
- #
73
66
  # @rbs message: Riffer::Messages::Base
74
67
  # @rbs return: void
75
68
  def render_tool_result: (Riffer::Messages::Base message) -> void
69
+
70
+ # Every animator start sits behind a smoother drain: the smoother's backlog
71
+ # may still be trickling out from streamed prose, and spinner frames drawn
72
+ # mid-drain would carve `\r…\e[K` through a half-printed sentence.
73
+ #
74
+ # @rbs mode: Symbol
75
+ # @rbs return: void
76
+ def start_animator: (?Symbol mode) -> void
76
77
  end
@@ -0,0 +1,101 @@
1
+ # Generated from lib/riffer/rig/runtime.rb with RBS::Inline
2
+
3
+ # One Runtime builds its own Riffer::Agent from a per-instance
4
+ # Riffer::Agent::Config and runs a prompt: streamed as events, or run to
5
+ # completion and returned as riffer's Agent::Response.
6
+ #
7
+ # runtime = Riffer::Rig::Runtime.new('mock/x')
8
+ # runtime.prompt('hello') { |event| ... } # yields riffer StreamEvents
9
+ # runtime.prompt('hello').each { |event| } # an Enumerator without a block
10
+ # response = runtime.ask('hello') # a Riffer::Agent::Response
11
+ #
12
+ # Two Runtimes in one process share nothing but the process-wide extension
13
+ # registry and riffer's provider repository. One prompt runs at a time; a
14
+ # second while one is running raises Riffer::Rig::Runtime::BusyError. The
15
+ # Runtime never renders, never prints, never reads the filesystem.
16
+ class Riffer::Rig::Runtime
17
+ # Raised when a second prompt, ask or registrar build runs while one is
18
+ # already running on this Runtime.
19
+ class BusyError < StandardError
20
+ end
21
+
22
+ BASE_PROMPT_TEMPLATE: ::String
23
+
24
+ DEFAULT_NAME: ::String
25
+
26
+ # The legacy CodingAgent's default: an unlimited agent loop. riffer's own
27
+ # default (16) is too small for a general-purpose harness.
28
+ DEFAULT_MAX_STEPS: Integer?
29
+
30
+ interface _Host
31
+ def ask: (?String, ?options: Array[String]?, ?secret: bool) -> String?
32
+
33
+ def confirm: (?String) -> bool
34
+
35
+ def notify: (?String, ?level: Symbol) -> void
36
+
37
+ def progress: (?String) { () -> void } -> void
38
+
39
+ def capabilities: () -> Set[Symbol]
40
+ end
41
+
42
+ @registrar: Riffer::Rig::Registrar
43
+
44
+ @busy: bool
45
+
46
+ @settings: Hash[Symbol, untyped]
47
+
48
+ @host: _Host
49
+
50
+ @cwd: String
51
+
52
+ @agent: Riffer::Agent
53
+
54
+ # @dynamic agent, cwd, host, settings
55
+ attr_reader agent: Riffer::Agent
56
+
57
+ attr_reader cwd: String
58
+
59
+ attr_reader host: _Host
60
+
61
+ attr_reader settings: Hash[Symbol, untyped]
62
+
63
+ # @rbs model: String
64
+ # @rbs extensions: Array[Riffer::Rig::Extension]
65
+ # @rbs tools: Array[String]?
66
+ # @rbs settings: Hash[Symbol, untyped]
67
+ # @rbs host: _Host
68
+ # @rbs cwd: String?
69
+ # @rbs name: String
70
+ # @rbs instructions: String?
71
+ # @rbs credentials: Hash[String, String]
72
+ # @rbs pricing: Hash[String, Riffer::Rig::Settings::Pricing]
73
+ # @rbs max_steps: Integer?
74
+ # @rbs snapshot: Hash[Symbol, untyped]?
75
+ # @rbs return: void
76
+ def initialize: (String model, ?extensions: Array[Riffer::Rig::Extension], ?tools: Array[String]?, ?settings: Hash[Symbol, untyped], ?host: _Host, ?cwd: String?, ?name: String, ?instructions: String?, ?credentials: Hash[String, String], ?pricing: Hash[String, Riffer::Rig::Settings::Pricing], ?max_steps: Integer?, ?snapshot: Hash[Symbol, untyped]?) -> void
77
+
78
+ # @rbs text: String
79
+ # @rbs &block: ?(Riffer::StreamEvents::Base) -> void
80
+ # @rbs return: (nil | Enumerator[Riffer::StreamEvents::Base, void])
81
+ def prompt: (String text) ?{ (Riffer::StreamEvents::Base) -> void } -> (nil | Enumerator[Riffer::StreamEvents::Base, void])
82
+
83
+ # @rbs text: String
84
+ # @rbs return: Riffer::Agent::Response
85
+ def ask: (String text) -> Riffer::Agent::Response
86
+
87
+ private
88
+
89
+ # @rbs extensions: Array[Riffer::Rig::Extension]
90
+ # @rbs return: Riffer::Rig::Registrar
91
+ def build_registrar: (Array[Riffer::Rig::Extension] extensions) -> Riffer::Rig::Registrar
92
+
93
+ # @rbs registered: Array[singleton(Riffer::Tool)]
94
+ # @rbs allowlist: Array[String]?
95
+ # @rbs return: Array[singleton(Riffer::Tool)]
96
+ def select_tools: (Array[singleton(Riffer::Tool)] registered, Array[String]? allowlist) -> Array[singleton(Riffer::Tool)]
97
+
98
+ # @rbs base_prompt: String
99
+ # @rbs return: String
100
+ def system_prompt: (String base_prompt) -> String
101
+ end
@@ -0,0 +1,20 @@
1
+ # Generated from lib/riffer/rig/settings/document.rb with RBS::Inline
2
+
3
+ class Riffer::Rig::Settings::Document
4
+ @model: String?
5
+
6
+ @reasoning: String?
7
+
8
+ @models: Hash[String, Riffer::Rig::Settings::Pricing]
9
+
10
+ # @dynamic model, reasoning, models
11
+ attr_reader model: String?
12
+
13
+ attr_reader reasoning: String?
14
+
15
+ attr_reader models: Hash[String, Riffer::Rig::Settings::Pricing]
16
+
17
+ # @rbs source: untyped
18
+ # @rbs return: void
19
+ def initialize: (untyped source) -> void
20
+ end
@@ -14,6 +14,10 @@ class Riffer::Rig::Settings::Pricing
14
14
  # @dynamic input, output, cache_write, cache_read
15
15
  attr_reader cache_read: Float
16
16
 
17
+ # @rbs entry: Hash[String, untyped]
18
+ # @rbs return: ::Riffer::Rig::Settings::Pricing
19
+ def self.from: (Hash[String, untyped] entry) -> ::Riffer::Rig::Settings::Pricing
20
+
17
21
  # @rbs input: Float
18
22
  # @rbs output: Float
19
23
  # @rbs cache_write: Float
@@ -71,9 +71,9 @@ module Riffer::Rig::Settings
71
71
  def base_options: (String? provider) -> Hash[Symbol, untyped]
72
72
 
73
73
  # @rbs path: String
74
- # @rbs ?provider: String?
74
+ # @rbs provider: String?
75
75
  # @rbs return: String?
76
- def reasoning_for: (?path: String, ?provider: untyped) -> String?
76
+ def reasoning_for: (?path: String, ?provider: String?) -> String?
77
77
 
78
78
  # Maps a reasoning level to the provider-specific model option hash expected
79
79
  # by Riffer. Returns an empty hash when +level+ is +nil+.
@@ -83,10 +83,10 @@ module Riffer::Rig::Settings
83
83
  # @rbs return: Hash[Symbol, untyped]
84
84
  def reasoning_options: (String? level, String? provider) -> Hash[Symbol, untyped]
85
85
 
86
- # The parsed settings file, or an empty hash when the file is absent or
86
+ # The parsed settings file, or an empty document when the file is absent or
87
87
  # malformed.
88
88
  #
89
89
  # @rbs path: String
90
- # @rbs return: Hash[String, untyped]
91
- def read: (String path) -> Hash[String, untyped]
90
+ # @rbs return: Document
91
+ def read: (String path) -> Document
92
92
  end
@@ -34,9 +34,9 @@ class Riffer::Rig::TokenTally
34
34
  # @dynamic input_tokens, output_tokens, cache_write_tokens, cache_read_tokens
35
35
  attr_reader cache_read_tokens: untyped
36
36
 
37
- # @rbs ?pricing: Riffer::Rig::Settings::Pricing?
37
+ # @rbs pricing: Riffer::Rig::Settings::Pricing?
38
38
  # @rbs return: void
39
- def initialize: (?pricing: untyped) -> void
39
+ def initialize: (?pricing: Riffer::Rig::Settings::Pricing?) -> void
40
40
 
41
41
  # Accumulates token counts from a +Riffer::Providers::TokenUsage+ object.
42
42
  #
@@ -7,9 +7,9 @@ class Riffer::Rig::Tools::Bash < Riffer::Tool
7
7
 
8
8
  # @rbs context: Riffer::Agent::Context?
9
9
  # @rbs command: String
10
- # @rbs ?timeout_ms: Integer
10
+ # @rbs timeout_ms: Integer
11
11
  # @rbs return: Riffer::Tools::Response
12
- def call: (context: Riffer::Agent::Context?, command: String, ?timeout_ms: untyped) -> Riffer::Tools::Response
12
+ def call: (context: Riffer::Agent::Context?, command: String, ?timeout_ms: Integer) -> Riffer::Tools::Response
13
13
 
14
14
  private
15
15
 
@@ -5,7 +5,7 @@ class Riffer::Rig::Tools::Edit < Riffer::Tool
5
5
  # @rbs path: String
6
6
  # @rbs old_string: String
7
7
  # @rbs new_string: String
8
- # @rbs ?replace_all: bool
8
+ # @rbs replace_all: bool
9
9
  # @rbs return: Riffer::Tools::Response
10
- def call: (context: Riffer::Agent::Context?, path: String, old_string: String, new_string: String, ?replace_all: untyped) -> Riffer::Tools::Response
10
+ def call: (context: Riffer::Agent::Context?, path: String, old_string: String, new_string: String, ?replace_all: bool) -> Riffer::Tools::Response
11
11
  end
@@ -5,8 +5,8 @@ class Riffer::Rig::Tools::Read < Riffer::Tool
5
5
 
6
6
  # @rbs context: Riffer::Agent::Context?
7
7
  # @rbs path: String
8
- # @rbs ?offset: Integer?
9
- # @rbs ?limit: Integer
8
+ # @rbs offset: Integer?
9
+ # @rbs limit: Integer
10
10
  # @rbs return: Riffer::Tools::Response
11
- def call: (context: Riffer::Agent::Context?, path: String, ?offset: untyped, ?limit: untyped) -> Riffer::Tools::Response
11
+ def call: (context: Riffer::Agent::Context?, path: String, ?offset: Integer?, ?limit: Integer) -> Riffer::Tools::Response
12
12
  end
@@ -27,12 +27,12 @@ class Riffer::Rig::UI::Animator
27
27
 
28
28
  @theme: Riffer::Rig::UI::Theme
29
29
 
30
- @io: untyped
30
+ @io: IO
31
31
 
32
- # @rbs io: untyped
33
- # @rbs ?theme: Riffer::Rig::UI::Theme
32
+ # @rbs io: IO
33
+ # @rbs theme: Riffer::Rig::UI::Theme
34
34
  # @rbs return: void
35
- def initialize: (?io: untyped, ?theme: untyped) -> void
35
+ def initialize: (?io: IO, ?theme: Riffer::Rig::UI::Theme) -> void
36
36
 
37
37
  # When not on a TTY, prints the final frame once instead of animating.
38
38
  #
@@ -40,17 +40,17 @@ class Riffer::Rig::UI::Animator
40
40
  # @rbs return: void
41
41
  def reveal: (Array[Array[String]] frames) -> void
42
42
 
43
- # @rbs ?mode: Symbol
43
+ # @rbs mode: Symbol
44
44
  # @rbs return: void
45
- def start: (?untyped mode) -> void
45
+ def start: (?Symbol mode) -> void
46
46
 
47
47
  # @rbs return: void
48
48
  def stop: () -> void
49
49
 
50
50
  # @rbs tick: Integer
51
- # @rbs ?label: String
51
+ # @rbs label: String
52
52
  # @rbs return: String
53
- def equalizer: (Integer tick, ?untyped label) -> String
53
+ def equalizer: (Integer tick, ?String label) -> String
54
54
 
55
55
  private
56
56
 
@@ -7,14 +7,14 @@ class Riffer::Rig::UI::Cursor
7
7
 
8
8
  SHOW: String
9
9
 
10
- @io: untyped
10
+ @io: IO
11
11
 
12
12
  @theme: Riffer::Rig::UI::Theme
13
13
 
14
- # @rbs io: untyped
15
- # @rbs ?theme: Riffer::Rig::UI::Theme
14
+ # @rbs io: IO
15
+ # @rbs theme: Riffer::Rig::UI::Theme
16
16
  # @rbs return: void
17
- def initialize: (?io: untyped, ?theme: untyped) -> void
17
+ def initialize: (?io: IO, ?theme: Riffer::Rig::UI::Theme) -> void
18
18
 
19
19
  # @rbs return: void
20
20
  def hide: () -> void