llm.rb 12.1.0 → 12.3.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +248 -0
  3. data/README.md +77 -27
  4. data/data/anthropic.json +3 -2
  5. data/data/bedrock.json +47 -0
  6. data/data/deepinfra.json +2 -2
  7. data/data/google.json +32 -0
  8. data/data/mistral.json +968 -0
  9. data/data/openai.json +422 -0
  10. data/data/xai.json +60 -1
  11. data/lib/llm/active_record/acts_as_agent.rb +11 -0
  12. data/lib/llm/agent.rb +27 -3
  13. data/lib/llm/compactor.rb +2 -2
  14. data/lib/llm/context.rb +18 -26
  15. data/lib/llm/function.rb +6 -0
  16. data/lib/llm/object.rb +13 -0
  17. data/lib/llm/provider.rb +12 -9
  18. data/lib/llm/providers/anthropic.rb +4 -5
  19. data/lib/llm/providers/bedrock.rb +4 -5
  20. data/lib/llm/providers/google.rb +7 -3
  21. data/lib/llm/providers/mistral/request_adapter/completion.rb +122 -0
  22. data/lib/llm/providers/mistral/request_adapter.rb +20 -0
  23. data/lib/llm/providers/mistral.rb +145 -0
  24. data/lib/llm/providers/ollama/response_adapter/completion.rb +39 -0
  25. data/lib/llm/providers/ollama.rb +2 -3
  26. data/lib/llm/providers/openai/responses.rb +6 -3
  27. data/lib/llm/providers/openai.rb +2 -3
  28. data/lib/llm/repl/bar.rb +52 -0
  29. data/lib/llm/repl/input.rb +143 -30
  30. data/lib/llm/repl/markdown.rb +85 -0
  31. data/lib/llm/repl/status.rb +16 -5
  32. data/lib/llm/repl/stream.rb +15 -5
  33. data/lib/llm/repl/transcript.rb +107 -18
  34. data/lib/llm/repl/window.rb +43 -17
  35. data/lib/llm/repl.rb +99 -18
  36. data/lib/llm/sequel/agent.rb +11 -0
  37. data/lib/llm/skill.rb +1 -1
  38. data/lib/llm/stream/disabled.rb +23 -0
  39. data/lib/llm/stream/io.rb +43 -0
  40. data/lib/llm/stream.rb +34 -0
  41. data/lib/llm/tools/git.rb +2 -3
  42. data/lib/llm/tools/pwd.rb +0 -1
  43. data/lib/llm/tools/rg.rb +2 -1
  44. data/lib/llm/tools/swap_text.rb +6 -0
  45. data/lib/llm/transport/execution.rb +1 -0
  46. data/lib/llm/version.rb +1 -1
  47. data/lib/llm.rb +19 -0
  48. data/llm.gemspec +8 -4
  49. data/resources/deepdive.md +170 -50
  50. metadata +15 -4
data/data/openai.json CHANGED
@@ -124,6 +124,99 @@
124
124
  "output": 168
125
125
  }
126
126
  },
