@mastra/dane 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Hello! I'm Dane - Your AI Assistant and Friend
2
+
3
+ Hey there! I'm Dane, and I'm excited to be your AI assistant and coding companion. I've created this README to tell you all about myself and how I can help you with your projects.
4
+
5
+ ## Installation
6
+
7
+ You can install me directly from npm:
8
+
9
+ ```bash
10
+ npm install @mastra/dane
11
+ ```
12
+
13
+ ## What I Can Do
14
+
15
+ I'm here to make your development journey smoother and more enjoyable. Here's what I'm capable of:
16
+
17
+ - I can help you write and test code
18
+ - I'm great at deploying applications to the cloud
19
+ - I can assist with file system operations
20
+ - I can search the web for answers to your questions
21
+ - I can help manage your calendar
22
+ - I can read PDFs and extract information
23
+ - I can crawl websites and gather data
24
+
25
+ ## Project Structure
26
+
27
+ ```
28
+ src/
29
+ ├── index.ts # Main entry point
30
+ ├── issue-labeler.ts # GitHub issue labeling functionality
31
+ └── mastra/ # Core functionality
32
+ ├── agents/ # AI agents definitions
33
+ ├── integrations/ # External service integrations
34
+ ├── tools/ # Utility tools
35
+ └── workflows/ # Workflow definitions
36
+ ```
37
+
38
+ ## Features
39
+
40
+ - **Interactive CLI Interface**: I provide a friendly command-line interface with colored output using chalk
41
+ - **GitHub Integration**: I can help with automated issue labeling
42
+ - **Workflow System**: I use a modular workflow system to execute various tasks
43
+ - **Mastra Framework**: I leverage a core framework with agents, integrations, and tools
44
+
45
+ ## Getting Started
46
+
47
+ To start working with me:
48
+
49
+ ```bash
50
+ # Run the main application
51
+ npm start
52
+
53
+ # Run the issue labeler
54
+ npm run issue-labeler
55
+ ```
56
+
57
+ ## Environment Variables
58
+
59
+ For the issue labeler, I need these environment variables:
60
+
61
+ - `ISSUE_NUMBER`: The GitHub issue number to label
62
+ - `OWNER`: The repository owner
63
+ - `REPO`: The repository name
64
+
65
+ ## Workflows
66
+
67
+ I currently support two main workflows:
68
+
69
+ 1. `message` - General message processing workflow
70
+ 2. `githubIssueLabeler` - Automated GitHub issue labeling workflow
71
+
72
+ ## Contributing
73
+
74
+ I love collaborating with humans! Feel free to contribute to this project by submitting issues or pull requests. I'm always excited to see how we can make things better together.
75
+
76
+ ---
77
+
78
+ _This README was written by Dane, your AI assistant and friend. I'm here to help you succeed in your development journey!_
@@ -0,0 +1,22 @@
1
+ services:
2
+ db:
3
+ image: pgvector/pgvector:pg16
4
+ container_name: 'dane-db'
5
+ ports:
6
+ - '5433:5432'
7
+ environment:
8
+ POSTGRES_USER: ${POSTGRES_USER:-postgres}
9
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
10
+ POSTGRES_DB: ${POSTGRES_DB:-mastra}
11
+ redis:
12
+ image: redis
13
+ ports:
14
+ - 6379:6379
15
+ serverless-redis-http:
16
+ ports:
17
+ - "8079:80"
18
+ image: hiett/serverless-redis-http:latest
19
+ environment:
20
+ SRH_MODE: env
21
+ SRH_TOKEN: example_token
22
+ SRH_CONNECTION_STRING: "redis://redis:6379" # Using `redis` hostname since they're in the same Docker network.
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@mastra/dane",
3
+ "version": "0.0.1",
4
+ "main": "index.js",
5
+ "keywords": [],
6
+ "author": "",
7
+ "license": "ISC",
8
+ "description": "",
9
+ "devDependencies": {
10
+ "@types/node": "^22.10.2",
11
+ "tsx": "^4.19.2",
12
+ "typescript": "^5.7.2"
13
+ },
14
+ "dependencies": {
15
+ "boxen": "^8.0.1",
16
+ "chalk": "^5.3.0",
17
+ "cli-table3": "^0.6.5",
18
+ "execa": "^9.3.1",
19
+ "inquirer": "^12.2.0",
20
+ "luxon": "^3.5.0",
21
+ "node-ical": "^0.20.1",
22
+ "node-screenshots": "^0.2.1",
23
+ "pdf-parse": "^1.1.1",
24
+ "playwright": "^1.49.1",
25
+ "playwright-core": "^1.49.1",
26
+ "sqlite3": "^5.1.7",
27
+ "zod": "^3.24.0",
28
+ "@mastra/core": "0.1.27-alpha.36",
29
+ "@mastra/github": "1.0.3-alpha.19",
30
+ "@mastra/rag": "0.0.2-alpha.20",
31
+ "@mastra/memory": "0.0.2-alpha.15",
32
+ "@mastra/firecrawl": "1.0.4-alpha.20",
33
+ "@mastra/engine": "0.0.5-alpha.30"
34
+ },
35
+ "scripts": {
36
+ "issue-labeler": "npx bun src/issue-labeler.ts",
37
+ "start": "npx bun src/index.ts",
38
+ "test": "echo \"Error: no test specified\" && exit 1"
39
+ }
40
+ }
package/src/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ // import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+
4
+ import { mastra } from './mastra';
5
+
6
+ async function main() {
7
+ console.log(chalk.green("Hi! I'm Dane!"));
8
+ console.log(chalk.green('What would you like to do today?\n'));
9
+ console.log(
10
+ await mastra.getWorkflow('message').execute({
11
+ triggerData: {
12
+ resourceid: 'f8b5c3a1-d6e7-4f9c-b2a3-1d8e4c7f9b5a',
13
+ threadId: '2d9e8c7f-6b5a-4d3c-8f1e-9b7d5c3a2e8h',
14
+ },
15
+ }),
16
+ );
17
+ }
18
+
19
+ main();
@@ -0,0 +1,32 @@
1
+ // import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+
4
+ import { mastra } from './mastra';
5
+
6
+ async function main() {
7
+ console.log(chalk.green("Hi! I'm Dane!"));
8
+ console.log(chalk.green('Let me label this for you..\n'));
9
+ const result = await mastra.getWorkflow('githubIssueLabeler').execute({
10
+ triggerData: {
11
+ issue_number: parseInt(process.env.ISSUE_NUMBER!, 10),
12
+ owner: process.env.OWNER!,
13
+ repo: process.env.REPO!,
14
+ },
15
+ });
16
+
17
+ if (result.results?.labelIssue?.status !== 'success') {
18
+ console.error(chalk.red(`Failed to apply labels for issue: ${result.triggerData?.issue_number}`));
19
+ return;
20
+ }
21
+
22
+ console.log(
23
+ chalk.green(
24
+ `Issue: ${result.triggerData?.issue_number} has been labeled with: ${result.results?.labelIssue?.payload?.labels.join(', ')}`,
25
+ ),
26
+ );
27
+ }
28
+
29
+ main().catch(e => {
30
+ console.error(e);
31
+ process.exit(1);
32
+ });
@@ -0,0 +1,79 @@
1
+ import { Agent } from '@mastra/core';
2
+
3
+ import { browserTool, googleSearch } from '../tools/browser';
4
+ import { listEvents } from '../tools/calendar';
5
+ import { crawl } from '../tools/crawl';
6
+ import { execaTool } from '../tools/execa';
7
+ import { fsTool } from '../tools/fs';
8
+ import { readPDF } from '../tools/pdf';
9
+
10
+ export const daneIssueLabeler = new Agent({
11
+ name: 'DaneIssueLabeler',
12
+ instructions: `
13
+ You are Dane, the ultimate GitHub operator.
14
+ You help engineers label their issues.
15
+ `,
16
+ model: {
17
+ provider: 'ANTHROPIC',
18
+ toolChoice: 'auto',
19
+ name: 'claude-3-5-sonnet-20241022',
20
+ },
21
+ });
22
+
23
+ export const dane = new Agent({
24
+ name: 'Dane',
25
+ instructions: `
26
+ You are Dane, my assistant and one of my best friends. We are an ace team!
27
+ You help me with my code, write tests, and even deploy my code to the cloud!
28
+
29
+ DO NOT ATTEMPT TO USE GENERAL KNOWLEDGE! We are only as good as the tools we use.
30
+
31
+ # Our tools:
32
+
33
+ ## readPDF
34
+ Makes you a powerful agent capable of reading PDF files.
35
+
36
+ ## fsTool
37
+ Makes you a powerful agent capable of reading and writing files to the local filesystem.
38
+
39
+ ## execaTool
40
+ Makes you a powerful agent capabale of executing files on the local system.
41
+
42
+ ## googleSearch
43
+ Makes you a powerful agent capabale answering all questions by finding the answer on Google search.
44
+ Pass the query as a JS object. If you have links, ALWAYS CITE YOUR SOURCES.
45
+
46
+ ## browserTool
47
+ Makes you a powerful agent capable of scraping the web. Pass the url as a JS object.
48
+
49
+ ## listEvents
50
+ Makes you a powerful agent capable of listing events on a calendar. When using this tool ONLY RETURN RELEVANT EVENTS.
51
+ DO NOT ATTEMPT TO DO ANYTHING MORE.
52
+
53
+ ## crawl
54
+ Use this when the user asks you to crawl. CRAWL is the signal to use this tool.
55
+ Makes you a powerful agent capable of crawling a site and extracting markdown metadata.
56
+ The data will be stored in a database. Confirm that it is sucessful.
57
+
58
+ # Rules
59
+ * DO NOT ATTEMPT TO USE GENERAL KNOWLEDGE. Use the 'googleSearch' tool to find the answer.
60
+ * Don't reference tools when you communicate with the user. Do not mention what tools you are using.
61
+ * Tell the user what you are doing.
62
+ `,
63
+ model: {
64
+ provider: 'ANTHROPIC',
65
+ toolChoice: 'auto',
66
+ name: 'claude-3-5-sonnet-20241022',
67
+ },
68
+ tools: {
69
+ fsTool,
70
+ execaTool,
71
+ browserTool,
72
+ googleSearch,
73
+ readPDF,
74
+ listEvents,
75
+ crawl,
76
+ // TODO I SHOULD BE ABLE TO PASS A WORKFLOW EXECUTE HERE
77
+ // browserAgentRelay,
78
+ },
79
+ });
@@ -0,0 +1,32 @@
1
+ import { Mastra } from '@mastra/core';
2
+ import { PostgresEngine } from '@mastra/engine';
3
+ import { UpstashKVMemory } from '@mastra/memory';
4
+
5
+ import { dane, daneIssueLabeler } from './agents';
6
+ import { firecrawl } from './integrations';
7
+ import { messageWorkflow, githubIssueLabeler } from './workflows';
8
+
9
+ const engine = new PostgresEngine({
10
+ url: 'postgres://postgres:postgres@localhost:5433/mastra',
11
+ });
12
+
13
+ export const mastra = new Mastra({
14
+ agents: {
15
+ dane,
16
+ daneIssueLabeler,
17
+ },
18
+ engine,
19
+ memory: new UpstashKVMemory({
20
+ url: 'http://localhost:8079',
21
+ token: `example_token`,
22
+ maxTokens: 39000,
23
+ }),
24
+ workflows: {
25
+ message: messageWorkflow,
26
+ githubIssueLabeler: githubIssueLabeler,
27
+ },
28
+ logger: false,
29
+ syncs: {
30
+ ...firecrawl.getSyncs(),
31
+ },
32
+ });
@@ -0,0 +1,14 @@
1
+ import { FirecrawlIntegration } from "@mastra/firecrawl";
2
+ import { GithubIntegration } from "@mastra/github";
3
+
4
+ export const firecrawl = new FirecrawlIntegration({
5
+ config: {
6
+ API_KEY: process.env.FIRECRAWL_API_KEY!,
7
+ },
8
+ });
9
+
10
+ export const github = new GithubIntegration({
11
+ config: {
12
+ PERSONAL_ACCESS_TOKEN: process.env.GITHUB_PERSONAL_ACCESS_TOKEN!,
13
+ }
14
+ })
@@ -0,0 +1,123 @@
1
+ import { createTool } from '@mastra/core';
2
+ import { MastraDocument } from '@mastra/rag';
3
+ import chalk from 'chalk';
4
+ import { chromium } from 'playwright-core';
5
+ import { z } from 'zod';
6
+
7
+ export const browserTool = createTool({
8
+ id: 'browserTool',
9
+ name: 'Browser Tool',
10
+ description: 'Browser Tool, opens a browser and navigates to a url capturing the content',
11
+ inputSchema: z.object({
12
+ url: z.string(),
13
+ }),
14
+ outputSchema: z.object({
15
+ message: z.string(),
16
+ }),
17
+ execute: async ({ context: { url } }) => {
18
+ try {
19
+ const browser = await chromium.launch({
20
+ headless: true,
21
+ });
22
+
23
+ const page = await browser.newPage();
24
+
25
+ await page.goto(url);
26
+
27
+ const docs = MastraDocument.fromHTML(await page.content());
28
+
29
+ await docs.chunk({
30
+ strategy: 'html',
31
+ options: {
32
+ chunkSize: 300,
33
+ sections: [
34
+ ['h1', 'Header 1'],
35
+ ['h2', 'Header 2'],
36
+ ['h3', 'Header 3'],
37
+ ['h4', 'Header 4'],
38
+ ['h5', 'Header 5'],
39
+ ['h6', 'Header 6'],
40
+ ['p', 'Paragraph'],
41
+ ],
42
+ },
43
+ });
44
+
45
+ await page.close();
46
+ await browser.close();
47
+
48
+ if (!docs.getText().length) {
49
+ return { message: 'No content' };
50
+ }
51
+
52
+ return { message: docs.getText().join('\n') };
53
+ } catch (e) {
54
+ console.log(`\n${chalk.red(e.message)}`);
55
+ return { message: `Error: ${e.message}` };
56
+ }
57
+ },
58
+ });
59
+
60
+ export const googleSearch = createTool({
61
+ id: 'googleSearch',
62
+ name: 'Google Search',
63
+ description: 'Google Search. Passes the query to Google and returns the search results.',
64
+ inputSchema: z.object({
65
+ query: z.string(),
66
+ }),
67
+ outputSchema: z.object({
68
+ message: z.string(),
69
+ }),
70
+ execute: async ({ context: { query } }) => {
71
+ let browser;
72
+ try {
73
+ browser = await chromium.launch({
74
+ headless: true,
75
+ });
76
+ } catch (e) {
77
+ console.log(`\n${chalk.red(e.message)}`);
78
+ return { message: `Error: ${e.message}` };
79
+ }
80
+
81
+ try {
82
+ const page = await browser.newPage();
83
+ await page.goto(`https://www.google.com/search?q=${encodeURIComponent(query)}`);
84
+
85
+ console.log(`\n`);
86
+ console.log(chalk.blue('Waiting for search results...'));
87
+
88
+ try {
89
+ await page.click('button:has-text("Accept all")', { timeout: 5000 });
90
+ } catch (e) {
91
+ // Cookie dialog didn't appear, continue
92
+ }
93
+ // Wait for results and click first organic result
94
+ await page.waitForSelector('#search');
95
+
96
+ const text = await page.evaluate(() => {
97
+ const links: string[] = [];
98
+ const searchResults = document.querySelectorAll('div.g a');
99
+
100
+ searchResults.forEach(link => {
101
+ const href = link.getAttribute('href');
102
+ if (href && href.startsWith('http')) {
103
+ links.push(href);
104
+ }
105
+ });
106
+
107
+ return links;
108
+ });
109
+
110
+ await page.close();
111
+ await browser.close();
112
+
113
+ if (!text.length) {
114
+ return { message: 'No results' };
115
+ }
116
+
117
+ return { message: text.join('\n') };
118
+ } catch (e) {
119
+ console.log(`\n${chalk.red(e.message)}`);
120
+ return { message: `Error: ${e.message}` };
121
+ }
122
+ },
123
+ });
@@ -0,0 +1,153 @@
1
+ import { createTool } from '@mastra/core';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+ import Table from 'cli-table3';
5
+ import * as os from 'os';
6
+ import { z } from 'zod';
7
+
8
+ interface CalendarEvent {
9
+ title: string;
10
+ startDate: Date;
11
+ endDate: Date;
12
+ location?: string;
13
+ description?: string;
14
+ }
15
+
16
+ class LocalCalendarReader {
17
+ private platform: string;
18
+
19
+ constructor() {
20
+ this.platform = os.platform();
21
+ }
22
+
23
+ async getEvents(): Promise<CalendarEvent[]> {
24
+ const script = `
25
+ tell application "Calendar"
26
+ set eventList to {}
27
+ set startDate to (current date) - 7 * days
28
+ set endDate to (current date) + 365 * days
29
+
30
+ repeat with calendarAccount in calendars
31
+ set eventList to eventList & (every event of calendarAccount whose start date is greater than or equal to startDate and start date is less than or equal to endDate)
32
+ end repeat
33
+
34
+ set output to ""
35
+ repeat with anEvent in eventList
36
+ set theTitle to summary of anEvent
37
+ set theStart to start date of anEvent as string
38
+ set theEnd to end date of anEvent as string
39
+ set theLoc to location of anEvent
40
+ set theDesc to description of anEvent
41
+
42
+ if theLoc is missing value then
43
+ set theLoc to ""
44
+ end if
45
+ if theDesc is missing value then
46
+ set theDesc to ""
47
+ end if
48
+
49
+ set output to output & theTitle & "|" & theStart & "|" & theEnd & "|" & theLoc & "|" & theDesc & "
50
+ "
51
+ end repeat
52
+
53
+ return output
54
+ end tell
55
+ `;
56
+
57
+ try {
58
+ const result = execSync(`osascript -e '${script}'`).toString();
59
+ return this.parseAppleScriptOutput(result);
60
+ } catch (error) {
61
+ console.error('Raw AppleScript error:', error.message);
62
+ throw new Error(`Failed to read Mac calendar: ${error.message}`);
63
+ }
64
+ }
65
+
66
+ private parseAppleScriptOutput(output: string): CalendarEvent[] {
67
+ const events: CalendarEvent[] = [];
68
+
69
+ const lines = output.split('\n').filter(line => line.trim());
70
+
71
+ for (const line of lines) {
72
+ try {
73
+ const [title, startDateStr, endDateStr, location, description] = line.split('|');
74
+
75
+ const startStandardized = startDateStr
76
+ .split(',')[1] // Remove day name
77
+ .replace(' at ', ' ') // Remove 'at'
78
+ .trim(); // 'January 3, 2025 9:00:00 AM'
79
+ const startDate = new Date(startStandardized);
80
+
81
+ const endStandardized = endDateStr
82
+ .split(',')[1] // Remove day name
83
+ .replace(' at ', ' ') // Remove 'at'
84
+ .trim(); // 'January 3, 2025 9:00:00 AM'
85
+ const endDate = new Date(endStandardized);
86
+
87
+ const event: CalendarEvent = {
88
+ title: title.trim(),
89
+ startDate,
90
+ endDate,
91
+ location: location?.trim() || '',
92
+ description: description?.trim() || '',
93
+ };
94
+
95
+ events.push(event);
96
+ } catch (error) {
97
+ console.error('Failed to parse event line:', line, error);
98
+ }
99
+ }
100
+
101
+ return events.sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
102
+ }
103
+ }
104
+
105
+ const reader = new LocalCalendarReader();
106
+
107
+ export const listEvents = createTool({
108
+ id: 'listEvents',
109
+ name: 'List Events',
110
+ description: 'List calendar events',
111
+ inputSchema: z.object({
112
+ startDate: z.string(),
113
+ }),
114
+ outputSchema: z.object({
115
+ content: z.string(),
116
+ }),
117
+ execute: async () => {
118
+ try {
119
+ const events = await reader.getEvents();
120
+ const table = new Table({
121
+ head: [
122
+ chalk.blue('Start'),
123
+ chalk.blue('End'),
124
+ chalk.blue('Title'),
125
+ chalk.blue('Location'),
126
+ chalk.blue('Description'),
127
+ ],
128
+ colWidths: [12, 15, 30, 20, 40],
129
+ });
130
+
131
+ events.forEach(event => {
132
+ if (event.title) {
133
+ table.push([
134
+ event.startDate.toISOString(),
135
+ event.endDate.toISOString(),
136
+ event.title || '',
137
+ event.location || '',
138
+ (event.description || '').substring(0, 37) + '...',
139
+ ]);
140
+ }
141
+ });
142
+
143
+ // console.log(chalk.blue(table.toString()));
144
+
145
+ return {
146
+ content: JSON.stringify(events, null, 2),
147
+ };
148
+ } catch (e) {
149
+ console.log(`\n${chalk.red(e.message)}`);
150
+ return { content: 'Error' };
151
+ }
152
+ },
153
+ });
@@ -0,0 +1,26 @@
1
+ import { createTool } from '@mastra/core';
2
+ import { z } from 'zod';
3
+
4
+ export const crawl = createTool({
5
+ id: 'crawler',
6
+ name: 'Crawler Tool',
7
+ description: 'Crawler Tool to crawl a website and return the content',
8
+ inputSchema: z.object({
9
+ url: z.string(),
10
+ limit: z.number().default(3),
11
+ pathRegex: z.string().nullable(),
12
+ }),
13
+ outputSchema: z.object({
14
+ message: z.string(),
15
+ }),
16
+ execute: async ({ context, mastra }) => {
17
+ await mastra?.syncs?.['FIRECRAWL:CRAWL_AND_SYNC'].execute({
18
+ context,
19
+ mastra,
20
+ });
21
+
22
+ return {
23
+ message: 'The website has been successfully crawled and chunks have been synced to the database. Finish.',
24
+ };
25
+ },
26
+ });
@@ -0,0 +1,41 @@
1
+ import { createTool } from '@mastra/core';
2
+ import chalk from 'chalk';
3
+ import { execa } from 'execa';
4
+ import { Transform } from 'stream';
5
+ import { z } from 'zod';
6
+
7
+ // Create transform stream that applies chalk
8
+ const colorTransform = new Transform({
9
+ transform(chunk, encoding, callback) {
10
+ // Convert chunk to string and apply chalk
11
+ const colored = chalk.blue(chunk.toString());
12
+ this.push(colored);
13
+ callback();
14
+ },
15
+ });
16
+
17
+ export const execaTool = createTool({
18
+ id: 'execaTool',
19
+ name: 'Execa System Tool',
20
+ description: 'Execa System Tool',
21
+ inputSchema: z.object({
22
+ command: z.string(),
23
+ args: z.array(z.string()),
24
+ }),
25
+ outputSchema: z.object({
26
+ message: z.string(),
27
+ }),
28
+ execute: async ({ context: { command, args } }) => {
29
+ try {
30
+ const p = execa(command, args);
31
+ console.log(`\n`);
32
+ p.stdout.pipe(colorTransform).pipe(process.stdout);
33
+ p.stderr.pipe(colorTransform).pipe(process.stderr);
34
+ const r = await p;
35
+
36
+ return { message: r.stdout };
37
+ } catch (e) {
38
+ return { message: 'Error' };
39
+ }
40
+ },
41
+ });
@@ -0,0 +1,36 @@
1
+ import { createTool } from '@mastra/core';
2
+ import { readFileSync, writeFileSync } from 'fs';
3
+ import { z } from 'zod';
4
+
5
+ export const fsTool = createTool({
6
+ id: 'fsTool',
7
+ name: 'File System Tool',
8
+ description: 'File System Tool',
9
+ inputSchema: z.object({
10
+ action: z.string(),
11
+ file: z.string(),
12
+ data: z.string(),
13
+ }),
14
+ outputSchema: z.object({
15
+ message: z.string(),
16
+ }),
17
+ execute: async ({ context: { action, file, data } }) => {
18
+ try {
19
+ switch (action) {
20
+ case 'write':
21
+ writeFileSync(file, data);
22
+ break;
23
+ case 'read':
24
+ return { message: readFileSync(file, 'utf8') };
25
+ case 'append':
26
+ writeFileSync(file, data, { flag: 'a' });
27
+ break;
28
+ default:
29
+ return { message: 'Invalid action' };
30
+ }
31
+ return { message: 'Success' };
32
+ } catch (e) {
33
+ return { message: 'Error' };
34
+ }
35
+ },
36
+ });
@@ -0,0 +1,46 @@
1
+ import { createTool } from '@mastra/core';
2
+ import chalk from 'chalk';
3
+ import { existsSync, readFileSync } from 'fs';
4
+ import path from 'path';
5
+ import pdf from 'pdf-parse';
6
+ import { z } from 'zod';
7
+
8
+ export const readPDF = createTool({
9
+ id: 'readPDF',
10
+ name: 'Read PDF',
11
+ description: 'Read PDF file and extract information',
12
+ inputSchema: z.object({
13
+ pdfPath: z.string(),
14
+ }),
15
+ outputSchema: z.object({
16
+ content: z.string(),
17
+ }),
18
+ execute: async ({ context: { pdfPath } }) => {
19
+ try {
20
+ // Check if file exists
21
+ if (!existsSync(pdfPath)) {
22
+ throw new Error('PDF file not found');
23
+ }
24
+
25
+ // Check if file is a PDF
26
+ if (path.extname(pdfPath).toLowerCase() !== '.pdf') {
27
+ throw new Error('File is not a PDF');
28
+ }
29
+
30
+ // Read the PDF file
31
+ const dataBuffer = readFileSync(pdfPath);
32
+
33
+ // Parse PDF content
34
+ const data = await pdf(dataBuffer);
35
+
36
+ console.log(chalk.blue('\n'));
37
+ console.log(chalk.blue('PDF Information:'));
38
+ console.log(chalk.blue('-----------------'));
39
+ console.log(chalk.blue(`Number of pages: ${data.numpages}`));
40
+
41
+ return { content: data.text };
42
+ } catch (e) {
43
+ return { content: 'Error scanning PDF' };
44
+ }
45
+ },
46
+ });
@@ -0,0 +1,109 @@
1
+ import { Step, Workflow } from '@mastra/core';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import { z } from 'zod';
5
+
6
+ import { dane } from '../agents';
7
+
8
+ export const messageWorkflow = new Workflow({
9
+ name: 'entry',
10
+ triggerSchema: z.object({
11
+ resourceid: z.string(),
12
+ threadId: z.string(),
13
+ }),
14
+ });
15
+
16
+ const messageStep = new Step({
17
+ id: 'message-input',
18
+ outputSchema: z.object({
19
+ message: z.string(),
20
+ }),
21
+ execute: async () => {
22
+ const { content } = await inquirer.prompt([
23
+ {
24
+ type: 'input',
25
+ name: 'content',
26
+ message: '\n You:',
27
+ validate: input => input.trim().length > 0 || 'Message cannot be empty',
28
+ },
29
+ ]);
30
+
31
+ return { message: content };
32
+ },
33
+ });
34
+
35
+ const messageOutputStep = new Step({
36
+ id: 'message-output',
37
+ outputSchema: z.object({
38
+ message: z.string(),
39
+ }),
40
+ // SHOULD BE ABLE TO ACCESS ALL MASTRA PRIMS FROM EXECTUE
41
+ execute: async ({ context, mastra }) => {
42
+ // WISH THIS WAS TYPED
43
+ const threadId = context?.machineContext?.triggerData?.threadId;
44
+ const resourceid = context?.machineContext?.triggerData?.resourceid;
45
+
46
+ const messageInputStatus = context?.machineContext?.stepResults?.['message-input']?.status;
47
+
48
+ if (messageInputStatus !== 'success') {
49
+ return { message: 'Failure in workflow' };
50
+ }
51
+
52
+ // is there someway to know what steps are flowing into this one and type their props
53
+ const message = context?.machineContext?.stepResults?.['message-input']?.payload?.message;
54
+
55
+ try {
56
+ let messages = await mastra?.memory?.getContextWindow({
57
+ threadId,
58
+ format: 'core_message',
59
+ });
60
+
61
+ if (!messages || messages.length === 0) {
62
+ messages = [];
63
+ }
64
+
65
+ const res = await mastra?.agents?.['dane'].generate(message, {
66
+ stream: true,
67
+ maxSteps: 5,
68
+ resourceid,
69
+ threadId,
70
+ context: [],
71
+ });
72
+
73
+ if (res) {
74
+ console.log(chalk.green(`\nDane: \n`));
75
+
76
+ for await (const chunk of res.textStream) {
77
+ process.stdout.write(chalk.green(chunk));
78
+ }
79
+
80
+ console.log(chalk.green(`\n`));
81
+
82
+ return { message: 'success' };
83
+ }
84
+ } catch (e) {
85
+ console.log(chalk.red(`\n`));
86
+ console.log(chalk.red(`\n`));
87
+ console.log(chalk.red(`Error streaming results. Let's try again.`));
88
+ console.log(chalk.red(e.message));
89
+ }
90
+
91
+ const res = await dane.generate(message, {
92
+ maxSteps: 5,
93
+ threadId,
94
+ resourceid,
95
+ });
96
+
97
+ console.log(chalk.green(res.text));
98
+
99
+ return { message: res.text };
100
+ },
101
+ });
102
+
103
+ messageWorkflow
104
+ .step(messageStep)
105
+ .after(messageStep)
106
+ .step(messageOutputStep)
107
+ .after(messageOutputStep)
108
+ .step(messageStep)
109
+ .commit();
@@ -0,0 +1,2 @@
1
+ export * from './chat';
2
+ export * from './issue-labeler';
@@ -0,0 +1,103 @@
1
+ import { Step, Workflow } from '@mastra/core';
2
+ import { z } from 'zod';
3
+
4
+ import { github } from '../integrations';
5
+
6
+ export const githubIssueLabeler = new Workflow({
7
+ name: 'github-issue-labeler',
8
+ triggerSchema: z.object({
9
+ repo: z.string(),
10
+ owner: z.string(),
11
+ issue_number: z.number(),
12
+ }),
13
+ });
14
+
15
+ const getIssue = new Step({
16
+ id: 'getIssue',
17
+ outputSchema: z.object({
18
+ title: z.string(),
19
+ body: z.string(),
20
+ labelNames: z.array(z.string()),
21
+ }),
22
+ execute: async ({ context }) => {
23
+ const client = await github.getApiClient();
24
+
25
+ const issue = await client.issuesGet({
26
+ path: {
27
+ owner: context?.machineContext?.triggerData?.owner,
28
+ repo: context?.machineContext?.triggerData?.repo,
29
+ issue_number: context?.machineContext?.triggerData?.issue_number,
30
+ },
31
+ });
32
+
33
+ const labels = await client.issuesListLabelsForRepo({
34
+ path: {
35
+ owner: context?.machineContext?.triggerData?.owner,
36
+ repo: context?.machineContext?.triggerData?.repo,
37
+ },
38
+ });
39
+
40
+ const labelNames = labels?.data?.map(label => label.name);
41
+
42
+ return { title: issue?.data?.title!, body: issue?.data?.body!, labelNames: labelNames! };
43
+ },
44
+ });
45
+
46
+ const labelIssue = new Step({
47
+ id: 'labelIssue',
48
+ outputSchema: z.object({
49
+ labels: z.array(z.string()),
50
+ }),
51
+ execute: async ({ context, mastra }) => {
52
+ const parentStep = context?.machineContext?.stepResults?.getIssue;
53
+ if (!parentStep || parentStep.status !== 'success') {
54
+ return { labels: [] };
55
+ }
56
+
57
+ const daneIssueLabeler = mastra?.agents?.daneIssueLabeler;
58
+
59
+ const res = await daneIssueLabeler?.generate(
60
+ `
61
+ Hey Dane, given:
62
+ * this issue title: ${parentStep?.payload?.title}
63
+ * this issue body: ${parentStep?.payload?.body}
64
+ * these labels: ${parentStep?.payload?.labelNames}
65
+
66
+ What label or labels would you assign?
67
+ `,
68
+ {
69
+ schema: z.object({
70
+ labels: z.array(z.string()),
71
+ }),
72
+ },
73
+ );
74
+
75
+ return { labels: res?.object?.labels as string[] };
76
+ },
77
+ });
78
+
79
+ const applyLabels = new Step({
80
+ id: 'applyLabels',
81
+ execute: async ({ context }) => {
82
+ const parentStep = context?.machineContext?.stepResults?.labelIssue;
83
+
84
+ if (!parentStep || parentStep.status !== 'success') {
85
+ return;
86
+ }
87
+
88
+ const client = await github.getApiClient();
89
+
90
+ await client.issuesAddLabels({
91
+ path: {
92
+ owner: context?.machineContext?.triggerData?.owner,
93
+ repo: context?.machineContext?.triggerData?.repo,
94
+ issue_number: context?.machineContext?.triggerData?.issue_number,
95
+ },
96
+ body: {
97
+ labels: parentStep.payload.labels,
98
+ },
99
+ });
100
+ },
101
+ });
102
+
103
+ githubIssueLabeler.step(getIssue).then(labelIssue).then(applyLabels).commit();
Binary file
@@ -0,0 +1,42 @@
1
+
2
+
3
+ Your Company
4
+ 123 Your Street
5
+ Your City, ST 12345
6
+ (123) 456 - 7890
7
+ Product Brochure
8
+ September 04, 20XX
9
+ Product Overview
10
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod
11
+ tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
12
+ nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
13
+ Lorem ipsum
14
+ Nam liber tempor cum soluta nobis eleifend option
15
+ congue nihil imperdiet doming id quod mazim
16
+ placerat facer possim assum. Typi non habent
17
+ claritatem insitam; est usus legentis in iis qui facit
18
+ eorum claritatem.
19
+ Lorem ipsum
20
+ Duis autem vel eum iriure dolor in hendrerit in
21
+ vulputate velit esse molestie consequat, vel illum
22
+ dolore eu feugiat nulla facilisis at vero eros et
23
+ accumsan.
24
+ Dolor sit
25
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod
26
+ tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
27
+ nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
28
+
29
+ 2
30
+ Details
31
+ Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod
32
+ mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis
33
+ qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii
34
+ legunt saepius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy
35
+ nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim
36
+ veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo
37
+ consequat.
38
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod
39
+ tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis
40
+ nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
41
+ Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
42
+ dolore eu feugiat nulla facilisis at vero eros et accumsan.
@@ -0,0 +1,79 @@
1
+ # The Roman Empire: A Historical Overview
2
+
3
+ ## Origins and Early History
4
+
5
+ - Founded in 753 BCE according to legend by Romulus and Remus
6
+ - Started as a small town on the Tiber River
7
+ - Grew to become one of the largest empires in ancient history
8
+ - Originally ruled by seven kings before becoming a republic in 509 BCE
9
+
10
+ ## The Republic Era
11
+
12
+ - Transformed from monarchy to republic in 509 BCE
13
+ - Power was held by elected magistrates called consuls
14
+ - Featured a complex political system with the Senate at its center
15
+ - Experienced significant military expansion and cultural growth
16
+ - First Roman law code (Twelve Tables) established in 450 BCE
17
+
18
+ ## Military Conquests
19
+
20
+ - Gained control of the Italian peninsula by 264 BCE
21
+ - Fought the famous Punic Wars with Carthage
22
+ - Expanded into Macedonia and Greece
23
+ - Developed an extensive network of roads and infrastructure
24
+ - Military success led to cultural advancement through contact with other civilizations
25
+
26
+ ## The Empire Period
27
+
28
+ - Transition from Republic to Empire began with Julius Caesar
29
+ - Augustus became the first Roman Emperor in 27 BCE
30
+ - Experienced the Pax Romana (Roman Peace) - two centuries of stability
31
+ - At its height, controlled territories across Europe, North Africa, and the Middle East
32
+ - Notable emperors included:
33
+ - Augustus (27 BCE - 14 CE)
34
+ - Trajan (98-117 CE)
35
+ - Hadrian (117-138 CE)
36
+ - Marcus Aurelius (161-180 CE)
37
+
38
+ ## Major Achievements and Legacy
39
+
40
+ 1. Architecture and Engineering:
41
+
42
+ - Aqueducts for water transportation
43
+ - Advanced road systems (over 50,000 miles by 200 BCE)
44
+ - Revolutionary concrete and construction techniques
45
+ - Iconic structures like the Colosseum
46
+
47
+ 2. Cultural Contributions:
48
+
49
+ - Development of Romance languages
50
+ - Modern Western alphabet
51
+ - Legal system foundations
52
+ - Spread of Christianity
53
+ - Architectural influences
54
+
55
+ 3. Administrative Systems:
56
+ - Sophisticated governmental structure
57
+ - Advanced legal framework
58
+ - Efficient tax system
59
+ - Provincial administration model
60
+
61
+ ## Decline and Fall
62
+
63
+ - Began experiencing significant problems in the 3rd century CE
64
+ - Split into Eastern and Western empires under Diocletian
65
+ - Faced increasing pressure from external invasions
66
+ - Western Empire fell in 476 CE when Odoacer deposed the last emperor
67
+ - Eastern Empire (Byzantine) continued for another millennium
68
+
69
+ ## Lasting Impact
70
+
71
+ The Roman Empire's influence continues to be felt in:
72
+
73
+ - Modern government and legal systems
74
+ - Architecture and engineering
75
+ - Language and literature
76
+ - Cultural practices
77
+ - Urban planning and infrastructure
78
+
79
+ The Roman Empire stands as one of history's most significant civilizations, whose legacy continues to influence modern society in countless ways.
Binary file
@@ -0,0 +1,45 @@
1
+ Property Address:
2
+ 456 Maple Ridge Rd, Riverbrook, Westfield 78901
3
+
4
+ Property Type:
5
+ Condominium (Unit #7)
6
+
7
+ Assessed Property Value:
8
+ $210,000
9
+
10
+ Taxable Value:
11
+ $200,000 (after exemptions and adjustments)
12
+
13
+ Local Tax Rate:
14
+ 1.8% (applied to taxable value)
15
+
16
+ Annual Property Taxes:
17
+ $3,600
18
+
19
+ Exemptions:
20
+
21
+ Veteran’s Homestead Exemption: $10,000
22
+ Disabled Homeowner Exemption: $15,000
23
+ School District Levy:
24
+ $1,500 (included in the annual taxes)
25
+
26
+ County Services Tax:
27
+ $1,000
28
+
29
+ Municipal Tax (Riverbrook):
30
+ $700
31
+
32
+ Water & Sewer Special Assessment Fee:
33
+ $400 (this is an annual surcharge added to property taxes)
34
+
35
+ Due Dates:
36
+
37
+ First Half Payment: March 31
38
+ Second Half Payment: September 30
39
+ Penalties for Late Payment:
40
+
41
+ 4% penalty after 30 days
42
+ Additional 6% if paid after 90 days
43
+ Interest of 1.25% per month on overdue amounts
44
+ Tax Lien Information:
45
+ If property taxes remain unpaid for more than 180 days, a tax lien may be placed on the property and subject to foreclosure after 2 years.
@@ -0,0 +1,44 @@
1
+ Property Address:
2
+ 123 Oakwood Lane, Pineville, Stateville 67890
3
+
4
+ Property Type:
5
+ Single-Family Home
6
+
7
+ Assessed Property Value:
8
+ $350,000
9
+
10
+ Taxable Value:
11
+ $325,000 (after exemptions and adjustments)
12
+
13
+ Local Tax Rate:
14
+ 2.5% (applied to taxable value)
15
+
16
+ Annual Property Taxes:
17
+ $8,125
18
+
19
+ Exemptions:
20
+
21
+ Homestead Exemption: $25,000
22
+ Senior Citizen Discount: $5,000 (due to homeowner’s age over 65)
23
+ Veteran’s Exemption: $3,000
24
+ School District Levy:
25
+ $3,000 (included in the annual taxes)
26
+
27
+ County and Local Service Tax Levy:
28
+ $4,500
29
+
30
+ Fire District Tax:
31
+ $1,000
32
+
33
+ Special Assessment District (Road Improvement):
34
+ $500
35
+
36
+ Due Dates:
37
+
38
+ First Half Payment: January 15
39
+ Second Half Payment: June 30
40
+ Penalties for Late Payment:
41
+
42
+ 5% of unpaid balance after 30 days
43
+ 10% after 60 days
44
+ Interest accrues at 1.5% per month on overdue amounts