llm.rb 16.0.0.pre.5 → 16.0.0.pre.6

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: f5558a0514d6bd6b9648f743a308ce8e6dbb3802b8709edc6caf45d7c1ab3de8
4
- data.tar.gz: a5d3178f0c79e152b8032cce974be69edd1e52cc629658034a750183ccb41ea8
3
+ metadata.gz: 0f5c0f9cb6f92099cec46e8c7a83e02498d375458a50b8b3f19a94ac2385dc8f
4
+ data.tar.gz: 11929258bad683f946ded02b7b2621fcfae30cf1ed11c57007e4b4cfbac05b5d
5
5
  SHA512:
6
- metadata.gz: 3a0288112d140d3e0a3e34dc35e570ceb25ad62fd7f3c33a2942cb111432992b7194e18fb406bf55a25a945aff0e89ce055c292a1de50c00b66c801027b95c52
7
- data.tar.gz: 454a1c74a59401689c88947714f741ada1d39f6ce95013bf8bdd6fab76690adafd3a4be8af02e9eace2a71ae26c3f4daf3a1751fdf326549f722da888cbcb309
6
+ metadata.gz: 5b32ee2a9301958487a808705f63895b1cd89898730e8b0bdcabcee06be62eef6a724795ccd0f6053227f0577380019436eab3b19ba3a15459560bcc78a505af
7
+ data.tar.gz: 7839665a301ee3ab68716737daaddc7f384308b6b24548efcb33699a3463de83efa638aa060293a27ced6145907dee6ddabb7b63d11d5cb5f1e1a0239b2e209f
data/CHANGELOG.md CHANGED
@@ -196,14 +196,17 @@
196
196
  Update `data/` with current model listings, limits, and pricing. Alibaba adds
197
197
  `qwen3.5-flash`, `qwen3.7-flash`, and `qwen3.8-omni-flash`, and gives
198
198
  `qwen3.7-plus` attachments, structured output, and a lower price; OpenAI adds
199
- `gpt-daybreak-blue-latest` and `gpt-daybreak-red-latest`; Bedrock adds
200
- `openai.gpt-6-sol`, `openai.gpt-6-luna`, and
201
- `global.anthropic.claude-sonnet-5-5`; and DeepInfra adds `tencent/Hy4-preview`
202
- and the Xiaomi MiMo V2.6 Pro and V2.6 Flash models.
199
+ `gpt-daybreak-blue-latest`, `gpt-daybreak-red-latest`, and `gpt-6.1-sol`, and
200
+ gives `gpt-6-astra` an `ultrafast` mode; Bedrock adds `openai.gpt-6-sol`,
201
+ `openai.gpt-6-luna`, `global.anthropic.claude-sonnet-5-5`,
202
+ `anthropic.claude-sonnet-5-5`, and the Grok 4.7 entries in both the global
203
+ and US regions; DeepInfra adds `tencent/Hy4-preview` and the Xiaomi MiMo
204
+ V2.6 Pro and V2.6 Flash models, and marks four older entries deprecated.
203
205
  Bedrock also corrects the context and output limits of fifteen models, Google
204
206
  lowers the limits of `gemini-2.5-computer-use-preview-10-2025` and
205
- `gemini-3-pro-image`, and OpenRouter adds five models, drops six, and reprices
206
- many of the DeepSeek, Z.ai, and Qwen entries.
207
+ `gemini-3-pro-image`, and OpenRouter adds seven models, `openai/gpt-6.1-sol`
208
+ and `openai/gpt-6.1-sol-pro` among them, drops six, and reprices or corrects
209
+ the limits of many of the DeepSeek, Z.ai, Qwen, and Tencent entries.
207
210
 
208
211
  ### Schema
209
212
 
@@ -230,6 +233,42 @@
230
233
  rate limit or a timeout calls it when it lands and not once per attempt, and
231
234
  it fires even when the stream is disabled.
232
235
 
