@combycode/llm-sdk 3.0.0 → 3.1.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.
@@ -599,6 +599,7 @@ var TelemetryAdapter = class {
599
599
  break;
600
600
  case "onModelError":
601
601
  this.metrics.errors++;
602
+ this.metrics.inFlight = Math.max(0, this.metrics.inFlight - 1);
602
603
  break;
603
604
  case "onCostEntry":
604
605
  this.metrics.costUsd += event.ctx.entry?.cost?.total ?? 0;
@@ -3401,7 +3402,8 @@ var anthropic_default = {
3401
3402
  "anthropic/claude-opus-4.1": {
3402
3403
  providerModelName: "claude-opus-4-1-20250805",
3403
3404
  aliases: [
3404
- "claude-opus-4-1-20250805"
3405
+ "claude-opus-4-1-20250805",
3406
+ "claude-opus-4-1"
3405
3407
  ],
3406
3408
  pricing: {
3407
3409
  inputPerMTok: 15,
@@ -3465,7 +3467,8 @@ var anthropic_default = {
3465
3467
  "anthropic/claude-opus-4.5": {
3466
3468
  providerModelName: "claude-opus-4-5-20251101",
3467
3469
  aliases: [
3468
- "claude-opus-4-5-20251101"
3470
+ "claude-opus-4-5-20251101",
3471
+ "claude-opus-4-5"
3469
3472
  ],
3470
3473
  pricing: {
3471
3474
  inputPerMTok: 5,
@@ -3804,7 +3807,8 @@ var anthropic_default = {
3804
3807
  "anthropic/claude-sonnet-4.5": {
3805
3808
  providerModelName: "claude-sonnet-4-5-20250929",
3806
3809
  aliases: [
3807
- "claude-sonnet-4-5-20250929"
3810
+ "claude-sonnet-4-5-20250929",
3811
+ "claude-sonnet-4-5"
3808
3812
  ],
3809
3813
  pricing: {
3810
3814
  inputPerMTok: 3,
@@ -3938,7 +3942,8 @@ var anthropic_default = {
3938
3942
  "anthropic/claude-haiku-4.5": {
3939
3943
  providerModelName: "claude-haiku-4-5-20251001",
3940
3944
  aliases: [
3941
- "claude-haiku-4-5-20251001"
3945
+ "claude-haiku-4-5-20251001",
3946
+ "claude-haiku-4-5"
3942
3947
  ],
3943
3948
  pricing: {
3944
3949
  inputPerMTok: 1,
@@ -4297,7 +4302,7 @@ var google_default = {
4297
4302
  structuredOutput: true,
4298
4303
  vision: true,
4299
4304
  audio: true,
4300
- video: false,
4305
+ video: true,
4301
4306
  imageGeneration: false,
4302
4307
  audioGeneration: false,
4303
4308
  videoGeneration: false
@@ -4313,7 +4318,9 @@ var google_default = {
4313
4318
  inputModalities: [
4314
4319
  "text",
4315
4320
  "image",
4316
- "audio"
4321
+ "audio",
4322
+ "pdf",
4323
+ "video"
4317
4324
  ],
4318
4325
  outputModalities: [
4319
4326
  "text"
@@ -4369,7 +4376,7 @@ var google_default = {
4369
4376
  structuredOutput: true,
4370
4377
  vision: true,
4371
4378
  audio: true,
4372
- video: false,
4379
+ video: true,
4373
4380
  imageGeneration: false,
4374
4381
  audioGeneration: false,
4375
4382
  videoGeneration: false
@@ -4391,7 +4398,9 @@ var google_default = {
4391
4398
  inputModalities: [
4392
4399
  "text",
4393
4400
  "image",
4394
- "audio"
4401
+ "audio",
4402
+ "pdf",
4403
+ "video"
4395
4404
  ],
4396
4405
  outputModalities: [
4397
4406
  "text"
@@ -4429,7 +4438,7 @@ var google_default = {
4429
4438
  structuredOutput: true,
4430
4439
  vision: true,
4431
4440
  audio: true,
4432
- video: false,
4441
+ video: true,
4433
4442
  imageGeneration: false,
4434
4443
  audioGeneration: false,
4435
4444
  videoGeneration: false
@@ -4445,7 +4454,9 @@ var google_default = {
4445
4454
  inputModalities: [
4446
4455
  "text",
4447
4456
  "image",
4448
- "audio"
4457
+ "audio",
4458
+ "pdf",
4459
+ "video"
4449
4460
  ],
4450
4461
  outputModalities: [
4451
4462
  "text"
@@ -4504,7 +4515,7 @@ var google_default = {
4504
4515
  structuredOutput: true,
4505
4516
  vision: true,
4506
4517
  audio: true,
4507
- video: false,
4518
+ video: true,
4508
4519
  imageGeneration: false,
4509
4520
  audioGeneration: false,
4510
4521
  videoGeneration: false
@@ -4520,7 +4531,9 @@ var google_default = {
4520
4531
  inputModalities: [
4521
4532
  "text",
4522
4533
  "image",
4523
- "audio"
4534
+ "audio",
4535
+ "pdf",
4536
+ "video"
4524
4537
  ],
4525
4538
  outputModalities: [
4526
4539
  "text"
@@ -4579,7 +4592,7 @@ var google_default = {
4579
4592
  structuredOutput: true,
4580
4593
  vision: true,
4581
4594
  audio: true,
4582
- video: false,
4595
+ video: true,
4583
4596
  imageGeneration: false,
4584
4597
  audioGeneration: false,
4585
4598
  videoGeneration: false
@@ -4602,7 +4615,9 @@ var google_default = {
4602
4615
  inputModalities: [
4603
4616
  "text",
4604
4617
  "image",
4605
- "audio"
4618
+ "audio",
4619
+ "pdf",
4620
+ "video"
4606
4621
  ],
4607
4622
  outputModalities: [
4608
4623
  "text"
@@ -4657,7 +4672,7 @@ var google_default = {
4657
4672
  structuredOutput: true,
4658
4673
  vision: true,
4659
4674
  audio: true,
4660
- video: false,
4675
+ video: true,
4661
4676
  imageGeneration: false,
4662
4677
  audioGeneration: false,
4663
4678
  videoGeneration: false
@@ -4673,7 +4688,9 @@ var google_default = {
4673
4688
  inputModalities: [
4674
4689
  "text",
4675
4690
  "image",
4676
- "audio"
4691
+ "audio",
4692
+ "pdf",
4693
+ "video"
4677
4694
  ],
4678
4695
  outputModalities: [
4679
4696
  "text"
@@ -4732,7 +4749,7 @@ var google_default = {
4732
4749
  structuredOutput: true,
4733
4750
  vision: true,
4734
4751
  audio: true,
4735
- video: false,
4752
+ video: true,
4736
4753
  imageGeneration: false,
4737
4754
  audioGeneration: false,
4738
4755
  videoGeneration: false
@@ -4748,7 +4765,9 @@ var google_default = {
4748
4765
  inputModalities: [
4749
4766
  "text",
4750
4767
  "image",
4751
- "audio"
4768
+ "audio",
4769
+ "pdf",
4770
+ "video"
4752
4771
  ],
4753
4772
  outputModalities: [
4754
4773
  "text"
@@ -4808,7 +4827,7 @@ var google_default = {
4808
4827
  structuredOutput: true,
4809
4828
  vision: true,
4810
4829
  audio: true,
4811
- video: false,
4830
+ video: true,
4812
4831
  imageGeneration: false,
4813
4832
  audioGeneration: false,
4814
4833
  videoGeneration: false
@@ -4824,7 +4843,9 @@ var google_default = {
4824
4843
  inputModalities: [
4825
4844
  "text",
4826
4845
  "image",
4827
- "audio"
4846
+ "audio",
4847
+ "pdf",
4848
+ "video"
4828
4849
  ],
4829
4850
  outputModalities: [
4830
4851
  "text"
@@ -5807,7 +5828,8 @@ var google_default = {
5807
5828
  type: "chat",
5808
5829
  inputModalities: [
5809
5830
  "text",
5810
- "image"
5831
+ "image",
5832
+ "pdf"
5811
5833
  ],
5812
5834
  outputModalities: [
5813
5835
  "text"
@@ -5860,7 +5882,8 @@ var google_default = {
5860
5882
  type: "chat",
5861
5883
  inputModalities: [
5862
5884
  "text",
5863
- "image"
5885
+ "image",
5886
+ "pdf"
5864
5887
  ],
5865
5888
  outputModalities: [
5866
5889
  "text"
@@ -7029,7 +7052,7 @@ var google_default = {
7029
7052
  structuredOutput: true,
7030
7053
  vision: true,
7031
7054
  audio: true,
7032
- video: false,
7055
+ video: true,
7033
7056
  imageGeneration: false,
7034
7057
  audioGeneration: false,
7035
7058
  videoGeneration: false
@@ -7045,7 +7068,9 @@ var google_default = {
7045
7068
  inputModalities: [
7046
7069
  "text",
7047
7070
  "image",
7048
- "audio"
7071
+ "audio",
7072
+ "pdf",
7073
+ "video"
7049
7074
  ],
7050
7075
  outputModalities: [
7051
7076
  "text"
@@ -7101,7 +7126,7 @@ var google_default = {
7101
7126
  structuredOutput: true,
7102
7127
  vision: true,
7103
7128
  audio: true,
7104
- video: false,
7129
+ video: true,
7105
7130
  imageGeneration: false,
7106
7131
  audioGeneration: false,
7107
7132
  videoGeneration: false
@@ -7117,7 +7142,9 @@ var google_default = {
7117
7142
  inputModalities: [
7118
7143
  "text",
7119
7144
  "image",
7120
- "audio"
7145
+ "audio",
7146
+ "pdf",
7147
+ "video"
7121
7148
  ],
7122
7149
  outputModalities: [
7123
7150
  "text"
@@ -7172,7 +7199,7 @@ var google_default = {
7172
7199
  structuredOutput: true,
7173
7200
  vision: true,
7174
7201
  audio: true,
7175
- video: false,
7202
+ video: true,
7176
7203
  imageGeneration: false,
7177
7204
  audioGeneration: false,
7178
7205
  videoGeneration: false
@@ -7188,7 +7215,9 @@ var google_default = {
7188
7215
  inputModalities: [
7189
7216
  "text",
7190
7217
  "image",
7191
- "audio"
7218
+ "audio",
7219
+ "pdf",
7220
+ "video"
7192
7221
  ],
7193
7222
  outputModalities: [
7194
7223
  "text"
@@ -7478,7 +7507,8 @@ var openai_default = {
7478
7507
  type: "chat",
7479
7508
  inputModalities: [
7480
7509
  "text",
7481
- "image"
7510
+ "image",
7511
+ "pdf"
7482
7512
  ],
7483
7513
  outputModalities: [
7484
7514
  "text"
@@ -7538,7 +7568,8 @@ var openai_default = {
7538
7568
  type: "chat",
7539
7569
  inputModalities: [
7540
7570
  "text",
7541
- "image"
7571
+ "image",
7572
+ "pdf"
7542
7573
  ],
7543
7574
  outputModalities: [
7544
7575
  "text"
@@ -7594,7 +7625,8 @@ var openai_default = {
7594
7625
  type: "chat",
7595
7626
  inputModalities: [
7596
7627
  "text",
7597
- "image"
7628
+ "image",
7629
+ "pdf"
7598
7630
  ],
7599
7631
  outputModalities: [
7600
7632
  "text"
@@ -7705,7 +7737,8 @@ var openai_default = {
7705
7737
  type: "chat",
7706
7738
  inputModalities: [
7707
7739
  "text",
7708
- "image"
7740
+ "image",
7741
+ "pdf"
7709
7742
  ],
7710
7743
  outputModalities: [
7711
7744
  "text"
@@ -7761,7 +7794,8 @@ var openai_default = {
7761
7794
  type: "chat",
7762
7795
  inputModalities: [
7763
7796
  "text",
7764
- "image"
7797
+ "image",
7798
+ "pdf"
7765
7799
  ],
7766
7800
  outputModalities: [
7767
7801
  "text"
@@ -7841,7 +7875,8 @@ var openai_default = {
7841
7875
  type: "chat",
7842
7876
  inputModalities: [
7843
7877
  "text",
7844
- "image"
7878
+ "image",
7879
+ "pdf"
7845
7880
  ],
7846
7881
  outputModalities: [
7847
7882
  "text"
@@ -7914,7 +7949,8 @@ var openai_default = {
7914
7949
  type: "chat",
7915
7950
  inputModalities: [
7916
7951
  "text",
7917
- "image"
7952
+ "image",
7953
+ "pdf"
7918
7954
  ],
7919
7955
  outputModalities: [
7920
7956
  "text"
@@ -7969,7 +8005,8 @@ var openai_default = {
7969
8005
  type: "chat",
7970
8006
  inputModalities: [
7971
8007
  "text",
7972
- "image"
8008
+ "image",
8009
+ "pdf"
7973
8010
  ],
7974
8011
  outputModalities: [
7975
8012
  "text"
@@ -8028,7 +8065,8 @@ var openai_default = {
8028
8065
  type: "chat",
8029
8066
  inputModalities: [
8030
8067
  "text",
8031
- "image"
8068
+ "image",
8069
+ "pdf"
8032
8070
  ],
8033
8071
  outputModalities: [
8034
8072
  "text"
@@ -8087,7 +8125,8 @@ var openai_default = {
8087
8125
  type: "chat",
8088
8126
  inputModalities: [
8089
8127
  "text",
8090
- "image"
8128
+ "image",
8129
+ "pdf"
8091
8130
  ],
8092
8131
  outputModalities: [
8093
8132
  "text"
@@ -8146,7 +8185,8 @@ var openai_default = {
8146
8185
  type: "chat",
8147
8186
  inputModalities: [
8148
8187
  "text",
8149
- "image"
8188
+ "image",
8189
+ "pdf"
8150
8190
  ],
8151
8191
  outputModalities: [
8152
8192
  "text"
@@ -8563,7 +8603,8 @@ var openai_default = {
8563
8603
  type: "chat",
8564
8604
  inputModalities: [
8565
8605
  "text",
8566
- "image"
8606
+ "image",
8607
+ "pdf"
8567
8608
  ],
8568
8609
  outputModalities: [
8569
8610
  "text"
@@ -8626,7 +8667,8 @@ var openai_default = {
8626
8667
  type: "chat",
8627
8668
  inputModalities: [
8628
8669
  "text",
8629
- "image"
8670
+ "image",
8671
+ "pdf"
8630
8672
  ],
8631
8673
  outputModalities: [
8632
8674
  "text"
@@ -8706,7 +8748,8 @@ var openai_default = {
8706
8748
  type: "chat",
8707
8749
  inputModalities: [
8708
8750
  "text",
8709
- "image"
8751
+ "image",
8752
+ "pdf"
8710
8753
  ],
8711
8754
  outputModalities: [
8712
8755
  "text"
@@ -8769,7 +8812,8 @@ var openai_default = {
8769
8812
  type: "chat",
8770
8813
  inputModalities: [
8771
8814
  "text",
8772
- "image"
8815
+ "image",
8816
+ "pdf"
8773
8817
  ],
8774
8818
  outputModalities: [
8775
8819
  "text"
@@ -8836,7 +8880,8 @@ var openai_default = {
8836
8880
  type: "chat",
8837
8881
  inputModalities: [
8838
8882
  "text",
8839
- "image"
8883
+ "image",
8884
+ "pdf"
8840
8885
  ],
8841
8886
  outputModalities: [
8842
8887
  "text"
@@ -8911,7 +8956,8 @@ var openai_default = {
8911
8956
  type: "chat",
8912
8957
  inputModalities: [
8913
8958
  "text",
8914
- "image"
8959
+ "image",
8960
+ "pdf"
8915
8961
  ],
8916
8962
  outputModalities: [
8917
8963
  "text"
@@ -8965,7 +9011,8 @@ var openai_default = {
8965
9011
  type: "chat",
8966
9012
  inputModalities: [
8967
9013
  "text",
8968
- "image"
9014
+ "image",
9015
+ "pdf"
8969
9016
  ],
8970
9017
  outputModalities: [
8971
9018
  "text"
@@ -9019,7 +9066,8 @@ var openai_default = {
9019
9066
  type: "chat",
9020
9067
  inputModalities: [
9021
9068
  "text",
9022
- "image"
9069
+ "image",
9070
+ "pdf"
9023
9071
  ],
9024
9072
  outputModalities: [
9025
9073
  "text"
@@ -9089,7 +9137,8 @@ var openai_default = {
9089
9137
  type: "chat",
9090
9138
  inputModalities: [
9091
9139
  "text",
9092
- "image"
9140
+ "image",
9141
+ "pdf"
9093
9142
  ],
9094
9143
  outputModalities: [
9095
9144
  "text"
@@ -9153,7 +9202,8 @@ var openai_default = {
9153
9202
  type: "chat",
9154
9203
  inputModalities: [
9155
9204
  "text",
9156
- "image"
9205
+ "image",
9206
+ "pdf"
9157
9207
  ],
9158
9208
  outputModalities: [
9159
9209
  "text"
@@ -9211,7 +9261,8 @@ var openai_default = {
9211
9261
  type: "chat",
9212
9262
  inputModalities: [
9213
9263
  "text",
9214
- "image"
9264
+ "image",
9265
+ "pdf"
9215
9266
  ],
9216
9267
  outputModalities: [
9217
9268
  "text"
@@ -9268,7 +9319,8 @@ var openai_default = {
9268
9319
  type: "chat",
9269
9320
  inputModalities: [
9270
9321
  "text",
9271
- "image"
9322
+ "image",
9323
+ "pdf"
9272
9324
  ],
9273
9325
  outputModalities: [
9274
9326
  "text"
@@ -10348,7 +10400,8 @@ var openai_default = {
10348
10400
  type: "chat",
10349
10401
  inputModalities: [
10350
10402
  "text",
10351
- "image"
10403
+ "image",
10404
+ "pdf"
10352
10405
  ],
10353
10406
  outputModalities: [
10354
10407
  "text"
@@ -10405,7 +10458,8 @@ var openai_default = {
10405
10458
  type: "chat",
10406
10459
  inputModalities: [
10407
10460
  "text",
10408
- "image"
10461
+ "image",
10462
+ "pdf"
10409
10463
  ],
10410
10464
  outputModalities: [
10411
10465
  "text"
@@ -10470,7 +10524,8 @@ var openai_default = {
10470
10524
  type: "chat",
10471
10525
  inputModalities: [
10472
10526
  "text",
10473
- "image"
10527
+ "image",
10528
+ "pdf"
10474
10529
  ],
10475
10530
  outputModalities: [
10476
10531
  "text"
@@ -10587,7 +10642,8 @@ var openai_default = {
10587
10642
  type: "chat",
10588
10643
  inputModalities: [
10589
10644
  "text",
10590
- "image"
10645
+ "image",
10646
+ "pdf"
10591
10647
  ],
10592
10648
  outputModalities: [
10593
10649
  "text"
@@ -10655,7 +10711,8 @@ var openai_default = {
10655
10711
  type: "chat",
10656
10712
  inputModalities: [
10657
10713
  "text",
10658
- "image"
10714
+ "image",
10715
+ "pdf"
10659
10716
  ],
10660
10717
  outputModalities: [
10661
10718
  "text"
@@ -11695,7 +11752,8 @@ var openai_default = {
11695
11752
  type: "chat",
11696
11753
  inputModalities: [
11697
11754
  "text",
11698
- "image"
11755
+ "image",
11756
+ "pdf"
11699
11757
  ],
11700
11758
  outputModalities: [
11701
11759
  "text"
@@ -11773,7 +11831,8 @@ var openai_default = {
11773
11831
  type: "chat",
11774
11832
  inputModalities: [
11775
11833
  "text",
11776
- "image"
11834
+ "image",
11835
+ "pdf"
11777
11836
  ],
11778
11837
  outputModalities: [
11779
11838
  "text"
@@ -11851,7 +11910,8 @@ var openai_default = {
11851
11910
  type: "chat",
11852
11911
  inputModalities: [
11853
11912
  "text",
11854
- "image"
11913
+ "image",
11914
+ "pdf"
11855
11915
  ],
11856
11916
  outputModalities: [
11857
11917
  "text"
@@ -29558,14 +29618,23 @@ function withBuiltinTools(provider, caps) {
29558
29618
  if (!tools || tools.length === 0) return caps;
29559
29619
  return { ...caps, builtinTools: [...tools] };
29560
29620
  }
29621
+ function normalizeId(model) {
29622
+ return model.toLowerCase().replace(/(?<=\d)[-.](?=\d)/g, ".");
29623
+ }
29561
29624
  var ModelCatalog = class _ModelCatalog {
29562
29625
  models = /* @__PURE__ */ new Map();
29563
29626
  /** `provider/alias` → `provider/canonical-slug`. Lets get()/resolveModelId
29564
29627
  * accept any callable id (providerModelName, dated snapshot) AND the slug. */
29565
29628
  aliasIndex = /* @__PURE__ */ new Map();
29629
+ /** `provider/normalized-id` → `provider/canonical-slug`. The last resort, so a
29630
+ * user's spelling of a version never decides whether the model is found. */
29631
+ normIndex = /* @__PURE__ */ new Map();
29566
29632
  key(provider, model) {
29567
29633
  return `${provider}/${model}`;
29568
29634
  }
29635
+ normKey(provider, model) {
29636
+ return `${provider}/${normalizeId(model)}`;
29637
+ }
29569
29638
  set(provider, model, info) {
29570
29639
  const canonical = this.key(provider, model);
29571
29640
  this.models.set(canonical, {
@@ -29603,19 +29672,39 @@ var ModelCatalog = class _ModelCatalog {
29603
29672
  this.aliasIndex.set(this.key(provider, alias), canonical);
29604
29673
  }
29605
29674
  }
29675
+ for (const name of [model, info.providerModelName, ...info.aliases ?? []]) {
29676
+ if (!name) continue;
29677
+ const nk = this.normKey(provider, name);
29678
+ if (!this.normIndex.has(nk)) this.normIndex.set(nk, canonical);
29679
+ }
29606
29680
  }
29607
29681
  get(provider, model) {
29608
29682
  const direct = this.models.get(this.key(provider, model));
29609
29683
  if (direct) return direct;
29610
- const canonical = this.aliasIndex.get(this.key(provider, model));
29684
+ const canonical = this.aliasIndex.get(this.key(provider, model)) ?? // Last resort: the same model under a different spelling of its version.
29685
+ this.normIndex.get(this.normKey(provider, model));
29611
29686
  return canonical ? this.models.get(canonical) ?? null : null;
29612
29687
  }
29613
- /** The exact id to SEND to the provider for a given model string. Translates
29614
- * our slug → providerModelName; passes an already-callable id (alias) through
29615
- * verbatim (respects an explicit choice); unknown model verbatim passthrough. */
29688
+ /** The exact id to SEND to the provider for a given model string.
29689
+ *
29690
+ * Three cases, and the difference between them is what the caller ASKED for:
29691
+ * - our slug → translate to providerModelName (the pinned snapshot)
29692
+ * - an id the provider itself accepts (a listed alias, e.g. a dated snapshot
29693
+ * or anthropic's undated name) → verbatim, because it is a deliberate choice
29694
+ * and rewriting it would pin a caller who asked to float
29695
+ * - a spelling variant that is NOT callable (`gemini-2-5-flash`) → the
29696
+ * canonical entry's providerModelName, since forwarding it verbatim only
29697
+ * produces a 404 with the user's typo in it
29698
+ * - unknown → verbatim, so a model we have never heard of still works */
29616
29699
  resolveModelId(provider, model) {
29617
29700
  const direct = this.models.get(this.key(provider, model));
29618
29701
  if (direct) return direct.providerModelName ?? model;
29702
+ if (this.aliasIndex.has(this.key(provider, model))) return model;
29703
+ const canonical = this.normIndex.get(this.normKey(provider, model));
29704
+ if (canonical) {
29705
+ const info = this.models.get(canonical);
29706
+ if (info) return info.providerModelName ?? info.model;
29707
+ }
29619
29708
  return model;
29620
29709
  }
29621
29710
  getPricing(provider, model) {
@@ -29764,14 +29853,31 @@ function evalCond(cond, ctx, reg) {
29764
29853
  const t = ctx.item?.value;
29765
29854
  return !reg.predicates.isFunctionTool(ctx) && t?.type === c.builtin;
29766
29855
  }
29856
+ if ("hasPartType" in c) {
29857
+ const messages = ctx.req.messages;
29858
+ return Boolean(
29859
+ messages?.some(
29860
+ (m) => Array.isArray(m?.content) ? m.content.some((part) => c.hasPartType.includes(part?.type)) : false
29861
+ )
29862
+ );
29863
+ }
29767
29864
  if ("hasTool" in c) {
29768
29865
  const tools = ctx.req.tools;
29769
- return Boolean(
29866
+ const present = Boolean(
29770
29867
  tools?.some((t) => {
29771
29868
  const itemCtx = { ...ctx, item: { value: t, index: 0, isLast: false } };
29772
29869
  return !reg.predicates.isFunctionTool(itemCtx) && t?.type === c.hasTool;
29773
29870
  })
29774
29871
  );
29872
+ if (!present) return false;
29873
+ const blocked = ctx.spec.toolConstraints?.find(
29874
+ (tc) => tc.tool === c.hasTool && evalCond(tc.conflictsWith, ctx, reg)
29875
+ );
29876
+ if (blocked) {
29877
+ if (ctx.notes && !ctx.notes.includes(blocked.why)) ctx.notes.push(blocked.why);
29878
+ return false;
29879
+ }
29880
+ return true;
29775
29881
  }
29776
29882
  if ("hasFunctionTool" in c) {
29777
29883
  const tools = ctx.req.tools;
@@ -29897,7 +30003,8 @@ function buildFromSpec(spec, req, reg, flavor = spec.provider, onUse, config = {
29897
30003
  flavor,
29898
30004
  config,
29899
30005
  variants: resolveVariants(spec, req.model ?? "", reg),
29900
- body: {}
30006
+ body: {},
30007
+ notes: []
29901
30008
  };
29902
30009
  for (const v of ctx.variants) onUse?.("variant", v);
29903
30010
  for (const f of spec.fields ?? []) {
@@ -29992,6 +30099,7 @@ function buildFromSpec(spec, req, reg, flavor = spec.provider, onUse, config = {
29992
30099
  }
29993
30100
  }
29994
30101
  const out = { body: ctx.body };
30102
+ if (ctx.notes?.length) out.notes = ctx.notes;
29995
30103
  if (ctx.multipart) out.multipart = ctx.multipart;
29996
30104
  if (spec.envelope?.bodyKind === "none") out.noBody = true;
29997
30105
  if (spec.envelope?.bodyKind === "raw") out.rawBody = true;
@@ -36289,6 +36397,18 @@ var LLMClient = class {
36289
36397
  return streamFile(file, this.retrieveContext());
36290
36398
  }
36291
36399
  /** Submit a request. Returns the parsed CompletionResponse. */
36400
+ /** Anything the spec left out on purpose reaches the caller as a warning.
36401
+ * Said once per request; the build already de-duplicates within one. */
36402
+ reportBuildNotes(req, ctx) {
36403
+ for (const note of req.notes ?? []) {
36404
+ this.hooks.emitSync("onWarning", {
36405
+ source: "llm",
36406
+ code: "request_adjusted",
36407
+ message: note,
36408
+ details: { provider: this.provider, model: this.model, ctx }
36409
+ });
36410
+ }
36411
+ }
36292
36412
  async complete(input, options = {}) {
36293
36413
  const rawMessages = normalizeInput(input);
36294
36414
  const { system: systemFromMessages, messages } = extractSystem(rawMessages);
@@ -36351,6 +36471,7 @@ var LLMClient = class {
36351
36471
  normalized.messages = decision.messages;
36352
36472
  }
36353
36473
  const providerReq = this.adapter.buildRequest(normalized);
36474
+ this.reportBuildNotes(providerReq, ctx);
36354
36475
  const url = this.adapter.baseURL() + (providerReq.path ?? this.adapter.completionPath());
36355
36476
  if (this.cacheKeyFn) {
36356
36477
  ctx.cacheKey = ctx.cacheKey ?? this.cacheKeyFn(normalized, ctx);
@@ -36512,6 +36633,7 @@ var LLMClient = class {
36512
36633
  normalized.messages = resolveCtx.messages;
36513
36634
  normalized.system = resolveCtx.system;
36514
36635
  const providerReq = this.adapter.buildRequest(normalized);
36636
+ this.reportBuildNotes(providerReq, ctx);
36515
36637
  this.adapter.enableStreaming?.(providerReq, normalized);
36516
36638
  const url = this.adapter.baseURL() + (providerReq.path ?? this.adapter.completionPath());
36517
36639
  const httpReq = {
@@ -37290,6 +37412,14 @@ var generate_2_5_default = {
37290
37412
  id: "google/generate@2.5",
37291
37413
  provider: "google",
37292
37414
  api: "generate",
37415
+ _toolConstraints: `Measured 2026-08-25: Google answers 400 "The mime type: X is not supported for code execution" when codeExecution is sent with a PDF or a video part. Images are fine, googleSearch is fine, and OpenAI accepts every combination -- so this is one provider's rule, kept with that provider's spec.`,
37416
+ toolConstraints: [
37417
+ {
37418
+ tool: "code_interpreter",
37419
+ conflictsWith: { hasPartType: ["document", "video"] },
37420
+ why: "google: code execution cannot run alongside a PDF or video attachment, so the request was sent without it"
37421
+ }
37422
+ ],
37293
37423
  tables: {
37294
37424
  toolMode: {
37295
37425
  auto: "AUTO",
@@ -54743,6 +54873,35 @@ var KNOWN_KEYS = /* @__PURE__ */ new Set([
54743
54873
  ...Object.keys(CAP_KEYS),
54744
54874
  ...Object.keys(BUILTIN_TOOL_KEYS)
54745
54875
  ]);
54876
+ function filterFacets(catalog) {
54877
+ const models = catalog?.list() ?? [];
54878
+ const distinct = (pick) => [...new Set(models.map(pick).filter((v) => !!v))].sort();
54879
+ const facets = [
54880
+ { key: "type", category: "what it is", label: "Type", values: distinct((m) => m.type), numeric: false, bare: false },
54881
+ { key: "provider", category: "what it is", label: "Provider", values: distinct((m) => m.provider), numeric: false, bare: false },
54882
+ // The named cutoffs the parser compares against, plus `free` for exactly zero.
54883
+ { key: "price", category: "cost", label: "Price", values: ["free", "low", "mid", "high"], numeric: true, bare: false },
54884
+ // filled below from the models themselves — tiers are per model, not a fixed set
54885
+ { key: "tier", category: "cost", label: "Billing tier", values: [], numeric: false, bare: false },
54886
+ { key: "context", category: "inputs", label: "Context window", values: ["small", "large"], numeric: true, bare: false },
54887
+ { key: "reasoning", category: "thinking", label: "Reasoning", values: ["yes", "no"], numeric: false, bare: true },
54888
+ { key: "status", category: "availability", label: "Status", values: distinct((m) => m.status), numeric: false, bare: false },
54889
+ { key: "active", category: "availability", label: "Offered now", values: ["yes", "no"], numeric: false, bare: true }
54890
+ ];
54891
+ for (const key of Object.keys(CAP_KEYS)) {
54892
+ facets.push({ key, category: "inputs", label: key, values: ["yes", "no"], numeric: false, bare: true });
54893
+ }
54894
+ for (const key of Object.keys(BUILTIN_TOOL_KEYS)) {
54895
+ facets.push({ key, category: "hosted tools", label: key.replace(/_/g, " "), values: ["yes", "no"], numeric: false, bare: true });
54896
+ }
54897
+ const tiers = [...new Set(models.flatMap((m) => Object.keys(m.pricing?.tiers ?? {})))].sort();
54898
+ const tierFacet = facets.find((f) => f.key === "tier");
54899
+ if (tierFacet) tierFacet.values = tiers;
54900
+ return facets;
54901
+ }
54902
+ function filterAliases() {
54903
+ return { ...DEFAULT_TAGS };
54904
+ }
54746
54905
  function parseNum(v) {
54747
54906
  const m = /^([\d.]+)\s*([kKmM]?)$/.exec(v.trim());
54748
54907
  if (!m) return Number.NaN;
@@ -54864,6 +55023,7 @@ function select(query, opts = {}) {
54864
55023
  function createRealtime(opts) {
54865
55024
  const engine = opts.engine ?? coreRegistry.get();
54866
55025
  const { provider, model } = resolveModel(opts.model, opts.provider, "createRealtime");
55026
+ const sendModel = engine.catalog.resolveModelId(provider, model);
54867
55027
  const apiKey = opts.apiKey ?? engine.apiKeys[provider];
54868
55028
  if (!apiKey) {
54869
55029
  throw new Error(
@@ -54873,11 +55033,11 @@ function createRealtime(opts) {
54873
55033
  const adapter = resolveAdapter2(provider, apiKey);
54874
55034
  const voice = resolveVoice(provider, opts.audio?.voice ?? opts.voice);
54875
55035
  const session = adapter.connect(
54876
- { model, modalities: opts.modalities, voice, instructions: opts.instructions },
55036
+ { model: sendModel, modalities: opts.modalities, voice, instructions: opts.instructions },
54877
55037
  engine.connect
54878
55038
  );
54879
55039
  session.on("usage", (e) => {
54880
- void engine.hooks.emit("onCompletion", realtimeCompletionContext(provider, model, e.usage)).catch(() => {
55040
+ void engine.hooks.emit("onCompletion", realtimeCompletionContext(provider, sendModel, e.usage)).catch(() => {
54881
55041
  });
54882
55042
  });
54883
55043
  return session;
@@ -57248,6 +57408,8 @@ export {
57248
57408
  exchangeCode,
57249
57409
  extractLastUserText,
57250
57410
  extractSystemText,
57411
+ filterAliases,
57412
+ filterFacets,
57251
57413
  finalAnswerText,
57252
57414
  finishMcpAuth,
57253
57415
  formatBulletedList,