return metadatas and conversations in job results. Consume them in Slack connector to use attachments in responses

This commit is contained in:
Ettore Di Giacinto
2025-03-01 22:10:21 +01:00
parent 4d6b04c6ed
commit 3a7b5e1461
10 changed files with 106 additions and 48 deletions

View File

@@ -25,7 +25,7 @@ type StateAction struct{}
// TODO: A special action is then used to let the LLM itself update its memory
// periodically during self-processing, and the same action is ALSO exposed
// during the conversation to let the user put for example, a new goal to the agent.
type StateResult struct {
type AgentInternalState struct {
NowDoing string `json:"doing_now"`
DoingNext string `json:"doing_next"`
DoneHistory []string `json:"done_history"`
@@ -81,7 +81,7 @@ You have a short memory with: %+v
=====================
`
func (c StateResult) String() string {
func (c AgentInternalState) String() string {
return fmt.Sprintf(
fmtT,
c.NowDoing,

View File

@@ -12,7 +12,7 @@ import (
type ActionState struct {
ActionCurrentState
Result string
action.ActionResult
}
type ActionCurrentState struct {

View File

@@ -31,7 +31,7 @@ type Agent struct {
context *action.ActionContext
currentReasoning string
currentState *action.StateResult
currentState *action.AgentInternalState
nextAction Action
nextActionParams *action.ActionParams
currentConversation Messages
@@ -67,7 +67,7 @@ func New(opts ...Option) (*Agent, error) {
options: options,
client: client,
Character: options.character,
currentState: &action.StateResult{},
currentState: &action.AgentInternalState{},
context: action.NewContext(ctx, cancel),
}
@@ -239,15 +239,15 @@ func (a *Agent) Memory() RAGDB {
return a.options.ragdb
}
func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (result string, err error) {
for _, action := range a.systemInternalActions() {
if action.Definition().Name == chosenAction.Definition().Name {
res, err := action.Run(a.actionContext, params)
func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (result action.ActionResult, err error) {
for _, act := range a.systemInternalActions() {
if act.Definition().Name == chosenAction.Definition().Name {
res, err := act.Run(a.actionContext, params)
if err != nil {
return "", fmt.Errorf("error running action: %w", err)
return action.ActionResult{}, fmt.Errorf("error running action: %w", err)
}
result = res.Result
result = res
}
}
@@ -255,11 +255,11 @@ func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (resu
if chosenAction.Definition().Name.Is(action.StateActionName) {
// We need to store the result in the state
state := action.StateResult{}
state := action.AgentInternalState{}
err = params.Unmarshal(&state)
if err != nil {
return "", fmt.Errorf("error unmarshalling state of the agent: %w", err)
return action.ActionResult{}, fmt.Errorf("error unmarshalling state of the agent: %w", err)
}
// update the current state with the one we just got from the action
a.currentState = &state
@@ -267,7 +267,7 @@ func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (resu
// update the state file
if a.options.statefile != "" {
if err := a.SaveState(a.options.statefile); err != nil {
return "", err
return action.ActionResult{}, err
}
}
}
@@ -445,6 +445,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
Role: "assistant",
Content: reasoning,
})
job.Result.Conversation = a.currentConversation
job.Result.SetResponse(reasoning)
job.Result.Finish(nil)
return
@@ -486,7 +487,8 @@ func (a *Agent) consumeJob(job *Job, role string) {
}
if !job.Callback(ActionCurrentState{chosenAction, actionParams, reasoning}) {
job.Result.SetResult(ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, "stopped by callback"})
job.Result.SetResult(ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, action.ActionResult{Result: "stopped by callback"}})
job.Result.Conversation = a.currentConversation
job.Result.Finish(nil)
return
}
@@ -512,6 +514,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
Content: message.Message,
}
}()
job.Result.Conversation = a.currentConversation
job.Result.SetResponse("decided to initiate a new conversation")
job.Result.Finish(nil)
return
@@ -524,7 +527,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
//job.Result.Finish(fmt.Errorf("error running action: %w", err))
//return
// make the LLM aware of the error of running the action instead of stopping the job here
result = fmt.Sprintf("Error running tool: %v", err)
result.Result = fmt.Sprintf("Error running tool: %v", err)
}
stateResult := ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, result}
@@ -549,7 +552,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
// result of calling the function
a.currentConversation = append(a.currentConversation, openai.ChatCompletionMessage{
Role: openai.ChatMessageRoleTool,
Content: result,
Content: result.Result,
Name: chosenAction.Definition().Name.String(),
ToolCallID: chosenAction.Definition().Name.String(),
})
@@ -561,6 +564,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
// to continue using another tool given the result
followingAction, followingParams, reasoning, err := a.pickAction(ctx, reEvaluationTemplate, a.currentConversation)
if err != nil {
job.Result.Conversation = a.currentConversation
job.Result.Finish(fmt.Errorf("error picking action: %w", err))
return
}
@@ -592,12 +596,15 @@ func (a *Agent) consumeJob(job *Job, role string) {
a.currentConversation = append(a.currentConversation, msg)
job.Result.SetResponse(msg.Content)
job.Result.Conversation = a.currentConversation
job.Result.Finish(nil)
return
}
}
}
job.Result.Conversation = a.currentConversation
// At this point can only be a reply action
xlog.Info("Computing reply", "agent", a.Character.Name)
@@ -605,6 +612,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
replyResponse := action.ReplyResponse{}
if err := actionParams.Unmarshal(&replyResponse); err != nil {
job.Result.Conversation = a.currentConversation
job.Result.Finish(fmt.Errorf("error unmarshalling reply response: %w", err))
return
}
@@ -628,6 +636,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
if a.options.enableHUD {
prompt, err := renderTemplate(hudTemplate, a.prepareHUD(), a.systemInternalActions(), reasoning)
if err != nil {
job.Result.Conversation = a.currentConversation
job.Result.Finish(fmt.Errorf("error renderTemplate: %w", err))
return
}
@@ -663,6 +672,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
}
a.currentConversation = append(a.currentConversation, msg)
job.Result.Conversation = a.currentConversation
job.Result.SetResponse(msg.Content)
job.Result.Finish(nil)
return
@@ -672,6 +682,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
xlog.Debug("Conversation", "conversation", fmt.Sprintf("%+v", a.currentConversation))
msg, err := a.askLLM(ctx, a.currentConversation)
if err != nil {
job.Result.Conversation = a.currentConversation
job.Result.Finish(err)
return
}
@@ -690,7 +701,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
a.currentConversation = append(a.currentConversation, msg)
job.Result.SetResponse(msg.Content)
xlog.Info("Response from LLM", "response", msg.Content, "agent", a.Character.Name)
job.Result.Conversation = a.currentConversation
job.Result.Finish(nil)
}

View File

@@ -23,10 +23,11 @@ type Job struct {
type JobResult struct {
sync.Mutex
// The result of a job
State []ActionState
Response string
Error error
ready chan bool
State []ActionState
Conversation []openai.ChatCompletionMessage
Response string
Error error
ready chan bool
}
type JobOption func(*Job)

View File

@@ -14,10 +14,10 @@ import (
// all information that should be displayed to the LLM
// in the prompts
type PromptHUD struct {
Character Character `json:"character"`
CurrentState action.StateResult `json:"current_state"`
PermanentGoal string `json:"permanent_goal"`
ShowCharacter bool `json:"show_character"`
Character Character `json:"character"`
CurrentState action.AgentInternalState `json:"current_state"`
PermanentGoal string `json:"permanent_goal"`
ShowCharacter bool `json:"show_character"`
}
type Character struct {
@@ -42,7 +42,7 @@ func Load(path string) (*Character, error) {
return &c, nil
}
func (a *Agent) State() action.StateResult {
func (a *Agent) State() action.AgentInternalState {
return *a.currentState
}

14
go.mod
View File

@@ -9,13 +9,13 @@ require (
github.com/chasefleming/elem-go v0.25.0
github.com/donseba/go-htmx v1.8.0
github.com/dslipak/pdf v0.0.2
github.com/eritikass/githubmarkdownconvertergo v0.1.10
github.com/go-telegram/bot v1.2.1
github.com/gofiber/fiber/v2 v2.52.4
github.com/gofiber/template/html/v2 v2.1.1
github.com/google/go-github/v61 v61.0.0
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.31.1
github.com/oxffaa/gopher-parse-sitemap v0.0.0-20191021113419-005d2eb1def4
github.com/philippgille/chromem-go v0.5.0
github.com/sashabaranov/go-openai v1.18.3
github.com/slack-go/slack v0.12.5
@@ -23,6 +23,7 @@ require (
github.com/traefik/yaegi v0.16.1
github.com/valyala/fasthttp v1.52.0
jaytaylor.com/html2text v0.0.0-20230321000545-74c2419ad056
mvdan.cc/xurls/v2 v2.6.0
)
require (
@@ -33,7 +34,6 @@ require (
github.com/antchfx/xmlquery v1.3.17 // indirect
github.com/antchfx/xpath v1.2.4 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/eritikass/githubmarkdownconvertergo v0.1.10 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/glob v0.2.3 // indirect
@@ -61,11 +61,11 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.16.1 // indirect
golang.org/x/crypto v0.30.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

24
go.sum
View File

@@ -112,8 +112,6 @@ github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
github.com/oxffaa/gopher-parse-sitemap v0.0.0-20191021113419-005d2eb1def4 h1:2vmb32OdDhjZf2ETGDlr9n8RYXx7c+jXPxMiPbwnA+8=
github.com/oxffaa/gopher-parse-sitemap v0.0.0-20191021113419-005d2eb1def4/go.mod h1:2JQx4jDHmWrbABvpOayg/+OTU6ehN0IyK2EHzceXpJo=
github.com/philippgille/chromem-go v0.5.0 h1:bryX0F3N6jnN/21iBd8i2/k9EzPTZn3nyiqAti19si8=
github.com/philippgille/chromem-go v0.5.0/go.mod h1:hTd+wGEm/fFPQl7ilfCwQXkgEUxceYh86iIdoKMolPo=
github.com/pkoukk/tiktoken-go v0.1.6 h1:JF0TlJzhTbrI30wCvFuiw6FzP2+/bR+FIxUdgEAcUsw=
@@ -155,8 +153,8 @@ go.starlark.net v0.0.0-20230302034142-4b1e35fe2254/go.mod h1:jxU+3+j+71eXOW14274
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -175,8 +173,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -197,8 +195,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -213,8 +211,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -223,8 +221,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -259,3 +257,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
jaytaylor.com/html2text v0.0.0-20230321000545-74c2419ad056 h1:6YFJoB+0fUH6X3xU/G2tQqCYg+PkGtnZ5nMR5rpw72g=
jaytaylor.com/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:OxvTsCwKosqQ1q7B+8FwXqg4rKZ/UG9dUW+g/VL2xH4=
mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=

View File

@@ -9,6 +9,10 @@ import (
"github.com/sashabaranov/go-openai/jsonschema"
)
const (
MetadataImages = "images_url"
)
func NewGenImage(config map[string]string) *GenImageAction {
defaultConfig := openai.DefaultConfig(config["apiKey"])
defaultConfig.BaseURL = config["apiURL"]
@@ -65,7 +69,7 @@ func (a *GenImageAction) Run(ctx context.Context, params action.ActionParams) (a
return action.ActionResult{
Result: fmt.Sprintf("The image was generated and available at: %s", resp.Data[0].URL), Metadata: map[string]interface{}{
"url": resp.Data[0].URL,
MetadataImages: []string{resp.Data[0].URL},
}}, nil
}

View File

@@ -8,6 +8,11 @@ import (
"github.com/mudler/LocalAgent/core/action"
"github.com/sashabaranov/go-openai/jsonschema"
"github.com/tmc/langchaingo/tools/duckduckgo"
"mvdan.cc/xurls/v2"
)
const (
MetadataUrls = "urls"
)
func NewSearch(config map[string]string) *SearchAction {
@@ -50,7 +55,11 @@ func (a *SearchAction) Run(ctx context.Context, params action.ActionParams) (act
return action.ActionResult{}, err
}
return action.ActionResult{Result: res}, nil
rxStrict := xurls.Strict()
urls := rxStrict.FindAllString(res, -1)
return action.ActionResult{Result: res, Metadata: map[string]interface{}{MetadataUrls: urls}}, nil
}
func (a *SearchAction) Definition() action.ActionDefinition {

View File

@@ -7,6 +7,7 @@ import (
"strings"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/actions"
"github.com/sashabaranov/go-openai"
"github.com/mudler/LocalAgent/core/agent"
@@ -55,6 +56,35 @@ func cleanUpUsernameFromMessage(message string, b *slack.AuthTestResponse) strin
return cleaned
}
func generateAttachmentsFromJobResponse(j *agent.JobResult) (attachments []slack.Attachment) {
for _, state := range j.State {
// coming from the search action
if urls, exists := state.Metadata[actions.MetadataUrls]; exists {
for _, url := range urls.([]string) {
attachment := slack.Attachment{
Title: "URL",
TitleLink: url,
Text: url,
}
attachments = append(attachments, attachment)
}
}
// coming from the gen image actions
if imagesUrls, exists := state.Metadata[actions.MetadataImages]; exists {
for _, url := range imagesUrls.([]string) {
attachment := slack.Attachment{
Title: "Image",
TitleLink: url,
ImageURL: url,
}
attachments = append(attachments, attachment)
}
}
}
return
}
func (t *Slack) Start(a *agent.Agent) {
api := slack.New(
t.botToken,
@@ -129,6 +159,7 @@ func (t *Slack) Start(a *agent.Agent) {
_, _, err = api.PostMessage(ev.Channel,
slack.MsgOptionText(res.Response, true),
slack.MsgOptionPostMessageParameters(postMessageParams),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
// slack.MsgOptionTS(ts),
)
if err != nil {
@@ -194,10 +225,12 @@ func (t *Slack) Start(a *agent.Agent) {
slack.MsgOptionPostMessageParameters(
postMessageParams,
),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
slack.MsgOptionTS(ts))
} else {
_, _, err = api.PostMessage(ev.Channel,
slack.MsgOptionText(res.Response, true),
slack.MsgOptionAttachments(generateAttachmentsFromJobResponse(res)...),
slack.MsgOptionPostMessageParameters(
postMessageParams,
),