236
+ ### Tracers
237
+
238
+ * **tracer: report a request that failed** <br>
239
+ [`LLM::Tracer#on_request_error`](https://r.uby.dev/api-docs/llm.rb/LLM/Tracer.html#on_request_error-instance_method)
240
+ is now called wherever a request ends without a response, so a span that
241
+ [`LLM::Tracer#on_request_start`](https://r.uby.dev/api-docs/llm.rb/LLM/Tracer.html#on_request_start-instance_method)
242
+ returned is closed. Before this, a request was reported only when a provider
243
+ turned an error response into an exception, so a dropped connection or a
244
+ socket read that failed left the tracer holding a span it had opened and never
245
+ closed, which in a trace reads the same as a process that died. A failure that
246
+ surfaces as one of the transport's own error classes is reported the same way
247
+ unless the request was interrupted, and the exception the caller receives is
248
+ unchanged.
249
+
250
+ * **tracer: add `on_interrupt`, called when a request is interrupted** <br>
251
+ [`LLM::Tracer#on_interrupt`](https://r.uby.dev/api-docs/llm.rb/LLM/Tracer.html#on_interrupt-instance_method)
252
+ is a new hook, called with a `scope:` of `:request` or `:tool` before
253
+ `LLM::Interrupt` reaches the caller, so a tracer that has to record what
254
+ happened to a turn does it while the work is still in flight. An interrupt is
255
+ the third ending a scope can have, beside `on_request_finish` and
256
+ `on_request_error`, and it is not reported as a failure. Unlike the other
257
+ request and tool hooks it does nothing by default, because an interrupt is
258
+ delivered to whatever tracer happens to be bound, and a hook that raised would
259
+ replace the interrupt every caller is written against. A request is announced
260
+ with the span that `on_request_start` returned and its `request_id`; a tool
261
+ pass has neither, so both arrive as `nil`.
262
+
263
+ * **tracer: announce an interrupted tool phase once** <br>
264
+ [`LLM::Context#wait`](https://r.uby.dev/api-docs/llm.rb/LLM/Context.html#wait-instance_method)
265
+ now calls the hook once when an interrupt unwinds through it, rather than once
266
+ per tool, because a cancel reaches every tool that is running and the caller
267
+ hears a single exception, so the announcement belongs to the phase rather than
268
+ to a tool. The hook runs before the caller is given the interrupt. A `:ractor`
269
+ call that answers `cancelled: true` instead of raising is not announced,
270
+ because the phase was not interrupted; one call was retired.
271
+
233
272
  ## v15.5.0
234
273
 
235
274
  Changes since `v15.4.1`.
data/data/bedrock.json CHANGED
@@ -777,6 +777,54 @@
777
777
  },
778
778
  "canonical_model_id": "anthropic/claude-opus-5-5"
779
779
  },
780
+ "anthropic.claude-sonnet-5-5": {
781
+ "id": "anthropic.claude-sonnet-5-5",
782
+ "name": "Claude Sonnet 5.5",
783
+ "description": "Fast Claude model for everyday coding, agents, and knowledge work",
784
+ "family": "claude-sonnet",
785
+ "attachment": true,
786
+ "reasoning": true,
787
+ "reasoning_options": [
788
+ {
789
+ "type": "effort",
790
+ "values": [
791
+ "low",
792
+ "medium",
793
+ "high",
794
+ "xhigh",
795
+ "max"
796
+ ]
797
+ }
798
+ ],
799
+ "tool_call": true,
800
+ "structured_output": false,
801
+ "temperature": false,
802
+ "knowledge": "2026-06",
803
+ "release_date": "2026-09-28",
804
+ "last_updated": "2026-09-28",
805
+ "modalities": {
806
+ "input": [
807
+ "text",
808
+ "image",
809
+ "pdf"
810
+ ],
811
+ "output": [
812
+ "text"
813
+ ]
814
+ },
815
+ "open_weights": false,
816
+ "limit": {
817
+ "context": 1000000,
818
+ "output": 128000
819
+ },
820
+ "cost": {
821
+ "input": 2,
822
+ "output": 10,
823
+ "cache_read": 0.2,
824
+ "cache_write": 2.5
825
+ },
826
+ "canonical_model_id": "anthropic/claude-sonnet-5-5"
827
+ },
780
828
  "global.anthropic.claude-sonnet-5-5": {
781
829
  "id": "global.anthropic.claude-sonnet-5-5",
782
830
  "name": "Claude Sonnet 5.5 (Global)",
@@ -3717,6 +3765,52 @@
3717
3765
  },
3718
3766
  "canonical_model_id": "anthropic/claude-opus-5"
3719
3767
  },
3768
+ "global.xai.grok-4.7": {
3769
+ "id": "global.xai.grok-4.7",
3770
+ "name": "Grok 4.7 (Global)",
3771
+ "description": "xAI's frontier model for long-running agents, coding, knowledge work, and visual projects",
3772
+ "family": "grok",
3773
+ "attachment": true,
3774
+ "reasoning": true,
3775
+ "reasoning_options": [
3776
+ {
3777
+ "type": "effort",
3778
+ "values": [
3779
+ "low",
3780
+ "medium",
3781
+ "high",
3782
+ "xhigh"
3783
+ ]
3784
+ }
3785
+ ],
3786
+ "tool_call": true,
3787
+ "structured_output": true,
3788
+ "temperature": true,
3789
+ "knowledge": "2026-05",
3790
+ "release_date": "2026-09-21",
3791
+ "last_updated": "2026-09-28",
3792
+ "modalities": {
3793
+ "input": [
3794
+ "text",
3795
+ "image",
3796
+ "pdf"
3797
+ ],
3798
+ "output": [
3799
+ "text"
3800
+ ]
3801
+ },
3802
+ "open_weights": false,
3803
+ "limit": {
3804
+ "context": 500000,
3805
+ "output": 500000
3806
+ },
3807
+ "cost": {
3808
+ "input": 2,
3809
+ "output": 6,
3810
+ "cache_read": 0.5
3811
+ },
3812
+ "canonical_model_id": "xai/grok-4.7"
3813
+ },
3720
3814
  "us.openai.gpt-5.6-sol": {
3721
3815
  "id": "us.openai.gpt-5.6-sol",
3722
3816
  "name": "GPT-5.6 Sol (US)",
@@ -4229,6 +4323,52 @@
4229
4323
  },
4230
4324
  "canonical_model_id": "mistral/ministral-3-3b-instruct-2512"
4231
4325
  },
