@mastra/code-sdk 1.11.0 → 1.12.0-alpha.1

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 (55) hide show
  1. package/dist/acp/agent.d.ts.map +1 -1
  2. package/dist/acp/agent.js +6 -9
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/runtime.d.ts.map +1 -1
  5. package/dist/acp/runtime.js +3 -0
  6. package/dist/acp/runtime.js.map +1 -1
  7. package/dist/agent-connections/ownership.d.ts.map +1 -1
  8. package/dist/agent-connections/ownership.js +1 -1
  9. package/dist/agent-connections/ownership.js.map +1 -1
  10. package/dist/agent-connections/tools.d.ts.map +1 -1
  11. package/dist/agent-connections/tools.js +14 -1
  12. package/dist/agent-connections/tools.js.map +1 -1
  13. package/dist/agents/mastracode-gateway.d.ts.map +1 -1
  14. package/dist/agents/mastracode-gateway.js +3 -3
  15. package/dist/agents/mastracode-gateway.js.map +1 -1
  16. package/dist/agents/model.d.ts.map +1 -1
  17. package/dist/agents/model.js +4 -1
  18. package/dist/agents/model.js.map +1 -1
  19. package/dist/auth/account-rotation-processor.d.ts +4 -3
  20. package/dist/auth/account-rotation-processor.d.ts.map +1 -1
  21. package/dist/auth/account-rotation-processor.js +10 -29
  22. package/dist/auth/account-rotation-processor.js.map +1 -1
  23. package/dist/auth/types.d.ts +7 -0
  24. package/dist/auth/types.d.ts.map +1 -1
  25. package/dist/headless/cli.d.ts.map +1 -1
  26. package/dist/headless/cli.js +3 -0
  27. package/dist/headless/cli.js.map +1 -1
  28. package/dist/index.d.ts +14 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +13 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers/anthropic-thinking.d.ts +5 -0
  33. package/dist/providers/anthropic-thinking.d.ts.map +1 -0
  34. package/dist/providers/anthropic-thinking.js +25 -0
  35. package/dist/providers/anthropic-thinking.js.map +1 -0
  36. package/dist/providers/claude-max.d.ts +1 -1
  37. package/dist/providers/claude-max.d.ts.map +1 -1
  38. package/dist/providers/claude-max.js +8 -34
  39. package/dist/providers/claude-max.js.map +1 -1
  40. package/dist/providers/google-thinking.d.ts +4 -2
  41. package/dist/providers/google-thinking.d.ts.map +1 -1
  42. package/dist/providers/google-thinking.js +23 -7
  43. package/dist/providers/google-thinking.js.map +1 -1
  44. package/dist/providers/openai-codex.d.ts.map +1 -1
  45. package/dist/providers/openai-codex.js +3 -3
  46. package/dist/providers/openai-codex.js.map +1 -1
  47. package/dist/thinking-catalog.d.ts +4 -0
  48. package/dist/thinking-catalog.d.ts.map +1 -0
  49. package/dist/thinking-catalog.js +13 -0
  50. package/dist/thinking-catalog.js.map +1 -0
  51. package/dist/thinking.d.ts +4 -1
  52. package/dist/thinking.d.ts.map +1 -1
  53. package/dist/thinking.js +65 -4
  54. package/dist/thinking.js.map +1 -1
  55. package/package.json +11 -11
@@ -0,0 +1,25 @@
1
+ //#region src/providers/anthropic-thinking.ts
2
+ const ANTHROPIC_THINKING_BUDGET_TOKENS = {
3
+ low: 4096,
4
+ medium: 8192,
5
+ high: 16384,
6
+ xhigh: 24576,
7
+ max: 24576
8
+ };
9
+ const ANTHROPIC_XHIGH_EFFORT_RE = /claude-(?:opus-4-[78]|opus-5|sonnet-5|fable-5)/;
10
+ const ADAPTIVE_THINKING_RE = /claude-(?:sonnet-4-6|opus-4-[678]|opus-5|sonnet-5|fable-5)/;
11
+ const BUDGET_THINKING_RE = /claude-(?:3-7|sonnet-4|opus-4|haiku-4-5)/;
12
+ const NO_THINKING_RE = /claude-(?:instant|v?2(?:[-.:]|$)|3(?:[-.]|$)|3-5)/;
13
+ function getAnthropicThinkingCapability(modelId) {
14
+ if (ADAPTIVE_THINKING_RE.test(modelId)) return "adaptive";
15
+ if (BUDGET_THINKING_RE.test(modelId)) return "budget";
16
+ if (NO_THINKING_RE.test(modelId)) return "none";
17
+ return "adaptive";
18
+ }
19
+ function supportsAnthropicXhighEffort(modelId) {
20
+ return ANTHROPIC_XHIGH_EFFORT_RE.test(modelId);
21
+ }
22
+ //#endregion
23
+ export { ANTHROPIC_THINKING_BUDGET_TOKENS, getAnthropicThinkingCapability, supportsAnthropicXhighEffort };
24
+
25
+ //# sourceMappingURL=anthropic-thinking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-thinking.js","names":[],"sources":["../../src/providers/anthropic-thinking.ts"],"sourcesContent":["import type { ActiveThinkingLevel } from '../thinking.js';\n\n// counts toward max_tokens: stay under the 32k output cap of Opus 4.0/4.1\nexport const ANTHROPIC_THINKING_BUDGET_TOKENS: Record<ActiveThinkingLevel, number> = {\n low: 4096,\n medium: 8192,\n high: 16384,\n xhigh: 24576,\n max: 24576,\n};\n\nconst ANTHROPIC_XHIGH_EFFORT_RE = /claude-(?:opus-4-[78]|opus-5|sonnet-5|fable-5)/;\nconst ADAPTIVE_THINKING_RE = /claude-(?:sonnet-4-6|opus-4-[678]|opus-5|sonnet-5|fable-5)/;\nconst BUDGET_THINKING_RE = /claude-(?:3-7|sonnet-4|opus-4|haiku-4-5)/;\nconst NO_THINKING_RE = /claude-(?:instant|v?2(?:[-.:]|$)|3(?:[-.]|$)|3-5)/;\n\nexport function getAnthropicThinkingCapability(modelId: string): 'adaptive' | 'budget' | 'none' {\n if (ADAPTIVE_THINKING_RE.test(modelId)) return 'adaptive';\n if (BUDGET_THINKING_RE.test(modelId)) return 'budget';\n if (NO_THINKING_RE.test(modelId)) return 'none';\n return 'adaptive';\n}\n\nexport function supportsAnthropicXhighEffort(modelId: string): boolean {\n return ANTHROPIC_XHIGH_EFFORT_RE.test(modelId);\n}\n"],"mappings":";AAGA,MAAa,mCAAwE;CACnF,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACP,KAAK;AACP;AAEA,MAAM,4BAA4B;AAClC,MAAM,uBAAuB;AAC7B,MAAM,qBAAqB;AAC3B,MAAM,iBAAiB;AAEvB,SAAgB,+BAA+B,SAAiD;CAC9F,IAAI,qBAAqB,KAAK,OAAO,GAAG,OAAO;CAC/C,IAAI,mBAAmB,KAAK,OAAO,GAAG,OAAO;CAC7C,IAAI,eAAe,KAAK,OAAO,GAAG,OAAO;CACzC,OAAO;AACT;AAEA,SAAgB,6BAA6B,SAA0B;CACrE,OAAO,0BAA0B,KAAK,OAAO;AAC/C"}
@@ -41,7 +41,7 @@ export declare const createPromptCacheMiddleware: (scope: AnthropicPromptCacheSc
41
41
  * model doesn't support thinking, preserving the previous request shape.
42
42
  *
43
43
  * - Adaptive-era models (Sonnet 4.6+/Opus 4.6+): `thinking: adaptive` plus
44
- * `output_config.effort` mapped 1:1 from the level (including `max`).
44
+ * `output_config.effort`, the closest effort the model accepts.
45
45
  * - Budget-era models (Claude 3.7 – Opus 4.5): `thinking: enabled` with a
46
46
  * `budget_tokens` value derived from the level.
47
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"claude-max.d.ts","sourceRoot":"","sources":["../../src/providers/claude-max.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoBvD;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAErE;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,uBAkBlC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,yBAAyB,KAAG,uBA8D7E,CAAC;AA+CH;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,aAAa,GAC5B,uBAAuB,GAAG,SAAS,CAiCrC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,eAAe,CAAA;CAAO,GAAG,OAAO,KAAK,CAuCnG;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,MAAmC,EAC5C,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;CAC9C,GACA,iBAAiB,CAgCnB"}
1
+ {"version":3,"file":"claude-max.d.ts","sourceRoot":"","sources":["../../src/providers/claude-max.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoBvD;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAErE;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,uBAkBlC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,yBAAyB,KAAG,uBA8D7E,CAAC;AAMH;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,aAAa,GAC5B,uBAAuB,GAAG,SAAS,CAiCrC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,eAAe,CAAA;CAAO,GAAG,OAAO,KAAK,CAuCnG;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,MAAmC,EAC5C,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,yBAAyB,CAAC;CAC9C,GACA,iBAAiB,CAgCnB"}
@@ -1,5 +1,7 @@
1
1
  import { AuthStorage } from "../auth/storage.js";
2
2
  import { ProviderAuthRequiredError } from "../auth/provider-auth-error.js";
3
+ import { ANTHROPIC_THINKING_BUDGET_TOKENS, getAnthropicThinkingCapability } from "./anthropic-thinking.js";
4
+ import { runCatalogThinkingLevel } from "../thinking-catalog.js";
3
5
  import "./anthropic-prompt-cache.js";
4
6
  import { wrapLanguageModel } from "ai";
5
7
  import { createAnthropic } from "@ai-sdk/anthropic";
@@ -113,36 +115,8 @@ const createPromptCacheMiddleware = (scope) => ({
113
115
  };
114
116
  }
115
117
  });
