riffer 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8975a79d79a073d1bca29cd43216049766975f010b74dbc6ba1dbaaf22f69982
4
- data.tar.gz: 5473e7c42541581bf7ad3c2efd046a3f3e76201e8b0c1a9a5ef324cc8175ae47
3
+ metadata.gz: 4e6c1902fc4a3a1ad047491befa79ae44aa7aea3e160dda3303fe18c3670e477
4
+ data.tar.gz: d4407ecd6a3af8900e7a2a456870e5e4a4211df016259980bf8f5b559ad8df2f
5
5
  SHA512:
6
- metadata.gz: a331b45d49617ffaa73b65df988d2b018fcc214c25480880bb9b420ac3415a5abf5a4703e2e1568d3982c7bebad77a3710b8d1f04a83b0f063117e35298bc485
7
- data.tar.gz: 3ed3b7446ce0385cf0a70a795ac7c00c27dc786a815b66bf77fe3927e4cb9bbae806342835eeb0759a5b7dcf8eb3b04df8fad249a69040e8b7a48a88da7435fe
6
+ metadata.gz: 5845e5336564993a8e23ff6a5a1c903fb28925991443d4beb2673a49f7d2d49587a2e799330ea1e30614f7c63343b35a9828d0a1ee1744d6c96e19c7aa476cc2
7
+ data.tar.gz: b0c71cf0f09e04982b4942b75d7dee3cee757a007a6d7279ca036fa5f81ae2216690d630f3e0a34e5ba1ea07d680f034b0d85568c5111c37805a3ff72f4d6eb5
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.21.0"
2
+ ".": "0.22.0"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.22.0](https://github.com/janeapp/riffer/compare/riffer/v0.21.0...riffer/v0.22.0) (2026-04-09)
9
+
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * `Tool.name` returns `namespace/tool_name` instead of `namespace__tool_name`.
14
+
15
+ ### Features
16
+
17
+ * use human-friendly `/` separator for tool names ([#202](https://github.com/janeapp/riffer/issues/202)) ([8dda251](https://github.com/janeapp/riffer/commit/8dda251ff6d91a6cebbbb82082b7ac21c2a51253))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * release 0.22.0 ([#204](https://github.com/janeapp/riffer/issues/204)) ([860a500](https://github.com/janeapp/riffer/commit/860a500bb6e991de8018b43cda0c5f2662e22402))
23
+
8
24
  ## [0.21.0](https://github.com/janeapp/riffer/compare/riffer/v0.20.0...riffer/v0.21.0) (2026-04-09)
9
25
 
10
26
 
@@ -120,7 +120,7 @@ class Riffer::Providers::AmazonBedrock < Riffer::Providers::Base
120
120
  if block.respond_to?(:tool_use) && block.tool_use
121
121
  tool_calls << Riffer::Messages::Assistant::ToolCall.new(
122
122
  call_id: block.tool_use.tool_use_id,
123
- name: block.tool_use.name,
123
+ name: decode_tool_name(block.tool_use.name, tools: @current_tools),
124
124
  arguments: block.tool_use.input.to_json
125
125
  )
126
126
  end
@@ -160,7 +160,7 @@ class Riffer::Providers::AmazonBedrock < Riffer::Providers::Base
160
160
  def handle_content_block_start_tool_use(event, state:, yielder:)
161
161
  state[:tool_call] = {
162
162
  id: event.start.tool_use.tool_use_id,
163
- name: event.start.tool_use.name,
163
+ name: decode_tool_name(event.start.tool_use.name, tools: @current_tools),
164
164
  arguments: ""
165
165
  }
166
166
  end
@@ -258,7 +258,7 @@ class Riffer::Providers::AmazonBedrock < Riffer::Providers::Base
258
258
  content << {
259
259
  tool_use: {
260
260
  tool_use_id: tc.call_id,
261
- name: tc.name,
261
+ name: encode_tool_name(tc.name),
262
262
  input: parse_tool_arguments(tc.arguments)
263
263
  }
264
264
  }
@@ -327,7 +327,7 @@ class Riffer::Providers::AmazonBedrock < Riffer::Providers::Base
327
327
  def convert_tool_to_bedrock_format(tool)
328
328
  {
329
329
  tool_spec: {
330
- name: tool.name,
330
+ name: encode_tool_name(tool.name),
331
331
  description: tool.description,
332
332
  input_schema: {
333
333
  json: tool.parameters_schema(strict: true)
@@ -123,7 +123,7 @@ class Riffer::Providers::Anthropic < Riffer::Providers::Base
123
123
  if block.type.to_s == "tool_use"
124
124
  tool_calls << Riffer::Messages::Assistant::ToolCall.new(
125
125
  call_id: block.id,
126
- name: block.name,
126
+ name: decode_tool_name(block.name, tools: @current_tools),
127
127
  arguments: block.input.to_json
128
128
  )
129
129
  end
@@ -229,7 +229,7 @@ class Riffer::Providers::Anthropic < Riffer::Providers::Base
229
229
  yielder << Riffer::StreamEvents::ToolCallDone.new(
230
230
  item_id: content_block.id,
231
231
  call_id: content_block.id,
232
- name: content_block.name,
232
+ name: decode_tool_name(content_block.name, tools: @current_tools),
233
233
  arguments: arguments
234
234
  )
235
235
  state[:tool_call] = nil
@@ -339,7 +339,7 @@ class Riffer::Providers::Anthropic < Riffer::Providers::Base
339
339
  content << {
340
340
  type: "tool_use",
341
341
  id: tc.call_id,
342
- name: tc.name,
342
+ name: encode_tool_name(tc.name),
343
343
  input: parse_tool_arguments(tc.arguments)
344
344
  }
345
345
  end
@@ -365,7 +365,7 @@ class Riffer::Providers::Anthropic < Riffer::Providers::Base
365
365
  #: (singleton(Riffer::Tool)) -> Hash[Symbol, untyped]
366
366
  def convert_tool_to_anthropic_format(tool)
367
367
  {
368
- name: tool.name,
368
+ name: encode_tool_name(tool.name),
369
369
  description: tool.description,
370
370
  input_schema: tool.parameters_schema(strict: true)
371
371
  }
@@ -20,6 +20,8 @@ class Riffer::Providers::Base
20
20
  include Riffer::Helpers::Dependencies
21
21
  include Riffer::Messages::Converter
22
22
 
23
+ WIRE_SEPARATOR = "__" #: String
24
+
23
25
  # Returns the preferred skill adapter for this provider.
24
26
  #
25
27
  # Override in subclasses for provider-specific formats.
@@ -36,6 +38,7 @@ class Riffer::Providers::Base
36
38
  #: (?prompt: String?, ?system: String?, ?messages: Array[Hash[Symbol, untyped] | Riffer::Messages::Base]?, ?model: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::FilePart]?, **untyped) -> Riffer::Messages::Assistant
37
39
  def generate_text(prompt: nil, system: nil, messages: nil, model: nil, files: nil, **options)
38
40
  validate_input!(prompt: prompt, system: system, messages: messages)
41
+ @current_tools = options[:tools] || []
39
42
  messages = normalize_messages(prompt: prompt, system: system, messages: messages, files: files)
40
43
  validate_normalized_messages!(messages)
41
44
  messages = merge_consecutive_messages(messages)
@@ -61,6 +64,7 @@ class Riffer::Providers::Base
61
64
  #: (?prompt: String?, ?system: String?, ?messages: Array[Hash[Symbol, untyped] | Riffer::Messages::Base]?, ?model: String?, ?files: Array[Hash[Symbol, untyped] | Riffer::FilePart]?, **untyped) -> Enumerator[Riffer::StreamEvents::Base, void]
62
65
  def stream_text(prompt: nil, system: nil, messages: nil, model: nil, files: nil, **options)
63
66
  validate_input!(prompt: prompt, system: system, messages: messages)
67
+ @current_tools = options[:tools] || []
64
68
  messages = normalize_messages(prompt: prompt, system: system, messages: messages, files: files)
65
69
  validate_normalized_messages!(messages)
66
70
  messages = merge_consecutive_messages(messages)
@@ -72,6 +76,19 @@ class Riffer::Providers::Base
72
76
 
73
77
  private
74
78
 
79
+ #--
80
+ #: (String) -> String
81
+ def encode_tool_name(name)
82
+ name.gsub("/", WIRE_SEPARATOR)
83
+ end
84
+
85
+ #--
86
+ #: (String, tools: Array[Riffer::Tool]) -> String
87
+ def decode_tool_name(wire_name, tools:)
88
+ tool = tools.find { |t| encode_tool_name(t.name) == wire_name }
89
+ tool ? tool.name : wire_name
90
+ end
91
+
75
92
  #--
76
93
  #: (Array[Riffer::Messages::Base], String?, Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
77
94
  def build_request_params(messages, model, options)
@@ -107,7 +107,7 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
107
107
  if item.type == :function_call
108
108
  tool_calls << Riffer::Messages::Assistant::ToolCall.new(
109
109
  call_id: item.call_id,
110
- name: item.name,
110
+ name: decode_tool_name(item.name, tools: @current_tools),
111
111
  arguments: item.arguments
112
112
  )
113
113
  end
@@ -158,7 +158,7 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
158
158
  #: (untyped, state: Hash[Symbol, untyped], yielder: Enumerator::Yielder) -> void
159
159
  def handle_output_item_added_function_call(event, state:, yielder:)
160
160
  state[:tool_info][event.item.id] = {
161
- name: event.item.name,
161
+ name: decode_tool_name(event.item.name, tools: @current_tools),
162
162
  call_id: event.item.call_id
163
163
  }
164
164
  end
@@ -284,7 +284,7 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
284
284
  items << {
285
285
  type: "function_call",
286
286
  call_id: tc.call_id,
287
- name: tc.name,
287
+ name: encode_tool_name(tc.name),
288
288
  arguments: tc.arguments.is_a?(String) ? tc.arguments : tc.arguments.to_json
289
289
  }
290
290
  end
@@ -311,7 +311,7 @@ class Riffer::Providers::OpenAI < Riffer::Providers::Base
311
311
  def convert_tool_to_openai_format(tool)
312
312
  {
313
313
  type: "function",
314
- name: tool.name,
314
+ name: encode_tool_name(tool.name),
315
315
  description: tool.description,
316
316
  parameters: tool.parameters_schema(strict: true),
317
317
  strict: true
data/lib/riffer/tool.rb CHANGED
@@ -26,9 +26,6 @@ require "timeout"
26
26
  class Riffer::Tool
27
27
  DEFAULT_TIMEOUT = 10 #: Integer
28
28
 
29
- # Some providers do not allow "/" in tool names, so we use "__" as separator.
30
- TOOL_SEPARATOR = "__" #: String
31
-
32
29
  extend Riffer::Helpers::ClassNameConverter
33
30
 
34
31
  # Gets or sets the tool description.
@@ -45,7 +42,7 @@ class Riffer::Tool
45
42
  #--
46
43
  #: (?String?) -> String
47
44
  def self.identifier(value = nil)
48
- return @identifier || class_name_to_path(Module.instance_method(:name).bind_call(self), separator: TOOL_SEPARATOR) if value.nil?
45
+ return @identifier || class_name_to_path(Module.instance_method(:name).bind_call(self)) if value.nil?
49
46
  @identifier = value.to_s
50
47
  end
51
48
 
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Riffer
5
- VERSION = "0.21.0" #: String
5
+ VERSION = "0.22.0" #: String
6
6
  end
@@ -18,6 +18,8 @@ class Riffer::Providers::Base
18
18
 
19
19
  include Riffer::Messages::Converter
20
20
 
21
+ WIRE_SEPARATOR: String
22
+
21
23
  # Returns the preferred skill adapter for this provider.
22
24
  #
23
25
  # Override in subclasses for provider-specific formats.
@@ -40,6 +42,14 @@ class Riffer::Providers::Base
40
42
 
41
43
  private
42
44
 
45
+ # --
46
+ # : (String) -> String
47
+ def encode_tool_name: (String) -> String
48
+
49
+ # --
50
+ # : (String, tools: Array[Riffer::Tool]) -> String
51
+ def decode_tool_name: (String, tools: Array[Riffer::Tool]) -> String
52
+
43
53
  # --
44
54
  # : (Array[Riffer::Messages::Base], String?, Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
45
55
  def build_request_params: (Array[Riffer::Messages::Base], String?, Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
@@ -22,9 +22,6 @@
22
22
  class Riffer::Tool
23
23
  DEFAULT_TIMEOUT: Integer
24
24
 
25
- # Some providers do not allow "/" in tool names, so we use "__" as separator.
26
- TOOL_SEPARATOR: String
27
-
28
25
  extend Riffer::Helpers::ClassNameConverter
29
26
 
30
27
  # Gets or sets the tool description.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riffer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Bottrall