feat(reminders): add reminder system to perform long-term goals in the background (#176)
* feat(reminders): add self-ability to set reminders Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(reminders): surface reminders result to the user as new conversations Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Fixups * Subscribe all connectors to agents new messages Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Set reminders in the list * fix(telegram): do not always auth Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Small fixups * Improve UX Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
committed by
GitHub
parent
490bf998a4
commit
9a90153dc6
@@ -83,6 +83,27 @@ func (d *Discord) Start(a *agent.Agent) {
|
||||
|
||||
dg.StateEnabled = true
|
||||
|
||||
if d.defaultChannel != "" {
|
||||
// handle new conversations
|
||||
a.AddSubscriber(func(ccm openai.ChatCompletionMessage) {
|
||||
xlog.Debug("Subscriber(discord)", "message", ccm.Content)
|
||||
|
||||
// Send the message to the default channel
|
||||
_, err := dg.ChannelMessageSend(d.defaultChannel, ccm.Content)
|
||||
if err != nil {
|
||||
xlog.Error(fmt.Sprintf("Error sending message: %v", err))
|
||||
}
|
||||
|
||||
a.SharedState().ConversationTracker.AddMessage(
|
||||
fmt.Sprintf("discord:%s", d.defaultChannel),
|
||||
openai.ChatCompletionMessage{
|
||||
Content: ccm.Content,
|
||||
Role: "assistant",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// Register the messageCreate func as a callback for MessageCreate events.
|
||||
dg.AddHandler(d.messageCreate(a))
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ type Email struct {
|
||||
smtpInsecure bool
|
||||
imapServer string
|
||||
imapInsecure bool
|
||||
defaultEmail string
|
||||
}
|
||||
|
||||
func NewEmail(config map[string]string) *Email {
|
||||
@@ -48,6 +49,7 @@ func NewEmail(config map[string]string) *Email {
|
||||
smtpInsecure: config["smtpInsecure"] == "true",
|
||||
imapServer: config["imapServer"],
|
||||
imapInsecure: config["imapInsecure"] == "true",
|
||||
defaultEmail: config["defaultEmail"],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +107,12 @@ func EmailConfigMeta() []config.Field {
|
||||
Required: true,
|
||||
HelpText: "Agent email address",
|
||||
},
|
||||
{
|
||||
Name: "defaultEmail",
|
||||
Label: "Default Recipient",
|
||||
Type: config.FieldTypeText,
|
||||
HelpText: "Default email address to send messages to when the agent wants to initiate a conversation",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +375,31 @@ func imapWorker(done chan bool, e *Email, a *agent.Agent, c *imapclient.Client,
|
||||
|
||||
func (e *Email) Start(a *agent.Agent) {
|
||||
go func() {
|
||||
if e.defaultEmail != "" {
|
||||
// handle new conversations
|
||||
a.AddSubscriber(func(ccm openai.ChatCompletionMessage) {
|
||||
xlog.Debug("Subscriber(email)", "message", ccm.Content)
|
||||
|
||||
// Send the message to the default email
|
||||
e.sendMail(
|
||||
e.defaultEmail,
|
||||
"Message from LocalAGI",
|
||||
ccm.Content,
|
||||
"",
|
||||
"",
|
||||
[]string{e.defaultEmail},
|
||||
false,
|
||||
)
|
||||
|
||||
a.SharedState().ConversationTracker.AddMessage(
|
||||
fmt.Sprintf("email:%s", e.defaultEmail),
|
||||
openai.ChatCompletionMessage{
|
||||
Content: ccm.Content,
|
||||
Role: "assistant",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
xlog.Info("Email connector is now running. Press CTRL-C to exit.")
|
||||
// IMAP dial
|
||||
|
||||
@@ -70,6 +70,52 @@ func (i *IRC) Start(a *agent.Agent) {
|
||||
return
|
||||
}
|
||||
i.conn.UseTLS = false
|
||||
|
||||
if i.channel != "" {
|
||||
// handle new conversations
|
||||
a.AddSubscriber(func(ccm openai.ChatCompletionMessage) {
|
||||
xlog.Debug("Subscriber(irc)", "message", ccm.Content)
|
||||
|
||||
// Split the response into multiple messages if it's too long
|
||||
maxLength := 400 // Safe limit for most IRC servers
|
||||
response := ccm.Content
|
||||
|
||||
// Handle multiline responses
|
||||
lines := strings.Split(response, "\n")
|
||||
for _, line := range lines {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Split long lines
|
||||
for len(line) > 0 {
|
||||
var chunk string
|
||||
if len(line) > maxLength {
|
||||
chunk = line[:maxLength]
|
||||
line = line[maxLength:]
|
||||
} else {
|
||||
chunk = line
|
||||
line = ""
|
||||
}
|
||||
|
||||
// Send the message to the channel
|
||||
i.conn.Privmsg(i.channel, chunk)
|
||||
|
||||
// Small delay to prevent flooding
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
a.SharedState().ConversationTracker.AddMessage(
|
||||
fmt.Sprintf("irc:%s", i.channel),
|
||||
openai.ChatCompletionMessage{
|
||||
Content: ccm.Content,
|
||||
Role: "assistant",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
i.conn.AddCallback("001", func(e *irc.Event) {
|
||||
xlog.Info("Connected to IRC server", "server", i.server, "arguments", e.Arguments)
|
||||
i.conn.Join(i.channel)
|
||||
|
||||
@@ -223,6 +223,24 @@ func (m *Matrix) Start(a *agent.Agent) {
|
||||
xlog.Info("Matrix client created")
|
||||
m.client = client
|
||||
|
||||
if m.roomID != "" {
|
||||
// handle new conversations
|
||||
a.AddSubscriber(func(ccm openai.ChatCompletionMessage) {
|
||||
xlog.Debug("Subscriber(matrix)", "message", ccm.Content)
|
||||
_, err := m.client.SendText(context.Background(), id.RoomID(m.roomID), ccm.Content)
|
||||
if err != nil {
|
||||
xlog.Error(fmt.Sprintf("Error posting message: %v", err))
|
||||
}
|
||||
a.SharedState().ConversationTracker.AddMessage(
|
||||
fmt.Sprintf("matrix:%s", m.roomID),
|
||||
openai.ChatCompletionMessage{
|
||||
Content: ccm.Content,
|
||||
Role: "assistant",
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
syncer := client.Syncer.(*mautrix.DefaultSyncer)
|
||||
syncer.OnEventType(event.EventMessage, func(ctx context.Context, evt *event.Event) {
|
||||
xlog.Info("Received message", evt.Content.AsMessage().Body)
|
||||
|
||||
@@ -225,7 +225,7 @@ func (t *Telegram) handleUpdate(ctx context.Context, b *bot.Bot, a *agent.Agent,
|
||||
})
|
||||
}
|
||||
if len(t.admins) > 0 && !slices.Contains(t.admins, username) {
|
||||
xlog.Info("Unauthorized user", "username", username)
|
||||
xlog.Info("Unauthorized user", "username", username, "admins", t.admins)
|
||||
_, err := b.SendMessage(ctx, &bot.SendMessageParams{
|
||||
ChatID: update.Message.Chat.ID,
|
||||
Text: "you are not authorized to use this bot!",
|
||||
@@ -444,7 +444,7 @@ func NewTelegramConnector(config map[string]string) (*Telegram, error) {
|
||||
|
||||
admins := []string{}
|
||||
|
||||
if _, ok := config["admins"]; ok {
|
||||
if _, ok := config["admins"]; ok && strings.Contains(config["admins"], ",") {
|
||||
admins = append(admins, strings.Split(config["admins"], ",")...)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user