anthropic 1.1.0 → 1.2.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -0
  3. data/README.md +32 -16
  4. data/lib/anthropic/errors.rb +22 -0
  5. data/lib/anthropic/helpers/bedrock/client.rb +3 -1
  6. data/lib/anthropic/helpers/streaming/events.rb +141 -0
  7. data/lib/anthropic/helpers/streaming/message_stream.rb +238 -0
  8. data/lib/anthropic/helpers/streaming.rb +37 -0
  9. data/lib/anthropic/helpers/vertex/client.rb +8 -3
  10. data/lib/anthropic/internal/stream.rb +4 -2
  11. data/lib/anthropic/internal/transport/base_client.rb +10 -2
  12. data/lib/anthropic/internal/type/array_of.rb +6 -1
  13. data/lib/anthropic/internal/type/base_model.rb +77 -23
  14. data/lib/anthropic/internal/type/base_stream.rb +3 -1
  15. data/lib/anthropic/internal/type/boolean.rb +7 -1
  16. data/lib/anthropic/internal/type/converter.rb +42 -34
  17. data/lib/anthropic/internal/type/enum.rb +16 -5
  18. data/lib/anthropic/internal/type/file_input.rb +6 -1
  19. data/lib/anthropic/internal/type/hash_of.rb +6 -1
  20. data/lib/anthropic/internal/type/union.rb +17 -9
  21. data/lib/anthropic/internal/type/unknown.rb +7 -1
  22. data/lib/anthropic/internal/util.rb +18 -11
  23. data/lib/anthropic/models/beta/beta_base64_pdf_block.rb +1 -65
  24. data/lib/anthropic/models/beta/beta_citation_search_result_location.rb +55 -0
  25. data/lib/anthropic/models/beta/beta_citation_search_result_location_param.rb +55 -0
  26. data/lib/anthropic/models/beta/beta_citations_delta.rb +5 -3
  27. data/lib/anthropic/models/beta/beta_content_block.rb +5 -5
  28. data/lib/anthropic/models/beta/beta_content_block_param.rb +20 -17
  29. data/lib/anthropic/models/beta/beta_message.rb +6 -2
  30. data/lib/anthropic/models/beta/beta_message_param.rb +3 -3
  31. data/lib/anthropic/models/beta/beta_raw_content_block_start_event.rb +7 -7
  32. data/lib/anthropic/models/beta/beta_request_document_block.rb +75 -0
  33. data/lib/anthropic/models/beta/beta_search_result_block_param.rb +55 -0
  34. data/lib/anthropic/models/beta/beta_text_block.rb +2 -2
  35. data/lib/anthropic/models/beta/beta_text_block_param.rb +2 -2
  36. data/lib/anthropic/models/beta/beta_text_citation.rb +3 -1
  37. data/lib/anthropic/models/beta/beta_text_citation_param.rb +3 -1
  38. data/lib/anthropic/models/beta/beta_tool.rb +7 -1
  39. data/lib/anthropic/models/beta/beta_tool_result_block_param.rb +6 -4
  40. data/lib/anthropic/models/beta/beta_tool_union.rb +7 -7
  41. data/lib/anthropic/models/beta/message_count_tokens_params.rb +16 -10
  42. data/lib/anthropic/models/beta/message_create_params.rb +9 -3
  43. data/lib/anthropic/models/beta/messages/batch_create_params.rb +9 -3
  44. data/lib/anthropic/models/content_block.rb +5 -5
  45. data/lib/anthropic/models/content_block_param.rb +11 -11
  46. data/lib/anthropic/models/message.rb +6 -2
  47. data/lib/anthropic/models/message_count_tokens_params.rb +9 -3
  48. data/lib/anthropic/models/message_count_tokens_tool.rb +35 -1
  49. data/lib/anthropic/models/message_create_params.rb +9 -3
  50. data/lib/anthropic/models/message_param.rb +3 -3
  51. data/lib/anthropic/models/messages/batch_create_params.rb +9 -3
  52. data/lib/anthropic/models/model.rb +6 -0
  53. data/lib/anthropic/models/raw_content_block_start_event.rb +7 -7
  54. data/lib/anthropic/models/tool.rb +7 -1
  55. data/lib/anthropic/models/tool_union.rb +34 -1
  56. data/lib/anthropic/models/tool_use_block.rb +6 -0
  57. data/lib/anthropic/models.rb +4 -4
  58. data/lib/anthropic/resources/beta/messages.rb +5 -5
  59. data/lib/anthropic/resources/messages.rb +68 -7
  60. data/lib/anthropic/streaming.rb +5 -0
  61. data/lib/anthropic/version.rb +1 -1
  62. data/lib/anthropic.rb +11 -1
  63. data/rbi/anthropic/errors.rbi +16 -0
  64. data/rbi/anthropic/helpers/streaming/events.rbi +85 -0
  65. data/rbi/anthropic/helpers/streaming/message_stream.rbi +59 -0
  66. data/rbi/anthropic/internal/type/base_stream.rbi +8 -1
  67. data/rbi/anthropic/internal/type/boolean.rbi +2 -0
  68. data/rbi/anthropic/internal/type/converter.rbi +15 -15
  69. data/rbi/anthropic/internal/type/union.rbi +5 -0
  70. data/rbi/anthropic/internal/type/unknown.rbi +2 -0
  71. data/rbi/anthropic/internal/util.rbi +2 -0
  72. data/rbi/anthropic/models/beta/beta_base64_pdf_block.rbi +1 -128
  73. data/rbi/anthropic/models/beta/beta_citation_search_result_location.rbi +78 -0
  74. data/rbi/anthropic/models/beta/beta_citation_search_result_location_param.rbi +79 -0
  75. data/rbi/anthropic/models/beta/beta_citations_delta.rbi +4 -2
  76. data/rbi/anthropic/models/beta/beta_content_block.rbi +3 -3
  77. data/rbi/anthropic/models/beta/beta_content_block_param.rbi +8 -7
  78. data/rbi/anthropic/models/beta/beta_message.rbi +11 -3
  79. data/rbi/anthropic/models/beta/beta_raw_content_block_start_event.rbi +6 -6
  80. data/rbi/anthropic/models/beta/beta_request_document_block.rbi +140 -0
  81. data/rbi/anthropic/models/beta/beta_search_result_block_param.rbi +91 -0
  82. data/rbi/anthropic/models/beta/beta_text_block.rbi +2 -1
  83. data/rbi/anthropic/models/beta/beta_text_block_param.rbi +6 -3
  84. data/rbi/anthropic/models/beta/beta_text_citation.rbi +2 -1
  85. data/rbi/anthropic/models/beta/beta_text_citation_param.rbi +2 -1
  86. data/rbi/anthropic/models/beta/beta_tool.rbi +14 -5
  87. data/rbi/anthropic/models/beta/beta_tool_result_block_param.rbi +2 -1
  88. data/rbi/anthropic/models/beta/beta_tool_union.rbi +5 -5
  89. data/rbi/anthropic/models/beta/message_count_tokens_params.rbi +39 -27
  90. data/rbi/anthropic/models/beta/message_create_params.rbi +34 -22
  91. data/rbi/anthropic/models/beta/messages/batch_create_params.rbi +34 -22
  92. data/rbi/anthropic/models/content_block.rbi +3 -3
  93. data/rbi/anthropic/models/content_block_param.rbi +5 -5
  94. data/rbi/anthropic/models/message.rbi +11 -3
  95. data/rbi/anthropic/models/message_count_tokens_params.rbi +18 -2
  96. data/rbi/anthropic/models/message_count_tokens_tool.rbi +61 -0
  97. data/rbi/anthropic/models/message_create_params.rbi +18 -2
  98. data/rbi/anthropic/models/messages/batch_create_params.rbi +18 -2
  99. data/rbi/anthropic/models/raw_content_block_start_event.rbi +6 -6
  100. data/rbi/anthropic/models/tool.rbi +16 -5
  101. data/rbi/anthropic/models/tool_union.rbi +61 -0
  102. data/rbi/anthropic/resources/beta/messages.rbi +36 -18
  103. data/rbi/anthropic/resources/messages.rbi +293 -3
  104. data/rbi/anthropic/streaming.rbi +5 -0
  105. data/sig/anthropic/errors.rbs +9 -0
  106. data/sig/anthropic/helpers/streaming/events.rbs +119 -0
  107. data/sig/anthropic/helpers/streaming/message_stream.rbs +55 -0
  108. data/sig/anthropic/internal/type/base_stream.rbs +4 -0
  109. data/sig/anthropic/internal/type/converter.rbs +7 -1
  110. data/sig/anthropic/models/beta/beta_base64_pdf_block.rbs +1 -58
  111. data/sig/anthropic/models/beta/beta_citation_search_result_location.rbs +54 -0
  112. data/sig/anthropic/models/beta/beta_citation_search_result_location_param.rbs +54 -0
  113. data/sig/anthropic/models/beta/beta_citations_delta.rbs +1 -0
  114. data/sig/anthropic/models/beta/beta_content_block.rbs +2 -2
  115. data/sig/anthropic/models/beta/beta_content_block_param.rbs +9 -8
  116. data/sig/anthropic/models/beta/beta_raw_content_block_start_event.rbs +2 -2
  117. data/sig/anthropic/models/beta/beta_request_document_block.rbs +66 -0
  118. data/sig/anthropic/models/beta/beta_search_result_block_param.rbs +53 -0
  119. data/sig/anthropic/models/beta/beta_text_citation.rbs +1 -0
  120. data/sig/anthropic/models/beta/beta_text_citation_param.rbs +1 -0
  121. data/sig/anthropic/models/beta/beta_tool.rbs +14 -3
  122. data/sig/anthropic/models/beta/beta_tool_result_block_param.rbs +1 -0
  123. data/sig/anthropic/models/beta/beta_tool_union.rbs +4 -4
  124. data/sig/anthropic/models/beta/message_count_tokens_params.rbs +4 -4
  125. data/sig/anthropic/models/content_block.rbs +2 -2
  126. data/sig/anthropic/models/content_block_param.rbs +5 -5
  127. data/sig/anthropic/models/message_count_tokens_tool.rbs +28 -0
  128. data/sig/anthropic/models/raw_content_block_start_event.rbs +2 -2
  129. data/sig/anthropic/models/tool.rbs +14 -3
  130. data/sig/anthropic/models/tool_union.rbs +28 -0
  131. data/sig/anthropic/streaming.rbs +3 -0
  132. metadata +26 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40c9c7c712197e8666740804eca676d573e5214f541cf983e0427f76b8eaefe3
