Skip to content

Commit ee3511e

Browse files
authored
Merge branch 'main' into processors-headers
2 parents 29bb742 + 9767cb8 commit ee3511e

File tree

32 files changed

+1535
-91
lines changed

32 files changed

+1535
-91
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@mastra/google-cloud-pubsub": patch
3+
---
4+
dependencies updates:
5+
- Updated dependency [`@google-cloud/pubsub@^5.2.2` ↗︎](https://www.npmjs.com/package/@google-cloud/pubsub/v/5.2.2) (from `^5.2.0`, in `dependencies`)

.changeset/frank-plums-stick.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@mastra/core': patch
3+
---
4+
5+
Fix ModelRouterLanguageModel to propagate supportedUrls from underlying model providers
6+
7+
Previously, `ModelRouterLanguageModel` (used when specifying models as strings like `"mistral/mistral-large-latest"` or `"openai/gpt-4o"`) had `supportedUrls` hardcoded as an empty object. This caused Mastra to download all file URLs and convert them to bytes/base64, even when the model provider supports URLs natively.
8+
9+
This fix:
10+
11+
- Changes `supportedUrls` to a lazy `PromiseLike` that resolves the underlying model's supported URL patterns
12+
- Updates `llm-execution-step.ts` to properly await `supportedUrls` when preparing messages
13+
14+
**Impact:**
15+
16+
- Mistral: PDF URLs are now passed directly (fixes #12152)
17+
- OpenAI: Image URLs (and PDF URLs in response models) are now passed directly
18+
- Anthropic: Image URLs are now passed directly
19+
- Google: Files from Google endpoints are now passed directly
20+
21+
**Note:** Users who were relying on Mastra to download files from URLs that model providers cannot directly access (internal URLs, auth-protected URLs) may need to adjust their approach by either using base64-encoded content or ensuring URLs are publicly accessible to the model provider.

.changeset/good-falcons-win.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@mastra/core': patch
3+
---
4+
5+
Fixed type error when using createTool with Agent when exactOptionalPropertyTypes is enabled in TypeScript config. The ProviderDefinedTool structural type now correctly marks inputSchema as optional and allows execute to be undefined, matching the ToolAction interface. Fixes #12281

.changeset/itchy-hornets-try.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@mastra/agent-builder': patch
3+
---
4+
5+
Fixed latent Memory storage bug in AgentBuilder. AgentBuilder was created without providing storage to Memory, causing intermittent failures when Memory operations were invoked. Now uses InMemoryStore as a fallback when no storage is provided, allowing it to function without explicit storage configuration.

.changeset/smooth-bananas-give.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@mastra/playground-ui': patch
3+
---
4+
5+
Remove hardcoded temperature: 0.5 and topP: 1 defaults from playground agent settings
6+
Let agent config and provider defaults handle these values instead
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
title: "CompositeAuth Class | Auth"
3+
description: "Documentation for the CompositeAuth class, which combines multiple authentication providers into a single auth handler."
4+
packages:
5+
- "@mastra/core"
6+
---
7+
8+
# CompositeAuth Class
9+
10+
The `CompositeAuth` class allows you to combine multiple authentication providers into a single auth handler. It tries each provider in order until one succeeds.
11+
12+
## Use Cases
13+
14+
- Support both API keys and OAuth tokens
15+
- Migrate between auth providers without breaking existing clients
16+
- Allow multiple identity providers (e.g., Clerk for web, API keys for integrations)
17+
- Gradual rollout of new authentication methods
18+
19+
## Installation
20+
21+
CompositeAuth is included in `@mastra/core`, no additional packages required.
22+
23+
```typescript
24+
import { CompositeAuth } from '@mastra/core/server';
25+
```
26+
27+
## Usage Example
28+
29+
Combine SimpleAuth (for API keys) with Clerk (for user sessions):
30+
31+
```typescript title="src/mastra/index.ts"
32+
import { Mastra } from '@mastra/core';
33+
import { CompositeAuth, SimpleAuth } from '@mastra/core/server';
34+
import { MastraAuthClerk } from '@mastra/auth-clerk';
35+
36+
// API key users
37+
type ApiKeyUser = {
38+
id: string;
39+
name: string;
40+
type: 'api-key';
41+
};
42+
43+
const apiKeyAuth = new SimpleAuth<ApiKeyUser>({
44+
tokens: {
45+
'sk-integration-key-123': {
46+
id: 'integration-1',
47+
name: 'CI/CD Pipeline',
48+
type: 'api-key',
49+
},
50+
},
51+
});
52+
53+
// Clerk users (from web app)
54+
const clerkAuth = new MastraAuthClerk({
55+
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
56+
secretKey: process.env.CLERK_SECRET_KEY,
57+
jwksUri: process.env.CLERK_JWKS_URI,
58+
});
59+
60+
export const mastra = new Mastra({
61+
server: {
62+
auth: new CompositeAuth([apiKeyAuth, clerkAuth]),
63+
},
64+
});
65+
```
66+
67+
## How It Works
68+
69+
When a request comes in, CompositeAuth:
70+
71+
1. Extracts the token from the `Authorization` header
72+
2. Tries each provider's `authenticateToken()` method in order
73+
3. Returns the user from the first provider that succeeds
74+
4. Returns `null` (401 Unauthorized) if all providers fail
75+
76+
For authorization, it calls each provider's `authorizeUser()` method until one returns `true`.
77+
78+
```typescript
79+
// Pseudocode of CompositeAuth behavior
80+
async authenticateToken(token, request) {
81+
for (const provider of this.providers) {
82+
const user = await provider.authenticateToken(token, request);
83+
if (user) return user; // First match wins
84+
}
85+
return null; // All providers failed
86+
}
87+
```
88+
89+
## Provider Order
90+
91+
The order of providers matters. Place the most common authentication method first for better performance:
92+
93+
```typescript
94+
// If most requests use Clerk, put it first
95+
new CompositeAuth([
96+
clerkAuth, // Checked first (most common)
97+
apiKeyAuth, // Checked second (less common)
98+
]);
99+
100+
// If most requests use API keys, put it first
101+
new CompositeAuth([
102+
apiKeyAuth, // Checked first (most common)
103+
clerkAuth, // Checked second (less common)
104+
]);
105+
```
106+
107+
## Multiple OAuth Providers
108+
109+
Support users from different identity providers:
110+
111+
```typescript
112+
import { CompositeAuth } from '@mastra/core/server';
113+
import { MastraAuthClerk } from '@mastra/auth-clerk';
114+
import { MastraAuthAuth0 } from '@mastra/auth-auth0';
115+
116+
const clerkAuth = new MastraAuthClerk({
117+
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
118+
secretKey: process.env.CLERK_SECRET_KEY,
119+
jwksUri: process.env.CLERK_JWKS_URI,
120+
});
121+
122+
const auth0Auth = new MastraAuthAuth0({
123+
domain: process.env.AUTH0_DOMAIN,
124+
audience: process.env.AUTH0_AUDIENCE,
125+
});
126+
127+
export const mastra = new Mastra({
128+
server: {
129+
auth: new CompositeAuth([clerkAuth, auth0Auth]),
130+
},
131+
});
132+
```
133+
134+
## Migration Example
135+
136+
Migrate from JWT to Clerk while maintaining backwards compatibility:
137+
138+
```typescript
139+
import { CompositeAuth } from '@mastra/core/server';
140+
import { MastraJwtAuth } from '@mastra/auth';
141+
import { MastraAuthClerk } from '@mastra/auth-clerk';
142+
143+
// Legacy JWT auth (existing clients)
144+
const legacyAuth = new MastraJwtAuth({
145+
secret: process.env.JWT_SECRET,
146+
});
147+
148+
// New Clerk auth (new clients)
149+
const clerkAuth = new MastraAuthClerk({
150+
publishableKey: process.env.CLERK_PUBLISHABLE_KEY,
151+
secretKey: process.env.CLERK_SECRET_KEY,
152+
jwksUri: process.env.CLERK_JWKS_URI,
153+
});
154+
155+
// Support both during migration
156+
export const mastra = new Mastra({
157+
server: {
158+
auth: new CompositeAuth([
159+
clerkAuth, // New auth method (preferred)
160+
legacyAuth, // Legacy support
161+
]),
162+
},
163+
});
164+
```
165+
166+
## With Custom Providers
167+
168+
Combine built-in providers with custom implementations:
169+
170+
```typescript
171+
import { CompositeAuth, SimpleAuth } from '@mastra/core/server';
172+
import { MyCustomAuth } from './my-custom-auth';
173+
174+
const apiKeyAuth = new SimpleAuth({
175+
tokens: {
176+
'sk-key-123': { id: 'user-1', name: 'API User' },
177+
},
178+
});
179+
180+
const customAuth = new MyCustomAuth({
181+
apiUrl: process.env.CUSTOM_AUTH_URL,
182+
});
183+
184+
export const mastra = new Mastra({
185+
server: {
186+
auth: new CompositeAuth([apiKeyAuth, customAuth]),
187+
},
188+
});
189+
```
190+
191+
## Error Handling
192+
193+
CompositeAuth silently catches errors from individual providers and moves to the next one. This prevents one failing provider from blocking authentication:
194+
195+
```typescript
196+
// If clerkAuth throws an error, apiKeyAuth still gets tried
197+
new CompositeAuth([clerkAuth, apiKeyAuth]);
198+
```
199+
200+
To debug authentication issues, add logging to your custom providers or check individual provider configurations.
201+
202+
## Limitations
203+
204+
- All providers share the same token from the `Authorization` header
205+
- User types may differ between providers (use discriminated unions if needed)
206+
- No built-in way to identify which provider authenticated a request
207+
208+
### Handling Different User Types
209+
210+
When providers return different user types, use a discriminated union:
211+
212+
```typescript
213+
type ApiKeyUser = {
214+
type: 'api-key';
215+
id: string;
216+
name: string;
217+
};
218+
219+
type ClerkUser = {
220+
type: 'clerk';
221+
sub: string;
222+
email: string;
223+
};
224+
225+
type User = ApiKeyUser | ClerkUser;
226+
227+
// In your application code
228+
function handleUser(user: User) {
229+
if (user.type === 'api-key') {
230+
console.log('API key user:', user.name);
231+
} else {
232+
console.log('Clerk user:', user.email);
233+
}
234+
}
235+
```
236+
237+
## Related
238+
239+
- [Auth Overview](/docs/server/auth) - Authentication concepts
240+
- [Simple Auth](/docs/server/auth/simple-auth) - Token-to-user mapping
241+
- [Custom Auth Provider](/docs/server/auth/custom-auth-provider) - Build your own provider

0 commit comments

Comments
 (0)