liter_llm 2.1.4 → 2.2.3

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.
@@ -1,5 +1,5 @@
1
1
  // This file is auto-generated by alef. DO NOT EDIT.
2
- // alef:hash:0298ffd63d1edf1d3ee3e4b3928b7608944a5687feff10faee95958dce861a54
2
+ // alef:hash:3861ed195f3c3e52018feb23f8f7da4fefbc958be2e63235f137618ed6fec98a
3
3
  // Re-generate with: alef generate
4
4
  #![allow(dead_code, unused_imports, unused_variables)]
5
5
  #![allow(
@@ -1404,6 +1404,141 @@ impl CacheConfig {
1404
1404
  }
1405
1405
  }
1406
1406
 
1407
+ #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
1408
+ #[serde(default)]
1409
+ #[magnus::wrap(class = "LiterLlm::CatalogInfo")]
1410
+ pub struct CatalogInfo {
1411
+ source: String,
1412
+ source_sha256: String,
1413
+ fetched: String,
1414
+ library_version: String,
1415
+ schema_version: u64,
1416
+ origin: String,
1417
+ }
1418
+
1419
+ unsafe impl IntoValueFromNative for CatalogInfo {}
1420
+
1421
+ impl magnus::TryConvert for CatalogInfo {
1422
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
1423
+ if let Ok(r) = <&CatalogInfo as magnus::TryConvert>::try_convert(val) {
1424
+ return Ok(r.clone());
1425
+ }
1426
+ let json_str: String = if let Ok(s) = <String as magnus::TryConvert>::try_convert(val) {
1427
+ s
1428
+ } else {
1429
+ val.funcall::<_, _, String>("to_json", ()).map_err(|e| {
1430
+ magnus::Error::new(
1431
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1432
+ format!("no implicit conversion into CatalogInfo: {}", e),
1433
+ )
1434
+ })?
1435
+ };
1436
+ serde_json::from_str::<CatalogInfo>(&json_str).map_err(|e| {
1437
+ magnus::Error::new(
1438
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1439
+ format!("failed to deserialize CatalogInfo: {}", e),
1440
+ )
1441
+ })
1442
+ }
1443
+ }
1444
+
1445
+ unsafe impl TryConvertOwned for CatalogInfo {}
1446
+
1447
+ impl Default for CatalogInfo {
1448
+ fn default() -> Self {
1449
+ liter_llm::CatalogInfo::default().into()
1450
+ }
1451
+ }
1452
+
1453
+ impl CatalogInfo {
1454
+ fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
1455
+ let ruby = unsafe { magnus::Ruby::get_unchecked() };
1456
+ let args = magnus::scan_args::scan_args::<(), (Option<magnus::RHash>,), (), (), (), ()>(args)?;
1457
+ let (kwargs_opt,) = args.optional;
1458
+ let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
1459
+ Ok(Self {
1460
+ source: match kwargs.get(ruby.to_symbol("source")) {
1461
+ Some(v) => String::try_convert(v).map_err(|e| {
1462
+ magnus::Error::new(
1463
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1464
+ format!("invalid value for `source`: {}", e),
1465
+ )
1466
+ })?,
1467
+ None => Default::default(),
1468
+ },
1469
+ source_sha256: match kwargs.get(ruby.to_symbol("source_sha256")) {
1470
+ Some(v) => String::try_convert(v).map_err(|e| {
1471
+ magnus::Error::new(
1472
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1473
+ format!("invalid value for `source_sha256`: {}", e),
1474
+ )
1475
+ })?,
1476
+ None => Default::default(),
1477
+ },
1478
+ fetched: match kwargs.get(ruby.to_symbol("fetched")) {
1479
+ Some(v) => String::try_convert(v).map_err(|e| {
1480
+ magnus::Error::new(
1481
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1482
+ format!("invalid value for `fetched`: {}", e),
1483
+ )
1484
+ })?,
1485
+ None => Default::default(),
1486
+ },
1487
+ library_version: match kwargs.get(ruby.to_symbol("library_version")) {
1488
+ Some(v) => String::try_convert(v).map_err(|e| {
1489
+ magnus::Error::new(
1490
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1491
+ format!("invalid value for `library_version`: {}", e),
1492
+ )
1493
+ })?,
1494
+ None => Default::default(),
1495
+ },
1496
+ schema_version: match kwargs.get(ruby.to_symbol("schema_version")) {
1497
+ Some(v) => u64::try_convert(v).map_err(|e| {
1498
+ magnus::Error::new(
1499
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1500
+ format!("invalid value for `schema_version`: {}", e),
1501
+ )
1502
+ })?,
1503
+ None => Default::default(),
1504
+ },
1505
+ origin: match kwargs.get(ruby.to_symbol("origin")) {
1506
+ Some(v) => String::try_convert(v).map_err(|e| {
1507
+ magnus::Error::new(
1508
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
1509
+ format!("invalid value for `origin`: {}", e),
1510
+ )
1511
+ })?,
1512
+ None => Default::default(),
1513
+ },
1514
+ })
1515
+ }
1516
+
1517
+ fn source(&self) -> String {
1518
+ self.source.clone()
1519
+ }
1520
+
1521
+ fn source_sha256(&self) -> String {
1522
+ self.source_sha256.clone()
1523
+ }
1524
+
1525
+ fn fetched(&self) -> String {
1526
+ self.fetched.clone()
1527
+ }
1528
+
1529
+ fn library_version(&self) -> String {
1530
+ self.library_version.clone()
1531
+ }
1532
+
1533
+ fn schema_version(&self) -> u64 {
1534
+ self.schema_version
1535
+ }
1536
+
1537
+ fn origin(&self) -> String {
1538
+ self.origin.clone()
1539
+ }
1540
+ }
1541
+
1407
1542
  #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