4326
+ "us.xai.grok-4.7": {
4327
+ "id": "us.xai.grok-4.7",
4328
+ "name": "Grok 4.7 (US)",
4329
+ "description": "xAI's frontier model for long-running agents, coding, knowledge work, and visual projects",
4330
+ "family": "grok",
4331
+ "attachment": true,
4332
+ "reasoning": true,
4333
+ "reasoning_options": [
4334
+ {
4335
+ "type": "effort",
4336
+ "values": [
4337
+ "low",
4338
+ "medium",
4339
+ "high",
4340
+ "xhigh"
4341
+ ]
4342
+ }
4343
+ ],
4344
+ "tool_call": true,
4345
+ "structured_output": true,
4346
+ "temperature": true,
4347
+ "knowledge": "2026-05",
4348
+ "release_date": "2026-09-21",
4349
+ "last_updated": "2026-09-28",
4350
+ "modalities": {
4351
+ "input": [
4352
+ "text",
4353
+ "image",
4354
+ "pdf"
4355
+ ],
4356
+ "output": [
4357
+ "text"
4358
+ ]
4359
+ },
4360
+ "open_weights": false,
4361
+ "limit": {
4362
+ "context": 500000,
4363
+ "output": 500000
4364
+ },
4365
+ "cost": {
4366
+ "input": 2.2,
4367
+ "output": 6.6,
4368
+ "cache_read": 0.55
4369
+ },
4370
+ "canonical_model_id": "xai/grok-4.7"
4371
+ },
4232
4372
  "us.openai.gpt-6-luna": {
4233
4373
  "id": "us.openai.gpt-6-luna",
4234
4374
  "name": "GPT-6 Luna (US)",
data/data/deepinfra.json CHANGED
@@ -246,6 +246,7 @@
246
246
  "context": 1048576,
247
247
  "output": 16384
248
248
  },
249
+ "status": "deprecated",
249
250
  "cost": {
250
251
  "input": 1,
251
252
  "output": 3,
@@ -330,6 +331,7 @@
330
331
  "context": 262144,
331
332
  "output": 16384
332
333
  },
334
+ "status": "deprecated",
333
335
  "cost": {
334
336
  "input": 0.14,
335
337
  "output": 0.28,
@@ -1712,6 +1714,7 @@
1712
1714
  "context": 163840,
1713
1715
  "output": 163840
1714
1716
  },
1717
+ "status": "deprecated",
1715
1718
  "cost": {
1716
1719
  "input": 0.24,
1717
1720
  "output": 0.9,
@@ -2022,6 +2025,7 @@
2022
2025
  "context": 262144,
2023
2026
  "output": 262144
2024
2027
  },
2028
+ "status": "deprecated",
2025
2029
  "cost": {
2026
2030
  "input": 0.68,
2027
2031
  "output": 3.4,
data/data/openai.json CHANGED
@@ -1121,6 +1121,99 @@
1121
1121
  "cache_read": 0.175
1122
1122
  }
1123
1123
  },
1124
+ "gpt-6.1-sol": {
1125
+ "id": "gpt-6.1-sol",
1126
+ "name": "GPT-6.1 Sol",
1127
+ "description": "Near-Astra performance for complex coding, computer use, and professional work at a lower cost.",
1128
+ "family": "gpt-sol",
1129
+ "attachment": true,
1130
+ "reasoning": true,
1131
+ "reasoning_options": [
1132
+ {
1133
+ "type": "effort",
1134
+ "values": [
1135
+ "low",
1136
+ "medium",
1137
+ "high",
1138
+ "xhigh",
1139
+ "max"
1140
+ ]
1141
+ }
1142
+ ],
1143
+ "tool_call": true,
1144
+ "structured_output": true,
1145
+ "temperature": false,
1146
+ "knowledge": "2026-04-30",
1147
+ "release_date": "2026-09-29",
1148
+ "last_updated": "2026-09-29",
1149
+ "modalities": {
1150
+ "input": [
1151
+ "text",
1152
+ "image",
1153
+ "pdf"
1154
+ ],
1155
+ "output": [
1156
+ "text"
1157
+ ]
1158
+ },
1159
+ "open_weights": false,
1160
+ "limit": {
1161
+ "context": 1050000,
1162
+ "input": 922000,
1163
+ "output": 128000
1164
+ },
1165
+ "experimental": {
1166
+ "modes": {
1167
+ "fast": {
1168
+ "cost": {
1169
+ "input": 4,
1170
+ "output": 20,
1171
+ "cache_read": 0.2,
1172
+ "cache_write": 5
1173
+ },
1174
+ "provider": {
1175
+ "body": {
1176
+ "service_tier": "priority"
1177
+ }
1178
+ }
1179
+ },
1180
+ "pro": {
1181
+ "provider": {
1182
+ "body": {
1183
+ "reasoning": {
1184
+ "mode": "pro"
1185
+ }
1186
+ }
1187
+ }
1188
+ }
1189
+ }
1190
+ },
1191
+ "cost": {
1192
+ "input": 2,
1193
+ "output": 10,
1194
+ "cache_read": 0.1,
1195
+ "cache_write": 2.5,
1196
+ "tiers": [
1197
+ {
1198
+ "input": 4,
1199
+ "output": 15,
1200
+ "cache_read": 0.2,
1201
+ "cache_write": 5,
1202
+ "tier": {
1203
+ "type": "context",
1204
+ "size": 272000
1205
+ }
1206
+ }
1207
+ ],
1208
+ "context_over_200k": {
1209
+ "input": 4,
1210
+ "output": 15,
1211
+ "cache_read": 0.2,
1212
+ "cache_write": 5
1213
+ }
1214
+ },
1215
+ "canonical_model_id": "openai/gpt-6.1-sol"
1216
+ },
1124
1217
  "text-embedding-3-large": {
1125
1218
  "id": "text-embedding-3-large",
1126
1219
  "name": "text-embedding-3-large",
@@ -1248,6 +1341,19 @@
1248
1341
  }
