@jaypie/llm 1.3.8 → 1.3.10

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.
Files changed (187) hide show
  1. package/dist/cjs/{src/constants.d.ts → constants.d.ts} +56 -7
  2. package/dist/cjs/index.cjs +404 -124
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs/index.d.cts +69 -10
  5. package/dist/{esm/src → cjs}/index.d.ts +1 -0
  6. package/dist/cjs/{src/operate → operate}/adapters/AnthropicAdapter.d.ts +3 -2
  7. package/dist/{esm/src → cjs}/operate/adapters/BedrockAdapter.d.ts +1 -1
  8. package/dist/cjs/{src/operate → operate}/adapters/GoogleAdapter.d.ts +1 -1
  9. package/dist/{esm/src → cjs}/operate/adapters/OpenAiAdapter.d.ts +7 -1
  10. package/dist/{esm/src → cjs}/operate/adapters/OpenRouterAdapter.d.ts +5 -1
  11. package/dist/cjs/operate/adapters/XaiAdapter.d.ts +24 -0
  12. package/dist/cjs/{src/operate → operate}/types.d.ts +5 -0
  13. package/dist/cjs/{src/providers → providers}/google/types.d.ts +5 -0
  14. package/dist/{esm/src → cjs}/types/LlmProvider.interface.d.ts +9 -0
  15. package/dist/cjs/util/effort.d.ts +42 -0
  16. package/dist/cjs/{src/util → util}/index.d.ts +1 -0
  17. package/dist/cjs/util/tallyOperate.d.ts +14 -0
  18. package/dist/esm/{src/constants.d.ts → constants.d.ts} +56 -7
  19. package/dist/esm/index.d.ts +69 -10
  20. package/dist/esm/index.js +404 -124
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/{src/operate → operate}/adapters/AnthropicAdapter.d.ts +3 -2
  23. package/dist/{cjs/src → esm}/operate/adapters/BedrockAdapter.d.ts +1 -1
  24. package/dist/esm/{src/operate → operate}/adapters/GoogleAdapter.d.ts +1 -1
  25. package/dist/{cjs/src → esm}/operate/adapters/OpenAiAdapter.d.ts +7 -1
  26. package/dist/{cjs/src → esm}/operate/adapters/OpenRouterAdapter.d.ts +5 -1
  27. package/dist/esm/operate/adapters/XaiAdapter.d.ts +24 -0
  28. package/dist/esm/{src/operate → operate}/types.d.ts +5 -0
  29. package/dist/esm/{src/providers → providers}/google/types.d.ts +5 -0
  30. package/dist/{cjs/src → esm}/types/LlmProvider.interface.d.ts +9 -0
  31. package/dist/esm/util/effort.d.ts +42 -0
  32. package/dist/esm/{src/util → util}/index.d.ts +1 -0
  33. package/dist/esm/util/tallyOperate.d.ts +14 -0
  34. package/package.json +1 -1
  35. package/dist/cjs/src/index.d.ts +0 -17
  36. package/dist/cjs/src/operate/adapters/XaiAdapter.d.ts +0 -14
  37. package/dist/esm/src/operate/adapters/XaiAdapter.d.ts +0 -14
  38. /package/dist/cjs/{src/Llm.d.ts → Llm.d.ts} +0 -0
  39. /package/dist/cjs/{src/observability → observability}/llmobs.d.ts +0 -0
  40. /package/dist/cjs/{src/operate → operate}/OperateLoop.d.ts +0 -0
  41. /package/dist/cjs/{src/operate → operate}/StreamLoop.d.ts +0 -0
  42. /package/dist/cjs/{src/operate → operate}/adapters/ProviderAdapter.interface.d.ts +0 -0
  43. /package/dist/cjs/{src/operate → operate}/adapters/index.d.ts +0 -0
  44. /package/dist/cjs/{src/operate → operate}/hooks/HookRunner.d.ts +0 -0
  45. /package/dist/cjs/{src/operate → operate}/hooks/index.d.ts +0 -0
  46. /package/dist/cjs/{src/operate → operate}/index.d.ts +0 -0
  47. /package/dist/cjs/{src/operate → operate}/input/InputProcessor.d.ts +0 -0
  48. /package/dist/cjs/{src/operate → operate}/input/index.d.ts +0 -0
  49. /package/dist/cjs/{src/operate → operate}/progress/emitProgress.d.ts +0 -0
  50. /package/dist/cjs/{src/operate → operate}/progress/index.d.ts +0 -0
  51. /package/dist/cjs/{src/operate → operate}/response/ResponseBuilder.d.ts +0 -0
  52. /package/dist/cjs/{src/operate → operate}/response/index.d.ts +0 -0
  53. /package/dist/cjs/{src/operate → operate}/retry/RetryExecutor.d.ts +0 -0
  54. /package/dist/cjs/{src/operate → operate}/retry/RetryPolicy.d.ts +0 -0
  55. /package/dist/cjs/{src/operate → operate}/retry/createStaleRejectionGuard.d.ts +0 -0
  56. /package/dist/cjs/{src/operate → operate}/retry/index.d.ts +0 -0
  57. /package/dist/cjs/{src/operate → operate}/retry/isTransientNetworkError.d.ts +0 -0
  58. /package/dist/cjs/{src/providers → providers}/anthropic/AnthropicProvider.class.d.ts +0 -0
  59. /package/dist/cjs/{src/providers → providers}/anthropic/client.d.ts +0 -0
  60. /package/dist/cjs/{src/providers → providers}/anthropic/index.d.ts +0 -0
  61. /package/dist/cjs/{src/providers → providers}/anthropic/types.d.ts +0 -0
  62. /package/dist/cjs/{src/providers → providers}/anthropic/utils.d.ts +0 -0
  63. /package/dist/cjs/{src/providers → providers}/bedrock/BedrockProvider.class.d.ts +0 -0
  64. /package/dist/cjs/{src/providers → providers}/bedrock/index.d.ts +0 -0
  65. /package/dist/cjs/{src/providers → providers}/bedrock/utils.d.ts +0 -0
  66. /package/dist/cjs/{src/providers → providers}/google/GoogleProvider.class.d.ts +0 -0
  67. /package/dist/cjs/{src/providers → providers}/google/client.d.ts +0 -0
  68. /package/dist/cjs/{src/providers → providers}/google/index.d.ts +0 -0
  69. /package/dist/cjs/{src/providers → providers}/google/utils.d.ts +0 -0
  70. /package/dist/cjs/{src/providers → providers}/openai/OpenAiProvider.class.d.ts +0 -0
  71. /package/dist/cjs/{src/providers → providers}/openai/client.d.ts +0 -0
  72. /package/dist/cjs/{src/providers → providers}/openai/index.d.ts +0 -0
  73. /package/dist/cjs/{src/providers → providers}/openai/responseFormat.d.ts +0 -0
  74. /package/dist/cjs/{src/providers → providers}/openai/types.d.ts +0 -0
  75. /package/dist/cjs/{src/providers → providers}/openai/utils.d.ts +0 -0
  76. /package/dist/cjs/{src/providers → providers}/openrouter/OpenRouterProvider.class.d.ts +0 -0
  77. /package/dist/cjs/{src/providers → providers}/openrouter/client.d.ts +0 -0
  78. /package/dist/cjs/{src/providers → providers}/openrouter/index.d.ts +0 -0
  79. /package/dist/cjs/{src/providers → providers}/openrouter/utils.d.ts +0 -0
  80. /package/dist/cjs/{src/providers → providers}/xai/XaiProvider.class.d.ts +0 -0
  81. /package/dist/cjs/{src/providers → providers}/xai/index.d.ts +0 -0
  82. /package/dist/cjs/{src/providers → providers}/xai/utils.d.ts +0 -0
  83. /package/dist/cjs/{src/tools → tools}/Toolkit.class.d.ts +0 -0
  84. /package/dist/cjs/{src/tools → tools}/index.d.ts +0 -0
  85. /package/dist/cjs/{src/tools → tools}/random.d.ts +0 -0
  86. /package/dist/cjs/{src/tools → tools}/roll.d.ts +0 -0
  87. /package/dist/cjs/{src/tools → tools}/time.d.ts +0 -0
  88. /package/dist/cjs/{src/tools → tools}/weather.d.ts +0 -0
  89. /package/dist/cjs/{src/types → types}/LlmOperateInput.guards.d.ts +0 -0
  90. /package/dist/cjs/{src/types → types}/LlmStreamChunk.interface.d.ts +0 -0
  91. /package/dist/cjs/{src/types → types}/LlmTool.interface.d.ts +0 -0
  92. /package/dist/cjs/{src/upload → upload}/detectMimeType.d.ts +0 -0
  93. /package/dist/cjs/{src/upload → upload}/extractPdfPages.d.ts +0 -0
  94. /package/dist/cjs/{src/upload → upload}/index.d.ts +0 -0
  95. /package/dist/cjs/{src/upload → upload}/loadLocalFile.d.ts +0 -0
  96. /package/dist/cjs/{src/upload → upload}/loadS3File.d.ts +0 -0
  97. /package/dist/cjs/{src/upload → upload}/resolveOperateInput.d.ts +0 -0
  98. /package/dist/cjs/{src/util → util}/determineModelProvider.d.ts +0 -0
  99. /package/dist/cjs/{src/util → util}/extractReasoning.d.ts +0 -0
  100. /package/dist/cjs/{src/util → util}/fillFormatArrays.d.ts +0 -0
  101. /package/dist/cjs/{src/util → util}/formatOperateInput.d.ts +0 -0
  102. /package/dist/cjs/{src/util → util}/formatOperateMessage.d.ts +0 -0
  103. /package/dist/cjs/{src/util → util}/jsonSchema.d.ts +0 -0
  104. /package/dist/cjs/{src/util → util}/jsonSchemaToOpenApi3.d.ts +0 -0
  105. /package/dist/cjs/{src/util → util}/logger.d.ts +0 -0
  106. /package/dist/cjs/{src/util → util}/maxOutputTokens.d.ts +0 -0
  107. /package/dist/cjs/{src/util → util}/maxTurnsFromOptions.d.ts +0 -0
  108. /package/dist/cjs/{src/util → util}/naturalZodSchema.d.ts +0 -0
  109. /package/dist/cjs/{src/util → util}/random.d.ts +0 -0
  110. /package/dist/cjs/{src/util → util}/repairFormatKeys.d.ts +0 -0
  111. /package/dist/cjs/{src/util → util}/sse.d.ts +0 -0
  112. /package/dist/cjs/{src/util → util}/tryParseNumber.d.ts +0 -0
  113. /package/dist/esm/{src/Llm.d.ts → Llm.d.ts} +0 -0
  114. /package/dist/esm/{src/observability → observability}/llmobs.d.ts +0 -0
  115. /package/dist/esm/{src/operate → operate}/OperateLoop.d.ts +0 -0
  116. /package/dist/esm/{src/operate → operate}/StreamLoop.d.ts +0 -0
  117. /package/dist/esm/{src/operate → operate}/adapters/ProviderAdapter.interface.d.ts +0 -0
  118. /package/dist/esm/{src/operate → operate}/adapters/index.d.ts +0 -0
  119. /package/dist/esm/{src/operate → operate}/hooks/HookRunner.d.ts +0 -0
  120. /package/dist/esm/{src/operate → operate}/hooks/index.d.ts +0 -0
  121. /package/dist/esm/{src/operate → operate}/index.d.ts +0 -0
  122. /package/dist/esm/{src/operate → operate}/input/InputProcessor.d.ts +0 -0
  123. /package/dist/esm/{src/operate → operate}/input/index.d.ts +0 -0
  124. /package/dist/esm/{src/operate → operate}/progress/emitProgress.d.ts +0 -0
  125. /package/dist/esm/{src/operate → operate}/progress/index.d.ts +0 -0
  126. /package/dist/esm/{src/operate → operate}/response/ResponseBuilder.d.ts +0 -0
  127. /package/dist/esm/{src/operate → operate}/response/index.d.ts +0 -0
  128. /package/dist/esm/{src/operate → operate}/retry/RetryExecutor.d.ts +0 -0
  129. /package/dist/esm/{src/operate → operate}/retry/RetryPolicy.d.ts +0 -0
  130. /package/dist/esm/{src/operate → operate}/retry/createStaleRejectionGuard.d.ts +0 -0
  131. /package/dist/esm/{src/operate → operate}/retry/index.d.ts +0 -0
  132. /package/dist/esm/{src/operate → operate}/retry/isTransientNetworkError.d.ts +0 -0
  133. /package/dist/esm/{src/providers → providers}/anthropic/AnthropicProvider.class.d.ts +0 -0
  134. /package/dist/esm/{src/providers → providers}/anthropic/client.d.ts +0 -0
  135. /package/dist/esm/{src/providers → providers}/anthropic/index.d.ts +0 -0
  136. /package/dist/esm/{src/providers → providers}/anthropic/types.d.ts +0 -0
  137. /package/dist/esm/{src/providers → providers}/anthropic/utils.d.ts +0 -0
  138. /package/dist/esm/{src/providers → providers}/bedrock/BedrockProvider.class.d.ts +0 -0
  139. /package/dist/esm/{src/providers → providers}/bedrock/index.d.ts +0 -0
  140. /package/dist/esm/{src/providers → providers}/bedrock/utils.d.ts +0 -0
  141. /package/dist/esm/{src/providers → providers}/google/GoogleProvider.class.d.ts +0 -0
  142. /package/dist/esm/{src/providers → providers}/google/client.d.ts +0 -0
  143. /package/dist/esm/{src/providers → providers}/google/index.d.ts +0 -0
  144. /package/dist/esm/{src/providers → providers}/google/utils.d.ts +0 -0
  145. /package/dist/esm/{src/providers → providers}/openai/OpenAiProvider.class.d.ts +0 -0
  146. /package/dist/esm/{src/providers → providers}/openai/client.d.ts +0 -0
  147. /package/dist/esm/{src/providers → providers}/openai/index.d.ts +0 -0
  148. /package/dist/esm/{src/providers → providers}/openai/responseFormat.d.ts +0 -0
  149. /package/dist/esm/{src/providers → providers}/openai/types.d.ts +0 -0
  150. /package/dist/esm/{src/providers → providers}/openai/utils.d.ts +0 -0
  151. /package/dist/esm/{src/providers → providers}/openrouter/OpenRouterProvider.class.d.ts +0 -0
  152. /package/dist/esm/{src/providers → providers}/openrouter/client.d.ts +0 -0
  153. /package/dist/esm/{src/providers → providers}/openrouter/index.d.ts +0 -0
  154. /package/dist/esm/{src/providers → providers}/openrouter/utils.d.ts +0 -0
  155. /package/dist/esm/{src/providers → providers}/xai/XaiProvider.class.d.ts +0 -0
  156. /package/dist/esm/{src/providers → providers}/xai/index.d.ts +0 -0
  157. /package/dist/esm/{src/providers → providers}/xai/utils.d.ts +0 -0
  158. /package/dist/esm/{src/tools → tools}/Toolkit.class.d.ts +0 -0
  159. /package/dist/esm/{src/tools → tools}/index.d.ts +0 -0
  160. /package/dist/esm/{src/tools → tools}/random.d.ts +0 -0
  161. /package/dist/esm/{src/tools → tools}/roll.d.ts +0 -0
  162. /package/dist/esm/{src/tools → tools}/time.d.ts +0 -0
  163. /package/dist/esm/{src/tools → tools}/weather.d.ts +0 -0
  164. /package/dist/esm/{src/types → types}/LlmOperateInput.guards.d.ts +0 -0
  165. /package/dist/esm/{src/types → types}/LlmStreamChunk.interface.d.ts +0 -0
  166. /package/dist/esm/{src/types → types}/LlmTool.interface.d.ts +0 -0
  167. /package/dist/esm/{src/upload → upload}/detectMimeType.d.ts +0 -0
  168. /package/dist/esm/{src/upload → upload}/extractPdfPages.d.ts +0 -0
  169. /package/dist/esm/{src/upload → upload}/index.d.ts +0 -0
  170. /package/dist/esm/{src/upload → upload}/loadLocalFile.d.ts +0 -0
  171. /package/dist/esm/{src/upload → upload}/loadS3File.d.ts +0 -0
  172. /package/dist/esm/{src/upload → upload}/resolveOperateInput.d.ts +0 -0
  173. /package/dist/esm/{src/util → util}/determineModelProvider.d.ts +0 -0
  174. /package/dist/esm/{src/util → util}/extractReasoning.d.ts +0 -0
  175. /package/dist/esm/{src/util → util}/fillFormatArrays.d.ts +0 -0
  176. /package/dist/esm/{src/util → util}/formatOperateInput.d.ts +0 -0
  177. /package/dist/esm/{src/util → util}/formatOperateMessage.d.ts +0 -0
  178. /package/dist/esm/{src/util → util}/jsonSchema.d.ts +0 -0
  179. /package/dist/esm/{src/util → util}/jsonSchemaToOpenApi3.d.ts +0 -0
  180. /package/dist/esm/{src/util → util}/logger.d.ts +0 -0
  181. /package/dist/esm/{src/util → util}/maxOutputTokens.d.ts +0 -0
  182. /package/dist/esm/{src/util → util}/maxTurnsFromOptions.d.ts +0 -0
  183. /package/dist/esm/{src/util → util}/naturalZodSchema.d.ts +0 -0
  184. /package/dist/esm/{src/util → util}/random.d.ts +0 -0
  185. /package/dist/esm/{src/util → util}/repairFormatKeys.d.ts +0 -0
  186. /package/dist/esm/{src/util → util}/sse.d.ts +0 -0
  187. /package/dist/esm/{src/util → util}/tryParseNumber.d.ts +0 -0
