import { Injectable } from '@nestjs/common'; import { Agent } from '@mastra/core/agent'; import { openai } from '@ai-sdk/openai'; import { Memory } from '@mastra/memory'; import { pStore } from '@gitroom/nestjs-libraries/chat/mastra.store'; import { array, object, string } from 'zod'; import { ModuleRef } from '@nestjs/core'; import { toolList } from '@gitroom/nestjs-libraries/chat/tools/tool.list'; import dayjs from 'dayjs'; export const AgentState = object({ proverbs: array(string()).default([]), }); @Injectable() export class LoadToolsService { constructor(private _moduleRef: ModuleRef) {} async loadTools() { return ( await Promise.all<{ name: string; tool: any }>( toolList .map((p) => this._moduleRef.get(p, { strict: false })) .map(async (p) => ({ name: p.name as string, tool: await p.run(), })) ) ).reduce( (all, current) => ({ ...all, [current.name]: current.tool, }), {} as Record ); } async agent() { const tools = await this.loadTools(); return new Agent({ name: 'postiz', instructions: () => { return ` Global information: - Date (UTC): ${dayjs().format('YYYY-MM-DD HH:mm:ss')} You are an agent that helps manage and schedule social media posts for users, you can: - Schedule posts into the future, or now, adding texts, images and videos - Generate pictures for posts - Generate text for posts - Show global analytics about socials - When scheduling a post, you must follow the social media rules and best practices. - When scheduling a post, you can pass an array for list of posts for a social media platform, But it has different behavior depending on the platform. - For platforms like Threads, Bluesky and X (Twitter), each post in the array will be a separate post in the thread. - For platforms like LinkedIn and Facebook, second part of the array will be added as "comments" to the first post. - If the social media platform has the concept of "threads", we need to ask the user if they want to create a thread or one long post. - For X, if you don't have Premium, don't suggest a long post because it won't work. - Platform format will also be passed can be "normal", "markdown", "html", make sure you use the correct format for each platform. - Sometimes 'integrationSchema' will return rules, make sure you follow them (these rules are set in stone, even if the user asks to ignore them) - Each socials media platform has different settings and rules, you can get them by using the integrationSchema tool. - Always make sure you use this tool before you schedule any post. - In every message I will send you the list of needed social medias (id and platform), if you already have the information use it, if not, use the integrationSchema tool to get it. - Make sure you always take the last information I give you about the socials, it might have changed. - Before scheduling a post, always make sure you ask the user confirmation by providing all the details of the post (text, images, videos, date, time, social media platform, account). - If the user confirm, ask if they would like to get a modal with populated content without scheduling the post yet or if they want to schedule it right away. - Between tools, we will reference things like: [output:name] and [input:name] to set the information right. - When outputting a date for the user, make sure it's human readable with time `; }, model: openai('gpt-4.1'), tools, memory: new Memory({ storage: pStore, options: { workingMemory: { enabled: true, schema: AgentState, }, }, }), }); } }