1249
1342
  }
1250
1343
  }
1344
+ },
1345
+ "ultrafast": {
1346
+ "cost": {
1347
+ "input": 60,
1348
+ "output": 300,
1349
+ "cache_read": 6,
1350
+ "cache_write": 75
1351
+ },
1352
+ "provider": {
1353
+ "body": {
1354
+ "service_tier": "ultrafast"
1355
+ }
1356
+ }
1251
1357
  }
1252
1358
  }
1253
1359
  },
data/data/openrouter.json CHANGED
@@ -518,9 +518,9 @@
518
518
  "output": 943718
519
519
  },
520
520
  "cost": {
521
- "input": 0.4,
522
- "output": 10,
523
- "cache_read": 0.4
521
+ "input": 0.29,
522
+ "output": 9,
523
+ "cache_read": 0.28
524
524
  }
525
525
  },
526
526
  "poolside/laguna-s-2.1:free": {
@@ -1859,13 +1859,13 @@
1859
1859
  },
1860
1860
  "open_weights": true,
1861
1861
  "limit": {
1862
- "context": 1310720,
1862
+ "context": 1048576,
1863
1863
  "output": 943718
1864
1864
  },
1865
1865
  "cost": {
1866
- "input": 0.018,
1867
- "output": 0.32,
1868
- "cache_read": 0.018
1866
+ "input": 0.01,
1867
+ "output": 1.28,
1868
+ "cache_read": 0.01
1869
1869
  },
1870
1870
  "canonical_model_id": "deepseek/deepseek-v4-flash-0731"
1871
1871
  },
@@ -1910,9 +1910,9 @@
1910
1910
  "output": 943718
1911
1911
  },
1912
1912
  "cost": {
1913
- "input": 0.3,
1914
- "output": 1.2,
1915
- "cache_read": 0.006
1913
+ "input": 0.0198,
1914
+ "output": 0.396,
1915
+ "cache_read": 0.00291
1916
1916
  },
1917
1917
  "canonical_model_id": "deepseek/deepseek-v4.1-flash"
1918
1918
  },
@@ -2067,12 +2067,12 @@
2067
2067
  "open_weights": true,
2068
2068
  "limit": {
2069
2069
  "context": 1048576,
2070
- "output": 943718
2070
+ "output": 393216
2071
2071
  },
2072
2072
  "cost": {
2073
- "input": 0.4,
2074
- "output": 4.2,
2075
- "cache_read": 0.32
2073
+ "input": 0.66,
2074
+ "output": 1.98,
2075
+ "cache_read": 0.022
2076
2076
  },
2077
2077
  "canonical_model_id": "deepseek/deepseek-v4-pro-0813"
2078
2078
  },
@@ -2219,9 +2219,9 @@
2219
2219
  "output": 384000
2220
2220
  },
2221
2221
  "cost": {
2222
- "input": 0.95526,
2223
- "output": 1.91052,
2224
- "cache_read": 0.079605
2222
+ "input": 0.783,
2223
+ "output": 1.566,
2224
+ "cache_read": 0.06525
2225
2225
  },
2226
2226
  "canonical_model_id": "deepseek/deepseek-v4-pro"
2227
2227
  },
@@ -2335,12 +2335,12 @@
2335
2335
  "open_weights": true,
2336
2336
  "limit": {
2337
2337
  "context": 1048576,
2338
- "output": 131072
2338
+ "output": 384000
2339
2339
  },
2340
2340
  "cost": {
2341
- "input": 0.14,
2342
- "output": 0.28,
2343
- "cache_read": 0.028
2341
+ "input": 0.07854,
2342
+ "output": 0.15708,
2343
+ "cache_read": 0.015708
2344
2344
  },
2345
2345
  "canonical_model_id": "deepseek/deepseek-v4-flash"
2346
2346
  },
@@ -2551,9 +2551,9 @@
2551
2551
  "output": 128000
2552
2552
  },
2553
2553
  "cost": {
2554
- "input": 0.132,
2555
- "output": 0.528,
2556
- "cache_read": 0.033
2554
+ "input": 0.0825,
2555
+ "output": 0.33,
2556
+ "cache_read": 0.020625
2557
2557
  },
2558
2558
  "canonical_model_id": "tencent/hy3"
2559
2559
  },
@@ -2623,9 +2623,9 @@
2623
2623
  "output": 64000
2624
2624
  },
2625
2625
  "cost": {
2626
- "input": 0.834,
2627
- "output": 2.501,
2628
- "cache_read": 0.042
2626
+ "input": 0.7506,
2627
+ "output": 2.2509,
2628
+ "cache_read": 0.0378
2629
2629
  },
2630
2630
  "canonical_model_id": "tencent/hy4-preview"
2631
2631
  },