1408
1543
  #[serde(default)]
1409
1544
  #[magnus::wrap(class = "LiterLlm::CatalogRefreshConfig")]
@@ -2538,6 +2673,220 @@ impl Choice {
2538
2673
  }
2539
2674
  }
2540
2675
 
2676
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2677
+ #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
2678
+ #[serde(default)]
2679
+ #[magnus::wrap(class = "LiterLlm::ClientOptions")]
2680
+ pub struct ClientOptions {
2681
+ api_key: String,
2682
+ base_url: Option<String>,
2683
+ timeout_secs: Option<u64>,
2684
+ max_retries: Option<u32>,
2685
+ max_response_bytes: Option<u64>,
2686
+ model_hint: Option<String>,
2687
+ }
2688
+
2689
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2690
+ unsafe impl IntoValueFromNative for ClientOptions {}
2691
+
2692
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2693
+ impl magnus::TryConvert for ClientOptions {
2694
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
2695
+ if let Ok(r) = <&ClientOptions as magnus::TryConvert>::try_convert(val) {
2696
+ return Ok(r.clone());
2697
+ }
2698
+ let json_str: String = if let Ok(s) = <String as magnus::TryConvert>::try_convert(val) {
2699
+ s
2700
+ } else {
2701
+ val.funcall::<_, _, String>("to_json", ()).map_err(|e| {
2702
+ magnus::Error::new(
2703
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2704
+ format!("no implicit conversion into ClientOptions: {}", e),
2705
+ )
2706
+ })?
2707
+ };
2708
+ serde_json::from_str::<ClientOptions>(&json_str).map_err(|e| {
2709
+ magnus::Error::new(
2710
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2711
+ format!("failed to deserialize ClientOptions: {}", e),
2712
+ )
2713
+ })
2714
+ }
2715
+ }
2716
+
2717
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2718
+ unsafe impl TryConvertOwned for ClientOptions {}
2719
+
2720
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2721
+ impl Default for ClientOptions {
2722
+ fn default() -> Self {
2723
+ liter_llm::ClientOptions::default().into()
2724
+ }
2725
+ }
2726
+
2727
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
2728
+ impl ClientOptions {
2729
+ fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
2730
+ let ruby = unsafe { magnus::Ruby::get_unchecked() };
2731
+ let args = magnus::scan_args::scan_args::<(), (Option<magnus::RHash>,), (), (), (), ()>(args)?;
2732
+ let (kwargs_opt,) = args.optional;
2733
+ let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2734
+ Ok(Self {
2735
+ api_key: match kwargs.get(ruby.to_symbol("api_key")) {
2736
+ Some(v) => String::try_convert(v).map_err(|e| {
2737
+ magnus::Error::new(
2738
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2739
+ format!("invalid value for `api_key`: {}", e),
2740
+ )
2741
+ })?,
2742
+ None => Default::default(),
2743
+ },
2744
+ base_url: match kwargs.get(ruby.to_symbol("base_url")).filter(|v| !v.is_nil()) {
2745
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2746
+ magnus::Error::new(
2747
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2748
+ format!("invalid value for `base_url`: {}", e),
2749
+ )
2750
+ })?),
2751
+ None => None,
2752
+ },
2753
+ timeout_secs: match kwargs.get(ruby.to_symbol("timeout_secs")).filter(|v| !v.is_nil()) {
2754
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
2755
+ magnus::Error::new(
2756
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2757
+ format!("invalid value for `timeout_secs`: {}", e),
2758
+ )
2759
+ })?),
2760
+ None => None,
2761
+ },
2762
+ max_retries: match kwargs.get(ruby.to_symbol("max_retries")).filter(|v| !v.is_nil()) {
2763
+ Some(v) => Some(u32::try_convert(v).map_err(|e| {
2764
+ magnus::Error::new(
2765
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2766
+ format!("invalid value for `max_retries`: {}", e),
2767
+ )
2768
+ })?),
2769
+ None => None,
2770
+ },
2771
+ max_response_bytes: match kwargs.get(ruby.to_symbol("max_response_bytes")).filter(|v| !v.is_nil()) {
2772
+ Some(v) => Some(u64::try_convert(v).map_err(|e| {
2773
+ magnus::Error::new(
2774
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2775
+ format!("invalid value for `max_response_bytes`: {}", e),
2776
+ )
2777
+ })?),
2778
+ None => None,
2779
+ },
2780
+ model_hint: match kwargs.get(ruby.to_symbol("model_hint")).filter(|v| !v.is_nil()) {
2781
+ Some(v) => Some(String::try_convert(v).map_err(|e| {
2782
+ magnus::Error::new(
2783
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2784
+ format!("invalid value for `model_hint`: {}", e),
2785
+ )
2786
+ })?),
2787
+ None => None,
2788
+ },
2789
+ })
2790
+ }
2791
+
2792
+ fn api_key(&self) -> String {
2793
+ self.api_key.clone()
2794
+ }
2795
+
2796
+ fn base_url(&self) -> Option<String> {
2797
+ self.base_url.clone()
2798
+ }
2799
+
2800
+ fn timeout_secs(&self) -> Option<u64> {
2801
+ self.timeout_secs
2802
+ }
2803
+
2804
+ fn max_retries(&self) -> Option<u32> {
2805
+ self.max_retries
2806
+ }
2807
+
2808
+ fn max_response_bytes(&self) -> Option<u64> {
2809
+ self.max_response_bytes
2810
+ }
2811
+
2812
+ fn model_hint(&self) -> Option<String> {
2813
+ self.model_hint.clone()
2814
+ }
2815
+ }
2816
+
2817
+ #[derive(Clone, Debug, serde::Serialize)]
2818
+ #[serde(default)]
2819
+ #[magnus::wrap(class = "LiterLlm::CompletionTokensDetails")]
2820
+ pub struct CompletionTokensDetails {
2821
+ reasoning_tokens: u64,
2822
+ }
2823
+
2824
+ unsafe impl IntoValueFromNative for CompletionTokensDetails {}
2825
+
2826
+ impl magnus::TryConvert for CompletionTokensDetails {
2827
+ fn try_convert(val: magnus::Value) -> Result<Self, magnus::Error> {
2828
+ if let Ok(r) = <&CompletionTokensDetails as magnus::TryConvert>::try_convert(val) {
2829
+ return Ok(r.clone());
2830
+ }
2831
+ let json_str: String = if let Ok(s) = <String as magnus::TryConvert>::try_convert(val) {
2832
+ s
2833
+ } else {
2834
+ val.funcall::<_, _, String>("to_json", ()).map_err(|e| {
2835
+ magnus::Error::new(
2836
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2837
+ format!("no implicit conversion into CompletionTokensDetails: {}", e),
2838
+ )
2839
+ })?
2840
+ };
2841
+ serde_json::from_str::<CompletionTokensDetails>(&json_str).map_err(|e| {
2842
+ magnus::Error::new(
2843
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2844
+ format!("failed to deserialize CompletionTokensDetails: {}", e),
2845
+ )
2846
+ })
2847
+ }
2848
+ }
2849
+
2850
+ unsafe impl TryConvertOwned for CompletionTokensDetails {}
2851
+ impl<'de> serde::Deserialize<'de> for CompletionTokensDetails {
2852
+ fn deserialize<D>(deserializer: D) -> ::core::result::Result<Self, D::Error>
2853
+ where
2854
+ D: serde::Deserializer<'de>,
2855
+ {
2856
+ <liter_llm::types::CompletionTokensDetails as serde::Deserialize>::deserialize(deserializer).map(Into::into)
2857
+ }
2858
+ }
2859
+
2860
+ impl Default for CompletionTokensDetails {
2861
+ fn default() -> Self {
2862
+ liter_llm::types::CompletionTokensDetails::default().into()
2863
+ }
2864
+ }
2865
+
2866
+ impl CompletionTokensDetails {
2867
+ fn new(args: &[magnus::Value]) -> Result<Self, magnus::Error> {
2868
+ let ruby = unsafe { magnus::Ruby::get_unchecked() };
2869
+ let args = magnus::scan_args::scan_args::<(), (Option<magnus::RHash>,), (), (), (), ()>(args)?;
2870
+ let (kwargs_opt,) = args.optional;
2871
+ let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
2872
+ Ok(Self {
2873
+ reasoning_tokens: match kwargs.get(ruby.to_symbol("reasoning_tokens")) {
2874
+ Some(v) => u64::try_convert(v).map_err(|e| {
2875
+ magnus::Error::new(
2876
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
2877
+ format!("invalid value for `reasoning_tokens`: {}", e),
2878
+ )
2879
+ })?,
2880
+ None => Default::default(),
2881
+ },
2882
+ })
2883
+ }
2884
+
2885
+ fn reasoning_tokens(&self) -> u64 {
2886
+ self.reasoning_tokens
2887
+ }
2888
+ }
2889
+
2541
2890
  #[derive(Clone, Debug, serde::Serialize)]
