@mastra/code-sdk 1.15.0-alpha.9 → 1.15.1-alpha.0

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 (145) hide show
  1. package/dist/acp/agent.js +2 -1
  2. package/dist/acp/agent.js.map +1 -1
  3. package/dist/acp/event-mapper.js +0 -2
  4. package/dist/acp/event-mapper.js.map +1 -1
  5. package/dist/acp.js +1 -2
  6. package/dist/agent-connections/registry.js.map +1 -1
  7. package/dist/agent-connections/signal-provider.js.map +1 -1
  8. package/dist/agent-connections/state-processor.js.map +1 -1
  9. package/dist/agent-connections/tools.js +26 -24
  10. package/dist/agent-connections/tools.js.map +1 -1
  11. package/dist/agents/background-completion.d.ts +15 -2
  12. package/dist/agents/background-completion.d.ts.map +1 -1
  13. package/dist/agents/background-completion.js +19 -2
  14. package/dist/agents/background-completion.js.map +1 -1
  15. package/dist/agents/instructions.js +3 -2
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +35 -27
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.d.ts.map +1 -1
  20. package/dist/agents/memory.js +17 -3
  21. package/dist/agents/memory.js.map +1 -1
  22. package/dist/agents/prompts/agent-instructions.js +1 -1
  23. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  24. package/dist/agents/prompts/index.js +3 -2
  25. package/dist/agents/prompts/index.js.map +1 -1
  26. package/dist/agents/prompts/plan.js +2 -1
  27. package/dist/agents/prompts/plan.js.map +1 -1
  28. package/dist/agents/sandbox-filesystem.d.ts +28 -0
  29. package/dist/agents/sandbox-filesystem.d.ts.map +1 -1
  30. package/dist/agents/sandbox-filesystem.js +81 -2
  31. package/dist/agents/sandbox-filesystem.js.map +1 -1
  32. package/dist/agents/tools.d.ts.map +1 -1
  33. package/dist/agents/tools.js +18 -12
  34. package/dist/agents/tools.js.map +1 -1
  35. package/dist/agents/workspace.js +2 -1
  36. package/dist/agents/workspace.js.map +1 -1
  37. package/dist/auth/account-rotation-processor.js +2 -1
  38. package/dist/auth/account-rotation-processor.js.map +1 -1
  39. package/dist/auth/providers/anthropic.js +2 -2
  40. package/dist/auth/providers/anthropic.js.map +1 -1
  41. package/dist/auth/providers/github-copilot.js +1 -1
  42. package/dist/auth/providers/github-copilot.js.map +1 -1
  43. package/dist/auth/providers/openai-codex.js +3 -2
  44. package/dist/auth/providers/openai-codex.js.map +1 -1
  45. package/dist/auth/providers/xai.js +1 -1
  46. package/dist/auth/providers/xai.js.map +1 -1
  47. package/dist/clipboard/index.js +5 -4
  48. package/dist/clipboard/index.js.map +1 -1
  49. package/dist/evals/context-builder.js +1 -3
  50. package/dist/evals/context-builder.js.map +1 -1
  51. package/dist/evals/scorers/outcome.js +2 -1
  52. package/dist/evals/scorers/outcome.js.map +1 -1
  53. package/dist/factory/remote-controller.js.map +1 -1
  54. package/dist/factory/remote-session.d.ts +1 -1
  55. package/dist/factory/remote-session.d.ts.map +1 -1
  56. package/dist/factory/remote-session.js +15 -13
  57. package/dist/factory/remote-session.js.map +1 -1
  58. package/dist/headless/cli.js +2 -1
  59. package/dist/headless/cli.js.map +1 -1
  60. package/dist/headless/run-mc.js +9 -9
  61. package/dist/headless/run-mc.js.map +1 -1
  62. package/dist/hooks/executor.js +3 -1
  63. package/dist/hooks/executor.js.map +1 -1
  64. package/dist/hooks/manager.js +40 -26
  65. package/dist/hooks/manager.js.map +1 -1
  66. package/dist/index.d.ts +2 -2
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +56 -29
  69. package/dist/index.js.map +1 -1
  70. package/dist/knowledge-inspector.js +2 -2
  71. package/dist/knowledge-inspector.js.map +1 -1
  72. package/dist/lsp/server.js +4 -2
  73. package/dist/lsp/server.js.map +1 -1
  74. package/dist/mcp/manager.d.ts.map +1 -1
  75. package/dist/mcp/manager.js +14 -2
  76. package/dist/mcp/manager.js.map +1 -1
  77. package/dist/onboarding/settings.js +5 -2
  78. package/dist/onboarding/settings.js.map +1 -1
  79. package/dist/platform/index.js +5 -3
  80. package/dist/platform/index.js.map +1 -1
  81. package/dist/plugins/loader.js +3 -1
  82. package/dist/plugins/loader.js.map +1 -1
  83. package/dist/plugins/manager.js +2 -1
  84. package/dist/plugins/manager.js.map +1 -1
  85. package/dist/plugins/package-link.js.map +1 -1
  86. package/dist/plugins/scaffold.js +4 -2
  87. package/dist/plugins/scaffold.js.map +1 -1
  88. package/dist/plugins/signal-lane.js.map +1 -1
  89. package/dist/process-memory-diagnostics.js +2 -1
  90. package/dist/process-memory-diagnostics.js.map +1 -1
  91. package/dist/providers/amazon-bedrock-gateway.js +2 -1
  92. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  93. package/dist/providers/amazon-bedrock.js +2 -2
  94. package/dist/providers/amazon-bedrock.js.map +1 -1
  95. package/dist/providers/claude-max.d.ts.map +1 -1
  96. package/dist/providers/claude-max.js +14 -10
  97. package/dist/providers/claude-max.js.map +1 -1
  98. package/dist/providers/github-copilot-gateway.js.map +1 -1
  99. package/dist/providers/github-copilot.js +13 -12
  100. package/dist/providers/github-copilot.js.map +1 -1
  101. package/dist/providers/openai-codex.js +14 -11
  102. package/dist/providers/openai-codex.js.map +1 -1
  103. package/dist/providers/provider-thinking.js.map +1 -1
  104. package/dist/providers/thinking-request.js +1 -1
  105. package/dist/providers/thinking-request.js.map +1 -1
  106. package/dist/schedules/run-script.js +1 -1
  107. package/dist/schedules/run-script.js.map +1 -1
  108. package/dist/schedules/scheduler.js.map +1 -1
  109. package/dist/tools/request-sandbox-access.js +7 -5
  110. package/dist/tools/request-sandbox-access.js.map +1 -1
  111. package/dist/tools/utils.js +3 -1
  112. package/dist/tools/utils.js.map +1 -1
  113. package/dist/tools/web-search.d.ts +13 -11
  114. package/dist/tools/web-search.d.ts.map +1 -1
  115. package/dist/tools/web-search.js +21 -15
  116. package/dist/tools/web-search.js.map +1 -1
  117. package/dist/utils/debug-log.js +2 -2
  118. package/dist/utils/debug-log.js.map +1 -1
  119. package/dist/utils/gateway-sync.js +1 -1
  120. package/dist/utils/gateway-sync.js.map +1 -1
  121. package/dist/utils/local-observability.d.ts +1 -1
  122. package/dist/utils/local-observability.d.ts.map +1 -1
  123. package/dist/utils/local-observability.js +1 -1
  124. package/dist/utils/local-observability.js.map +1 -1
  125. package/dist/utils/prune-cli.js +10 -8
  126. package/dist/utils/prune-cli.js.map +1 -1
  127. package/dist/utils/signals-pubsub.js.map +1 -1
  128. package/dist/utils/slash-command-processor.js +1 -1
  129. package/dist/utils/slash-command-processor.js.map +1 -1
  130. package/dist/utils/stdin-pipe.js +1 -1
  131. package/dist/utils/stdin-pipe.js.map +1 -1
  132. package/dist/utils/storage-factory.d.ts.map +1 -1
  133. package/dist/utils/storage-factory.js +1 -1
  134. package/dist/utils/storage-factory.js.map +1 -1
  135. package/dist/utils/storage-maintenance.js +1 -1
  136. package/dist/utils/storage-maintenance.js.map +1 -1
  137. package/dist/utils/update-check.js +2 -1
  138. package/dist/utils/update-check.js.map +1 -1
  139. package/dist/utils/wake-session.d.ts +1 -1
  140. package/dist/utils/wake-session.d.ts.map +1 -1
  141. package/dist/utils/wake-session.js +8 -1
  142. package/dist/utils/wake-session.js.map +1 -1
  143. package/dist/workflows/register-primitives.js +1 -1
  144. package/dist/workflows/register-primitives.js.map +1 -1
  145. package/package.json +22 -22
