Compare commits

..

18 Commits

Author SHA1 Message Date
mudler
9bea6c7322 chore(tests): fix env var
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 15:46:39 +02:00
mudler
0ab7a615f0 fix: do not override actions
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 13:10:34 +02:00
mudler
b4b77c564e Not needed anymore, using tests
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 13:09:24 +02:00
mudler
24c3e41d27 Improve setup' 2025-04-24 13:07:06 +02:00
mudler
ebf26ebb64 Wire mcpbox to tests 2025-04-24 12:59:22 +02:00
mudler
3e80bd9608 Add container image to CI builds 2025-04-24 12:58:54 +02:00
mudler
34d0954171 Make it working, expose MCP prepare script to UI
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:46:47 +02:00
Ettore Di Giacinto
9b7344fbdf fixes
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:46:47 +02:00
mudler
608d7aba85 quality of life improvements
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:46:47 +02:00
mudler
bd903a3f33 add one-time process, attach to UI the mcp server json configuration
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:46:46 +02:00
mudler
0e1106eaf5 Revert "Attach to ui"
This reverts commit 088d0c47e87ee8f84297e47d178fb7384bbe6d45.

Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
e9cd6a1073 Attach to ui
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
4b727116cd Attach to config
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
3ebeb82f0d Add to dockerfile
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
6d9c58e6c0 Attach mcp stdio box to agent
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
02490ea8a2 Add mcpbox dockerfile and entrypoint
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
eec88d74fe Add groups to mcpbox
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
Ettore Di Giacinto
33b8aaddfe wip
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Signed-off-by: mudler <mudler@localai.io>
2025-04-24 12:45:52 +02:00
8 changed files with 12 additions and 61 deletions

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v2
- run: |
# Add Docker's official GPG key:
sudo apt-get update

View File