2542
2891
  #[serde(default)]
2543
2892
  #[magnus::wrap(class = "LiterLlm::CreateBatchRequest")]
@@ -6913,6 +7262,9 @@ impl LlmRateLimitConfig {
6913
7262
  #[serde(default)]
6914
7263
  #[magnus::wrap(class = "LiterLlm::ModelInfo")]
6915
7264
  pub struct ModelInfo {
7265
+ matched_key: String,
7266
+ exact: bool,
7267
+ price_known: bool,
6916
7268
  input_cost_per_token: f64,
6917
7269
  output_cost_per_token: f64,
6918
7270
  cache_read_input_token_cost: Option<f64>,
@@ -6975,6 +7327,33 @@ impl ModelInfo {
6975
7327
  let (kwargs_opt,) = args.optional;
6976
7328
  let kwargs = kwargs_opt.unwrap_or_else(|| ruby.hash_new());
6977
7329
  Ok(Self {
7330
+ matched_key: match kwargs.get(ruby.to_symbol("matched_key")) {
7331
+ Some(v) => String::try_convert(v).map_err(|e| {
7332
+ magnus::Error::new(
7333
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
7334
+ format!("invalid value for `matched_key`: {}", e),
7335
+ )
7336
+ })?,
7337
+ None => Default::default(),
7338
+ },
7339
+ exact: match kwargs.get(ruby.to_symbol("exact")) {
7340
+ Some(v) => bool::try_convert(v).map_err(|e| {
7341
+ magnus::Error::new(
7342
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
7343
+ format!("invalid value for `exact`: {}", e),
7344
+ )
7345
+ })?,
7346
+ None => Default::default(),
7347
+ },
7348
+ price_known: match kwargs.get(ruby.to_symbol("price_known")) {
7349
+ Some(v) => bool::try_convert(v).map_err(|e| {
7350
+ magnus::Error::new(
7351
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
7352
+ format!("invalid value for `price_known`: {}", e),
7353
+ )
7354
+ })?,
7355
+ None => Default::default(),
7356
+ },
6978
7357
  input_cost_per_token: match kwargs.get(ruby.to_symbol("input_cost_per_token")) {
6979
7358
  Some(v) => f64::try_convert(v).map_err(|e| {
6980
7359
  magnus::Error::new(
@@ -7179,6 +7558,18 @@ impl ModelInfo {
7179
7558
  })
7180
7559
  }
7181
7560
 
7561
+ fn matched_key(&self) -> String {
7562
+ self.matched_key.clone()
7563
+ }
7564
+
7565
+ fn exact(&self) -> bool {
7566
+ self.exact
7567
+ }
7568
+
7569
+ fn price_known(&self) -> bool {
7570
+ self.price_known
7571
+ }
7572
+
7182
7573
  fn input_cost_per_token(&self) -> f64 {
7183
7574
  self.input_cost_per_token
7184
7575
  }
@@ -8862,6 +9253,7 @@ impl PageDimensions {
8862
9253
  #[magnus::wrap(class = "LiterLlm::PromptTokensDetails")]
8863
9254
  pub struct PromptTokensDetails {
8864
9255
  cached_tokens: u64,
9256
+ cache_creation_tokens: u64,
8865
9257
  audio_tokens: u64,
8866
9258
  }
8867
9259
 
@@ -8923,6 +9315,15 @@ impl PromptTokensDetails {
8923
9315
  })?,
8924
9316
  None => Default::default(),
8925
9317
  },
9318
+ cache_creation_tokens: match kwargs.get(ruby.to_symbol("cache_creation_tokens")) {
9319
+ Some(v) => u64::try_convert(v).map_err(|e| {
9320
+ magnus::Error::new(
9321
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
9322
+ format!("invalid value for `cache_creation_tokens`: {}", e),
9323
+ )
9324
+ })?,
9325
+ None => Default::default(),
9326
+ },
8926
9327
  audio_tokens: match kwargs.get(ruby.to_symbol("audio_tokens")) {
8927
9328
  Some(v) => u64::try_convert(v).map_err(|e| {
8928
9329
  magnus::Error::new(
@@ -8939,6 +9340,10 @@ impl PromptTokensDetails {
8939
9340
  self.cached_tokens
8940
9341
  }
8941
9342
 
9343
+ fn cache_creation_tokens(&self) -> u64 {
9344
+ self.cache_creation_tokens
9345
+ }
9346
+
8942
9347
  fn audio_tokens(&self) -> u64 {
8943
9348
  self.audio_tokens
8944
9349
  }
@@ -11703,6 +12108,7 @@ pub struct Usage {
11703
12108
  completion_tokens: u64,
11704
12109
  total_tokens: u64,
11705
12110
  prompt_tokens_details: Option<PromptTokensDetails>,
12111
+ completion_tokens_details: Option<CompletionTokensDetails>,
11706
12112
  }
11707
12113
 
11708
12114
  unsafe impl IntoValueFromNative for Usage {}
@@ -11793,6 +12199,18 @@ impl Usage {
11793
12199
  })?),
11794
12200
  None => None,
11795
12201
  },
12202
+ completion_tokens_details: match kwargs
12203
+ .get(ruby.to_symbol("completion_tokens_details"))
12204
+ .filter(|v| !v.is_nil())
12205
+ {
12206
+ Some(v) => Some(CompletionTokensDetails::try_convert(v).map_err(|e| {
12207
+ magnus::Error::new(
12208
+ unsafe { magnus::Ruby::get_unchecked() }.exception_type_error(),
12209
+ format!("invalid value for `completion_tokens_details`: {}", e),
12210
+ )
12211
+ })?),
12212
+ None => None,
12213
+ },
11796
12214
  })
11797
12215
  }
11798
12216
 
@@ -11811,6 +12229,10 @@ impl Usage {
11811
12229
  fn prompt_tokens_details(&self) -> Option<PromptTokensDetails> {
11812
12230
  self.prompt_tokens_details.clone()
11813
12231
  }
12232
+
12233
+ fn completion_tokens_details(&self) -> Option<CompletionTokensDetails> {
12234
+ self.completion_tokens_details.clone()
12235
+ }
11814
12236
  }
11815
12237
 
11816
12238
  #[derive(Clone, Debug, serde::Serialize)]
@@ -13773,6 +14195,10 @@ fn capabilities(provider_name: String) -> ProviderCapabilities {
13773
14195
  liter_llm::provider::capabilities(&provider_name).into()
13774
14196
  }
13775
14197
 
14198
+ fn catalog_info() -> Option<CatalogInfo> {
14199
+ liter_llm::catalog_info().map(Into::into)
14200
+ }
14201
+
13776
14202
  fn check_bound(context: String, current_len: usize, incoming: usize, limit: usize) -> Result<(), Error> {
13777
14203
  let result = liter_llm::util::bounds::check_bound(&context, current_len, incoming, limit).map_err(|e| {
13778
14204
  magnus::Error::new(
@@ -13804,6 +14230,22 @@ fn completion_cost_with_cache(
13804
14230
  liter_llm::completion_cost_with_cache(&model, prompt_tokens, cached_tokens, completion_tokens)
13805
14231
  }
13806
14232
 
14233
+ fn completion_cost_with_cache_details(
14234
+ model: String,
14235
+ prompt_tokens: u64,
14236
+ cached_tokens: u64,
14237
+ cache_creation_tokens: u64,
14238
+ completion_tokens: u64,
14239
+ ) -> Option<f64> {
14240
+ liter_llm::completion_cost_with_cache_details(
14241
+ &model,
14242
+ prompt_tokens,
14243
+ cached_tokens,
14244
+ cache_creation_tokens,
14245
+ completion_tokens,
14246
+ )
14247
+ }
14248
+
13807
14249
  fn complex_provider_names() -> Result<Vec<String>, Error> {
13808
14250
  let result = liter_llm::provider::complex_provider_names().map_err(|e| {
13809
14251
  magnus::Error::new(
@@ -13907,6 +14349,31 @@ fn create_client_from_json(json: String) -> Result<DefaultClient, Error> {
13907
14349
  })
13908
14350
  }
13909
14351
 
14352
+ #[cfg(feature = "native-http")]
14353
+ fn create_client_with_options(args: &[magnus::Value]) -> Result<DefaultClient, Error> {
14354
+ let args = magnus::scan_args::scan_args::<(), (Option<magnus::Value>,), (), (), (), ()>(args)?;
14355
+ let (options,) = args.optional;
14356
+
14357
+ let options: liter_llm::ClientOptions = match options {
14358
+ Some(_v) if !_v.is_nil() => {
14359
+ let binding_val: ClientOptions = ClientOptions::try_convert(_v).map_err(|e| {
14360
+ magnus::Error::new(unsafe { Ruby::get_unchecked() }.exception_type_error(), e.to_string())
14361
+ })?;
14362
+ binding_val.into()
14363
+ }
14364
+ _ => Default::default(),
14365
+ };
14366
+ let result = liter_llm::create_client_with_options(options.into()).map_err(|e| {
14367
+ magnus::Error::new(
14368
+ unsafe { Ruby::get_unchecked() }.exception_runtime_error(),
14369
+ e.to_string(),
14370
+ )
14371
+ })?;
14372
+ Ok(DefaultClient {
14373
+ inner: Arc::new(result),
14374
+ })
14375
+ }
14376
+
13910
14377
  fn decode_data_url(url: String) -> Option<DecodedDataUrl> {
13911
14378
  liter_llm::image::decode_data_url(&url).map(Into::into)
13912
14379
  }
@@ -13936,6 +14403,10 @@ fn ensure_crypto_provider() -> () {
13936
14403
  liter_llm::ensure_crypto_provider()
13937
14404
  }
13938
14405
 
14406
+ fn exact_model_info(model: String) -> Option<ModelInfo> {
14407
+ liter_llm::exact_model_info(&model).map(Into::into)
14408
+ }
14409
+
13939
14410
  fn install_catalog_overlay_from_str(catalog_json: String) -> Result<(), Error> {
13940
14411
  let result = liter_llm::install_catalog_overlay_from_str(&catalog_json).map_err(|e| {
13941
14412
  magnus::Error::new(
@@ -14308,6 +14779,34 @@ impl From<liter_llm::CacheConfig> for CacheConfig {
14308
14779
  }
14309
14780
  }
14310
14781
 
14782
+ #[allow(clippy::needless_update)]
14783
+ impl From<CatalogInfo> for liter_llm::CatalogInfo {
14784
+ fn from(val: CatalogInfo) -> Self {
14785
+ Self {
14786
+ source: val.source,
14787
+ source_sha256: val.source_sha256,
14788
+ fetched: val.fetched,
14789
+ library_version: val.library_version,
14790
+ schema_version: val.schema_version,
14791
+ origin: val.origin,
14792
+ ..Default::default()
14793
+ }
14794
+ }
14795
+ }
14796
+
14797
+ impl From<liter_llm::CatalogInfo> for CatalogInfo {
14798
+ fn from(val: liter_llm::CatalogInfo) -> Self {
14799
+ Self {
14800
+ source: val.source.to_string(),
14801
+ source_sha256: val.source_sha256.to_string(),
14802
+ fetched: val.fetched.to_string(),
14803
+ library_version: val.library_version.to_string(),
14804
+ schema_version: val.schema_version,
14805
+ origin: val.origin.to_string(),
14806
+ }
14807
+ }
14808
+ }
14809
+
14311
14810
  #[allow(clippy::needless_update)]
14312
14811
  impl From<CatalogRefreshConfig> for liter_llm::CatalogRefreshConfig {
14313
14812
  fn from(val: CatalogRefreshConfig) -> Self {
@@ -14532,6 +15031,55 @@ impl From<liter_llm::types::Choice> for Choice {
14532
15031
  }
14533
15032
  }
14534
15033
 
15034
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
15035
+ #[allow(clippy::needless_update)]
15036
+ impl From<ClientOptions> for liter_llm::ClientOptions {
15037
+ fn from(val: ClientOptions) -> Self {
15038
+ Self {
15039
+ api_key: val.api_key,
15040
+ base_url: val.base_url,
15041
+ timeout_secs: val.timeout_secs,
15042
+ max_retries: val.max_retries,
15043
+ max_response_bytes: val.max_response_bytes,
15044
+ model_hint: val.model_hint,
15045
+ ..Default::default()
15046
+ }
15047
+ }
15048
+ }
15049
+
15050
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
15051
+ #[allow(clippy::redundant_closure)]
15052
+ impl From<liter_llm::ClientOptions> for ClientOptions {
15053
+ fn from(val: liter_llm::ClientOptions) -> Self {
15054
+ Self {
15055
+ api_key: val.api_key.to_string(),
15056
+ base_url: val.base_url.map(|v| v.to_string()),
15057
+ timeout_secs: val.timeout_secs,
15058
+ max_retries: val.max_retries,
15059
+ max_response_bytes: val.max_response_bytes,
15060
+ model_hint: val.model_hint.map(|v| v.to_string()),
15061
+ }
15062
+ }
15063
+ }
15064
+
15065
+ #[allow(clippy::needless_update)]
15066
+ impl From<CompletionTokensDetails> for liter_llm::types::CompletionTokensDetails {
15067
+ fn from(val: CompletionTokensDetails) -> Self {
15068
+ Self {
15069
+ reasoning_tokens: val.reasoning_tokens,
15070
+ ..Default::default()
15071
+ }
15072
+ }
15073
+ }
15074
+
15075
+ impl From<liter_llm::types::CompletionTokensDetails> for CompletionTokensDetails {
15076
+ fn from(val: liter_llm::types::CompletionTokensDetails) -> Self {
15077
+ Self {
15078
+ reasoning_tokens: val.reasoning_tokens,
15079
+ }
15080
+ }
15081
+ }
15082
+
14535
15083
  #[allow(clippy::needless_update)]
14536
15084
  #[allow(clippy::redundant_closure)]
14537
15085
  impl From<CreateBatchRequest> for liter_llm::types::CreateBatchRequest {
@@ -15292,6 +15840,9 @@ impl From<liter_llm::client::LlmRateLimitConfig> for LlmRateLimitConfig {
15292
15840
  impl From<ModelInfo> for liter_llm::ModelInfo {
15293
15841
  fn from(val: ModelInfo) -> Self {
15294
15842
  Self {
15843
+ matched_key: val.matched_key,
15844
+ exact: val.exact,
15845
+ price_known: val.price_known,
15295
15846
  input_cost_per_token: val.input_cost_per_token,
15296
15847
  output_cost_per_token: val.output_cost_per_token,
15297
15848
  cache_read_input_token_cost: val.cache_read_input_token_cost,
@@ -15320,6 +15871,9 @@ impl From<ModelInfo> for liter_llm::ModelInfo {
15320
15871
  impl From<liter_llm::ModelInfo> for ModelInfo {
15321
15872
  fn from(val: liter_llm::ModelInfo) -> Self {
15322
15873
  Self {
15874
+ matched_key: val.matched_key.to_string(),
15875
+ exact: val.exact,
15876
+ price_known: val.price_known,
15323
15877
  input_cost_per_token: val.input_cost_per_token,
15324
15878
  output_cost_per_token: val.output_cost_per_token,
15325
15879
  cache_read_input_token_cost: val.cache_read_input_token_cost,
@@ -15677,6 +16231,7 @@ impl From<PromptTokensDetails> for liter_llm::types::PromptTokensDetails {
15677
16231
  fn from(val: PromptTokensDetails) -> Self {
15678
16232
  Self {
15679
16233
  cached_tokens: val.cached_tokens,
16234
+ cache_creation_tokens: val.cache_creation_tokens,
15680
16235
  audio_tokens: val.audio_tokens,
15681
16236
  ..Default::default()
15682
16237
  }
@@ -15687,6 +16242,7 @@ impl From<liter_llm::types::PromptTokensDetails> for PromptTokensDetails {
15687
16242
  fn from(val: liter_llm::types::PromptTokensDetails) -> Self {
15688
16243
  Self {
15689
16244
  cached_tokens: val.cached_tokens,
16245
+ cache_creation_tokens: val.cache_creation_tokens,
15690
16246
  audio_tokens: val.audio_tokens,
15691
16247
  }
15692
16248
  }
@@ -16319,6 +16875,7 @@ impl From<Usage> for liter_llm::types::Usage {
16319
16875
  completion_tokens: val.completion_tokens,
16320
16876
  total_tokens: val.total_tokens,
16321
16877
  prompt_tokens_details: val.prompt_tokens_details.map(Into::into),
16878
+ completion_tokens_details: val.completion_tokens_details.map(Into::into),
16322
16879
  ..Default::default()
16323
16880
  }
16324
16881
  }
@@ -16332,6 +16889,7 @@ impl From<liter_llm::types::Usage> for Usage {
16332
16889
  completion_tokens: val.completion_tokens,
16333
16890
  total_tokens: val.total_tokens,
16334
16891
  prompt_tokens_details: val.prompt_tokens_details.map(Into::into),
16892
+ completion_tokens_details: val.completion_tokens_details.map(Into::into),
16335
16893
  }
16336
16894
  }
16337
16895
  }
@@ -17313,6 +17871,22 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
17313
17871
  #[cfg(feature = "tower")]
17314
17872
  class.define_method("backend", method!(CacheConfig::backend, 0))?;
17315
17873
 
17874
+ let class = module.define_class("CatalogInfo", ruby.class_object())?;
17875
+
17876
+ class.define_singleton_method("new", function!(CatalogInfo::new, -1))?;
17877
+
17878
+ class.define_method("source", method!(CatalogInfo::source, 0))?;
17879
+
17880
+ class.define_method("source_sha256", method!(CatalogInfo::source_sha256, 0))?;
17881
+
17882
+ class.define_method("fetched", method!(CatalogInfo::fetched, 0))?;
17883
+
17884
+ class.define_method("library_version", method!(CatalogInfo::library_version, 0))?;
17885
+
17886
+ class.define_method("schema_version", method!(CatalogInfo::schema_version, 0))?;
17887
+
17888
+ class.define_method("origin", method!(CatalogInfo::origin, 0))?;
17889
+
17316
17890
  let class = module.define_class("CatalogRefreshConfig", ruby.class_object())?;
17317
17891
 
17318
17892
  class.define_singleton_method("new", function!(CatalogRefreshConfig::new, -1))?;
@@ -17467,6 +18041,38 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
17467
18041
 
17468
18042
  class.define_method("logprobs", method!(Choice::logprobs, 0))?;
17469
18043
 
18044
+ let class = module.define_class("ClientOptions", ruby.class_object())?;
18045
+
18046
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18047
+ class.define_singleton_method("new", function!(ClientOptions::new, -1))?;
18048
+
18049
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18050
+ class.define_method("api_key", method!(ClientOptions::api_key, 0))?;
18051
+
18052
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18053
+ class.define_method("base_url", method!(ClientOptions::base_url, 0))?;
18054
+
18055
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18056
+ class.define_method("timeout_secs", method!(ClientOptions::timeout_secs, 0))?;
18057
+
18058
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18059
+ class.define_method("max_retries", method!(ClientOptions::max_retries, 0))?;
18060
+
18061
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18062
+ class.define_method("max_response_bytes", method!(ClientOptions::max_response_bytes, 0))?;
18063
+
18064
+ #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18065
+ class.define_method("model_hint", method!(ClientOptions::model_hint, 0))?;
18066
+
18067
+ let class = module.define_class("CompletionTokensDetails", ruby.class_object())?;
18068
+
18069
+ class.define_singleton_method("new", function!(CompletionTokensDetails::new, -1))?;
18070
+
18071
+ class.define_method(
18072
+ "reasoning_tokens",
18073
+ method!(CompletionTokensDetails::reasoning_tokens, 0),
18074
+ )?;
18075
+
17470
18076
  let class = module.define_class("CreateBatchRequest", ruby.class_object())?;
17471
18077
 
17472
18078
  class.define_singleton_method("new", function!(CreateBatchRequest::new, -1))?;
@@ -17963,6 +18569,12 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
17963
18569
 
17964
18570
  class.define_singleton_method("new", function!(ModelInfo::new, -1))?;
17965
18571
 
18572
+ class.define_method("matched_key", method!(ModelInfo::matched_key, 0))?;
18573
+
18574
+ class.define_method("exact", method!(ModelInfo::exact, 0))?;
18575
+
18576
+ class.define_method("price_known", method!(ModelInfo::price_known, 0))?;
18577
+
17966
18578
  class.define_method("input_cost_per_token", method!(ModelInfo::input_cost_per_token, 0))?;
17967
18579
 
17968
18580
  class.define_method("output_cost_per_token", method!(ModelInfo::output_cost_per_token, 0))?;
@@ -18237,6 +18849,11 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18237
18849
 
18238
18850
  class.define_method("cached_tokens", method!(PromptTokensDetails::cached_tokens, 0))?;
18239
18851
 
18852
+ class.define_method(
18853
+ "cache_creation_tokens",
18854
+ method!(PromptTokensDetails::cache_creation_tokens, 0),
18855
+ )?;
18856
+
18240
18857
  class.define_method("audio_tokens", method!(PromptTokensDetails::audio_tokens, 0))?;
18241
18858
 
18242
18859
  let class = module.define_class("ProviderCapabilities", ruby.class_object())?;
@@ -18543,6 +19160,11 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18543
19160
 
18544
19161
  class.define_method("prompt_tokens_details", method!(Usage::prompt_tokens_details, 0))?;
18545
19162
 
19163
+ class.define_method(
19164
+ "completion_tokens_details",
19165
+ method!(Usage::completion_tokens_details, 0),
19166
+ )?;
19167
+
18546
19168
  let class = module.define_class("UserMessage", ruby.class_object())?;
18547
19169
 
18548
19170
  class.define_singleton_method("new", function!(UserMessage::new, -1))?;
@@ -18590,6 +19212,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18590
19212
 
18591
19213
  module.define_module_function("capabilities", function!(capabilities, 1))?;
18592
19214
 
19215
+ module.define_module_function("catalog_info", function!(catalog_info, 0))?;
19216
+
18593
19217
  module.define_module_function("check_bound", function!(check_bound, 4))?;
18594
19218
 
18595
19219
  module.define_module_function("clear", function!(clear, 0))?;
@@ -18600,6 +19224,11 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18600
19224
 
18601
19225
  module.define_module_function("completion_cost_with_cache", function!(completion_cost_with_cache, 4))?;
18602
19226
 
19227
+ module.define_module_function(
19228
+ "completion_cost_with_cache_details",
19229
+ function!(completion_cost_with_cache_details, 5),
19230
+ )?;
19231
+
18603
19232
  module.define_module_function("complex_provider_names", function!(complex_provider_names, 0))?;
18604
19233
 
18605
19234
  #[cfg(feature = "tokenizer")]
@@ -18614,6 +19243,9 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18614
19243
  #[cfg(any(feature = "native-http", feature = "wasm-http"))]
18615
19244
  module.define_module_function("create_client_from_json", function!(create_client_from_json, 1))?;
18616
19245
 
19246
+ #[cfg(feature = "native-http")]
19247
+ module.define_module_function("create_client_with_options", function!(create_client_with_options, -1))?;
19248
+
18617
19249
  module.define_module_function("decode_data_url", function!(decode_data_url, 1))?;
18618
19250
 
18619
19251
  module.define_module_function("encode_data_url", function!(encode_data_url, -1))?;
@@ -18624,6 +19256,8 @@ fn ruby_init(ruby: &Ruby) -> Result<(), Error> {
18624
19256
  ))]
18625
19257
  module.define_module_function("ensure_crypto_provider", function!(ensure_crypto_provider, 0))?;
18626
19258
 
19259
+ module.define_module_function("exact_model_info", function!(exact_model_info, 1))?;
19260
+
18627
19261
  module.define_module_function(
18628
19262
  "install_catalog_overlay_from_str",
18629
19263
  function!(install_catalog_overlay_from_str, 1),