@@ -1 +1 @@
1
- {"version":3,"file":"process-memory-diagnostics.js","names":["platform"],"sources":["../src/process-memory-diagnostics.ts"],"sourcesContent":["import { appendFile, chmod, mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { Session } from 'node:inspector/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { PerformanceObserver } from 'node:perf_hooks';\nimport type { PerformanceEntry } from 'node:perf_hooks';\nimport { arch, platform } from 'node:process';\nimport { getHeapSpaceStatistics, getHeapStatistics } from 'node:v8';\n\nexport const PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS = {\n sampleIntervalMs: 10_000,\n captureIntervalMs: 300_000,\n allocationIntervalBytes: 524_288,\n} as const;\n\nexport const PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS = {\n sampleIntervalMs: 1_000,\n captureIntervalMs: 10_000,\n allocationIntervalBytes: 32_768,\n} as const;\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\nconst MAX_PENDING_GC_EVENTS = 1_000;\n\nexport interface ProcessMemoryDiagnosticsConfig {\n parentDirectory: string;\n sampleIntervalMs: number;\n captureIntervalMs: number;\n allocationIntervalBytes: number;\n}\n\nexport interface ProcessMemoryDiagnosticsEnvironment {\n MASTRACODE_PROFILE?: string;\n MASTRACODE_PROFILE_DIR?: string;\n MASTRACODE_PROFILE_SAMPLE_INTERVAL_MS?: string;\n MASTRACODE_PROFILE_CAPTURE_INTERVAL_MS?: string;\n MASTRACODE_PROFILE_ALLOCATION_INTERVAL_BYTES?: string;\n}\n\nexport interface ProcessMemoryDiagnosticsMemorySample {\n timestamp: string;\n sequence: number;\n elapsedMs: number;\n memory: ReturnType<typeof process.memoryUsage>;\n resourceUsage: ReturnType<typeof process.resourceUsage>;\n heap: ReturnType<typeof getHeapStatistics>;\n heapSpaces: ReturnType<typeof getHeapSpaceStatistics>;\n}\n\nexport interface ProcessMemoryDiagnosticsStatus {\n state: 'inactive' | 'starting' | 'active' | 'stopping' | 'error';\n outputDirectory: string | null;\n config: ProcessMemoryDiagnosticsConfig;\n sampleCount: number;\n captureCount: number;\n gcEventCount: number;\n latestSample: ProcessMemoryDiagnosticsMemorySample | null;\n latestCapturePath: string | null;\n error: string | null;\n}\n\nexport interface ProcessMemoryDiagnosticsCapture {\n path: string;\n sequence: number;\n timestamp: string;\n reason: 'manual' | 'periodic' | 'stop';\n}\n\ninterface InspectorSessionAdapter {\n connect(): void;\n disconnect(): void;\n post(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;\n}\n\ninterface PerformanceObserverAdapter {\n observe(options: Parameters<PerformanceObserver['observe']>[0]): void;\n disconnect(): void;\n}\n\ninterface ProcessMemoryDiagnosticsDependencies {\n createInspectorSession?: () => InspectorSessionAdapter;\n createPerformanceObserver?: (callback: (entries: PerformanceEntry[]) => void) => PerformanceObserverAdapter;\n now?: () => Date;\n randomId?: () => string;\n}\n\nexport interface ProcessMemoryDiagnosticsSetup {\n diagnostics: ProcessMemoryDiagnostics;\n enabled: boolean;\n error: string | null;\n}\n\nexport class ProcessMemoryDiagnosticsConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ProcessMemoryDiagnosticsConfigError';\n }\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return ['1', 'true', 'yes', 'on'].includes(value?.trim().toLowerCase() ?? '');\n}\n\nfunction parseBoundedInteger(\n env: ProcessMemoryDiagnosticsEnvironment,\n name: keyof ProcessMemoryDiagnosticsEnvironment,\n fallback: number,\n minimum: number,\n maximum?: number,\n): number {\n const raw = env[name];\n if (raw === undefined || raw.trim() === '') return fallback;\n const value = Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum || (maximum !== undefined && value > maximum)) {\n const range = maximum === undefined ? `greater than or equal to ${minimum}` : `between ${minimum} and ${maximum}`;\n throw new ProcessMemoryDiagnosticsConfigError(\n `${name} must be an integer ${range}; received ${JSON.stringify(raw)}.`,\n );\n }\n return value;\n}\n\nfunction getDefaultProfileParentDirectory(): string {\n if (process.env.MASTRA_APP_DATA_DIR) return join(process.env.MASTRA_APP_DATA_DIR, 'profiles');\n\n const baseDirectory =\n platform === 'darwin'\n ? join(homedir(), 'Library', 'Application Support')\n : platform === 'win32'\n ? process.env.APPDATA || join(homedir(), 'AppData', 'Roaming')\n : process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');\n return join(baseDirectory, 'mastracode', 'profiles');\n}\n\nexport function parseProcessMemoryDiagnosticsEnvironment(env: ProcessMemoryDiagnosticsEnvironment = process.env): {\n enabled: boolean;\n config: ProcessMemoryDiagnosticsConfig;\n} {\n return {\n enabled: isEnabled(env.MASTRACODE_PROFILE),\n config: {\n parentDirectory: env.MASTRACODE_PROFILE_DIR?.trim() || getDefaultProfileParentDirectory(),\n sampleIntervalMs: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_SAMPLE_INTERVAL_MS',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.sampleIntervalMs,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.sampleIntervalMs,\n MAX_TIMER_DELAY_MS,\n ),\n captureIntervalMs: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_CAPTURE_INTERVAL_MS',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.captureIntervalMs,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.captureIntervalMs,\n MAX_TIMER_DELAY_MS,\n ),\n allocationIntervalBytes: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_ALLOCATION_INTERVAL_BYTES',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.allocationIntervalBytes,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.allocationIntervalBytes,\n ),\n },\n };\n}\n\nexport function createProcessMemoryDiagnosticsFromEnvironment(\n env: ProcessMemoryDiagnosticsEnvironment = process.env,\n dependencies: ProcessMemoryDiagnosticsDependencies = {},\n): ProcessMemoryDiagnosticsSetup {\n try {\n const { enabled, config } = parseProcessMemoryDiagnosticsEnvironment(env);\n return { diagnostics: new ProcessMemoryDiagnostics(config, dependencies), enabled, error: null };\n } catch (error) {\n const config: ProcessMemoryDiagnosticsConfig = {\n parentDirectory: env.MASTRACODE_PROFILE_DIR?.trim() || getDefaultProfileParentDirectory(),\n ...PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS,\n };\n const message = error instanceof Error ? error.message : String(error);\n return {\n diagnostics: new ProcessMemoryDiagnostics(config, dependencies, message),\n enabled: isEnabled(env.MASTRACODE_PROFILE),\n error: message,\n };\n }\n}\n\nexport async function startConfiguredProcessMemoryDiagnostics(\n setup: ProcessMemoryDiagnosticsSetup,\n warn: (message: string) => void,\n): Promise<ProcessMemoryDiagnostics> {\n if (!setup.enabled) return setup.diagnostics;\n if (setup.error) {\n warn(`Process memory diagnostics were not started: ${setup.error}`);\n return setup.diagnostics;\n }\n\n const status = await setup.diagnostics.start();\n if (status.state !== 'active') {\n warn(`Process memory diagnostics were not started: ${status.error ?? 'unknown inspector error'}`);\n }\n return setup.diagnostics;\n}\n\nexport async function stopProcessMemoryDiagnosticsWithTimeout(\n diagnostics: ProcessMemoryDiagnostics,\n warn: (message: string) => void,\n timeoutMs = 5_000,\n): Promise<void> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const timedOut = await Promise.race([\n diagnostics.stop().then(\n () => false,\n error => {\n warn(`Process memory diagnostics did not stop cleanly: ${errorMessage(error)}`);\n return false;\n },\n ),\n new Promise<true>(resolve => {\n timeout = setTimeout(() => resolve(true), timeoutMs);\n timeout.unref();\n }),\n ]);\n if (timeout) clearTimeout(timeout);\n if (timedOut)\n warn(`Process memory diagnostics did not stop within ${timeoutMs}ms; final artifacts may be incomplete.`);\n}\n\nfunction defaultInspectorSession(): InspectorSessionAdapter {\n const session = new Session();\n return {\n connect: () => session.connect(),\n disconnect: () => session.disconnect(),\n post: async (method, params) =>\n (await session.post(\n method as Parameters<Session['post']>[0],\n params as Parameters<Session['post']>[1],\n )) as unknown as Record<string, unknown>,\n };\n}\n\nfunction defaultPerformanceObserver(callback: (entries: PerformanceEntry[]) => void) {\n const observer = new PerformanceObserver(list => callback(list.getEntries()));\n return observer;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeTimestamp(date: Date): string {\n return date.toISOString().replaceAll(':', '-');\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n timer.unref?.();\n}\n\nexport class ProcessMemoryDiagnostics {\n readonly config: ProcessMemoryDiagnosticsConfig;\n\n private state: ProcessMemoryDiagnosticsStatus['state'] = 'inactive';\n private outputDirectory: string | null = null;\n private inspector: InspectorSessionAdapter | null = null;\n private observer: PerformanceObserverAdapter | null = null;\n private sampleTimer: ReturnType<typeof setInterval> | null = null;\n private captureTimer: ReturnType<typeof setInterval> | null = null;\n private startedAt: Date | null = null;\n private sampleCount = 0;\n private captureCount = 0;\n private gcEventCount = 0;\n private latestSample: ProcessMemoryDiagnosticsMemorySample | null = null;\n private latestCapturePath: string | null = null;\n private latestError: string | null;\n private samplingActive = false;\n private stopRequested = false;\n private startingPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private stoppingPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private restartAfterStopPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private restartRequested = false;\n private pendingGcEvents: Array<Record<string, unknown>> = [];\n private gcEventBufferOverflowed = false;\n private artifactWriteFailed = false;\n private captureQueue: Promise<unknown> = Promise.resolve();\n private writeQueue: Promise<unknown> = Promise.resolve();\n\n private readonly configError: string | null;\n private readonly createInspectorSession: () => InspectorSessionAdapter;\n private readonly createPerformanceObserver: NonNullable<\n ProcessMemoryDiagnosticsDependencies['createPerformanceObserver']\n >;\n private readonly now: () => Date;\n private readonly randomId: () => string;\n\n constructor(\n config: ProcessMemoryDiagnosticsConfig,\n dependencies: ProcessMemoryDiagnosticsDependencies = {},\n initialError: string | null = null,\n ) {\n this.config = { ...config };\n this.configError = initialError;\n this.latestError = initialError;\n this.createInspectorSession = dependencies.createInspectorSession ?? defaultInspectorSession;\n this.createPerformanceObserver = dependencies.createPerformanceObserver ?? defaultPerformanceObserver;\n this.now = dependencies.now ?? (() => new Date());\n this.randomId = dependencies.randomId ?? (() => globalThis.crypto.randomUUID());\n }\n\n getStatus(): ProcessMemoryDiagnosticsStatus {\n return {\n state: this.state,\n outputDirectory: this.outputDirectory,\n config: { ...this.config },\n sampleCount: this.sampleCount,\n captureCount: this.captureCount,\n gcEventCount: this.gcEventCount,\n latestSample: this.latestSample,\n latestCapturePath: this.latestCapturePath,\n error: this.latestError,\n };\n }\n\n start(): Promise<ProcessMemoryDiagnosticsStatus> {\n if (this.state === 'active') return Promise.resolve(this.getStatus());\n if (this.state === 'starting' && this.startingPromise) return this.startingPromise;\n if (this.state === 'stopping' && this.stoppingPromise) {\n this.restartRequested = true;\n this.restartAfterStopPromise ??= this.stoppingPromise.then(() => {\n this.restartAfterStopPromise = null;\n if (!this.restartRequested) return this.getStatus();\n this.restartRequested = false;\n return this.start();\n });\n return this.restartAfterStopPromise;\n }\n if (this.configError) {\n this.latestError = this.configError;\n this.state = 'error';\n return Promise.resolve(this.getStatus());\n }\n\n this.state = 'starting';\n this.stoppingPromise = null;\n this.restartRequested = false;\n this.stopRequested = false;\n this.outputDirectory = null;\n this.sampleCount = 0;\n this.captureCount = 0;\n this.gcEventCount = 0;\n this.pendingGcEvents = [];\n this.gcEventBufferOverflowed = false;\n this.artifactWriteFailed = false;\n this.latestSample = null;\n this.latestCapturePath = null;\n this.latestError = null;\n this.startedAt = this.now();\n\n const startingPromise = this.startRun();\n this.startingPromise = startingPromise;\n void startingPromise.finally(() => {\n if (this.startingPromise === startingPromise) this.startingPromise = null;\n });\n return startingPromise;\n }\n\n private async startRun(): Promise<ProcessMemoryDiagnosticsStatus> {\n try {\n await this.createArtifacts();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n this.observeGc();\n this.inspector = this.createInspectorSession();\n this.inspector.connect();\n await this.startSampling();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n await this.takeSample();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n this.sampleTimer = setInterval(() => {\n void this.takeSample().catch(error => this.recordError('Process sample failed', error));\n }, this.config.sampleIntervalMs);\n unrefTimer(this.sampleTimer);\n\n this.captureTimer = setInterval(() => {\n void this.capture('periodic').catch(error => this.recordError('Periodic allocation capture failed', error));\n }, this.config.captureIntervalMs);\n unrefTimer(this.captureTimer);\n\n this.state = 'active';\n return this.getStatus();\n } catch (error) {\n this.latestError = `Unable to start process memory diagnostics: ${errorMessage(error)}`;\n await this.cleanupAfterStartFailure();\n this.state = 'error';\n return this.getStatus();\n }\n }\n\n private async abortStartIfRequested(): Promise<boolean> {\n if (!this.stopRequested) return false;\n await this.cleanupAfterStartFailure();\n this.state = 'inactive';\n return true;\n }\n\n capture(reason: 'manual' | 'periodic' = 'manual'): Promise<ProcessMemoryDiagnosticsCapture> {\n if (this.state !== 'active') {\n return Promise.reject(new Error(this.latestError ?? 'Process memory diagnostics are not active.'));\n }\n return this.enqueueCapture(() => this.captureEpoch(reason, false));\n }\n\n async stop(): Promise<ProcessMemoryDiagnosticsStatus> {\n if (this.stoppingPromise) {\n this.restartRequested = false;\n return this.stoppingPromise;\n }\n if (this.state === 'inactive') return this.getStatus();\n if (this.state === 'error' && !this.inspector && !this.outputDirectory) return this.getStatus();\n\n const startingPromise = this.state === 'starting' ? this.startingPromise : null;\n this.stopRequested = true;\n this.state = 'stopping';\n this.clearTimersAndObserver();\n\n if (startingPromise) {\n this.stoppingPromise = startingPromise.then(() => this.getStatus());\n return this.stoppingPromise;\n }\n\n this.stoppingPromise = (async () => {\n let stopError: string | null = null;\n try {\n if (this.outputDirectory) await this.takeSample();\n await this.enqueueCapture(async () => {\n if (this.inspector && this.samplingActive) await this.captureEpoch('stop', true);\n });\n await this.writeQueue;\n if (this.gcEventBufferOverflowed) {\n throw new Error(`GC event buffer exceeded ${MAX_PENDING_GC_EVENTS} records before the next process sample.`);\n }\n if (this.artifactWriteFailed) throw new Error('One or more process memory diagnostic artifact writes failed.');\n this.latestError = null;\n } catch (error) {\n stopError = `Unable to stop process memory diagnostics cleanly: ${errorMessage(error)}`;\n this.latestError = stopError;\n } finally {\n this.disconnectInspector();\n this.state = stopError ? 'error' : 'inactive';\n }\n return this.getStatus();\n })();\n\n return this.stoppingPromise;\n }\n\n private async createArtifacts(): Promise<void> {\n await mkdir(this.config.parentDirectory, { recursive: true, mode: 0o700 });\n await chmod(this.config.parentDirectory, 0o700);\n const runName = `run-${safeTimestamp(this.startedAt!)}-${process.pid}-${this.randomId()\n .replaceAll(/[^a-zA-Z0-9-]/g, '')\n .slice(0, 12)}`;\n this.outputDirectory = join(this.config.parentDirectory, runName);\n await mkdir(this.outputDirectory, { mode: 0o700 });\n await chmod(this.outputDirectory, 0o700);\n\n const metadata = {\n schemaVersion: 1,\n runId: runName,\n startedAt: this.startedAt!.toISOString(),\n pid: process.pid,\n nodeVersion: process.version,\n platform,\n arch,\n config: this.config,\n };\n await writeFile(join(this.outputDirectory, 'metadata.json'), `${JSON.stringify(metadata, null, 2)}\\n`, {\n flag: 'wx',\n mode: 0o600,\n });\n await writeFile(join(this.outputDirectory, 'process-samples.jsonl'), '', { flag: 'wx', mode: 0o600 });\n await writeFile(join(this.outputDirectory, 'gc-events.jsonl'), '', { flag: 'wx', mode: 0o600 });\n }\n\n private observeGc(): void {\n const observer = this.createPerformanceObserver(entries => {\n const before = this.latestSample?.memory ?? null;\n const after = process.memoryUsage();\n const timestamp = this.now().toISOString();\n for (const entry of entries) {\n const gcEntry = entry as PerformanceEntry & {\n kind?: number;\n flags?: number;\n detail?: { kind?: number; flags?: number };\n };\n this.gcEventCount += 1;\n if (this.pendingGcEvents.length >= MAX_PENDING_GC_EVENTS) {\n this.gcEventBufferOverflowed = true;\n this.latestError = `GC event buffer exceeded ${MAX_PENDING_GC_EVENTS} records before the next process sample.`;\n continue;\n }\n this.pendingGcEvents.push({\n timestamp,\n sequence: this.gcEventCount,\n name: entry.name,\n startTime: entry.startTime,\n duration: entry.duration,\n kind: gcEntry.detail?.kind ?? gcEntry.kind ?? null,\n flags: gcEntry.detail?.flags ?? gcEntry.flags ?? null,\n before,\n after,\n latestSampleSequence: this.latestSample?.sequence ?? null,\n });\n }\n });\n observer.observe({ entryTypes: ['gc'] });\n this.observer = observer;\n }\n\n private async startSampling(): Promise<void> {\n if (!this.inspector) throw new Error('Inspector session is unavailable.');\n await this.inspector.post('HeapProfiler.startSampling', {\n samplingInterval: this.config.allocationIntervalBytes,\n includeObjectsCollectedByMajorGC: true,\n includeObjectsCollectedByMinorGC: true,\n });\n this.samplingActive = true;\n }\n\n private async takeSample(): Promise<ProcessMemoryDiagnosticsMemorySample> {\n if (!this.outputDirectory || !this.startedAt) throw new Error('Diagnostics output directory is unavailable.');\n const sample: ProcessMemoryDiagnosticsMemorySample = {\n timestamp: this.now().toISOString(),\n sequence: this.sampleCount + 1,\n elapsedMs: Math.max(0, this.now().getTime() - this.startedAt.getTime()),\n memory: process.memoryUsage(),\n resourceUsage: process.resourceUsage(),\n heap: getHeapStatistics(),\n heapSpaces: getHeapSpaceStatistics(),\n };\n this.sampleCount = sample.sequence;\n this.latestSample = sample;\n await this.enqueueWrite('process-samples.jsonl', sample);\n const gcEvents = this.pendingGcEvents.splice(0);\n if (gcEvents.length > 0) await this.enqueueWriteBatch('gc-events.jsonl', gcEvents);\n return sample;\n }\n\n private enqueueWrite(fileName: string, value: unknown): Promise<void> {\n return this.enqueueWriteBatch(fileName, [value]);\n }\n\n private enqueueWriteBatch(fileName: string, values: unknown[]): Promise<void> {\n const operation = this.writeQueue.then(async () => {\n if (!this.outputDirectory || values.length === 0) return;\n const lines = values.map(value => JSON.stringify(value)).join('\\n');\n try {\n await appendFile(join(this.outputDirectory, fileName), `${lines}\\n`, { mode: 0o600 });\n } catch (error) {\n this.artifactWriteFailed = true;\n throw error;\n }\n });\n this.writeQueue = operation.catch(() => undefined);\n return operation;\n }\n\n private enqueueCapture<T>(operation: () => Promise<T>): Promise<T> {\n const result = this.captureQueue.then(operation);\n this.captureQueue = result.catch(() => undefined);\n return result;\n }\n\n private async captureEpoch(\n reason: ProcessMemoryDiagnosticsCapture['reason'],\n final: boolean,\n ): Promise<ProcessMemoryDiagnosticsCapture> {\n if (!this.inspector || !this.samplingActive || !this.outputDirectory) {\n throw new Error(this.latestError ?? 'Allocation sampling is not active.');\n }\n\n let response: Record<string, unknown>;\n try {\n response = await this.inspector.post('HeapProfiler.stopSampling');\n this.samplingActive = false;\n } catch (error) {\n this.latestError = `Allocation capture failed: ${errorMessage(error)}`;\n if (!final && !this.stopRequested) await this.restartSamplingAfterFailure();\n throw new Error(this.latestError, { cause: error });\n }\n\n const profile = response.profile;\n if (!profile || typeof profile !== 'object') {\n this.latestError = 'Allocation capture failed: inspector returned no profile.';\n if (!final && !this.stopRequested) await this.restartSamplingAfterFailure();\n throw new Error(this.latestError);\n }\n\n const sequence = this.captureCount + 1;\n const timestamp = this.now().toISOString();\n const filename = `allocation-${String(sequence).padStart(6, '0')}-${safeTimestamp(new Date(timestamp))}.heapprofile`;\n const finalPath = join(this.outputDirectory, filename);\n const temporaryPath = join(this.outputDirectory, `.${filename}.${this.randomId()}.tmp`);\n\n try {\n await writeFile(temporaryPath, `${JSON.stringify(profile)}\\n`, { flag: 'wx', mode: 0o600 });\n await chmod(temporaryPath, 0o600);\n await rename(temporaryPath, finalPath);\n await chmod(finalPath, 0o600);\n this.captureCount = sequence;\n this.latestCapturePath = finalPath;\n this.latestError = null;\n } catch (error) {\n this.artifactWriteFailed = true;\n this.latestError = `Unable to persist allocation capture: ${errorMessage(error)}`;\n throw new Error(this.latestError, { cause: error });\n } finally {\n if (!final && !this.stopRequested && this.state === 'active') {\n try {\n await this.startSampling();\n } catch (error) {\n this.latestError = `Unable to restart allocation sampling: ${errorMessage(error)}`;\n this.state = 'error';\n }\n }\n }\n\n if (!final && !this.stopRequested && !this.samplingActive) {\n throw new Error(this.latestError ?? 'Allocation sampling did not restart.');\n }\n\n return { path: finalPath, sequence, timestamp, reason };\n }\n\n private async restartSamplingAfterFailure(): Promise<void> {\n try {\n await this.startSampling();\n } catch (error) {\n this.latestError = `Unable to restart allocation sampling: ${errorMessage(error)}`;\n this.state = 'error';\n }\n }\n\n private recordError(prefix: string, error: unknown): void {\n this.latestError = `${prefix}: ${errorMessage(error)}`;\n }\n\n private clearTimersAndObserver(): void {\n if (this.sampleTimer) clearInterval(this.sampleTimer);\n if (this.captureTimer) clearInterval(this.captureTimer);\n this.sampleTimer = null;\n this.captureTimer = null;\n this.observer?.disconnect();\n this.observer = null;\n }\n\n private disconnectInspector(): void {\n this.samplingActive = false;\n if (!this.inspector) return;\n try {\n this.inspector.disconnect();\n } catch {\n // Best-effort cleanup after an inspector failure.\n }\n this.inspector = null;\n }\n\n private async cleanupAfterStartFailure(): Promise<void> {\n this.clearTimersAndObserver();\n this.disconnectInspector();\n await this.writeQueue;\n try {\n if (this.outputDirectory) await rm(this.outputDirectory, { recursive: true, force: true });\n } catch (error) {\n this.latestError = `${this.latestError} Failed to remove partial artifacts: ${errorMessage(error)}`;\n } finally {\n this.outputDirectory = null;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-memory-diagnostics.js","names":["platform"],"sources":["../src/process-memory-diagnostics.ts"],"sourcesContent":["import { appendFile, chmod, mkdir, rename, rm, writeFile } from 'node:fs/promises';\nimport { Session } from 'node:inspector/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { PerformanceObserver } from 'node:perf_hooks';\nimport type { PerformanceEntry } from 'node:perf_hooks';\nimport { arch, platform } from 'node:process';\nimport { getHeapSpaceStatistics, getHeapStatistics } from 'node:v8';\n\nexport const PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS = {\n sampleIntervalMs: 10_000,\n captureIntervalMs: 300_000,\n allocationIntervalBytes: 524_288,\n} as const;\n\nexport const PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS = {\n sampleIntervalMs: 1_000,\n captureIntervalMs: 10_000,\n allocationIntervalBytes: 32_768,\n} as const;\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\nconst MAX_PENDING_GC_EVENTS = 1_000;\n\nexport interface ProcessMemoryDiagnosticsConfig {\n parentDirectory: string;\n sampleIntervalMs: number;\n captureIntervalMs: number;\n allocationIntervalBytes: number;\n}\n\nexport interface ProcessMemoryDiagnosticsEnvironment {\n MASTRACODE_PROFILE?: string;\n MASTRACODE_PROFILE_DIR?: string;\n MASTRACODE_PROFILE_SAMPLE_INTERVAL_MS?: string;\n MASTRACODE_PROFILE_CAPTURE_INTERVAL_MS?: string;\n MASTRACODE_PROFILE_ALLOCATION_INTERVAL_BYTES?: string;\n}\n\nexport interface ProcessMemoryDiagnosticsMemorySample {\n timestamp: string;\n sequence: number;\n elapsedMs: number;\n memory: ReturnType<typeof process.memoryUsage>;\n resourceUsage: ReturnType<typeof process.resourceUsage>;\n heap: ReturnType<typeof getHeapStatistics>;\n heapSpaces: ReturnType<typeof getHeapSpaceStatistics>;\n}\n\nexport interface ProcessMemoryDiagnosticsStatus {\n state: 'inactive' | 'starting' | 'active' | 'stopping' | 'error';\n outputDirectory: string | null;\n config: ProcessMemoryDiagnosticsConfig;\n sampleCount: number;\n captureCount: number;\n gcEventCount: number;\n latestSample: ProcessMemoryDiagnosticsMemorySample | null;\n latestCapturePath: string | null;\n error: string | null;\n}\n\nexport interface ProcessMemoryDiagnosticsCapture {\n path: string;\n sequence: number;\n timestamp: string;\n reason: 'manual' | 'periodic' | 'stop';\n}\n\ninterface InspectorSessionAdapter {\n connect(): void;\n disconnect(): void;\n post(method: string, params?: Record<string, unknown>): Promise<Record<string, unknown>>;\n}\n\ninterface PerformanceObserverAdapter {\n observe(options: Parameters<PerformanceObserver['observe']>[0]): void;\n disconnect(): void;\n}\n\ninterface ProcessMemoryDiagnosticsDependencies {\n createInspectorSession?: () => InspectorSessionAdapter;\n createPerformanceObserver?: (callback: (entries: PerformanceEntry[]) => void) => PerformanceObserverAdapter;\n now?: () => Date;\n randomId?: () => string;\n}\n\nexport interface ProcessMemoryDiagnosticsSetup {\n diagnostics: ProcessMemoryDiagnostics;\n enabled: boolean;\n error: string | null;\n}\n\nexport class ProcessMemoryDiagnosticsConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ProcessMemoryDiagnosticsConfigError';\n }\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return ['1', 'true', 'yes', 'on'].includes(value?.trim().toLowerCase() ?? '');\n}\n\nfunction parseBoundedInteger(\n env: ProcessMemoryDiagnosticsEnvironment,\n name: keyof ProcessMemoryDiagnosticsEnvironment,\n fallback: number,\n minimum: number,\n maximum?: number,\n): number {\n const raw = env[name];\n if (raw === undefined || raw.trim() === '') return fallback;\n const value = Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum || (maximum !== undefined && value > maximum)) {\n const range = maximum === undefined ? `greater than or equal to ${minimum}` : `between ${minimum} and ${maximum}`;\n throw new ProcessMemoryDiagnosticsConfigError(\n `${name} must be an integer ${range}; received ${JSON.stringify(raw)}.`,\n );\n }\n return value;\n}\n\nfunction getDefaultProfileParentDirectory(): string {\n if (process.env.MASTRA_APP_DATA_DIR) return join(process.env.MASTRA_APP_DATA_DIR, 'profiles');\n\n const baseDirectory =\n platform === 'darwin'\n ? join(homedir(), 'Library', 'Application Support')\n : platform === 'win32'\n ? process.env.APPDATA || join(homedir(), 'AppData', 'Roaming')\n : process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');\n return join(baseDirectory, 'mastracode', 'profiles');\n}\n\nexport function parseProcessMemoryDiagnosticsEnvironment(env: ProcessMemoryDiagnosticsEnvironment = process.env): {\n enabled: boolean;\n config: ProcessMemoryDiagnosticsConfig;\n} {\n return {\n enabled: isEnabled(env.MASTRACODE_PROFILE),\n config: {\n parentDirectory: env.MASTRACODE_PROFILE_DIR?.trim() || getDefaultProfileParentDirectory(),\n sampleIntervalMs: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_SAMPLE_INTERVAL_MS',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.sampleIntervalMs,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.sampleIntervalMs,\n MAX_TIMER_DELAY_MS,\n ),\n captureIntervalMs: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_CAPTURE_INTERVAL_MS',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.captureIntervalMs,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.captureIntervalMs,\n MAX_TIMER_DELAY_MS,\n ),\n allocationIntervalBytes: parseBoundedInteger(\n env,\n 'MASTRACODE_PROFILE_ALLOCATION_INTERVAL_BYTES',\n PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS.allocationIntervalBytes,\n PROCESS_MEMORY_DIAGNOSTICS_MINIMUMS.allocationIntervalBytes,\n ),\n },\n };\n}\n\nexport function createProcessMemoryDiagnosticsFromEnvironment(\n env: ProcessMemoryDiagnosticsEnvironment = process.env,\n dependencies: ProcessMemoryDiagnosticsDependencies = {},\n): ProcessMemoryDiagnosticsSetup {\n try {\n const { enabled, config } = parseProcessMemoryDiagnosticsEnvironment(env);\n return { diagnostics: new ProcessMemoryDiagnostics(config, dependencies), enabled, error: null };\n } catch (error) {\n const config: ProcessMemoryDiagnosticsConfig = {\n parentDirectory: env.MASTRACODE_PROFILE_DIR?.trim() || getDefaultProfileParentDirectory(),\n ...PROCESS_MEMORY_DIAGNOSTICS_DEFAULTS,\n };\n const message = error instanceof Error ? error.message : String(error);\n return {\n diagnostics: new ProcessMemoryDiagnostics(config, dependencies, message),\n enabled: isEnabled(env.MASTRACODE_PROFILE),\n error: message,\n };\n }\n}\n\nexport async function startConfiguredProcessMemoryDiagnostics(\n setup: ProcessMemoryDiagnosticsSetup,\n warn: (message: string) => void,\n): Promise<ProcessMemoryDiagnostics> {\n if (!setup.enabled) return setup.diagnostics;\n if (setup.error) {\n warn(`Process memory diagnostics were not started: ${setup.error}`);\n return setup.diagnostics;\n }\n\n const status = await setup.diagnostics.start();\n if (status.state !== 'active') {\n warn(`Process memory diagnostics were not started: ${status.error ?? 'unknown inspector error'}`);\n }\n return setup.diagnostics;\n}\n\nexport async function stopProcessMemoryDiagnosticsWithTimeout(\n diagnostics: ProcessMemoryDiagnostics,\n warn: (message: string) => void,\n timeoutMs = 5_000,\n): Promise<void> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const timedOut = await Promise.race([\n diagnostics.stop().then(\n () => false,\n error => {\n warn(`Process memory diagnostics did not stop cleanly: ${errorMessage(error)}`);\n return false;\n },\n ),\n new Promise<true>(resolve => {\n timeout = setTimeout(() => resolve(true), timeoutMs);\n timeout.unref();\n }),\n ]);\n if (timeout) clearTimeout(timeout);\n if (timedOut)\n warn(`Process memory diagnostics did not stop within ${timeoutMs}ms; final artifacts may be incomplete.`);\n}\n\nfunction defaultInspectorSession(): InspectorSessionAdapter {\n const session = new Session();\n return {\n connect: () => session.connect(),\n disconnect: () => session.disconnect(),\n post: async (method, params) =>\n (await session.post(\n method as Parameters<Session['post']>[0],\n params as Parameters<Session['post']>[1],\n )) as unknown as Record<string, unknown>,\n };\n}\n\nfunction defaultPerformanceObserver(callback: (entries: PerformanceEntry[]) => void) {\n const observer = new PerformanceObserver(list => callback(list.getEntries()));\n return observer;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction safeTimestamp(date: Date): string {\n return date.toISOString().replaceAll(':', '-');\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n timer.unref?.();\n}\n\nexport class ProcessMemoryDiagnostics {\n readonly config: ProcessMemoryDiagnosticsConfig;\n\n private state: ProcessMemoryDiagnosticsStatus['state'] = 'inactive';\n private outputDirectory: string | null = null;\n private inspector: InspectorSessionAdapter | null = null;\n private observer: PerformanceObserverAdapter | null = null;\n private sampleTimer: ReturnType<typeof setInterval> | null = null;\n private captureTimer: ReturnType<typeof setInterval> | null = null;\n private startedAt: Date | null = null;\n private sampleCount = 0;\n private captureCount = 0;\n private gcEventCount = 0;\n private latestSample: ProcessMemoryDiagnosticsMemorySample | null = null;\n private latestCapturePath: string | null = null;\n private latestError: string | null;\n private samplingActive = false;\n private stopRequested = false;\n private startingPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private stoppingPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private restartAfterStopPromise: Promise<ProcessMemoryDiagnosticsStatus> | null = null;\n private restartRequested = false;\n private pendingGcEvents: Array<Record<string, unknown>> = [];\n private gcEventBufferOverflowed = false;\n private artifactWriteFailed = false;\n private captureQueue: Promise<unknown> = Promise.resolve();\n private writeQueue: Promise<unknown> = Promise.resolve();\n\n private readonly configError: string | null;\n private readonly createInspectorSession: () => InspectorSessionAdapter;\n private readonly createPerformanceObserver: NonNullable<\n ProcessMemoryDiagnosticsDependencies['createPerformanceObserver']\n >;\n private readonly now: () => Date;\n private readonly randomId: () => string;\n\n constructor(\n config: ProcessMemoryDiagnosticsConfig,\n dependencies: ProcessMemoryDiagnosticsDependencies = {},\n initialError: string | null = null,\n ) {\n this.config = { ...config };\n this.configError = initialError;\n this.latestError = initialError;\n this.createInspectorSession = dependencies.createInspectorSession ?? defaultInspectorSession;\n this.createPerformanceObserver = dependencies.createPerformanceObserver ?? defaultPerformanceObserver;\n this.now = dependencies.now ?? (() => new Date());\n this.randomId = dependencies.randomId ?? (() => globalThis.crypto.randomUUID());\n }\n\n getStatus(): ProcessMemoryDiagnosticsStatus {\n return {\n state: this.state,\n outputDirectory: this.outputDirectory,\n config: { ...this.config },\n sampleCount: this.sampleCount,\n captureCount: this.captureCount,\n gcEventCount: this.gcEventCount,\n latestSample: this.latestSample,\n latestCapturePath: this.latestCapturePath,\n error: this.latestError,\n };\n }\n\n start(): Promise<ProcessMemoryDiagnosticsStatus> {\n if (this.state === 'active') return Promise.resolve(this.getStatus());\n if (this.state === 'starting' && this.startingPromise) return this.startingPromise;\n if (this.state === 'stopping' && this.stoppingPromise) {\n this.restartRequested = true;\n this.restartAfterStopPromise ??= this.stoppingPromise.then(() => {\n this.restartAfterStopPromise = null;\n if (!this.restartRequested) return this.getStatus();\n this.restartRequested = false;\n return this.start();\n });\n return this.restartAfterStopPromise;\n }\n if (this.configError) {\n this.latestError = this.configError;\n this.state = 'error';\n return Promise.resolve(this.getStatus());\n }\n\n this.state = 'starting';\n this.stoppingPromise = null;\n this.restartRequested = false;\n this.stopRequested = false;\n this.outputDirectory = null;\n this.sampleCount = 0;\n this.captureCount = 0;\n this.gcEventCount = 0;\n this.pendingGcEvents = [];\n this.gcEventBufferOverflowed = false;\n this.artifactWriteFailed = false;\n this.latestSample = null;\n this.latestCapturePath = null;\n this.latestError = null;\n this.startedAt = this.now();\n\n const startingPromise = this.startRun();\n this.startingPromise = startingPromise;\n void startingPromise.finally(() => {\n if (this.startingPromise === startingPromise) this.startingPromise = null;\n });\n return startingPromise;\n }\n\n private async startRun(): Promise<ProcessMemoryDiagnosticsStatus> {\n try {\n await this.createArtifacts();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n this.observeGc();\n this.inspector = this.createInspectorSession();\n this.inspector.connect();\n await this.startSampling();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n await this.takeSample();\n if (await this.abortStartIfRequested()) return this.getStatus();\n\n this.sampleTimer = setInterval(() => {\n void this.takeSample().catch(error => this.recordError('Process sample failed', error));\n }, this.config.sampleIntervalMs);\n unrefTimer(this.sampleTimer);\n\n this.captureTimer = setInterval(() => {\n void this.capture('periodic').catch(error => this.recordError('Periodic allocation capture failed', error));\n }, this.config.captureIntervalMs);\n unrefTimer(this.captureTimer);\n\n this.state = 'active';\n return this.getStatus();\n } catch (error) {\n this.latestError = `Unable to start process memory diagnostics: ${errorMessage(error)}`;\n await this.cleanupAfterStartFailure();\n this.state = 'error';\n return this.getStatus();\n }\n }\n\n private async abortStartIfRequested(): Promise<boolean> {\n if (!this.stopRequested) return false;\n await this.cleanupAfterStartFailure();\n this.state = 'inactive';\n return true;\n }\n\n capture(reason: 'manual' | 'periodic' = 'manual'): Promise<ProcessMemoryDiagnosticsCapture> {\n if (this.state !== 'active') {\n return Promise.reject(new Error(this.latestError ?? 'Process memory diagnostics are not active.'));\n }\n return this.enqueueCapture(() => this.captureEpoch(reason, false));\n }\n\n async stop(): Promise<ProcessMemoryDiagnosticsStatus> {\n if (this.stoppingPromise) {\n this.restartRequested = false;\n return this.stoppingPromise;\n }\n if (this.state === 'inactive') return this.getStatus();\n if (this.state === 'error' && !this.inspector && !this.outputDirectory) return this.getStatus();\n\n const startingPromise = this.state === 'starting' ? this.startingPromise : null;\n this.stopRequested = true;\n this.state = 'stopping';\n this.clearTimersAndObserver();\n\n if (startingPromise) {\n this.stoppingPromise = startingPromise.then(() => this.getStatus());\n return this.stoppingPromise;\n }\n\n this.stoppingPromise = (async () => {\n let stopError: string | null = null;\n try {\n if (this.outputDirectory) await this.takeSample();\n await this.enqueueCapture(async () => {\n if (this.inspector && this.samplingActive) await this.captureEpoch('stop', true);\n });\n await this.writeQueue;\n if (this.gcEventBufferOverflowed) {\n throw new Error(`GC event buffer exceeded ${MAX_PENDING_GC_EVENTS} records before the next process sample.`);\n }\n if (this.artifactWriteFailed) throw new Error('One or more process memory diagnostic artifact writes failed.');\n this.latestError = null;\n } catch (error) {\n stopError = `Unable to stop process memory diagnostics cleanly: ${errorMessage(error)}`;\n this.latestError = stopError;\n } finally {\n this.disconnectInspector();\n this.state = stopError ? 'error' : 'inactive';\n }\n return this.getStatus();\n })();\n\n return this.stoppingPromise;\n }\n\n private async createArtifacts(): Promise<void> {\n await mkdir(this.config.parentDirectory, { recursive: true, mode: 0o700 });\n await chmod(this.config.parentDirectory, 0o700);\n const runName = `run-${safeTimestamp(this.startedAt!)}-${process.pid}-${this.randomId()\n .replaceAll(/[^a-zA-Z0-9-]/g, '')\n .slice(0, 12)}`;\n this.outputDirectory = join(this.config.parentDirectory, runName);\n await mkdir(this.outputDirectory, { mode: 0o700 });\n await chmod(this.outputDirectory, 0o700);\n\n const metadata = {\n schemaVersion: 1,\n runId: runName,\n startedAt: this.startedAt!.toISOString(),\n pid: process.pid,\n nodeVersion: process.version,\n platform,\n arch,\n config: this.config,\n };\n await writeFile(join(this.outputDirectory, 'metadata.json'), `${JSON.stringify(metadata, null, 2)}\\n`, {\n flag: 'wx',\n mode: 0o600,\n });\n await writeFile(join(this.outputDirectory, 'process-samples.jsonl'), '', { flag: 'wx', mode: 0o600 });\n await writeFile(join(this.outputDirectory, 'gc-events.jsonl'), '', { flag: 'wx', mode: 0o600 });\n }\n\n private observeGc(): void {\n const observer = this.createPerformanceObserver(entries => {\n const before = this.latestSample?.memory ?? null;\n const after = process.memoryUsage();\n const timestamp = this.now().toISOString();\n for (const entry of entries) {\n const gcEntry = entry as PerformanceEntry & {\n kind?: number;\n flags?: number;\n detail?: { kind?: number; flags?: number };\n };\n this.gcEventCount += 1;\n if (this.pendingGcEvents.length >= MAX_PENDING_GC_EVENTS) {\n this.gcEventBufferOverflowed = true;\n this.latestError = `GC event buffer exceeded ${MAX_PENDING_GC_EVENTS} records before the next process sample.`;\n continue;\n }\n this.pendingGcEvents.push({\n timestamp,\n sequence: this.gcEventCount,\n name: entry.name,\n startTime: entry.startTime,\n duration: entry.duration,\n kind: gcEntry.detail?.kind ?? gcEntry.kind ?? null,\n flags: gcEntry.detail?.flags ?? gcEntry.flags ?? null,\n before,\n after,\n latestSampleSequence: this.latestSample?.sequence ?? null,\n });\n }\n });\n observer.observe({ entryTypes: ['gc'] });\n this.observer = observer;\n }\n\n private async startSampling(): Promise<void> {\n if (!this.inspector) throw new Error('Inspector session is unavailable.');\n await this.inspector.post('HeapProfiler.startSampling', {\n samplingInterval: this.config.allocationIntervalBytes,\n includeObjectsCollectedByMajorGC: true,\n includeObjectsCollectedByMinorGC: true,\n });\n this.samplingActive = true;\n }\n\n private async takeSample(): Promise<ProcessMemoryDiagnosticsMemorySample> {\n if (!this.outputDirectory || !this.startedAt) throw new Error('Diagnostics output directory is unavailable.');\n const sample: ProcessMemoryDiagnosticsMemorySample = {\n timestamp: this.now().toISOString(),\n sequence: this.sampleCount + 1,\n elapsedMs: Math.max(0, this.now().getTime() - this.startedAt.getTime()),\n memory: process.memoryUsage(),\n resourceUsage: process.resourceUsage(),\n heap: getHeapStatistics(),\n heapSpaces: getHeapSpaceStatistics(),\n };\n this.sampleCount = sample.sequence;\n this.latestSample = sample;\n await this.enqueueWrite('process-samples.jsonl', sample);\n const gcEvents = this.pendingGcEvents.splice(0);\n if (gcEvents.length > 0) await this.enqueueWriteBatch('gc-events.jsonl', gcEvents);\n return sample;\n }\n\n private enqueueWrite(fileName: string, value: unknown): Promise<void> {\n return this.enqueueWriteBatch(fileName, [value]);\n }\n\n private enqueueWriteBatch(fileName: string, values: unknown[]): Promise<void> {\n const operation = this.writeQueue.then(async () => {\n if (!this.outputDirectory || values.length === 0) return;\n const lines = values.map(value => JSON.stringify(value)).join('\\n');\n try {\n await appendFile(join(this.outputDirectory, fileName), `${lines}\\n`, { mode: 0o600 });\n } catch (error) {\n this.artifactWriteFailed = true;\n throw error;\n }\n });\n this.writeQueue = operation.catch(() => undefined);\n return operation;\n }\n\n private enqueueCapture<T>(operation: () => Promise<T>): Promise<T> {\n const result = this.captureQueue.then(operation);\n this.captureQueue = result.catch(() => undefined);\n return result;\n }\n\n private async captureEpoch(\n reason: ProcessMemoryDiagnosticsCapture['reason'],\n final: boolean,\n ): Promise<ProcessMemoryDiagnosticsCapture> {\n if (!this.inspector || !this.samplingActive || !this.outputDirectory) {\n throw new Error(this.latestError ?? 'Allocation sampling is not active.');\n }\n\n let response: Record<string, unknown>;\n try {\n response = await this.inspector.post('HeapProfiler.stopSampling');\n this.samplingActive = false;\n } catch (error) {\n this.latestError = `Allocation capture failed: ${errorMessage(error)}`;\n if (!final && !this.stopRequested) await this.restartSamplingAfterFailure();\n throw new Error(this.latestError, { cause: error });\n }\n\n const profile = response.profile;\n if (!profile || typeof profile !== 'object') {\n this.latestError = 'Allocation capture failed: inspector returned no profile.';\n if (!final && !this.stopRequested) await this.restartSamplingAfterFailure();\n throw new Error(this.latestError);\n }\n\n const sequence = this.captureCount + 1;\n const timestamp = this.now().toISOString();\n const filename = `allocation-${String(sequence).padStart(6, '0')}-${safeTimestamp(new Date(timestamp))}.heapprofile`;\n const finalPath = join(this.outputDirectory, filename);\n const temporaryPath = join(this.outputDirectory, `.${filename}.${this.randomId()}.tmp`);\n\n try {\n await writeFile(temporaryPath, `${JSON.stringify(profile)}\\n`, { flag: 'wx', mode: 0o600 });\n await chmod(temporaryPath, 0o600);\n await rename(temporaryPath, finalPath);\n await chmod(finalPath, 0o600);\n this.captureCount = sequence;\n this.latestCapturePath = finalPath;\n this.latestError = null;\n } catch (error) {\n this.artifactWriteFailed = true;\n this.latestError = `Unable to persist allocation capture: ${errorMessage(error)}`;\n throw new Error(this.latestError, { cause: error });\n } finally {\n if (!final && !this.stopRequested && this.state === 'active') {\n try {\n await this.startSampling();\n } catch (error) {\n this.latestError = `Unable to restart allocation sampling: ${errorMessage(error)}`;\n this.state = 'error';\n }\n }\n }\n\n if (!final && !this.stopRequested && !this.samplingActive) {\n throw new Error(this.latestError ?? 'Allocation sampling did not restart.');\n }\n\n return { path: finalPath, sequence, timestamp, reason };\n }\n\n private async restartSamplingAfterFailure(): Promise<void> {\n try {\n await this.startSampling();\n } catch (error) {\n this.latestError = `Unable to restart allocation sampling: ${errorMessage(error)}`;\n this.state = 'error';\n }\n }\n\n private recordError(prefix: string, error: unknown): void {\n this.latestError = `${prefix}: ${errorMessage(error)}`;\n }\n\n private clearTimersAndObserver(): void {\n if (this.sampleTimer) clearInterval(this.sampleTimer);\n if (this.captureTimer) clearInterval(this.captureTimer);\n this.sampleTimer = null;\n this.captureTimer = null;\n this.observer?.disconnect();\n this.observer = null;\n }\n\n private disconnectInspector(): void {\n this.samplingActive = false;\n if (!this.inspector) return;\n try {\n this.inspector.disconnect();\n } catch {\n // Best-effort cleanup after an inspector failure.\n }\n this.inspector = null;\n }\n\n private async cleanupAfterStartFailure(): Promise<void> {\n this.clearTimersAndObserver();\n this.disconnectInspector();\n await this.writeQueue;\n try {\n if (this.outputDirectory) await rm(this.outputDirectory, { recursive: true, force: true });\n } catch (error) {\n this.latestError = `${this.latestError} Failed to remove partial artifacts: ${errorMessage(error)}`;\n } finally {\n this.outputDirectory = null;\n }\n }\n}\n"],"mappings":"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"}
@@ -84,8 +84,9 @@ function hasAwsCredentials() {
84
84
  * SDK and only wire up SigV4 here.
85
85
  */
86
86
  function bedrockProvider(modelId, headers) {
87
+ const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || "us-east-1";
87
88
  const model = createAmazonBedrock({
88
- region: process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || "us-east-1",
89
+ region,
89
90
  credentialProvider: fromNodeProviderChain(),
90
91
  headers
91
92
  })(modelId);
@@ -1 +1 @@
1
- {"version":3,"file":"amazon-bedrock-gateway.js","names":[],"sources":["../../src/providers/amazon-bedrock-gateway.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';\nimport { fromNodeProviderChain } from '@aws-sdk/credential-providers';\nimport { MastraModelGateway } from '@mastra/core/llm';\nimport type { GatewayAuthRequest, GatewayAuthResult, GatewayLanguageModel, ProviderConfig } from '@mastra/core/llm';\nimport { getBedrockModelCatalog } from './amazon-bedrock.js';\n\ntype ModelRequestHeaders = Record<string, string>;\ntype BedrockModel = ReturnType<ReturnType<typeof createAmazonBedrock>>;\ntype BedrockPrompt = Parameters<BedrockModel['doGenerate']>[0]['prompt'];\n\n// Claude 3.x is a closed set: only these three variants support cachePoint on Bedrock.\n// claude-3-5-sonnet-20240620 is intentionally excluded (only the 20241022-v2:0 variant caches).\n// Every Claude 4+ and every named family (opus-5, sonnet-5, fable, mythos, …) supports it.\nconst CLAUDE_3_CACHEABLE = /claude-3-7-sonnet|claude-3-5-sonnet-20241022|claude-3-5-haiku/;\n\nexport function supportsBedrockPromptCaching(modelId: string): boolean {\n if (!modelId.includes('anthropic.claude')) return false;\n return /anthropic\\.claude-3-/.test(modelId) ? CLAUDE_3_CACHEABLE.test(modelId) : true;\n}\n\nexport function addBedrockCachePoints(prompt: BedrockPrompt): BedrockPrompt {\n const result = [...prompt];\n const markCachePoint = (message: (typeof result)[number]) => ({\n ...message,\n providerOptions: {\n ...message.providerOptions,\n bedrock: {\n ...message.providerOptions?.bedrock,\n cachePoint: { type: 'default' },\n },\n },\n });\n\n let lastSystemIndex = -1;\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index]!.role === 'system') {\n lastSystemIndex = index;\n break;\n }\n }\n\n if (lastSystemIndex >= 0) {\n result[lastSystemIndex] = markCachePoint(result[lastSystemIndex]!);\n }\n\n let lastNonSystemIndex = -1;\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index]!.role !== 'system') {\n lastNonSystemIndex = index;\n break;\n }\n }\n\n if (lastNonSystemIndex >= 0) {\n result[lastNonSystemIndex] = markCachePoint(result[lastNonSystemIndex]!);\n }\n\n return result;\n}\n\nexport function withBedrockCache(model: BedrockModel): BedrockModel {\n return new Proxy(model, {\n get(target, property, receiver) {\n if (property === 'doGenerate') {\n return (options: Parameters<BedrockModel['doGenerate']>[0]) =>\n target.doGenerate({ ...options, prompt: addBedrockCachePoints(options.prompt) });\n }\n if (property === 'doStream') {\n return (options: Parameters<BedrockModel['doStream']>[0]) =>\n target.doStream({ ...options, prompt: addBedrockCachePoints(options.prompt) });\n }\n return Reflect.get(target, property, receiver);\n },\n });\n}\n\nexport const AMAZON_BEDROCK_GATEWAY_ID = 'amazon-bedrock';\n\n/**\n * Whether AWS credentials look available for Bedrock.\n *\n * Amazon Bedrock authenticates with AWS SigV4 rather than a bearer API key, so\n * this only governs whether Bedrock models are offered as \"authenticated\" in the\n * picker. We look for the common signals (env vars, bearer token, a configured\n * profile, or a shared credentials/config file) rather than resolving\n * credentials here, since the auth checker must stay sync.\n */\nexport function hasAwsCredentials(): boolean {\n if (\n process.env.AWS_BEARER_TOKEN_BEDROCK ||\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n process.env.AWS_SHARED_CREDENTIALS_FILE ||\n process.env.AWS_CONFIG_FILE ||\n process.env.AWS_PROFILE ||\n process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n process.env.AWS_WEB_IDENTITY_TOKEN_FILE\n ) {\n return true;\n }\n const home = process.env.HOME || process.env.USERPROFILE;\n if (home) {\n const awsDir = path.join(home, '.aws');\n const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE ?? path.join(awsDir, 'credentials');\n const configPath = process.env.AWS_CONFIG_FILE ?? path.join(awsDir, 'config');\n if (existsSync(credentialsPath) || existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Create an Amazon Bedrock model.\n *\n * Bedrock authenticates with AWS SigV4 rather than a bearer API key, so this\n * resolves credentials through the standard AWS provider chain\n * (`fromNodeProviderChain`): environment variables, shared `~/.aws` config and\n * SSO profiles, and container/instance roles — the same resolution order the AWS\n * CLI uses. The region falls back to `us-east-1` to match the AWS SDK default.\n *\n * When `AWS_BEARER_TOKEN_BEDROCK` is set, `@ai-sdk/amazon-bedrock` uses bearer\n * auth instead and ignores the credential provider, so we leave that path to the\n * SDK and only wire up SigV4 here.\n */\nfunction bedrockProvider(modelId: string, headers?: ModelRequestHeaders) {\n const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1';\n const bedrock = createAmazonBedrock({\n region,\n credentialProvider: fromNodeProviderChain(),\n headers,\n });\n const model = bedrock(modelId);\n return supportsBedrockPromptCaching(modelId) ? withBedrockCache(model) : model;\n}\n\n/**\n * Standalone Amazon Bedrock gateway.\n *\n * Bedrock is resolved directly via AWS SigV4 (not through the model router) and\n * its models are surfaced from the public models.dev catalog. It is exposed as\n * its own gateway/provider (`amazon-bedrock/...`) rather than nested under the\n * MastraCode gateway namespace.\n */\nexport class AmazonBedrockGateway extends MastraModelGateway {\n readonly id = AMAZON_BEDROCK_GATEWAY_ID;\n readonly name = 'Amazon Bedrock';\n\n shouldEnable(): boolean {\n return hasAwsCredentials();\n }\n\n async fetchProviders(): Promise<Record<string, ProviderConfig>> {\n const providers: Record<string, ProviderConfig> = {};\n try {\n const bedrockModels = await getBedrockModelCatalog();\n providers['amazon-bedrock'] = {\n name: 'Amazon Bedrock',\n apiKeyEnvVar: '',\n apiKeyHeader: 'Authorization',\n gateway: this.id,\n models: bedrockModels.map(model => model.id),\n };\n } catch (error) {\n console.warn('Failed to load Amazon Bedrock model catalog:', error);\n }\n return providers;\n }\n\n buildUrl(_modelId: string): string | undefined {\n return undefined;\n }\n\n async getApiKey(_modelId: string): Promise<string> {\n return hasAwsCredentials() ? 'aws-credential-chain' : '';\n }\n\n resolveAuth(_request: GatewayAuthRequest): GatewayAuthResult | undefined {\n // Amazon Bedrock authenticates via the AWS credential chain rather than a\n // stored API key, so report it as authenticated whenever AWS credentials look\n // available. The actual SigV4 signing happens inside `bedrockProvider()`.\n if (hasAwsCredentials()) {\n return { apiKey: 'aws-credential-chain', source: 'gateway' };\n }\n return undefined;\n }\n\n resolveLanguageModel(args: {\n modelId: string;\n providerId: string;\n apiKey: string;\n headers?: Record<string, string>;\n transport?: any;\n responsesWebSocket?: any;\n }): GatewayLanguageModel {\n return bedrockProvider(args.modelId, args.headers) as unknown as GatewayLanguageModel;\n }\n}\n\nexport function createAmazonBedrockGateway(): AmazonBedrockGateway {\n return new AmazonBedrockGateway();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"amazon-bedrock-gateway.js","names":[],"sources":["../../src/providers/amazon-bedrock-gateway.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';\nimport { fromNodeProviderChain } from '@aws-sdk/credential-providers';\nimport { MastraModelGateway } from '@mastra/core/llm';\nimport type { GatewayAuthRequest, GatewayAuthResult, GatewayLanguageModel, ProviderConfig } from '@mastra/core/llm';\nimport { getBedrockModelCatalog } from './amazon-bedrock.js';\n\ntype ModelRequestHeaders = Record<string, string>;\ntype BedrockModel = ReturnType<ReturnType<typeof createAmazonBedrock>>;\ntype BedrockPrompt = Parameters<BedrockModel['doGenerate']>[0]['prompt'];\n\n// Claude 3.x is a closed set: only these three variants support cachePoint on Bedrock.\n// claude-3-5-sonnet-20240620 is intentionally excluded (only the 20241022-v2:0 variant caches).\n// Every Claude 4+ and every named family (opus-5, sonnet-5, fable, mythos, …) supports it.\nconst CLAUDE_3_CACHEABLE = /claude-3-7-sonnet|claude-3-5-sonnet-20241022|claude-3-5-haiku/;\n\nexport function supportsBedrockPromptCaching(modelId: string): boolean {\n if (!modelId.includes('anthropic.claude')) return false;\n return /anthropic\\.claude-3-/.test(modelId) ? CLAUDE_3_CACHEABLE.test(modelId) : true;\n}\n\nexport function addBedrockCachePoints(prompt: BedrockPrompt): BedrockPrompt {\n const result = [...prompt];\n const markCachePoint = (message: (typeof result)[number]) => ({\n ...message,\n providerOptions: {\n ...message.providerOptions,\n bedrock: {\n ...message.providerOptions?.bedrock,\n cachePoint: { type: 'default' },\n },\n },\n });\n\n let lastSystemIndex = -1;\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index]!.role === 'system') {\n lastSystemIndex = index;\n break;\n }\n }\n\n if (lastSystemIndex >= 0) {\n result[lastSystemIndex] = markCachePoint(result[lastSystemIndex]!);\n }\n\n let lastNonSystemIndex = -1;\n for (let index = result.length - 1; index >= 0; index--) {\n if (result[index]!.role !== 'system') {\n lastNonSystemIndex = index;\n break;\n }\n }\n\n if (lastNonSystemIndex >= 0) {\n result[lastNonSystemIndex] = markCachePoint(result[lastNonSystemIndex]!);\n }\n\n return result;\n}\n\nexport function withBedrockCache(model: BedrockModel): BedrockModel {\n return new Proxy(model, {\n get(target, property, receiver) {\n if (property === 'doGenerate') {\n return (options: Parameters<BedrockModel['doGenerate']>[0]) =>\n target.doGenerate({ ...options, prompt: addBedrockCachePoints(options.prompt) });\n }\n if (property === 'doStream') {\n return (options: Parameters<BedrockModel['doStream']>[0]) =>\n target.doStream({ ...options, prompt: addBedrockCachePoints(options.prompt) });\n }\n return Reflect.get(target, property, receiver);\n },\n });\n}\n\nexport const AMAZON_BEDROCK_GATEWAY_ID = 'amazon-bedrock';\n\n/**\n * Whether AWS credentials look available for Bedrock.\n *\n * Amazon Bedrock authenticates with AWS SigV4 rather than a bearer API key, so\n * this only governs whether Bedrock models are offered as \"authenticated\" in the\n * picker. We look for the common signals (env vars, bearer token, a configured\n * profile, or a shared credentials/config file) rather than resolving\n * credentials here, since the auth checker must stay sync.\n */\nexport function hasAwsCredentials(): boolean {\n if (\n process.env.AWS_BEARER_TOKEN_BEDROCK ||\n (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n process.env.AWS_SHARED_CREDENTIALS_FILE ||\n process.env.AWS_CONFIG_FILE ||\n process.env.AWS_PROFILE ||\n process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n process.env.AWS_WEB_IDENTITY_TOKEN_FILE\n ) {\n return true;\n }\n const home = process.env.HOME || process.env.USERPROFILE;\n if (home) {\n const awsDir = path.join(home, '.aws');\n const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE ?? path.join(awsDir, 'credentials');\n const configPath = process.env.AWS_CONFIG_FILE ?? path.join(awsDir, 'config');\n if (existsSync(credentialsPath) || existsSync(configPath)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Create an Amazon Bedrock model.\n *\n * Bedrock authenticates with AWS SigV4 rather than a bearer API key, so this\n * resolves credentials through the standard AWS provider chain\n * (`fromNodeProviderChain`): environment variables, shared `~/.aws` config and\n * SSO profiles, and container/instance roles — the same resolution order the AWS\n * CLI uses. The region falls back to `us-east-1` to match the AWS SDK default.\n *\n * When `AWS_BEARER_TOKEN_BEDROCK` is set, `@ai-sdk/amazon-bedrock` uses bearer\n * auth instead and ignores the credential provider, so we leave that path to the\n * SDK and only wire up SigV4 here.\n */\nfunction bedrockProvider(modelId: string, headers?: ModelRequestHeaders) {\n const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1';\n const bedrock = createAmazonBedrock({\n region,\n credentialProvider: fromNodeProviderChain(),\n headers,\n });\n const model = bedrock(modelId);\n return supportsBedrockPromptCaching(modelId) ? withBedrockCache(model) : model;\n}\n\n/**\n * Standalone Amazon Bedrock gateway.\n *\n * Bedrock is resolved directly via AWS SigV4 (not through the model router) and\n * its models are surfaced from the public models.dev catalog. It is exposed as\n * its own gateway/provider (`amazon-bedrock/...`) rather than nested under the\n * MastraCode gateway namespace.\n */\nexport class AmazonBedrockGateway extends MastraModelGateway {\n readonly id = AMAZON_BEDROCK_GATEWAY_ID;\n readonly name = 'Amazon Bedrock';\n\n shouldEnable(): boolean {\n return hasAwsCredentials();\n }\n\n async fetchProviders(): Promise<Record<string, ProviderConfig>> {\n const providers: Record<string, ProviderConfig> = {};\n try {\n const bedrockModels = await getBedrockModelCatalog();\n providers['amazon-bedrock'] = {\n name: 'Amazon Bedrock',\n apiKeyEnvVar: '',\n apiKeyHeader: 'Authorization',\n gateway: this.id,\n models: bedrockModels.map(model => model.id),\n };\n } catch (error) {\n console.warn('Failed to load Amazon Bedrock model catalog:', error);\n }\n return providers;\n }\n\n buildUrl(_modelId: string): string | undefined {\n return undefined;\n }\n\n async getApiKey(_modelId: string): Promise<string> {\n return hasAwsCredentials() ? 'aws-credential-chain' : '';\n }\n\n resolveAuth(_request: GatewayAuthRequest): GatewayAuthResult | undefined {\n // Amazon Bedrock authenticates via the AWS credential chain rather than a\n // stored API key, so report it as authenticated whenever AWS credentials look\n // available. The actual SigV4 signing happens inside `bedrockProvider()`.\n if (hasAwsCredentials()) {\n return { apiKey: 'aws-credential-chain', source: 'gateway' };\n }\n return undefined;\n }\n\n resolveLanguageModel(args: {\n modelId: string;\n providerId: string;\n apiKey: string;\n headers?: Record<string, string>;\n transport?: any;\n responsesWebSocket?: any;\n }): GatewayLanguageModel {\n return bedrockProvider(args.modelId, args.headers) as unknown as GatewayLanguageModel;\n }\n}\n\nexport function createAmazonBedrockGateway(): AmazonBedrockGateway {\n return new AmazonBedrockGateway();\n}\n"],"mappings":"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"}
@@ -11,8 +11,8 @@
11
11
  */
12
12
  const MODELS_DEV_API_URL = "https://models.dev/api.json";
13
13
  const BEDROCK_PROVIDER_ID = "amazon-bedrock";
14
- const CATALOG_TTL_MS = 3600 * 1e3;
15
- const CATALOG_FAILURE_TTL_MS = 60 * 1e3;
14
+ const CATALOG_TTL_MS = 36e5;
15
+ const CATALOG_FAILURE_TTL_MS = 6e4;
16
16
  const CATALOG_FETCH_TIMEOUT_MS = 5e3;
17
17
  /**
18
18
  * True when the catalog entry asks for a transport this catalog cannot serve.
@@ -1 +1 @@
1
- {"version":3,"file":"amazon-bedrock.js","names":[],"sources":["../../src/providers/amazon-bedrock.ts"],"sourcesContent":["/**\n * Amazon Bedrock model catalog.\n *\n * Bedrock is not part of mastracode's gateway-synced model router (it\n * authenticates with AWS SigV4 rather than an API key / base URL, so it is\n * resolved directly in `agents/model.ts`). To still offer Bedrock models in the\n * `/models` picker and packs, we fetch the public models.dev catalog — the same\n * source the model router uses — and expose the `amazon-bedrock` provider's\n * model list. This mirrors the GitHub Copilot catalog approach.\n */\n\nconst MODELS_DEV_API_URL = 'https://models.dev/api.json';\nconst BEDROCK_PROVIDER_ID = 'amazon-bedrock';\n\nconst CATALOG_TTL_MS = 60 * 60 * 1000;\nconst CATALOG_FAILURE_TTL_MS = 60 * 1000;\nconst CATALOG_FETCH_TIMEOUT_MS = 5_000;\n\nexport interface BedrockModelEntry {\n id: string;\n}\n\n/**\n * A models.dev catalog entry for one Bedrock model.\n *\n * Most entries carry no `provider` block: they are served by the SigV4\n * `bedrock-runtime` Converse API, which is what this catalog feeds. An entry\n * that *does* carry one is overriding that transport.\n */\ninterface BedrockCatalogEntry {\n provider?: {\n npm?: string;\n api?: string;\n shape?: string;\n };\n}\n\n/**\n * True when the catalog entry asks for a transport this catalog cannot serve.\n *\n * Every id returned here is handed to `createAmazonBedrock()(modelId)` by\n * `amazon-bedrock-gateway.ts`, i.e. the Converse API, unconditionally. A\n * `provider` override in the catalog means the model wants a different endpoint\n * and API shape: the nine `bedrock-mantle` models point at\n * `https://bedrock-mantle.${AWS_REGION}.api.aws/openai/v1` with\n * `shape: \"responses\"`. Advertising them makes them selectable in `/models` and\n * in packs even though the request that follows cannot reach them.\n *\n * Filtering is deliberately conservative: it hides what is currently unusable\n * rather than guessing at a transport. Routing these to Mantle properly is a\n * separate change and a design call for the maintainers.\n */\nfunction needsUnsupportedTransport(entry: unknown): boolean {\n const provider = (entry as BedrockCatalogEntry | null)?.provider;\n return Boolean(provider && (provider.npm || provider.api || provider.shape));\n}\n\n/**\n * A small, stable fallback so Bedrock packs keep working offline or when\n * models.dev is unreachable. Intentionally minimal — the live catalog is the\n * source of truth and supersedes this within one fetch.\n */\nconst BEDROCK_FALLBACK_MODELS: BedrockModelEntry[] = [\n { id: 'us.anthropic.claude-opus-4-6-v1' },\n { id: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0' },\n { id: 'us.anthropic.claude-haiku-4-5-20251001-v1:0' },\n];\n\ninterface CatalogCacheEntry {\n fetchedAt: number;\n ttl: number;\n models: BedrockModelEntry[];\n}\n\nlet catalogCache: CatalogCacheEntry | null = null;\nlet inflightFetch: Promise<BedrockModelEntry[]> | null = null;\n\n/** Reset the in-process Bedrock catalog cache (test seam). */\nexport function clearBedrockCatalogCache(): void {\n catalogCache = null;\n inflightFetch = null;\n}\n\nasync function fetchBedrockModels(signal: AbortSignal): Promise<BedrockModelEntry[]> {\n const response = await fetch(MODELS_DEV_API_URL, { signal });\n if (!response.ok) {\n throw new Error(`models.dev returned ${response.status}`);\n }\n const data = (await response.json()) as Record<string, { models?: Record<string, unknown> }>;\n const provider = data[BEDROCK_PROVIDER_ID];\n const models = provider?.models ?? {};\n return Object.entries(models)\n .filter(([, entry]) => !needsUnsupportedTransport(entry))\n .map(([id]) => id)\n .sort()\n .map(id => ({ id }));\n}\n\n/**\n * Return the available Amazon Bedrock models.\n *\n * - Returns the cached list when a recent fetch succeeded.\n * - On cache miss / expiry, fetches the models.dev catalog with a 5s timeout and\n * caches it for an hour.\n * - On fetch failure, returns a small hard-coded fallback (so packs still work\n * offline) and caches that briefly to avoid hammering the network.\n *\n * Concurrent calls during a fetch share the inflight promise.\n */\nexport async function getBedrockModelCatalog(): Promise<BedrockModelEntry[]> {\n const now = Date.now();\n if (catalogCache && now - catalogCache.fetchedAt < catalogCache.ttl) {\n return catalogCache.models;\n }\n\n if (inflightFetch) return inflightFetch;\n\n inflightFetch = (async (): Promise<BedrockModelEntry[]> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), CATALOG_FETCH_TIMEOUT_MS);\n try {\n const models = await fetchBedrockModels(controller.signal);\n catalogCache = { fetchedAt: Date.now(), ttl: CATALOG_TTL_MS, models };\n return models;\n } catch (error) {\n catalogCache = {\n fetchedAt: Date.now(),\n ttl: CATALOG_FAILURE_TTL_MS,\n models: BEDROCK_FALLBACK_MODELS,\n };\n console.warn(\n 'Failed to fetch live Amazon Bedrock models, using fallback list:',\n error instanceof Error ? error.message : error,\n );\n return BEDROCK_FALLBACK_MODELS;\n } finally {\n clearTimeout(timer);\n inflightFetch = null;\n }\n })();\n\n return inflightFetch;\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAE5B,MAAM,iBAAiB,OAAU;AACjC,MAAM,yBAAyB,KAAK;AACpC,MAAM,2BAA2B;;;;;;;;;;;;;;;;AAoCjC,SAAS,0BAA0B,OAAyB;CAC1D,MAAM,WAAY,OAAsC;CACxD,OAAO,QAAQ,aAAa,SAAS,OAAO,SAAS,OAAO,SAAS,MAAM;AAC7E;;;;;;AAOA,MAAM,0BAA+C;CACnD,EAAE,IAAI,kCAAkC;CACxC,EAAE,IAAI,+CAA+C;CACrD,EAAE,IAAI,8CAA8C;AACtD;AAQA,IAAI,eAAyC;AAC7C,IAAI,gBAAqD;;AAGzD,SAAgB,2BAAiC;CAC/C,eAAe;CACf,gBAAgB;AAClB;AAEA,eAAe,mBAAmB,QAAmD;CACnF,MAAM,WAAW,MAAM,MAAM,oBAAoB,EAAE,OAAO,CAAC;CAC3D,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;CAI1D,MAAM,UADW,MADG,SAAS,KAAK,EAAA,CACZ,oBACC,EAAE,UAAU,CAAC;CACpC,OAAO,OAAO,QAAQ,MAAM,CAAC,CAC1B,QAAQ,GAAG,WAAW,CAAC,0BAA0B,KAAK,CAAC,CAAC,CACxD,KAAK,CAAC,QAAQ,EAAE,CAAC,CACjB,KAAK,CAAC,CACN,KAAI,QAAO,EAAE,GAAG,EAAE;AACvB;;;;;;;;;;;;AAaA,eAAsB,yBAAuD;CAE3E,IAAI,gBADQ,KAAK,IACK,IAAI,aAAa,YAAY,aAAa,KAC9D,OAAO,aAAa;CAGtB,IAAI,eAAe,OAAO;CAE1B,iBAAiB,YAA0C;EACzD,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,QAAQ,iBAAiB,WAAW,MAAM,GAAG,wBAAwB;EAC3E,IAAI;GACF,MAAM,SAAS,MAAM,mBAAmB,WAAW,MAAM;GACzD,eAAe;IAAE,WAAW,KAAK,IAAI;IAAG,KAAK;IAAgB;GAAO;GACpE,OAAO;EACT,SAAS,OAAO;GACd,eAAe;IACb,WAAW,KAAK,IAAI;IACpB,KAAK;IACL,QAAQ;GACV;GACA,QAAQ,KACN,oEACA,iBAAiB,QAAQ,MAAM,UAAU,KAC3C;GACA,OAAO;EACT,UAAU;GACR,aAAa,KAAK;GAClB,gBAAgB;EAClB;CACF,EAAA,CAAG;CAEH,OAAO;AACT"}
1
+ {"version":3,"file":"amazon-bedrock.js","names":[],"sources":["../../src/providers/amazon-bedrock.ts"],"sourcesContent":["/**\n * Amazon Bedrock model catalog.\n *\n * Bedrock is not part of mastracode's gateway-synced model router (it\n * authenticates with AWS SigV4 rather than an API key / base URL, so it is\n * resolved directly in `agents/model.ts`). To still offer Bedrock models in the\n * `/models` picker and packs, we fetch the public models.dev catalog — the same\n * source the model router uses — and expose the `amazon-bedrock` provider's\n * model list. This mirrors the GitHub Copilot catalog approach.\n */\n\nconst MODELS_DEV_API_URL = 'https://models.dev/api.json';\nconst BEDROCK_PROVIDER_ID = 'amazon-bedrock';\n\nconst CATALOG_TTL_MS = 60 * 60 * 1000;\nconst CATALOG_FAILURE_TTL_MS = 60 * 1000;\nconst CATALOG_FETCH_TIMEOUT_MS = 5_000;\n\nexport interface BedrockModelEntry {\n id: string;\n}\n\n/**\n * A models.dev catalog entry for one Bedrock model.\n *\n * Most entries carry no `provider` block: they are served by the SigV4\n * `bedrock-runtime` Converse API, which is what this catalog feeds. An entry\n * that *does* carry one is overriding that transport.\n */\ninterface BedrockCatalogEntry {\n provider?: {\n npm?: string;\n api?: string;\n shape?: string;\n };\n}\n\n/**\n * True when the catalog entry asks for a transport this catalog cannot serve.\n *\n * Every id returned here is handed to `createAmazonBedrock()(modelId)` by\n * `amazon-bedrock-gateway.ts`, i.e. the Converse API, unconditionally. A\n * `provider` override in the catalog means the model wants a different endpoint\n * and API shape: the nine `bedrock-mantle` models point at\n * `https://bedrock-mantle.${AWS_REGION}.api.aws/openai/v1` with\n * `shape: \"responses\"`. Advertising them makes them selectable in `/models` and\n * in packs even though the request that follows cannot reach them.\n *\n * Filtering is deliberately conservative: it hides what is currently unusable\n * rather than guessing at a transport. Routing these to Mantle properly is a\n * separate change and a design call for the maintainers.\n */\nfunction needsUnsupportedTransport(entry: unknown): boolean {\n const provider = (entry as BedrockCatalogEntry | null)?.provider;\n return Boolean(provider && (provider.npm || provider.api || provider.shape));\n}\n\n/**\n * A small, stable fallback so Bedrock packs keep working offline or when\n * models.dev is unreachable. Intentionally minimal — the live catalog is the\n * source of truth and supersedes this within one fetch.\n */\nconst BEDROCK_FALLBACK_MODELS: BedrockModelEntry[] = [\n { id: 'us.anthropic.claude-opus-4-6-v1' },\n { id: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0' },\n { id: 'us.anthropic.claude-haiku-4-5-20251001-v1:0' },\n];\n\ninterface CatalogCacheEntry {\n fetchedAt: number;\n ttl: number;\n models: BedrockModelEntry[];\n}\n\nlet catalogCache: CatalogCacheEntry | null = null;\nlet inflightFetch: Promise<BedrockModelEntry[]> | null = null;\n\n/** Reset the in-process Bedrock catalog cache (test seam). */\nexport function clearBedrockCatalogCache(): void {\n catalogCache = null;\n inflightFetch = null;\n}\n\nasync function fetchBedrockModels(signal: AbortSignal): Promise<BedrockModelEntry[]> {\n const response = await fetch(MODELS_DEV_API_URL, { signal });\n if (!response.ok) {\n throw new Error(`models.dev returned ${response.status}`);\n }\n const data = (await response.json()) as Record<string, { models?: Record<string, unknown> }>;\n const provider = data[BEDROCK_PROVIDER_ID];\n const models = provider?.models ?? {};\n return Object.entries(models)\n .filter(([, entry]) => !needsUnsupportedTransport(entry))\n .map(([id]) => id)\n .sort()\n .map(id => ({ id }));\n}\n\n/**\n * Return the available Amazon Bedrock models.\n *\n * - Returns the cached list when a recent fetch succeeded.\n * - On cache miss / expiry, fetches the models.dev catalog with a 5s timeout and\n * caches it for an hour.\n * - On fetch failure, returns a small hard-coded fallback (so packs still work\n * offline) and caches that briefly to avoid hammering the network.\n *\n * Concurrent calls during a fetch share the inflight promise.\n */\nexport async function getBedrockModelCatalog(): Promise<BedrockModelEntry[]> {\n const now = Date.now();\n if (catalogCache && now - catalogCache.fetchedAt < catalogCache.ttl) {\n return catalogCache.models;\n }\n\n if (inflightFetch) return inflightFetch;\n\n inflightFetch = (async (): Promise<BedrockModelEntry[]> => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), CATALOG_FETCH_TIMEOUT_MS);\n try {\n const models = await fetchBedrockModels(controller.signal);\n catalogCache = { fetchedAt: Date.now(), ttl: CATALOG_TTL_MS, models };\n return models;\n } catch (error) {\n catalogCache = {\n fetchedAt: Date.now(),\n ttl: CATALOG_FAILURE_TTL_MS,\n models: BEDROCK_FALLBACK_MODELS,\n };\n console.warn(\n 'Failed to fetch live Amazon Bedrock models, using fallback list:',\n error instanceof Error ? error.message : error,\n );\n return BEDROCK_FALLBACK_MODELS;\n } finally {\n clearTimeout(timer);\n inflightFetch = null;\n }\n })();\n\n return inflightFetch;\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAE5B,MAAM,iBAAiB;AACvB,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B;;;;;;;;;;;;;;;;AAoCjC,SAAS,0BAA0B,OAAyB;CAC1D,MAAM,WAAY,OAAsC;CACxD,OAAO,QAAQ,aAAa,SAAS,OAAO,SAAS,OAAO,SAAS,MAAM;AAC7E;;;;;;AAOA,MAAM,0BAA+C;CACnD,EAAE,IAAI,kCAAkC;CACxC,EAAE,IAAI,+CAA+C;CACrD,EAAE,IAAI,8CAA8C;AACtD;AAQA,IAAI,eAAyC;AAC7C,IAAI,gBAAqD;;AAGzD,SAAgB,2BAAiC;CAC/C,eAAe;CACf,gBAAgB;AAClB;AAEA,eAAe,mBAAmB,QAAmD;CACnF,MAAM,WAAW,MAAM,MAAM,oBAAoB,EAAE,OAAO,CAAC;CAC3D,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;CAI1D,MAAM,UADW,MADG,SAAS,KAAK,EAAA,CACZ,oBACC,EAAE,UAAU,CAAC;CACpC,OAAO,OAAO,QAAQ,MAAM,CAAC,CAC1B,QAAQ,GAAG,WAAW,CAAC,0BAA0B,KAAK,CAAC,CAAC,CACxD,KAAK,CAAC,QAAQ,EAAE,CAAC,CACjB,KAAK,CAAC,CACN,KAAI,QAAO,EAAE,GAAG,EAAE;AACvB;;;;;;;;;;;;AAaA,eAAsB,yBAAuD;CAE3E,IAAI,gBADQ,KAAK,IACK,IAAI,aAAa,YAAY,aAAa,KAC9D,OAAO,aAAa;CAGtB,IAAI,eAAe,OAAO;CAE1B,iBAAiB,YAA0C;EACzD,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,QAAQ,iBAAiB,WAAW,MAAM,GAAG,wBAAwB;EAC3E,IAAI;GACF,MAAM,SAAS,MAAM,mBAAmB,WAAW,MAAM;GACzD,eAAe;IAAE,WAAW,KAAK,IAAI;IAAG,KAAK;IAAgB;GAAO;GACpE,OAAO;EACT,SAAS,OAAO;GACd,eAAe;IACb,WAAW,KAAK,IAAI;IACpB,KAAK;IACL,QAAQ;GACV;GACA,QAAQ,KACN,oEACA,iBAAiB,QAAQ,MAAM,UAAU,KAC3C;GACA,OAAO;EACT,UAAU;GACR,aAAa,KAAK;GAClB,gBAAgB;EAClB;CACF,EAAA,CAAG;CAEH,OAAO;AACT"}
@@ -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;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,CAyCnG;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,CAyCnG;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,MAA4B,EACrC,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"}
@@ -200,7 +200,7 @@ function buildAnthropicOAuthFetch(opts = {}) {
200
200
  * Creates an Anthropic model using Claude Max OAuth authentication
201
201
  * Uses OAuth tokens from AuthStorage (auto-refreshes when needed)
202
202
  */
203
- function opencodeClaudeMaxProvider(modelId = "claude-sonnet-4-20250514", options) {
203
+ function opencodeClaudeMaxProvider(modelId = "claude-sonnet-5-5", options) {
204
204
  const headers = options?.headers;
205
205
  const thinkingMiddleware = createAnthropicThinkingMiddleware(modelId, options?.thinkingLevel);
206
206
  const middleware = [
@@ -208,19 +208,23 @@ function opencodeClaudeMaxProvider(modelId = "claude-sonnet-4-20250514", options
208
208
  createPromptCacheMiddleware(options?.promptCacheScope ?? "conversation"),
209
209
  ...thinkingMiddleware ? [thinkingMiddleware] : []
210
210
  ];
211
- if (process.env.NODE_ENV === "test" || process.env.VITEST) return wrapLanguageModel({
212
- model: createAnthropic({
211
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) {
212
+ const anthropic = createAnthropic({
213
213
  apiKey: "test-api-key",
214
214
  headers
215
- })(modelId),
216
- middleware
215
+ });
216
+ return wrapLanguageModel({
217
+ model: anthropic(modelId),
218
+ middleware
219
+ });
220
+ }
221
+ const anthropic = createAnthropic({
222
+ apiKey: "oauth-placeholder",
223
+ headers,
224
+ fetch: buildAnthropicOAuthFetch({ authStorage: options?.authStorage })
217
225
  });
218
226
  return wrapLanguageModel({
219
- model: createAnthropic({
220
- apiKey: "oauth-placeholder",
221
- headers,
222
- fetch: buildAnthropicOAuthFetch({ authStorage: options?.authStorage })
223
- })(modelId),
227
+ model: anthropic(modelId),
224
228
  middleware
225
229
  });
226
230
  }
@@ -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, rejectUnauthorizedResponse } 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 const requestUrl = url instanceof URL ? url.toString() : typeof url === 'string' ? url : url.url;\n try {\n return await rejectUnauthorizedResponse(await fetch(url, { ...init, headers }), {\n providerName: 'Anthropic',\n requestUrl,\n });\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, { requestUrl });\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, rejectUnauthorizedResponse } 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 const requestUrl = url instanceof URL ? url.toString() : typeof url === 'string' ? url : url.url;\n try {\n return await rejectUnauthorizedResponse(await fetch(url, { ...init, headers }), {\n providerName: 'Anthropic',\n requestUrl,\n });\n } catch (error) {\n if (error && typeof error === 'object') {\n Object.assign(error as Record<string, unknown>, { requestUrl });\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-5-5',\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 +1 @@
1
- {"version":3,"file":"github-copilot-gateway.js","names":["#credentials","#store"],"sources":["../../src/providers/github-copilot-gateway.ts"],"sourcesContent":["import { MastraModelGateway } from '@mastra/core/llm';\nimport type { GatewayAuthRequest, GatewayAuthResult, GatewayLanguageModel, ProviderConfig } from '@mastra/core/llm';\nimport type { CredentialStore } from '../auth/types.js';\nimport { getAuthStorage, getCopilotModelCatalog, githubCopilotProvider } from './github-copilot.js';\n\nexport const GITHUB_COPILOT_GATEWAY_ID = 'github-copilot';\n\n/**\n * Standalone GitHub Copilot gateway.\n *\n * models.dev excludes Copilot from the shared registry, so Mastra Code supplies\n * the provider itself. It is its own gateway so catalog ids are the canonical\n * `github-copilot/<model>` rather than `mastracode/github-copilot/<model>`.\n */\nexport class GitHubCopilotGateway extends MastraModelGateway {\n readonly id = GITHUB_COPILOT_GATEWAY_ID;\n readonly name = 'GitHub Copilot';\n readonly #credentials?: CredentialStore;\n\n constructor(options: { credentialStore?: CredentialStore } = {}) {\n super();\n this.#credentials = options.credentialStore;\n }\n\n get #store(): CredentialStore {\n return this.#credentials ?? getAuthStorage();\n }\n\n async fetchProviders(): Promise<Record<string, ProviderConfig>> {\n try {\n const models = await getCopilotModelCatalog({ authStorage: this.#store });\n return {\n [GITHUB_COPILOT_GATEWAY_ID]: {\n name: 'GitHub Copilot',\n apiKeyEnvVar: '',\n apiKeyHeader: 'Authorization',\n gateway: this.id,\n models: models.map(model => model.id),\n },\n };\n } catch (error) {\n console.warn('Failed to load GitHub Copilot model catalog:', error);\n return {};\n }\n }\n\n buildUrl(_modelId: string): string | undefined {\n return undefined;\n }\n\n async getApiKey(_modelId: string): Promise<string> {\n return '';\n }\n\n resolveAuth(_request: GatewayAuthRequest): GatewayAuthResult | undefined {\n // The OAuth token is attached per request by the Copilot fetch wrapper.\n return this.#store.get(GITHUB_COPILOT_GATEWAY_ID)?.type === 'oauth'\n ? { bearerToken: 'oauth', source: 'gateway' }\n : undefined;\n }\n\n resolveLanguageModel(args: {\n modelId: string;\n providerId: string;\n apiKey: string;\n headers?: Record<string, string>;\n transport?: any;\n responsesWebSocket?: any;\n }): GatewayLanguageModel {\n return githubCopilotProvider(args.modelId, {\n headers: args.headers,\n authStorage: this.#store,\n }) as unknown as GatewayLanguageModel;\n }\n}\n\nexport function createGitHubCopilotGateway(options?: { credentialStore?: CredentialStore }): GitHubCopilotGateway {\n return new GitHubCopilotGateway(options);\n}\n"],"mappings":";;;AAKA,MAAa,4BAA4B;;;;;;;;AASzC,IAAa,uBAAb,cAA0C,mBAAmB;CAC3D,KAAc;CACd,OAAgB;CAChB;CAEA,YAAY,UAAiD,CAAC,GAAG;EAC/D,MAAM;EACN,KAAKA,eAAe,QAAQ;CAC9B;CAEA,IAAIC,SAA0B;EAC5B,OAAO,KAAKD,gBAAgB,eAAe;CAC7C;CAEA,MAAM,iBAA0D;EAC9D,IAAI;GACF,MAAM,SAAS,MAAM,uBAAuB,EAAE,aAAa,KAAKC,OAAO,CAAC;GACxE,OAAO,GACJ,4BAA4B;IAC3B,MAAM;IACN,cAAc;IACd,cAAc;IACd,SAAS,KAAK;IACd,QAAQ,OAAO,KAAI,UAAS,MAAM,EAAE;GACtC,EACF;EACF,SAAS,OAAO;GACd,QAAQ,KAAK,gDAAgD,KAAK;GAClE,OAAO,CAAC;EACV;CACF;CAEA,SAAS,UAAsC,CAE/C;CAEA,MAAM,UAAU,UAAmC;EACjD,OAAO;CACT;CAEA,YAAY,UAA6D;EAEvE,OAAO,KAAKA,OAAO,IAAA,gBAA6B,CAAC,EAAE,SAAS,UACxD;GAAE,aAAa;GAAS,QAAQ;EAAU,IAC1C,KAAA;CACN;CAEA,qBAAqB,MAOI;EACvB,OAAO,sBAAsB,KAAK,SAAS;GACzC,SAAS,KAAK;GACd,aAAa,KAAKA;EACpB,CAAC;CACH;AACF;AAEA,SAAgB,2BAA2B,SAAuE;CAChH,OAAO,IAAI,qBAAqB,OAAO;AACzC"}
1
+ {"version":3,"file":"github-copilot-gateway.js","names":[],"sources":["../../src/providers/github-copilot-gateway.ts"],"sourcesContent":["import { MastraModelGateway } from '@mastra/core/llm';\nimport type { GatewayAuthRequest, GatewayAuthResult, GatewayLanguageModel, ProviderConfig } from '@mastra/core/llm';\nimport type { CredentialStore } from '../auth/types.js';\nimport { getAuthStorage, getCopilotModelCatalog, githubCopilotProvider } from './github-copilot.js';\n\nexport const GITHUB_COPILOT_GATEWAY_ID = 'github-copilot';\n\n/**\n * Standalone GitHub Copilot gateway.\n *\n * models.dev excludes Copilot from the shared registry, so Mastra Code supplies\n * the provider itself. It is its own gateway so catalog ids are the canonical\n * `github-copilot/<model>` rather than `mastracode/github-copilot/<model>`.\n */\nexport class GitHubCopilotGateway extends MastraModelGateway {\n readonly id = GITHUB_COPILOT_GATEWAY_ID;\n readonly name = 'GitHub Copilot';\n readonly #credentials?: CredentialStore;\n\n constructor(options: { credentialStore?: CredentialStore } = {}) {\n super();\n this.#credentials = options.credentialStore;\n }\n\n get #store(): CredentialStore {\n return this.#credentials ?? getAuthStorage();\n }\n\n async fetchProviders(): Promise<Record<string, ProviderConfig>> {\n try {\n const models = await getCopilotModelCatalog({ authStorage: this.#store });\n return {\n [GITHUB_COPILOT_GATEWAY_ID]: {\n name: 'GitHub Copilot',\n apiKeyEnvVar: '',\n apiKeyHeader: 'Authorization',\n gateway: this.id,\n models: models.map(model => model.id),\n },\n };\n } catch (error) {\n console.warn('Failed to load GitHub Copilot model catalog:', error);\n return {};\n }\n }\n\n buildUrl(_modelId: string): string | undefined {\n return undefined;\n }\n\n async getApiKey(_modelId: string): Promise<string> {\n return '';\n }\n\n resolveAuth(_request: GatewayAuthRequest): GatewayAuthResult | undefined {\n // The OAuth token is attached per request by the Copilot fetch wrapper.\n return this.#store.get(GITHUB_COPILOT_GATEWAY_ID)?.type === 'oauth'\n ? { bearerToken: 'oauth', source: 'gateway' }\n : undefined;\n }\n\n resolveLanguageModel(args: {\n modelId: string;\n providerId: string;\n apiKey: string;\n headers?: Record<string, string>;\n transport?: any;\n responsesWebSocket?: any;\n }): GatewayLanguageModel {\n return githubCopilotProvider(args.modelId, {\n headers: args.headers,\n authStorage: this.#store,\n }) as unknown as GatewayLanguageModel;\n }\n}\n\nexport function createGitHubCopilotGateway(options?: { credentialStore?: CredentialStore }): GitHubCopilotGateway {\n return new GitHubCopilotGateway(options);\n}\n"],"mappings":";;;AAKA,MAAa,4BAA4B;;;;;;;;AASzC,IAAa,uBAAb,cAA0C,mBAAmB;CAC3D,KAAc;CACd,OAAgB;CAChB;CAEA,YAAY,UAAiD,CAAC,GAAG;EAC/D,MAAM;EACN,KAAK,eAAe,QAAQ;CAC9B;CAEA,IAAI,SAA0B;EAC5B,OAAO,KAAK,gBAAgB,eAAe;CAC7C;CAEA,MAAM,iBAA0D;EAC9D,IAAI;GACF,MAAM,SAAS,MAAM,uBAAuB,EAAE,aAAa,KAAK,OAAO,CAAC;GACxE,OAAO,GACJ,4BAA4B;IAC3B,MAAM;IACN,cAAc;IACd,cAAc;IACd,SAAS,KAAK;IACd,QAAQ,OAAO,KAAI,UAAS,MAAM,EAAE;GACtC,EACF;EACF,SAAS,OAAO;GACd,QAAQ,KAAK,gDAAgD,KAAK;GAClE,OAAO,CAAC;EACV;CACF;CAEA,SAAS,UAAsC,CAE/C;CAEA,MAAM,UAAU,UAAmC;EACjD,OAAO;CACT;CAEA,YAAY,UAA6D;EAEvE,OAAO,KAAK,OAAO,IAAA,gBAA6B,CAAC,EAAE,SAAS,UACxD;GAAE,aAAa;GAAS,QAAQ;EAAU,IAC1C,KAAA;CACN;CAEA,qBAAqB,MAOI;EACvB,OAAO,sBAAsB,KAAK,SAAS;GACzC,SAAS,KAAK;GACd,aAAa,KAAK;EACpB,CAAC;CACH;AACF;AAEA,SAAgB,2BAA2B,SAAuE;CAChH,OAAO,IAAI,qBAAqB,OAAO;AACzC"}
@@ -187,17 +187,18 @@ function createCopilotMiddleware(modelId) {
187
187
  */
188
188
  function githubCopilotProvider(modelId = "gpt-4.1", options) {
189
189
  const headers = options?.headers;
190
+ const copilot = createOpenAICompatible({
191
+ name: COPILOT_PROVIDER_ID,
192
+ baseURL: "https://api.githubcopilot.com",
193
+ apiKey: process.env.NODE_ENV === "test" || process.env.VITEST ? "test-api-key" : "oauth-placeholder",
194
+ headers,
195
+ fetch: process.env.NODE_ENV === "test" || process.env.VITEST ? void 0 : buildGitHubCopilotOAuthFetch({
196
+ rewriteUrl: false,
197
+ authStorage: options?.authStorage
198
+ })
199
+ });
190
200
  return wrapLanguageModel({
191
- model: createOpenAICompatible({
192
- name: COPILOT_PROVIDER_ID,
193
- baseURL: "https://api.githubcopilot.com",
194
- apiKey: process.env.NODE_ENV === "test" || process.env.VITEST ? "test-api-key" : "oauth-placeholder",
195
- headers,
196
- fetch: process.env.NODE_ENV === "test" || process.env.VITEST ? void 0 : buildGitHubCopilotOAuthFetch({
197
- rewriteUrl: false,
198
- authStorage: options?.authStorage
199
- })
200
- }).chatModel(modelId),
201
+ model: copilot.chatModel(modelId),
201
202
  middleware: [createCopilotMiddleware(modelId)]
202
203
  });
203
204
  }
@@ -217,8 +218,8 @@ const COPILOT_FALLBACK_MODELS = [{
217
218
  supportsVision: true,
218
219
  supportsToolCalls: true
219
220
  }];
220
- const CATALOG_TTL_MS = 600 * 1e3;
221
- const CATALOG_FAILURE_TTL_MS = 60 * 1e3;
221
+ const CATALOG_TTL_MS = 6e5;
222
+ const CATALOG_FAILURE_TTL_MS = 6e4;
222
223
  const CATALOG_FETCH_TIMEOUT_MS = 5e3;
223
224
  const catalogCache = /* @__PURE__ */ new Map();
224
225
  const inflightFetches = /* @__PURE__ */ new Map();