@@ -2,7 +2,7 @@
<img src="./webui/react-ui/public/logo_1.png" alt="LocalAGI Logo" width="220"/>
</p>
<h3 align="center"><em>Your AI. Your Hardware. Your Rules</em></h3>
<h3 align="center"><em>Your AI. Your Hardware. Your Rules.</em></h3>
<div align="center">
@@ -13,9 +13,9 @@
</div>
Create customizable AI assistants, automations, chat bots and agents that run 100% locally. No need for agentic Python libraries or cloud service keys, just bring your GPU (or even just CPU) and a web browser.
We empower you building AI Agents that you can run locally, without coding.
**LocalAGI** is a powerful, self-hostable AI Agent platform that allows you to design AI automations without writing code. A complete drop-in replacement for OpenAI's Responses APIs with advanced agentic capabilities. No clouds. No data leaks. Just pure local AI that works on consumer-grade hardware (CPU and GPU).
**LocalAGI** is a powerful, self-hostable AI Agent platform designed for maximum privacy and flexibility. A complete drop-in replacement for OpenAI's Responses APIs with advanced agentic capabilities. No clouds. No data leaks. Just pure local AI that works on consumer-grade hardware (CPU and GPU).
## 🛡️ Take Back Your Privacy
@@ -37,7 +37,6 @@ LocalAGI ensures your data stays exactly where you want it—on your hardware. N
- 🖼 **Multimodal Support**: Ready for vision, text, and more.
- 🔧 **Extensible Custom Actions**: Easily script dynamic agent behaviors in Go (interpreted, no compilation!).
- 🛠 **Fully Customizable Models**: Use your own models or integrate seamlessly with [LocalAI](https://github.com/mudler/LocalAI).
- 📊 **Observability**: Monitor agent status and view detailed observable updates in real-time.
## 🛠️ Quickstart
@@ -195,8 +194,6 @@ LocalAGI is part of the powerful Local family of privacy-focused AI tools:
![Web UI Dashboard](https://github.com/user-attachments/assets/a40194f9-af3a-461f-8b39-5f4612fbf221)
![Web UI Agent Settings](https://github.com/user-attachments/assets/fb3c3e2a-cd53-4ca8-97aa-c5da51ff1f83)
![Web UI Create Group](https://github.com/user-attachments/assets/102189a2-0fba-4a1e-b0cb-f99268ef8062)
![Web UI Agent Observability](https://github.com/user-attachments/assets/f7359048-9d28-4cf1-9151-1f5556ce9235)
### Connectors Ready-to-Go

View File

@@ -12,11 +12,6 @@ services:
- /dev/dri/card1
- /dev/dri/renderD129
mcpbox:
extends:
file: docker-compose.yaml
service: mcpbox
localrecall:
extends:
file: docker-compose.yaml

View File

@@ -17,11 +17,6 @@ services:
count: 1
capabilities: [gpu]
mcpbox:
extends:
file: docker-compose.yaml
service: mcpbox
localrecall:
extends:
file: docker-compose.yaml
@@ -35,4 +30,4 @@ services:
localagi:
extends:
file: docker-compose.yaml
service: localagi
service: localagi

View File

@@ -1,4 +1,4 @@
package localoperator
package api
import (
"bytes"

View File

@@ -10,10 +10,6 @@ import (
"github.com/sashabaranov/go-openai/jsonschema"
)
const (
MetadataBrowserAgentHistory = "browser_agent_history"
)
type BrowserAgentRunner struct {
baseURL, customActionName string
client *api.Client
@@ -66,7 +62,7 @@ func (b *BrowserAgentRunner) Run(ctx context.Context, params types.ActionParams)
return types.ActionResult{
Result: fmt.Sprintf("Browser agent completed successfully. History:\n%s", historyStr),
Metadata: map[string]interface{}{MetadataBrowserAgentHistory: stateHistory},
Metadata: map[string]interface{}{"browser_agent_history": stateHistory},
}, nil
}

View File

@@ -11,7 +11,6 @@ import (
"time"
"github.com/mudler/LocalAGI/pkg/config"
"github.com/mudler/LocalAGI/pkg/localoperator"
"github.com/mudler/LocalAGI/pkg/xlog"
"github.com/mudler/LocalAGI/pkg/xstrings"
"github.com/mudler/LocalAGI/services/actions"
@@ -168,38 +167,8 @@ func replaceUserIDsWithNamesInMessage(api *slack.Client, message string) string
return message
}
func generateAttachmentsFromJobResponse(j *types.JobResult, api *slack.Client, channelID, ts string) (attachments []slack.Attachment) {
func generateAttachmentsFromJobResponse(j *types.JobResult) (attachments []slack.Attachment) {
for _, state := range j.State {
// coming from the browser agent
if history, exists := state.Metadata[actions.MetadataBrowserAgentHistory]; exists {
if historyStruct, ok := history.(*localoperator.StateHistory); ok {
state := historyStruct.States[len(historyStruct.States)-1]
// Decode base64 screenshot and upload to Slack
if state.Screenshot != "" {
screenshotData, err := base64.StdEncoding.DecodeString(state.Screenshot)
if err != nil {
xlog.Error(fmt.Sprintf("Error decoding screenshot: %v", err))
continue
}
data := string(screenshotData)
// Upload the file to Slack
_, err = api.UploadFileV2(slack.UploadFileV2Parameters{
Reader: bytes.NewReader(screenshotData),
FileSize: len(data),
ThreadTimestamp: ts,
Channel: channelID,
Filename: "screenshot.png",
InitialComment: "Browser Agent Screenshot",
})
if err != nil {
xlog.Error(fmt.Sprintf("Error uploading screenshot: %v", err))
continue
}
}
}
}
// coming from the search action
if urls, exists := state.Metadata[actions.MetadataUrls]; exists {
for _, url := range xstrings.UniqueSlice(urls.([]string)) {
@@ -406,7 +375,7 @@ func replyWithPostMessage(finalResponse string, api *slack.Client, ev *slackeven
slack.MsgOptionEnableLinkUnfurl(),
slack.MsgOptionText(message, true),
slack.MsgOptionPostMessageParameters(postMessageParams),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res, api, ev.Channel, "")...),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
)
if err != nil {
xlog.Error(fmt.Sprintf("Error posting message: %v", err))
@@ -418,7 +387,7 @@ func replyWithPostMessage(finalResponse string, api *slack.Client, ev *slackeven
slack.MsgOptionEnableLinkUnfurl(),
slack.MsgOptionText(res.Response, true),
slack.MsgOptionPostMessageParameters(postMessageParams),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res, api, ev.Channel, "")...),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
// slack.MsgOptionTS(ts),
)
if err != nil {
@@ -439,7 +408,7 @@ func replyToUpdateMessage(finalResponse string, api *slack.Client, ev *slackeven
slack.MsgOptionLinkNames(true),
slack.MsgOptionEnableLinkUnfurl(),
slack.MsgOptionText(messages[0], true),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res, api, ev.Channel, msgTs)...),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
)
if err != nil {
xlog.Error(fmt.Sprintf("Error updating final message: %v", err))
@@ -466,7 +435,7 @@ func replyToUpdateMessage(finalResponse string, api *slack.Client, ev *slackeven
slack.MsgOptionLinkNames(true),
slack.MsgOptionEnableLinkUnfurl(),
slack.MsgOptionText(finalResponse, true),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res, api, ev.Channel, msgTs)...),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
)
if err != nil {
xlog.Error(fmt.Sprintf("Error updating final message: %v", err))

View File

@@ -23,7 +23,6 @@ oauth_config:
- commands
- groups:history
- files:read
- files:write
- im:history
- im:read
- im:write