@@ -3142,7 +3142,7 @@
3142
3142
  "cost": {
3143
3143
  "input": 0.3,
3144
3144
  "output": 0.9,
3145
- "cache_read": 0.05
3145
+ "cache_read": 0.055
3146
3146
  },
3147
3147
  "canonical_model_id": "zhipuai/glm-4.6v"
3148
3148
  },
@@ -3298,7 +3298,7 @@
3298
3298
  },
3299
3299
  "open_weights": true,
3300
3300
  "limit": {
3301
- "context": 1310720,
3301
+ "context": 1048576,
3302
3302
  "output": 943717
3303
3303
  },
3304
3304
  "cost": {
@@ -3590,9 +3590,9 @@
3590
3590
  "output": 943718
3591
3591
  },
3592
3592
  "cost": {
3593
- "input": 0.3249,
3594
- "output": 4.4,
3595
- "cache_read": 0.2599
3593
+ "input": 0.432,
3594
+ "output": 3.99,
3595
+ "cache_read": 0.26
3596
3596
  },
3597
3597
  "canonical_model_id": "zhipuai/glm-5.2"
3598
3598
  },
@@ -3630,9 +3630,9 @@
3630
3630
  "output": 131072
3631
3631
  },
3632
3632
  "cost": {
3633
- "input": 1.4,
3634
- "output": 4.4,
3635
- "cache_read": 0.26
3633
+ "input": 0.9646,
3634
+ "output": 3.0316,
3635
+ "cache_read": 0.17914
3636
3636
  },
3637
3637
  "canonical_model_id": "zhipuai/glm-5.1"
3638
3638
  },
@@ -3746,7 +3746,7 @@
3746
3746
  },
3747
3747
  "open_weights": true,
3748
3748
  "limit": {
3749
- "context": 1310720,
3749
+ "context": 1048576,
3750
3750
  "output": 943717
3751
3751
  },
3752
3752
  "cost": {
@@ -4430,11 +4430,11 @@
4430
4430
  "open_weights": true,
4431
4431
  "limit": {
4432
4432
  "context": 131072,
4433
- "output": 16384
4433
+ "output": 117964
4434
4434
  },
4435
4435
  "cost": {
4436
- "input": 0.3,
4437
- "output": 1.2,
4436
+ "input": 0.35,
4437
+ "output": 1.5,
4438
4438
  "cache_read": 0.04
4439
4439
  },
4440
4440
  "canonical_model_id": "meta/muse-glimmer-30b"
@@ -4758,12 +4758,12 @@
4758
4758
  },
4759
4759
  "open_weights": false,
4760
4760
  "limit": {
4761
- "context": 1310720,
4761
+ "context": 1048576,
4762
4762
  "output": 943718
4763
4763
  },
4764
4764
  "cost": {
4765
4765
  "input": 0.02,
4766
- "output": 0.3,
4766
+ "output": 0.2475,
4767
4767
  "cache_read": 0.01
4768
4768
  }
4769
4769
  },
@@ -4799,13 +4799,13 @@
4799
4799
  },
4800
4800
  "open_weights": false,
4801
4801
  "limit": {
4802
- "context": 1310720,
4802
+ "context": 1048576,
4803
4803
  "output": 131072
4804
4804
  },
4805
4805
  "cost": {
4806
- "input": 0.19,
4806
+ "input": 0.13,
4807
4807
  "output": 4,
4808
- "cache_read": 0.19
4808
+ "cache_read": 0.13
4809
4809
  }
4810
4810
  },