127
+ "gpt-5.6": {
128
+ "id": "gpt-5.6",
129
+ "name": "GPT-5.6",
130
+ "description": "Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows",
131
+ "family": "gpt",
132
+ "attachment": true,
133
+ "reasoning": true,
134
+ "reasoning_options": [
135
+ {
136
+ "type": "effort",
137
+ "values": [
138
+ "none",
139
+ "low",
140
+ "medium",
141
+ "high",
142
+ "xhigh",
143
+ "max"
144
+ ]
145
+ }
146
+ ],
147
+ "tool_call": true,
148
+ "structured_output": true,
149
+ "temperature": false,
150
+ "knowledge": "2026-02-16",
151
+ "release_date": "2026-07-09",
152
+ "last_updated": "2026-07-09",
153
+ "modalities": {
154
+ "input": [
155
+ "text",
156
+ "image",
157
+ "pdf"
158
+ ],
159
+ "output": [
160
+ "text"
161
+ ]
162
+ },
163
+ "open_weights": false,
164
+ "limit": {
165
+ "context": 1050000,
166
+ "input": 922000,
167
+ "output": 128000
168
+ },
169
+ "experimental": {
170
+ "modes": {
171
+ "fast": {
172
+ "cost": {
173
+ "input": 10,
174
+ "output": 60,
175
+ "cache_read": 1,
176
+ "cache_write": 12.5
177
+ },
178
+ "provider": {
179
+ "body": {
180
+ "service_tier": "priority"
181
+ }
182
+ }
183
+ },
184
+ "pro": {
185
+ "provider": {
186
+ "body": {
187
+ "reasoning": {
188
+ "mode": "pro"
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ },
195
+ "cost": {
196
+ "input": 5,
197
+ "output": 30,
198
+ "cache_read": 0.5,
199
+ "cache_write": 6.25,
200
+ "tiers": [
201
+ {
202
+ "input": 10,
203
+ "output": 45,
204
+ "cache_read": 1,
205
+ "cache_write": 12.5,
206
+ "tier": {
207
+ "type": "context",
208
+ "size": 272000
209
+ }
210
+ }
211
+ ],
212
+ "context_over_200k": {
213
+ "input": 10,
214
+ "output": 45,
215
+ "cache_read": 1,
216
+ "cache_write": 12.5
217
+ }
218
+ }
219
+ },
127
220
  "gpt-5": {
128
221
  "id": "gpt-5",
129
222
  "name": "GPT-5",
@@ -930,6 +1023,99 @@
930
1023
  "output": 0
931
1024
  }
932
1025
  },
1026
+ "gpt-5.6-luna": {
1027
+ "id": "gpt-5.6-luna",
1028
+ "name": "GPT-5.6 Luna",
1029
+ "description": "Cost-efficient GPT-5.6 model for fast, high-volume workloads",
1030
+ "family": "gpt-nano",
1031
+ "attachment": true,
1032
+ "reasoning": true,
1033
+ "reasoning_options": [
1034
+ {
1035
+ "type": "effort",
1036
+ "values": [
1037
+ "none",
1038
+ "low",
1039
+ "medium",
1040
+ "high",
1041
+ "xhigh",
1042
+ "max"
1043
+ ]
1044
+ }
1045
+ ],
1046
+ "tool_call": true,
1047
+ "structured_output": true,
1048
+ "temperature": false,
1049
+ "knowledge": "2026-02-16",
1050
+ "release_date": "2026-07-09",
1051
+ "last_updated": "2026-07-09",
1052
+ "modalities": {
1053
+ "input": [
1054
+ "text",
1055
+ "image",
1056
+ "pdf"
1057
+ ],
1058
+ "output": [
1059
+ "text"
1060
+ ]
1061
+ },
1062
+ "open_weights": false,
1063
+ "limit": {
1064
+ "context": 1050000,
1065
+ "input": 922000,
1066
+ "output": 128000
1067
+ },
1068
+ "experimental": {
1069
+ "modes": {
1070
+ "fast": {
1071
+ "cost": {
1072
+ "input": 2,
1073
+ "output": 12,
1074
+ "cache_read": 0.2,
1075
+ "cache_write": 2.5
1076
+ },
1077
+ "provider": {
1078
+ "body": {
1079
+ "service_tier": "priority"
1080
+ }
1081
+ }
1082
+ },
1083
+ "pro": {
1084
+ "provider": {
1085
+ "body": {
1086
+ "reasoning": {
1087
+ "mode": "pro"
1088
+ }
1089
+ }
1090
+ }
1091
+ }
1092
+ }
1093
+ },
1094
+ "cost": {
1095
+ "input": 1,
1096
+ "output": 6,
1097
+ "cache_read": 0.1,
1098
+ "cache_write": 1.25,
1099
+ "tiers": [
1100
+ {
1101
+ "input": 2,
1102
+ "output": 9,
1103
+ "cache_read": 0.2,
1104
+ "cache_write": 2.5,
1105
+ "tier": {
1106
+ "type": "context",
1107
+ "size": 272000
1108
+ }
1109
+ }
1110
+ ],
1111
+ "context_over_200k": {
1112
+ "input": 2,
1113
+ "output": 9,
1114
+ "cache_read": 0.2,
1115
+ "cache_write": 2.5
1116
+ }
1117
+ }
1118
+ },
933
1119
  "gpt-5.1-codex-mini": {
934
1120
  "id": "gpt-5.1-codex-mini",
935
1121
  "name": "GPT-5.1 Codex mini",
@@ -974,6 +1160,149 @@
974
1160
  "cache_read": 0.025
975
1161
  }
976
1162
  },
1163
+ "gpt-realtime-2.1": {
1164
+ "id": "gpt-realtime-2.1",
1165
+ "name": "GPT-Realtime-2.1",
1166
+ "description": "Realtime speech-to-speech model with configurable reasoning, tool use, and robust voice-agent behavior",
1167
+ "family": "gpt",
1168
+ "attachment": true,
1169
+ "reasoning": true,
1170
+ "reasoning_options": [
1171
+ {
1172
+ "type": "effort",
1173
+ "values": [
1174
+ "minimal",
1175
+ "low",
1176
+ "medium",
1177
+ "high",
1178
+ "xhigh"
1179
+ ]
1180
+ }
1181
+ ],
1182
+ "tool_call": true,
1183
+ "structured_output": false,
1184
+ "temperature": false,
1185
+ "knowledge": "2024-09-30",
1186
+ "release_date": "2026-07-06",
1187
+ "last_updated": "2026-07-06",
1188
+ "modalities": {
1189
+ "input": [
1190
+ "text",
1191
+ "audio",
1192
+ "image"
1193
+ ],
1194
+ "output": [
1195
+ "text",
1196
+ "audio"
1197
+ ]
1198
+ },
1199
+ "open_weights": false,
1200
+ "limit": {
1201
+ "context": 128000,
1202
+ "input": 96000,
1203
+ "output": 32000
1204
+ },
1205
+ "cost": {
1206
+ "input": 4,
1207
+ "output": 24,
1208
+ "cache_read": 0.4,
1209
+ "input_audio": 32,
1210
+ "output_audio": 64
1211
+ }
1212
+ },
1213
+ "gpt-5.6-terra": {
1214
+ "id": "gpt-5.6-terra",
1215
+ "name": "GPT-5.6 Terra",
1216
+ "description": "Balanced GPT-5.6 model for capable, cost-efficient everyday work",
1217
+ "family": "gpt-mini",
1218
+ "attachment": true,
1219
+ "reasoning": true,
1220
+ "reasoning_options": [
1221
+ {
1222
+ "type": "effort",
1223
+ "values": [
1224
+ "none",
1225
+ "low",
1226
+ "medium",
1227
+ "high",
1228
+ "xhigh",
1229
+ "max"
1230
+ ]
1231
+ }
1232
+ ],
1233
+ "tool_call": true,
1234
+ "structured_output": true,
1235
+ "temperature": false,
1236
+ "knowledge": "2026-02-16",
1237
+ "release_date": "2026-07-09",
1238
+ "last_updated": "2026-07-09",
1239
+ "modalities": {
1240
+ "input": [
1241
+ "text",
1242
+ "image",
1243
+ "pdf"
1244
+ ],
1245
+ "output": [
1246
+ "text"
1247
+ ]
1248
+ },
1249
+ "open_weights": false,
1250
+ "limit": {
1251
+ "context": 1050000,
1252
+ "input": 922000,
1253
+ "output": 128000
1254
+ },
1255
+ "experimental": {
1256
+ "modes": {
1257
+ "fast": {
1258
+ "cost": {
1259
+ "input": 5,
1260
+ "output": 30,
1261
+ "cache_read": 0.5,
1262
+ "cache_write": 6.25
1263
+ },
1264
+ "provider": {
1265
+ "body": {
1266
+ "service_tier": "priority"
1267
+ }
1268
+ }
1269
+ },
1270
+ "pro": {
1271
+ "provider": {
1272
+ "body": {
1273
+ "reasoning": {
1274
+ "mode": "pro"
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ }
1280
+ },
1281
+ "cost": {
1282
+ "input": 2.5,
1283
+ "output": 15,
1284
+ "cache_read": 0.25,
1285
+ "cache_write": 3.125,
1286
+ "tiers": [
1287
+ {
1288
+ "input": 5,
1289
+ "output": 22.5,
1290
+ "cache_read": 0.5,
1291
+ "cache_write": 6.25,
1292
+ "tier": {
1293
+ "type": "context",
1294
+ "size": 272000
1295
+ }
1296
+ }
1297
+ ],
1298
+ "context_over_200k": {
1299
+ "input": 5,
1300
+ "output": 22.5,
1301
+ "cache_read": 0.5,
1302
+ "cache_write": 6.25
1303
+ }
1304
+ }
1305
+ },
977
1306
  "gpt-5.1-chat-latest": {
978
1307
  "id": "gpt-5.1-chat-latest",
979
1308
  "name": "GPT-5.1 Chat",
@@ -1851,6 +2180,99 @@
1851
2180
  "cache_read": 0.075
1852
2181
  }
1853
2182
  },
2183
+ "gpt-5.6-sol": {
2184
+ "id": "gpt-5.6-sol",
2185
+ "name": "GPT-5.6 Sol",
2186
+ "description": "Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows",
2187
+ "family": "gpt",
2188
+ "attachment": true,
2189
+ "reasoning": true,
2190
+ "reasoning_options": [
2191
+ {
2192
+ "type": "effort",
2193
+ "values": [
2194
+ "none",
2195
+ "low",
2196
+ "medium",
2197
+ "high",
2198
+ "xhigh",
2199
+ "max"
2200
+ ]
2201
+ }
2202
+ ],
2203
+ "tool_call": true,
2204
+ "structured_output": true,
2205
+ "temperature": false,
2206
+ "knowledge": "2026-02-16",
2207
+ "release_date": "2026-07-09",
2208
+ "last_updated": "2026-07-09",
2209
+ "modalities": {
2210
+ "input": [
2211
+ "text",
2212
+ "image",
2213
+ "pdf"
2214
+ ],
2215
+ "output": [
2216
+ "text"
2217
+ ]
2218
+ },
2219
+ "open_weights": false,
2220
+ "limit": {
2221
+ "context": 1050000,
2222
+ "input": 922000,
2223
+ "output": 128000
2224
+ },
2225
+ "experimental": {
2226
+ "modes": {
2227
+ "fast": {
2228
+ "cost": {
2229
+ "input": 10,
2230
+ "output": 60,
2231
+ "cache_read": 1,
2232
+ "cache_write": 12.5
2233
+ },
2234
+ "provider": {
2235
+ "body": {
2236
+ "service_tier": "priority"
2237
+ }
2238
+ }
2239
+ },
2240
+ "pro": {
2241
+ "provider": {
2242
+ "body": {
2243
+ "reasoning": {
2244
+ "mode": "pro"
2245
+ }
2246
+ }
2247
+ }
2248
+ }
2249
+ }
2250
+ },
2251
+ "cost": {
2252
+ "input": 5,
2253
+ "output": 30,
2254
+ "cache_read": 0.5,
2255
+ "cache_write": 6.25,
2256
+ "tiers": [
2257
+ {
2258
+ "input": 10,
2259
+ "output": 45,
2260
+ "cache_read": 1,
2261
+ "cache_write": 12.5,
2262
+ "tier": {
2263
+ "type": "context",
2264
+ "size": 272000
2265
+ }
2266
+ }
2267
+ ],
2268
+ "context_over_200k": {
2269
+ "input": 10,
2270
+ "output": 45,
2271
+ "cache_read": 1,
2272
+ "cache_write": 12.5
2273
+ }
2274
+ }
2275
+ },
1854
2276
  "gpt-5-codex": {
1855
2277
  "id": "gpt-5-codex",
1856
2278
  "name": "GPT-5-Codex",
data/data/xai.json CHANGED
@@ -119,7 +119,7 @@
119
119
  "grok-4.3": {
120
120
  "id": "grok-4.3",
121
121
  "name": "Grok 4.3",
122
- "description": "xAI's default Grok for chat, coding, agentic tools, and lower hallucination risk",
122
+ "description": "xAI's Grok for chat, coding, agentic tools, and lower hallucination risk",
123
123
  "family": "grok",
124
124
  "attachment": true,
125
125
  "reasoning": true,
@@ -232,6 +232,65 @@
232
232
  "output": 0
233
233
  }
234
234
  },
235
+ "grok-4.5": {
236
+ "id": "grok-4.5",
237
+ "name": "Grok 4.5",
238
+ "description": "xAI's latest Grok for chat, coding, agentic tools, and lower hallucination risk",
239
+ "family": "grok",
240
+ "attachment": true,
241
+ "reasoning": true,
242
+ "reasoning_options": [
243
+ {
244
+ "type": "effort",
245
+ "values": [
246
+ "low",
247
+ "medium",
248
+ "high"
249
+ ]
250
+ }
251
+ ],
252
+ "tool_call": true,
253
+ "structured_output": true,
254
+ "temperature": true,
255
+ "release_date": "2026-07-08",
256
+ "last_updated": "2026-07-08",
257
+ "modalities": {
258
+ "input": [
259
+ "text",
260
+ "image",
261
+ "pdf"
262
+ ],
263
+ "output": [
264
+ "text"
265
+ ]
266
+ },
267
+ "open_weights": false,
268
+ "limit": {
269
+ "context": 500000,
270
+ "output": 500000
271
+ },
272
+ "cost": {
273
+ "input": 2,
274
+ "output": 6,
275
+ "cache_read": 0.5,
276
+ "tiers": [
277
+ {
278
+ "input": 4,
279
+ "output": 12,
280
+ "cache_read": 1,
281
+ "tier": {
282
+ "type": "context",
283
+ "size": 200000
284
+ }
285
+ }
286
+ ],
287
+ "context_over_200k": {
288
+ "input": 4,
289
+ "output": 12,
290
+ "cache_read": 1
291
+ }
292
+ }
293
+ },
235
294
  "grok-4.20-0309-reasoning": {
236
295
  "id": "grok-4.20-0309-reasoning",
237
296
  "name": "Grok 4.20 (Reasoning)",
@@ -75,6 +75,17 @@ module LLM::ActiveRecord
75
75
  @llm
76
76
  end
77
77
 
78
+ ##
79
+ # @note
80
+ # This method does not persist to the database,
81
+ # but it can inspect and alter runtime state in
82
+ # a way that is temporary.
83
+ # @param (see LLM::Agent#repl)
84
+ # @return (see LLM::Agent#repl)
85
+ def repl(**params)
86
+ ctx.repl(**params)
87
+ end
88
+
78
89
  private
79
90
 
80
91
  ##
data/lib/llm/agent.rb CHANGED
@@ -393,10 +393,34 @@ module LLM
393
393
  # with the agent and its current state. This
394
394
  # method requires the 'curses' gem to be installed
395
395
  # and available to require.
396
+ #
397
+ # @note
398
+ # By default this method disables the tracer for
399
+ # the duration of the repl session, and restores
400
+ # it afterwards.
401
+ # @param [Boolean] tracer
402
+ # When true, the tracer is kept alive during the
403
+ # repl session. Default is false.
404
+ # @param [Array<LLM::Tool>] tools
405
+ # Extra tools to attach for the repl session
406
+ # @param [Array<String>] skills
407
+ # Extra skills to attach for the repl session
396
408
  # @return [void]
397
- def repl
409
+ def repl(tracer: false, trace: nil, tools: [], skills: [])
410
+ if trace != nil
411
+ warn "llm.rb: trace option is deprecated, use tracer instead"
412
+ tracer = trace
413
+ end
414
+ if !tracer
415
+ previous = self.tracer
416
+ self.tracer = nil
417
+ end
398
418
  require_relative "repl" unless defined?(::LLM::Repl)
399
- LLM::Repl.new(self).start
419
+ LLM::Repl.new(agent: self, tools:, skills:).start
420
+ ensure
421
+ if !trace
422
+ self.tracer = previous
423
+ end
400
424
  end
401
425
 
402
426
  ##
@@ -510,7 +534,7 @@ module LLM
510
534
  max = params.key?(:tool_attempts) ? params.delete(:tool_attempts) : 25
511
535
  max = Integer(max) if max
512
536
  stream = params[:stream] || @ctx.params[:stream]
513
- stream.extra[:concurrency] = concurrency if LLM::Stream === stream
537
+ params[:stream] = LLM::Stream.try(stream, extra: {concurrency:})
514
538
  res = talk.call(apply_instructions(prompt), params)
515
539
  while @ctx.functions?
516
540
  if max
data/lib/llm/compactor.rb CHANGED
@@ -71,13 +71,13 @@ class LLM::Compactor
71
71
  retention_window = [config[:retention_window], messages.size].min
72
72
  return nil unless messages.size > retention_window
73
73
  stream = ctx.params[:stream]
74
- stream.on_compaction(ctx, self) if LLM::Stream === stream
74
+ stream.on_compaction(ctx, self)
75
75
  recent = retained_messages
76
76
  older = messages[0...(messages.size - recent.size)]
77
77
  summary = LLM::Message.new(ctx.llm.user_role, "[Previous conversation summary]\n\n#{summarize(older)}", {compaction: true})
78
78
  ctx.messages.replace([*ctx.messages.take_while(&:system?), summary, *recent])
79
79
  ctx.compacted = true
80
- stream.on_compaction_finish(ctx, self) if LLM::Stream === stream
80
+ stream.on_compaction_finish(ctx, self)
81
81
  summary
82
82
  end
83
83