@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.
@@ -30,7 +30,7 @@ declare const PROVIDER: {
30
30
  };
31
31
  readonly ANTHROPIC: {
32
32
  readonly MAX_TOKENS: {
33
- readonly DEFAULT: 4096;
33
+ readonly DEFAULT: 16384;
34
34
  };
35
35
  readonly MODEL: {
36
36
  readonly DEFAULT: "claude-sonnet-4-6";
@@ -26,7 +26,7 @@ export declare const PROVIDER: {
26
26
  };
27
27
  readonly ANTHROPIC: {
28
28
  readonly MAX_TOKENS: {
29
- readonly DEFAULT: 4096;
29
+ readonly DEFAULT: 16384;
30
30
  };
31
31
  readonly MODEL: {
32
32
  readonly DEFAULT: "claude-sonnet-4-6";
@@ -70,6 +70,8 @@ export interface OperateRequest {
70
70
  format?: JsonObject;
71
71
  /** Provider-specific options */
72
72
  providerOptions?: JsonObject;
73
+ /** Whether the request will execute over a streaming transport */
74
+ stream?: boolean;
73
75
  /** Sampling temperature (0-2 for most providers) */
74
76
  temperature?: number;
75
77
  /** User identifier for tracking */
@@ -6,6 +6,7 @@ export * from "./formatOperateMessage.js";
6
6
  export * from "./jsonSchema.js";
7
7
  export * from "./jsonSchemaToOpenApi3.js";
8
8
  export * from "./logger.js";
9
+ export * from "./maxOutputTokens.js";
9
10
  export * from "./maxTurnsFromOptions.js";
10
11
  export * from "./naturalZodSchema.js";
11
12
  export * from "./random.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Maximum output tokens the model supports, or undefined when unknown.
3
+ */
4
+ export declare function maxOutputTokens(model: string): number | undefined;
5
+ /**
6
+ * Default output token limit for a request: the model maximum when
7
+ * streaming, capped at the non-streaming maximum otherwise. Returns
8
+ * undefined when the model's maximum is unknown.
9
+ */
10
+ export declare function resolveMaxOutputTokens(model: string, { stream }?: {
11
+ stream?: boolean;
12
+ }): number | undefined;
@@ -30,7 +30,7 @@ declare const PROVIDER: {
30
30
  };
31
31
  readonly ANTHROPIC: {
32
32
  readonly MAX_TOKENS: {
33
- readonly DEFAULT: 4096;
33
+ readonly DEFAULT: 16384;
34
34
  };
35
35
  readonly MODEL: {
36
36
  readonly DEFAULT: "claude-sonnet-4-6";
package/dist/esm/index.js CHANGED
@@ -98,7 +98,10 @@ const PROVIDER = {
98
98
  ANTHROPIC: {
99
99
  // https://docs.anthropic.com/en/docs/about-claude/models/overview
100
100
  MAX_TOKENS: {
101
- DEFAULT: 4096,
101
+ // Non-streaming ceiling: responses above ~16K output tokens risk HTTP
102
+ // timeouts; streaming requests resolve to the model maximum instead
103
+ // (see util/maxOutputTokens.ts)
104
+ DEFAULT: 16384,
102
105
  },
103
106
  MODEL: {
104
107
  DEFAULT: FIRST_CLASS_PROVIDER.ANTHROPIC.DEFAULT,
@@ -447,14 +450,12 @@ class BaseProviderAdapter {
447
450
  /**
448
451
  * Default implementation returns false - override for providers with native structured output
449
452
  */
450
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
451
453
  hasStructuredOutput(_response) {
452
454
  return false;
453
455
  }
454
456
  /**
455
457
  * Default implementation returns undefined - override for providers with native structured output
456
458
  */
457
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
458
459
  extractStructuredOutput(_response) {
459
460
  return undefined;
460
461
  }
@@ -922,6 +923,52 @@ function jsonSchemaToOpenApi3(schema) {
922
923
 
923
924
  const getLogger$6 = () => log$2.lib({ lib: JAYPIE.LIB.LLM });
924
925
 
926
+ //
927
+ //
928
+ // Constants
929
+ //
930
+ // Non-streaming requests above ~16K output tokens risk HTTP timeouts
931
+ // (Anthropic guidance is to stream anything larger), so non-streaming
932
+ // defaults are capped here and only streaming requests resolve to the
933
+ // full model maximum.
934
+ const NON_STREAMING_MAX_TOKENS = PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT;
935
+ // Maximum output tokens by model; first match wins.
936
+ // Providers without low output ceilings (OpenAI, xAI) are intentionally
937
+ // absent — their requests leave the limit unset.
938
+ const MODEL_MAX_OUTPUT_TOKENS = [
939
+ // Anthropic — https://platform.claude.com/docs/en/about-claude/models/overview
940
+ { pattern: /^claude-opus-4-(0$|1$|1-|2025)/, tokens: 32000 },
941
+ { pattern: /^claude-opus-4-5/, tokens: 64000 },
942
+ { pattern: /^claude-sonnet-4-(0$|5$|5-|2025)/, tokens: 64000 },
943
+ { pattern: /haiku/, tokens: 64000 },
944
+ { pattern: /claude|fable|mythos|opus|sonnet/, tokens: 128000 },
945
+ // Google — https://ai.google.dev/gemini-api/docs/models
946
+ { pattern: /gemini-(2\.5|3)/, tokens: 65536 },
947
+ { pattern: /gemini/, tokens: 8192 },
948
+ ];
949
+ //
950
+ //
951
+ // Main
952
+ //
953
+ /**
954
+ * Maximum output tokens the model supports, or undefined when unknown.
955
+ */
956
+ function maxOutputTokens(model) {
957
+ const match = MODEL_MAX_OUTPUT_TOKENS.find(({ pattern }) => pattern.test(model));
958
+ return match?.tokens;
959
+ }
960
+ /**
961
+ * Default output token limit for a request: the model maximum when
962
+ * streaming, capped at the non-streaming maximum otherwise. Returns
963
+ * undefined when the model's maximum is unknown.
964
+ */
965
+ function resolveMaxOutputTokens(model, { stream = false } = {}) {
966
+ const max = maxOutputTokens(model);
967
+ if (max === undefined)
968
+ return undefined;
969
+ return stream ? max : Math.min(max, NON_STREAMING_MAX_TOKENS);
970
+ }
971
+
925
972
  // Turn policy constants
926
973
  const MAX_TURNS_ABSOLUTE_LIMIT = 72;
927
974
  const MAX_TURNS_DEFAULT_LIMIT = 24;
@@ -1746,11 +1793,13 @@ class AnthropicAdapter extends BaseProviderAdapter {
1746
1793
  lastMsg.content = lastMsg.content + "\n\n" + request.instructions;
1747
1794
  }
1748
1795
  }
1796
+ const model = (request.model ||
1797
+ this.defaultModel);
1749
1798
  const anthropicRequest = {
1750
- model: (request.model ||
1751
- this.defaultModel),
1799
+ model,
1752
1800
  messages,
1753
- max_tokens: PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT,
1801
+ max_tokens: resolveMaxOutputTokens(model, { stream: request.stream }) ??
1802
+ PROVIDER.ANTHROPIC.MAX_TOKENS.DEFAULT,
1754
1803
  stream: false,
1755
1804
  };
1756
1805
  if (request.system) {
@@ -1813,7 +1862,6 @@ class AnthropicAdapter extends BaseProviderAdapter {
1813
1862
  // outputSchema is part of the interface contract but Anthropic now uses
1814
1863
  // native `output_format` (set in buildRequest), so we no longer inject a
1815
1864
  // synthetic structured-output tool here.
1816
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1817
1865
  _outputSchema) {
1818
1866
  return toolkit.tools.map((tool) => ({
1819
1867
  name: tool.name,
@@ -3000,6 +3048,18 @@ class GoogleAdapter extends BaseProviderAdapter {
3000
3048
  : structuredOutputInstruction,
3001
3049
  };
3002
3050
  }
3051
+ // Default output ceiling: Google's own default (8,192) silently
3052
+ // truncates long generations, so resolve to the model maximum (capped
3053
+ // for non-streaming); providerOptions below override
3054
+ const maxOutputTokens = resolveMaxOutputTokens(geminiRequest.model, {
3055
+ stream: request.stream,
3056
+ });
3057
+ if (maxOutputTokens !== undefined) {
3058
+ geminiRequest.config = {
3059
+ ...geminiRequest.config,
3060
+ maxOutputTokens,
3061
+ };
3062
+ }
3003
3063
  // Add provider-specific options
3004
3064
  if (request.providerOptions) {
3005
3065
  geminiRequest.config = {
@@ -3021,7 +3081,6 @@ class GoogleAdapter extends BaseProviderAdapter {
3021
3081
  // structured output via `responseJsonSchema`/`responseSchema` (or the
3022
3082
  // legacy fake-tool injected in buildRequest as a fallback). We no longer
3023
3083
  // inject a synthetic structured-output tool here.
3024
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
3025
3084
  _outputSchema) {
3026
3085
  return toolkit.tools.map((tool) => ({
3027
3086
  name: tool.name,
@@ -4686,7 +4745,6 @@ class OpenRouterAdapter extends BaseProviderAdapter {
4686
4745
  // native `response_format` (set in buildRequest), so we no longer inject a
4687
4746
  // synthetic structured-output tool here. The legacy fake-tool injection
4688
4747
  // happens in buildRequest only as a runtime fallback.
4689
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4690
4748
  _outputSchema) {
4691
4749
  return toolkit.tools.map((tool) => ({
4692
4750
  name: tool.name,
@@ -7018,6 +7076,7 @@ class StreamLoop {
7018
7076
  messages: state.currentInput,
7019
7077
  model: options.model ?? this.adapter.defaultModel,
7020
7078
  providerOptions: options.providerOptions,
7079
+ stream: true,
7021
7080
  system: options.system,
7022
7081
  temperature: options.temperature,
7023
7082
  tools: state.formattedTools,
@@ -7086,6 +7145,7 @@ class StreamLoop {
7086
7145
  messages: state.currentInput,
7087
7146
  model: options.model ?? this.adapter.defaultModel,
7088
7147
  providerOptions: options.providerOptions,
7148
+ stream: true,
7089
7149
  system: options.system,
7090
7150
  temperature: options.temperature,
7091
7151
  tools: state.formattedTools,