4
- data.tar.gz: 2423170ab39925e637cb77782db3883645d0064d4582a87afcd50bd6fec6e7af
3
+ metadata.gz: 4d36e1f15e69568a09c53f6050d60cf715dd92adf8df94877f9ea59693a58f16
4
+ data.tar.gz: 862a093342067fecddb4c2cc2c9365c2a0a69ffd6d93661c7ee5c70056606bba
5
5
  SHA512:
6
- metadata.gz: 503e09fa3681d40df1045b3cc57c29e7e81594f44011e837dd8ea41f0c6c0b7fbe35c4659d9e5d1803f7ec0dc73bfea0c8ebb70249820e8d1854c4a9b8b127d8
7
- data.tar.gz: 810826a076fbc6614429d4ed0ae073e90487a9fb17521375ed174d087c9b1ec865c7d12470ab5c4b77bc3d62cec2016a356a0a5c3e26b4fcce31c5101ba90366
6
+ metadata.gz: 4ce2b4e8c467b715b86b3e2756ffaa3a7b7df6b37eff492c8d0b552adaaa5b1c6efb3172308d0b61f9abecdfa2f392c70a3ac850678b1c92806865eaad1851c5
7
+ data.tar.gz: 80fc591eac84e7d9e95cae8b7d5ed51a7a68ae19f3c66c1a27442f3f46838050e50d939132e019452218766eec3fc6d7d40db5092fbedfdaec25c970c3ccceed
data/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.0 (2025-07-18)
4
+
5
+ Full Changelog: [v1.1.1...v1.2.0](https://github.com/anthropics/anthropic-sdk-ruby/compare/v1.1.1...v1.2.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** add support for Search Result Content Blocks ([158a7ce](https://github.com/anthropics/anthropic-sdk-ruby/commit/158a7ced1013c3af956554caf41ee08ec5d1db3c))
10
+ * **api:** api update ([cd22765](https://github.com/anthropics/anthropic-sdk-ruby/commit/cd2276536c7960a4f7276ceb9baba8ba5aec196e))
11
+ * **api:** manual updates ([7f51b33](https://github.com/anthropics/anthropic-sdk-ruby/commit/7f51b336943422d230d8704583f42dc6f8a3ac62))
12
+ * **client:** add breaking change detection to CI ([52e342f](https://github.com/anthropics/anthropic-sdk-ruby/commit/52e342fe8c8231ad6b6b6ff68ed522033cd503c7))
13
+ * **client:** add support for new text_editor_20250429 tool ([9049af2](https://github.com/anthropics/anthropic-sdk-ruby/commit/9049af2f634f88d867104f2dc0ddc6396f5f8031))
14
+ * streaming helpers ([#627](https://github.com/anthropics/anthropic-sdk-ruby/issues/627)) ([43fbbf8](https://github.com/anthropics/anthropic-sdk-ruby/commit/43fbbf8a39ac1d99920845ba19da43d7419a5e73))
15
+ * **vertex:** support global region endpoint ([da8c452](https://github.com/anthropics/anthropic-sdk-ruby/commit/da8c452a22c56780f311f4f1ab3477a48ac46891))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * `to_sorbet_type` should not return branded types ([2658903](https://github.com/anthropics/anthropic-sdk-ruby/commit/2658903f13178a133ca679f4b87615e9cddcd813))
21
+ * **ci:** release-doctor — report correct token name ([e30183e](https://github.com/anthropics/anthropic-sdk-ruby/commit/e30183e5561070dfd3dfe041f48e76765975cb3b))
22
+ * **client:** deprecate BetaBase64PDFBlock in favor of BetaRequestDocumentBlock ([f75705b](https://github.com/anthropics/anthropic-sdk-ruby/commit/f75705bfb4af3160b2fa7208adfad10719cd17a7))
23
+ * default content-type for text in multi-part formdata uploads should be text/plain ([0a91592](https://github.com/anthropics/anthropic-sdk-ruby/commit/0a915925fc93ca7ad191bab33dba8c72b6c48a2a))
24
+ * **internal:** fix: should publish to ruby gems when a release is created ([cc88c6c](https://github.com/anthropics/anthropic-sdk-ruby/commit/cc88c6c7c164c5bb1937e12cefb4d91f05fec157))
25
+ * issue where we cannot mutate arrays on base model derivatives ([446c8be](https://github.com/anthropics/anthropic-sdk-ruby/commit/446c8be0eb77a29641d472ea36cbaf6f786f7e3a))
26
+
27
+
28
+ ### Chores
29
+
30
+ * add `license` to the gemspec ([#101](https://github.com/anthropics/anthropic-sdk-ruby/issues/101)) ([af509a7](https://github.com/anthropics/anthropic-sdk-ruby/commit/af509a735c0e985e615f9279bc070dc090874df8))
31
+ * add RBS types for helpers/streaming ([#631](https://github.com/anthropics/anthropic-sdk-ruby/issues/631)) ([0d7941d](https://github.com/anthropics/anthropic-sdk-ruby/commit/0d7941df6628b1500f7e7e8def88f613d7bcf2fa))
32
+ * **api:** mark claude-3-opus-20240229 as deprecated ([1edd9bd](https://github.com/anthropics/anthropic-sdk-ruby/commit/1edd9bdf0bf508f5467daf92c4b1db11128d70ea))
33
+ * **api:** update BetaCitationSearchResultLocation ([b294f7e](https://github.com/anthropics/anthropic-sdk-ruby/commit/b294f7e2bfd44d01504eeb7e30b37926ca7200e2))
34
+ * **ci:** enable for pull requests ([31bbb43](https://github.com/anthropics/anthropic-sdk-ruby/commit/31bbb43d02cc56505ad5ec8d737801b73f9f5fd8))
35
+ * **ci:** link to correct github repo ([37b5902](https://github.com/anthropics/anthropic-sdk-ruby/commit/37b59027a26268ad5bb20ee6530c7f0c630bc5b5))
36
+ * **ci:** only run for pushes and fork pull requests ([8d3c942](https://github.com/anthropics/anthropic-sdk-ruby/commit/8d3c9425afe873a49e403c7a8a36f14642191a89))
37
+ * **internal:** allow streams to also be unwrapped on a per-row basis ([a271d21](https://github.com/anthropics/anthropic-sdk-ruby/commit/a271d21d2f01a9f7c9c2d126b1f3d9b0611dd8cd))
38
+ * **internal:** codegen related update ([8b12fd6](https://github.com/anthropics/anthropic-sdk-ruby/commit/8b12fd6e8ec1c06d3cbf7d20c63c6933538d0983))
39
+ * remove workaround for updating arrays in place in streaming ([#643](https://github.com/anthropics/anthropic-sdk-ruby/issues/643)) ([e0a30b8](https://github.com/anthropics/anthropic-sdk-ruby/commit/e0a30b8128624566f673ac77f97c305953b11c63))
40
+
41
+
42
+ ### Documentation
43
+
44
+ * model in examples ([18ba0b6](https://github.com/anthropics/anthropic-sdk-ruby/commit/18ba0b62bd8f87b84766265726090ca2265a64b7))
45
+ * update documentation in MessageStream ([#630](https://github.com/anthropics/anthropic-sdk-ruby/issues/630)) ([4795c73](https://github.com/anthropics/anthropic-sdk-ruby/commit/4795c73f0628d2bc710f77bd0868be18c53ec31a))
46
+ * update models and non-beta ([a4ea04e](https://github.com/anthropics/anthropic-sdk-ruby/commit/a4ea04eaf88e608612512d39d07051842beaf500))
47
+
48
+ ## 1.1.1 (2025-05-28)
49
+
50
+ Full Changelog: [v1.1.0...v1.1.1](https://github.com/anthropics/anthropic-sdk-ruby/compare/v1.1.0...v1.1.1)
51
+
52
+ ### Bug Fixes
53
+
54
+ * prevent rubocop from mangling `===` to `is_a?` check ([303ad55](https://github.com/anthropics/anthropic-sdk-ruby/commit/303ad550c542c726b2ce8bc3d53e01108af634d5))
55
+ * sorbet types for enums, and make tapioca detection ignore `tapioca dsl` ([fb289a1](https://github.com/anthropics/anthropic-sdk-ruby/commit/fb289a1be37379cea207b024e0fb4503ea174639))
56
+
57
+
58
+ ### Chores
59
+
60
+ * add more examples ([e14665e](https://github.com/anthropics/anthropic-sdk-ruby/commit/e14665e4e236cce4a17de06507d1b855d1d153d2))
61
+ * image example ([#621](https://github.com/anthropics/anthropic-sdk-ruby/issues/621)) ([9bdc648](https://github.com/anthropics/anthropic-sdk-ruby/commit/9bdc6487d77d856c87d658917f53faa6f12bc38f))
62
+ * **internal:** fix release workflows ([fffb4b8](https://github.com/anthropics/anthropic-sdk-ruby/commit/fffb4b8eeff759ac98e9cfb5d778b014336e2956))
63
+ * more examples ([#619](https://github.com/anthropics/anthropic-sdk-ruby/issues/619)) ([e14665e](https://github.com/anthropics/anthropic-sdk-ruby/commit/e14665e4e236cce4a17de06507d1b855d1d153d2))
64
+
3
65
  ## 1.1.0 (2025-05-22)
4
66
 
5
67
  Full Changelog: [v1.0.0...v1.1.0](https://github.com/anthropics/anthropic-sdk-ruby/compare/v1.0.0...v1.1.0)
data/README.md CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
15
15
  <!-- x-release-please-start-version -->
16
16
 
17
17
  ```ruby
18
- gem "anthropic", "~> 1.1.0"
18
+ gem "anthropic", "~> 1.2.0"
19
19
  ```
20
20
 
21
21
  <!-- x-release-please-end -->
@@ -39,7 +39,7 @@ anthropic = Anthropic::Client.new(
39
39
  message = anthropic.messages.create(
40
40
  max_tokens: 1024,
41
41
  messages: [{role: "user", content: "Hello, Claude"}],
42
- model: :"claude-3-7-sonnet-latest"
42
+ model: :"claude-sonnet-4-20250514"
43
43
  )
44
44
 
45
45
  puts(message.content)
@@ -49,13 +49,11 @@ puts(message.content)
49
49
 
50
50
  We provide support for streaming responses using Server-Sent Events (SSE).
51
51
 
52
- **coming soon**: `anthropic.messages.stream` will have [Python SDK](https://github.com/anthropics/anthropic-sdk-python?tab=readme-ov-file#streaming-helpers) style streaming response helpers.
53
-
54
52
  ```ruby
55
- stream = anthropic.messages.stream_raw(
53
+ stream = anthropic.messages.stream(
56
54
  max_tokens: 1024,
57
55
  messages: [{role: "user", content: "Hello, Claude"}],
58
- model: :"claude-3-7-sonnet-latest"
56
+ model: :"claude-sonnet-4-20250514"
59
57
  )
60
58
 
61
59
  stream.each do |message|
@@ -63,6 +61,24 @@ stream.each do |message|
63
61
  end
64
62
  ```
65
63
 
64
+ ### Streaming Helpers
65
+
66
+ This library provides several conveniences for streaming messages, for example:
67
+
68
+ ```ruby
69
+ stream = anthropic.messages.stream(
70
+ max_tokens: 1024,
71
+ messages: [{role: :user, content: "Say hello there!"}],
72
+ model: :"claude-sonnet-4-20250514"
73
+ )
74
+
75
+ stream.text.each do |text|
76
+ print(text)
77
+ end
78
+ ```
79
+
80
+ Streaming with `anthropic.messages.stream(...)` exposes [various helpers for your convenience](helpers.md) including accumulation & SDK-specific events.
81
+
66
82
  ### Pagination
67
83
 
68
84
  List methods in the Anthropic API are paginated.
@@ -70,7 +86,7 @@ List methods in the Anthropic API are paginated.
70
86
  This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
71
87
 
72
88
  ```ruby
73
- page = anthropic.beta.messages.batches.list(limit: 20)
89
+ page = anthropic.messages.batches.list(limit: 20)
74
90
 
75
91
  # Fetch single item from page.
76
92
  batch = page.data[0]
@@ -122,7 +138,7 @@ begin
122
138
  message = anthropic.messages.create(
123
139
  max_tokens: 1024,
124
140
  messages: [{role: "user", content: "Hello, Claude"}],
125
- model: :"claude-3-7-sonnet-latest"
141
+ model: :"claude-sonnet-4-20250514"
126
142
  )
127
143
  rescue Anthropic::Errors::APIConnectionError => e
128
144
  puts("The server could not be reached")
@@ -169,7 +185,7 @@ anthropic = Anthropic::Client.new(
169
185
  anthropic.messages.create(
170
186
  max_tokens: 1024,
171
187
  messages: [{role: "user", content: "Hello, Claude"}],
172
- model: :"claude-3-7-sonnet-latest",
188
+ model: :"claude-sonnet-4-20250514",
173
189
  request_options: {max_retries: 5}
174
190
  )
175
191
  ```
@@ -188,7 +204,7 @@ anthropic = Anthropic::Client.new(
188
204
  anthropic.messages.create(
189
205
  max_tokens: 1024,
190
206
  messages: [{role: "user", content: "Hello, Claude"}],
191
- model: :"claude-3-7-sonnet-latest",
207
+ model: :"claude-sonnet-4-20250514",
192
208
  request_options: {timeout: 5}
193
209
  )
194
210
  ```
@@ -219,7 +235,7 @@ message = anthropic.messages.create(
219
235
  content: "Hello, Claude"
220
236
  }
221
237
  ],
222
- model: "anthropic.claude-3-5-sonnet-20241022-v2:0"
238
+ model: "anthropic.claude-sonnet-4-20250514-v2:0"
223
239
  )
224
240
 
225
241
  puts(message)
@@ -247,7 +263,7 @@ message = anthropic.messages.create(
247
263
  content: "Hello, Claude"
248
264
  }
249
265
  ],
250
- model: "claude-3-7-sonnet@20250219"
266
+ model: "claude-sonnet-4@20250514"
251
267
  )
252
268
 
253
269
  puts(message)
@@ -284,7 +300,7 @@ message =
284
300
  anthropic.messages.create(
285
301
  max_tokens: 1024,
286
302
  messages: [{role: "user", content: "Hello, Claude"}],
287
- model: :"claude-3-7-sonnet-latest",
303
+ model: :"claude-sonnet-4-20250514",
288
304
  request_options: {
289
305
  extra_query: {my_query_parameter: value},
290
306
  extra_body: {my_body_parameter: value},
@@ -333,7 +349,7 @@ You can provide typesafe request parameters like so:
333
349
  anthropic.messages.create(
334
350
  max_tokens: 1024,
335
351
  messages: [Anthropic::MessageParam.new(role: "user", content: "Hello, Claude")],
336
- model: :"claude-3-7-sonnet-latest"
352
+ model: :"claude-sonnet-4-20250514"
337
353
  )
338
354
  ```
339
355
 
@@ -344,14 +360,14 @@ Or, equivalently:
344
360
  anthropic.messages.create(
345
361
  max_tokens: 1024,
346
362
  messages: [{role: "user", content: "Hello, Claude"}],
347
- model: :"claude-3-7-sonnet-latest"
363
+ model: :"claude-sonnet-4-20250514"
348
364
  )
349
365
 
350
366
  # You can also splat a full Params class:
351
367
  params = Anthropic::MessageCreateParams.new(
352
368
  max_tokens: 1024,
353
369
  messages: [Anthropic::MessageParam.new(role: "user", content: "Hello, Claude")],
354
- model: :"claude-3-7-sonnet-latest"
370
+ model: :"claude-sonnet-4-20250514"
355
371
  )
356
372
  anthropic.messages.create(**params)
357
373
  ```
@@ -9,6 +9,28 @@ module Anthropic
9
9
  end
10
10
 
11
11
  class ConversionError < Anthropic::Errors::Error
12
+ # @return [StandardError, nil]
13
+ def cause = @cause.nil? ? super : @cause
14
+
15
+ # @api private
16
+ #
17
+ # @param on [Class<StandardError>]
18
+ # @param method [Symbol]
19
+ # @param target [Object]
20
+ # @param value [Object]
21
+ # @param cause [StandardError, nil]
22
+ def initialize(on:, method:, target:, value:, cause: nil)
23
+ cls = on.name.split("::").last
24
+
25
+ message = [
26
+ "Failed to parse #{cls}.#{method} from #{value.class} to #{target.inspect}.",
27
+ "To get the unparsed API response, use #{cls}[#{method.inspect}].",
28
+ cause && "Cause: #{cause.message}"
29
+ ].filter(&:itself).join(" ")
30
+
31
+ @cause = cause
32
+ super(message)
33
+ end
12
34
  end
13
35
 
14
36
  class APIError < Anthropic::Errors::Error
@@ -62,7 +62,7 @@ module Anthropic
62
62
  begin
63
63
  require("aws-sdk-bedrockruntime")
64
64
  rescue LoadError
65
- raise <<~MSG
65
+ message = <<~MSG
66
66
 
67
67
  In order to access Anthropic models on Bedrock you must require the `aws-sdk-bedrockruntime` gem.
68
68
  You can install it by adding the following to your Gemfile:
@@ -75,6 +75,8 @@ module Anthropic
75
75
 
76
76
  gem install aws-sdk-bedrockruntime
77
77
  MSG
78
+
79
+ raise RuntimeError.new(message)
78
80
  end
79
81
 
80
82
  @aws_region, @aws_credentials = resolve_region_and_credentials(
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anthropic
4
+ module Helpers
5
+ module Streaming
6
+ class TextEvent < Anthropic::Internal::Type::BaseModel
7
+ # @!attribute type
8
+ #
9
+ # @return [Symbol, :text]
10
+ required :type, const: :text
11
+
12
+ # @!attribute text
13
+ # The text delta received in this streaming event.
14
+ #
15
+ # @return [String]
16
+ required :text, String
17
+
18
+ # @!attribute snapshot
19
+ # The entire accumulated text up to this point in the stream.
20
+ #
21
+ # @return [String]
22
+ required :snapshot, String
23
+ end
24
+
25
+ class CitationEvent < Anthropic::Internal::Type::BaseModel
26
+ # @!attribute type
27
+ #
28
+ # @return [Symbol, :citation]
29
+ required :type, const: :citation
30
+
31
+ # @!attribute citation
32
+ # The new citation received in this streaming event.
33
+ #
34
+ # @return [Anthropic::Models::CitationCharLocation, Anthropic::Models::CitationPageLocation, Anthropic::Models::CitationContentBlockLocation, Anthropic::Models::CitationsWebSearchResultLocation]
35
+ required :citation, union: -> { Anthropic::CitationsDelta::Citation }
36
+
37
+ # @!attribute snapshot
38
+ # All of the accumulated citations up to this point in the stream.
39
+ #
40
+ # @return [Array<Anthropic::Models::CitationCharLocation, Anthropic::Models::CitationPageLocation, Anthropic::Models::CitationContentBlockLocation, Anthropic::Models::CitationsWebSearchResultLocation>]
41
+ required :snapshot,
42
+ -> {
43
+ Anthropic::Internal::Type::ArrayOf[union: Anthropic::CitationsDelta::Citation]
44
+ }
45
+ end
46
+
47
+ class ThinkingEvent < Anthropic::Internal::Type::BaseModel
48
+ # @!attribute type
49
+ #
50
+ # @return [Symbol, :thinking]
51
+ required :type, const: :thinking
52
+
53
+ # @!attribute thinking
54
+ # The thinking delta received in this streaming event.
55
+ #
56
+ # @return [String]
57
+ required :thinking, String
58
+
59
+ # @!attribute snapshot
60
+ # The accumulated thinking content up to this point in the stream.
61
+ #
62
+ # @return [String]
63
+ required :snapshot, String
64
+ end
65
+
66
+ class SignatureEvent < Anthropic::Internal::Type::BaseModel
67
+ # @!attribute type
68
+ #
69
+ # @return [Symbol, :signature]
70
+ required :type, const: :signature
71
+
72
+ # @!attribute signature
73
+ # The signature of the thinking block.
74
+ #
75
+ # @return [String]
76
+ required :signature, String
77
+ end
78
+
79
+ class InputJsonEvent < Anthropic::Internal::Type::BaseModel
80
+ # @!attribute type
81
+ #
82
+ # @return [Symbol, :input_json]
83
+ required :type, const: :input_json
84
+
85
+ # @!attribute partial_json
86
+ # A partial JSON string delta received in this streaming event.
87
+ #
88
+ # Example:
89
+ # ```
90
+ # "{'location':,"
91
+ # ```
92
+ #
93
+ # @return [String]
94
+ required :partial_json, String
95
+
96
+ # @!attribute snapshot
97
+ # The currently accumulated parsed object up to this point in the stream.
98
+ #
99
+ # Example:
100
+ # ```
101
+ # {'location': 'San Francisco, CA'}
102
+ # ```
103
+ #
104
+ # @return [Object]
105
+ required :snapshot, Anthropic::Internal::Type::Unknown
106
+ end
107
+
108
+ class MessageStopEvent < Anthropic::Models::RawMessageStopEvent
109
+ # @!attribute type
110
+ #
111
+ # @return [Symbol, :message_stop]
112
+ required :type, const: :message_stop
113
+
114
+ # @!attribute message
115
+ # The completed message when streaming ends.
116
+ #
117
+ # @return [Anthropic::Models::Message]
118
+ required :message, Anthropic::Models::Message
119
+ end
120
+
121
+ class ContentBlockStopEvent < Anthropic::Models::RawContentBlockStopEvent
122
+ # @!attribute index
123
+ # The index of the content block that has stopped streaming.
124
+ #
125
+ # @return [Integer]
126
+ required :index, Integer
127
+
128
+ # @!attribute type
129
+ #
130
+ # @return [Symbol, :content_block_stop]
131
+ required :type, const: :content_block_stop
132
+
133
+ # @!attribute content_block
134
+ # The completed content block when streaming for this block ends.
135
+ #
136
+ # @return [Anthropic::Models::TextBlock, Anthropic::Models::ToolUseBlock]
137
+ required :content_block, Anthropic::Models::ContentBlock
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anthropic
4
+ module Helpers
5
+ module Streaming
6
+ # @api private
7
+ #
8
+ # MessageStream provides a Ruby Enumerable interface over Server-Sent Events from
9
+ # the Anthropic API, yielding a mix of raw streaming events and higher-level typed
10
+ # events while maintaining accumulated message state throughout the stream lifecycle.
11
+ #
12
+ #
13
+ # @generic Elem
14
+ class MessageStream
15
+ include Anthropic::Internal::Type::BaseStream
16
+
17
+ # @api private
18
+ #
19
+ # Consumes raw stream events and yields a mix of raw and higher-level typed events while
20
+ # maintaining accumulated message state. This is what's called when you run `each` on the
21
+ # stream.
22
+ #
23
+ # @return [Enumerable<generic<Elem>>]
24
+ private def iterator
25
+ @iterator ||= Anthropic::Internal::Util.chain_fused(@stream) do |y|
26
+ @raw_stream.each do |raw_event|
27
+ @accumated_message_snapshot = accumulate_event(
28
+ event: raw_event,
29
+ current_snapshot: @accumated_message_snapshot
30
+ )
31
+ events_to_yield = build_events(event: raw_event, message_snapshot: @accumated_message_snapshot)
32
+ events_to_yield.each(&y)
33
+ end
34
+ end
35
+ end
36
+
37
+ # @api public
38
+ #
39
+ # Blocks until the stream has been consumed
40
+ #
41
+ # @return [void]
42
+ def until_done = each {} # rubocop:disable Lint/EmptyBlock
43
+
44
+ # @api public
45
+ #
46
+ # Returns an enumerable of text deltas from the streaming response.
47
+ #
48
+ # @return [Enumerable<String>]
49
+ def text
50
+ Anthropic::Internal::Util.chain_fused(@iterator) do |y|
51
+ @iterator.each do |event|
52
+ if event.type == :content_block_delta && event.delta.type == :text_delta
53
+ y << event.delta.text
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # @api public
60
+ #
61
+ # Returns the complete accumulated Message object after stream completion.
62
+ #
63
+ # @return [Anthropic::Models::Message]
64
+ def accumulated_message
65
+ until_done
66
+ @accumated_message_snapshot
67
+ end
68
+
69
+ # @api public
70
+ #
71
+ # Returns all text content blocks concatenated into a single string.
72
+ # NOTE: Currently the API will only respond with a single content block.
73
+ #
74
+ # Will raise an error if no `text` content blocks were returned.
75
+ # @return [String]
76
+ def accumulated_text
77
+ message = accumulated_message
78
+ text_blocks = []
79
+ message.content.each do |block|
80
+ if block.type == :text
81
+ text_blocks << block.text
82
+ end
83
+ end
84
+
85
+ if text_blocks.empty?
86
+ raise RuntimeError.new("Expected to have received at least 1 text block")
87
+ end
88
+
89
+ text_blocks.join
90
+ end
91
+
92
+ # @api private
93
+ #
94
+ # Builds up a complete Message object as streaming events arrive.
95
+ #
96
+ # @param event [Anthropic::Models::RawMessageStreamEvent] the raw streaming event to process
97
+ # @param current_snapshot [Anthropic::Models::Message, nil] current accumulated message state
98
+ #
99
+ # @return [Anthropic::Models::Message] updated message snapshot with event applied
100
+ private def accumulate_event(event:, current_snapshot:)
101
+ unless event in Anthropic::Models::RawMessageStreamEvent
102
+ message = "Expected event to be a variant of RawMessageStreamEvent, got #{event.class}"
103
+ raise ArgumentError.new(message)
104
+ end
105
+
106
+ if current_snapshot.nil?
107
+ return event.message if event.type == :message_start
108
+
109
+ message = "Unexpected event order, got \"#{event.type}\" before \":message_start\""
110
+ raise RuntimeError.new(message)
111
+ end
112
+
113
+ case event
114
+ in Anthropic::Models::RawMessageStartEvent
115
+ # Use the converter to create a new, isolated copy of the message object.
116
+ # This ensures proper type validation and prevents shared object references
117
+ # that could lead to unintended mutations during streaming accumulation.
118
+ # Matches the Python SDK's approach of explicitly constructing Message objects.
119
+ return Anthropic::Internal::Type::Converter.coerce(Anthropic::Models::Message, event.message)
120
+ in Anthropic::Models::RawContentBlockStartEvent
121
+ current_snapshot.content = (current_snapshot.content || []) + [event.content_block]
122
+ in Anthropic::Models::RawContentBlockDeltaEvent
123
+ content = current_snapshot.content[event.index]
124
+
125
+ case (delta = event.delta)
126
+ in Anthropic::Models::TextDelta if content.type == :text
127
+ content.text += delta.text
128
+ in Anthropic::Models::InputJSONDelta if content.type == :tool_use
129
+ json_buf = content.json_buf.to_s
130
+ json_buf += delta.partial_json
131
+
132
+ content.input = json_buf
133
+ content.json_buf = json_buf
134
+ in Anthropic::Models::CitationsDelta if content.type == :text
135
+ content.citations ||= []
136
+ content.citations << delta.citation
137
+ in Anthropic::Models::ThinkingDelta if content.type == :thinking
138
+ content.thinking += delta.thinking
139
+ in Anthropic::Models::SignatureDelta if content.type == :thinking
140
+ content.signature = delta.signature
141
+ else
142
+ end
143
+ in Anthropic::Models::RawMessageDeltaEvent
144
+ current_snapshot.stop_reason = event.delta.stop_reason
145
+ current_snapshot.stop_sequence = event.delta.stop_sequence
146
+ current_snapshot.usage.output_tokens = event.usage.output_tokens
147
+ else
148
+ end
149
+
150
+ current_snapshot
151
+ end
152
+
153
+ # @api private
154
+ #
155
+ # Determines which events to yield for a given raw streaming event.
156
+ #
157
+ # May transform events into higher-level types (TextEvent, InputJsonEvent),
158
+ # pass through raw events unchanged, or produce multiple events.
159
+ #
160
+ # @param event [Anthropic::Models::RawMessageStreamEvent] the raw event to process
161
+ # @param message_snapshot [Anthropic::Models::Message] current accumulated message state
162
+ #
163
+ # @return [Array<Object>] events to yield (mix of raw and typed events)
164
+ private def build_events(event:, message_snapshot:)
165
+ events_to_yield = []
166
+
167
+ case event
168
+ in Anthropic::Models::RawMessageStopEvent
169
+ events_to_yield << MessageStopEvent.new(
170
+ type: :message_stop,
171
+ message: message_snapshot
172
+ )
173
+ in Anthropic::Models::RawContentBlockDeltaEvent
174
+ events_to_yield << event
175
+ content_block = message_snapshot.content[event.index]
176
+
177
+ case (delta = event.delta)
178
+ in Anthropic::Models::TextDelta if content_block.type == :text
179
+ events_to_yield << Anthropic::Streaming::TextEvent.new(
180
+ type: :text,
181
+ text: delta.text,
182
+ snapshot: content_block.text
183
+ )
184
+ in Anthropic::Models::InputJSONDelta if content_block.type == :tool_use
185
+ events_to_yield << Anthropic::Streaming::InputJsonEvent.new(
186
+ type: :input_json,
187
+ partial_json: delta.partial_json,
188
+ snapshot: content_block.input
189
+ )
190
+ in Anthropic::Models::CitationsDelta if content_block.type == :text
191
+ events_to_yield << Anthropic::Streaming::CitationEvent.new(
192
+ type: :citation,
193
+ citation: delta.citation,
194
+ snapshot: content_block.citations || []
195
+ )
196
+ in Anthropic::Models::ThinkingDelta if content_block.type == :thinking
197
+ events_to_yield << Anthropic::Streaming::ThinkingEvent.new(
198
+ type: :thinking,
199
+ thinking: delta.thinking,
200
+ snapshot: content_block.thinking
201
+ )
202
+ in Anthropic::Models::SignatureDelta if content_block.type == :thinking
203
+ events_to_yield << Anthropic::Streaming::SignatureEvent.new(
204
+ type: :signature,
205
+ signature: content_block.signature
206
+ )
207
+ else
208
+ end
209
+ in Anthropic::Models::RawContentBlockStopEvent
210
+ content_block = message_snapshot.content[event.index]
211
+
212
+ events_to_yield << ContentBlockStopEvent.new(
213
+ type: :content_block_stop,
214
+ index: event.index,
215
+ content_block: content_block
216
+ )
217
+ else
218
+ events_to_yield << event
219
+ end
220
+
221
+ events_to_yield
222
+ end
223
+
224
+ # @api private
225
+ #
226
+ # @param raw_stream [Anthropic::Internal::Type::BaseStream]
227
+ def initialize(raw_stream:)
228
+ # The underlying Server-Sent Event stream from the Anthropic API.
229
+ @raw_stream = raw_stream
230
+ # Accumulated message state that builds up as events are processed.
231
+ @accumated_message_snapshot = nil
232
+ # Lazy enumerable that transforms raw events into consumable events.
233
+ @iterator = iterator
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end