@jambonz/llm 0.5.2 → 0.5.4

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.
@@ -146,12 +146,18 @@ async function* streamFromOpenAI(client, req, options) {
146
146
  let usage;
147
147
  let finalFinishReason = null;
148
148
  let finalRawReason;
149
+ let sawContent = false;
149
150
  try {
150
151
  for await (const chunk of stream) {
151
152
  if (req.signal?.aborted) {
152
153
  yield { type: "end", finishReason: "aborted" };
153
154
  return;
154
155
  }
156
+ const chunkError = chunk.error;
157
+ if (chunkError) {
158
+ const message = chunkError && typeof chunkError === "object" && "message" in chunkError ? String(chunkError.message) : JSON.stringify(chunkError);
159
+ throw new Error(`OpenAI-compatible stream returned an error: ${message}`);
160
+ }
155
161
  if (chunk.usage) {
156
162
  usage = {
157
163
  ...chunk.usage.prompt_tokens !== void 0 ? { inputTokens: chunk.usage.prompt_tokens } : {},
@@ -165,6 +171,7 @@ async function* streamFromOpenAI(client, req, options) {
165
171
  const finishReason = choice.finish_reason;
166
172
  if (delta?.content) {
167
173
  if (t2 === void 0) t2 = process.hrtime.bigint();
174
+ sawContent = true;
168
175
  yield { type: "token", text: delta.content };
169
176
  }
170
177
  if (delta?.tool_calls) {
@@ -222,6 +229,12 @@ async function* streamFromOpenAI(client, req, options) {
222
229
  }
223
230
  throw err;
224
231
  }
232
+ const producedNothing = finalFinishReason === null && !sawContent && toolCallsEmitted.size === 0 && startedIds.size === 0 && usage === void 0;
233
+ if (producedNothing) {
234
+ throw new Error(
235
+ "OpenAI-compatible stream produced no data (no content, tool calls, usage, or finish reason). This usually means a misconfigured base URL or a vendor error returned in an HTTP 200 body. Verify the base URL and credentials."
236
+ );
237
+ }
225
238
  const endEvent = {
226
239
  type: "end",
227
240
  finishReason: finalFinishReason ?? "stop",
@@ -527,7 +540,7 @@ var OpenAIAdapter = class {
527
540
  }
528
541
  stream(req) {
529
542
  return streamFromOpenAI(this.ensureClient(), req, {
530
- knownModels: openAIManifest.knownModels,
543
+ knownModels: this.knownModels(),
531
544
  vendorMetadataExtractor: OPENAI_METADATA_EXTRACTOR
532
545
  });
533
546
  }
@@ -538,7 +551,16 @@ var OpenAIAdapter = class {
538
551
  return appendOpenAIToolResult(history, toolCallId, result);
539
552
  }
540
553
  async listAvailableModels() {
541
- return listOpenAICompatibleModels(this.ensureClient(), openAIManifest.knownModels);
554
+ return listOpenAICompatibleModels(this.ensureClient(), this.knownModels());
555
+ }
556
+ /**
557
+ * Capability table used to enrich both `stream()` (for tools/vision gating)
558
+ * and `listAvailableModels()` (for filling capability flags on live entries).
559
+ * Subclasses backed by the same OpenAI wire (DeepSeek, Baseten, …) override
560
+ * this so their own manifest entries are consulted instead of OpenAI's.
561
+ */
562
+ knownModels() {
563
+ return openAIManifest.knownModels;
542
564
  }
543
565
  async testCredential() {
544
566
  await this.ensureClient().models.list();
@@ -649,12 +671,311 @@ var DeepSeekAdapter = class extends OpenAIAdapter {
649
671
  client
650
672
  );
651
673
  }
674
+ knownModels() {
675
+ return deepseekManifest.knownModels;
676
+ }
652
677
  };
653
678
  var deepseekFactory = {
654
679
  vendor: deepseekManifest.vendor,
655
680
  manifest: deepseekManifest,
656
681
  create: () => new DeepSeekAdapter()
657
682
  };
683
+ var basetenManifest = {
684
+ vendor: "baseten",
685
+ displayName: "Baseten",
686
+ authKinds: [
687
+ {
688
+ kind: "apiKey",
689
+ displayName: "API Key",
690
+ fields: [
691
+ {
692
+ name: "apiKey",
693
+ label: "API Key",
694
+ type: "password",
695
+ required: true,
696
+ help: "Get an API key from https://app.baseten.co/settings/api_keys"
697
+ },
698
+ {
699
+ name: "baseURL",
700
+ label: "Base URL",
701
+ type: "url",
702
+ required: false,
703
+ default: "https://inference.baseten.co/v1",
704
+ help: "Defaults to Baseten Model APIs. Set to https://bridge.baseten.co/v1/direct to route to a dedicated deployment."
705
+ }
706
+ ]
707
+ }
708
+ ],
709
+ knownModels: [
710
+ {
711
+ id: "deepseek-ai/DeepSeek-V3.1",
712
+ displayName: "DeepSeek V3.1",
713
+ capabilities: {
714
+ streaming: true,
715
+ tools: true,
716
+ vision: false,
717
+ systemPrompt: true,
718
+ maxContextTokens: 163840
719
+ }
720
+ },
721
+ {
722
+ id: "deepseek-ai/DeepSeek-V4-Pro",
723
+ displayName: "DeepSeek V4 Pro",
724
+ capabilities: {
725
+ streaming: true,
726
+ tools: true,
727
+ vision: false,
728
+ systemPrompt: true,
729
+ maxContextTokens: 131072
730
+ }
731
+ },
732
+ {
733
+ id: "zai-org/GLM-4.7",
734
+ displayName: "GLM 4.7",
735
+ capabilities: {
736
+ streaming: true,
737
+ tools: true,
738
+ vision: false,
739
+ systemPrompt: true,
740
+ maxContextTokens: 2e5
741
+ }
742
+ },
743
+ {
744
+ id: "zai-org/GLM-5",
745
+ displayName: "GLM 5",
746
+ capabilities: {
747
+ streaming: true,
748
+ tools: true,
749
+ vision: false,
750
+ systemPrompt: true,
751
+ maxContextTokens: 202800
752
+ }
753
+ },
754
+ {
755
+ id: "moonshotai/Kimi-K2.5",
756
+ displayName: "Kimi K2.5",
757
+ capabilities: {
758
+ streaming: true,
759
+ tools: true,
760
+ vision: true,
761
+ systemPrompt: true,
762
+ maxContextTokens: 262e3
763
+ }
764
+ },
765
+ {
766
+ id: "moonshotai/Kimi-K2.6",
767
+ displayName: "Kimi K2.6",
768
+ capabilities: {
769
+ streaming: true,
770
+ tools: true,
771
+ vision: true,
772
+ systemPrompt: true,
773
+ maxContextTokens: 262e3
774
+ }
775
+ },
776
+ {
777
+ id: "MiniMaxAI/MiniMax-M2.5",
778
+ displayName: "MiniMax M2.5",
779
+ capabilities: {
780
+ streaming: true,
781
+ tools: true,
782
+ vision: false,
783
+ systemPrompt: true,
784
+ maxContextTokens: 204e3
785
+ }
786
+ },
787
+ {
788
+ id: "nvidia/Nemotron-120B-A12B",
789
+ displayName: "Nemotron Super",
790
+ capabilities: {
791
+ streaming: true,
792
+ tools: true,
793
+ vision: false,
794
+ systemPrompt: true,
795
+ maxContextTokens: 202800
796
+ }
797
+ },
798
+ {
799
+ id: "openai/gpt-oss-120b",
800
+ displayName: "OpenAI GPT 120B",
801
+ capabilities: {
802
+ streaming: true,
803
+ tools: true,
804
+ vision: false,
805
+ systemPrompt: true,
806
+ maxContextTokens: 128072
807
+ }
808
+ }
809
+ ],
810
+ supportsModelListing: true,
811
+ docsUrl: "https://docs.baseten.co/inference/model-apis/overview"
812
+ };
813
+ var BasetenAdapter = class extends OpenAIAdapter {
814
+ vendor = basetenManifest.vendor;
815
+ init(auth, client) {
816
+ super.init(
817
+ {
818
+ ...auth,
819
+ baseURL: auth.baseURL ?? "https://inference.baseten.co/v1"
820
+ },
821
+ client
822
+ );
823
+ }
824
+ knownModels() {
825
+ return basetenManifest.knownModels;
826
+ }
827
+ };
828
+ var basetenFactory = {
829
+ vendor: basetenManifest.vendor,
830
+ manifest: basetenManifest,
831
+ create: () => new BasetenAdapter()
832
+ };
833
+ var moonshotManifest = {
834
+ vendor: "moonshot",
835
+ displayName: "Moonshot (Kimi)",
836
+ authKinds: [
837
+ {
838
+ kind: "apiKey",
839
+ displayName: "API Key",
840
+ fields: [
841
+ {
842
+ name: "apiKey",
843
+ label: "API Key",
844
+ type: "password",
845
+ required: true,
846
+ help: "Get an API key from https://platform.moonshot.ai/console/api-keys"
847
+ },
848
+ {
849
+ name: "baseURL",
850
+ label: "Base URL",
851
+ type: "url",
852
+ required: false,
853
+ default: "https://api.moonshot.ai/v1",
854
+ help: "Defaults to the global endpoint. Set to https://api.moonshot.cn/v1 for the China endpoint."
855
+ }
856
+ ]
857
+ }
858
+ ],
859
+ knownModels: [
860
+ {
861
+ id: "kimi-k2.6",
862
+ displayName: "Kimi K2.6",
863
+ capabilities: {
864
+ streaming: true,
865
+ tools: true,
866
+ vision: true,
867
+ systemPrompt: true,
868
+ maxContextTokens: 262144
869
+ }
870
+ },
871
+ {
872
+ id: "kimi-k2.5",
873
+ displayName: "Kimi K2.5",
874
+ capabilities: {
875
+ streaming: true,
876
+ tools: true,
877
+ vision: true,
878
+ systemPrompt: true,
879
+ maxContextTokens: 262144
880
+ }
881
+ }
882
+ ],
883
+ supportsModelListing: true,
884
+ docsUrl: "https://platform.moonshot.ai/docs"
885
+ };
886
+ var MoonshotAdapter = class extends OpenAIAdapter {
887
+ vendor = moonshotManifest.vendor;
888
+ init(auth, client) {
889
+ super.init(
890
+ {
891
+ ...auth,
892
+ baseURL: auth.baseURL ?? "https://api.moonshot.ai/v1"
893
+ },
894
+ client
895
+ );
896
+ }
897
+ knownModels() {
898
+ return moonshotManifest.knownModels;
899
+ }
900
+ };
901
+ var moonshotFactory = {
902
+ vendor: moonshotManifest.vendor,
903
+ manifest: moonshotManifest,
904
+ create: () => new MoonshotAdapter()
905
+ };
906
+ var zaiManifest = {
907
+ vendor: "zai",
908
+ displayName: "Z.ai (GLM)",
909
+ authKinds: [
910
+ {
911
+ kind: "apiKey",
912
+ displayName: "API Key",
913
+ fields: [
914
+ {
915
+ name: "apiKey",
916
+ label: "API Key",
917
+ type: "password",
918
+ required: true,
919
+ help: "Get an API key from https://z.ai/manage-apikey/apikey-list"
920
+ },
921
+ {
922
+ name: "baseURL",
923
+ label: "Base URL",
924
+ type: "url",
925
+ required: false,
926
+ default: "https://api.z.ai/api/paas/v4",
927
+ help: "Defaults to the general API. Coding-Plan keys must use https://api.z.ai/api/coding/paas/v4."
928
+ }
929
+ ]
930
+ }
931
+ ],
932
+ knownModels: [
933
+ {
934
+ id: "glm-5.2",
935
+ displayName: "GLM-5.2",
936
+ capabilities: {
937
+ streaming: true,
938
+ tools: true,
939
+ vision: false,
940
+ systemPrompt: true,
941
+ maxContextTokens: 1e6
942
+ }
943
+ },
944
+ {
945
+ id: "glm-4.7",
946
+ displayName: "GLM-4.7",
947
+ capabilities: {
948
+ streaming: true,
949
+ tools: true,
950
+ vision: false,
951
+ systemPrompt: true,
952
+ maxContextTokens: 2e5
953
+ }
954
+ }
955
+ ],
956
+ supportsModelListing: false,
957
+ docsUrl: "https://docs.z.ai/"
958
+ };
959
+ var ZaiAdapter = class extends OpenAIAdapter {
960
+ vendor = zaiManifest.vendor;
961
+ init(auth, client) {
962
+ super.init(
963
+ {
964
+ ...auth,
965
+ baseURL: auth.baseURL ?? "https://api.z.ai/api/paas/v4"
966
+ },
967
+ client
968
+ );
969
+ }
970
+ knownModels() {
971
+ return zaiManifest.knownModels;
972
+ }
973
+ };
974
+ var zaiFactory = {
975
+ vendor: zaiManifest.vendor,
976
+ manifest: zaiManifest,
977
+ create: () => new ZaiAdapter()
978
+ };
658
979
 
659
980
  // src/adapters/anthropic/adapter.ts
660
981
  var import_sdk = __toESM(require("@anthropic-ai/sdk"), 1);
@@ -2827,6 +3148,9 @@ var huggingfaceFactory = {
2827
3148
  // src/adapters/index.ts
2828
3149
  registerAdapter(openAIFactory);
2829
3150
  registerAdapter(deepseekFactory);
3151
+ registerAdapter(basetenFactory);
3152
+ registerAdapter(moonshotFactory);
3153
+ registerAdapter(zaiFactory);
2830
3154
  registerAdapter(anthropicFactory);
2831
3155
  registerAdapter(googleFactory);
2832
3156
  registerAdapter(vertexGeminiFactory);