package/dist/esm/index.js CHANGED
@@ -11,61 +11,61 @@ import { resolve } from 'path';
11
11
  import { getS3FileBuffer, getEnvSecret } from '@jaypie/aws';
12
12
  import { fetchWeatherApi } from 'openmeteo';
13
13
 
14
- const FIRST_CLASS_PROVIDER = {
15
- // https://docs.anthropic.com/en/docs/about-claude/models/overview
16
- ANTHROPIC: {
17
- DEFAULT: "claude-sonnet-4-6",
18
- LARGE: "claude-opus-4-8",
19
- SMALL: "claude-sonnet-4-6",
20
- TINY: "claude-haiku-4-5",
21
- },
22
- // https://ai.google.dev/gemini-api/docs/models
23
- GOOGLE: {
24
- DEFAULT: "gemini-3.1-pro-preview",
25
- LARGE: "gemini-3.1-pro-preview",
26
- SMALL: "gemini-3.5-flash",
27
- TINY: "gemini-3.1-flash-lite",
28
- },
29
- // https://developers.openai.com/api/docs/models
30
- OPENAI: {
31
- DEFAULT: "gpt-5.4",
32
- LARGE: "gpt-5.5",
33
- SMALL: "gpt-5.4-mini",
34
- TINY: "gpt-5.4-nano",
35
- },
36
- // https://docs.x.ai/developers/models
37
- XAI: {
38
- DEFAULT: "grok-latest",
39
- LARGE: "grok-4.3-latest",
40
- SMALL: "grok-4-1-fast-reasoning",
41
- TINY: "grok-4-1-fast-non-reasoning",
42
- },
14
+ /**
15
+ * Provider-neutral reasoning-effort levels — a five-point relative scale that
16
+ * deliberately borrows no provider's vocabulary. Each adapter translates these
17
+ * to its provider's native control (OpenAI `reasoning.effort`, Anthropic
18
+ * `output_config.effort`, Gemini `thinkingLevel`/`thinkingBudget`, Grok
19
+ * `reasoning_effort`, OpenRouter `reasoning.effort`), spreading the scale across
20
+ * the provider's available range. Omitting `effort` leaves the provider default
21
+ * untouched, so it is safe to set across a fallback chain.
22
+ */
23
+ const EFFORT = {
24
+ LOWEST: "lowest",
25
+ LOW: "low",
26
+ MEDIUM: "medium",
27
+ HIGH: "high",
28
+ HIGHEST: "highest",
43
29
  };
44
30
  const MODEL = {
45
31
  // Anthropic
32
+ FABLE: "claude-fable-5",
46
33
  OPUS: "claude-opus-4-8",
47
- SONNET: "claude-sonnet-4-6",
34
+ SONNET: "claude-sonnet-5",
48
35
  HAIKU: "claude-haiku-4-5",
49
- FABLE: "claude-fable-5",
50
36
  MYTHOS: "claude-mythos-5",
51
37
  // Google
52
38
  GEMINI_FLASH: "gemini-3.5-flash",
53
39
  GEMINI_FLASH_LITE: "gemini-3.1-flash-lite",
54
40
  GEMINI_PRO: "gemini-3.1-pro-preview",
55
41
  // OpenAI
42
+ SOL: "gpt-5.6-sol",
43
+ TERRA: "gpt-5.6-terra",
44
+ LUNA: "gpt-5.6-luna",
45
+ /** @deprecated use MODEL.SOL (gpt-5.6-sol) */
56
46
  GPT: "gpt-5.5",
47
+ /** @deprecated use MODEL.TERRA (gpt-5.6-terra) */
57
48
  GPT_MINI: "gpt-5.4-mini",
49
+ /** @deprecated use MODEL.LUNA (gpt-5.6-luna) */
58
50
  GPT_NANO: "gpt-5.4-nano",
59
51
  // xAI
60
52
  GROK: "grok-latest",
53
+ // OpenRouter (provider-prefixed routes; traversed by the OpenRouter hot test)
54
+ OPENROUTER: {
55
+ GLM: "z-ai/glm-5.2",
56
+ LUNA: "openai/gpt-5.6-luna",
57
+ SONNET: "anthropic/claude-sonnet-5",
58
+ },
61
59
  };
62
60
  const GOOGLE_PROVIDER = {
63
61
  // https://ai.google.dev/gemini-api/docs/models
62
+ DEFAULT: MODEL.GEMINI_FLASH,
63
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.GOOGLE.DEFAULT, or pick a specific model from MODEL.*. */
64
64
  MODEL: {
65
- DEFAULT: FIRST_CLASS_PROVIDER.GOOGLE.DEFAULT,
66
- LARGE: FIRST_CLASS_PROVIDER.GOOGLE.LARGE,
67
- SMALL: FIRST_CLASS_PROVIDER.GOOGLE.SMALL,
68
- TINY: FIRST_CLASS_PROVIDER.GOOGLE.TINY,
65
+ DEFAULT: "gemini-3.1-pro-preview",
66
+ LARGE: "gemini-3.1-pro-preview",
67
+ SMALL: "gemini-3.5-flash",
68
+ TINY: "gemini-3.1-flash-lite",
69
69
  },
70
70
  MODEL_MATCH_WORDS: ["gemini", "google"],
71
71
  NAME: "google",
@@ -77,6 +77,10 @@ const GOOGLE_PROVIDER = {
77
77
  const PROVIDER = {
78
78
  // https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html
79
79
  BEDROCK: {
80
+ // Bedrock has no MODEL.* catalog entry yet; keep the literal default id.
81
+ // nova-pro is the Amazon-native model that reliably does tools+structured.
82
+ DEFAULT: "amazon.nova-pro-v1:0",
83
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.BEDROCK.DEFAULT. */
80
84
  MODEL: {
81
85
  DEFAULT: "amazon.nova-lite-v1:0",
82
86
  LARGE: "amazon.nova-pro-v1:0",
@@ -97,22 +101,26 @@ const PROVIDER = {
97
101
  },
98
102
  ANTHROPIC: {
99
103
  // https://docs.anthropic.com/en/docs/about-claude/models/overview
104
+ DEFAULT: MODEL.SONNET,
100
105
  MAX_TOKENS: {
101
106
  // Non-streaming ceiling: responses above ~16K output tokens risk HTTP
102
107
  // timeouts; streaming requests resolve to the model maximum instead
103
108
  // (see util/maxOutputTokens.ts)
104
109
  DEFAULT: 16384,
105
110
  },
111
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.ANTHROPIC.DEFAULT, or pick a specific model from MODEL.*. */
106
112
  MODEL: {
107
- DEFAULT: FIRST_CLASS_PROVIDER.ANTHROPIC.DEFAULT,
108
- LARGE: FIRST_CLASS_PROVIDER.ANTHROPIC.LARGE,
109
- SMALL: FIRST_CLASS_PROVIDER.ANTHROPIC.SMALL,
110
- TINY: FIRST_CLASS_PROVIDER.ANTHROPIC.TINY,
113
+ DEFAULT: "claude-sonnet-4-6",
114
+ LARGE: "claude-opus-4-8",
115
+ SMALL: "claude-sonnet-4-6",
116
+ TINY: "claude-haiku-4-5",
111
117
  },
112
118
  MODEL_MATCH_WORDS: [
113
119
  "anthropic",
114
120
  "claude",
121
+ "fable",
115
122
  "haiku",
123
+ "mythos",
116
124
  "opus",
117
125
  "sonnet",
118
126
  ],
@@ -135,21 +143,25 @@ const PROVIDER = {
135
143
  GOOGLE: GOOGLE_PROVIDER,
136
144
  OPENAI: {
137
145
  // https://platform.openai.com/docs/models
146
+ DEFAULT: MODEL.SOL,
147
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.OPENAI.DEFAULT, or pick a specific model from MODEL.*. */
138
148
  MODEL: {
139
- DEFAULT: FIRST_CLASS_PROVIDER.OPENAI.DEFAULT,
140
- LARGE: FIRST_CLASS_PROVIDER.OPENAI.LARGE,
141
- SMALL: FIRST_CLASS_PROVIDER.OPENAI.SMALL,
142
- TINY: FIRST_CLASS_PROVIDER.OPENAI.TINY,
149
+ DEFAULT: "gpt-5.4",
150
+ LARGE: "gpt-5.5",
151
+ SMALL: "gpt-5.4-mini",
152
+ TINY: "gpt-5.4-nano",
143
153
  },
144
- MODEL_MATCH_WORDS: ["openai", "gpt", /^o\d/],
154
+ MODEL_MATCH_WORDS: ["gpt", "luna", "openai", "sol", "terra", /^o\d/],
145
155
  NAME: "openai",
146
156
  },
147
157
  OPENROUTER: {
158
+ DEFAULT: MODEL.OPENROUTER.SONNET,
159
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.OPENROUTER.DEFAULT, or pick a specific route from MODEL.OPENROUTER.*. */
148
160
  MODEL: {
149
- DEFAULT: `anthropic/${FIRST_CLASS_PROVIDER.ANTHROPIC.DEFAULT}`,
150
- LARGE: `anthropic/${FIRST_CLASS_PROVIDER.ANTHROPIC.LARGE}`,
151
- SMALL: `anthropic/${FIRST_CLASS_PROVIDER.ANTHROPIC.SMALL}`,
152
- TINY: `anthropic/${FIRST_CLASS_PROVIDER.ANTHROPIC.TINY}`,
161
+ DEFAULT: "anthropic/claude-sonnet-4-6",
162
+ LARGE: "anthropic/claude-opus-4-8",
163
+ SMALL: "anthropic/claude-sonnet-4-6",
164
+ TINY: "anthropic/claude-haiku-4-5",
153
165
  },
154
166
  MODEL_MATCH_WORDS: ["openrouter"],
155
167
  NAME: "openrouter",
@@ -164,11 +176,13 @@ const PROVIDER = {
164
176
  // https://docs.x.ai/docs/models
165
177
  API_KEY: "XAI_API_KEY",
166
178
  BASE_URL: "https://api.x.ai/v1",
179
+ DEFAULT: MODEL.GROK,
180
+ /** @deprecated Size tiers are retired in 2.0. Use PROVIDER.XAI.DEFAULT, or pick a specific model from MODEL.*. */
167
181
  MODEL: {
168
- DEFAULT: FIRST_CLASS_PROVIDER.XAI.DEFAULT,
169
- LARGE: FIRST_CLASS_PROVIDER.XAI.LARGE,
170
- SMALL: FIRST_CLASS_PROVIDER.XAI.SMALL,
171
- TINY: FIRST_CLASS_PROVIDER.XAI.TINY,
182
+ DEFAULT: "grok-latest",
183
+ LARGE: "grok-latest",
184
+ SMALL: "grok-4-1-fast-reasoning",
185
+ TINY: "grok-4-1-fast-non-reasoning",
172
186
  },
173
187
  MODEL_MATCH_WORDS: ["grok", "xai"],
174
188
  NAME: "xai",
@@ -176,6 +190,7 @@ const PROVIDER = {
176
190
  };
177
191
  // Last: Defaults
178
192
  const DEFAULT = {
193
+ /** @deprecated Size tiers are retired in 2.0. Use DEFAULT.PROVIDER.DEFAULT, or pick a specific model from MODEL.*. */
179
194
  MODEL: {
180
195
  BASE: PROVIDER.OPENAI.MODEL.DEFAULT,
181
196
  LARGE: PROVIDER.OPENAI.MODEL.LARGE,
@@ -184,6 +199,10 @@ const DEFAULT = {
184
199
  },
185
200
  PROVIDER: PROVIDER.OPENAI,
186
201
  };
202
+ /**
203
+ * @deprecated Size-tier catalogs are retired in 2.0. Pick specific models from
204
+ * MODEL.* (grouped by provider via MODEL_MATCH_WORDS / determineModelProvider).
205
+ */
187
206
  // Only include "first class" models, not OpenRouter or other proxy services
188
207
  const ALL = {
189
208
  BASE: [
@@ -236,6 +255,7 @@ var constants = /*#__PURE__*/Object.freeze({
236
255
  __proto__: null,
237
256
  ALL: ALL,
238
257
  DEFAULT: DEFAULT,
258
+ EFFORT: EFFORT,
239
259
  MODEL: MODEL,
240
260
  PROVIDER: PROVIDER
241
261
  });
@@ -243,7 +263,7 @@ var constants = /*#__PURE__*/Object.freeze({
243
263
  function determineModelProvider(input) {
244
264
  if (!input) {
245
265
  return {
246
- model: DEFAULT.PROVIDER.MODEL.DEFAULT,
266
+ model: DEFAULT.PROVIDER.DEFAULT,
247
267
  provider: DEFAULT.PROVIDER.NAME,
248
268
  };
249
269
  }
@@ -266,85 +286,42 @@ function determineModelProvider(input) {
266
286
  // Check if input is a provider name
267
287
  if (input === PROVIDER.BEDROCK.NAME) {
268
288
  return {
269
- model: PROVIDER.BEDROCK.MODEL.DEFAULT,
289
+ model: PROVIDER.BEDROCK.DEFAULT,
270
290
  provider: PROVIDER.BEDROCK.NAME,
271
291
  };
272
292
  }
273
293
  if (input === PROVIDER.ANTHROPIC.NAME) {
274
294
  return {
275
- model: PROVIDER.ANTHROPIC.MODEL.DEFAULT,
295
+ model: PROVIDER.ANTHROPIC.DEFAULT,
276
296
  provider: PROVIDER.ANTHROPIC.NAME,
277
297
  };
278
298
  }
279
299
  if (input === PROVIDER.GOOGLE.NAME || input === "gemini") {
280
300
  return {
281
- model: PROVIDER.GOOGLE.MODEL.DEFAULT,
301
+ model: PROVIDER.GOOGLE.DEFAULT,
282
302
  provider: PROVIDER.GOOGLE.NAME,
283
303
  };
284
304
  }
285
305
  if (input === PROVIDER.OPENAI.NAME) {
286
306
  return {
287
- model: PROVIDER.OPENAI.MODEL.DEFAULT,
307
+ model: PROVIDER.OPENAI.DEFAULT,
288
308
  provider: PROVIDER.OPENAI.NAME,
289
309
  };
290
310
  }
291
311
  if (input === PROVIDER.OPENROUTER.NAME) {
292
312
  return {
293
- model: PROVIDER.OPENROUTER.MODEL.DEFAULT,
313
+ model: PROVIDER.OPENROUTER.DEFAULT,
294
314
  provider: PROVIDER.OPENROUTER.NAME,
295
315
  };
296
316
  }
297
317
  if (input === PROVIDER.XAI.NAME) {
298
318
  return {
299
- model: PROVIDER.XAI.MODEL.DEFAULT,
319
+ model: PROVIDER.XAI.DEFAULT,
300
320
  provider: PROVIDER.XAI.NAME,
301
321
  };
302
322
  }
303
- // Check if input matches an Anthropic model exactly
304
- for (const [, modelValue] of Object.entries(PROVIDER.ANTHROPIC.MODEL)) {
305
- if (input === modelValue) {
306
- return {
307
- model: input,
308
- provider: PROVIDER.ANTHROPIC.NAME,
309
- };
310
- }
311
- }
312
- // Check if input matches a Gemini model exactly
313
- for (const [, modelValue] of Object.entries(PROVIDER.GOOGLE.MODEL)) {
314
- if (input === modelValue) {
315
- return {
316
- model: input,
317
- provider: PROVIDER.GOOGLE.NAME,
318
- };
319
- }
320
- }
321
- // Check if input matches an OpenAI model exactly
322
- for (const [, modelValue] of Object.entries(PROVIDER.OPENAI.MODEL)) {
323
- if (input === modelValue) {
324
- return {
325
- model: input,
326
- provider: PROVIDER.OPENAI.NAME,
327
- };
328
- }
329
- }
330
- // Check if input matches an OpenRouter model exactly
331
- for (const [, modelValue] of Object.entries(PROVIDER.OPENROUTER.MODEL)) {
332
- if (input === modelValue) {
333
- return {
334
- model: input,
335
- provider: PROVIDER.OPENROUTER.NAME,
336
- };
337
- }
338
- }
339
- // Check if input matches an xAI model exactly
340
- for (const [, modelValue] of Object.entries(PROVIDER.XAI.MODEL)) {
341
- if (input === modelValue) {
342
- return {
343
- model: input,
344
- provider: PROVIDER.XAI.NAME,
345
- };
346
- }
347
- }
323
+ // Exact model ids are classified by the "/" rule and MODEL_MATCH_WORDS below,
324
+ // so no per-provider id catalog is consulted here.
348
325
  // Assume OpenRouter for models containing "/" (e.g., "openai/gpt-4", "anthropic/claude-3-opus")
349
326
  // This check must come before match words so that "openai/gpt-4" is not matched by "openai" keyword
350
327
  if (input.includes("/")) {
@@ -461,6 +438,125 @@ class BaseProviderAdapter {
461
438
  }
462
439
  }
463
440
 
441
+ /**
442
+ * Per-provider translation of the provider-neutral {@link LlmEffort} scale.
443
+ *
444
+ * The neutral enum (lowest → low → medium → high → highest) is a relative
445
+ * five-point scale. Each table below maps it onto the target provider's native
446
+ * effort control, keeping `medium`/`high` semantically aligned across providers
447
+ * and using each provider's extra bottom (`minimal`) or top (`xhigh`/`max`)
448
+ * rung where one exists. Providers with fewer levels collapse the ends and mark
449
+ * the result `papered`. A single `effort` value is therefore safe to reuse
450
+ * across providers and fallback chains.
451
+ */
452
+ /** Consistent debug message for a papered-over effort level. */
453
+ function paperedEffortMessage({ model, provider, requested, value, }) {
454
+ return `[llm] effort '${requested}' has no distinct tier on ${provider} model '${model}'; using '${value}'`;
455
+ }
456
+ // OpenAI Responses API `reasoning.effort`.
457
+ // Full ladder: minimal | low | medium | high | xhigh (plus `none`). Availability
458
+ // is not uniform across the gpt-5 line:
459
+ // - `xhigh` was introduced at gpt-5.2 and has been continuous since, so it is
460
+ // safe for our gpt-5.4 default and everything newer.
461
+ // - `minimal` shipped on gpt-5/5.1, was dropped at gpt-5.2, and returned on
462
+ // the current line; because that history is non-monotonic we only trust it
463
+ // from gpt-5.4 (our default floor) onward.
464
+ // Outside those windows (older gpt-5, o-series) the extreme rung is clamped and
465
+ // the mapping reports `papered: true`.
466
+ const OPENAI_EFFORT = {
467
+ [EFFORT.LOWEST]: "minimal",
468
+ [EFFORT.LOW]: "low",
469
+ [EFFORT.MEDIUM]: "medium",
470
+ [EFFORT.HIGH]: "high",
471
+ [EFFORT.HIGHEST]: "xhigh",
472
+ };
473
+ function openAiGptVersion(model) {
474
+ const match = model.match(/^gpt-(\d+)(?:\.(\d+))?/);
475
+ if (!match)
476
+ return null;
477
+ return { major: Number(match[1]), minor: match[2] ? Number(match[2]) : 0 };
478
+ }
479
+ function atLeast(version, major, minor) {
480
+ if (!version)
481
+ return false;
482
+ return (version.major > major || (version.major === major && version.minor >= minor));
483
+ }
484
+ function toOpenAiEffort(effort, { model }) {
485
+ const native = OPENAI_EFFORT[effort];
486
+ const version = openAiGptVersion(model);
487
+ // `minimal` only from gpt-5.4 (non-monotonic history; absent on o-series)
488
+ if (native === "minimal" && !atLeast(version, 5, 4)) {
489
+ return { papered: true, value: "low" };
490
+ }
491
+ // `xhigh` from gpt-5.2 onward (absent on older gpt-5 and o-series)
492
+ if (native === "xhigh" && !atLeast(version, 5, 2)) {
493
+ return { papered: true, value: "high" };
494
+ }
495
+ return { papered: false, value: native };
496
+ }
497
+ // xAI Grok `reasoning_effort` — low | medium | high. No sub-low or top rung, so
498
+ // `lowest` collapses onto `low` and `highest` onto `high`.
499
+ const XAI_EFFORT = {
500
+ [EFFORT.LOWEST]: { papered: true, value: "low" },
501
+ [EFFORT.LOW]: { papered: false, value: "low" },
502
+ [EFFORT.MEDIUM]: { papered: false, value: "medium" },
503
+ [EFFORT.HIGH]: { papered: false, value: "high" },
504
+ [EFFORT.HIGHEST]: { papered: true, value: "high" },
505
+ };
506
+ function toXaiEffort(effort) {
507
+ return XAI_EFFORT[effort];
508
+ }
509
+ // Anthropic `output_config.effort` — low | medium | high | xhigh | max. No
510
+ // sub-low rung, so `lowest` collapses onto `low`; `highest` reaches `max`.
511
+ const ANTHROPIC_EFFORT = {
512
+ [EFFORT.LOWEST]: { papered: true, value: "low" },
513
+ [EFFORT.LOW]: { papered: false, value: "low" },
514
+ [EFFORT.MEDIUM]: { papered: false, value: "medium" },
515
+ [EFFORT.HIGH]: { papered: false, value: "high" },
516
+ [EFFORT.HIGHEST]: { papered: false, value: "max" },
517
+ };
518
+ function toAnthropicEffort(effort) {
519
+ return ANTHROPIC_EFFORT[effort];
520
+ }
521
+ // Gemini 3.x `thinkingConfig.thinkingLevel` — MINIMAL | LOW | MEDIUM | HIGH. No
522
+ // top rung above HIGH, so `highest` collapses onto HIGH.
523
+ const GEMINI_THINKING_LEVEL = {
524
+ [EFFORT.LOWEST]: { papered: false, value: "MINIMAL" },
525
+ [EFFORT.LOW]: { papered: false, value: "LOW" },
526
+ [EFFORT.MEDIUM]: { papered: false, value: "MEDIUM" },
527
+ [EFFORT.HIGH]: { papered: false, value: "HIGH" },
528
+ [EFFORT.HIGHEST]: { papered: true, value: "HIGH" },
529
+ };
530
+ function toGeminiThinkingLevel(effort) {
531
+ return GEMINI_THINKING_LEVEL[effort];
532
+ }
533
+ // Gemini 2.5 `thinkingConfig.thinkingBudget` — every tier is a distinct token
534
+ // budget, so nothing is papered over. Floor (512) clears every 2.5 minimum;
535
+ // ceiling (24,576) is valid across 2.5 Pro (max 32,768) and Flash (max 24,576).
536
+ const GEMINI_THINKING_BUDGET = {
537
+ [EFFORT.LOWEST]: 512,
538
+ [EFFORT.LOW]: 4096,
539
+ [EFFORT.MEDIUM]: 8192,
540
+ [EFFORT.HIGH]: 16384,
541
+ [EFFORT.HIGHEST]: 24576,
542
+ };
543
+ function toGeminiThinkingBudget(effort) {
544
+ return { papered: false, value: GEMINI_THINKING_BUDGET[effort] };
545
+ }
546
+ // OpenRouter `reasoning.effort` — accepts the full minimal..xhigh ladder and
547
+ // maps to the routed provider's nearest supported level itself, so nothing is
548
+ // papered here.
549
+ const OPENROUTER_EFFORT = {
550
+ [EFFORT.LOWEST]: "minimal",
551
+ [EFFORT.LOW]: "low",
552
+ [EFFORT.MEDIUM]: "medium",
553
+ [EFFORT.HIGH]: "high",
554
+ [EFFORT.HIGHEST]: "xhigh",
555
+ };
556
+ function toOpenRouterEffort(effort) {
557
+ return { papered: false, value: OPENROUTER_EFFORT[effort] };
558
+ }
559
+
464
560
  // Enums
465
561
  var LlmMessageRole;
466
562
  (function (LlmMessageRole) {
@@ -1294,6 +1390,43 @@ async function* parseSseStream(body, { doneSentinel = DEFAULT_DONE_SENTINEL } =
1294
1390
  }
1295
1391
  }
1296
1392
 
1393
+ const UNKNOWN = "unknown";
1394
+ /**
1395
+ * Tally loop totals onto the root logger's report session so handlers
1396
+ * (express, lambda) include llm activity in the report emitted at teardown.
1397
+ * Silently no-ops outside an active session or when the logger predates
1398
+ * tally support.
1399
+ */
1400
+ function tallyOperate({ toolCallNames = [], turns, usage = [], }) {
1401
+ if (typeof log$2.tally !== "function")
1402
+ return;
1403
+ const llm = {
1404
+ operates: 1,
1405
+ toolCalls: toolCallNames.length,
1406
+ turns,
1407
+ };
1408
+ if (toolCallNames.length > 0) {
1409
+ const tools = {};
1410
+ for (const name of toolCallNames) {
1411
+ tools[name] = (tools[name] ?? 0) + 1;
1412
+ }
1413
+ llm.tools = tools;
1414
+ }
1415
+ if (usage.length > 0) {
1416
+ const usageByModel = {};
1417
+ for (const item of usage) {
1418
+ const key = [item.provider, item.model].filter(Boolean).join(":") || UNKNOWN;
1419
+ usageByModel[key] ?? (usageByModel[key] = { input: 0, output: 0, reasoning: 0, total: 0 });
1420
+ usageByModel[key].input += item.input;
1421
+ usageByModel[key].output += item.output;
1422
+ usageByModel[key].reasoning += item.reasoning;
1423
+ usageByModel[key].total += item.total;
1424
+ }
1425
+ llm.usage = usageByModel;
1426
+ }
1427
+ log$2.tally({ llm });
1428
+ }
1429
+
1297
1430
  /**
1298
1431
  * Helper function to safely call a function that might throw
1299
1432
  * @param fn Function to call safely
@@ -1454,6 +1587,22 @@ function isTransientNetworkError(error) {
1454
1587
  // Constants
1455
1588
  //
1456
1589
  const STRUCTURED_OUTPUT_TOOL_NAME$3 = "structured_output";
1590
+ /**
1591
+ * Whether `output_config.effort` may be sent for this model. Anthropic added
1592
+ * the effort control on the Claude 4.5 line and up (the 5 family); older models
1593
+ * reject it. Parsing major/minor avoids matching a minor "5" in legacy ids
1594
+ * like `claude-3-5-sonnet`.
1595
+ */
1596
+ function supportsAnthropicEffort(model) {
1597
+ const match = model.match(/claude-[a-z]+-(\d+)(?:-(\d+))?/);
1598
+ if (!match)
1599
+ return false;
1600
+ const major = Number(match[1]);
1601
+ const minor = match[2] !== undefined ? Number(match[2]) : 0;
1602
+ if (major >= 5)
1603
+ return true;
1604
+ return major === 4 && minor >= 5;
1605
+ }
1457
1606
  const STRUCTURED_OUTPUT_NON_PARSE_STOP_REASONS = new Set([
1458
1607
  "refusal",
1459
1608
  "max_tokens",
@@ -1719,7 +1868,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1719
1868
  constructor() {
1720
1869
  super(...arguments);
1721
1870
  this.name = PROVIDER.ANTHROPIC.NAME;
1722
- this.defaultModel = PROVIDER.ANTHROPIC.MODEL.DEFAULT;
1871
+ this.defaultModel = PROVIDER.ANTHROPIC.DEFAULT;
1723
1872
  // Session-level cache of models observed to reject `temperature` at runtime.
1724
1873
  // Populated by executeRequest on 400 errors so repeat calls skip the param.
1725
1874
  this.runtimeNoTemperatureModels = new Set();
@@ -1859,6 +2008,24 @@ class AnthropicAdapter extends BaseProviderAdapter {
1859
2008
  if (request.providerOptions) {
1860
2009
  Object.assign(anthropicRequest, request.providerOptions);
1861
2010
  }
2011
+ // Normalized reasoning effort -> output_config.effort (merged so a format
2012
+ // config above survives). First-class effort wins over providerOptions.
2013
+ if (request.effort &&
2014
+ supportsAnthropicEffort(anthropicRequest.model)) {
2015
+ const mapping = toAnthropicEffort(request.effort);
2016
+ if (mapping.papered) {
2017
+ log$2.debug(paperedEffortMessage({
2018
+ model: anthropicRequest.model,
2019
+ provider: this.name,
2020
+ requested: request.effort,
2021
+ value: mapping.value,
2022
+ }));
2023
+ }
2024
+ anthropicRequest.output_config = {
2025
+ ...anthropicRequest.output_config,
2026
+ effort: mapping.value,
2027
+ };
2028
+ }
1862
2029
  // First-class temperature takes precedence over providerOptions
1863
2030
  if (request.temperature !== undefined) {
1864
2031
  anthropicRequest.temperature = request.temperature;
@@ -1953,9 +2120,13 @@ class AnthropicAdapter extends BaseProviderAdapter {
1953
2120
  */
1954
2121
  toFallbackStructuredOutputRequest(request) {
1955
2122
  const { output_config, ...rest } = request;
1956
- if (!output_config)
2123
+ if (!output_config?.format)
1957
2124
  return request;
1958
2125
  const fallbackRequest = { ...rest };
2126
+ // Preserve an effort setting; only the structured-output format falls back.
2127
+ if (output_config.effort) {
2128
+ fallbackRequest.output_config = { effort: output_config.effort };
2129
+ }
1959
2130
  const fakeTool = {
1960
2131
  name: STRUCTURED_OUTPUT_TOOL_NAME$3,
1961
2132
  description: "Output a structured JSON object, " +
@@ -2399,7 +2570,7 @@ class BedrockAdapter extends BaseProviderAdapter {
2399
2570
  constructor() {
2400
2571
  super(...arguments);
2401
2572
  this.name = PROVIDER.BEDROCK.NAME;
2402
- this.defaultModel = PROVIDER.BEDROCK.MODEL.DEFAULT;
2573
+ this.defaultModel = PROVIDER.BEDROCK.DEFAULT;
2403
2574
  this._modelsFallbackToStructuredOutputTool = new Set();
2404
2575
  this._modelsWithoutTemperature = new Set();
2405
2576
  }
@@ -2905,6 +3076,11 @@ const STRUCTURED_OUTPUT_TOOL_NAME$1 = "structured_output";
2905
3076
  // (including 2.5 thinking) do not support the combo and fall back to the
2906
3077
  // legacy `structured_output` fake-tool emulation.
2907
3078
  const GEMINI_3_PATTERN = /^gemini-3/;
3079
+ // Reasoning-effort control differs by generation: Gemini 3.x takes the
3080
+ // `thinkingLevel` enum, Gemini 2.5 takes an integer `thinkingBudget`. Sending
3081
+ // the wrong one errors, and models outside these families have no thinking
3082
+ // control, so effort is only applied when one of these matches.
3083
+ const GEMINI_25_PATTERN = /^gemini-2\.5/;
2908
3084
  /**
2909
3085
  * Detect 4xx errors that indicate the model itself does not support the
2910
3086
  * `responseJsonSchema` + tools combo. Triggers the runtime fallback to the
@@ -2951,7 +3127,7 @@ class GoogleAdapter extends BaseProviderAdapter {
2951
3127
  constructor() {
2952
3128
  super(...arguments);
2953
3129
  this.name = PROVIDER.GOOGLE.NAME;
2954
- this.defaultModel = PROVIDER.GOOGLE.MODEL.DEFAULT;
3130
+ this.defaultModel = PROVIDER.GOOGLE.DEFAULT;
2955
3131
  // Session-level cache of Gemini 3 models observed to reject the native
2956
3132
  // `responseJsonSchema` + tools combo. When a model is in this set,
2957
3133
  // buildRequest engages the legacy fake-tool path instead.
@@ -3079,6 +3255,42 @@ class GoogleAdapter extends BaseProviderAdapter {
3079
3255
  ...request.providerOptions,
3080
3256
  };
3081
3257
  }
3258
+ // Normalized reasoning effort -> thinkingConfig. Gemini 3.x uses the
3259
+ // thinkingLevel enum; 2.5 uses an integer thinkingBudget. Merged so a
3260
+ // providerOptions.thinkingConfig survives; first-class effort wins.
3261
+ if (request.effort) {
3262
+ const model = geminiRequest.model;
3263
+ let thinkingConfig;
3264
+ let papered = false;
3265
+ let value;
3266
+ if (GEMINI_3_PATTERN.test(model)) {
3267
+ const mapping = toGeminiThinkingLevel(request.effort);
3268
+ ({ papered, value } = mapping);
3269
+ thinkingConfig = { thinkingLevel: mapping.value };
3270
+ }
3271
+ else if (GEMINI_25_PATTERN.test(model)) {
3272
+ const mapping = toGeminiThinkingBudget(request.effort);
3273
+ ({ papered, value } = mapping);
3274
+ thinkingConfig = { thinkingBudget: mapping.value };
3275
+ }
3276
+ if (thinkingConfig) {
3277
+ if (papered) {
3278
+ log$2.debug(paperedEffortMessage({
3279
+ model,
3280
+ provider: this.name,
3281
+ requested: request.effort,
3282
+ value: value,
3283
+ }));
3284
+ }
3285
+ geminiRequest.config = {
3286
+ ...geminiRequest.config,
3287
+ thinkingConfig: {
3288
+ ...geminiRequest.config?.thinkingConfig,
3289
+ ...thinkingConfig,
3290
+ },
3291
+ };
3292
+ }
3293
+ }
3082
3294
  // First-class temperature takes precedence over providerOptions
3083
3295
  if (request.temperature !== undefined) {
3084
3296
  geminiRequest.config = {
@@ -3998,7 +4210,7 @@ class OpenAiAdapter extends BaseProviderAdapter {
3998
4210
  constructor() {
3999
4211
  super(...arguments);
4000
4212
  this.name = PROVIDER.OPENAI.NAME;
4001
- this.defaultModel = PROVIDER.OPENAI.MODEL.DEFAULT;
4213
+ this.defaultModel = PROVIDER.OPENAI.DEFAULT;
4002
4214
  // Session-level cache of models observed to reject `temperature` at runtime.
4003
4215
  // Populated by executeRequest on 400 errors so repeat calls skip the param.
4004
4216
  this.runtimeNoTemperatureModels = new Set();
@@ -4014,6 +4226,14 @@ class OpenAiAdapter extends BaseProviderAdapter {
4014
4226
  return false;
4015
4227
  return !MODELS_WITHOUT_TEMPERATURE$1.some((pattern) => pattern.test(model));
4016
4228
  }
4229
+ /** Whether `reasoning.effort` may be sent for this model. Overridden by xAI. */
4230
+ supportsReasoningEffort(model) {
4231
+ return isReasoningModel(model);
4232
+ }
4233
+ /** Translate a normalized effort to this provider's `reasoning.effort` value. */
4234
+ mapReasoningEffort(effort, model) {
4235
+ return toOpenAiEffort(effort, { model });
4236
+ }
4017
4237
  //
4018
4238
  // Request Building
4019
4239
  //
@@ -4052,6 +4272,24 @@ class OpenAiAdapter extends BaseProviderAdapter {
4052
4272
  if (request.providerOptions) {
4053
4273
  Object.assign(openaiRequest, request.providerOptions);
4054
4274
  }
4275
+ // Normalized reasoning effort -> reasoning.effort (merged so the
4276
+ // summary:auto above survives). First-class effort wins over providerOptions.
4277
+ if (request.effort && this.supportsReasoningEffort(model)) {
4278
+ const mapping = this.mapReasoningEffort(request.effort, model);
4279
+ if (mapping.papered) {
4280
+ log$2.debug(paperedEffortMessage({
4281
+ model,
4282
+ provider: this.name,
4283
+ requested: request.effort,
4284
+ value: mapping.value,
4285
+ }));
4286
+ }
4287
+ const existingReasoning = openaiRequest.reasoning ?? {};
4288
+ openaiRequest.reasoning = {
4289
+ ...existingReasoning,
4290
+ effort: mapping.value,
4291
+ };
4292
+ }
4055
4293
  // First-class temperature takes precedence over providerOptions
4056
4294
  if (request.temperature !== undefined) {
4057
4295
  openaiRequest.temperature = request.temperature;
@@ -4646,7 +4884,7 @@ class OpenRouterAdapter extends BaseProviderAdapter {
4646
4884
  constructor() {
4647
4885
  super(...arguments);
4648
4886
  this.name = PROVIDER.OPENROUTER.NAME;
4649
- this.defaultModel = PROVIDER.OPENROUTER.MODEL.DEFAULT;
4887
+ this.defaultModel = PROVIDER.OPENROUTER.DEFAULT;
4650
4888
  // Session-level cache of models observed to reject native
4651
4889
  // `response_format: json_schema`. When a model is in this set, buildRequest
4652
4890
  // engages the legacy fake-tool path instead of native structured output.
@@ -4739,6 +4977,15 @@ class OpenRouterAdapter extends BaseProviderAdapter {
4739
4977
  if (request.providerOptions) {
4740
4978
  Object.assign(openRouterRequest, request.providerOptions);
4741
4979
  }
4980
+ // Normalized reasoning effort -> reasoning.effort. OpenRouter accepts the
4981
+ // full ladder and maps to the routed provider's nearest supported level.
4982
+ // First-class effort wins over providerOptions.
4983
+ if (request.effort) {
4984
+ openRouterRequest.reasoning = {
4985
+ ...openRouterRequest.reasoning,
4986
+ effort: toOpenRouterEffort(request.effort).value,
4987
+ };
4988
+ }
4742
4989
  // First-class temperature takes precedence over providerOptions
4743
4990
  if (request.temperature !== undefined) {
4744
4991
  openRouterRequest.temperature =
@@ -5357,8 +5604,21 @@ class XaiAdapter extends OpenAiAdapter {
5357
5604
  super(...arguments);
5358
5605
  // @ts-expect-error Narrowing override: xAI name differs from parent's literal "openai"
5359
5606
  this.name = PROVIDER.XAI.NAME;
5360
- // @ts-expect-error Narrowing override: xAI default model differs from parent's literal
5361
- this.defaultModel = PROVIDER.XAI.MODEL.DEFAULT;
5607
+ this.defaultModel = PROVIDER.XAI.DEFAULT;
5608
+ }
5609
+ /**
5610
+ * Grok gates reasoning effort by model, not by the OpenAI `gpt-*`/`o*`
5611
+ * patterns. Only explicit `*-reasoning` models accept `reasoning_effort`;
5612
+ * bare grok-4 reasons implicitly and rejects it, so we stay conservative and
5613
+ * only opt in models whose name advertises reasoning.
5614
+ */
5615
+ supportsReasoningEffort(model) {
5616
+ if (/non-reasoning/.test(model))
5617
+ return false;
5618
+ return /reasoning/.test(model);
5619
+ }
5620
+ mapReasoningEffort(effort) {
5621
+ return toXaiEffort(effort);
5362
5622
  }
5363
5623
  classifyError(error) {
5364
5624
  if (isTransientIngestError(error)) {
@@ -6635,6 +6895,7 @@ class OperateLoop {
6635
6895
  }
6636
6896
  // Rebuild request with updated history for next turn
6637
6897
  request = {
6898
+ effort: options.effort,
6638
6899
  format: state.formattedFormat,
6639
6900
  instructions: options.instructions,
6640
6901
  messages: state.currentInput,
@@ -6652,6 +6913,11 @@ class OperateLoop {
6652
6913
  metrics: usageToLlmObsMetrics(response.usage),
6653
6914
  outputData: response.content,
6654
6915
  });
6916
+ tallyOperate({
6917
+ toolCallNames: state.toolCallNames,
6918
+ turns: state.currentTurn,
6919
+ usage: response.usage,
6920
+ });
6655
6921
  await emitProgress({
6656
6922
  event: {
6657
6923
  content: response.content,
@@ -6721,6 +6987,7 @@ class OperateLoop {
6721
6987
  formattedTools,
6722
6988
  maxTurns,
6723
6989
  responseBuilder,
6990
+ toolCallNames: [],
6724
6991
  toolkit,
6725
6992
  };
6726
6993
  }
@@ -6732,6 +6999,7 @@ class OperateLoop {
6732
6999
  }
6733
7000
  buildInitialRequest(state, options) {
6734
7001
  return {
7002
+ effort: options.effort,
6735
7003
  format: state.formattedFormat,
6736
7004
  instructions: options.instructions,
6737
7005
  messages: state.currentInput,
@@ -6889,6 +7157,7 @@ class OperateLoop {
6889
7157
  this.appendResponseItemsToRequest(currentProviderRequest, responseItems);
6890
7158
  // Process each tool call
6891
7159
  for (const toolCall of toolCalls) {
7160
+ state.toolCallNames.push(toolCall.name);
6892
7161
  // Resolved once per call; never throws (undefined when tool has no message)
6893
7162
  const toolMessage = await state.toolkit.resolveMessage({
6894
7163
  arguments: toolCall.arguments,
@@ -7245,6 +7514,7 @@ class StreamLoop {
7245
7514
  }
7246
7515
  // Rebuild request with updated history for next turn
7247
7516
  request = {
7517
+ effort: options.effort,
7248
7518
  format: state.formattedFormat,
7249
7519
  instructions: options.instructions,
7250
7520
  messages: state.currentInput,
@@ -7262,6 +7532,11 @@ class StreamLoop {
7262
7532
  }
7263
7533
  }
7264
7534
  // Emit final done chunk with accumulated usage
7535
+ tallyOperate({
7536
+ toolCallNames: state.toolCallNames,
7537
+ turns: state.currentTurn,
7538
+ usage: state.usageItems,
7539
+ });
7265
7540
  yield {
7266
7541
  type: LlmStreamChunkType.Done,
7267
7542
  usage: state.usageItems,
@@ -7302,6 +7577,7 @@ class StreamLoop {
7302
7577
  formattedFormat,
7303
7578
  formattedTools,
7304
7579
  maxTurns,
7580
+ toolCallNames: [],
7305
7581
  toolkit,
7306
7582
  usageItems: [],
7307
7583
  };
@@ -7314,6 +7590,7 @@ class StreamLoop {
7314
7590
  }
7315
7591
  buildInitialRequest(state, options) {
7316
7592
  return {
7593
+ effort: options.effort,
7317
7594
  format: state.formattedFormat,
7318
7595
  instructions: options.instructions,
7319
7596
  messages: state.currentInput,
@@ -7484,6 +7761,7 @@ class StreamLoop {
7484
7761
  async *processToolCalls(toolCalls, state, context) {
7485
7762
  const log = getLogger$6();
7486
7763
  for (const toolCall of toolCalls) {
7764
+ state.toolCallNames.push(toolCall.name);
7487
7765
  // Resolved once per call; never throws (undefined when tool has no message)
7488
7766
  const toolMessage = await state.toolkit.resolveMessage({
7489
7767
  arguments: toolCall.arguments,
@@ -7876,7 +8154,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
7876
8154
 
7877
8155
  // Main class implementation
7878
8156
  class AnthropicProvider {
7879
- constructor(model = PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey } = {}) {
8157
+ constructor(model = PROVIDER.ANTHROPIC.DEFAULT, { apiKey } = {}) {
7880
8158
  this.log = getLogger$5();
7881
8159
  this.conversationHistory = [];
7882
8160
  this.model = model;
@@ -7984,7 +8262,7 @@ async function initializeClient$4({ region, } = {}) {
7984
8262
  }
7985
8263
 
7986
8264
  class BedrockProvider {
7987
- constructor(model = PROVIDER.BEDROCK.MODEL.DEFAULT, { region } = {}) {
8265
+ constructor(model = PROVIDER.BEDROCK.DEFAULT, { region } = {}) {
7988
8266
  this.log = getLogger$4();
7989
8267
  this.conversationHistory = [];
7990
8268
  this.model = model;
@@ -8227,7 +8505,7 @@ function prepareMessages$2(message, { data, placeholders } = {}) {
8227
8505
  }
8228
8506
 
8229
8507
  class GoogleProvider {
8230
- constructor(model = PROVIDER.GOOGLE.MODEL.DEFAULT, { apiKey } = {}) {
8508
+ constructor(model = PROVIDER.GOOGLE.DEFAULT, { apiKey } = {}) {
8231
8509
  this.log = getLogger$3();
8232
8510
  this.conversationHistory = [];
8233
8511
  this.model = model;
@@ -8429,7 +8707,7 @@ async function createTextCompletion(client, { messages, model, }) {
8429
8707
  }
8430
8708
 
8431
8709
  class OpenAiProvider {
8432
- constructor(model = PROVIDER.OPENAI.MODEL.DEFAULT, { apiKey } = {}) {
8710
+ constructor(model = PROVIDER.OPENAI.DEFAULT, { apiKey } = {}) {
8433
8711
  this.log = getLogger$2();
8434
8712
  this.conversationHistory = [];
8435
8713
  this.model = model;
@@ -8660,7 +8938,7 @@ async function initializeClient$1({ apiKey, } = {}) {
8660
8938
  }
8661
8939
  // Get default model from environment or constants
8662
8940
  function getDefaultModel() {
8663
- return process.env.OPENROUTER_MODEL || PROVIDER.OPENROUTER.MODEL.DEFAULT;
8941
+ return process.env.OPENROUTER_MODEL || PROVIDER.OPENROUTER.DEFAULT;
8664
8942
  }
8665
8943
  function formatSystemMessage(systemPrompt, { data, placeholders: placeholders$1 } = {}) {
8666
8944
  const content = placeholders$1?.system === false
@@ -8812,7 +9090,7 @@ async function initializeClient({ apiKey, } = {}) {
8812
9090
  }
8813
9091
 
8814
9092
  class XaiProvider {
8815
- constructor(model = PROVIDER.XAI.MODEL.DEFAULT, { apiKey } = {}) {
9093
+ constructor(model = PROVIDER.XAI.DEFAULT, { apiKey } = {}) {
8816
9094
  this.log = getLogger$2();
8817
9095
  this.conversationHistory = [];
8818
9096
  this.model = model;
@@ -8943,23 +9221,25 @@ class Llm {
8943
9221
  const { apiKey, model } = options;
8944
9222
  switch (providerName) {
8945
9223
  case PROVIDER.ANTHROPIC.NAME:
8946
- return new AnthropicProvider(model || PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey });
9224
+ return new AnthropicProvider(model || PROVIDER.ANTHROPIC.DEFAULT, {
9225
+ apiKey,
9226
+ });
8947
9227
  case PROVIDER.BEDROCK.NAME:
8948
- return new BedrockProvider(model || PROVIDER.BEDROCK.MODEL.DEFAULT);
9228
+ return new BedrockProvider(model || PROVIDER.BEDROCK.DEFAULT);
8949
9229
  case PROVIDER.GOOGLE.NAME:
8950
- return new GoogleProvider(model || PROVIDER.GOOGLE.MODEL.DEFAULT, {
9230
+ return new GoogleProvider(model || PROVIDER.GOOGLE.DEFAULT, {
8951
9231
  apiKey,
8952
9232
  });
8953
9233
  case PROVIDER.OPENAI.NAME:
8954
- return new OpenAiProvider(model || PROVIDER.OPENAI.MODEL.DEFAULT, {
9234
+ return new OpenAiProvider(model || PROVIDER.OPENAI.DEFAULT, {
8955
9235
  apiKey,
8956
9236
  });
8957
9237
  case PROVIDER.OPENROUTER.NAME:
8958
- return new OpenRouterProvider(model || PROVIDER.OPENROUTER.MODEL.DEFAULT, {
9238
+ return new OpenRouterProvider(model || PROVIDER.OPENROUTER.DEFAULT, {
8959
9239
  apiKey,
8960
9240
  });
8961
9241
  case PROVIDER.XAI.NAME:
8962
- return new XaiProvider(model || PROVIDER.XAI.MODEL.DEFAULT, {
9242
+ return new XaiProvider(model || PROVIDER.XAI.DEFAULT, {
8963
9243
  apiKey,
8964
9244
  });
8965
9245
  default: