@mastra/code-sdk 1.8.2-alpha.0 → 1.8.2-alpha.2
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.
- package/dist/agent-connections/signal-provider.d.ts +1 -2
- package/dist/agent-connections/signal-provider.d.ts.map +1 -1
- package/dist/agent-connections/tools.d.ts +1 -2
- package/dist/agent-connections/tools.d.ts.map +1 -1
- package/dist/agent-connections/tools.js +12 -18
- package/dist/agent-connections/tools.js.map +1 -1
- package/dist/agents/mastracode-gateway.d.ts.map +1 -1
- package/dist/agents/mastracode-gateway.js +41 -15
- package/dist/agents/mastracode-gateway.js.map +1 -1
- package/dist/agents/modes/build.d.ts +6 -4
- package/dist/agents/modes/build.d.ts.map +1 -1
- package/dist/agents/modes/build.js +0 -13
- package/dist/agents/modes/build.js.map +1 -1
- package/dist/agents/modes/explore.d.ts +4 -4
- package/dist/agents/modes/explore.d.ts.map +1 -1
- package/dist/agents/modes/explore.js +0 -14
- package/dist/agents/modes/explore.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +3 -1
- package/dist/plugins/loader.js.map +1 -1
- package/dist/providers/google-thinking.d.ts +29 -0
- package/dist/providers/google-thinking.d.ts.map +1 -0
- package/dist/providers/google-thinking.js +51 -0
- package/dist/providers/google-thinking.js.map +1 -0
- package/dist/providers/openai-codex.d.ts +11 -0
- package/dist/providers/openai-codex.d.ts.map +1 -1
- package/dist/providers/openai-codex.js +27 -1
- package/dist/providers/openai-codex.js.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","names":[],"sources":["../../src/plugins/loader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { isSignalProvider } from '@mastra/core/signals';\nimport type { SignalProvider } from '@mastra/core/signals';\n\nimport type {\n MastraCodePlugin,\n MastraCodePluginConfigSchema,\n MastraCodePluginConfigValues,\n MastraCodePluginContext,\n MastraCodePluginProcessorEntries,\n MastraCodePluginRuntime,\n MastraCodePluginSignalProviderEntries,\n MastraCodePluginToolEntries,\n MastraCodePluginTools,\n MastraCodeToolRenderConfig,\n} from '../plugin.js';\nimport { getPluginRoot } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, mergePluginRegistries } from './registry.js';\nimport type { LoadedPlugin, LoadedPluginProcessors, PluginRegistry, ScopedInstalledPluginRecord } from './types.js';\n\nexport type LoadPluginRecordOptions = PluginPathOptions & {\n /** Lazy accessors for Mastra Code's runtime, passed on to plugin field resolvers. */\n runtime?: MastraCodePluginRuntime;\n};\n\nexport type LoadPluginsOptions = LoadPluginRecordOptions & {\n globalRegistry?: PluginRegistry;\n projectRegistry?: PluginRegistry;\n};\n\nexport async function loadPlugins(options: LoadPluginsOptions): Promise<LoadedPlugin[]> {\n const globalRegistry =\n options.globalRegistry ?? loadPluginRegistry(path.join(getPluginRoot('global', options), 'plugins.json'));\n const projectRegistry =\n options.projectRegistry ?? loadPluginRegistry(path.join(getPluginRoot('project', options), 'plugins.json'));\n const records = mergePluginRegistries(globalRegistry, projectRegistry);\n const loaded: LoadedPlugin[] = [];\n\n for (const record of records) {\n if (record.blocked) {\n loaded.push({ ...record, status: 'blocked', tools: {}, toolNames: [] });\n continue;\n }\n if (!record.enabled) {\n loaded.push({ ...record, status: 'inactive', tools: {}, toolNames: [] });\n continue;\n }\n\n loaded.push(await loadPluginRecord(record, options));\n }\n\n return markToolConflicts(loaded);\n}\n\nexport async function loadPluginRecord(\n record: ScopedInstalledPluginRecord,\n options: LoadPluginRecordOptions,\n): Promise<LoadedPlugin> {\n try {\n const entryPath = resolvePluginEntryPath(record, options);\n const plugin = await importPluginModule(entryPath);\n if (plugin.id !== record.id) {\n throw new Error(`Plugin id mismatch: registry has \"${record.id}\" but module exports \"${plugin.id}\"`);\n }\n\n const configSchema = validatePluginConfigSchema(plugin.config);\n const configValues = resolvePluginConfigValues(configSchema, record.config);\n const pluginDir = path.dirname(entryPath);\n const pluginRoot = resolvePluginRoot(record, options);\n const context: MastraCodePluginContext = {\n cwd: options.projectRoot,\n scope: record.scope,\n pluginDir,\n config: configValues,\n // Accessors, not instances: plugins load before the controller and the\n // session exist, so a plugin resolves these when it needs them, not now.\n getController: options.runtime?.getController,\n getActiveSession: options.runtime?.getActiveSession,\n getStorage: options.runtime?.getStorage,\n };\n const { tools, renderConfigs } = await resolvePluginTools(plugin, context);\n const processors = await resolvePluginProcessors(plugin, context);\n const signalProviders = await resolvePluginSignalProviders(plugin, context);\n const instructions = await resolvePluginInstructions(plugin, context);\n\n return {\n ...record,\n name: plugin.name,\n version: plugin.version ?? record.version,\n description: plugin.description,\n instructions,\n status: 'active',\n tools,\n renderConfigs,\n toolNames: Object.keys(tools).sort(),\n processors,\n signalProviders,\n skillPaths: resolveExistingAssetDirs(pluginRoot, 'skills'),\n commandPaths: resolveExistingAssetDirs(pluginRoot, 'commands'),\n configSchema,\n configValues,\n };\n } catch (error) {\n return {\n ...record,\n status: 'load failed',\n error: error instanceof Error ? error.message : String(error),\n tools: {},\n toolNames: [],\n };\n }\n}\n\nexport async function loadPluginFromEntry(entryPath: string): Promise<MastraCodePlugin> {\n return validatePluginExport(await importPluginModule(entryPath));\n}\n\nexport function resolvePluginRoot(record: ScopedInstalledPluginRecord, options: PluginPathOptions): string {\n const scopeRoot = path.resolve(getPluginRoot(record.scope, options));\n const pluginRoot = path.resolve(path.isAbsolute(record.path) ? record.path : path.join(scopeRoot, record.path));\n if (record.source === 'github' && !isInsideDirectory(pluginRoot, scopeRoot)) {\n throw new Error(`Plugin path for \"${record.id}\" must be inside the ${record.scope} plugin directory`);\n }\n return pluginRoot;\n}\n\nexport function resolvePluginEntryPath(record: ScopedInstalledPluginRecord, options: PluginPathOptions): string {\n const pluginRoot = resolvePluginRoot(record, options);\n const entryPath = path.resolve(pluginRoot, record.entry);\n if (!isInsideDirectory(entryPath, pluginRoot)) {\n throw new Error(`Plugin entry for \"${record.id}\" must be inside the plugin directory`);\n }\n return entryPath;\n}\n\nexport function isInsideDirectory(targetPath: string, root: string): boolean {\n const resolvedTarget = path.resolve(targetPath);\n const resolvedRoot = path.resolve(root);\n return resolvedTarget === resolvedRoot || resolvedTarget.startsWith(resolvedRoot + path.sep);\n}\n\nfunction resolveExistingAssetDirs(pluginRoot: string, dirname: 'skills' | 'commands'): string[] {\n const dir = path.join(pluginRoot, dirname);\n try {\n return fs.statSync(dir).isDirectory() ? [dir] : [];\n } catch {\n return [];\n }\n}\n\nasync function importPluginModule(entryPath: string): Promise<MastraCodePlugin> {\n if (path.extname(entryPath) !== '.ts') {\n throw new Error(\n `Unsupported plugin entry extension \"${path.extname(entryPath)}\". V1 plugins must use .ts entries.`,\n );\n }\n\n const url = pathToFileURL(entryPath);\n const stat = fs.statSync(entryPath, { bigint: true });\n url.searchParams.set('mtimeNs', stat.mtimeNs.toString());\n url.searchParams.set('size', stat.size.toString());\n const mod = (await import(url.href)) as { default?: unknown; plugin?: unknown };\n return validatePluginExport(mod.default ?? mod.plugin);\n}\n\nfunction validatePluginExport(value: unknown): MastraCodePlugin {\n if (!value || typeof value !== 'object') {\n throw new Error('Plugin module must export a plugin object as default or named \"plugin\" export');\n }\n\n const plugin = value as MastraCodePlugin;\n if (typeof plugin.id !== 'string' || plugin.id.trim().length === 0) {\n throw new Error('Plugin id must be a non-empty string');\n }\n\n if (plugin.tools !== undefined && typeof plugin.tools !== 'object' && typeof plugin.tools !== 'function') {\n throw new Error('Plugin tools must be an object or function');\n }\n\n if (\n plugin.processors !== undefined &&\n typeof plugin.processors !== 'object' &&\n typeof plugin.processors !== 'function'\n ) {\n throw new Error('Plugin processors must be an array, object, or function');\n }\n\n if (\n plugin.signalProviders !== undefined &&\n !Array.isArray(plugin.signalProviders) &&\n typeof plugin.signalProviders !== 'function'\n ) {\n throw new Error('Plugin signal providers must be an array or function');\n }\n\n return plugin;\n}\n\nasync function resolvePluginTools(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<{ tools: MastraCodePluginTools; renderConfigs: Record<string, MastraCodeToolRenderConfig> }> {\n if (!plugin.tools) return { tools: {}, renderConfigs: {} };\n const entries = typeof plugin.tools === 'function' ? await plugin.tools(context) : plugin.tools;\n if (!entries || typeof entries !== 'object' || Array.isArray(entries)) {\n throw new Error('Plugin tools function must return an object');\n }\n return normalizePluginToolEntries(entries);\n}\n\n/** Mirrors {@link resolvePluginTools}: object-or-function, resolved with the same context. */\nasync function resolvePluginProcessors(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<LoadedPluginProcessors> {\n if (!plugin.processors) return { input: [], output: [] };\n const entries = typeof plugin.processors === 'function' ? await plugin.processors(context) : plugin.processors;\n if (!entries || typeof entries !== 'object') {\n throw new Error('Plugin processors function must return an array or object');\n }\n return normalizePluginProcessorEntries(entries);\n}\n\nasync function resolvePluginSignalProviders(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<MastraCodePluginSignalProviderEntries> {\n if (!plugin.signalProviders) return [];\n const entries =\n typeof plugin.signalProviders === 'function' ? await plugin.signalProviders(context) : plugin.signalProviders;\n if (!Array.isArray(entries)) {\n throw new Error('Plugin signal providers function must return an array');\n }\n for (const [index, provider] of entries.entries()) {\n if (!isPluginSignalProvider(provider)) {\n throw new Error(\n `Plugin signal provider at index ${index} must be a SignalProvider (an object with an id that implements connect, startPolling, stop and __registerMastra)`,\n );\n }\n }\n return entries;\n}\n\n/**\n * Structural, not `instanceof`.\n *\n * A plugin that depends on a published provider package — the motivating case, a plugin wrapping\n * `@mastra/github-signals` — installs that package's own copy of `@mastra/core`, so its provider is\n * never an instance of the `SignalProvider` class Mastra Code loaded. `isSignalProvider` would reject\n * a perfectly working provider. Nothing in the lifecycle needs class identity: the lane only calls\n * these methods, so the methods are what is checked.\n */\nfunction isPluginSignalProvider(value: unknown): value is SignalProvider<string> {\n if (isSignalProvider(value)) return true;\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<SignalProvider<string>> & { __registerMastra?: unknown };\n return (\n typeof candidate.id === 'string' &&\n candidate.id.length > 0 &&\n typeof candidate.connect === 'function' &&\n typeof candidate.startPolling === 'function' &&\n typeof candidate.stop === 'function' &&\n typeof candidate.__registerMastra === 'function'\n );\n}\n\n/** A bare array is shorthand for the input lane, the common case. */\nfunction normalizePluginProcessorEntries(entries: MastraCodePluginProcessorEntries): LoadedPluginProcessors {\n const input = Array.isArray(entries) ? entries : (entries.input ?? []);\n const output = Array.isArray(entries) ? [] : (entries.output ?? []);\n if (!Array.isArray(input) || !Array.isArray(output)) {\n throw new Error('Plugin processor lanes must be arrays');\n }\n for (const processor of [...input, ...output]) {\n if (!processor || typeof processor !== 'object' || typeof processor.id !== 'string') {\n throw new Error('Plugin processors must be objects with an id');\n }\n }\n return { input, output };\n}\n\nasync function resolvePluginInstructions(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<string | undefined> {\n if (plugin.instructions === undefined) return undefined;\n const instructions =\n typeof plugin.instructions === 'function' ? await plugin.instructions(context) : plugin.instructions;\n if (typeof instructions !== 'string') {\n throw new Error('Plugin instructions must be a string');\n }\n const trimmed = instructions.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction normalizePluginToolEntries(entries: MastraCodePluginToolEntries): {\n tools: MastraCodePluginTools;\n renderConfigs: Record<string, MastraCodeToolRenderConfig>;\n} {\n const tools: MastraCodePluginTools = {};\n const renderConfigs: Record<string, MastraCodeToolRenderConfig> = {};\n for (const [name, entry] of Object.entries(entries)) {\n if (!isToolEntryObject(entry)) {\n throw new Error(`Plugin tool \"${name}\" must be an object with a tool property`);\n }\n tools[name] = entry.tool;\n if (entry.render) renderConfigs[name] = entry.render;\n }\n return { tools, renderConfigs };\n}\n\nfunction isToolEntryObject(entry: MastraCodePluginToolEntries[string]): entry is MastraCodePluginToolEntries[string] {\n if (!entry || typeof entry !== 'object' || !('tool' in entry)) return false;\n const tool = (entry as { tool?: unknown }).tool;\n return !!tool && typeof tool === 'object' && !Array.isArray(tool);\n}\n\nfunction validatePluginConfigSchema(schema: unknown): MastraCodePluginConfigSchema | undefined {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return undefined;\n const validated: MastraCodePluginConfigSchema = {};\n for (const [key, option] of Object.entries(schema)) {\n if (!option || typeof option !== 'object' || Array.isArray(option)) continue;\n const record = option as Record<string, unknown>;\n if (record.type !== 'model' && record.type !== 'boolean' && record.type !== 'string') continue;\n validated[key] = {\n type: record.type,\n ...(typeof record.label === 'string' ? { label: record.label } : {}),\n ...(typeof record.description === 'string' ? { description: record.description } : {}),\n ...(typeof record.default === 'string' || typeof record.default === 'boolean' ? { default: record.default } : {}),\n };\n }\n return Object.keys(validated).length > 0 ? validated : undefined;\n}\n\nfunction resolvePluginConfigValues(\n schema: MastraCodePluginConfigSchema | undefined,\n recordValues: Record<string, unknown> | undefined,\n): MastraCodePluginConfigValues {\n const values: MastraCodePluginConfigValues = {};\n if (!schema) return values;\n for (const [key, option] of Object.entries(schema)) {\n const value = recordValues?.[key];\n if (option.type === 'boolean') {\n values[key] = typeof value === 'boolean' ? value : typeof option.default === 'boolean' ? option.default : false;\n continue;\n }\n values[key] = typeof value === 'string' ? value : typeof option.default === 'string' ? option.default : undefined;\n }\n return values;\n}\n\nexport function collectActivePluginTools(plugins: LoadedPlugin[]): MastraCodePluginTools {\n const tools: MastraCodePluginTools = {};\n for (const plugin of plugins) {\n if (plugin.status !== 'active') continue;\n for (const [name, tool] of Object.entries(plugin.tools)) {\n if (!(name in tools)) {\n tools[name] = tool;\n }\n }\n }\n return tools;\n}\n\nfunction markToolConflicts(plugins: LoadedPlugin[]): LoadedPlugin[] {\n const seen = new Map<string, string>();\n return plugins.map(plugin => {\n if (plugin.status !== 'active') return plugin;\n const conflicts = plugin.toolNames.filter(toolName => seen.has(toolName));\n for (const toolName of plugin.toolNames) {\n if (!seen.has(toolName)) seen.set(toolName, plugin.id);\n }\n return conflicts.length > 0 ? { ...plugin, status: 'conflicted', conflicts } : plugin;\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"loader.js","names":[],"sources":["../../src/plugins/loader.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport { isSignalProvider } from '@mastra/core/signals';\nimport type { SignalProvider } from '@mastra/core/signals';\n\nimport type {\n MastraCodePlugin,\n MastraCodePluginConfigSchema,\n MastraCodePluginConfigValues,\n MastraCodePluginContext,\n MastraCodePluginProcessorEntries,\n MastraCodePluginRuntime,\n MastraCodePluginSignalProviderEntries,\n MastraCodePluginToolEntries,\n MastraCodePluginTools,\n MastraCodeToolRenderConfig,\n} from '../plugin.js';\nimport { getPluginRoot } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, mergePluginRegistries } from './registry.js';\nimport type { LoadedPlugin, LoadedPluginProcessors, PluginRegistry, ScopedInstalledPluginRecord } from './types.js';\n\nexport type LoadPluginRecordOptions = PluginPathOptions & {\n /** Lazy accessors for Mastra Code's runtime, passed on to plugin field resolvers. */\n runtime?: MastraCodePluginRuntime;\n};\n\nexport type LoadPluginsOptions = LoadPluginRecordOptions & {\n globalRegistry?: PluginRegistry;\n projectRegistry?: PluginRegistry;\n};\n\nexport async function loadPlugins(options: LoadPluginsOptions): Promise<LoadedPlugin[]> {\n const globalRegistry =\n options.globalRegistry ?? loadPluginRegistry(path.join(getPluginRoot('global', options), 'plugins.json'));\n const projectRegistry =\n options.projectRegistry ?? loadPluginRegistry(path.join(getPluginRoot('project', options), 'plugins.json'));\n const records = mergePluginRegistries(globalRegistry, projectRegistry);\n const loaded: LoadedPlugin[] = [];\n\n for (const record of records) {\n if (record.blocked) {\n loaded.push({ ...record, status: 'blocked', tools: {}, toolNames: [] });\n continue;\n }\n if (!record.enabled) {\n loaded.push({ ...record, status: 'inactive', tools: {}, toolNames: [] });\n continue;\n }\n\n loaded.push(await loadPluginRecord(record, options));\n }\n\n return markToolConflicts(loaded);\n}\n\nexport async function loadPluginRecord(\n record: ScopedInstalledPluginRecord,\n options: LoadPluginRecordOptions,\n): Promise<LoadedPlugin> {\n try {\n const entryPath = resolvePluginEntryPath(record, options);\n const plugin = await importPluginModule(entryPath);\n if (plugin.id !== record.id) {\n throw new Error(`Plugin id mismatch: registry has \"${record.id}\" but module exports \"${plugin.id}\"`);\n }\n\n const configSchema = validatePluginConfigSchema(plugin.config);\n const configValues = resolvePluginConfigValues(configSchema, record.config);\n const pluginDir = path.dirname(entryPath);\n const pluginRoot = resolvePluginRoot(record, options);\n const context: MastraCodePluginContext = {\n cwd: options.projectRoot,\n scope: record.scope,\n pluginDir,\n config: configValues,\n // Accessors, not instances: plugins load before the controller and the\n // session exist, so a plugin resolves these when it needs them, not now.\n getController: options.runtime?.getController,\n getActiveSession: options.runtime?.getActiveSession,\n getStorage: options.runtime?.getStorage,\n };\n const { tools, renderConfigs } = await resolvePluginTools(plugin, context);\n const processors = await resolvePluginProcessors(plugin, context);\n const signalProviders = await resolvePluginSignalProviders(plugin, context);\n const instructions = await resolvePluginInstructions(plugin, context);\n\n return {\n ...record,\n name: plugin.name,\n version: plugin.version ?? record.version,\n description: plugin.description,\n instructions,\n status: 'active',\n tools,\n renderConfigs,\n toolNames: Object.keys(tools).sort(),\n processors,\n signalProviders,\n skillPaths: resolveExistingAssetDirs(pluginRoot, 'skills'),\n commandPaths: resolveExistingAssetDirs(pluginRoot, 'commands'),\n configSchema,\n configValues,\n };\n } catch (error) {\n return {\n ...record,\n status: 'load failed',\n error: error instanceof Error ? error.message : String(error),\n tools: {},\n toolNames: [],\n };\n }\n}\n\nexport async function loadPluginFromEntry(entryPath: string): Promise<MastraCodePlugin> {\n return validatePluginExport(await importPluginModule(entryPath));\n}\n\nexport function resolvePluginRoot(record: ScopedInstalledPluginRecord, options: PluginPathOptions): string {\n const scopeRoot = path.resolve(getPluginRoot(record.scope, options));\n const pluginRoot = path.resolve(path.isAbsolute(record.path) ? record.path : path.join(scopeRoot, record.path));\n if (record.source === 'github' && !isInsideDirectory(pluginRoot, scopeRoot)) {\n throw new Error(`Plugin path for \"${record.id}\" must be inside the ${record.scope} plugin directory`);\n }\n return pluginRoot;\n}\n\nexport function resolvePluginEntryPath(record: ScopedInstalledPluginRecord, options: PluginPathOptions): string {\n const pluginRoot = resolvePluginRoot(record, options);\n const entryPath = path.resolve(pluginRoot, record.entry);\n if (!isInsideDirectory(entryPath, pluginRoot)) {\n throw new Error(`Plugin entry for \"${record.id}\" must be inside the plugin directory`);\n }\n return entryPath;\n}\n\nexport function isInsideDirectory(targetPath: string, root: string): boolean {\n const resolvedTarget = path.resolve(targetPath);\n const resolvedRoot = path.resolve(root);\n return resolvedTarget === resolvedRoot || resolvedTarget.startsWith(resolvedRoot + path.sep);\n}\n\nfunction resolveExistingAssetDirs(pluginRoot: string, dirname: 'skills' | 'commands'): string[] {\n const dir = path.join(pluginRoot, dirname);\n try {\n return fs.statSync(dir).isDirectory() ? [dir] : [];\n } catch {\n return [];\n }\n}\n\nasync function importPluginModule(entryPath: string): Promise<MastraCodePlugin> {\n if (path.extname(entryPath) !== '.ts') {\n throw new Error(\n `Unsupported plugin entry extension \"${path.extname(entryPath)}\". V1 plugins must use .ts entries.`,\n );\n }\n\n const url = pathToFileURL(entryPath);\n const contentHash = createHash('sha1').update(fs.readFileSync(entryPath)).digest('hex');\n const stat = fs.statSync(entryPath, { bigint: true });\n url.searchParams.set('contentHash', contentHash);\n url.searchParams.set('mtimeNs', stat.mtimeNs.toString());\n const mod = (await import(url.href)) as { default?: unknown; plugin?: unknown };\n return validatePluginExport(mod.default ?? mod.plugin);\n}\n\nfunction validatePluginExport(value: unknown): MastraCodePlugin {\n if (!value || typeof value !== 'object') {\n throw new Error('Plugin module must export a plugin object as default or named \"plugin\" export');\n }\n\n const plugin = value as MastraCodePlugin;\n if (typeof plugin.id !== 'string' || plugin.id.trim().length === 0) {\n throw new Error('Plugin id must be a non-empty string');\n }\n\n if (plugin.tools !== undefined && typeof plugin.tools !== 'object' && typeof plugin.tools !== 'function') {\n throw new Error('Plugin tools must be an object or function');\n }\n\n if (\n plugin.processors !== undefined &&\n typeof plugin.processors !== 'object' &&\n typeof plugin.processors !== 'function'\n ) {\n throw new Error('Plugin processors must be an array, object, or function');\n }\n\n if (\n plugin.signalProviders !== undefined &&\n !Array.isArray(plugin.signalProviders) &&\n typeof plugin.signalProviders !== 'function'\n ) {\n throw new Error('Plugin signal providers must be an array or function');\n }\n\n return plugin;\n}\n\nasync function resolvePluginTools(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<{ tools: MastraCodePluginTools; renderConfigs: Record<string, MastraCodeToolRenderConfig> }> {\n if (!plugin.tools) return { tools: {}, renderConfigs: {} };\n const entries = typeof plugin.tools === 'function' ? await plugin.tools(context) : plugin.tools;\n if (!entries || typeof entries !== 'object' || Array.isArray(entries)) {\n throw new Error('Plugin tools function must return an object');\n }\n return normalizePluginToolEntries(entries);\n}\n\n/** Mirrors {@link resolvePluginTools}: object-or-function, resolved with the same context. */\nasync function resolvePluginProcessors(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<LoadedPluginProcessors> {\n if (!plugin.processors) return { input: [], output: [] };\n const entries = typeof plugin.processors === 'function' ? await plugin.processors(context) : plugin.processors;\n if (!entries || typeof entries !== 'object') {\n throw new Error('Plugin processors function must return an array or object');\n }\n return normalizePluginProcessorEntries(entries);\n}\n\nasync function resolvePluginSignalProviders(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<MastraCodePluginSignalProviderEntries> {\n if (!plugin.signalProviders) return [];\n const entries =\n typeof plugin.signalProviders === 'function' ? await plugin.signalProviders(context) : plugin.signalProviders;\n if (!Array.isArray(entries)) {\n throw new Error('Plugin signal providers function must return an array');\n }\n for (const [index, provider] of entries.entries()) {\n if (!isPluginSignalProvider(provider)) {\n throw new Error(\n `Plugin signal provider at index ${index} must be a SignalProvider (an object with an id that implements connect, startPolling, stop and __registerMastra)`,\n );\n }\n }\n return entries;\n}\n\n/**\n * Structural, not `instanceof`.\n *\n * A plugin that depends on a published provider package — the motivating case, a plugin wrapping\n * `@mastra/github-signals` — installs that package's own copy of `@mastra/core`, so its provider is\n * never an instance of the `SignalProvider` class Mastra Code loaded. `isSignalProvider` would reject\n * a perfectly working provider. Nothing in the lifecycle needs class identity: the lane only calls\n * these methods, so the methods are what is checked.\n */\nfunction isPluginSignalProvider(value: unknown): value is SignalProvider<string> {\n if (isSignalProvider(value)) return true;\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<SignalProvider<string>> & { __registerMastra?: unknown };\n return (\n typeof candidate.id === 'string' &&\n candidate.id.length > 0 &&\n typeof candidate.connect === 'function' &&\n typeof candidate.startPolling === 'function' &&\n typeof candidate.stop === 'function' &&\n typeof candidate.__registerMastra === 'function'\n );\n}\n\n/** A bare array is shorthand for the input lane, the common case. */\nfunction normalizePluginProcessorEntries(entries: MastraCodePluginProcessorEntries): LoadedPluginProcessors {\n const input = Array.isArray(entries) ? entries : (entries.input ?? []);\n const output = Array.isArray(entries) ? [] : (entries.output ?? []);\n if (!Array.isArray(input) || !Array.isArray(output)) {\n throw new Error('Plugin processor lanes must be arrays');\n }\n for (const processor of [...input, ...output]) {\n if (!processor || typeof processor !== 'object' || typeof processor.id !== 'string') {\n throw new Error('Plugin processors must be objects with an id');\n }\n }\n return { input, output };\n}\n\nasync function resolvePluginInstructions(\n plugin: MastraCodePlugin,\n context: MastraCodePluginContext,\n): Promise<string | undefined> {\n if (plugin.instructions === undefined) return undefined;\n const instructions =\n typeof plugin.instructions === 'function' ? await plugin.instructions(context) : plugin.instructions;\n if (typeof instructions !== 'string') {\n throw new Error('Plugin instructions must be a string');\n }\n const trimmed = instructions.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction normalizePluginToolEntries(entries: MastraCodePluginToolEntries): {\n tools: MastraCodePluginTools;\n renderConfigs: Record<string, MastraCodeToolRenderConfig>;\n} {\n const tools: MastraCodePluginTools = {};\n const renderConfigs: Record<string, MastraCodeToolRenderConfig> = {};\n for (const [name, entry] of Object.entries(entries)) {\n if (!isToolEntryObject(entry)) {\n throw new Error(`Plugin tool \"${name}\" must be an object with a tool property`);\n }\n tools[name] = entry.tool;\n if (entry.render) renderConfigs[name] = entry.render;\n }\n return { tools, renderConfigs };\n}\n\nfunction isToolEntryObject(entry: MastraCodePluginToolEntries[string]): entry is MastraCodePluginToolEntries[string] {\n if (!entry || typeof entry !== 'object' || !('tool' in entry)) return false;\n const tool = (entry as { tool?: unknown }).tool;\n return !!tool && typeof tool === 'object' && !Array.isArray(tool);\n}\n\nfunction validatePluginConfigSchema(schema: unknown): MastraCodePluginConfigSchema | undefined {\n if (!schema || typeof schema !== 'object' || Array.isArray(schema)) return undefined;\n const validated: MastraCodePluginConfigSchema = {};\n for (const [key, option] of Object.entries(schema)) {\n if (!option || typeof option !== 'object' || Array.isArray(option)) continue;\n const record = option as Record<string, unknown>;\n if (record.type !== 'model' && record.type !== 'boolean' && record.type !== 'string') continue;\n validated[key] = {\n type: record.type,\n ...(typeof record.label === 'string' ? { label: record.label } : {}),\n ...(typeof record.description === 'string' ? { description: record.description } : {}),\n ...(typeof record.default === 'string' || typeof record.default === 'boolean' ? { default: record.default } : {}),\n };\n }\n return Object.keys(validated).length > 0 ? validated : undefined;\n}\n\nfunction resolvePluginConfigValues(\n schema: MastraCodePluginConfigSchema | undefined,\n recordValues: Record<string, unknown> | undefined,\n): MastraCodePluginConfigValues {\n const values: MastraCodePluginConfigValues = {};\n if (!schema) return values;\n for (const [key, option] of Object.entries(schema)) {\n const value = recordValues?.[key];\n if (option.type === 'boolean') {\n values[key] = typeof value === 'boolean' ? value : typeof option.default === 'boolean' ? option.default : false;\n continue;\n }\n values[key] = typeof value === 'string' ? value : typeof option.default === 'string' ? option.default : undefined;\n }\n return values;\n}\n\nexport function collectActivePluginTools(plugins: LoadedPlugin[]): MastraCodePluginTools {\n const tools: MastraCodePluginTools = {};\n for (const plugin of plugins) {\n if (plugin.status !== 'active') continue;\n for (const [name, tool] of Object.entries(plugin.tools)) {\n if (!(name in tools)) {\n tools[name] = tool;\n }\n }\n }\n return tools;\n}\n\nfunction markToolConflicts(plugins: LoadedPlugin[]): LoadedPlugin[] {\n const seen = new Map<string, string>();\n return plugins.map(plugin => {\n if (plugin.status !== 'active') return plugin;\n const conflicts = plugin.toolNames.filter(toolName => seen.has(toolName));\n for (const toolName of plugin.toolNames) {\n if (!seen.has(toolName)) seen.set(toolName, plugin.id);\n }\n return conflicts.length > 0 ? { ...plugin, status: 'conflicted', conflicts } : plugin;\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google (Gemini) thinking-level middleware.
|
|
3
|
+
*
|
|
4
|
+
* Maps the Mastra Code session thinking level (`off|low|medium|high|xhigh|max`)
|
|
5
|
+
* onto the thinking control each Gemini family accepts:
|
|
6
|
+
* - Gemini 3+: `thinkingConfig.thinkingLevel` (Gemini 3 Pro only accepts `low|high`).
|
|
7
|
+
* - Gemini 2.5: `thinkingConfig.thinkingBudget` (token budget).
|
|
8
|
+
* Unknown model families get no thinking config, so requests are unchanged.
|
|
9
|
+
*/
|
|
10
|
+
import type { LanguageModelMiddleware } from 'ai';
|
|
11
|
+
import type { ThinkingLevelSetting } from '../thinking.js';
|
|
12
|
+
type GoogleThinkingConfig = {
|
|
13
|
+
thinkingLevel: 'minimal' | 'low' | 'medium' | 'high';
|
|
14
|
+
} | {
|
|
15
|
+
thinkingBudget: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the Google thinking config for a model and session level.
|
|
19
|
+
* Returns `undefined` for `off`, unset levels, and unrecognized model families.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveGoogleThinkingConfig(modelId: string, level: ThinkingLevelSetting | undefined): GoogleThinkingConfig | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Create middleware that injects the resolved config into
|
|
24
|
+
* `providerOptions.google.thinkingConfig`. Returns `undefined` when there is
|
|
25
|
+
* nothing to inject, so callers wrap nothing.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createGoogleThinkingMiddleware(modelId: string, level: ThinkingLevelSetting | undefined): LanguageModelMiddleware | undefined;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=google-thinking.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/providers/google-thinking.ts
|
|
2
|
+
const GEMINI_25_BUDGETS = {
|
|
3
|
+
low: 1024,
|
|
4
|
+
medium: 8192,
|
|
5
|
+
high: 24576
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the Google thinking config for a model and session level.
|
|
9
|
+
* Returns `undefined` for `off`, unset levels, and unrecognized model families.
|
|
10
|
+
*/
|
|
11
|
+
function resolveGoogleThinkingConfig(modelId, level) {
|
|
12
|
+
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 };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create middleware that injects the resolved config into
|
|
22
|
+
* `providerOptions.google.thinkingConfig`. Returns `undefined` when there is
|
|
23
|
+
* nothing to inject, so callers wrap nothing.
|
|
24
|
+
*/
|
|
25
|
+
function createGoogleThinkingMiddleware(modelId, level) {
|
|
26
|
+
const config = resolveGoogleThinkingConfig(modelId, level);
|
|
27
|
+
if (!config) return void 0;
|
|
28
|
+
return {
|
|
29
|
+
specificationVersion: "v3",
|
|
30
|
+
transformParams: async ({ params }) => {
|
|
31
|
+
const google = params.providerOptions?.google ?? {};
|
|
32
|
+
const thinkingConfig = google.thinkingConfig ?? {};
|
|
33
|
+
if (thinkingConfig.thinkingBudget !== void 0 || thinkingConfig.thinkingLevel !== void 0) return params;
|
|
34
|
+
params.providerOptions = {
|
|
35
|
+
...params.providerOptions,
|
|
36
|
+
google: {
|
|
37
|
+
...google,
|
|
38
|
+
thinkingConfig: {
|
|
39
|
+
...thinkingConfig,
|
|
40
|
+
...config
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return params;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { createGoogleThinkingMiddleware, resolveGoogleThinkingConfig };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=google-thinking.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -28,6 +28,17 @@ export declare const THINKING_LEVEL_TO_REASONING_EFFORT: Record<ThinkingLevel, s
|
|
|
28
28
|
* Create Codex middleware with the given reasoning effort level.
|
|
29
29
|
*/
|
|
30
30
|
export declare function createCodexMiddleware(reasoningEffort?: string): LanguageModelMiddleware;
|
|
31
|
+
/**
|
|
32
|
+
* Create middleware that forwards a resolved reasoning effort to an
|
|
33
|
+
* OpenAI-compatible provider as `providerOptions[providerKey].reasoningEffort`.
|
|
34
|
+
*
|
|
35
|
+
* Returns `undefined` when `reasoningEffort` is unset so callers wrap nothing
|
|
36
|
+
* (e.g. thinking level `off`), leaving the wire request without a
|
|
37
|
+
* `reasoning_effort` field. Unlike {@link createCodexMiddleware}, it does not
|
|
38
|
+
* inject Codex-only options (instructions/store); it only sets reasoning
|
|
39
|
+
* effort, keyed by the caller-supplied provider id.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createReasoningEffortMiddleware(providerKey: string, reasoningEffort?: string): LanguageModelMiddleware | undefined;
|
|
31
42
|
/**
|
|
32
43
|
* Build a fetch function that handles OpenAI Codex OAuth.
|
|
33
44
|
* Preserves non-authorization headers from init.
|
|
@@ -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;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,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"}
|
|
@@ -69,6 +69,32 @@ function createCodexMiddleware(reasoningEffort) {
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
+
* Create middleware that forwards a resolved reasoning effort to an
|
|
73
|
+
* OpenAI-compatible provider as `providerOptions[providerKey].reasoningEffort`.
|
|
74
|
+
*
|
|
75
|
+
* Returns `undefined` when `reasoningEffort` is unset so callers wrap nothing
|
|
76
|
+
* (e.g. thinking level `off`), leaving the wire request without a
|
|
77
|
+
* `reasoning_effort` field. Unlike {@link createCodexMiddleware}, it does not
|
|
78
|
+
* inject Codex-only options (instructions/store); it only sets reasoning
|
|
79
|
+
* effort, keyed by the caller-supplied provider id.
|
|
80
|
+
*/
|
|
81
|
+
function createReasoningEffortMiddleware(providerKey, reasoningEffort) {
|
|
82
|
+
if (!reasoningEffort) return void 0;
|
|
83
|
+
return {
|
|
84
|
+
specificationVersion: "v3",
|
|
85
|
+
transformParams: async ({ params }) => {
|
|
86
|
+
params.providerOptions = {
|
|
87
|
+
...params.providerOptions,
|
|
88
|
+
[providerKey]: {
|
|
89
|
+
...params.providerOptions?.[providerKey] ?? {},
|
|
90
|
+
reasoningEffort
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return params;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
72
98
|
* Get a live OAuth bearer token for the Codex OAuth credential.
|
|
73
99
|
*
|
|
74
100
|
* Refreshes the token if it's expired, and returns the credential's
|
|
@@ -316,6 +342,6 @@ function openaiCodexProvider(modelId = "codex-mini-latest", options) {
|
|
|
316
342
|
});
|
|
317
343
|
}
|
|
318
344
|
//#endregion
|
|
319
|
-
export { THINKING_LEVEL_TO_REASONING_EFFORT, buildCodexStagehandFetch, buildOpenAICodexOAuthFetch, createCodexMiddleware, getAuthStorage, getEffectiveThinkingLevel, openaiCodexProvider, setAuthStorage, supportsMaxReasoningEffort };
|
|
345
|
+
export { THINKING_LEVEL_TO_REASONING_EFFORT, buildCodexStagehandFetch, buildOpenAICodexOAuthFetch, createCodexMiddleware, createReasoningEffortMiddleware, getAuthStorage, getEffectiveThinkingLevel, openaiCodexProvider, setAuthStorage, supportsMaxReasoningEffort };
|
|
320
346
|
|
|
321
347
|
//# sourceMappingURL=openai-codex.js.map
|
|
@@ -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 * 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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"}
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/code-sdk",
|
|
3
|
-
"version": "1.8.2-alpha.
|
|
3
|
+
"version": "1.8.2-alpha.2",
|
|
4
4
|
"description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -57,19 +57,19 @@
|
|
|
57
57
|
"yaml": "^2.7.1",
|
|
58
58
|
"zod": "^4.6.4",
|
|
59
59
|
"@mastra/agent-browser": "0.5.3",
|
|
60
|
-
"@mastra/
|
|
61
|
-
"@mastra/
|
|
60
|
+
"@mastra/duckdb": "1.11.0-alpha.2",
|
|
61
|
+
"@mastra/core": "1.70.0-alpha.2",
|
|
62
|
+
"@mastra/fastembed": "1.3.1",
|
|
62
63
|
"@mastra/github-signals": "0.5.0",
|
|
63
|
-
"@mastra/libsql": "1.23.
|
|
64
|
+
"@mastra/libsql": "1.23.2-alpha.0",
|
|
64
65
|
"@mastra/mcp": "2.1.0-alpha.0",
|
|
65
|
-
"@mastra/memory": "1.
|
|
66
|
+
"@mastra/memory": "1.32.0-alpha.1",
|
|
66
67
|
"@mastra/observability": "1.18.0",
|
|
67
|
-
"@mastra/
|
|
68
|
+
"@mastra/pg": "1.27.0-alpha.2",
|
|
68
69
|
"@mastra/parallel": "0.1.2",
|
|
69
|
-
"@mastra/schema-compat": "1.3.11",
|
|
70
|
-
"@mastra/stagehand": "0.3.5",
|
|
71
70
|
"@mastra/tavily": "1.1.2",
|
|
72
|
-
"@mastra/
|
|
71
|
+
"@mastra/schema-compat": "1.3.11",
|
|
72
|
+
"@mastra/stagehand": "0.3.5"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@libsql/client": "^0.18.0",
|