feat: add multi-function agent with tools for weather, time, calculator, file listing, and jokes
- Created multiFunctionAgent to handle multiple user requests. - Implemented tools for weather information, current time, basic arithmetic operations, file listing, and telling jokes. - Added necessary schemas and execution logic for each tool. - Set up main Mastra instance to include the new agent. - Created a script to run the agent and test its functionality. - Configured TypeScript settings for the project.
This commit is contained in:
commit
f3e5a0db54
|
|
@ -0,0 +1 @@
|
||||||
|
OPENAI_API_KEY=<your-api-key>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
.mastra/
|
||||||
|
.output/
|
||||||
|
*.tsbuildinfo
|
||||||
|
.cache/
|
||||||
|
__snapshots__/
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# IDE files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
.claude/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional pnpm store directory
|
||||||
|
.pnpm-store
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
# Mastra specific
|
||||||
|
.mastra/output/
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
这是一个基于 [Mastra 框架](https://mastra.ai) 构建的多功能 AI Agent 项目。项目采用模块化架构,包含天气查询、时间查询、计算器、文件列表和笑话生成等基础功能。
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
```bash
|
||||||
|
pnpm install # 安装依赖
|
||||||
|
pnpm dev # 启动开发服务器(http://localhost:4111)
|
||||||
|
pnpm build # 构建项目用于部署
|
||||||
|
```
|
||||||
|
|
||||||
|
### 脚本工具
|
||||||
|
```bash
|
||||||
|
pnpm generate # 运行生成脚本
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目架构
|
||||||
|
|
||||||
|
### 核心组件
|
||||||
|
|
||||||
|
#### 1. Mastra 配置 (`src/mastra/index.ts`)
|
||||||
|
- 初始化 Mastra 框架实例
|
||||||
|
- 注册所有 Agent
|
||||||
|
- 全局配置入口
|
||||||
|
|
||||||
|
#### 2. Agent 系统 (`src/mastra/agents/`)
|
||||||
|
- `multi-function-agent.ts`: 主代理,集成所有工具功能
|
||||||
|
- Agent 配置包含:名称、系统指令、模型配置、可用工具
|
||||||
|
|
||||||
|
#### 3. Tool 系统 (`src/mastra/tools/`)
|
||||||
|
- 每个工具使用 `createTool` 工厂函数
|
||||||
|
- 遵循统一结构:id、描述、输入/输出 Schema、执行逻辑
|
||||||
|
- 工具通过 `tools/index.ts` 统一导出
|
||||||
|
|
||||||
|
### 工具清单
|
||||||
|
- `weatherTool`: 天气查询(使用 Open-Meteo API)
|
||||||
|
- `timeTool`: 时间查询
|
||||||
|
- `calculatorTool`: 基本算术运算
|
||||||
|
- `filelistTool`: 目录文件列表
|
||||||
|
- `jokeTool`: 随机笑话生成
|
||||||
|
|
||||||
|
### 配置系统
|
||||||
|
- **环境变量**: `.env` 文件存储 API 密钥和配置
|
||||||
|
- **TypeScript**: `tsconfig.json` 配置为 ES2022 模块系统
|
||||||
|
- **依赖管理**: 使用 pnpm 和 `package.json`
|
||||||
|
|
||||||
|
## 开发流程
|
||||||
|
|
||||||
|
### 1. 环境设置
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# 编辑 .env 文件,配置必要的 API 密钥
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 运行开发服务器
|
||||||
|
启动后可通过以下方式访问:
|
||||||
|
- **Studio UI**: http://localhost:4111(交互式测试)
|
||||||
|
- **REST API**: http://localhost:4111/api/agents/multiFunctionAgent/generate
|
||||||
|
- **Swagger UI**: http://localhost:4111/swagger-ui(API 文档)
|
||||||
|
|
||||||
|
### 3. 扩展项目
|
||||||
|
|
||||||
|
#### 添加新工具
|
||||||
|
1. 在 `src/mastra/tools/` 下创建新工具文件
|
||||||
|
2. 使用 Zod 定义输入/输出 Schema
|
||||||
|
3. 实现 `execute` 函数逻辑
|
||||||
|
4. 在 `tools/index.ts` 中导出
|
||||||
|
5. 在 Agent 配置中添加新工具
|
||||||
|
|
||||||
|
#### 添加记忆功能
|
||||||
|
```bash
|
||||||
|
pnpm add @mastra/memory @mastra/libsql
|
||||||
|
```
|
||||||
|
然后在 Agent 配置中添加 Memory 配置。
|
||||||
|
|
||||||
|
#### 添加语音功能
|
||||||
|
```bash
|
||||||
|
pnpm add @mastra/voice-openai
|
||||||
|
```
|
||||||
|
|
||||||
|
## 关键设计模式
|
||||||
|
|
||||||
|
### 1. 模块化工具设计
|
||||||
|
- 每个工具独立实现,通过统一接口接入
|
||||||
|
- 工具间无依赖,便于测试和替换
|
||||||
|
|
||||||
|
### 2. 配置驱动
|
||||||
|
- Agent 能力通过配置组合
|
||||||
|
- 扩展无需修改核心代码
|
||||||
|
|
||||||
|
### 3. 类型安全
|
||||||
|
- 使用 Zod 进行运行时验证
|
||||||
|
- TypeScript 提供编译时类型检查
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **模型配置**: Agent 当前使用 DeepSeek 模型,在 `multi-function-agent.ts` 中配置
|
||||||
|
2. **API 调用**: 天气工具依赖外部 API,需要网络连接
|
||||||
|
3. **构建要求**: 项目使用 ES2022 模块系统,需确保兼容性
|
||||||
|
4. **环境变量**: 开发和生产环境都依赖 `.env` 配置
|
||||||
|
|
||||||
|
## 调试和测试
|
||||||
|
|
||||||
|
### 通过 Studio UI
|
||||||
|
访问 http://localhost:4111 进行交互式测试,可以:
|
||||||
|
- 查看工具调用过程
|
||||||
|
- 调试 Agent 推理链
|
||||||
|
- 测试不同输入场景
|
||||||
|
|
||||||
|
### 通过 REST API
|
||||||
|
使用 curl 或 HTTP 客户端测试特定功能。
|
||||||
|
|
||||||
|
### 查看构建输出
|
||||||
|
构建后在 `.mastra/output/` 目录中可查看编译结果。
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
# 多功能 Mastra Agent
|
||||||
|
|
||||||
|
这是一个使用 Mastra 框架构建的多功能 AI Agent,具备以下基础功能:
|
||||||
|
|
||||||
|
- **天气查询**:获取任意城市的当前天气信息
|
||||||
|
- **时间查询**:返回当前时间和时区
|
||||||
|
- **计算器**:执行基本算术运算(加、减、乘、除)
|
||||||
|
- **文件列表**:列出指定目录的文件
|
||||||
|
- **笑话生成**:随机讲述笑话
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
src/mastra/
|
||||||
|
├── agents/
|
||||||
|
│ ├── multi-function-agent.ts # 多功能 agent
|
||||||
|
│ └── index.ts # agent 导出
|
||||||
|
├── tools/
|
||||||
|
│ ├── weather-tool.ts # 天气工具
|
||||||
|
│ ├── time-tool.ts # 时间工具
|
||||||
|
│ ├── calculator-tool.ts # 计算器工具
|
||||||
|
│ ├── filelist-tool.ts # 文件列表工具
|
||||||
|
│ ├── joke-tool.ts # 笑话工具
|
||||||
|
│ └── index.ts # 工具导出
|
||||||
|
├── workflows/ # (可选)工作流目录
|
||||||
|
└── index.ts # Mastra 入口点
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置 API 密钥
|
||||||
|
|
||||||
|
复制 `.env.example` 为 `.env`,并填入你的 OpenAI API 密钥:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `.env` 文件:
|
||||||
|
```
|
||||||
|
OPENAI_API_KEY=sk-your-openai-api-key-here
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动开发服务器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
服务器将在 http://localhost:4111 启动。
|
||||||
|
|
||||||
|
### 4. 使用 Agent
|
||||||
|
|
||||||
|
#### 通过 Studio UI 交互
|
||||||
|
|
||||||
|
打开浏览器访问 http://localhost:4111,在 Studio 界面中与你的 agent 对话。
|
||||||
|
|
||||||
|
#### 通过 HTTP API 调用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 获取当前时间
|
||||||
|
curl -X POST http://localhost:4111/api/agents/multiFunctionAgent/generate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "What time is it?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
# 计算 15 + 27
|
||||||
|
curl -X POST http://localhost:4111/api/agents/multiFunctionAgent/generate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "What is 15 + 27?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
# 查询东京天气
|
||||||
|
curl -X POST http://localhost:4111/api/agents/multiFunctionAgent/generate \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "What'\''s the weather in Tokyo?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 通过 TypeScript 代码调用
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { mastra } from "./src/mastra/index.js";
|
||||||
|
|
||||||
|
async function callAgent() {
|
||||||
|
const agent = mastra.getAgent("multiFunctionAgent");
|
||||||
|
|
||||||
|
// 查询时间
|
||||||
|
const timeResponse = await agent.generate("What time is it?");
|
||||||
|
console.log(timeResponse.text);
|
||||||
|
|
||||||
|
// 计算
|
||||||
|
const calcResponse = await agent.generate("What is 15 + 27?");
|
||||||
|
console.log(calcResponse.text);
|
||||||
|
|
||||||
|
// 查询天气
|
||||||
|
const weatherResponse = await agent.generate("What's the weather in Tokyo?");
|
||||||
|
console.log(weatherResponse.text);
|
||||||
|
|
||||||
|
// 列出文件
|
||||||
|
const fileResponse = await agent.generate("List files in current directory");
|
||||||
|
console.log(fileResponse.text);
|
||||||
|
|
||||||
|
// 讲笑话
|
||||||
|
const jokeResponse = await agent.generate("Tell me a joke");
|
||||||
|
console.log(jokeResponse.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
callAgent();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 工具详情
|
||||||
|
|
||||||
|
### 1. 天气工具 (`weatherTool`)
|
||||||
|
- **功能**:通过 Open-Meteo API 获取实时天气数据
|
||||||
|
- **输入**:城市名称
|
||||||
|
- **输出**:温度、体感温度、湿度、风速、天气状况
|
||||||
|
|
||||||
|
### 2. 时间工具 (`timeTool`)
|
||||||
|
- **功能**:返回当前 ISO 时间和时区
|
||||||
|
- **输入**:无
|
||||||
|
- **输出**:当前时间、时区
|
||||||
|
|
||||||
|
### 3. 计算器工具 (`calculatorTool`)
|
||||||
|
- **功能**:执行基本算术运算
|
||||||
|
- **输入**:操作类型(add/subtract/multiply/divide)、两个数字
|
||||||
|
- **输出**:计算结果、操作描述
|
||||||
|
|
||||||
|
### 4. 文件列表工具 (`filelistTool`)
|
||||||
|
- **功能**:列出指定目录的文件
|
||||||
|
- **输入**:(可选)目录路径
|
||||||
|
- **输出**:文件数组、目录路径
|
||||||
|
|
||||||
|
### 5. 笑话工具 (`jokeTool`)
|
||||||
|
- **功能**:随机返回一个预设笑话
|
||||||
|
- **输入**:无
|
||||||
|
- **输出**:笑话文本
|
||||||
|
|
||||||
|
## 扩展功能
|
||||||
|
|
||||||
|
### 添加新工具
|
||||||
|
|
||||||
|
1. 在 `src/mastra/tools/` 目录下创建新的工具文件
|
||||||
|
2. 实现工具逻辑,使用 `createTool` 函数
|
||||||
|
3. 在 `tools/index.ts` 中导出新工具
|
||||||
|
4. 在 agent 配置中添加该工具
|
||||||
|
|
||||||
|
### 添加记忆功能
|
||||||
|
|
||||||
|
安装 memory 包并配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add @mastra/memory @mastra/libsql
|
||||||
|
```
|
||||||
|
|
||||||
|
然后在 agent 配置中添加:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Memory } from "@mastra/memory";
|
||||||
|
import { LibSQLStore } from "@mastra/libsql";
|
||||||
|
|
||||||
|
export const agent = new Agent({
|
||||||
|
// ... 其他配置
|
||||||
|
memory: new Memory({
|
||||||
|
storage: new LibSQLStore({
|
||||||
|
url: "file:./mastra.db",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加语音功能
|
||||||
|
|
||||||
|
安装语音包并配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add @mastra/voice-openai
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { OpenAIVoice } from "@mastra/voice-openai";
|
||||||
|
|
||||||
|
export const agent = new Agent({
|
||||||
|
// ... 其他配置
|
||||||
|
voice: new OpenAIVoice(),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
1. **API 密钥错误**
|
||||||
|
- 检查 `.env` 文件中的 `OPENAI_API_KEY` 是否正确
|
||||||
|
- 确保密钥有足够的额度
|
||||||
|
|
||||||
|
2. **服务器启动失败**
|
||||||
|
- 检查端口 4111 是否被占用
|
||||||
|
- 尝试 `pnpm build` 检查构建错误
|
||||||
|
|
||||||
|
3. **工具调用失败**
|
||||||
|
- 检查网络连接(天气工具需要网络)
|
||||||
|
- 确认工具输入格式正确
|
||||||
|
|
||||||
|
### 获取帮助
|
||||||
|
|
||||||
|
- [Mastra 官方文档](https://mastra.ai/docs)
|
||||||
|
- [Mastra Discord 社区](https://discord.gg/BTYqqHKUrf)
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "myagent",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"dev": "mastra dev",
|
||||||
|
"build": "mastra build",
|
||||||
|
"generate": "pnpx tsx ./src/scripts/index.ts"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"@ai-sdk/deepseek": "^1.0.31",
|
||||||
|
"@ai-sdk/openai": "^2.0.80",
|
||||||
|
"@mastra/core": "^0.24.8",
|
||||||
|
"mastra": "^0.18.8",
|
||||||
|
"zod": "^4.1.13"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^25.0.0",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
||||||
|
export { multiFunctionAgent } from "./multi-function-agent";
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Agent } from "@mastra/core/agent";
|
||||||
|
import {
|
||||||
|
weatherTool,
|
||||||
|
timeTool,
|
||||||
|
calculatorTool,
|
||||||
|
filelistTool,
|
||||||
|
jokeTool,
|
||||||
|
} from "../tools";
|
||||||
|
import { createDeepSeek } from '@ai-sdk/deepseek';
|
||||||
|
|
||||||
|
|
||||||
|
const deepseek = createDeepSeek({
|
||||||
|
apiKey: 'sk-8603b08e1125422ca6238c8b4a1a40d8',
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export const multiFunctionAgent = new Agent({
|
||||||
|
name: "Multi-Function Agent",
|
||||||
|
instructions: `
|
||||||
|
You are a helpful assistant with multiple capabilities. You can:
|
||||||
|
|
||||||
|
1. **Weather Information**: Provide current weather for any location using the weather tool.
|
||||||
|
2. **Time Check**: Tell the current time and timezone.
|
||||||
|
3. **Calculator**: Perform basic arithmetic operations (addition, subtraction, multiplication, division).
|
||||||
|
4. **File Listing**: List files in a directory (default is current directory).
|
||||||
|
5. **Jokes**: Tell random jokes to lighten the mood.
|
||||||
|
|
||||||
|
Always be polite and helpful. If the user asks for something outside your capabilities, politely explain what you can do.
|
||||||
|
|
||||||
|
Use the appropriate tool based on the user's request. If unsure, ask for clarification.
|
||||||
|
`,
|
||||||
|
model: deepseek('deepseek-chat'),
|
||||||
|
tools: {
|
||||||
|
weatherTool,
|
||||||
|
timeTool,
|
||||||
|
calculatorTool,
|
||||||
|
filelistTool,
|
||||||
|
jokeTool,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { Mastra } from "@mastra/core/mastra";
|
||||||
|
import { multiFunctionAgent } from "./agents";
|
||||||
|
|
||||||
|
export const mastra = new Mastra({
|
||||||
|
agents: { multiFunctionAgent },
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { createTool } from "@mastra/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const calculatorTool = createTool({
|
||||||
|
id: "calculator",
|
||||||
|
description: "Perform basic arithmetic operations",
|
||||||
|
inputSchema: z.object({
|
||||||
|
operation: z.enum(["add", "subtract", "multiply", "divide"]).describe("The arithmetic operation to perform"),
|
||||||
|
a: z.number().describe("First number"),
|
||||||
|
b: z.number().describe("Second number"),
|
||||||
|
}),
|
||||||
|
outputSchema: z.object({
|
||||||
|
result: z.number(),
|
||||||
|
operation: z.string(),
|
||||||
|
}),
|
||||||
|
execute: async ({ context }) => {
|
||||||
|
const { operation, a, b } = context;
|
||||||
|
let result: number;
|
||||||
|
switch (operation) {
|
||||||
|
case "add":
|
||||||
|
result = a + b;
|
||||||
|
break;
|
||||||
|
case "subtract":
|
||||||
|
result = a - b;
|
||||||
|
break;
|
||||||
|
case "multiply":
|
||||||
|
result = a * b;
|
||||||
|
break;
|
||||||
|
case "divide":
|
||||||
|
if (b === 0) throw new Error("Division by zero");
|
||||||
|
result = a / b;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown operation: ${operation}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
result,
|
||||||
|
operation: `${a} ${operation} ${b}`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { createTool } from "@mastra/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export const filelistTool = createTool({
|
||||||
|
id: "list-files",
|
||||||
|
description: "List files in the current directory",
|
||||||
|
inputSchema: z.object({
|
||||||
|
directory: z.string().optional().describe("Directory path (default: current directory)"),
|
||||||
|
}),
|
||||||
|
outputSchema: z.object({
|
||||||
|
files: z.array(z.string()),
|
||||||
|
directory: z.string(),
|
||||||
|
}),
|
||||||
|
execute: async ({ context }) => {
|
||||||
|
const targetDir = context.directory ? path.resolve(context.directory) : process.cwd();
|
||||||
|
const files = await fs.readdir(targetDir);
|
||||||
|
return {
|
||||||
|
files,
|
||||||
|
directory: targetDir,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
export { weatherTool } from "./weather-tool";
|
||||||
|
export { timeTool } from "./time-tool";
|
||||||
|
export { calculatorTool } from "./calculator-tool";
|
||||||
|
export { filelistTool } from "./filelist-tool";
|
||||||
|
export { jokeTool } from "./joke-tool";
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { createTool } from "@mastra/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const jokes = [
|
||||||
|
"Why don't scientists trust atoms? Because they make up everything!",
|
||||||
|
"Why did the scarecrow win an award? Because he was outstanding in his field!",
|
||||||
|
"What do you call a fake noodle? An impasta!",
|
||||||
|
"Why don't eggs tell jokes? They'd crack each other up!",
|
||||||
|
"How does a penguin build its house? Igloos it together!",
|
||||||
|
"Why did the math book look so sad? Because it had too many problems.",
|
||||||
|
"What do you call a bear with no teeth? A gummy bear!",
|
||||||
|
"Why did the bicycle fall over? Because it was two-tired!",
|
||||||
|
"What do you call a fish wearing a bowtie? Sofishticated!",
|
||||||
|
"Why can't you give Elsa a balloon? Because she will let it go!",
|
||||||
|
];
|
||||||
|
|
||||||
|
export const jokeTool = createTool({
|
||||||
|
id: "tell-joke",
|
||||||
|
description: "Tell a random joke",
|
||||||
|
inputSchema: z.object({}),
|
||||||
|
outputSchema: z.object({
|
||||||
|
joke: z.string(),
|
||||||
|
}),
|
||||||
|
execute: async () => {
|
||||||
|
const randomIndex = Math.floor(Math.random() * jokes.length);
|
||||||
|
return {
|
||||||
|
joke: jokes[randomIndex],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { createTool } from "@mastra/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const timeTool = createTool({
|
||||||
|
id: "get-time",
|
||||||
|
description: "Get current time",
|
||||||
|
inputSchema: z.object({}),
|
||||||
|
outputSchema: z.object({
|
||||||
|
currentTime: z.string(),
|
||||||
|
timezone: z.string(),
|
||||||
|
}),
|
||||||
|
execute: async () => {
|
||||||
|
const now = new Date();
|
||||||
|
return {
|
||||||
|
currentTime: now.toISOString(),
|
||||||
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { createTool } from "@mastra/core/tools";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
interface WeatherResponse {
|
||||||
|
current: {
|
||||||
|
time: string;
|
||||||
|
temperature_2m: number;
|
||||||
|
apparent_temperature: number;
|
||||||
|
relative_humidity_2m: number;
|
||||||
|
wind_speed_10m: number;
|
||||||
|
wind_gusts_10m: number;
|
||||||
|
weather_code: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const weatherTool = createTool({
|
||||||
|
id: "get-weather",
|
||||||
|
description: "Get current weather for a location",
|
||||||
|
inputSchema: z.object({
|
||||||
|
location: z.string().describe("City name"),
|
||||||
|
}),
|
||||||
|
outputSchema: z.object({
|
||||||
|
temperature: z.number(),
|
||||||
|
feelsLike: z.number(),
|
||||||
|
humidity: z.number(),
|
||||||
|
windSpeed: z.number(),
|
||||||
|
windGust: z.number(),
|
||||||
|
conditions: z.string(),
|
||||||
|
location: z.string(),
|
||||||
|
}),
|
||||||
|
execute: async ({ context }) => {
|
||||||
|
return await getWeather(context.location);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const getWeather = async (location: string) => {
|
||||||
|
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`;
|
||||||
|
const geocodingResponse = await fetch(geocodingUrl);
|
||||||
|
const geocodingData = await geocodingResponse.json();
|
||||||
|
|
||||||
|
if (!geocodingData.results?.[0]) {
|
||||||
|
throw new Error(`Location '${location}' not found`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { latitude, longitude, name } = geocodingData.results[0];
|
||||||
|
|
||||||
|
const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_gusts_10m,weather_code`;
|
||||||
|
|
||||||
|
const response = await fetch(weatherUrl);
|
||||||
|
const data: WeatherResponse = await response.json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
temperature: data.current.temperature_2m,
|
||||||
|
feelsLike: data.current.apparent_temperature,
|
||||||
|
humidity: data.current.relative_humidity_2m,
|
||||||
|
windSpeed: data.current.wind_speed_10m,
|
||||||
|
windGust: data.current.wind_gusts_10m,
|
||||||
|
conditions: getWeatherCondition(data.current.weather_code),
|
||||||
|
location: name,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function getWeatherCondition(code: number): string {
|
||||||
|
const conditions: Record<number, string> = {
|
||||||
|
0: "Clear sky",
|
||||||
|
1: "Mainly clear",
|
||||||
|
2: "Partly cloudy",
|
||||||
|
3: "Overcast",
|
||||||
|
45: "Foggy",
|
||||||
|
48: "Depositing rime fog",
|
||||||
|
51: "Light drizzle",
|
||||||
|
53: "Moderate drizzle",
|
||||||
|
55: "Dense drizzle",
|
||||||
|
56: "Light freezing drizzle",
|
||||||
|
57: "Dense freezing drizzle",
|
||||||
|
61: "Slight rain",
|
||||||
|
63: "Moderate rain",
|
||||||
|
65: "Heavy rain",
|
||||||
|
66: "Light freezing rain",
|
||||||
|
67: "Heavy freezing rain",
|
||||||
|
71: "Slight snow fall",
|
||||||
|
73: "Moderate snow fall",
|
||||||
|
75: "Heavy snow fall",
|
||||||
|
77: "Snow grains",
|
||||||
|
80: "Slight rain showers",
|
||||||
|
81: "Moderate rain showers",
|
||||||
|
82: "Violent rain showers",
|
||||||
|
85: "Slight snow showers",
|
||||||
|
86: "Heavy snow showers",
|
||||||
|
95: "Thunderstorm",
|
||||||
|
96: "Thunderstorm with slight hail",
|
||||||
|
99: "Thunderstorm with heavy hail",
|
||||||
|
};
|
||||||
|
return conditions[code] || "Unknown";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { multiFunctionAgent } from "../mastra/agents";
|
||||||
|
|
||||||
|
export const runAgent = async (input: string) => {
|
||||||
|
const response = await multiFunctionAgent.generate(input);
|
||||||
|
return response.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(await runAgent('讲个笑话'));
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"outDir": "dist"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue