@jaypie/llm 1.3.5 → 1.3.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.
@@ -101,7 +101,10 @@ const PROVIDER = {
101
101
  ANTHROPIC: {
102
102
  // https://docs.anthropic.com/en/docs/about-claude/models/overview
103
103
  MAX_TOKENS: {
104
- DEFAULT: 4096,
104
+ // Non-streaming ceiling: responses above ~16K output tokens risk HTTP
105
+ // timeouts; streaming requests resolve to the model maximum instead
106
+ // (see util/maxOutputTokens.ts)
107
+ DEFAULT: 16384,
105
108
  },
106
109
  MODEL: {
107
110
  DEFAULT: FIRST_CLASS_PROVIDER.ANTHROPIC.DEFAULT,
@@ -450,14 +453,12 @@ class BaseProviderAdapter {
450
453
  /**
451
454
  * Default implementation returns false - override for providers with native structured output
452
455
  */
453
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
454
456
  hasStructuredOutput(_response) {
455
457
  return false;
456
458
  }
457
459
  /**
458
460
  * Default implementation returns undefined - override for providers with native structured output
459
461
  */
460
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
461
462
  extractStructuredOutput(_response) {
462
463
  return undefined;
463
464
  }
@@ -925,6 +926,52 @@ function jsonSchemaToOpenApi3(schema) {
925
926
 
926
927
  const getLogger$6 = () => log$1.log.lib({ lib: kit.JAYPIE.LIB.LLM });
927
928
 
929
+ //
930
+ //
931
+ // Constants
932
+ //
933
+ // Non-streaming requests above ~16K output tokens risk HTTP timeouts
934
+ // (Anthropic guidance is to stream anything larger), so non-streaming
935
+ // defaults are capped here and only streaming requests resolve to the
936
+ // full model maximum.
937
+ const NON_STREAMING_MAX_TOKENS = PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT;
938
+ // Maximum output tokens by model; first match wins.
939
+ // Providers without low output ceilings (OpenAI, xAI) are intentionally
940
+ // absent — their requests leave the limit unset.
941
+ const MODEL_MAX_OUTPUT_TOKENS = [
942
+ // Anthropic — https://platform.claude.com/docs/en/about-claude/models/overview
943
+ { pattern: /^claude-opus-4-(0$|1$|1-|2025)/, tokens: 32000 },
944
+ { pattern: /^claude-opus-4-5/, tokens: 64000 },
945
+ { pattern: /^claude-sonnet-4-(0$|5$|5-|2025)/, tokens: 64000 },
946
+ { pattern: /haiku/, tokens: 64000 },
947
+ { pattern: /claude|fable|mythos|opus|sonnet/, tokens: 128000 },
948
+ // Google — https://ai.google.dev/gemini-api/docs/models
949
+ { pattern: /gemini-(2\.5|3)/, tokens: 65536 },
950
+ { pattern: /gemini/, tokens: 8192 },
951
+ ];
952
+ //
953
+ //
954
+ // Main
955
+ //
956
+ /**
957
+ * Maximum output tokens the model supports, or undefined when unknown.
958
+ */
959
+ function maxOutputTokens(model) {
960
+ const match = MODEL_MAX_OUTPUT_TOKENS.find(({ pattern }) => pattern.test(model));
961
+ return match?.tokens;
962
+ }
963
+ /**
964
+ * Default output token limit for a request: the model maximum when
965
+ * streaming, capped at the non-streaming maximum otherwise. Returns
966
+ * undefined when the model's maximum is unknown.
967
+ */
968
+ function resolveMaxOutputTokens(model, { stream = false } = {}) {
969
+ const max = maxOutputTokens(model);
970
+ if (max === undefined)
971
+ return undefined;
972
+ return stream ? max : Math.min(max, NON_STREAMING_MAX_TOKENS);
973
+ }
974
+
928
975
  // Turn policy constants
929
976
  const MAX_TURNS_ABSOLUTE_LIMIT = 72;
930
977
  const MAX_TURNS_DEFAULT_LIMIT = 24;
@@ -1749,11 +1796,13 @@ class AnthropicAdapter extends BaseProviderAdapter {
1749
1796
  lastMsg.content = lastMsg.content + "\n\n" + request.instructions;
1750
1797
  }
1751
1798
  }
1799
+ const model = (request.model ||
1800
+ this.defaultModel);
1752
1801
  const anthropicRequest = {
1753
- model: (request.model ||
1754
- this.defaultModel),
1802
+ model,
1755
1803
  messages,
1756
- max_tokens: PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT,
1804
+ max_tokens: resolveMaxOutputTokens(model, { stream: request.stream }) ??
1805
+ PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT,
1757
1806
  stream: false,
1758
1807
  };
1759
1808
  if (request.system) {
@@ -1816,7 +1865,6 @@ class AnthropicAdapter extends BaseProviderAdapter {
1816
1865
  // outputSchema is part of the interface contract but Anthropic now uses
1817
1866
  // native `output_format` (set in buildRequest), so we no longer inject a
1818
1867
  // synthetic structured-output tool here.
1819
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1820
1868
  _outputSchema) {
1821
1869
  return toolkit.tools.map((tool) => ({
1822
1870
  name: tool.name,
@@ -3003,6 +3051,18 @@ class GoogleAdapter extends BaseProviderAdapter {
3003
3051
  : structuredOutputInstruction,
3004
3052
  };
3005
3053
  }
3054
+ // Default output ceiling: Google's own default (8,192) silently
3055
+ // truncates long generations, so resolve to the model maximum (capped
3056
+ // for non-streaming); providerOptions below override
3057
+ const maxOutputTokens = resolveMaxOutputTokens(geminiRequest.model, {
3058
+ stream: request.stream,
3059
+ });
3060
+ if (maxOutputTokens !== undefined) {
3061
+ geminiRequest.config = {
3062
+ ...geminiRequest.config,
3063
+ maxOutputTokens,
3064
+ };
3065
+ }
3006
3066
  // Add provider-specific options
3007
3067
  if (request.providerOptions) {
3008
3068
  geminiRequest.config = {
@@ -3024,7 +3084,6 @@ class GoogleAdapter extends BaseProviderAdapter {
3024
3084
  // structured output via `responseJsonSchema`/`responseSchema` (or the
3025
3085
  // legacy fake-tool injected in buildRequest as a fallback). We no longer
3026
3086
  // inject a synthetic structured-output tool here.
3027
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3028
3087
  _outputSchema) {
3029
3088
  return toolkit.tools.map((tool) => ({
3030
3089
  name: tool.name,
@@ -4689,7 +4748,6 @@ class OpenRouterAdapter extends BaseProviderAdapter {
4689
4748
  // native `response_format` (set in buildRequest), so we no longer inject a
4690
4749
  // synthetic structured-output tool here. The legacy fake-tool injection
4691
4750
  // happens in buildRequest only as a runtime fallback.
4692
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4693
4751
  _outputSchema) {
4694
4752
  return toolkit.tools.map((tool) => ({
4695
4753
  name: tool.name,
@@ -7021,6 +7079,7 @@ class StreamLoop {
7021
7079
  messages: state.currentInput,
7022
7080
  model: options.model ?? this.adapter.defaultModel,
7023
7081
  providerOptions: options.providerOptions,
7082
+ stream: true,
7024
7083
  system: options.system,
7025
7084
  temperature: options.temperature,
7026
7085
  tools: state.formattedTools,
@@ -7089,6 +7148,7 @@ class StreamLoop {
7089
7148
  messages: state.currentInput,
7090
7149
  model: options.model ?? this.adapter.defaultModel,
7091
7150
  providerOptions: options.providerOptions,
7151
+ stream: true,
7092
7152
  system: options.system,
7093
7153
  temperature: options.temperature,
7094
7154
  tools: state.formattedTools,