116
- const ANTHROPIC_EFFORT = {
117
- low: "low",
118
- medium: "medium",
119
- high: "high",
120
- xhigh: "xhigh",
121
- max: "max"
122
- };
123
- const ANTHROPIC_XHIGH_EFFORT_RE = /claude-(?:opus-4-[78]|opus-5|sonnet-5|fable-5)/;
124
- function getAnthropicEffort(modelId, level) {
125
- if (level === "xhigh" && !ANTHROPIC_XHIGH_EFFORT_RE.test(modelId)) return "high";
126
- return ANTHROPIC_EFFORT[level];
127
- }
128
- const ANTHROPIC_THINKING_BUDGET_TOKENS = {
129
- low: 4096,
130
- medium: 8192,
131
- high: 16384,
132
- xhigh: 24576,
133
- max: 24576
134
- };
135
- /** Claude generations that support adaptive thinking + `output_config.effort`. */
136
- const ADAPTIVE_THINKING_RE = /claude-(?:sonnet-4-6|opus-4-[678]|opus-5|sonnet-5|fable-5)/;
137
- /** Older generations that support extended thinking via `budget_tokens`. */
138
- const BUDGET_THINKING_RE = /claude-(?:3-7|sonnet-4|opus-4|haiku-4-5)/;
139
- /** Generations with no extended-thinking support at all. */
140
- const NO_THINKING_RE = /claude-(?:instant|v?2(?:[-.:]|$)|3(?:[-.]|$)|3-5)/;
141
- function getAnthropicThinkingCapability(modelId) {
142
- if (ADAPTIVE_THINKING_RE.test(modelId)) return "adaptive";
143
- if (BUDGET_THINKING_RE.test(modelId)) return "budget";
144
- if (NO_THINKING_RE.test(modelId)) return "none";
145
- return "adaptive";
118
+ function runAnthropicRequestLevel(modelId, level) {
119
+ return runCatalogThinkingLevel(`anthropic/${modelId}`, level);
146
120
  }
147
121
  /**
148
122
  * Middleware that maps the session thinking level onto Anthropic extended
@@ -150,15 +124,15 @@ function getAnthropicThinkingCapability(modelId) {
150
124
  * model doesn't support thinking, preserving the previous request shape.
151
125
  *
152
126
  * - Adaptive-era models (Sonnet 4.6+/Opus 4.6+): `thinking: adaptive` plus
153
- * `output_config.effort` mapped 1:1 from the level (including `max`).
127
+ * `output_config.effort`, the closest effort the model accepts.
154
128
  * - Budget-era models (Claude 3.7 – Opus 4.5): `thinking: enabled` with a
155
129
  * `budget_tokens` value derived from the level.
156
130
  */
157
131
  function createAnthropicThinkingMiddleware(modelId, thinkingLevel) {
158
132
  if (!thinkingLevel || thinkingLevel === "off") return void 0;
159
133
  const capability = getAnthropicThinkingCapability(modelId);
160
- if (capability === "none") return void 0;
161
- const level = thinkingLevel;
134
+ const level = runAnthropicRequestLevel(modelId, thinkingLevel);
135
+ if (level === "off") return void 0;
162
136
  return {
163
137
  specificationVersion: "v3",
164
138
  transformParams: async ({ params }) => {
@@ -176,7 +150,7 @@ function createAnthropicThinkingMiddleware(modelId, thinkingLevel) {
176
150
  type: "adaptive",
177
151
  display: "summarized"
178
152
  },
179
- effort: getAnthropicEffort(modelId, level)
153
+ effort: level
180
154
  } : { thinking: {
181
155
  type: "enabled",
182
156
  budgetTokens: ANTHROPIC_THINKING_BUDGET_TOKENS[level]
@@ -1 +1 @@
1
- {"version":3,"file":"claude-max.js","names":[],"sources":["../../src/providers/claude-max.ts"],"sourcesContent":["/**\n * Claude Max OAuth Provider\n *\n * Uses OAuth tokens from AuthStorage to authenticate with Claude Max plan.\n * The OAuth endpoint requires a specific system message to be present.\n */\n\nimport { createAnthropic } from '@ai-sdk/anthropic';\nimport type { MastraModelConfig } from '@mastra/core/llm';\nimport { wrapLanguageModel } from 'ai';\nimport type { LanguageModelMiddleware } from 'ai';\nimport { ProviderAuthRequiredError } from '../auth/provider-auth-error.js';\nimport { AuthStorage } from '../auth/storage.js';\nimport type { CredentialStore } from '../auth/types.js';\nimport { ANTHROPIC_PROMPT_CACHE_TTL } from './anthropic-prompt-cache.js';\nimport type { AnthropicPromptCacheScope } from './anthropic-prompt-cache.js';\nimport type { ThinkingLevel } from './openai-codex.js';\n\n// Required for Claude Max plan OAuth - the endpoint checks for this system message\nconst claudeCodeIdentity = \"You are Claude Code, Anthropic's official CLI for Claude.\";\n\n// Betas required for Claude Max plan OAuth. Merged with (not replacing) any\n// betas the AI SDK already set on the request — e.g. the SDK adds\n// `server-side-fallback-2026-06-01` when `providerOptions.anthropic.fallbacks`\n// is configured; dropping it makes the API reject the `fallbacks` body field\n// with \"Extra inputs are not permitted\".\nconst OAUTH_REQUIRED_BETAS = [\n 'oauth-2025-04-20',\n 'claude-code-20250219',\n 'interleaved-thinking-2025-05-14',\n 'fine-grained-tool-streaming-2025-05-14',\n];\n\n// Singleton auth storage instance\nlet authStorageInstance: AuthStorage | null = null;\n\n/**\n * Get or create the shared AuthStorage instance\n */\nexport function getAuthStorage(): AuthStorage {\n if (!authStorageInstance) {\n authStorageInstance = new AuthStorage();\n }\n return authStorageInstance;\n}\n\n/**\n * Set a custom AuthStorage instance (useful for TUI integration)\n */\nexport function setAuthStorage(storage: AuthStorage | undefined): void {\n authStorageInstance = storage ?? null;\n}\n\n/**\n * Middleware that injects the Claude Code identity system message\n * Required for Claude Max OAuth authentication\n */\nexport const claudeCodeMiddleware: LanguageModelMiddleware = {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n // Prepend the Claude Code identity as the first system message\n const systemMessage = {\n role: 'system' as const,\n content: claudeCodeIdentity,\n };\n\n if (params.temperature) {\n delete params.topP;\n }\n\n return {\n ...params,\n prompt: [systemMessage, ...params.prompt],\n };\n },\n};\n\n/**\n * Prompt caching middleware for Anthropic\n *\n * Adds cache breakpoints at strategic locations:\n * 1. Last system message (end of static instructions + dynamic memory)\n * 2. Most recent user/assistant message (conversation context), `conversation` scope only\n *\n * This allows Anthropic to cache:\n * - System prompts and instructions (rarely change)\n * - Conversation history up to the last message\n */\nexport const createPromptCacheMiddleware = (scope: AnthropicPromptCacheScope): LanguageModelMiddleware => ({\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const prompt = [...params.prompt];\n\n const cacheControl = {\n type: 'ephemeral' as const,\n ttl: scope === 'conversation' ? ANTHROPIC_PROMPT_CACHE_TTL : ('5m' as const),\n };\n\n // Helper to add cache control to a message's last content part\n const addCacheToMessage = (msg: any) => {\n // For system messages with string content\n if (typeof msg.content === 'string') {\n return {\n ...msg,\n providerOptions: {\n ...msg.providerOptions,\n anthropic: { ...msg.providerOptions?.anthropic, cacheControl },\n },\n };\n }\n\n // For messages with array content, add to last part\n if (Array.isArray(msg.content) && msg.content.length > 0) {\n const content = [...msg.content];\n const lastPart = content[content.length - 1];\n content[content.length - 1] = {\n ...lastPart,\n providerOptions: {\n ...lastPart.providerOptions,\n anthropic: { ...lastPart.providerOptions?.anthropic, cacheControl },\n },\n };\n return { ...msg, content };\n }\n\n return msg;\n };\n\n // Find the last system message index\n let lastSystemIdx = -1;\n for (let i = prompt.length - 1; i >= 0; i--) {\n if ((prompt[i] as any).role === 'system') {\n lastSystemIdx = i;\n break;\n }\n }\n\n // Add cache breakpoint to last system message\n if (lastSystemIdx >= 0) {\n prompt[lastSystemIdx] = addCacheToMessage(prompt[lastSystemIdx]);\n }\n\n // Add cache breakpoint to the most recent message (last in array)\n const lastIdx = prompt.length - 1;\n if (scope === 'conversation' && lastIdx >= 0 && lastIdx !== lastSystemIdx) {\n prompt[lastIdx] = addCacheToMessage(prompt[lastIdx]);\n }\n\n return { ...params, prompt };\n },\n});\n\ntype ActiveThinkingLevel = Exclude<ThinkingLevel, 'off'>;\n\n// Anthropic's effort scale matches mastracode thinking levels 1:1 (minus 'off'),\n// including 'max' — the level OpenAI's scale stops short of.\nconst ANTHROPIC_EFFORT: Record<ActiveThinkingLevel, 'low' | 'medium' | 'high' | 'xhigh' | 'max'> = {\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n};\n\nconst ANTHROPIC_XHIGH_EFFORT_RE = /claude-(?:opus-4-[78]|opus-5|sonnet-5|fable-5)/;\n\nfunction getAnthropicEffort(modelId: string, level: ActiveThinkingLevel) {\n if (level === 'xhigh' && !ANTHROPIC_XHIGH_EFFORT_RE.test(modelId)) return 'high';\n return ANTHROPIC_EFFORT[level];\n}\n\n// Extended-thinking budgets for models that predate adaptive thinking/effort.\n// Budgets count toward max_tokens, so they stay well below the smallest\n// output ceiling of the budget-era models (32k on Opus 4.0/4.1).\nconst ANTHROPIC_THINKING_BUDGET_TOKENS: Record<ActiveThinkingLevel, number> = {\n low: 4096,\n medium: 8192,\n high: 16384,\n xhigh: 24576,\n max: 24576,\n};\n\n/** Claude generations that support adaptive thinking + `output_config.effort`. */\nconst ADAPTIVE_THINKING_RE = /claude-(?:sonnet-4-6|opus-4-[678]|opus-5|sonnet-5|fable-5)/;\n/** Older generations that support extended thinking via `budget_tokens`. */\nconst BUDGET_THINKING_RE = /claude-(?:3-7|sonnet-4|opus-4|haiku-4-5)/;\n/** Generations with no extended-thinking support at all. */\nconst NO_THINKING_RE = /claude-(?:instant|v?2(?:[-.:]|$)|3(?:[-.]|$)|3-5)/;\n\nfunction getAnthropicThinkingCapability(modelId: string): 'adaptive' | 'budget' | 'none' {\n if (ADAPTIVE_THINKING_RE.test(modelId)) return 'adaptive';\n if (BUDGET_THINKING_RE.test(modelId)) return 'budget';\n if (NO_THINKING_RE.test(modelId)) return 'none';\n // Unknown (i.e. newer) Claude models: assume the current API surface.\n return 'adaptive';\n}\n\n/**\n * Middleware that maps the session thinking level onto Anthropic extended\n * thinking. Returns `undefined` (no middleware) when the level is `off` or the\n * model doesn't support thinking, preserving the previous request shape.\n *\n * - Adaptive-era models (Sonnet 4.6+/Opus 4.6+): `thinking: adaptive` plus\n * `output_config.effort` mapped 1:1 from the level (including `max`).\n * - Budget-era models (Claude 3.7 – Opus 4.5): `thinking: enabled` with a\n * `budget_tokens` value derived from the level.\n */\nexport function createAnthropicThinkingMiddleware(\n modelId: string,\n thinkingLevel?: ThinkingLevel,\n): LanguageModelMiddleware | undefined {\n if (!thinkingLevel || thinkingLevel === 'off') return undefined;\n const capability = getAnthropicThinkingCapability(modelId);\n if (capability === 'none') return undefined;\n const level = thinkingLevel as ActiveThinkingLevel;\n\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const anthropicOptions = (params.providerOptions?.anthropic ?? {}) as Record<string, unknown>;\n // Don't override explicit per-request thinking configuration.\n if (anthropicOptions.thinking !== undefined || anthropicOptions.effort !== undefined) {\n return params;\n }\n\n // Anthropic rejects sampling parameters when thinking is enabled.\n delete params.temperature;\n delete params.topP;\n delete params.topK;\n\n params.providerOptions = {\n ...params.providerOptions,\n anthropic: {\n ...anthropicOptions,\n ...(capability === 'adaptive'\n ? { thinking: { type: 'adaptive', display: 'summarized' }, effort: getAnthropicEffort(modelId, level) }\n : { thinking: { type: 'enabled', budgetTokens: ANTHROPIC_THINKING_BUDGET_TOKENS[level] } }),\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Build a fetch function that handles Anthropic OAuth.\n * Preserves non-auth headers from init (critical for gateway auth header to survive\n * when used with the gateway). Strips `authorization` and `x-api-key`.\n */\nexport function buildAnthropicOAuthFetch(opts: { authStorage?: CredentialStore } = {}): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n const storage = opts.authStorage ?? getAuthStorage();\n storage.reload();\n\n const storedCred = storage.get('anthropic');\n if (storedCred?.type === 'api_key') {\n throw new Error('Anthropic API key credential is configured, but OAuth is required.');\n }\n\n const accessToken = await storage.getApiKey('anthropic');\n if (!accessToken) {\n throw new ProviderAuthRequiredError('Not logged in to Anthropic.');\n }\n\n // Preserve Request headers and let explicit init headers override them.\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (init?.headers) new Headers(init.headers).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n const requestBetas = (headers.get('anthropic-beta') ?? '')\n .split(',')\n .map(beta => beta.trim())\n .filter(Boolean);\n headers.set('anthropic-beta', Array.from(new Set([...OAUTH_REQUIRED_BETAS, ...requestBetas])).join(','));\n headers.set('anthropic-version', '2023-06-01');\n\n try {\n return await fetch(url, { ...init, headers });\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, {\n requestUrl: url instanceof URL ? url.toString() : typeof url === 'string' ? url : url.url,\n });\n }\n throw error;\n }\n }) as typeof fetch;\n}\n\n/**\n * Creates an Anthropic model using Claude Max OAuth authentication\n * Uses OAuth tokens from AuthStorage (auto-refreshes when needed)\n */\nexport function opencodeClaudeMaxProvider(\n modelId: string = 'claude-sonnet-4-20250514',\n options?: {\n headers?: Record<string, string>;\n authStorage?: CredentialStore;\n thinkingLevel?: ThinkingLevel;\n promptCacheScope?: AnthropicPromptCacheScope;\n },\n): MastraModelConfig {\n const headers = options?.headers;\n const thinkingMiddleware = createAnthropicThinkingMiddleware(modelId, options?.thinkingLevel);\n const middleware = [\n claudeCodeMiddleware,\n createPromptCacheMiddleware(options?.promptCacheScope ?? 'conversation'),\n ...(thinkingMiddleware ? [thinkingMiddleware] : []),\n ];\n\n // Test environment: use API key\n if (process.env.NODE_ENV === 'test' || process.env.VITEST) {\n const anthropic = createAnthropic({\n apiKey: 'test-api-key',\n headers,\n });\n return wrapLanguageModel({\n model: anthropic(modelId),\n middleware,\n });\n }\n\n const anthropic = createAnthropic({\n apiKey: 'oauth-placeholder',\n headers,\n fetch: buildAnthropicOAuthFetch({ authStorage: options?.authStorage }) as any,\n });\n\n // Wrap with middleware to inject Claude Code identity and enable prompt caching\n return wrapLanguageModel({\n model: anthropic(modelId),\n middleware,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"claude-max.js","names":[],"sources":["../../src/providers/claude-max.ts"],"sourcesContent":["/**\n * Claude Max OAuth Provider\n *\n * Uses OAuth tokens from AuthStorage to authenticate with Claude Max plan.\n * The OAuth endpoint requires a specific system message to be present.\n */\n\nimport { createAnthropic } from '@ai-sdk/anthropic';\nimport type { MastraModelConfig } from '@mastra/core/llm';\nimport { wrapLanguageModel } from 'ai';\nimport type { LanguageModelMiddleware } from 'ai';\nimport { ProviderAuthRequiredError } from '../auth/provider-auth-error.js';\nimport { AuthStorage } from '../auth/storage.js';\nimport type { CredentialStore } from '../auth/types.js';\nimport { runCatalogThinkingLevel } from '../thinking-catalog.js';\nimport { ANTHROPIC_PROMPT_CACHE_TTL } from './anthropic-prompt-cache.js';\nimport type { AnthropicPromptCacheScope } from './anthropic-prompt-cache.js';\nimport { ANTHROPIC_THINKING_BUDGET_TOKENS, getAnthropicThinkingCapability } from './anthropic-thinking.js';\nimport type { ThinkingLevel } from './openai-codex.js';\n\n// Required for Claude Max plan OAuth - the endpoint checks for this system message\nconst claudeCodeIdentity = \"You are Claude Code, Anthropic's official CLI for Claude.\";\n\n// Betas required for Claude Max plan OAuth. Merged with (not replacing) any\n// betas the AI SDK already set on the request — e.g. the SDK adds\n// `server-side-fallback-2026-06-01` when `providerOptions.anthropic.fallbacks`\n// is configured; dropping it makes the API reject the `fallbacks` body field\n// with \"Extra inputs are not permitted\".\nconst OAUTH_REQUIRED_BETAS = [\n 'oauth-2025-04-20',\n 'claude-code-20250219',\n 'interleaved-thinking-2025-05-14',\n 'fine-grained-tool-streaming-2025-05-14',\n];\n\n// Singleton auth storage instance\nlet authStorageInstance: AuthStorage | null = null;\n\n/**\n * Get or create the shared AuthStorage instance\n */\nexport function getAuthStorage(): AuthStorage {\n if (!authStorageInstance) {\n authStorageInstance = new AuthStorage();\n }\n return authStorageInstance;\n}\n\n/**\n * Set a custom AuthStorage instance (useful for TUI integration)\n */\nexport function setAuthStorage(storage: AuthStorage | undefined): void {\n authStorageInstance = storage ?? null;\n}\n\n/**\n * Middleware that injects the Claude Code identity system message\n * Required for Claude Max OAuth authentication\n */\nexport const claudeCodeMiddleware: LanguageModelMiddleware = {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n // Prepend the Claude Code identity as the first system message\n const systemMessage = {\n role: 'system' as const,\n content: claudeCodeIdentity,\n };\n\n if (params.temperature) {\n delete params.topP;\n }\n\n return {\n ...params,\n prompt: [systemMessage, ...params.prompt],\n };\n },\n};\n\n/**\n * Prompt caching middleware for Anthropic\n *\n * Adds cache breakpoints at strategic locations:\n * 1. Last system message (end of static instructions + dynamic memory)\n * 2. Most recent user/assistant message (conversation context), `conversation` scope only\n *\n * This allows Anthropic to cache:\n * - System prompts and instructions (rarely change)\n * - Conversation history up to the last message\n */\nexport const createPromptCacheMiddleware = (scope: AnthropicPromptCacheScope): LanguageModelMiddleware => ({\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const prompt = [...params.prompt];\n\n const cacheControl = {\n type: 'ephemeral' as const,\n ttl: scope === 'conversation' ? ANTHROPIC_PROMPT_CACHE_TTL : ('5m' as const),\n };\n\n // Helper to add cache control to a message's last content part\n const addCacheToMessage = (msg: any) => {\n // For system messages with string content\n if (typeof msg.content === 'string') {\n return {\n ...msg,\n providerOptions: {\n ...msg.providerOptions,\n anthropic: { ...msg.providerOptions?.anthropic, cacheControl },\n },\n };\n }\n\n // For messages with array content, add to last part\n if (Array.isArray(msg.content) && msg.content.length > 0) {\n const content = [...msg.content];\n const lastPart = content[content.length - 1];\n content[content.length - 1] = {\n ...lastPart,\n providerOptions: {\n ...lastPart.providerOptions,\n anthropic: { ...lastPart.providerOptions?.anthropic, cacheControl },\n },\n };\n return { ...msg, content };\n }\n\n return msg;\n };\n\n // Find the last system message index\n let lastSystemIdx = -1;\n for (let i = prompt.length - 1; i >= 0; i--) {\n if ((prompt[i] as any).role === 'system') {\n lastSystemIdx = i;\n break;\n }\n }\n\n // Add cache breakpoint to last system message\n if (lastSystemIdx >= 0) {\n prompt[lastSystemIdx] = addCacheToMessage(prompt[lastSystemIdx]);\n }\n\n // Add cache breakpoint to the most recent message (last in array)\n const lastIdx = prompt.length - 1;\n if (scope === 'conversation' && lastIdx >= 0 && lastIdx !== lastSystemIdx) {\n prompt[lastIdx] = addCacheToMessage(prompt[lastIdx]);\n }\n\n return { ...params, prompt };\n },\n});\n\nfunction runAnthropicRequestLevel(modelId: string, level: ThinkingLevel): ThinkingLevel {\n return runCatalogThinkingLevel(`anthropic/${modelId}`, level);\n}\n\n/**\n * Middleware that maps the session thinking level onto Anthropic extended\n * thinking. Returns `undefined` (no middleware) when the level is `off` or the\n * model doesn't support thinking, preserving the previous request shape.\n *\n * - Adaptive-era models (Sonnet 4.6+/Opus 4.6+): `thinking: adaptive` plus\n * `output_config.effort`, the closest effort the model accepts.\n * - Budget-era models (Claude 3.7 – Opus 4.5): `thinking: enabled` with a\n * `budget_tokens` value derived from the level.\n */\nexport function createAnthropicThinkingMiddleware(\n modelId: string,\n thinkingLevel?: ThinkingLevel,\n): LanguageModelMiddleware | undefined {\n if (!thinkingLevel || thinkingLevel === 'off') return undefined;\n const capability = getAnthropicThinkingCapability(modelId);\n const level = runAnthropicRequestLevel(modelId, thinkingLevel);\n if (level === 'off') return undefined;\n\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const anthropicOptions = (params.providerOptions?.anthropic ?? {}) as Record<string, unknown>;\n // Don't override explicit per-request thinking configuration.\n if (anthropicOptions.thinking !== undefined || anthropicOptions.effort !== undefined) {\n return params;\n }\n\n // Anthropic rejects sampling parameters when thinking is enabled.\n delete params.temperature;\n delete params.topP;\n delete params.topK;\n\n params.providerOptions = {\n ...params.providerOptions,\n anthropic: {\n ...anthropicOptions,\n ...(capability === 'adaptive'\n ? { thinking: { type: 'adaptive', display: 'summarized' }, effort: level }\n : { thinking: { type: 'enabled', budgetTokens: ANTHROPIC_THINKING_BUDGET_TOKENS[level] } }),\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Build a fetch function that handles Anthropic OAuth.\n * Preserves non-auth headers from init (critical for gateway auth header to survive\n * when used with the gateway). Strips `authorization` and `x-api-key`.\n */\nexport function buildAnthropicOAuthFetch(opts: { authStorage?: CredentialStore } = {}): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n const storage = opts.authStorage ?? getAuthStorage();\n storage.reload();\n\n const storedCred = storage.get('anthropic');\n if (storedCred?.type === 'api_key') {\n throw new Error('Anthropic API key credential is configured, but OAuth is required.');\n }\n\n const accessToken = await storage.getApiKey('anthropic');\n if (!accessToken) {\n throw new ProviderAuthRequiredError('Not logged in to Anthropic.');\n }\n\n // Preserve Request headers and let explicit init headers override them.\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (init?.headers) new Headers(init.headers).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n const requestBetas = (headers.get('anthropic-beta') ?? '')\n .split(',')\n .map(beta => beta.trim())\n .filter(Boolean);\n headers.set('anthropic-beta', Array.from(new Set([...OAUTH_REQUIRED_BETAS, ...requestBetas])).join(','));\n headers.set('anthropic-version', '2023-06-01');\n\n try {\n return await fetch(url, { ...init, headers });\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, {\n requestUrl: url instanceof URL ? url.toString() : typeof url === 'string' ? url : url.url,\n });\n }\n throw error;\n }\n }) as typeof fetch;\n}\n\n/**\n * Creates an Anthropic model using Claude Max OAuth authentication\n * Uses OAuth tokens from AuthStorage (auto-refreshes when needed)\n */\nexport function opencodeClaudeMaxProvider(\n modelId: string = 'claude-sonnet-4-20250514',\n options?: {\n headers?: Record<string, string>;\n authStorage?: CredentialStore;\n thinkingLevel?: ThinkingLevel;\n promptCacheScope?: AnthropicPromptCacheScope;\n },\n): MastraModelConfig {\n const headers = options?.headers;\n const thinkingMiddleware = createAnthropicThinkingMiddleware(modelId, options?.thinkingLevel);\n const middleware = [\n claudeCodeMiddleware,\n createPromptCacheMiddleware(options?.promptCacheScope ?? 'conversation'),\n ...(thinkingMiddleware ? [thinkingMiddleware] : []),\n ];\n\n // Test environment: use API key\n if (process.env.NODE_ENV === 'test' || process.env.VITEST) {\n const anthropic = createAnthropic({\n apiKey: 'test-api-key',\n headers,\n });\n return wrapLanguageModel({\n model: anthropic(modelId),\n middleware,\n });\n }\n\n const anthropic = createAnthropic({\n apiKey: 'oauth-placeholder',\n headers,\n fetch: buildAnthropicOAuthFetch({ authStorage: options?.authStorage }) as any,\n });\n\n // Wrap with middleware to inject Claude Code identity and enable prompt caching\n return wrapLanguageModel({\n model: anthropic(modelId),\n middleware,\n });\n}\n"],"mappings":"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"}
@@ -8,12 +8,14 @@
8
8
  * Unknown model families get no thinking config, so requests are unchanged.
9
9
  */
10
10
  import type { LanguageModelMiddleware } from 'ai';
11
- import type { ThinkingLevelSetting } from '../thinking.js';
11
+ import type { ActiveThinkingLevel, ThinkingLevelSetting } from '../thinking.js';
12
+ type GeminiLevel = 'low' | 'medium' | 'high';
12
13
  type GoogleThinkingConfig = {
13
- thinkingLevel: 'minimal' | 'low' | 'medium' | 'high';
14
+ thinkingLevel: 'minimal' | GeminiLevel;
14
15
  } | {
15
16
  thinkingBudget: number;
16
17
  };
18
+ export declare function runGeminiThinkingLevel(modelId: string, level: ActiveThinkingLevel): ThinkingLevelSetting;
17
19
  /**
18
20
  * Resolve the Google thinking config for a model and session level.
19
21
  * Returns `undefined` for `off`, unset levels, and unrecognized model families.
@@ -1 +1 @@
1
- {"version":3,"file":"google-thinking.d.ts","sourceRoot":"","sources":["../../src/providers/google-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,KAAK,oBAAoB,GAAG;IAAE,aAAa,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,GAAG;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAKlH;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,GAAG,SAAS,GACtC,oBAAoB,GAAG,SAAS,CAoBlC;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,GAAG,SAAS,GACtC,uBAAuB,GAAG,SAAS,CAkBrC"}
1
+ {"version":3,"file":"google-thinking.d.ts","sourceRoot":"","sources":["../../src/providers/google-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,KAAK,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7C,KAAK,oBAAoB,GAAG;IAAE,aAAa,EAAE,SAAS,GAAG,WAAW,CAAA;CAAE,GAAG;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAuBpG,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAGxG;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,GAAG,SAAS,GACtC,oBAAoB,GAAG,SAAS,CASlC;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,GAAG,SAAS,GACtC,uBAAuB,GAAG,SAAS,CAkBrC"}
@@ -4,18 +4,34 @@ const GEMINI_25_BUDGETS = {
4
4
  medium: 8192,
5
5
  high: 24576
6
6
  };
7
+ function getGeminiThinkingFamily(modelId) {
8
+ const id = modelId.toLowerCase();
9
+ if (id.startsWith("gemini-2.5")) return "budget";
10
+ if (id.startsWith("gemini-3-pro")) return "low-high";
11
+ if (id.startsWith("gemini-3.1-flash-image") || id.startsWith("gemini-3.1-flash-lite-image")) return "minimal-high";
12
+ if (/^gemini-\d/.test(id) && !id.startsWith("gemini-1") && !id.startsWith("gemini-2")) return "levels";
13
+ }
14
+ function geminiLevelForFamily(family, level) {
15
+ const cappedAtHigh = level === "xhigh" || level === "max" ? "high" : level;
16
+ if ((family === "low-high" || family === "minimal-high") && cappedAtHigh === "medium") return "high";
17
+ return cappedAtHigh;
18
+ }
19
+ function runGeminiThinkingLevel(modelId, level) {
20
+ const family = getGeminiThinkingFamily(modelId);
21
+ return family ? geminiLevelForFamily(family, level) : "off";
22
+ }
7
23
  /**
8
24
  * Resolve the Google thinking config for a model and session level.
9
25
  * Returns `undefined` for `off`, unset levels, and unrecognized model families.
10
26
  */
11
27
  function resolveGoogleThinkingConfig(modelId, level) {
12
28
  if (!level || level === "off") return void 0;
13
- const clamped = level === "xhigh" || level === "max" ? "high" : level;
14
- const id = modelId.toLowerCase();
15
- if (id.startsWith("gemini-2.5")) return { thinkingBudget: GEMINI_25_BUDGETS[clamped] };
16
- if (id.startsWith("gemini-3-pro")) return { thinkingLevel: clamped === "low" ? "low" : "high" };
17
- if (id.startsWith("gemini-3.1-flash-image") || id.startsWith("gemini-3.1-flash-lite-image")) return { thinkingLevel: clamped === "low" ? "minimal" : "high" };
18
- if (/^gemini-\d/.test(id) && !id.startsWith("gemini-1") && !id.startsWith("gemini-2")) return { thinkingLevel: clamped };
29
+ const family = getGeminiThinkingFamily(modelId);
30
+ if (!family) return void 0;
31
+ const geminiLevel = geminiLevelForFamily(family, level);
32
+ if (family === "budget") return { thinkingBudget: GEMINI_25_BUDGETS[geminiLevel] };
33
+ if (family === "minimal-high") return { thinkingLevel: geminiLevel === "low" ? "minimal" : "high" };
34
+ return { thinkingLevel: geminiLevel };
19
35
  }
20
36
  /**
21
37
  * Create middleware that injects the resolved config into
@@ -46,6 +62,6 @@ function createGoogleThinkingMiddleware(modelId, level) {
46
62
  };
47
63
  }
48
64
  //#endregion
49
- export { createGoogleThinkingMiddleware, resolveGoogleThinkingConfig };
65
+ export { createGoogleThinkingMiddleware, resolveGoogleThinkingConfig, runGeminiThinkingLevel };
50
66
 
51
67
  //# sourceMappingURL=google-thinking.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-thinking.js","names":[],"sources":["../../src/providers/google-thinking.ts"],"sourcesContent":["/**\n * Google (Gemini) thinking-level middleware.\n *\n * Maps the Mastra Code session thinking level (`off|low|medium|high|xhigh|max`)\n * onto the thinking control each Gemini family accepts:\n * - Gemini 3+: `thinkingConfig.thinkingLevel` (Gemini 3 Pro only accepts `low|high`).\n * - Gemini 2.5: `thinkingConfig.thinkingBudget` (token budget).\n * Unknown model families get no thinking config, so requests are unchanged.\n */\n\nimport type { LanguageModelMiddleware } from 'ai';\nimport type { ThinkingLevelSetting } from '../thinking.js';\n\ntype GoogleThinkingConfig = { thinkingLevel: 'minimal' | 'low' | 'medium' | 'high' } | { thinkingBudget: number };\n\n// Budgets stay within the smallest Gemini 2.5 maximum (24576 for Flash / Flash-Lite).\nconst GEMINI_25_BUDGETS = { low: 1024, medium: 8192, high: 24576 } as const;\n\n/**\n * Resolve the Google thinking config for a model and session level.\n * Returns `undefined` for `off`, unset levels, and unrecognized model families.\n */\nexport function resolveGoogleThinkingConfig(\n modelId: string,\n level: ThinkingLevelSetting | undefined,\n): GoogleThinkingConfig | undefined {\n if (!level || level === 'off') return undefined;\n const clamped = level === 'xhigh' || level === 'max' ? 'high' : level;\n const id = modelId.toLowerCase();\n\n if (id.startsWith('gemini-2.5')) {\n return { thinkingBudget: GEMINI_25_BUDGETS[clamped] };\n }\n // Only Gemini 3 Pro lacks `medium`; Gemini 3.1 Pro accepts it.\n if (id.startsWith('gemini-3-pro')) {\n return { thinkingLevel: clamped === 'low' ? 'low' : 'high' };\n }\n // Gemini 3.1 Flash Image models only accept `minimal|high`.\n if (id.startsWith('gemini-3.1-flash-image') || id.startsWith('gemini-3.1-flash-lite-image')) {\n return { thinkingLevel: clamped === 'low' ? 'minimal' : 'high' };\n }\n if (/^gemini-\\d/.test(id) && !id.startsWith('gemini-1') && !id.startsWith('gemini-2')) {\n return { thinkingLevel: clamped };\n }\n return undefined;\n}\n\n/**\n * Create middleware that injects the resolved config into\n * `providerOptions.google.thinkingConfig`. Returns `undefined` when there is\n * nothing to inject, so callers wrap nothing.\n */\nexport function createGoogleThinkingMiddleware(\n modelId: string,\n level: ThinkingLevelSetting | undefined,\n): LanguageModelMiddleware | undefined {\n const config = resolveGoogleThinkingConfig(modelId, level);\n if (!config) return undefined;\n\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const google = (params.providerOptions?.google ?? {}) as Record<string, unknown>;\n const thinkingConfig = (google.thinkingConfig ?? {}) as Record<string, unknown>;\n // Explicit caller settings win; Google rejects budget and level together.\n if (thinkingConfig.thinkingBudget !== undefined || thinkingConfig.thinkingLevel !== undefined) return params;\n params.providerOptions = {\n ...params.providerOptions,\n google: { ...google, thinkingConfig: { ...thinkingConfig, ...config } },\n } as typeof params.providerOptions;\n return params;\n },\n };\n}\n"],"mappings":";AAgBA,MAAM,oBAAoB;CAAE,KAAK;CAAM,QAAQ;CAAM,MAAM;AAAM;;;;;AAMjE,SAAgB,4BACd,SACA,OACkC;CAClC,IAAI,CAAC,SAAS,UAAU,OAAO,OAAO,KAAA;CACtC,MAAM,UAAU,UAAU,WAAW,UAAU,QAAQ,SAAS;CAChE,MAAM,KAAK,QAAQ,YAAY;CAE/B,IAAI,GAAG,WAAW,YAAY,GAC5B,OAAO,EAAE,gBAAgB,kBAAkB,SAAS;CAGtD,IAAI,GAAG,WAAW,cAAc,GAC9B,OAAO,EAAE,eAAe,YAAY,QAAQ,QAAQ,OAAO;CAG7D,IAAI,GAAG,WAAW,wBAAwB,KAAK,GAAG,WAAW,6BAA6B,GACxF,OAAO,EAAE,eAAe,YAAY,QAAQ,YAAY,OAAO;CAEjE,IAAI,aAAa,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,UAAU,KAAK,CAAC,GAAG,WAAW,UAAU,GAClF,OAAO,EAAE,eAAe,QAAQ;AAGpC;;;;;;AAOA,SAAgB,+BACd,SACA,OACqC;CACrC,MAAM,SAAS,4BAA4B,SAAS,KAAK;CACzD,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,OAAO;EACL,sBAAsB;EACtB,iBAAiB,OAAO,EAAE,aAAa;GACrC,MAAM,SAAU,OAAO,iBAAiB,UAAU,CAAC;GACnD,MAAM,iBAAkB,OAAO,kBAAkB,CAAC;GAElD,IAAI,eAAe,mBAAmB,KAAA,KAAa,eAAe,kBAAkB,KAAA,GAAW,OAAO;GACtG,OAAO,kBAAkB;IACvB,GAAG,OAAO;IACV,QAAQ;KAAE,GAAG;KAAQ,gBAAgB;MAAE,GAAG;MAAgB,GAAG;KAAO;IAAE;GACxE;GACA,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"google-thinking.js","names":[],"sources":["../../src/providers/google-thinking.ts"],"sourcesContent":["/**\n * Google (Gemini) thinking-level middleware.\n *\n * Maps the Mastra Code session thinking level (`off|low|medium|high|xhigh|max`)\n * onto the thinking control each Gemini family accepts:\n * - Gemini 3+: `thinkingConfig.thinkingLevel` (Gemini 3 Pro only accepts `low|high`).\n * - Gemini 2.5: `thinkingConfig.thinkingBudget` (token budget).\n * Unknown model families get no thinking config, so requests are unchanged.\n */\n\nimport type { LanguageModelMiddleware } from 'ai';\nimport type { ActiveThinkingLevel, ThinkingLevelSetting } from '../thinking.js';\n\ntype GeminiLevel = 'low' | 'medium' | 'high';\ntype GeminiThinkingFamily = 'budget' | 'low-high' | 'minimal-high' | 'levels';\ntype GoogleThinkingConfig = { thinkingLevel: 'minimal' | GeminiLevel } | { thinkingBudget: number };\n\n// Budgets stay within the smallest Gemini 2.5 maximum (24576 for Flash / Flash-Lite).\nconst GEMINI_25_BUDGETS: Record<GeminiLevel, number> = { low: 1024, medium: 8192, high: 24576 };\n\nfunction getGeminiThinkingFamily(modelId: string): GeminiThinkingFamily | undefined {\n const id = modelId.toLowerCase();\n if (id.startsWith('gemini-2.5')) return 'budget';\n // Only Gemini 3 Pro lacks `medium`; Gemini 3.1 Pro accepts it.\n if (id.startsWith('gemini-3-pro')) return 'low-high';\n // Gemini 3.1 Flash Image models only accept `minimal|high`.\n if (id.startsWith('gemini-3.1-flash-image') || id.startsWith('gemini-3.1-flash-lite-image')) return 'minimal-high';\n if (/^gemini-\\d/.test(id) && !id.startsWith('gemini-1') && !id.startsWith('gemini-2')) return 'levels';\n return undefined;\n}\n\nfunction geminiLevelForFamily(family: GeminiThinkingFamily, level: ActiveThinkingLevel): GeminiLevel {\n const cappedAtHigh = level === 'xhigh' || level === 'max' ? 'high' : level;\n const hasNoMedium = family === 'low-high' || family === 'minimal-high';\n if (hasNoMedium && cappedAtHigh === 'medium') return 'high';\n return cappedAtHigh;\n}\n\nexport function runGeminiThinkingLevel(modelId: string, level: ActiveThinkingLevel): ThinkingLevelSetting {\n const family = getGeminiThinkingFamily(modelId);\n return family ? geminiLevelForFamily(family, level) : 'off';\n}\n\n/**\n * Resolve the Google thinking config for a model and session level.\n * Returns `undefined` for `off`, unset levels, and unrecognized model families.\n */\nexport function resolveGoogleThinkingConfig(\n modelId: string,\n level: ThinkingLevelSetting | undefined,\n): GoogleThinkingConfig | undefined {\n if (!level || level === 'off') return undefined;\n const family = getGeminiThinkingFamily(modelId);\n if (!family) return undefined;\n\n const geminiLevel = geminiLevelForFamily(family, level);\n if (family === 'budget') return { thinkingBudget: GEMINI_25_BUDGETS[geminiLevel] };\n if (family === 'minimal-high') return { thinkingLevel: geminiLevel === 'low' ? 'minimal' : 'high' };\n return { thinkingLevel: geminiLevel };\n}\n\n/**\n * Create middleware that injects the resolved config into\n * `providerOptions.google.thinkingConfig`. Returns `undefined` when there is\n * nothing to inject, so callers wrap nothing.\n */\nexport function createGoogleThinkingMiddleware(\n modelId: string,\n level: ThinkingLevelSetting | undefined,\n): LanguageModelMiddleware | undefined {\n const config = resolveGoogleThinkingConfig(modelId, level);\n if (!config) return undefined;\n\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n const google = (params.providerOptions?.google ?? {}) as Record<string, unknown>;\n const thinkingConfig = (google.thinkingConfig ?? {}) as Record<string, unknown>;\n // Explicit caller settings win; Google rejects budget and level together.\n if (thinkingConfig.thinkingBudget !== undefined || thinkingConfig.thinkingLevel !== undefined) return params;\n params.providerOptions = {\n ...params.providerOptions,\n google: { ...google, thinkingConfig: { ...thinkingConfig, ...config } },\n } as typeof params.providerOptions;\n return params;\n },\n };\n}\n"],"mappings":";AAkBA,MAAM,oBAAiD;CAAE,KAAK;CAAM,QAAQ;CAAM,MAAM;AAAM;AAE9F,SAAS,wBAAwB,SAAmD;CAClF,MAAM,KAAK,QAAQ,YAAY;CAC/B,IAAI,GAAG,WAAW,YAAY,GAAG,OAAO;CAExC,IAAI,GAAG,WAAW,cAAc,GAAG,OAAO;CAE1C,IAAI,GAAG,WAAW,wBAAwB,KAAK,GAAG,WAAW,6BAA6B,GAAG,OAAO;CACpG,IAAI,aAAa,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,UAAU,KAAK,CAAC,GAAG,WAAW,UAAU,GAAG,OAAO;AAEhG;AAEA,SAAS,qBAAqB,QAA8B,OAAyC;CACnG,MAAM,eAAe,UAAU,WAAW,UAAU,QAAQ,SAAS;CAErE,KADoB,WAAW,cAAc,WAAW,mBACrC,iBAAiB,UAAU,OAAO;CACrD,OAAO;AACT;AAEA,SAAgB,uBAAuB,SAAiB,OAAkD;CACxG,MAAM,SAAS,wBAAwB,OAAO;CAC9C,OAAO,SAAS,qBAAqB,QAAQ,KAAK,IAAI;AACxD;;;;;AAMA,SAAgB,4BACd,SACA,OACkC;CAClC,IAAI,CAAC,SAAS,UAAU,OAAO,OAAO,KAAA;CACtC,MAAM,SAAS,wBAAwB,OAAO;CAC9C,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,MAAM,cAAc,qBAAqB,QAAQ,KAAK;CACtD,IAAI,WAAW,UAAU,OAAO,EAAE,gBAAgB,kBAAkB,aAAa;CACjF,IAAI,WAAW,gBAAgB,OAAO,EAAE,eAAe,gBAAgB,QAAQ,YAAY,OAAO;CAClG,OAAO,EAAE,eAAe,YAAY;AACtC;;;;;;AAOA,SAAgB,+BACd,SACA,OACqC;CACrC,MAAM,SAAS,4BAA4B,SAAS,KAAK;CACzD,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,OAAO;EACL,sBAAsB;EACtB,iBAAiB,OAAO,EAAE,aAAa;GACrC,MAAM,SAAU,OAAO,iBAAiB,UAAU,CAAC;GACnD,MAAM,iBAAkB,OAAO,kBAAkB,CAAC;GAElD,IAAI,eAAe,mBAAmB,KAAA,KAAa,eAAe,kBAAkB,KAAA,GAAW,OAAO;GACtG,OAAO,kBAAkB;IACvB,GAAG,OAAO;IACV,QAAQ;KAAE,GAAG;KAAQ,gBAAgB;MAAE,GAAG;MAAgB,GAAG;KAAO;IAAE;GACxE;GACA,OAAO;EACT;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai-codex.d.ts","sourceRoot":"","sources":["../../src/providers/openai-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAU5D;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAErE;AAOD,MAAM,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAIjD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,aAAa,CAY9F;AAMD,eAAO,MAAM,kCAAkC,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAOxF,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,uBAAuB,CA4BvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,uBAAuB,GAAG,SAAS,CAgBrC;AA2CD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,eAAe,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACjE,OAAO,KAAK,CAkDd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,KAAK,CAuC/E;AAwID;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,MAA4B,EACrC,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,WAAW,CAAC,EAAE,eAAe,CAAA;CAAE,GAC3G,iBAAiB,CAmCnB"}
1
+ {"version":3,"file":"openai-codex.d.ts","sourceRoot":"","sources":["../../src/providers/openai-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAU5D;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAK5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAErE;AAOD,MAAM,MAAM,aAAa,GAAG,oBAAoB,CAAC;AAIjD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,aAAa,CAI9F;AAKD,eAAO,MAAM,kCAAkC,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAOxF,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,uBAAuB,CA4BvF;AAED;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,uBAAuB,GAAG,SAAS,CAgBrC;AA2CD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,eAAe,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GACjE,OAAO,KAAK,CAkDd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,KAAK,CAuC/E;AAwID;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,MAA4B,EACrC,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,WAAW,CAAC,EAAE,eAAe,CAAA;CAAE,GAC3G,iBAAiB,CAmCnB"}
@@ -1,6 +1,7 @@
1
1
  import { AuthStorage } from "../auth/storage.js";
2
2
  import { ProviderAuthRequiredError } from "../auth/provider-auth-error.js";
3
3
  import { supportsMaxReasoningEffort } from "../thinking.js";
4
+ import { runCatalogThinkingLevel } from "../thinking-catalog.js";
4
5
  import { createOpenAI } from "@ai-sdk/openai";
5
6
  import { wrapLanguageModel } from "ai";
6
7
  //#region src/providers/openai-codex.ts
@@ -35,9 +36,8 @@ const CODEX_INSTRUCTIONS = `You are an interactive CLI tool that helps users wit
35
36
  IMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;
36
37
  const GPT5_MODEL_RE = /^gpt-5(?:\.|-|$)/;
37
38
  function getEffectiveThinkingLevel(modelId, level) {
38
- if (GPT5_MODEL_RE.test(modelId) && level === "off") return "low";
39
- if (level === "max" && !supportsMaxReasoningEffort(modelId)) return "xhigh";
40
- return level;
39
+ const requestedLevel = GPT5_MODEL_RE.test(modelId) && level === "off" ? "low" : level;
40
+ return runCatalogThinkingLevel(`openai/${modelId}`, requestedLevel);
41
41
  }
42
42
  const THINKING_LEVEL_TO_REASONING_EFFORT = {
43
43
  off: void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"openai-codex.js","names":[],"sources":["../../src/providers/openai-codex.ts"],"sourcesContent":["/**\n * OpenAI Codex OAuth Provider\n *\n * Uses OAuth tokens from AuthStorage to authenticate with ChatGPT Plus/Pro subscription.\n * This allows access to OpenAI models through the ChatGPT OAuth flow.\n *\n * Inspired by opencode's Codex plugin implementation:\n * https://github.com/sst/opencode/blob/main/packages/opencode/src/plugin/codex.ts\n */\n\nimport { createOpenAI } from '@ai-sdk/openai';\nimport type { MastraModelConfig } from '@mastra/core/llm';\nimport { wrapLanguageModel } from 'ai';\nimport type { LanguageModelMiddleware } from 'ai';\nimport { ProviderAuthRequiredError } from '../auth/provider-auth-error.js';\nimport { AuthStorage } from '../auth/storage.js';\nimport type { CredentialStore } from '../auth/types.js';\nimport { supportsMaxReasoningEffort } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nexport { supportsMaxReasoningEffort } from '../thinking.js';\n\n// Codex API endpoint (not standard OpenAI API)\nconst CODEX_API_ENDPOINT = 'https://chatgpt.com/backend-api/codex/responses';\nconst CODEX_ORIGINATOR = 'mastracode';\nconst CODEX_USER_AGENT = 'mastracode';\n\n// Singleton auth storage instance (shared with claude-max.ts)\nlet authStorageInstance: AuthStorage | null = null;\n\n/**\n * Get or create the shared AuthStorage instance\n */\nexport function getAuthStorage(): AuthStorage {\n if (!authStorageInstance) {\n authStorageInstance = new AuthStorage();\n }\n return authStorageInstance;\n}\n\n/**\n * Set a custom AuthStorage instance (useful for TUI integration)\n */\nexport function setAuthStorage(storage: AuthStorage | undefined): void {\n authStorageInstance = storage ?? null;\n}\n\n// Default instructions for Codex API (required)\nconst CODEX_INSTRUCTIONS = `You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\nIMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;\n\nexport type ThinkingLevel = ThinkingLevelSetting;\n\nconst GPT5_MODEL_RE = /^gpt-5(?:\\.|-|$)/;\n\nexport function getEffectiveThinkingLevel(modelId: string, level: ThinkingLevel): ThinkingLevel {\n // GPT-5.* models on Codex require at least low reasoning.\n if (GPT5_MODEL_RE.test(modelId) && level === 'off') {\n return 'low';\n }\n\n // Clamp `max` to `xhigh` only for models whose effort scale tops out there.\n if (level === 'max' && !supportsMaxReasoningEffort(modelId)) {\n return 'xhigh';\n }\n\n return level;\n}\n\n// Map thinkingLevel state values to OpenAI reasoningEffort values.\n// undefined means omit the parameter (no reasoning). Model-dependent clamping\n// (e.g. `max` → `xhigh` for pre-GPT-5.6 models) happens in\n// getEffectiveThinkingLevel before this lookup.\nexport const THINKING_LEVEL_TO_REASONING_EFFORT: Record<ThinkingLevel, string | undefined> = {\n off: undefined,\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n};\n\n/**\n * Create Codex middleware with the given reasoning effort level.\n */\nexport function createCodexMiddleware(reasoningEffort?: string): LanguageModelMiddleware {\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n // Remove topP if temperature is set (OpenAI doesn't like both)\n if (params.temperature !== undefined && params.temperature !== null) {\n delete params.topP;\n }\n\n // Codex API requires specific settings via providerOptions\n // Use type assertion to satisfy JSONValue constraints\n params.providerOptions = {\n ...params.providerOptions,\n openai: {\n ...(params.providerOptions?.openai ?? {}),\n instructions: CODEX_INSTRUCTIONS,\n // Codex API requires store to be false\n store: false,\n // Enable reasoning for Codex models — without this, the model\n // skips the reasoning/action phase and goes straight to final_answer,\n // resulting in narration instead of tool calls.\n ...(reasoningEffort ? { reasoningEffort } : {}),\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Create middleware that forwards a resolved reasoning effort to an\n * OpenAI-compatible provider as `providerOptions[providerKey].reasoningEffort`.\n *\n * Returns `undefined` when `reasoningEffort` is unset so callers wrap nothing\n * (e.g. thinking level `off`), leaving the wire request without a\n * `reasoning_effort` field. Unlike {@link createCodexMiddleware}, it does not\n * inject Codex-only options (instructions/store); it only sets reasoning\n * effort, keyed by the caller-supplied provider id.\n */\nexport function createReasoningEffortMiddleware(\n providerKey: string,\n reasoningEffort?: string,\n): LanguageModelMiddleware | undefined {\n if (!reasoningEffort) return undefined;\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n params.providerOptions = {\n ...params.providerOptions,\n [providerKey]: {\n ...(params.providerOptions?.[providerKey] ?? {}),\n reasoningEffort,\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Get a live OAuth bearer token for the Codex OAuth credential.\n *\n * Refreshes the token if it's expired, and returns the credential's\n * accountId alongside the access token. Throws if the user isn't logged in\n * or if the refresh fails.\n *\n * This is the only piece of Codex auth that is genuinely shared between\n * the main agent's fetch (`buildOpenAICodexOAuthFetch`) and the Stagehand\n * fetch (`buildCodexStagehandFetch`).\n */\nasync function getCodexBearer(\n authStorage?: CredentialStore,\n): Promise<{ accessToken: string; accountId: string | undefined }> {\n const storage = authStorage ?? getAuthStorage();\n storage.reload();\n\n let cred = storage.get('openai-codex');\n if (!cred || cred.type !== 'oauth') {\n throw new ProviderAuthRequiredError('Not logged in to OpenAI Codex.');\n }\n\n if (storage.getOAuthCredential) {\n cred = await storage.getOAuthCredential('openai-codex');\n if (!cred) throw new ProviderAuthRequiredError('Failed to refresh the OpenAI Codex token.');\n } else if (Date.now() >= cred.expires) {\n const refreshedToken = await storage.getApiKey('openai-codex');\n if (!refreshedToken) {\n throw new ProviderAuthRequiredError('Failed to refresh the OpenAI Codex token.');\n }\n storage.reload();\n const reloaded = storage.get('openai-codex');\n if (!reloaded || reloaded.type !== 'oauth') {\n throw new ProviderAuthRequiredError('Not logged in to OpenAI Codex.');\n }\n cred = { ...reloaded, access: refreshedToken };\n }\n\n return { accessToken: cred.access, accountId: (cred as any).accountId as string | undefined };\n}\n\n/**\n * Build a fetch function that handles OpenAI Codex OAuth.\n * Preserves non-authorization headers from init.\n * When rewriteUrl is true (default), rewrites /v1/responses and /chat/completions\n * to the Codex API endpoint. Set rewriteUrl: false for gateway usage where the\n * SDK already targets the correct URL.\n */\nexport function buildOpenAICodexOAuthFetch(\n opts: { authStorage?: CredentialStore; rewriteUrl?: boolean } = {},\n): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n const { accessToken, accountId } = await getCodexBearer(opts.authStorage);\n const { headers: initHeaders, ...requestInit } = init ?? {};\n const request = new Request(url, requestInit);\n\n // Preserve Request headers and let explicit init headers override them.\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (initHeaders) new Headers(initHeaders).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n if (!headers.has('originator')) {\n headers.set('originator', CODEX_ORIGINATOR);\n }\n if (!headers.has('User-Agent')) {\n headers.set('User-Agent', CODEX_USER_AGENT);\n }\n if (accountId) {\n headers.set('ChatGPT-Account-ID', accountId);\n }\n\n // URL rewriting — only when rewriteUrl !== false\n const parsed = new URL(request.url);\n const shouldRewrite =\n opts.rewriteUrl !== false &&\n (parsed.pathname.includes('/v1/responses') || parsed.pathname.includes('/chat/completions'));\n const finalUrl = shouldRewrite ? new URL(CODEX_API_ENDPOINT) : parsed;\n\n const body = request.method === 'GET' || request.method === 'HEAD' ? undefined : request.body;\n const finalRequest = new Request(finalUrl, {\n method: request.method,\n headers,\n body,\n signal: request.signal,\n redirect: request.redirect,\n integrity: request.integrity,\n ...(body ? ({ duplex: 'half' } as RequestInit) : {}),\n });\n try {\n return await fetch(finalRequest);\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, {\n requestUrl: finalUrl.toString(),\n });\n }\n throw error;\n }\n }) as typeof fetch;\n}\n\n/**\n * Build a fetch function for Stagehand-on-Codex.\n *\n * The Codex backend has two requirements that AI SDK's non-streaming\n * `generateText` path doesn't naturally satisfy:\n *\n * 1. `stream: true` must be set on every request body.\n * 2. The response is delivered as Server-Sent Events; AI SDK's\n * non-streaming code path expects a single JSON body.\n *\n * This fetch forces streaming on the outgoing request, collects the SSE\n * events, and synthesizes the non-streaming JSON shape that\n * `@ai-sdk/openai`'s Responses API parser expects.\n *\n * Headers, OAuth refresh, and URL targeting are handled by the caller via\n * `baseURL` / `headers` on the AI SDK provider; this fetch only injects the\n * live OAuth bearer per call.\n */\nexport function buildCodexStagehandFetch(authStorage: AuthStorage): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n // Refresh + inject the OAuth bearer per call.\n const { accessToken } = await getCodexBearer(authStorage);\n const { headers: initHeaders, ...requestInit } = init ?? {};\n const request = new Request(url, requestInit);\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (initHeaders) new Headers(initHeaders).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n headers.set('Accept', 'text/event-stream');\n\n // Stagehand sends JSON; force stream: true while preserving Request bodies.\n let body = await request.clone().text();\n try {\n const parsed = JSON.parse(body) as Record<string, unknown>;\n parsed.stream = true;\n body = JSON.stringify(parsed);\n if (!headers.has('content-type')) headers.set('content-type', 'application/json');\n } catch {\n // Not JSON; leave as-is.\n }\n\n const upstream = await fetch(\n new Request(request, {\n headers,\n ...(request.method === 'GET' || request.method === 'HEAD' ? {} : { body }),\n }),\n );\n if (!upstream.ok) return upstream;\n\n // Aggregate SSE -> synthesized non-streaming Response\n const aggregated = await aggregateCodexStream(upstream);\n return new Response(aggregated, {\n status: 200,\n headers: { 'content-type': 'application/json' },\n });\n }) as typeof fetch;\n}\n\n/**\n * Read an SSE Response and reduce it to a single JSON string matching the\n * non-streaming OpenAI Responses-API shape.\n *\n * Event vocabulary we care about (per OpenAI Responses API streaming):\n * - response.created → carries `response` object (id, model, usage stub)\n * - response.output_item.added/done → output items (message, reasoning, etc.)\n * - response.output_text.delta → text chunks\n * - response.completed → final `response` snapshot incl. usage\n * - response.error / error → bubble up as a thrown body\n *\n * Reasoning events (`response.reasoning_summary.*`) are intentionally ignored\n * for the non-streaming text response.\n */\nasync function aggregateCodexStream(response: Response): Promise<string> {\n if (!response.body) {\n throw new Error('Codex streaming response had no body');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n let finalResponse: any = null;\n let createdResponse: any = null;\n // Track output_items by index so we can rebuild the final array\n const items = new Map<number, any>();\n // Accumulate output_text deltas keyed by item_index + content_index\n const textBuffers = new Map<string, string>();\n\n const handleEvent = (event: { event?: string; data?: string }) => {\n if (!event.data || event.data === '[DONE]') return;\n let payload: any;\n try {\n payload = JSON.parse(event.data);\n } catch {\n return;\n }\n const type: string = payload.type ?? event.event ?? '';\n\n switch (type) {\n case 'response.created': {\n createdResponse = payload.response ?? createdResponse;\n break;\n }\n case 'response.output_item.added': {\n if (typeof payload.output_index === 'number' && payload.item) {\n items.set(payload.output_index, payload.item);\n }\n break;\n }\n case 'response.output_item.done': {\n if (typeof payload.output_index === 'number' && payload.item) {\n items.set(payload.output_index, payload.item);\n }\n break;\n }\n case 'response.output_text.delta': {\n const key = `${payload.output_index}:${payload.content_index ?? 0}`;\n textBuffers.set(key, (textBuffers.get(key) ?? '') + (payload.delta ?? ''));\n break;\n }\n case 'response.completed': {\n finalResponse = payload.response ?? finalResponse;\n break;\n }\n case 'response.error':\n case 'error': {\n throw new Error(`Codex stream error: ${JSON.stringify(payload.error ?? payload)}`);\n }\n default:\n // Ignore reasoning / unknown events\n break;\n }\n };\n\n // SSE parser: events separated by blank line; lines like \"event: x\" / \"data: y\"\n // Normalize CRLF→LF so \\r\\n\\r\\n event boundaries parse correctly (SSE spec allows CRLF).\n const processChunk = (chunk: string) => {\n buffer += chunk.replace(/\\r\\n/g, '\\n');\n let sepIdx: number;\n while ((sepIdx = buffer.indexOf('\\n\\n')) !== -1) {\n const raw = buffer.slice(0, sepIdx);\n buffer = buffer.slice(sepIdx + 2);\n const event: { event?: string; data?: string } = {};\n const dataLines: string[] = [];\n for (const line of raw.split('\\n')) {\n if (line.startsWith('event:')) {\n event.event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart());\n }\n }\n if (dataLines.length > 0) {\n event.data = dataLines.join('\\n');\n }\n handleEvent(event);\n }\n };\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n processChunk(decoder.decode(value, { stream: true }));\n }\n processChunk(decoder.decode());\n } finally {\n reader.releaseLock();\n }\n\n // Stitch accumulated text deltas back into their items\n const base = finalResponse ?? createdResponse ?? { output: [] };\n const finalItems = Array.from(items.entries())\n .sort(([a], [b]) => a - b)\n .map(([index, item]) => {\n // Patch message-type items' content text using buffered deltas\n if (item?.type === 'message' && Array.isArray(item.content)) {\n item.content = item.content.map((c: any, ci: number) => {\n const key = `${index}:${ci}`;\n if (textBuffers.has(key)) {\n return { ...c, text: textBuffers.get(key) };\n }\n return c;\n });\n }\n return item;\n });\n\n base.output = finalItems.length > 0 ? finalItems : (base.output ?? []);\n\n return JSON.stringify(base);\n}\n\n/**\n * Creates an OpenAI model using ChatGPT OAuth authentication\n * Uses OAuth tokens from AuthStorage (auto-refreshes when needed)\n *\n * IMPORTANT: This uses the Codex API endpoint, not the standard OpenAI API.\n * URLs are rewritten from /v1/responses or /chat/completions to the Codex endpoint.\n */\nexport function openaiCodexProvider(\n modelId: string = 'codex-mini-latest',\n options?: { thinkingLevel?: ThinkingLevel; headers?: Record<string, string>; authStorage?: CredentialStore },\n): MastraModelConfig {\n const requestedLevel: ThinkingLevel = options?.thinkingLevel ?? 'medium';\n const effectiveLevel = getEffectiveThinkingLevel(modelId, requestedLevel);\n const reasoningEffort = THINKING_LEVEL_TO_REASONING_EFFORT[effectiveLevel];\n const middleware = createCodexMiddleware(reasoningEffort);\n const headers = options?.headers;\n\n const baseURL = process.env.OPENAI_BASE_URL;\n\n // Test environment: use API key\n if (process.env.NODE_ENV === 'test' || process.env.VITEST) {\n const openai = createOpenAI({\n apiKey: 'test-api-key',\n baseURL,\n headers,\n });\n return wrapLanguageModel({\n model: openai.responses(modelId),\n middleware: [middleware],\n });\n }\n\n const openai = createOpenAI({\n apiKey: 'oauth-dummy-key',\n baseURL,\n headers,\n fetch: buildOpenAICodexOAuthFetch({ authStorage: options?.authStorage }) as any,\n });\n\n // Use the responses API for Codex models\n // Wrap with middleware\n return wrapLanguageModel({\n model: openai.responses(modelId),\n middleware: [middleware],\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsBA,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AAGzB,IAAI,sBAA0C;;;;AAK9C,SAAgB,iBAA8B;CAC5C,IAAI,CAAC,qBACH,sBAAsB,IAAI,YAAY;CAExC,OAAO;AACT;;;;AAKA,SAAgB,eAAe,SAAwC;CACrE,sBAAsB,WAAW;AACnC;AAGA,MAAM,qBAAqB;;;AAM3B,MAAM,gBAAgB;AAEtB,SAAgB,0BAA0B,SAAiB,OAAqC;CAE9F,IAAI,cAAc,KAAK,OAAO,KAAK,UAAU,OAC3C,OAAO;CAIT,IAAI,UAAU,SAAS,CAAC,2BAA2B,OAAO,GACxD,OAAO;CAGT,OAAO;AACT;AAMA,MAAa,qCAAgF;CAC3F,KAAK,KAAA;CACL,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACP,KAAK;AACP;;;;AAKA,SAAgB,sBAAsB,iBAAmD;CACvF,OAAO;EACL,sBAAsB;EACtB,iBAAiB,OAAO,EAAE,aAAa;GAErC,IAAI,OAAO,gBAAgB,KAAA,KAAa,OAAO,gBAAgB,MAC7D,OAAO,OAAO;GAKhB,OAAO,kBAAkB;IACvB,GAAG,OAAO;IACV,QAAQ;KACN,GAAI,OAAO,iBAAiB,UAAU,CAAC;KACvC,cAAc;KAEd,OAAO;KAIP,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;IAC/C;GACF;GAEA,OAAO;EACT;CACF;AACF;;;;;;;;;;;AAYA,SAAgB,gCACd,aACA,iBACqC;CACrC,IAAI,CAAC,iBAAiB,OAAO,KAAA;CAC7B,OAAO;EACL,sBAAsB;EACtB,iBAAiB,OAAO,EAAE,aAAa;GACrC,OAAO,kBAAkB;IACvB,GAAG,OAAO;KACT,cAAc;KACb,GAAI,OAAO,kBAAkB,gBAAgB,CAAC;KAC9C;IACF;GACF;GAEA,OAAO;EACT;CACF;AACF;;;;;;;;;;;;AAaA,eAAe,eACb,aACiE;CACjE,MAAM,UAAU,eAAe,eAAe;CAC9C,QAAQ,OAAO;CAEf,IAAI,OAAO,QAAQ,IAAI,cAAc;CACrC,IAAI,CAAC,QAAQ,KAAK,SAAS,SACzB,MAAM,IAAI,0BAA0B,gCAAgC;CAGtE,IAAI,QAAQ,oBAAoB;EAC9B,OAAO,MAAM,QAAQ,mBAAmB,cAAc;EACtD,IAAI,CAAC,MAAM,MAAM,IAAI,0BAA0B,2CAA2C;CAC5F,OAAO,IAAI,KAAK,IAAI,KAAK,KAAK,SAAS;EACrC,MAAM,iBAAiB,MAAM,QAAQ,UAAU,cAAc;EAC7D,IAAI,CAAC,gBACH,MAAM,IAAI,0BAA0B,2CAA2C;EAEjF,QAAQ,OAAO;EACf,MAAM,WAAW,QAAQ,IAAI,cAAc;EAC3C,IAAI,CAAC,YAAY,SAAS,SAAS,SACjC,MAAM,IAAI,0BAA0B,gCAAgC;EAEtE,OAAO;GAAE,GAAG;GAAU,QAAQ;EAAe;CAC/C;CAEA,OAAO;EAAE,aAAa,KAAK;EAAQ,WAAY,KAAa;CAAgC;AAC9F;;;;;;;;AASA,SAAgB,2BACd,OAAgE,CAAC,GACnD;CACd,QAAQ,OAAO,KAA6B,SAAuC;EACjF,MAAM,EAAE,aAAa,cAAc,MAAM,eAAe,KAAK,WAAW;EACxE,MAAM,EAAE,SAAS,aAAa,GAAG,gBAAgB,QAAQ,CAAC;EAC1D,MAAM,UAAU,IAAI,QAAQ,KAAK,WAAW;EAG5C,MAAM,UAAU,IAAI,QAAQ,eAAe,UAAU,IAAI,UAAU,KAAA,CAAS;EAC5E,IAAI,aAAa,IAAI,QAAQ,WAAW,CAAC,CAAC,SAAS,OAAO,QAAQ,QAAQ,IAAI,KAAK,KAAK,CAAC;EACzF,QAAQ,OAAO,eAAe;EAC9B,QAAQ,OAAO,WAAW;EAC1B,QAAQ,IAAI,iBAAiB,UAAU,aAAa;EACpD,IAAI,CAAC,QAAQ,IAAI,YAAY,GAC3B,QAAQ,IAAI,cAAc,gBAAgB;EAE5C,IAAI,CAAC,QAAQ,IAAI,YAAY,GAC3B,QAAQ,IAAI,cAAc,gBAAgB;EAE5C,IAAI,WACF,QAAQ,IAAI,sBAAsB,SAAS;EAI7C,MAAM,SAAS,IAAI,IAAI,QAAQ,GAAG;EAIlC,MAAM,WAFJ,KAAK,eAAe,UACnB,OAAO,SAAS,SAAS,eAAe,KAAK,OAAO,SAAS,SAAS,mBAAmB,KAC3D,IAAI,IAAI,kBAAkB,IAAI;EAE/D,MAAM,OAAO,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAAS,KAAA,IAAY,QAAQ;EACzF,MAAM,eAAe,IAAI,QAAQ,UAAU;GACzC,QAAQ,QAAQ;GAChB;GACA;GACA,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,WAAW,QAAQ;GACnB,GAAI,OAAQ,EAAE,QAAQ,OAAO,IAAoB,CAAC;EACpD,CAAC;EACD,IAAI;GACF,OAAO,MAAM,MAAM,YAAY;EACjC,SAAS,OAAO;GACd,IAAI,SAAS,OAAO,UAAU,UAC5B,OAAO,OAAO,OAAkC,EAC9C,YAAY,SAAS,SAAS,EAChC,CAAC;GAEH,MAAM;EACR;CACF;AACF;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,yBAAyB,aAAwC;CAC/E,QAAQ,OAAO,KAA6B,SAAuC;EAEjF,MAAM,EAAE,gBAAgB,MAAM,eAAe,WAAW;EACxD,MAAM,EAAE,SAAS,aAAa,GAAG,gBAAgB,QAAQ,CAAC;EAC1D,MAAM,UAAU,IAAI,QAAQ,KAAK,WAAW;EAC5C,MAAM,UAAU,IAAI,QAAQ,eAAe,UAAU,IAAI,UAAU,KAAA,CAAS;EAC5E,IAAI,aAAa,IAAI,QAAQ,WAAW,CAAC,CAAC,SAAS,OAAO,QAAQ,QAAQ,IAAI,KAAK,KAAK,CAAC;EACzF,QAAQ,OAAO,eAAe;EAC9B,QAAQ,OAAO,WAAW;EAC1B,QAAQ,IAAI,iBAAiB,UAAU,aAAa;EACpD,QAAQ,IAAI,UAAU,mBAAmB;EAGzC,IAAI,OAAO,MAAM,QAAQ,MAAM,CAAC,CAAC,KAAK;EACtC,IAAI;GACF,MAAM,SAAS,KAAK,MAAM,IAAI;GAC9B,OAAO,SAAS;GAChB,OAAO,KAAK,UAAU,MAAM;GAC5B,IAAI,CAAC,QAAQ,IAAI,cAAc,GAAG,QAAQ,IAAI,gBAAgB,kBAAkB;EAClF,QAAQ,CAER;EAEA,MAAM,WAAW,MAAM,MACrB,IAAI,QAAQ,SAAS;GACnB;GACA,GAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAAS,CAAC,IAAI,EAAE,KAAK;EAC1E,CAAC,CACH;EACA,IAAI,CAAC,SAAS,IAAI,OAAO;EAGzB,MAAM,aAAa,MAAM,qBAAqB,QAAQ;EACtD,OAAO,IAAI,SAAS,YAAY;GAC9B,QAAQ;GACR,SAAS,EAAE,gBAAgB,mBAAmB;EAChD,CAAC;CACH;AACF;;;;;;;;;;;;;;;AAgBA,eAAe,qBAAqB,UAAqC;CACvE,IAAI,CAAC,SAAS,MACZ,MAAM,IAAI,MAAM,sCAAsC;CAGxD,MAAM,SAAS,SAAS,KAAK,UAAU;CACvC,MAAM,UAAU,IAAI,YAAY,OAAO;CACvC,IAAI,SAAS;CAEb,IAAI,gBAAqB;CACzB,IAAI,kBAAuB;CAE3B,MAAM,wBAAQ,IAAI,IAAiB;CAEnC,MAAM,8BAAc,IAAI,IAAoB;CAE5C,MAAM,eAAe,UAA6C;EAChE,IAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,UAAU;EAC5C,IAAI;EACJ,IAAI;GACF,UAAU,KAAK,MAAM,MAAM,IAAI;EACjC,QAAQ;GACN;EACF;EAGA,QAFqB,QAAQ,QAAQ,MAAM,SAAS,IAEpD;GACE,KAAK;IACH,kBAAkB,QAAQ,YAAY;IACtC;GAEF,KAAK;IACH,IAAI,OAAO,QAAQ,iBAAiB,YAAY,QAAQ,MACtD,MAAM,IAAI,QAAQ,cAAc,QAAQ,IAAI;IAE9C;GAEF,KAAK;IACH,IAAI,OAAO,QAAQ,iBAAiB,YAAY,QAAQ,MACtD,MAAM,IAAI,QAAQ,cAAc,QAAQ,IAAI;IAE9C;GAEF,KAAK,8BAA8B;IACjC,MAAM,MAAM,GAAG,QAAQ,aAAa,GAAG,QAAQ,iBAAiB;IAChE,YAAY,IAAI,MAAM,YAAY,IAAI,GAAG,KAAK,OAAO,QAAQ,SAAS,GAAG;IACzE;GACF;GACA,KAAK;IACH,gBAAgB,QAAQ,YAAY;IACpC;GAEF,KAAK;GACL,KAAK,SACH,MAAM,IAAI,MAAM,uBAAuB,KAAK,UAAU,QAAQ,SAAS,OAAO,GAAG;GAEnF,SAEE;EACJ;CACF;CAIA,MAAM,gBAAgB,UAAkB;EACtC,UAAU,MAAM,QAAQ,SAAS,IAAI;EACrC,IAAI;EACJ,QAAQ,SAAS,OAAO,QAAQ,MAAM,OAAO,IAAI;GAC/C,MAAM,MAAM,OAAO,MAAM,GAAG,MAAM;GAClC,SAAS,OAAO,MAAM,SAAS,CAAC;GAChC,MAAM,QAA2C,CAAC;GAClD,MAAM,YAAsB,CAAC;GAC7B,KAAK,MAAM,QAAQ,IAAI,MAAM,IAAI,GAC/B,IAAI,KAAK,WAAW,QAAQ,GAC1B,MAAM,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK;QAC5B,IAAI,KAAK,WAAW,OAAO,GAChC,UAAU,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;GAG5C,IAAI,UAAU,SAAS,GACrB,MAAM,OAAO,UAAU,KAAK,IAAI;GAElC,YAAY,KAAK;EACnB;CACF;CAEA,IAAI;EACF,OAAO,MAAM;GACX,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,aAAa,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;EACtD;EACA,aAAa,QAAQ,OAAO,CAAC;CAC/B,UAAU;EACR,OAAO,YAAY;CACrB;CAGA,MAAM,OAAO,iBAAiB,mBAAmB,EAAE,QAAQ,CAAC,EAAE;CAC9D,MAAM,aAAa,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,CAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CACzB,KAAK,CAAC,OAAO,UAAU;EAEtB,IAAI,MAAM,SAAS,aAAa,MAAM,QAAQ,KAAK,OAAO,GACxD,KAAK,UAAU,KAAK,QAAQ,KAAK,GAAQ,OAAe;GACtD,MAAM,MAAM,GAAG,MAAM,GAAG;GACxB,IAAI,YAAY,IAAI,GAAG,GACrB,OAAO;IAAE,GAAG;IAAG,MAAM,YAAY,IAAI,GAAG;GAAE;GAE5C,OAAO;EACT,CAAC;EAEH,OAAO;CACT,CAAC;CAEH,KAAK,SAAS,WAAW,SAAS,IAAI,aAAc,KAAK,UAAU,CAAC;CAEpE,OAAO,KAAK,UAAU,IAAI;AAC5B;;;;;;;;AASA,SAAgB,oBACd,UAAkB,qBAClB,SACmB;CAEnB,MAAM,iBAAiB,0BAA0B,SADX,SAAS,iBAAiB,QACQ;CACxE,MAAM,kBAAkB,mCAAmC;CAC3D,MAAM,aAAa,sBAAsB,eAAe;CACxD,MAAM,UAAU,SAAS;CAEzB,MAAM,UAAU,QAAQ,IAAI;CAG5B,IAAI,QAAQ,IAAI,aAAa,UAAU,QAAQ,IAAI,QAMjD,OAAO,kBAAkB;EACvB,OANa,aAAa;GAC1B,QAAQ;GACR;GACA;EACF,CAEc,CAAC,CAAC,UAAU,OAAO;EAC/B,YAAY,CAAC,UAAU;CACzB,CAAC;CAYH,OAAO,kBAAkB;EACvB,OAVa,aAAa;GAC1B,QAAQ;GACR;GACA;GACA,OAAO,2BAA2B,EAAE,aAAa,SAAS,YAAY,CAAC;EACzE,CAKc,CAAC,CAAC,UAAU,OAAO;EAC/B,YAAY,CAAC,UAAU;CACzB,CAAC;AACH"}
1
+ {"version":3,"file":"openai-codex.js","names":[],"sources":["../../src/providers/openai-codex.ts"],"sourcesContent":["/**\n * OpenAI Codex OAuth Provider\n *\n * Uses OAuth tokens from AuthStorage to authenticate with ChatGPT Plus/Pro subscription.\n * This allows access to OpenAI models through the ChatGPT OAuth flow.\n *\n * Inspired by opencode's Codex plugin implementation:\n * https://github.com/sst/opencode/blob/main/packages/opencode/src/plugin/codex.ts\n */\n\nimport { createOpenAI } from '@ai-sdk/openai';\nimport type { MastraModelConfig } from '@mastra/core/llm';\nimport { wrapLanguageModel } from 'ai';\nimport type { LanguageModelMiddleware } from 'ai';\nimport { ProviderAuthRequiredError } from '../auth/provider-auth-error.js';\nimport { AuthStorage } from '../auth/storage.js';\nimport type { CredentialStore } from '../auth/types.js';\nimport { runCatalogThinkingLevel } from '../thinking-catalog.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nexport { supportsMaxReasoningEffort } from '../thinking.js';\n\n// Codex API endpoint (not standard OpenAI API)\nconst CODEX_API_ENDPOINT = 'https://chatgpt.com/backend-api/codex/responses';\nconst CODEX_ORIGINATOR = 'mastracode';\nconst CODEX_USER_AGENT = 'mastracode';\n\n// Singleton auth storage instance (shared with claude-max.ts)\nlet authStorageInstance: AuthStorage | null = null;\n\n/**\n * Get or create the shared AuthStorage instance\n */\nexport function getAuthStorage(): AuthStorage {\n if (!authStorageInstance) {\n authStorageInstance = new AuthStorage();\n }\n return authStorageInstance;\n}\n\n/**\n * Set a custom AuthStorage instance (useful for TUI integration)\n */\nexport function setAuthStorage(storage: AuthStorage | undefined): void {\n authStorageInstance = storage ?? null;\n}\n\n// Default instructions for Codex API (required)\nconst CODEX_INSTRUCTIONS = `You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\nIMPORTANT: You should be concise, direct, and helpful. Focus on solving the user's problem efficiently.`;\n\nexport type ThinkingLevel = ThinkingLevelSetting;\n\nconst GPT5_MODEL_RE = /^gpt-5(?:\\.|-|$)/;\n\nexport function getEffectiveThinkingLevel(modelId: string, level: ThinkingLevel): ThinkingLevel {\n // GPT-5.* models on Codex require at least low reasoning.\n const requestedLevel = GPT5_MODEL_RE.test(modelId) && level === 'off' ? 'low' : level;\n return runCatalogThinkingLevel(`openai/${modelId}`, requestedLevel);\n}\n\n// Map thinkingLevel state values to OpenAI reasoningEffort values.\n// undefined means omit the parameter (no reasoning). Model-dependent fitting\n// happens in getEffectiveThinkingLevel before this lookup.\nexport const THINKING_LEVEL_TO_REASONING_EFFORT: Record<ThinkingLevel, string | undefined> = {\n off: undefined,\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n};\n\n/**\n * Create Codex middleware with the given reasoning effort level.\n */\nexport function createCodexMiddleware(reasoningEffort?: string): LanguageModelMiddleware {\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n // Remove topP if temperature is set (OpenAI doesn't like both)\n if (params.temperature !== undefined && params.temperature !== null) {\n delete params.topP;\n }\n\n // Codex API requires specific settings via providerOptions\n // Use type assertion to satisfy JSONValue constraints\n params.providerOptions = {\n ...params.providerOptions,\n openai: {\n ...(params.providerOptions?.openai ?? {}),\n instructions: CODEX_INSTRUCTIONS,\n // Codex API requires store to be false\n store: false,\n // Enable reasoning for Codex models — without this, the model\n // skips the reasoning/action phase and goes straight to final_answer,\n // resulting in narration instead of tool calls.\n ...(reasoningEffort ? { reasoningEffort } : {}),\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Create middleware that forwards a resolved reasoning effort to an\n * OpenAI-compatible provider as `providerOptions[providerKey].reasoningEffort`.\n *\n * Returns `undefined` when `reasoningEffort` is unset so callers wrap nothing\n * (e.g. thinking level `off`), leaving the wire request without a\n * `reasoning_effort` field. Unlike {@link createCodexMiddleware}, it does not\n * inject Codex-only options (instructions/store); it only sets reasoning\n * effort, keyed by the caller-supplied provider id.\n */\nexport function createReasoningEffortMiddleware(\n providerKey: string,\n reasoningEffort?: string,\n): LanguageModelMiddleware | undefined {\n if (!reasoningEffort) return undefined;\n return {\n specificationVersion: 'v3',\n transformParams: async ({ params }) => {\n params.providerOptions = {\n ...params.providerOptions,\n [providerKey]: {\n ...(params.providerOptions?.[providerKey] ?? {}),\n reasoningEffort,\n },\n } as typeof params.providerOptions;\n\n return params;\n },\n };\n}\n\n/**\n * Get a live OAuth bearer token for the Codex OAuth credential.\n *\n * Refreshes the token if it's expired, and returns the credential's\n * accountId alongside the access token. Throws if the user isn't logged in\n * or if the refresh fails.\n *\n * This is the only piece of Codex auth that is genuinely shared between\n * the main agent's fetch (`buildOpenAICodexOAuthFetch`) and the Stagehand\n * fetch (`buildCodexStagehandFetch`).\n */\nasync function getCodexBearer(\n authStorage?: CredentialStore,\n): Promise<{ accessToken: string; accountId: string | undefined }> {\n const storage = authStorage ?? getAuthStorage();\n storage.reload();\n\n let cred = storage.get('openai-codex');\n if (!cred || cred.type !== 'oauth') {\n throw new ProviderAuthRequiredError('Not logged in to OpenAI Codex.');\n }\n\n if (storage.getOAuthCredential) {\n cred = await storage.getOAuthCredential('openai-codex');\n if (!cred) throw new ProviderAuthRequiredError('Failed to refresh the OpenAI Codex token.');\n } else if (Date.now() >= cred.expires) {\n const refreshedToken = await storage.getApiKey('openai-codex');\n if (!refreshedToken) {\n throw new ProviderAuthRequiredError('Failed to refresh the OpenAI Codex token.');\n }\n storage.reload();\n const reloaded = storage.get('openai-codex');\n if (!reloaded || reloaded.type !== 'oauth') {\n throw new ProviderAuthRequiredError('Not logged in to OpenAI Codex.');\n }\n cred = { ...reloaded, access: refreshedToken };\n }\n\n return { accessToken: cred.access, accountId: (cred as any).accountId as string | undefined };\n}\n\n/**\n * Build a fetch function that handles OpenAI Codex OAuth.\n * Preserves non-authorization headers from init.\n * When rewriteUrl is true (default), rewrites /v1/responses and /chat/completions\n * to the Codex API endpoint. Set rewriteUrl: false for gateway usage where the\n * SDK already targets the correct URL.\n */\nexport function buildOpenAICodexOAuthFetch(\n opts: { authStorage?: CredentialStore; rewriteUrl?: boolean } = {},\n): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n const { accessToken, accountId } = await getCodexBearer(opts.authStorage);\n const { headers: initHeaders, ...requestInit } = init ?? {};\n const request = new Request(url, requestInit);\n\n // Preserve Request headers and let explicit init headers override them.\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (initHeaders) new Headers(initHeaders).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n if (!headers.has('originator')) {\n headers.set('originator', CODEX_ORIGINATOR);\n }\n if (!headers.has('User-Agent')) {\n headers.set('User-Agent', CODEX_USER_AGENT);\n }\n if (accountId) {\n headers.set('ChatGPT-Account-ID', accountId);\n }\n\n // URL rewriting — only when rewriteUrl !== false\n const parsed = new URL(request.url);\n const shouldRewrite =\n opts.rewriteUrl !== false &&\n (parsed.pathname.includes('/v1/responses') || parsed.pathname.includes('/chat/completions'));\n const finalUrl = shouldRewrite ? new URL(CODEX_API_ENDPOINT) : parsed;\n\n const body = request.method === 'GET' || request.method === 'HEAD' ? undefined : request.body;\n const finalRequest = new Request(finalUrl, {\n method: request.method,\n headers,\n body,\n signal: request.signal,\n redirect: request.redirect,\n integrity: request.integrity,\n ...(body ? ({ duplex: 'half' } as RequestInit) : {}),\n });\n try {\n return await fetch(finalRequest);\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, {\n requestUrl: finalUrl.toString(),\n });\n }\n throw error;\n }\n }) as typeof fetch;\n}\n\n/**\n * Build a fetch function for Stagehand-on-Codex.\n *\n * The Codex backend has two requirements that AI SDK's non-streaming\n * `generateText` path doesn't naturally satisfy:\n *\n * 1. `stream: true` must be set on every request body.\n * 2. The response is delivered as Server-Sent Events; AI SDK's\n * non-streaming code path expects a single JSON body.\n *\n * This fetch forces streaming on the outgoing request, collects the SSE\n * events, and synthesizes the non-streaming JSON shape that\n * `@ai-sdk/openai`'s Responses API parser expects.\n *\n * Headers, OAuth refresh, and URL targeting are handled by the caller via\n * `baseURL` / `headers` on the AI SDK provider; this fetch only injects the\n * live OAuth bearer per call.\n */\nexport function buildCodexStagehandFetch(authStorage: AuthStorage): typeof fetch {\n return (async (url: string | URL | Request, init?: Parameters<typeof fetch>[1]) => {\n // Refresh + inject the OAuth bearer per call.\n const { accessToken } = await getCodexBearer(authStorage);\n const { headers: initHeaders, ...requestInit } = init ?? {};\n const request = new Request(url, requestInit);\n const headers = new Headers(url instanceof Request ? url.headers : undefined);\n if (initHeaders) new Headers(initHeaders).forEach((value, key) => headers.set(key, value));\n headers.delete('authorization');\n headers.delete('x-api-key');\n headers.set('Authorization', `Bearer ${accessToken}`);\n headers.set('Accept', 'text/event-stream');\n\n // Stagehand sends JSON; force stream: true while preserving Request bodies.\n let body = await request.clone().text();\n try {\n const parsed = JSON.parse(body) as Record<string, unknown>;\n parsed.stream = true;\n body = JSON.stringify(parsed);\n if (!headers.has('content-type')) headers.set('content-type', 'application/json');\n } catch {\n // Not JSON; leave as-is.\n }\n\n const upstream = await fetch(\n new Request(request, {\n headers,\n ...(request.method === 'GET' || request.method === 'HEAD' ? {} : { body }),\n }),\n );\n if (!upstream.ok) return upstream;\n\n // Aggregate SSE -> synthesized non-streaming Response\n const aggregated = await aggregateCodexStream(upstream);\n return new Response(aggregated, {\n status: 200,\n headers: { 'content-type': 'application/json' },\n });\n }) as typeof fetch;\n}\n\n/**\n * Read an SSE Response and reduce it to a single JSON string matching the\n * non-streaming OpenAI Responses-API shape.\n *\n * Event vocabulary we care about (per OpenAI Responses API streaming):\n * - response.created → carries `response` object (id, model, usage stub)\n * - response.output_item.added/done → output items (message, reasoning, etc.)\n * - response.output_text.delta → text chunks\n * - response.completed → final `response` snapshot incl. usage\n * - response.error / error → bubble up as a thrown body\n *\n * Reasoning events (`response.reasoning_summary.*`) are intentionally ignored\n * for the non-streaming text response.\n */\nasync function aggregateCodexStream(response: Response): Promise<string> {\n if (!response.body) {\n throw new Error('Codex streaming response had no body');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder('utf-8');\n let buffer = '';\n\n let finalResponse: any = null;\n let createdResponse: any = null;\n // Track output_items by index so we can rebuild the final array\n const items = new Map<number, any>();\n // Accumulate output_text deltas keyed by item_index + content_index\n const textBuffers = new Map<string, string>();\n\n const handleEvent = (event: { event?: string; data?: string }) => {\n if (!event.data || event.data === '[DONE]') return;\n let payload: any;\n try {\n payload = JSON.parse(event.data);\n } catch {\n return;\n }\n const type: string = payload.type ?? event.event ?? '';\n\n switch (type) {\n case 'response.created': {\n createdResponse = payload.response ?? createdResponse;\n break;\n }\n case 'response.output_item.added': {\n if (typeof payload.output_index === 'number' && payload.item) {\n items.set(payload.output_index, payload.item);\n }\n break;\n }\n case 'response.output_item.done': {\n if (typeof payload.output_index === 'number' && payload.item) {\n items.set(payload.output_index, payload.item);\n }\n break;\n }\n case 'response.output_text.delta': {\n const key = `${payload.output_index}:${payload.content_index ?? 0}`;\n textBuffers.set(key, (textBuffers.get(key) ?? '') + (payload.delta ?? ''));\n break;\n }\n case 'response.completed': {\n finalResponse = payload.response ?? finalResponse;\n break;\n }\n case 'response.error':\n case 'error': {\n throw new Error(`Codex stream error: ${JSON.stringify(payload.error ?? payload)}`);\n }\n default:\n // Ignore reasoning / unknown events\n break;\n }\n };\n\n // SSE parser: events separated by blank line; lines like \"event: x\" / \"data: y\"\n // Normalize CRLF→LF so \\r\\n\\r\\n event boundaries parse correctly (SSE spec allows CRLF).\n const processChunk = (chunk: string) => {\n buffer += chunk.replace(/\\r\\n/g, '\\n');\n let sepIdx: number;\n while ((sepIdx = buffer.indexOf('\\n\\n')) !== -1) {\n const raw = buffer.slice(0, sepIdx);\n buffer = buffer.slice(sepIdx + 2);\n const event: { event?: string; data?: string } = {};\n const dataLines: string[] = [];\n for (const line of raw.split('\\n')) {\n if (line.startsWith('event:')) {\n event.event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart());\n }\n }\n if (dataLines.length > 0) {\n event.data = dataLines.join('\\n');\n }\n handleEvent(event);\n }\n };\n\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n processChunk(decoder.decode(value, { stream: true }));\n }\n processChunk(decoder.decode());\n } finally {\n reader.releaseLock();\n }\n\n // Stitch accumulated text deltas back into their items\n const base = finalResponse ?? createdResponse ?? { output: [] };\n const finalItems = Array.from(items.entries())\n .sort(([a], [b]) => a - b)\n .map(([index, item]) => {\n // Patch message-type items' content text using buffered deltas\n if (item?.type === 'message' && Array.isArray(item.content)) {\n item.content = item.content.map((c: any, ci: number) => {\n const key = `${index}:${ci}`;\n if (textBuffers.has(key)) {\n return { ...c, text: textBuffers.get(key) };\n }\n return c;\n });\n }\n return item;\n });\n\n base.output = finalItems.length > 0 ? finalItems : (base.output ?? []);\n\n return JSON.stringify(base);\n}\n\n/**\n * Creates an OpenAI model using ChatGPT OAuth authentication\n * Uses OAuth tokens from AuthStorage (auto-refreshes when needed)\n *\n * IMPORTANT: This uses the Codex API endpoint, not the standard OpenAI API.\n * URLs are rewritten from /v1/responses or /chat/completions to the Codex endpoint.\n */\nexport function openaiCodexProvider(\n modelId: string = 'codex-mini-latest',\n options?: { thinkingLevel?: ThinkingLevel; headers?: Record<string, string>; authStorage?: CredentialStore },\n): MastraModelConfig {\n const requestedLevel: ThinkingLevel = options?.thinkingLevel ?? 'medium';\n const effectiveLevel = getEffectiveThinkingLevel(modelId, requestedLevel);\n const reasoningEffort = THINKING_LEVEL_TO_REASONING_EFFORT[effectiveLevel];\n const middleware = createCodexMiddleware(reasoningEffort);\n const headers = options?.headers;\n\n const baseURL = process.env.OPENAI_BASE_URL;\n\n // Test environment: use API key\n if (process.env.NODE_ENV === 'test' || process.env.VITEST) {\n const openai = createOpenAI({\n apiKey: 'test-api-key',\n baseURL,\n headers,\n });\n return wrapLanguageModel({\n model: openai.responses(modelId),\n middleware: [middleware],\n });\n }\n\n const openai = createOpenAI({\n apiKey: 'oauth-dummy-key',\n baseURL,\n headers,\n fetch: buildOpenAICodexOAuthFetch({ authStorage: options?.authStorage }) as any,\n });\n\n // Use the responses API for Codex models\n // Wrap with middleware\n return wrapLanguageModel({\n model: openai.responses(modelId),\n middleware: [middleware],\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ThinkingLevelSetting } from './thinking.js';
2
+ export declare function runCatalogThinkingLevel(modelId: string, level: ThinkingLevelSetting): ThinkingLevelSetting;
3
+ export declare function getCatalogThinkingLevels(modelId: string): ThinkingLevelSetting[];
4
+ //# sourceMappingURL=thinking-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinking-catalog.d.ts","sourceRoot":"","sources":["../src/thinking-catalog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,oBAAoB,CAE1G;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAEhF"}
@@ -0,0 +1,13 @@
1
+ import { getAvailableThinkingLevelsForModel, runThinkingLevel } from "./thinking.js";
2
+ import { getModelReasoningOptions } from "@mastra/core/llm";
3
+ //#region src/thinking-catalog.ts
4
+ function runCatalogThinkingLevel(modelId, level) {
5
+ return runThinkingLevel(modelId, level, getModelReasoningOptions(modelId));
6
+ }
7
+ function getCatalogThinkingLevels(modelId) {
8
+ return getAvailableThinkingLevelsForModel(modelId, getModelReasoningOptions(modelId));
9
+ }
10
+ //#endregion
11
+ export { getCatalogThinkingLevels, runCatalogThinkingLevel };
12
+
13
+ //# sourceMappingURL=thinking-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinking-catalog.js","names":[],"sources":["../src/thinking-catalog.ts"],"sourcesContent":["import { getModelReasoningOptions } from '@mastra/core/llm';\nimport { getAvailableThinkingLevelsForModel, runThinkingLevel } from './thinking.js';\nimport type { ThinkingLevelSetting } from './thinking.js';\n\nexport function runCatalogThinkingLevel(modelId: string, level: ThinkingLevelSetting): ThinkingLevelSetting {\n return runThinkingLevel(modelId, level, getModelReasoningOptions(modelId));\n}\n\nexport function getCatalogThinkingLevels(modelId: string): ThinkingLevelSetting[] {\n return getAvailableThinkingLevelsForModel(modelId, getModelReasoningOptions(modelId));\n}\n"],"mappings":";;;AAIA,SAAgB,wBAAwB,SAAiB,OAAmD;CAC1G,OAAO,iBAAiB,SAAS,OAAO,yBAAyB,OAAO,CAAC;AAC3E;AAEA,SAAgB,yBAAyB,SAAyC;CAChF,OAAO,mCAAmC,SAAS,yBAAyB,OAAO,CAAC;AACtF"}
@@ -1,4 +1,6 @@
1
+ import type { ModelReasoningOption } from '@mastra/core/llm';
1
2
  export type ThinkingLevelSetting = 'off' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
3
+ export type ActiveThinkingLevel = Exclude<ThinkingLevelSetting, 'off'>;
2
4
  export type ThinkingLevelSource = 'mode-default' | 'global';
3
5
  export interface ThinkingDefaults {
4
6
  globalDefault: ThinkingLevelSetting;
@@ -24,7 +26,8 @@ export type ThinkCommandAction = {
24
26
  };
25
27
  export declare function isThinkingLevelSetting(value: unknown): value is ThinkingLevelSetting;
26
28
  export declare function supportsMaxReasoningEffort(modelId: string): boolean;
27
- export declare function getAvailableThinkingLevelsForModel(modelId: string): ThinkingLevelSetting[];
29
+ export declare function runThinkingLevel(modelId: string, level: ThinkingLevelSetting, reasoningOptions: readonly ModelReasoningOption[] | undefined): ThinkingLevelSetting;
30
+ export declare function getAvailableThinkingLevelsForModel(modelId: string, reasoningOptions?: readonly ModelReasoningOption[]): ThinkingLevelSetting[];
28
31
  export declare function parseThinkCommand(input: string, levels?: readonly ThinkingLevelSetting[]): ThinkCommandAction;
29
32
  export declare function resolveDefaultThinkingLevel(defaults: ThinkingDefaults, mode?: string | null): {
30
33
  level: ThinkingLevelSetting;
@@ -1 +1 @@
1
- {"version":3,"file":"thinking.d.ts","sourceRoot":"","sources":["../src/thinking.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEvF,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,oBAAoB,CAAC;IACpC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,qBAAqB,EAAE,oBAAoB,EAAqD,CAAC;AAE9G,eAAO,MAAM,wBAAwB;;;;CAIpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAAE,CAAC;AAIhF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAK1F;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,SAAS,oBAAoB,EAA0B,GAC9D,kBAAkB,CAMpB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAG9D"}
1
+ {"version":3,"file":"thinking.d.ts","sourceRoot":"","sources":["../src/thinking.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAS7D,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEvF,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AAEvE,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,oBAAoB,CAAC;IACpC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,qBAAqB,EAAE,oBAAoB,EAAqD,CAAC;AAI9G,eAAO,MAAM,wBAAwB;;;;CAIpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAAE,CAAC;AAIhF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOnE;AA0DD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,EAC3B,gBAAgB,EAAE,SAAS,oBAAoB,EAAE,GAAG,SAAS,GAC5D,oBAAoB,CAYtB;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,SAAS,oBAAoB,EAAE,GACjD,oBAAoB,EAAE,CAExB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,SAAS,oBAAoB,EAA0B,GAC9D,kBAAkB,CAMpB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAG9D"}