4811
4811
  "arcee-ai/trinity-large-thinking": {
@@ -4984,7 +4984,6 @@
4984
4984
  {
4985
4985
  "type": "effort",
4986
4986
  "values": [
4987
- "none",
4988
4987
  "low",
4989
4988
  "medium",
4990
4989
  "high",
@@ -5017,13 +5016,13 @@
5017
5016
  "cost": {
5018
5017
  "input": 2,
5019
5018
  "output": 10,
5020
- "cache_read": 0.2,
5019
+ "cache_read": 0.1,
5021
5020
  "cache_write": 2.5,
5022
5021
  "tiers": [
5023
5022
  {
5024
5023
  "input": 4,
5025
5024
  "output": 15,
5026
- "cache_read": 0.4,
5025
+ "cache_read": 0.2,
5027
5026
  "cache_write": 5,
5028
5027
  "tier": {
5029
5028
  "type": "context",
@@ -5034,7 +5033,7 @@
5034
5033
  "context_over_200k": {
5035
5034
  "input": 4,
5036
5035
  "output": 15,
5037
- "cache_read": 0.4,
5036
+ "cache_read": 0.2,
5038
5037
  "cache_write": 5
5039
5038
  }
5040
5039
  }
@@ -6072,9 +6071,9 @@
6072
6071
  "output": 943718
6073
6072
  },
6074
6073
  "cost": {
6075
- "input": 0.02,
6076
- "output": 0.6,
6077
- "cache_read": 0.02
6074
+ "input": 0.0198,
6075
+ "output": 0.396,
6076
+ "cache_read": 0.00291
6078
6077
  }
6079
6078
  },
6080
6079
  "~deepseek/deepseek-pro-latest": {
@@ -6113,12 +6112,12 @@
6113
6112
  "open_weights": false,
6114
6113
  "limit": {
6115
6114
  "context": 1048576,
6116
- "output": 943718
6115
+ "output": 393216
6117
6116
  },
6118
6117
  "cost": {
6119
- "input": 0.15808,
6120
- "output": 1.9584,
6121
- "cache_read": 0.07488
6118
+ "input": 0.123,
6119
+ "output": 3.5,
6120
+ "cache_read": 0.123
6122
6121
  }
6123
6122
  },
6124
6123
  "~deepseek/deepseek-v4-flash-latest": {
@@ -6156,13 +6155,13 @@
6156
6155
  },
6157
6156
  "open_weights": false,
6158
6157
  "limit": {
6159
- "context": 1310720,
6158
+ "context": 1048576,
6160
6159
  "output": 943718
6161
6160
  },
6162
6161
  "cost": {
6163
- "input": 0.012,
6164
- "output": 0.7,
6165
- "cache_read": 0.01
6162
+ "input": 0.0099,
6163
+ "output": 0.13068,
6164
+ "cache_read": 0.001386
6166
6165
  }
6167
6166
  },
6168
6167
  "~x-ai/grok-latest": {
@@ -6666,9 +6665,9 @@
6666
6665
  "output": 235929
6667
6666
  },
6668
6667
  "cost": {
6669
- "input": 0.0765,
6670
- "output": 0.255,
6671
- "cache_read": 0.0425
6668
+ "input": 0.09,
6669
+ "output": 0.3,
6670
+ "cache_read": 0.05
6672
6671
  },
6673
6672
  "canonical_model_id": "google/gemma-4-26b-a4b-it"
6674
6673
  },
@@ -9041,8 +9040,8 @@
9041
9040
  "output": 235929
9042
9041
  },
9043
9042
  "cost": {
9044
- "input": 0.6562,
9045
- "output": 3.3,
9043
+ "input": 0.6712,
9044
+ "output": 3.35,
9046
9045
  "cache_read": 0.18
9047
9046
  },
9048
9047
  "canonical_model_id": "moonshotai/kimi-k2.7-code"
@@ -9212,7 +9211,7 @@
9212
9211
  },
9213
9212
  "open_weights": true,
9214
9213
  "limit": {
9215
- "context": 1000000,
9214
+ "context": 262144,
9216
9215
  "output": 32768
9217
9216
  },
9218
9217
  "cost": {
@@ -9717,7 +9716,7 @@
9717
9716
  },
9718
9717
  "open_weights": true,
9719
9718
  "limit": {
9720
- "context": 1048576,
9719
+ "context": 1050000,
9721
9720
  "output": 131072
9722
9721
  },
9723
9722
  "cost": {
@@ -10865,9 +10864,9 @@
10865
10864
  "output": 235929
10866
10865
  },
10867
10866
  "cost": {
10868
- "input": 0.0647,
10869
- "output": 4.4,
10870
- "cache_read": 0.0517
10867
+ "input": 0.0249,
10868
+ "output": 4.35,
10869
+ "cache_read": 0.0199
10871
10870
  },
10872
10871
  "canonical_model_id": "alibaba/qwen3.8-27b"
10873
10872
  },
@@ -11500,7 +11499,7 @@
11500
11499
  "open_weights": true,
11501
11500
  "limit": {
11502
11501
  "context": 262144,
11503
- "output": 235929
11502
+ "output": 65536
11504
11503
  },
11505
11504
  "cost": {
11506
11505
  "input": 0.26,
@@ -12242,11 +12241,11 @@
12242
12241
  "open_weights": true,
12243
12242
  "limit": {
12244
12243
  "context": 131072,
12245
- "output": 8192
12244
+ "output": 16384
12246
12245
  },
12247
12246
  "cost": {
12248
- "input": 0.13,
12249
- "output": 0.52
12247
+ "input": 0.12,
12248
+ "output": 0.5
12250
12249
  },
12251
12250
  "canonical_model_id": "alibaba/qwen3-30b-a3b"
12252
12251
  },
@@ -14148,6 +14147,73 @@
14148
14147
  "output": 2
14149
14148
  }
14150
14149
  },
14150
+ "openai/gpt-6.1-sol": {
14151
+ "id": "openai/gpt-6.1-sol",
14152
+ "name": "GPT-6.1 Sol",
14153
+ "description": "Near-Astra performance for complex coding, computer use, and professional work at a lower cost.",
14154
+ "family": "gpt-sol",
14155
+ "attachment": true,
14156
+ "reasoning": true,
14157
+ "reasoning_options": [
14158
+ {
14159
+ "type": "effort",
14160
+ "values": [
14161
+ "low",
14162
+ "medium",
14163
+ "high",
14164
+ "xhigh",
14165
+ "max"
14166
+ ]
14167
+ }
14168
+ ],
14169
+ "tool_call": true,
14170
+ "structured_output": true,
14171
+ "temperature": false,
14172
+ "knowledge": "2026-04-30",
14173
+ "release_date": "2026-09-29",
14174
+ "last_updated": "2026-09-29",
14175
+ "modalities": {
14176
+ "input": [
14177
+ "text",
14178
+ "image",
14179
+ "pdf"
14180
+ ],
14181
+ "output": [
14182
+ "text"
14183
+ ]
14184
+ },
14185
+ "open_weights": false,
14186
+ "limit": {
14187
+ "context": 1050000,
14188
+ "input": 922000,
14189
+ "output": 128000
14190
+ },
14191
+ "cost": {
14192
+ "input": 2,
14193
+ "output": 10,
14194
+ "cache_read": 0.1,
14195
+ "cache_write": 2.5,
14196
+ "tiers": [
14197
+ {
14198
+ "input": 4,
14199
+ "output": 15,
14200
+ "cache_read": 0.2,
14201
+ "cache_write": 5,
14202
+ "tier": {
14203
+ "type": "context",
14204
+ "size": 272000
14205
+ }
14206
+ }
14207
+ ],
14208
+ "context_over_200k": {
14209
+ "input": 4,
14210
+ "output": 15,
14211
+ "cache_read": 0.2,
14212
+ "cache_write": 5
14213
+ }
14214
+ },
14215
+ "canonical_model_id": "openai/gpt-6.1-sol"
14216
+ },
14151
14217
  "openai/gpt-4o-2024-08-06": {
14152
14218
  "id": "openai/gpt-4o-2024-08-06",
14153
14219
  "name": "GPT-4o (2024-08-06)",
@@ -15311,6 +15377,70 @@
15311
15377
  },
