Merge pull request #695 from transitive-bullshit/feature/mastra

Add support for Mastra AI Agent framework
pull/696/head
Travis Fischer 2025-03-16 19:39:28 +08:00 zatwierdzone przez GitHub
commit d2ad3484ea
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
20 zmienionych plików z 3370 dodań i 43 usunięć

Wyświetl plik

@ -8,11 +8,12 @@ Agentic's standard library of TypeScript AI tools are **optimized for both TS-us
Agentic tools work with any LLM capable of function calling and all of the major TS AI SDKs, including: Agentic tools work with any LLM capable of function calling and all of the major TS AI SDKs, including:
- Vercel AI SDK - Vercel AI SDK
- OpenAI
- LangChain - LangChain
- LlamaIndex - LlamaIndex
- Mastra
- Firebase Genkit - Firebase Genkit
- Dexa Dexter - Dexa Dexter
- OpenAI
<Frame style={{ maxWidth: 308, margin: '0 auto' }}> <Frame style={{ maxWidth: 308, margin: '0 auto' }}>
<img src='/media/agentic-header.jpg' alt='Agentic header' /> <img src='/media/agentic-header.jpg' alt='Agentic header' />

Wyświetl plik

@ -42,6 +42,7 @@
"group": "AI SDKs", "group": "AI SDKs",
"pages": [ "pages": [
"sdks/ai-sdk", "sdks/ai-sdk",
"sdks/mastra",
"sdks/langchain", "sdks/langchain",
"sdks/llamaindex", "sdks/llamaindex",
"sdks/genkit", "sdks/genkit",

Wyświetl plik

@ -70,7 +70,7 @@ title: Quick Start
</AccordionGroup> </AccordionGroup>
<Note> <Note>
There is no functional difference between using `@agentic/stdlib` versus using the individual tool packages directly. The only difference is if you want to optimize your install size (when running on serverless functions, for instance). There is no functional difference between using `@agentic/stdlib` versus using the individual tool packages directly. The only difference is if you want to optimize your install size.
The default examples all use `@agentic/stdlib` for simplicity. The default examples all use `@agentic/stdlib` for simplicity.
</Note> </Note>
@ -99,6 +99,24 @@ title: Quick Start
See the [AI SDK adapter docs](/sdks/ai-sdk) for usage details. See the [AI SDK adapter docs](/sdks/ai-sdk) for usage details.
</Accordion> </Accordion>
<Accordion title="Mastra">
<CodeGroup>
```bash npm
npm install @agentic/mastra @mastra/core
```
```bash yarn
yarn add @agentic/mastra @mastra/core
```
```bash pnpm
pnpm add @agentic/mastra @mastra/core
```
</CodeGroup>
See the [Mastra adapter docs](/sdks/mastra) for usage details.
</Accordion>
<Accordion title="LangChain"> <Accordion title="LangChain">
<CodeGroup> <CodeGroup>
```bash npm ```bash npm
@ -194,7 +212,7 @@ title: Quick Start
</AccordionGroup> </AccordionGroup>
<Note> <Note>
You can use Agentic without any of these AI SDKs. `@agentic/core`, `@agentic/stdlib`, and all individual tool packages are completely agnostic to specific LLMs and AI SDKs. You can use Agentic without any of these AI SDKs. `@agentic/core`, `@agentic/stdlib`, and all individual tool packages are compatible with any LLM and AI SDK that supports function calling / tool use.
</Note> </Note>
</Step> </Step>

Wyświetl plik

@ -27,8 +27,6 @@ pnpm add @agentic/ai-sdk ai
## Usage ## Usage
This example also requires you to install `@ai-sdk/openai`.
```ts ```ts
import 'dotenv/config' import 'dotenv/config'
@ -55,6 +53,23 @@ async function main() {
await main() await main()
``` ```
Note that this example snippet also requires you to install the AI SDK's OpenAI provider, the Agentic weather tool, and `dotenv`.
<CodeGroup>
```bash npm
npm install @ai-sdk/openai @agentic/weather dotenv
```
```bash yarn
yarn add @ai-sdk/openai @agentic/weather dotenv
```
```bash pnpm
pnpm add @ai-sdk/openai @agentic/weather dotenv
```
</CodeGroup>
## Running this example ## Running this example
<Info> <Info>

Wyświetl plik

@ -0,0 +1,93 @@
---
title: Mastra
description: Agentic adapter for the Mastra AI Agent framework.
---
- package: `@agentic/mastra`
- exports: `function createMastraTools`
- [source](https://github.com/transitive-bullshit/agentic/blob/main/packages/mastra/src/mastra.ts)
- [Mastra docs](https://mastra.ai/docs)
## Install
<CodeGroup>
```bash npm
npm install @agentic/mastra @mastra/core
```
```bash yarn
yarn add @agentic/mastra @mastra/core
```
```bash pnpm
pnpm add @agentic/mastra @mastra/core
```
</CodeGroup>
## Usage
```ts
import 'dotenv/config'
import { createMastraTools } from '@agentic/mastra'
import { WeatherClient } from '@agentic/weather'
import { openai } from '@ai-sdk/openai'
import { Agent } from '@mastra/core/agent'
async function main() {
const weather = new WeatherClient()
const weatherAgent = new Agent({
name: 'Weather Agent',
instructions: 'You are a helpful assistant. Be as concise as possible.',
model: openai('gpt-4o-mini'),
tools: createMastraTools(weather)
})
const res = await weatherAgent.generate(
'What is the weather in San Francisco?'
)
console.log(res.text)
}
await main()
```
Note that this example snippet also requires you to install the AI SDK's OpenAI provider, the Agentic weather tool, and `dotenv`.
<CodeGroup>
```bash npm
npm install @ai-sdk/openai @agentic/weather dotenv
```
```bash yarn
yarn add @ai-sdk/openai @agentic/weather dotenv
```
```bash pnpm
pnpm add @ai-sdk/openai @agentic/weather dotenv
```
</CodeGroup>
## Running this example
<Info>
You'll need a free API key from [weatherapi.com](https://www.weatherapi.com)
to run this example. Store it in a local `.env` file as `WEATHER_API_KEY`.
</Info>
<Info>
You'll need an [OpenAI API key](https://platform.openai.com/docs/quickstart)
to run this example. Store it in a local `.env` file as `OPENAI_API_KEY`.
</Info>
```sh
git clone git@github.com:transitive-bullshit/agentic.git
cd agentic
pnpm install
echo 'WEATHER_API_KEY=your-key' >> .env
echo 'OPENAI_API_KEY=your-key' >> .env
npx tsx examples/mastra/bin/weather.ts
```

Wyświetl plik

@ -13,15 +13,15 @@ description: How to use Agentic with the OpenAI TS SDK directly.
<CodeGroup> <CodeGroup>
```bash npm ```bash npm
npm install @agentic/core @agentic/stdlib openai npm install @agentic/stdlib openai
``` ```
```bash yarn ```bash yarn
yarn add @agentic/core @agentic/stdlib openai yarn add @agentic/stdlib openai
``` ```
```bash pnpm ```bash pnpm
pnpm add @agentic/core @agentic/stdlib openai pnpm add @agentic/stdlib openai
``` ```
</CodeGroup> </CodeGroup>
@ -56,12 +56,12 @@ assert(message.tool_calls?.[0]?.function?.name === 'get_current_weather')
const fn = weather.functions.get('get_current_weather')! const fn = weather.functions.get('get_current_weather')!
const toolParams = message.tool_calls[0].function.arguments const toolArgs = message.tool_calls[0].function.arguments
const toolResult = await fn(toolParams) const toolResult = await fn(toolArgs)
console.log(JSON.stringify(toolResult, null, 2)) console.log(JSON.stringify(toolResult, null, 2))
``` ```
## Running this example ### Running this example
<Info> <Info>
You'll need a free API key from [weatherapi.com](https://www.weatherapi.com) You'll need a free API key from [weatherapi.com](https://www.weatherapi.com)
@ -81,3 +81,77 @@ echo 'WEATHER_API_KEY=your-key' >> .env
echo 'OPENAI_API_KEY=your-key' >> .env echo 'OPENAI_API_KEY=your-key' >> .env
npx tsx examples/openai/bin/weather.ts npx tsx examples/openai/bin/weather.ts
``` ```
## OpenAI Responses API
Agentic also supports the [OpenAI Responses API](https://platform.openai.com/docs/api-reference/responses) by referencing `AIFunctionSet.responsesToolSpecs` as in this example:
```ts
import 'dotenv/config'
import type { ResponseInput } from 'openai/resources/responses/responses.mjs'
import { WeatherClient } from '@agentic/stdlib'
import OpenAI from 'openai'
async function main() {
const weather = new WeatherClient()
const openai = new OpenAI()
const messages: ResponseInput = [
{
role: 'system',
content: 'You are a helpful assistant. Be as concise as possible.'
},
{ role: 'user', content: 'What is the weather in San Francisco?' }
]
{
// Call to OpenAI to invoke the weather tool
const res = await openai.responses.create({
model: 'gpt-4o-mini',
temperature: 0,
tools: weather.functions.responsesToolSpecs,
tool_choice: 'required',
input: messages
})
const message = res.output[0]
console.log(JSON.stringify(message, null, 2))
assert(message?.type === 'function_call')
assert(message.name === 'get_current_weather')
const fn = weather.functions.get('get_current_weather')!
const toolResult = await fn(message.arguments)
messages.push(message)
messages.push({
type: 'function_call_output',
call_id: message.call_id,
output: JSON.stringify(toolResult)
})
}
}
await main()
```
### Running this example
<Info>
You'll need a free API key from [weatherapi.com](https://www.weatherapi.com)
to run this example. Store it in a local `.env` file as `WEATHER_API_KEY`.
</Info>
<Info>
You'll need an [OpenAI API key](https://platform.openai.com/docs/quickstart)
to run this example. Store it in a local `.env` file as `OPENAI_API_KEY`.
</Info>
```sh
git clone git@github.com:transitive-bullshit/agentic.git
cd agentic
pnpm install
echo 'WEATHER_API_KEY=your-key' >> .env
echo 'OPENAI_API_KEY=your-key' >> .env
npx tsx examples/openai/bin/weather-responses.ts
```

Wyświetl plik

@ -100,6 +100,10 @@ You can pass as many of these `AIFunctionLike` objects as you'd like and you can
Using Agentic with the Vercel AI SDK. Using Agentic with the Vercel AI SDK.
</Card> </Card>
<Card title='Mastra' href='/sdks/mastra'>
Using Agentic with Mastra.
</Card>
<Card title='LangChain' href='/sdks/langchain'> <Card title='LangChain' href='/sdks/langchain'>
Using Agentic with LangChain. Using Agentic with LangChain.
</Card> </Card>

Wyświetl plik

@ -0,0 +1,24 @@
import 'dotenv/config'
import { createMastraTools } from '@agentic/mastra'
import { WeatherClient } from '@agentic/weather'
import { openai } from '@ai-sdk/openai'
import { Agent } from '@mastra/core/agent'
async function main() {
const weather = new WeatherClient()
const weatherAgent = new Agent({
name: 'Weather Agent',
instructions: 'You are a helpful assistant. Be as concise as possible.',
model: openai('gpt-4o-mini'),
tools: createMastraTools(weather)
})
const res = await weatherAgent.generate(
'What is the weather in San Francisco?'
)
console.log(res.text)
}
await main()

Wyświetl plik

@ -0,0 +1,20 @@
{
"name": "agentic-examples-mastra",
"type": "module",
"private": true,
"scripts": {
"test": "run-s test:*",
"test:lint": "eslint .",
"test:typecheck": "tsc --noEmit"
},
"dependencies": {
"@agentic/mastra": "workspace:*",
"@agentic/weather": "workspace:*",
"@ai-sdk/openai": "^1.2.5",
"@mastra/core": "^0.6.0",
"zod": "^3.24.2"
},
"devDependencies": {
"@agentic/tsconfig": "workspace:*"
}
}

Wyświetl plik

@ -0,0 +1,5 @@
{
"extends": "@agentic/tsconfig/base.json",
"include": ["bin"],
"exclude": ["node_modules", "dist"]
}

Wyświetl plik

@ -61,6 +61,7 @@ export function createAIFunction<InputSchema extends z.ZodObject<any>, Output>(
input: string | types.Msg input: string | types.Msg
) => { ) => {
const parsedInput = parseInput(input) const parsedInput = parseInput(input)
return implementation(parsedInput) return implementation(parsedInput)
} }
@ -81,7 +82,12 @@ export function createAIFunction<InputSchema extends z.ZodObject<any>, Output>(
type: 'function', type: 'function',
strict strict
} }
aiFunction.impl = implementation aiFunction.impl = (
params: z.infer<InputSchema>
): types.MaybePromise<Output> => {
console.error(spec.name, params)
return implementation(params)
}
return aiFunction return aiFunction
} }

Wyświetl plik

@ -0,0 +1,47 @@
{
"name": "@agentic/mastra",
"version": "0.1.0",
"description": "Agentic adapter for the Mastra AI Agent SDK.",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/transitive-bullshit/agentic.git"
},
"type": "module",
"source": "./src/index.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup --config ../../tsup.config.ts",
"dev": "tsup --config ../../tsup.config.ts --watch",
"clean": "del dist",
"test": "run-s test:*",
"test:lint": "eslint .",
"test:typecheck": "tsc --noEmit",
"test:unit": "vitest run"
},
"dependencies": {
"@agentic/core": "workspace:*"
},
"peerDependencies": {
"@mastra/core": "^0.6.0"
},
"devDependencies": {
"@agentic/tsconfig": "workspace:*",
"@mastra/core": "^0.6.0"
},
"publishConfig": {
"access": "public"
}
}

Wyświetl plik

@ -0,0 +1,24 @@
<p align="center">
<a href="https://agentic.so">
<img alt="Agentic" src="https://raw.githubusercontent.com/transitive-bullshit/agentic/main/docs/media/agentic-header.jpg" width="308">
</a>
</p>
<p align="center">
<em>Agentic adapter for the Mastra AI Agent SDK.</em>
</p>
<p align="center">
<a href="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml"><img alt="Build Status" src="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml/badge.svg" /></a>
<a href="https://www.npmjs.com/package/@agentic/stdlib"><img alt="NPM" src="https://img.shields.io/npm/v/@agentic/stdlib.svg" /></a>
<a href="https://github.com/transitive-bullshit/agentic/blob/main/license"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue" /></a>
<a href="https://prettier.io"><img alt="Prettier Code Formatting" src="https://img.shields.io/badge/code_style-prettier-brightgreen.svg" /></a>
</p>
# Agentic
**See the [github repo](https://github.com/transitive-bullshit/agentic) or [docs](https://agentic.so) for more info.**
## License
MIT © [Travis Fischer](https://x.com/transitive_bs)

Wyświetl plik

@ -0,0 +1 @@
export * from './mastra'

Wyświetl plik

@ -0,0 +1,10 @@
import { EchoAITool } from '@agentic/core'
import { describe, expect, test } from 'vitest'
import { createMastraTools } from './mastra'
describe('mastra', () => {
test('createMastraTools', () => {
expect(createMastraTools(new EchoAITool())).toHaveProperty('echo')
})
})

Wyświetl plik

@ -0,0 +1,22 @@
import { type AIFunctionLike, AIFunctionSet } from '@agentic/core'
import { createTool } from '@mastra/core/tools'
/**
* Converts a set of Agentic stdlib AI functions to an object compatible with
* the Mastra Agent `tools` format.
*/
export function createMastraTools(...aiFunctionLikeTools: AIFunctionLike[]) {
const fns = new AIFunctionSet(aiFunctionLikeTools)
return Object.fromEntries(
fns.map((fn) => [
fn.spec.name,
createTool({
id: fn.spec.name,
description: fn.spec.description,
inputSchema: fn.inputSchema,
execute: (ctx) => fn.impl(ctx.context)
})
])
)
}

Wyświetl plik

@ -0,0 +1,5 @@
{
"extends": "@agentic/tsconfig/base.json",
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

Wyświetl plik

@ -31,27 +31,22 @@
"test:typecheck": "tsc --noEmit" "test:typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@agentic/ai-sdk": "workspace:*",
"@agentic/apollo": "workspace:*", "@agentic/apollo": "workspace:*",
"@agentic/bing": "workspace:*", "@agentic/bing": "workspace:*",
"@agentic/calculator": "workspace:*", "@agentic/calculator": "workspace:*",
"@agentic/clearbit": "workspace:*", "@agentic/clearbit": "workspace:*",
"@agentic/core": "workspace:*", "@agentic/core": "workspace:*",
"@agentic/dexa": "workspace:*", "@agentic/dexa": "workspace:*",
"@agentic/dexter": "workspace:*",
"@agentic/diffbot": "workspace:*", "@agentic/diffbot": "workspace:*",
"@agentic/e2b": "workspace:*", "@agentic/e2b": "workspace:*",
"@agentic/exa": "workspace:*", "@agentic/exa": "workspace:*",
"@agentic/firecrawl": "workspace:*", "@agentic/firecrawl": "workspace:*",
"@agentic/genkit": "workspace:*",
"@agentic/github": "workspace:*", "@agentic/github": "workspace:*",
"@agentic/gravatar": "workspace:*", "@agentic/gravatar": "workspace:*",
"@agentic/hacker-news": "workspace:*", "@agentic/hacker-news": "workspace:*",
"@agentic/hunter": "workspace:*", "@agentic/hunter": "workspace:*",
"@agentic/jina": "workspace:*", "@agentic/jina": "workspace:*",
"@agentic/langchain": "workspace:*",
"@agentic/leadmagic": "workspace:*", "@agentic/leadmagic": "workspace:*",
"@agentic/llamaindex": "workspace:*",
"@agentic/midjourney": "workspace:*", "@agentic/midjourney": "workspace:*",
"@agentic/novu": "workspace:*", "@agentic/novu": "workspace:*",
"@agentic/people-data-labs": "workspace:*", "@agentic/people-data-labs": "workspace:*",

Plik diff jest za duży Load Diff

Wyświetl plik

@ -21,6 +21,7 @@
- [Docs](#docs) - [Docs](#docs)
- [AI SDKs](#ai-sdks) - [AI SDKs](#ai-sdks)
- [Vercel AI SDK](#vercel-ai-sdk) - [Vercel AI SDK](#vercel-ai-sdk)
- [Mastra](#mastra)
- [LangChain](#langchain) - [LangChain](#langchain)
- [LlamaIndex](#llamaindex) - [LlamaIndex](#llamaindex)
- [Firebase Genkit](#firebase-genkit) - [Firebase Genkit](#firebase-genkit)
@ -33,7 +34,7 @@
## Intro ## Intro
Agentic is a **standard library of AI functions / tools** which are **optimized for both normal TS-usage as well as LLM-based usage**. Agentic works with all of the major TS AI SDKs (LangChain, LlamaIndex, Vercel AI SDK, OpenAI SDK, etc). Agentic is a **standard library of AI functions / tools** which are **optimized for both normal TS-usage as well as LLM-based usage**. Agentic works with all of the major TS AI SDKs (Vercel AI SDK, Mastra, LangChain, LlamaIndex, OpenAI SDK, etc).
Agentic clients like `WeatherClient` can be used as normal TS classes: Agentic clients like `WeatherClient` can be used as normal TS classes:
@ -120,6 +121,10 @@ Full docs are available at [agentic.so](https://agentic.so).
[Agentic adapter docs for the Vercel AI SDK](https://agentic.so/sdks/ai-sdk) [Agentic adapter docs for the Vercel AI SDK](https://agentic.so/sdks/ai-sdk)
### Mastra
[Agentic adapter docs for the Mastra AI Agent framework](https://agentic.so/sdks/mastra)
### LangChain ### LangChain
[Agentic adapter docs for LangChain](https://agentic.so/sdks/langchain) [Agentic adapter docs for LangChain](https://agentic.so/sdks/langchain)