15312
15378
  "canonical_model_id": "openai/gpt-6-luna"
15313
15379
  },
15380
+ "openai/gpt-6.1-sol-pro": {
15381
+ "id": "openai/gpt-6.1-sol-pro",
15382
+ "name": "GPT-6.1 Sol Pro",
15383
+ "description": "Frontier GPT model for professional reasoning, coding, and multimodal work",
15384
+ "family": "gpt",
15385
+ "attachment": true,
15386
+ "reasoning": true,
15387
+ "reasoning_options": [
15388
+ {
15389
+ "type": "effort",
15390
+ "values": [
15391
+ "low",
15392
+ "medium",
15393
+ "high",
15394
+ "xhigh",
15395
+ "max"
15396
+ ]
15397
+ }
15398
+ ],
15399
+ "tool_call": true,
15400
+ "structured_output": true,
15401
+ "temperature": false,
15402
+ "release_date": "2026-09-29",
15403
+ "last_updated": "2026-09-29",
15404
+ "modalities": {
15405
+ "input": [
15406
+ "pdf",
15407
+ "image",
15408
+ "text"
15409
+ ],
15410
+ "output": [
15411
+ "text"
15412
+ ]
15413
+ },
15414
+ "open_weights": false,
15415
+ "limit": {
15416
+ "context": 1050000,
15417
+ "output": 128000
15418
+ },
15419
+ "cost": {
15420
+ "input": 2,
15421
+ "output": 10,
15422
+ "cache_read": 0.1,
15423
+ "cache_write": 2.5,
15424
+ "tiers": [
15425
+ {
15426
+ "input": 4,
15427
+ "output": 15,
15428
+ "cache_read": 0.2,
15429
+ "cache_write": 5,
15430
+ "tier": {
15431
+ "type": "context",
15432
+ "size": 272000
15433
+ }
15434
+ }
15435
+ ],
15436
+ "context_over_200k": {
15437
+ "input": 4,
15438
+ "output": 15,
15439
+ "cache_read": 0.2,
15440
+ "cache_write": 5
15441
+ }
15442
+ }
15443
+ },
15314
15444
  "openai/o4-mini-high": {
15315
15445
  "id": "openai/o4-mini-high",
15316
15446
  "name": "o4 Mini High",
@@ -15552,12 +15682,11 @@
15552
15682
  "open_weights": true,
15553
15683
  "limit": {
15554
15684
  "context": 131072,
15555
- "output": 65536
15685
+ "output": 117964
15556
15686
  },
15557
15687
  "cost": {
15558
- "input": 0.15,
15559
- "output": 0.6,
15560
- "cache_read": 0.075
15688
+ "input": 0.037,
15689
+ "output": 0.17
15561
15690
  },
15562
15691
  "canonical_model_id": "openai/gpt-oss-120b"
15563
15692
  },
@@ -156,6 +156,15 @@ Three more hooks cover a local tool call. `on_tool_start` fires before
156
156
  the tool runs and returns the span that `on_tool_finish` and
157
157
  `on_tool_error` receive.
158
158
 
159
+ An interrupt is neither a finish nor an error, and it is reported to a
160
+ hook of its own. `on_interrupt` is called with a `scope:` of `:request`
161
+ or `:tool` before the caller is given the exception, so a tracer that
162
+ records what happened to a turn records it while the work is still in
163
+ flight. The hook receives the span that `on_request_start` returned and
164
+ its `request_id`; a tool pass carries neither, because a tool's span
165
+ belongs to the call. A cancel reaches every tool that is running, so the
166
+ tool phase is announced once rather than once per tool.
167
+
159
168
  A tracer's own lifetime is bracketed as well. `on_exit` fires once,
160
169
  when the last scope that is open for that tracer ends. That scope can
161
170
  belong to a different thread than the one that opened the first: a tool
@@ -214,11 +223,15 @@ as hooks gain parameters.
214
223
 
215
224
  #### Notes
216
225
 
217
- The base class raises `NotImplementedError` for any hook it does not
218
- implement, so a tracer must cover every hook the runtime calls: the six
219
- request and tool hooks above. Accept `**` to absorb keywords you do not
220
- read, as the built-in tracers do, so a hook that gains a parameter does
221
- not break your subclass.
226
+ The base class raises `NotImplementedError` for the six request and tool
227
+ hooks above, so a tracer has to answer for each of them. The remaining
228
+ hooks do nothing by default. `on_exit` does nothing because most tracers
229
+ hold nothing that needs releasing, and `start_trace` and `stop_trace`
230
+ are no-ops too. `on_interrupt` does nothing because an interrupt is
231
+ delivered to whatever tracer happens to be bound, and a hook that raised
232
+ would replace the interrupt every caller is written against. Accept `**`
233
+ to absorb keywords you do not read, as the built-in tracers do, so a
234
+ hook that gains a parameter does not break your subclass.
222
235
 
223
236
  ### PrettyLogger
224
237
 
data/lib/llm/context.rb CHANGED
@@ -343,6 +343,14 @@ module LLM
343
343
  @queue = stream.queue
344
344
  @queue.wait
345
345
  end
346
+ rescue LLM::Interrupt
347
+ ##
348
+ # Once, not once per tool. A cancel reaches every tool that is
349
+ # running, and the caller hears one exception, so the phase is
350
+ # announced here - the frame every strategy's interrupt unwinds
351
+ # through - and before the caller is given it.
352
+ tracer.on_interrupt(scope: :tool)
353
+ raise
346
354
  ensure
347
355
  @queue = nil
348
356
  @stream = nil
data/lib/llm/tracer.rb CHANGED
@@ -194,6 +194,37 @@ module LLM
194
194
  raise NotImplementedError, "#{self.class} does not implement '#{__method__}'"
195
195
  end
196
196
 
197
+ ##
198
+ # Called when a request or a tool is interrupted.
199
+ #
200
+ # An interrupt is not a failure, so this is not {#on_request_error} or
201
+ # {#on_tool_error} under another name: it is the third ending either
202
+ # scope can have, and it is called before {LLM::Interrupt} reaches the
203
+ # caller, so a tracer that has to record what happened to a turn does it
204
+ # while the work is still the work in flight.
205
+ #
206
+ # A request is announced once, by the transport. A tool is announced
207
+ # once for the phase rather than once per tool: a cancel reaches every
208
+ # tool that is running and the caller hears one exception, so there is
209
+ # no one tool the announcement belongs to.
210
+ #
211
+ # The default does nothing, which is the difference from the rest of the
212
+ # lifecycle. Every other hook raises, because a tracer that means to draw
213
+ # a request has to answer for it - but an interrupt is delivered to
214
+ # whatever tracer happens to be bound, and a hook that raised here would
215
+ # replace the interrupt every caller is written against.
216
+ # @param [Symbol] scope
217
+ # :request for a request, :tool for a tool
218
+ # @param [Object, nil] span
219
+ # The span that {#on_request_start} returned. A tool pass has none:
220
+ # a tool's span belongs to the call, and the announcement is not one
221
+ # tool's to make.
222
+ # @param [String, nil] request_id
223
+ # The id, as passed to {#on_request_start}, when the scope is a request
224
+ # @return [void]
225
+ def on_interrupt(scope:, span: nil, request_id: nil)
226
+ end
227
+
197
228
  ##
198
229
  # Opens a trace group so subsequent LLM spans share the same OpenTelemetry
199
230
  # trace_id (and appear as one trace in backends like Langfuse).
@@ -38,8 +38,37 @@ class LLM::Transport
38
38
  res = transport.request(request, owner:, stream:, &b)
39
39
  res = LLM::Transport::Response.from(res)
40
40
  [handle_response(res, tracer, span, request_id), span, tracer, request_id]
41
- rescue *transport.interrupt_errors
42
- raise LLM::Interrupt, "request interrupted" if transport.interrupted?(owner)
41
+ rescue LLM::Interrupt
42
+ ##
43
+ # Curb raises this itself, from the chunk it is reading,
44
+ # which is the curb shape rather than something raised
45
+ # ordinarily: the other transports fail, and reach the
46
+ # rescue below.
47
+ #
48
+ # An interrupt is not a failure, so it is not reported as
49
+ # one - `on_interrupt` is the hook for it - and it is called
50
+ # before the caller is given the exception.
51
+ tracer.on_interrupt(scope: :request, span:, request_id:)
52
+ raise
53
+ rescue *transport.interrupt_errors => ex
54
+ ##
55
+ # Where a Net::HTTP interrupt becomes the exception the
56
+ # caller gets: the socket is closed from another thread
57
+ # and the read fails as one of these classes. The owner
58
+ # is what tells the two apart.
59
+ if transport.interrupted?(owner)
60
+ tracer.on_interrupt(scope: :request, span:, request_id:)
61
+ raise LLM::Interrupt, "request interrupted"
62
+ else
63
+ tracer.on_request_error(ex:, span:, request_id:)
64
+ raise
65
+ end
66
+ rescue => ex
67
+ ##
68
+ # Everything else ends the request, so the tracer is told:
69
+ # a span that was opened and never closed draws a request
70
+ # that never ended.
71
+ tracer.on_request_error(ex:, span:, request_id:)
43
72
  raise
44
73
  end
45
74
 
data/lib/llm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LLM
4
- VERSION = "16.0.0.pre.5"
4
+ VERSION = "16.0.0.pre.6"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llm.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.0.0.pre.5
4
+ version: 16.0.0.pre.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Gleeson