Finish moving types
This commit is contained in:
committed by
Ettore Di Giacinto
parent
f0b8bfb4f4
commit
75a8d63e83
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"github.com/traefik/yaegi/interp"
|
"github.com/traefik/yaegi/interp"
|
||||||
@@ -79,24 +80,24 @@ func (a *CustomAction) Plannable() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *CustomAction) Run(ctx context.Context, params ActionParams) (ActionResult, error) {
|
func (a *CustomAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
v, err := a.i.Eval(fmt.Sprintf("%s.Run", a.config["name"]))
|
v, err := a.i.Eval(fmt.Sprintf("%s.Run", a.config["name"]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
run := v.Interface().(func(map[string]interface{}) (string, map[string]interface{}, error))
|
run := v.Interface().(func(map[string]interface{}) (string, map[string]interface{}, error))
|
||||||
|
|
||||||
res, meta, err := run(params)
|
res, meta, err := run(params)
|
||||||
return ActionResult{Result: res, Metadata: meta}, err
|
return types.ActionResult{Result: res, Metadata: meta}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *CustomAction) Definition() ActionDefinition {
|
func (a *CustomAction) Definition() types.ActionDefinition {
|
||||||
|
|
||||||
v, err := a.i.Eval(fmt.Sprintf("%s.Definition", a.config["name"]))
|
v, err := a.i.Eval(fmt.Sprintf("%s.Definition", a.config["name"]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xlog.Error("Error getting custom action definition", "error", err)
|
xlog.Error("Error getting custom action definition", "error", err)
|
||||||
return ActionDefinition{}
|
return types.ActionDefinition{}
|
||||||
}
|
}
|
||||||
|
|
||||||
properties := v.Interface().(func() map[string][]string)
|
properties := v.Interface().(func() map[string][]string)
|
||||||
@@ -104,7 +105,7 @@ func (a *CustomAction) Definition() ActionDefinition {
|
|||||||
v, err = a.i.Eval(fmt.Sprintf("%s.RequiredFields", a.config["name"]))
|
v, err = a.i.Eval(fmt.Sprintf("%s.RequiredFields", a.config["name"]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xlog.Error("Error getting custom action definition", "error", err)
|
xlog.Error("Error getting custom action definition", "error", err)
|
||||||
return ActionDefinition{}
|
return types.ActionDefinition{}
|
||||||
}
|
}
|
||||||
|
|
||||||
requiredFields := v.Interface().(func() []string)
|
requiredFields := v.Interface().(func() []string)
|
||||||
@@ -121,8 +122,8 @@ func (a *CustomAction) Definition() ActionDefinition {
|
|||||||
Description: v[1],
|
Description: v[1],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: ActionDefinitionName(a.config["name"]),
|
Name: types.ActionDefinitionName(a.config["name"]),
|
||||||
Description: a.config["description"],
|
Description: a.config["description"],
|
||||||
Properties: prop,
|
Properties: prop,
|
||||||
Required: requiredFields(),
|
Required: requiredFields(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
. "github.com/mudler/LocalAgent/core/action"
|
. "github.com/mudler/LocalAgent/core/action"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ return []string{"foo"}
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
definition := customAction.Definition()
|
definition := customAction.Definition()
|
||||||
Expect(definition).To(Equal(ActionDefinition{
|
Expect(definition).To(Equal(types.ActionDefinition{
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"foo": {
|
"foo": {
|
||||||
Type: jsonschema.String,
|
Type: jsonschema.String,
|
||||||
@@ -75,7 +76,7 @@ return []string{"foo"}
|
|||||||
Description: "A test action",
|
Description: "A test action",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
runResult, err := customAction.Run(context.Background(), ActionParams{
|
runResult, err := customAction.Run(context.Background(), types.ActionParams{
|
||||||
"Foo": "bar",
|
"Foo": "bar",
|
||||||
})
|
})
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package action
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,16 +22,16 @@ type IntentResponse struct {
|
|||||||
Reasoning string `json:"reasoning"`
|
Reasoning string `json:"reasoning"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *IntentAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *IntentAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{}, nil
|
return types.ActionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *IntentAction) Plannable() bool {
|
func (a *IntentAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *IntentAction) Definition() ActionDefinition {
|
func (a *IntentAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "pick_tool",
|
Name: "pick_tool",
|
||||||
Description: "Pick a tool",
|
Description: "Pick a tool",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package action
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,16 +19,16 @@ type ConversationActionResponse struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ConversationAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *ConversationAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{}, nil
|
return types.ActionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ConversationAction) Plannable() bool {
|
func (a *ConversationAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ConversationAction) Definition() ActionDefinition {
|
func (a *ConversationAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: ConversationActionName,
|
Name: ConversationActionName,
|
||||||
Description: "Use this tool to initiate a new conversation or to notify something.",
|
Description: "Use this tool to initiate a new conversation or to notify something.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
// StopActionName is the name of the action
|
// StopActionName is the name of the action
|
||||||
// used by the LLM to stop any further action
|
// used by the LLM to stop any further action
|
||||||
@@ -12,16 +16,16 @@ func NewStop() *StopAction {
|
|||||||
|
|
||||||
type StopAction struct{}
|
type StopAction struct{}
|
||||||
|
|
||||||
func (a *StopAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *StopAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{}, nil
|
return types.ActionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StopAction) Plannable() bool {
|
func (a *StopAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StopAction) Definition() ActionDefinition {
|
func (a *StopAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: StopActionName,
|
Name: StopActionName,
|
||||||
Description: "Use this tool to stop any further action and stop the conversation. You must use this when it looks like there is a conclusion to the conversation or the topic diverged too much from the original conversation. For instance if the user offer his help and you already replied with a message, you can use this tool to stop the conversation.",
|
Description: "Use this tool to stop any further action and stop the conversation. You must use this when it looks like there is a conclusion to the conversation or the topic diverged too much from the original conversation. For instance if the user offer his help and you already replied with a message, you can use this tool to stop the conversation.",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package action
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,16 +30,16 @@ type PlanSubtask struct {
|
|||||||
Reasoning string `json:"reasoning"`
|
Reasoning string `json:"reasoning"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlanAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *PlanAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{}, nil
|
return types.ActionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlanAction) Plannable() bool {
|
func (a *PlanAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlanAction) Definition() ActionDefinition {
|
func (a *PlanAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: PlanActionName,
|
Name: PlanActionName,
|
||||||
Description: "The assistant for solving complex tasks that involves calling more functions in sequence, replies with the action.",
|
Description: "The assistant for solving complex tasks that involves calling more functions in sequence, replies with the action.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package action
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,16 +20,16 @@ type ReasoningResponse struct {
|
|||||||
Reasoning string `json:"reasoning"`
|
Reasoning string `json:"reasoning"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ReasoningAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *ReasoningAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{}, nil
|
return types.ActionResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ReasoningAction) Plannable() bool {
|
func (a *ReasoningAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ReasoningAction) Definition() ActionDefinition {
|
func (a *ReasoningAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "pick_action",
|
Name: "pick_action",
|
||||||
Description: "try to understand what's the best thing to do and pick an action with a reasoning",
|
Description: "try to understand what's the best thing to do and pick an action with a reasoning",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package action
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ type ReplyResponse struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ReplyAction) Run(context.Context, ActionParams) (string, error) {
|
func (a *ReplyAction) Run(context.Context, types.ActionParams) (string, error) {
|
||||||
return "no-op", nil
|
return "no-op", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,8 +30,8 @@ func (a *ReplyAction) Plannable() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ReplyAction) Definition() ActionDefinition {
|
func (a *ReplyAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: ReplyActionName,
|
Name: ReplyActionName,
|
||||||
Description: "Use this tool to reply to the user once we have all the informations we need.",
|
Description: "Use this tool to reply to the user once we have all the informations we need.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,16 +34,16 @@ type AgentInternalState struct {
|
|||||||
Goal string `json:"goal"`
|
Goal string `json:"goal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAction) Run(context.Context, ActionParams) (ActionResult, error) {
|
func (a *StateAction) Run(context.Context, types.ActionParams) (types.ActionResult, error) {
|
||||||
return ActionResult{Result: "internal state has been updated"}, nil
|
return types.ActionResult{Result: "internal state has been updated"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAction) Plannable() bool {
|
func (a *StateAction) Plannable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *StateAction) Definition() ActionDefinition {
|
func (a *StateAction) Definition() types.ActionDefinition {
|
||||||
return ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: StateActionName,
|
Name: StateActionName,
|
||||||
Description: "update the agent state (short memory) with the current state of the conversation.",
|
Description: "update the agent state (short memory) with the current state of the conversation.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -7,53 +7,15 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/action"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionState struct {
|
|
||||||
ActionCurrentState
|
|
||||||
action.ActionResult
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActionCurrentState struct {
|
|
||||||
Action Action
|
|
||||||
Params action.ActionParams
|
|
||||||
Reasoning string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions is something the agent can do
|
|
||||||
type Action interface {
|
|
||||||
Run(ctx context.Context, action action.ActionParams) (action.ActionResult, error)
|
|
||||||
Definition() action.ActionDefinition
|
|
||||||
Plannable() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Actions []Action
|
|
||||||
|
|
||||||
func (a Actions) ToTools() []openai.Tool {
|
|
||||||
tools := []openai.Tool{}
|
|
||||||
for _, action := range a {
|
|
||||||
tools = append(tools, openai.Tool{
|
|
||||||
Type: openai.ToolTypeFunction,
|
|
||||||
Function: action.Definition().ToFunctionDefinition(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return tools
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Actions) Find(name string) Action {
|
|
||||||
for _, action := range a {
|
|
||||||
if action.Definition().Name.Is(name) {
|
|
||||||
return action
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type decisionResult struct {
|
type decisionResult struct {
|
||||||
actionParams action.ActionParams
|
actionParams types.ActionParams
|
||||||
message string
|
message string
|
||||||
actioName string
|
actioName string
|
||||||
}
|
}
|
||||||
@@ -85,7 +47,7 @@ func (a *Agent) decision(
|
|||||||
return &decisionResult{message: msg.Content}, nil
|
return &decisionResult{message: msg.Content}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
params := action.ActionParams{}
|
params := types.ActionParams{}
|
||||||
if err := params.Read(msg.ToolCalls[0].Function.Arguments); err != nil {
|
if err := params.Read(msg.ToolCalls[0].Function.Arguments); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -173,7 +135,7 @@ func (m Messages) IsLastMessageFromRole(role string) bool {
|
|||||||
return m[len(m)-1].Role == role
|
return m[len(m)-1].Role == role
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) generateParameters(ctx context.Context, pickTemplate string, act Action, c []openai.ChatCompletionMessage, reasoning string) (*decisionResult, error) {
|
func (a *Agent) generateParameters(ctx context.Context, pickTemplate string, act types.Action, c []openai.ChatCompletionMessage, reasoning string) (*decisionResult, error) {
|
||||||
|
|
||||||
stateHUD, err := renderTemplate(pickTemplate, a.prepareHUD(), a.availableActions(), reasoning)
|
stateHUD, err := renderTemplate(pickTemplate, a.prepareHUD(), a.availableActions(), reasoning)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -212,7 +174,7 @@ func (a *Agent) generateParameters(ctx context.Context, pickTemplate string, act
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) handlePlanning(ctx context.Context, job *Job, chosenAction Action, actionParams action.ActionParams, reasoning string, pickTemplate string) error {
|
func (a *Agent) handlePlanning(ctx context.Context, job *types.Job, chosenAction types.Action, actionParams types.ActionParams, reasoning string, pickTemplate string) error {
|
||||||
// Planning: run all the actions in sequence
|
// Planning: run all the actions in sequence
|
||||||
if !chosenAction.Definition().Name.Is(action.PlanActionName) {
|
if !chosenAction.Definition().Name.Is(action.PlanActionName) {
|
||||||
xlog.Debug("no plan action")
|
xlog.Debug("no plan action")
|
||||||
@@ -225,9 +187,17 @@ func (a *Agent) handlePlanning(ctx context.Context, job *Job, chosenAction Actio
|
|||||||
return fmt.Errorf("error unmarshalling plan result: %w", err)
|
return fmt.Errorf("error unmarshalling plan result: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateResult := ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, action.ActionResult{
|
stateResult := types.ActionState{
|
||||||
Result: fmt.Sprintf("planning %s, subtasks: %+v", planResult.Goal, planResult.Subtasks),
|
ActionCurrentState: types.ActionCurrentState{
|
||||||
}}
|
Job: job,
|
||||||
|
Action: chosenAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: reasoning,
|
||||||
|
},
|
||||||
|
ActionResult: types.ActionResult{
|
||||||
|
Result: fmt.Sprintf("planning %s, subtasks: %+v", planResult.Goal, planResult.Subtasks),
|
||||||
|
},
|
||||||
|
}
|
||||||
job.Result.SetResult(stateResult)
|
job.Result.SetResult(stateResult)
|
||||||
job.CallbackWithResult(stateResult)
|
job.CallbackWithResult(stateResult)
|
||||||
|
|
||||||
@@ -258,8 +228,23 @@ func (a *Agent) handlePlanning(ctx context.Context, job *Job, chosenAction Actio
|
|||||||
}
|
}
|
||||||
actionParams = params.actionParams
|
actionParams = params.actionParams
|
||||||
|
|
||||||
if !job.Callback(ActionCurrentState{subTaskAction, actionParams, subTaskReasoning}) {
|
if !job.Callback(types.ActionCurrentState{
|
||||||
job.Result.SetResult(ActionState{ActionCurrentState{chosenAction, actionParams, subTaskReasoning}, action.ActionResult{Result: "stopped by callback"}})
|
Job: job,
|
||||||
|
Action: subTaskAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: subTaskReasoning,
|
||||||
|
}) {
|
||||||
|
job.Result.SetResult(types.ActionState{
|
||||||
|
ActionCurrentState: types.ActionCurrentState{
|
||||||
|
Job: job,
|
||||||
|
Action: chosenAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: subTaskReasoning,
|
||||||
|
},
|
||||||
|
ActionResult: types.ActionResult{
|
||||||
|
Result: "stopped by callback",
|
||||||
|
},
|
||||||
|
})
|
||||||
job.Result.Conversation = a.currentConversation
|
job.Result.Conversation = a.currentConversation
|
||||||
job.Result.Finish(nil)
|
job.Result.Finish(nil)
|
||||||
break
|
break
|
||||||
@@ -270,7 +255,15 @@ func (a *Agent) handlePlanning(ctx context.Context, job *Job, chosenAction Actio
|
|||||||
return fmt.Errorf("error running action: %w", err)
|
return fmt.Errorf("error running action: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateResult := ActionState{ActionCurrentState{subTaskAction, actionParams, subTaskReasoning}, result}
|
stateResult := types.ActionState{
|
||||||
|
ActionCurrentState: types.ActionCurrentState{
|
||||||
|
Job: job,
|
||||||
|
Action: subTaskAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: subTaskReasoning,
|
||||||
|
},
|
||||||
|
ActionResult: result,
|
||||||
|
}
|
||||||
job.Result.SetResult(stateResult)
|
job.Result.SetResult(stateResult)
|
||||||
job.CallbackWithResult(stateResult)
|
job.CallbackWithResult(stateResult)
|
||||||
xlog.Debug("[subtask] Action executed", "agent", a.Character.Name, "action", subTaskAction.Definition().Name, "result", result)
|
xlog.Debug("[subtask] Action executed", "agent", a.Character.Name, "action", subTaskAction.Definition().Name, "result", result)
|
||||||
@@ -280,10 +273,10 @@ func (a *Agent) handlePlanning(ctx context.Context, job *Job, chosenAction Actio
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) availableActions() Actions {
|
func (a *Agent) availableActions() types.Actions {
|
||||||
// defaultActions := append(a.options.userActions, action.NewReply())
|
// defaultActions := append(a.options.userActions, action.NewReply())
|
||||||
|
|
||||||
addPlanAction := func(actions Actions) Actions {
|
addPlanAction := func(actions types.Actions) types.Actions {
|
||||||
if !a.options.canPlan {
|
if !a.options.canPlan {
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
@@ -341,7 +334,7 @@ func (a *Agent) prepareHUD() (promptHUD *PromptHUD) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pickAction picks an action based on the conversation
|
// pickAction picks an action based on the conversation
|
||||||
func (a *Agent) pickAction(ctx context.Context, templ string, messages []openai.ChatCompletionMessage) (Action, action.ActionParams, string, error) {
|
func (a *Agent) pickAction(ctx context.Context, templ string, messages []openai.ChatCompletionMessage) (types.Action, types.ActionParams, string, error) {
|
||||||
c := messages
|
c := messages
|
||||||
|
|
||||||
if !a.options.forceReasoning {
|
if !a.options.forceReasoning {
|
||||||
@@ -390,7 +383,7 @@ func (a *Agent) pickAction(ctx context.Context, templ string, messages []openai.
|
|||||||
// and then use the reply to get the action
|
// and then use the reply to get the action
|
||||||
thought, err := a.decision(ctx,
|
thought, err := a.decision(ctx,
|
||||||
c,
|
c,
|
||||||
Actions{action.NewReasoning()}.ToTools(),
|
types.Actions{action.NewReasoning()}.ToTools(),
|
||||||
action.NewReasoning().Definition().Name)
|
action.NewReasoning().Definition().Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
@@ -421,7 +414,7 @@ func (a *Agent) pickAction(ctx context.Context, templ string, messages []openai.
|
|||||||
Role: "system",
|
Role: "system",
|
||||||
Content: "Given the assistant thought, pick the relevant action: " + reason,
|
Content: "Given the assistant thought, pick the relevant action: " + reason,
|
||||||
}),
|
}),
|
||||||
Actions{intentionsTools}.ToTools(),
|
types.Actions{intentionsTools}.ToTools(),
|
||||||
intentionsTools.Definition().Name)
|
intentionsTools.Definition().Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", fmt.Errorf("failed to get the action tool parameters: %v", err)
|
return nil, nil, "", fmt.Errorf("failed to get the action tool parameters: %v", err)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/action"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/llm"
|
"github.com/mudler/LocalAgent/pkg/llm"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
)
|
)
|
||||||
@@ -25,21 +26,21 @@ type Agent struct {
|
|||||||
options *options
|
options *options
|
||||||
Character Character
|
Character Character
|
||||||
client *openai.Client
|
client *openai.Client
|
||||||
jobQueue chan *Job
|
jobQueue chan *types.Job
|
||||||
actionContext *action.ActionContext
|
actionContext *types.ActionContext
|
||||||
context *action.ActionContext
|
context *types.ActionContext
|
||||||
|
|
||||||
currentReasoning string
|
currentReasoning string
|
||||||
currentState *action.AgentInternalState
|
currentState *action.AgentInternalState
|
||||||
nextAction Action
|
nextAction types.Action
|
||||||
nextActionParams *action.ActionParams
|
nextActionParams *types.ActionParams
|
||||||
currentConversation Messages
|
currentConversation Messages
|
||||||
selfEvaluationInProgress bool
|
selfEvaluationInProgress bool
|
||||||
pause bool
|
pause bool
|
||||||
|
|
||||||
newConversations chan openai.ChatCompletionMessage
|
newConversations chan openai.ChatCompletionMessage
|
||||||
|
|
||||||
mcpActions Actions
|
mcpActions types.Actions
|
||||||
}
|
}
|
||||||
|
|
||||||
type RAGDB interface {
|
type RAGDB interface {
|
||||||
@@ -64,12 +65,12 @@ func New(opts ...Option) (*Agent, error) {
|
|||||||
|
|
||||||
ctx, cancel := context.WithCancel(c)
|
ctx, cancel := context.WithCancel(c)
|
||||||
a := &Agent{
|
a := &Agent{
|
||||||
jobQueue: make(chan *Job),
|
jobQueue: make(chan *types.Job),
|
||||||
options: options,
|
options: options,
|
||||||
client: client,
|
client: client,
|
||||||
Character: options.character,
|
Character: options.character,
|
||||||
currentState: &action.AgentInternalState{},
|
currentState: &action.AgentInternalState{},
|
||||||
context: action.NewContext(ctx, cancel),
|
context: types.NewActionContext(ctx, cancel),
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.options.statefile != "" {
|
if a.options.statefile != "" {
|
||||||
@@ -130,18 +131,18 @@ func (a *Agent) ConversationChannel() chan openai.ChatCompletionMessage {
|
|||||||
|
|
||||||
// Ask is a pre-emptive, blocking call that returns the response as soon as it's ready.
|
// Ask is a pre-emptive, blocking call that returns the response as soon as it's ready.
|
||||||
// It discards any other computation.
|
// It discards any other computation.
|
||||||
func (a *Agent) Ask(opts ...JobOption) *JobResult {
|
func (a *Agent) Ask(opts ...types.JobOption) *types.JobResult {
|
||||||
xlog.Debug("Agent Ask()", "agent", a.Character.Name, "model", a.options.LLMAPI.Model)
|
xlog.Debug("Agent Ask()", "agent", a.Character.Name, "model", a.options.LLMAPI.Model)
|
||||||
defer func() {
|
defer func() {
|
||||||
xlog.Debug("Agent has finished being asked", "agent", a.Character.Name)
|
xlog.Debug("Agent has finished being asked", "agent", a.Character.Name)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//a.StopAction()
|
//a.StopAction()
|
||||||
j := NewJob(
|
j := types.NewJob(
|
||||||
append(
|
append(
|
||||||
opts,
|
opts,
|
||||||
WithReasoningCallback(a.options.reasoningCallback),
|
types.WithReasoningCallback(a.options.reasoningCallback),
|
||||||
WithResultCallback(a.options.resultCallback),
|
types.WithResultCallback(a.options.resultCallback),
|
||||||
)...,
|
)...,
|
||||||
)
|
)
|
||||||
a.jobQueue <- j
|
a.jobQueue <- j
|
||||||
@@ -224,12 +225,12 @@ func (a *Agent) Memory() RAGDB {
|
|||||||
return a.options.ragdb
|
return a.options.ragdb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (result action.ActionResult, err error) {
|
func (a *Agent) runAction(chosenAction types.Action, params types.ActionParams) (result types.ActionResult, err error) {
|
||||||
for _, act := range a.availableActions() {
|
for _, act := range a.availableActions() {
|
||||||
if act.Definition().Name == chosenAction.Definition().Name {
|
if act.Definition().Name == chosenAction.Definition().Name {
|
||||||
res, err := act.Run(a.actionContext, params)
|
res, err := act.Run(a.actionContext, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, fmt.Errorf("error running action: %w", err)
|
return types.ActionResult{}, fmt.Errorf("error running action: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = res
|
result = res
|
||||||
@@ -244,7 +245,7 @@ func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (resu
|
|||||||
|
|
||||||
err = params.Unmarshal(&state)
|
err = params.Unmarshal(&state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, fmt.Errorf("error unmarshalling state of the agent: %w", err)
|
return types.ActionResult{}, fmt.Errorf("error unmarshalling state of the agent: %w", err)
|
||||||
}
|
}
|
||||||
// update the current state with the one we just got from the action
|
// update the current state with the one we just got from the action
|
||||||
a.currentState = &state
|
a.currentState = &state
|
||||||
@@ -252,7 +253,7 @@ func (a *Agent) runAction(chosenAction Action, params action.ActionParams) (resu
|
|||||||
// update the state file
|
// update the state file
|
||||||
if a.options.statefile != "" {
|
if a.options.statefile != "" {
|
||||||
if err := a.SaveState(a.options.statefile); err != nil {
|
if err := a.SaveState(a.options.statefile); err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +349,7 @@ func extractImageContent(message openai.ChatCompletionMessage) (imageURL, text s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) processUserInputs(job *Job, role string) {
|
func (a *Agent) processUserInputs(job *types.Job, role string) {
|
||||||
|
|
||||||
noNewMessage := job.Text == "" && job.Image == ""
|
noNewMessage := job.Text == "" && job.Image == ""
|
||||||
onlyText := job.Text != "" && job.Image == ""
|
onlyText := job.Text != "" && job.Image == ""
|
||||||
@@ -434,7 +435,7 @@ func (a *Agent) processUserInputs(job *Job, role string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) consumeJob(job *Job, role string) {
|
func (a *Agent) consumeJob(job *types.Job, role string) {
|
||||||
a.Lock()
|
a.Lock()
|
||||||
paused := a.pause
|
paused := a.pause
|
||||||
a.Unlock()
|
a.Unlock()
|
||||||
@@ -451,10 +452,10 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
a.Lock()
|
a.Lock()
|
||||||
// Set the action context
|
// Set the action context
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
a.actionContext = action.NewContext(ctx, cancel)
|
a.actionContext = types.NewActionContext(ctx, cancel)
|
||||||
a.selfEvaluationInProgress = selfEvaluation
|
a.selfEvaluationInProgress = selfEvaluation
|
||||||
if len(job.conversationHistory) != 0 {
|
if len(job.ConversationHistory) != 0 {
|
||||||
a.currentConversation = job.conversationHistory
|
a.currentConversation = job.ConversationHistory
|
||||||
}
|
}
|
||||||
a.Unlock()
|
a.Unlock()
|
||||||
|
|
||||||
@@ -493,9 +494,9 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// choose an action first
|
// choose an action first
|
||||||
var chosenAction Action
|
var chosenAction types.Action
|
||||||
var reasoning string
|
var reasoning string
|
||||||
var actionParams action.ActionParams
|
var actionParams types.ActionParams
|
||||||
|
|
||||||
if a.nextAction != nil {
|
if a.nextAction != nil {
|
||||||
// if we are being re-evaluated, we already have the action
|
// if we are being re-evaluated, we already have the action
|
||||||
@@ -576,8 +577,19 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !job.Callback(ActionCurrentState{chosenAction, actionParams, reasoning}) {
|
if !job.Callback(types.ActionCurrentState{
|
||||||
job.Result.SetResult(ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, action.ActionResult{Result: "stopped by callback"}})
|
Job: job,
|
||||||
|
Action: chosenAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: reasoning}) {
|
||||||
|
job.Result.SetResult(types.ActionState{
|
||||||
|
ActionCurrentState: types.ActionCurrentState{
|
||||||
|
Job: job,
|
||||||
|
Action: chosenAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: reasoning,
|
||||||
|
},
|
||||||
|
ActionResult: types.ActionResult{Result: "stopped by callback"}})
|
||||||
job.Result.Conversation = a.currentConversation
|
job.Result.Conversation = a.currentConversation
|
||||||
job.Result.Finish(nil)
|
job.Result.Finish(nil)
|
||||||
return
|
return
|
||||||
@@ -622,7 +634,15 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
result.Result = fmt.Sprintf("Error running tool: %v", err)
|
result.Result = fmt.Sprintf("Error running tool: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateResult := ActionState{ActionCurrentState{chosenAction, actionParams, reasoning}, result}
|
stateResult := types.ActionState{
|
||||||
|
ActionCurrentState: types.ActionCurrentState{
|
||||||
|
Job: job,
|
||||||
|
Action: chosenAction,
|
||||||
|
Params: actionParams,
|
||||||
|
Reasoning: reasoning,
|
||||||
|
},
|
||||||
|
ActionResult: result,
|
||||||
|
}
|
||||||
job.Result.SetResult(stateResult)
|
job.Result.SetResult(stateResult)
|
||||||
job.CallbackWithResult(stateResult)
|
job.CallbackWithResult(stateResult)
|
||||||
xlog.Debug("Action executed", "agent", a.Character.Name, "action", chosenAction.Definition().Name, "result", result)
|
xlog.Debug("Action executed", "agent", a.Character.Name, "action", chosenAction.Definition().Name, "result", result)
|
||||||
@@ -781,7 +801,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
job.Result.Finish(nil)
|
job.Result.Finish(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) addFunctionResultToConversation(chosenAction Action, actionParams action.ActionParams, result action.ActionResult) {
|
func (a *Agent) addFunctionResultToConversation(chosenAction types.Action, actionParams types.ActionParams, result types.ActionResult) {
|
||||||
// calling the function
|
// calling the function
|
||||||
a.currentConversation = append(a.currentConversation, openai.ChatCompletionMessage{
|
a.currentConversation = append(a.currentConversation, openai.ChatCompletionMessage{
|
||||||
Role: "assistant",
|
Role: "assistant",
|
||||||
@@ -847,10 +867,10 @@ func (a *Agent) periodicallyRun(timer *time.Timer) {
|
|||||||
// - asking the agent to do something else based on the result
|
// - asking the agent to do something else based on the result
|
||||||
|
|
||||||
// whatNext := NewJob(WithText("Decide what to do based on the state"))
|
// whatNext := NewJob(WithText("Decide what to do based on the state"))
|
||||||
whatNext := NewJob(
|
whatNext := types.NewJob(
|
||||||
WithText(innerMonologueTemplate),
|
types.WithText(innerMonologueTemplate),
|
||||||
WithReasoningCallback(a.options.reasoningCallback),
|
types.WithReasoningCallback(a.options.reasoningCallback),
|
||||||
WithResultCallback(a.options.resultCallback),
|
types.WithResultCallback(a.options.resultCallback),
|
||||||
)
|
)
|
||||||
a.consumeJob(whatNext, SystemRole)
|
a.consumeJob(whatNext, SystemRole)
|
||||||
a.ResetConversation()
|
a.ResetConversation()
|
||||||
@@ -913,7 +933,7 @@ func (a *Agent) Run() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) loop(timer *time.Timer, job *Job) {
|
func (a *Agent) loop(timer *time.Timer, job *types.Job) {
|
||||||
// Remember always to reset the timer - if we don't the agent will stop..
|
// Remember always to reset the timer - if we don't the agent will stop..
|
||||||
defer timer.Reset(a.options.periodicRuns)
|
defer timer.Reset(a.options.periodicRuns)
|
||||||
// Consume the job and generate a response
|
// Consume the job and generate a response
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/actions"
|
"github.com/mudler/LocalAgent/services/actions"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
|
||||||
. "github.com/mudler/LocalAgent/core/agent"
|
. "github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
@@ -19,14 +19,14 @@ const testActionResult = "In Boston it's 30C today, it's sunny, and humidity is
|
|||||||
const testActionResult2 = "In milan it's very hot today, it is 45C and the humidity is at 200%"
|
const testActionResult2 = "In milan it's very hot today, it is 45C and the humidity is at 200%"
|
||||||
const testActionResult3 = "In paris it's very cold today, it is 2C and the humidity is at 10%"
|
const testActionResult3 = "In paris it's very cold today, it is 2C and the humidity is at 10%"
|
||||||
|
|
||||||
var _ Action = &TestAction{}
|
var _ types.Action = &TestAction{}
|
||||||
|
|
||||||
var debugOptions = []JobOption{
|
var debugOptions = []types.JobOption{
|
||||||
WithReasoningCallback(func(state ActionCurrentState) bool {
|
types.WithReasoningCallback(func(state types.ActionCurrentState) bool {
|
||||||
xlog.Info("Reasoning", state)
|
xlog.Info("Reasoning", state)
|
||||||
return true
|
return true
|
||||||
}),
|
}),
|
||||||
WithResultCallback(func(state ActionState) {
|
types.WithResultCallback(func(state types.ActionState) {
|
||||||
xlog.Info("Reasoning", state.Reasoning)
|
xlog.Info("Reasoning", state.Reasoning)
|
||||||
xlog.Info("Action", state.Action)
|
xlog.Info("Action", state.Action)
|
||||||
xlog.Info("Result", state.Result)
|
xlog.Info("Result", state.Result)
|
||||||
@@ -41,18 +41,18 @@ func (a *TestAction) Plannable() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *TestAction) Run(c context.Context, p action.ActionParams) (action.ActionResult, error) {
|
func (a *TestAction) Run(c context.Context, p types.ActionParams) (types.ActionResult, error) {
|
||||||
for k, r := range a.response {
|
for k, r := range a.response {
|
||||||
if strings.Contains(strings.ToLower(p.String()), strings.ToLower(k)) {
|
if strings.Contains(strings.ToLower(p.String()), strings.ToLower(k)) {
|
||||||
return action.ActionResult{Result: r}, nil
|
return types.ActionResult{Result: r}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: "No match"}, nil
|
return types.ActionResult{Result: "No match"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *TestAction) Definition() action.ActionDefinition {
|
func (a *TestAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "get_weather",
|
Name: "get_weather",
|
||||||
Description: "get current weather",
|
Description: "get current weather",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
@@ -74,8 +74,8 @@ type FakeStoreResultAction struct {
|
|||||||
TestAction
|
TestAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FakeStoreResultAction) Definition() action.ActionDefinition {
|
func (a *FakeStoreResultAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "store_results",
|
Name: "store_results",
|
||||||
Description: "store results permanently. Use this tool after you have a result you want to keep.",
|
Description: "store results permanently. Use this tool after you have a result you want to keep.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
@@ -93,8 +93,8 @@ type FakeInternetAction struct {
|
|||||||
TestAction
|
TestAction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FakeInternetAction) Definition() action.ActionDefinition {
|
func (a *FakeInternetAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "search_internet",
|
Name: "search_internet",
|
||||||
Description: "search on internet",
|
Description: "search on internet",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
@@ -127,7 +127,7 @@ var _ = Describe("Agent test", func() {
|
|||||||
|
|
||||||
res := agent.Ask(
|
res := agent.Ask(
|
||||||
append(debugOptions,
|
append(debugOptions,
|
||||||
WithText("what's the weather in Boston and Milano? Use celsius units"),
|
types.WithText("what's the weather in Boston and Milano? Use celsius units"),
|
||||||
)...,
|
)...,
|
||||||
)
|
)
|
||||||
Expect(res.Error).ToNot(HaveOccurred())
|
Expect(res.Error).ToNot(HaveOccurred())
|
||||||
@@ -142,7 +142,7 @@ var _ = Describe("Agent test", func() {
|
|||||||
|
|
||||||
res = agent.Ask(
|
res = agent.Ask(
|
||||||
append(debugOptions,
|
append(debugOptions,
|
||||||
WithText("Now I want to know the weather in Paris, always use celsius units"),
|
types.WithText("Now I want to know the weather in Paris, always use celsius units"),
|
||||||
)...)
|
)...)
|
||||||
for _, r := range res.State {
|
for _, r := range res.State {
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ var _ = Describe("Agent test", func() {
|
|||||||
defer agent.Stop()
|
defer agent.Stop()
|
||||||
res := agent.Ask(
|
res := agent.Ask(
|
||||||
append(debugOptions,
|
append(debugOptions,
|
||||||
WithText("can you get the weather in boston? Use celsius units"))...,
|
types.WithText("can you get the weather in boston? Use celsius units"))...,
|
||||||
)
|
)
|
||||||
reasons := []string{}
|
reasons := []string{}
|
||||||
for _, r := range res.State {
|
for _, r := range res.State {
|
||||||
@@ -196,7 +196,7 @@ var _ = Describe("Agent test", func() {
|
|||||||
defer agent.Stop()
|
defer agent.Stop()
|
||||||
|
|
||||||
result := agent.Ask(
|
result := agent.Ask(
|
||||||
WithText("Update your goals such as you want to learn to play the guitar"),
|
types.WithText("Update your goals such as you want to learn to play the guitar"),
|
||||||
)
|
)
|
||||||
fmt.Printf("%+v\n", result)
|
fmt.Printf("%+v\n", result)
|
||||||
Expect(result.Error).ToNot(HaveOccurred())
|
Expect(result.Error).ToNot(HaveOccurred())
|
||||||
@@ -221,7 +221,7 @@ var _ = Describe("Agent test", func() {
|
|||||||
defer agent.Stop()
|
defer agent.Stop()
|
||||||
|
|
||||||
result := agent.Ask(
|
result := agent.Ask(
|
||||||
WithText("plan a trip to San Francisco from Venice, Italy"),
|
types.WithText("plan a trip to San Francisco from Venice, Italy"),
|
||||||
)
|
)
|
||||||
Expect(len(result.State)).To(BeNumerically(">", 1))
|
Expect(len(result.State)).To(BeNumerically(">", 1))
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import (
|
|||||||
|
|
||||||
mcp "github.com/metoro-io/mcp-golang"
|
mcp "github.com/metoro-io/mcp-golang"
|
||||||
"github.com/metoro-io/mcp-golang/transport/http"
|
"github.com/metoro-io/mcp-golang/transport/http"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Action = &mcpAction{}
|
var _ types.Action = &mcpAction{}
|
||||||
|
|
||||||
type MCPServer struct {
|
type MCPServer struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
@@ -30,11 +30,11 @@ func (a *mcpAction) Plannable() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mcpAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (m *mcpAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
resp, err := m.mcpClient.CallTool(ctx, m.toolName, params)
|
resp, err := m.mcpClient.CallTool(ctx, m.toolName, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
xlog.Error("Failed to call tool", "error", err.Error())
|
xlog.Error("Failed to call tool", "error", err.Error())
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
xlog.Debug("MCP response", "response", resp)
|
xlog.Debug("MCP response", "response", resp)
|
||||||
@@ -51,12 +51,12 @@ func (m *mcpAction) Run(ctx context.Context, params action.ActionParams) (action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{
|
return types.ActionResult{
|
||||||
Result: textResult,
|
Result: textResult,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mcpAction) Definition() action.ActionDefinition {
|
func (m *mcpAction) Definition() types.ActionDefinition {
|
||||||
props := map[string]jsonschema.Definition{}
|
props := map[string]jsonschema.Definition{}
|
||||||
dat, err := json.Marshal(m.inputSchema.Properties)
|
dat, err := json.Marshal(m.inputSchema.Properties)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -64,8 +64,8 @@ func (m *mcpAction) Definition() action.ActionDefinition {
|
|||||||
}
|
}
|
||||||
json.Unmarshal(dat, &props)
|
json.Unmarshal(dat, &props)
|
||||||
|
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(m.toolName),
|
Name: types.ActionDefinitionName(m.toolName),
|
||||||
Description: m.toolDescription,
|
Description: m.toolDescription,
|
||||||
Required: m.inputSchema.Required,
|
Required: m.inputSchema.Required,
|
||||||
//Properties: ,
|
//Properties: ,
|
||||||
@@ -84,7 +84,7 @@ func (a *Agent) initMCPActions() error {
|
|||||||
a.mcpActions = nil
|
a.mcpActions = nil
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
generatedActions := Actions{}
|
generatedActions := types.Actions{}
|
||||||
|
|
||||||
for _, mcpServer := range a.options.mcpServers {
|
for _, mcpServer := range a.options.mcpServers {
|
||||||
transport := http.NewHTTPClientTransport("/mcp")
|
transport := http.NewHTTPClientTransport("/mcp")
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option func(*options) error
|
type Option func(*options) error
|
||||||
@@ -20,7 +22,7 @@ type options struct {
|
|||||||
character Character
|
character Character
|
||||||
randomIdentityGuidance string
|
randomIdentityGuidance string
|
||||||
randomIdentity bool
|
randomIdentity bool
|
||||||
userActions Actions
|
userActions types.Actions
|
||||||
enableHUD, standaloneJob, showCharacter, enableKB, enableSummaryMemory, enableLongTermMemory bool
|
enableHUD, standaloneJob, showCharacter, enableKB, enableSummaryMemory, enableLongTermMemory bool
|
||||||
|
|
||||||
canStopItself bool
|
canStopItself bool
|
||||||
@@ -41,8 +43,8 @@ type options struct {
|
|||||||
systemPrompt string
|
systemPrompt string
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
reasoningCallback func(ActionCurrentState) bool
|
reasoningCallback func(types.ActionCurrentState) bool
|
||||||
resultCallback func(ActionState)
|
resultCallback func(types.ActionState)
|
||||||
|
|
||||||
conversationsPath string
|
conversationsPath string
|
||||||
|
|
||||||
@@ -262,14 +264,14 @@ func WithContext(ctx context.Context) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithAgentReasoningCallback(cb func(ActionCurrentState) bool) Option {
|
func WithAgentReasoningCallback(cb func(types.ActionCurrentState) bool) Option {
|
||||||
return func(o *options) error {
|
return func(o *options) error {
|
||||||
o.reasoningCallback = cb
|
o.reasoningCallback = cb
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithAgentResultCallback(cb func(ActionState)) Option {
|
func WithAgentResultCallback(cb func(types.ActionState)) Option {
|
||||||
return func(o *options) error {
|
return func(o *options) error {
|
||||||
o.resultCallback = cb
|
o.resultCallback = cb
|
||||||
return nil
|
return nil
|
||||||
@@ -310,7 +312,7 @@ func WithRandomIdentity(guidance ...string) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithActions(actions ...Action) Option {
|
func WithActions(actions ...types.Action) Option {
|
||||||
return func(o *options) error {
|
return func(o *options) error {
|
||||||
o.userActions = actions
|
o.userActions = actions
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"html/template"
|
"html/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
)
|
)
|
||||||
|
|
||||||
func renderTemplate(templ string, hud *PromptHUD, actions Actions, reasoning string) (string, error) {
|
func renderTemplate(templ string, hud *PromptHUD, actions types.Actions, reasoning string) (string, error) {
|
||||||
// prepare the prompt
|
// prepare the prompt
|
||||||
prompt := bytes.NewBuffer([]byte{})
|
prompt := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
@@ -19,14 +19,14 @@ func renderTemplate(templ string, hud *PromptHUD, actions Actions, reasoning str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all the actions definitions
|
// Get all the actions definitions
|
||||||
definitions := []action.ActionDefinition{}
|
definitions := []types.ActionDefinition{}
|
||||||
for _, m := range actions {
|
for _, m := range actions {
|
||||||
definitions = append(definitions, m.Definition())
|
definitions = append(definitions, m.Definition())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = promptTemplate.Execute(prompt, struct {
|
err = promptTemplate.Execute(prompt, struct {
|
||||||
HUD *PromptHUD
|
HUD *PromptHUD
|
||||||
Actions []action.ActionDefinition
|
Actions []types.ActionDefinition
|
||||||
Reasoning string
|
Reasoning string
|
||||||
Messages []openai.ChatCompletionMessage
|
Messages []openai.ChatCompletionMessage
|
||||||
Time string
|
Time string
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectorConfig struct {
|
type ConnectorConfig struct {
|
||||||
@@ -61,7 +62,7 @@ type AgentConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Connector interface {
|
type Connector interface {
|
||||||
AgentResultCallback() func(state agent.ActionState)
|
AgentResultCallback() func(state types.ActionState)
|
||||||
AgentReasoningCallback() func(state agent.ActionCurrentState) bool
|
AgentReasoningCallback() func(state types.ActionCurrentState) bool
|
||||||
Start(a *agent.Agent)
|
Start(a *agent.Agent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
|
||||||
. "github.com/mudler/LocalAgent/core/agent"
|
. "github.com/mudler/LocalAgent/core/agent"
|
||||||
"github.com/mudler/LocalAgent/core/sse"
|
"github.com/mudler/LocalAgent/core/sse"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/llm"
|
"github.com/mudler/LocalAgent/pkg/llm"
|
||||||
"github.com/mudler/LocalAgent/pkg/localrag"
|
"github.com/mudler/LocalAgent/pkg/localrag"
|
||||||
"github.com/mudler/LocalAgent/pkg/utils"
|
"github.com/mudler/LocalAgent/pkg/utils"
|
||||||
@@ -26,25 +26,26 @@ import (
|
|||||||
|
|
||||||
type AgentPool struct {
|
type AgentPool struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
file string
|
file string
|
||||||
pooldir string
|
pooldir string
|
||||||
pool AgentPoolData
|
pool AgentPoolData
|
||||||
agents map[string]*Agent
|
agents map[string]*Agent
|
||||||
managers map[string]sse.Manager
|
managers map[string]sse.Manager
|
||||||
agentStatus map[string]*Status
|
agentStatus map[string]*Status
|
||||||
apiURL, defaultModel, defaultMultimodalModel, imageModel, localRAGAPI, localRAGKey, apiKey string
|
apiURL, defaultModel, defaultMultimodalModel string
|
||||||
availableActions func(*AgentConfig) func(ctx context.Context, pool *AgentPool) []Action
|
imageModel, localRAGAPI, localRAGKey, apiKey string
|
||||||
connectors func(*AgentConfig) []Connector
|
availableActions func(*AgentConfig) func(ctx context.Context, pool *AgentPool) []types.Action
|
||||||
promptBlocks func(*AgentConfig) []PromptBlock
|
connectors func(*AgentConfig) []Connector
|
||||||
timeout string
|
promptBlocks func(*AgentConfig) []PromptBlock
|
||||||
conversationLogs string
|
timeout string
|
||||||
|
conversationLogs string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
ActionResults []ActionState
|
ActionResults []types.ActionState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Status) addResult(result ActionState) {
|
func (s *Status) addResult(result types.ActionState) {
|
||||||
// If we have more than 10 results, remove the oldest one
|
// If we have more than 10 results, remove the oldest one
|
||||||
if len(s.ActionResults) > 10 {
|
if len(s.ActionResults) > 10 {
|
||||||
s.ActionResults = s.ActionResults[1:]
|
s.ActionResults = s.ActionResults[1:]
|
||||||
@@ -53,7 +54,7 @@ func (s *Status) addResult(result ActionState) {
|
|||||||
s.ActionResults = append(s.ActionResults, result)
|
s.ActionResults = append(s.ActionResults, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Status) Results() []ActionState {
|
func (s *Status) Results() []types.ActionState {
|
||||||
return s.ActionResults
|
return s.ActionResults
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ func loadPoolFromFile(path string) (*AgentPoolData, error) {
|
|||||||
func NewAgentPool(
|
func NewAgentPool(
|
||||||
defaultModel, defaultMultimodalModel, imageModel, apiURL, apiKey, directory string,
|
defaultModel, defaultMultimodalModel, imageModel, apiURL, apiKey, directory string,
|
||||||
LocalRAGAPI string,
|
LocalRAGAPI string,
|
||||||
availableActions func(*AgentConfig) func(ctx context.Context, pool *AgentPool) []agent.Action,
|
availableActions func(*AgentConfig) func(ctx context.Context, pool *AgentPool) []types.Action,
|
||||||
connectors func(*AgentConfig) []Connector,
|
connectors func(*AgentConfig) []Connector,
|
||||||
promptBlocks func(*AgentConfig) []PromptBlock,
|
promptBlocks func(*AgentConfig) []PromptBlock,
|
||||||
timeout string,
|
timeout string,
|
||||||
@@ -158,24 +159,24 @@ func (a *AgentPool) CreateAgent(name string, agentConfig *AgentConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(ac AgentConfig, pool *AgentPool) {
|
go func(ac AgentConfig) {
|
||||||
// Create the agent avatar
|
// Create the agent avatar
|
||||||
if err := a.createAgentAvatar(ac); err != nil {
|
if err := createAgentAvatar(a.apiURL, a.apiKey, a.defaultModel, a.imageModel, a.pooldir, ac); err != nil {
|
||||||
xlog.Error("Failed to create agent avatar", "error", err)
|
xlog.Error("Failed to create agent avatar", "error", err)
|
||||||
}
|
}
|
||||||
}(a.pool[name], a)
|
}(a.pool[name])
|
||||||
|
|
||||||
return a.startAgentWithConfig(name, agentConfig)
|
return a.startAgentWithConfig(name, agentConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AgentPool) createAgentAvatar(agent AgentConfig) error {
|
func createAgentAvatar(APIURL, APIKey, model, imageModel, avatarDir string, agent AgentConfig) error {
|
||||||
client := llm.NewClient(a.apiKey, a.apiURL+"/v1", "10m")
|
client := llm.NewClient(APIKey, APIURL+"/v1", "10m")
|
||||||
|
|
||||||
if a.imageModel == "" {
|
if imageModel == "" {
|
||||||
return fmt.Errorf("image model not set")
|
return fmt.Errorf("image model not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.defaultModel == "" {
|
if model == "" {
|
||||||
return fmt.Errorf("default model not set")
|
return fmt.Errorf("default model not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +186,9 @@ func (a *AgentPool) createAgentAvatar(agent AgentConfig) error {
|
|||||||
|
|
||||||
err := llm.GenerateTypedJSON(
|
err := llm.GenerateTypedJSON(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
llm.NewClient(a.apiKey, a.apiURL, "10m"),
|
llm.NewClient(APIKey, APIURL, "10m"),
|
||||||
"Generate a prompt that I can use to create a random avatar for the bot '"+agent.Name+"', the description of the bot is: "+agent.Description,
|
"Generate a prompt that I can use to create a random avatar for the bot '"+agent.Name+"', the description of the bot is: "+agent.Description,
|
||||||
a.defaultModel,
|
model,
|
||||||
jsonschema.Definition{
|
jsonschema.Definition{
|
||||||
Type: jsonschema.Object,
|
Type: jsonschema.Object,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
@@ -209,7 +210,7 @@ func (a *AgentPool) createAgentAvatar(agent AgentConfig) error {
|
|||||||
|
|
||||||
req := openai.ImageRequest{
|
req := openai.ImageRequest{
|
||||||
Prompt: results.ImagePrompt,
|
Prompt: results.ImagePrompt,
|
||||||
Model: a.imageModel,
|
Model: imageModel,
|
||||||
Size: openai.CreateImageSize256x256,
|
Size: openai.CreateImageSize256x256,
|
||||||
ResponseFormat: openai.CreateImageResponseFormatB64JSON,
|
ResponseFormat: openai.CreateImageResponseFormatB64JSON,
|
||||||
}
|
}
|
||||||
@@ -228,10 +229,10 @@ func (a *AgentPool) createAgentAvatar(agent AgentConfig) error {
|
|||||||
|
|
||||||
imageJson := resp.Data[0].B64JSON
|
imageJson := resp.Data[0].B64JSON
|
||||||
|
|
||||||
os.MkdirAll(filepath.Join(a.pooldir, "avatars"), 0755)
|
os.MkdirAll(filepath.Join(avatarDir, "avatars"), 0755)
|
||||||
|
|
||||||
// Save the image to the agent directory
|
// Save the image to the agent directory
|
||||||
imagePath := filepath.Join(a.pooldir, "avatars", fmt.Sprintf("%s.png", agent.Name))
|
imagePath := filepath.Join(avatarDir, "avatars", fmt.Sprintf("%s.png", agent.Name))
|
||||||
imageData, err := base64.StdEncoding.DecodeString(imageJson)
|
imageData, err := base64.StdEncoding.DecodeString(imageJson)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -343,7 +344,7 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
|
|||||||
WithLLMAPIKey(a.apiKey),
|
WithLLMAPIKey(a.apiKey),
|
||||||
WithTimeout(a.timeout),
|
WithTimeout(a.timeout),
|
||||||
WithRAGDB(localrag.NewWrappedClient(a.localRAGAPI, a.localRAGKey, name)),
|
WithRAGDB(localrag.NewWrappedClient(a.localRAGAPI, a.localRAGKey, name)),
|
||||||
WithAgentReasoningCallback(func(state ActionCurrentState) bool {
|
WithAgentReasoningCallback(func(state types.ActionCurrentState) bool {
|
||||||
xlog.Info(
|
xlog.Info(
|
||||||
"Agent is thinking",
|
"Agent is thinking",
|
||||||
"agent", name,
|
"agent", name,
|
||||||
@@ -367,7 +368,7 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
|
|||||||
}),
|
}),
|
||||||
WithSystemPrompt(config.SystemPrompt),
|
WithSystemPrompt(config.SystemPrompt),
|
||||||
WithMultimodalModel(multimodalModel),
|
WithMultimodalModel(multimodalModel),
|
||||||
WithAgentResultCallback(func(state ActionState) {
|
WithAgentResultCallback(func(state types.ActionState) {
|
||||||
a.Lock()
|
a.Lock()
|
||||||
if _, ok := a.agentStatus[name]; !ok {
|
if _, ok := a.agentStatus[name]; !ok {
|
||||||
a.agentStatus[name] = &Status{}
|
a.agentStatus[name] = &Status{}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package action
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -19,7 +19,7 @@ func (ac *ActionContext) Cancel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContext(ctx context.Context, cancel context.CancelFunc) *ActionContext {
|
func NewActionContext(ctx context.Context, cancel context.CancelFunc) *ActionContext {
|
||||||
return &ActionContext{
|
return &ActionContext{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
cancelFunc: cancel,
|
cancelFunc: cancel,
|
||||||
@@ -29,6 +29,7 @@ func NewContext(ctx context.Context, cancel context.CancelFunc) *ActionContext {
|
|||||||
type ActionParams map[string]interface{}
|
type ActionParams map[string]interface{}
|
||||||
|
|
||||||
type ActionResult struct {
|
type ActionResult struct {
|
||||||
|
Job *Job
|
||||||
Result string
|
Result string
|
||||||
Metadata map[string]interface{}
|
Metadata map[string]interface{}
|
||||||
}
|
}
|
||||||
@@ -84,3 +85,44 @@ func (a ActionDefinition) ToFunctionDefinition() openai.FunctionDefinition {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actions is something the agent can do
|
||||||
|
type Action interface {
|
||||||
|
Run(ctx context.Context, action ActionParams) (ActionResult, error)
|
||||||
|
Definition() ActionDefinition
|
||||||
|
Plannable() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Actions []Action
|
||||||
|
|
||||||
|
func (a Actions) ToTools() []openai.Tool {
|
||||||
|
tools := []openai.Tool{}
|
||||||
|
for _, action := range a {
|
||||||
|
tools = append(tools, openai.Tool{
|
||||||
|
Type: openai.ToolTypeFunction,
|
||||||
|
Function: action.Definition().ToFunctionDefinition(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return tools
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Actions) Find(name string) Action {
|
||||||
|
for _, action := range a {
|
||||||
|
if action.Definition().Name.Is(name) {
|
||||||
|
return action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionState struct {
|
||||||
|
ActionCurrentState
|
||||||
|
ActionResult
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionCurrentState struct {
|
||||||
|
Job *Job
|
||||||
|
Action Action
|
||||||
|
Params ActionParams
|
||||||
|
Reasoning string
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package agent
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,7 +18,8 @@ type Job struct {
|
|||||||
Result *JobResult
|
Result *JobResult
|
||||||
reasoningCallback func(ActionCurrentState) bool
|
reasoningCallback func(ActionCurrentState) bool
|
||||||
resultCallback func(ActionState)
|
resultCallback func(ActionState)
|
||||||
conversationHistory []openai.ChatCompletionMessage
|
ConversationHistory []openai.ChatCompletionMessage
|
||||||
|
UUID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// JobResult is the result of a job
|
// JobResult is the result of a job
|
||||||
@@ -26,16 +29,16 @@ type JobResult struct {
|
|||||||
State []ActionState
|
State []ActionState
|
||||||
Conversation []openai.ChatCompletionMessage
|
Conversation []openai.ChatCompletionMessage
|
||||||
|
|
||||||
Response string
|
Response string
|
||||||
Error error
|
Error error
|
||||||
ready chan bool
|
ready chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type JobOption func(*Job)
|
type JobOption func(*Job)
|
||||||
|
|
||||||
func WithConversationHistory(history []openai.ChatCompletionMessage) JobOption {
|
func WithConversationHistory(history []openai.ChatCompletionMessage) JobOption {
|
||||||
return func(j *Job) {
|
return func(j *Job) {
|
||||||
j.conversationHistory = history
|
j.ConversationHistory = history
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +88,19 @@ func WithText(text string) JobOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newUUID() string {
|
||||||
|
// Generate UUID with google/uuid
|
||||||
|
// https://pkg.go.dev/github.com/google/uuid
|
||||||
|
|
||||||
|
// Generate a Version 4 UUID
|
||||||
|
u, err := uuid.NewRandom()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to generate UUID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
|
||||||
// NewJob creates a new job
|
// NewJob creates a new job
|
||||||
// It is a request to the agent to do something
|
// It is a request to the agent to do something
|
||||||
// It has a JobResult to get the result asynchronously
|
// It has a JobResult to get the result asynchronously
|
||||||
@@ -92,42 +108,17 @@ func WithText(text string) JobOption {
|
|||||||
func NewJob(opts ...JobOption) *Job {
|
func NewJob(opts ...JobOption) *Job {
|
||||||
j := &Job{
|
j := &Job{
|
||||||
Result: NewJobResult(),
|
Result: NewJobResult(),
|
||||||
|
UUID: newUUID(),
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(j)
|
o(j)
|
||||||
}
|
}
|
||||||
|
|
||||||
return j
|
return j
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetResult sets the result of a job
|
func WithUUID(uuid string) JobOption {
|
||||||
func (j *JobResult) SetResult(text ActionState) {
|
return func(j *Job) {
|
||||||
j.Lock()
|
j.UUID = uuid
|
||||||
defer j.Unlock()
|
}
|
||||||
|
|
||||||
j.State = append(j.State, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetResult sets the result of a job
|
|
||||||
func (j *JobResult) Finish(e error) {
|
|
||||||
j.Lock()
|
|
||||||
defer j.Unlock()
|
|
||||||
|
|
||||||
j.Error = e
|
|
||||||
close(j.ready)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetResult sets the result of a job
|
|
||||||
func (j *JobResult) SetResponse(response string) {
|
|
||||||
j.Lock()
|
|
||||||
defer j.Unlock()
|
|
||||||
|
|
||||||
j.Response = response
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitResult waits for the result of a job
|
|
||||||
func (j *JobResult) WaitResult() *JobResult {
|
|
||||||
<-j.ready
|
|
||||||
j.Lock()
|
|
||||||
defer j.Unlock()
|
|
||||||
return j
|
|
||||||
}
|
}
|
||||||
34
core/types/result.go
Normal file
34
core/types/result.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
// SetResult sets the result of a job
|
||||||
|
func (j *JobResult) SetResult(text ActionState) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
|
||||||
|
j.State = append(j.State, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetResult sets the result of a job
|
||||||
|
func (j *JobResult) Finish(e error) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
|
||||||
|
j.Error = e
|
||||||
|
close(j.ready)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetResult sets the result of a job
|
||||||
|
func (j *JobResult) SetResponse(response string) {
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
|
||||||
|
j.Response = response
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitResult waits for the result of a job
|
||||||
|
func (j *JobResult) WaitResult() *JobResult {
|
||||||
|
<-j.ready
|
||||||
|
j.Lock()
|
||||||
|
defer j.Unlock()
|
||||||
|
return j
|
||||||
|
}
|
||||||
@@ -7,9 +7,9 @@ import (
|
|||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/action"
|
||||||
"github.com/mudler/LocalAgent/core/state"
|
"github.com/mudler/LocalAgent/core/state"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
|
||||||
"github.com/mudler/LocalAgent/services/actions"
|
"github.com/mudler/LocalAgent/services/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ var AvailableActions = []string{
|
|||||||
ActionShellcommand,
|
ActionShellcommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
func Actions(a *state.AgentConfig) func(ctx context.Context, pool *state.AgentPool) []agent.Action {
|
func Actions(a *state.AgentConfig) func(ctx context.Context, pool *state.AgentPool) []types.Action {
|
||||||
return func(ctx context.Context, pool *state.AgentPool) []agent.Action {
|
return func(ctx context.Context, pool *state.AgentPool) []types.Action {
|
||||||
allActions := []agent.Action{}
|
allActions := []types.Action{}
|
||||||
|
|
||||||
for _, a := range a.Actions {
|
for _, a := range a.Actions {
|
||||||
var config map[string]string
|
var config map[string]string
|
||||||
@@ -82,8 +82,8 @@ func Actions(a *state.AgentConfig) func(ctx context.Context, pool *state.AgentPo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Action(name string, config map[string]string, pool *state.AgentPool) (agent.Action, error) {
|
func Action(name string, config map[string]string, pool *state.AgentPool) (types.Action, error) {
|
||||||
var a agent.Action
|
var a types.Action
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"jaytaylor.com/html2text"
|
"jaytaylor.com/html2text"
|
||||||
)
|
)
|
||||||
@@ -18,7 +18,7 @@ func NewBrowse(config map[string]string) *BrowseAction {
|
|||||||
|
|
||||||
type BrowseAction struct{}
|
type BrowseAction struct{}
|
||||||
|
|
||||||
func (a *BrowseAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *BrowseAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}{}
|
}{}
|
||||||
@@ -26,35 +26,35 @@ func (a *BrowseAction) Run(ctx context.Context, params action.ActionParams) (act
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
// download page with http.Client
|
// download page with http.Client
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
req, err := http.NewRequest("GET", result.URL, nil)
|
req, err := http.NewRequest("GET", result.URL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
pagebyte, err := io.ReadAll(resp.Body)
|
pagebyte, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rendered, err := html2text.FromString(string(pagebyte), html2text.Options{PrettyTables: true})
|
rendered, err := html2text.FromString(string(pagebyte), html2text.Options{PrettyTables: true})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: fmt.Sprintf("The webpage '%s' content is:\n%s", result.URL, rendered)}, nil
|
return types.ActionResult{Result: fmt.Sprintf("The webpage '%s' content is:\n%s", result.URL, rendered)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BrowseAction) Definition() action.ActionDefinition {
|
func (a *BrowseAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "browse",
|
Name: "browse",
|
||||||
Description: "Use this tool to visit an URL. It browse a website page and return the text content.",
|
Description: "Use this tool to visit an URL. It browse a website page and return the text content.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
|
||||||
"github.com/mudler/LocalAgent/core/state"
|
"github.com/mudler/LocalAgent/core/state"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
@@ -21,7 +20,7 @@ type CallAgentAction struct {
|
|||||||
pool *state.AgentPool
|
pool *state.AgentPool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *CallAgentAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *CallAgentAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
AgentName string `json:"agent_name"`
|
AgentName string `json:"agent_name"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
@@ -30,16 +29,16 @@ func (a *CallAgentAction) Run(ctx context.Context, params action.ActionParams) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ag := a.pool.GetAgent(result.AgentName)
|
ag := a.pool.GetAgent(result.AgentName)
|
||||||
if ag == nil {
|
if ag == nil {
|
||||||
return action.ActionResult{}, fmt.Errorf("agent '%s' not found", result.AgentName)
|
return types.ActionResult{}, fmt.Errorf("agent '%s' not found", result.AgentName)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := ag.Ask(
|
resp := ag.Ask(
|
||||||
agent.WithConversationHistory(
|
types.WithConversationHistory(
|
||||||
[]openai.ChatCompletionMessage{
|
[]openai.ChatCompletionMessage{
|
||||||
{
|
{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
@@ -49,13 +48,13 @@ func (a *CallAgentAction) Run(ctx context.Context, params action.ActionParams) (
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: resp.Response}, nil
|
return types.ActionResult{Result: resp.Response}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *CallAgentAction) Definition() action.ActionDefinition {
|
func (a *CallAgentAction) Definition() types.ActionDefinition {
|
||||||
allAgents := a.pool.AllAgents()
|
allAgents := a.pool.AllAgents()
|
||||||
|
|
||||||
description := "Use this tool to call another agent. Available agents and their roles are:"
|
description := "Use this tool to call another agent. Available agents and their roles are:"
|
||||||
@@ -68,7 +67,7 @@ func (a *CallAgentAction) Definition() action.ActionDefinition {
|
|||||||
description += fmt.Sprintf("\n- %s: %s", agent, agentConfig.Description)
|
description += fmt.Sprintf("\n- %s: %s", agent, agentConfig.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "call_agent",
|
Name: "call_agent",
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ func NewCounter(config map[string]string) *CounterAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run executes the counter action
|
// Run executes the counter action
|
||||||
func (a *CounterAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *CounterAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
// Parse parameters
|
// Parse parameters
|
||||||
request := struct {
|
request := struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -32,11 +32,11 @@ func (a *CounterAction) Run(ctx context.Context, params action.ActionParams) (ac
|
|||||||
}{}
|
}{}
|
||||||
|
|
||||||
if err := params.Unmarshal(&request); err != nil {
|
if err := params.Unmarshal(&request); err != nil {
|
||||||
return action.ActionResult{}, fmt.Errorf("invalid parameters: %w", err)
|
return types.ActionResult{}, fmt.Errorf("invalid parameters: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.Name == "" {
|
if request.Name == "" {
|
||||||
return action.ActionResult{}, fmt.Errorf("counter name cannot be empty")
|
return types.ActionResult{}, fmt.Errorf("counter name cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
a.mutex.Lock()
|
a.mutex.Lock()
|
||||||
@@ -63,7 +63,7 @@ func (a *CounterAction) Run(ctx context.Context, params action.ActionParams) (ac
|
|||||||
message = fmt.Sprintf("Current value of counter '%s' is %d", request.Name, newValue)
|
message = fmt.Sprintf("Current value of counter '%s' is %d", request.Name, newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{
|
return types.ActionResult{
|
||||||
Result: message,
|
Result: message,
|
||||||
Metadata: map[string]any{
|
Metadata: map[string]any{
|
||||||
"counter_name": request.Name,
|
"counter_name": request.Name,
|
||||||
@@ -75,8 +75,8 @@ func (a *CounterAction) Run(ctx context.Context, params action.ActionParams) (ac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Definition returns the action definition
|
// Definition returns the action definition
|
||||||
func (a *CounterAction) Definition() action.ActionDefinition {
|
func (a *CounterAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "counter",
|
Name: "counter",
|
||||||
Description: "Create, update, or query named counters. Specify a name and an adjustment value (positive to increase, negative to decrease, zero to query).",
|
Description: "Create, update, or query named counters. Specify a name and an adjustment value (positive to increase, negative to decrease, zero to query).",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
@@ -28,18 +28,18 @@ type GenImageAction struct {
|
|||||||
imageModel string
|
imageModel string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GenImageAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *GenImageAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Prompt string `json:"prompt"`
|
Prompt string `json:"prompt"`
|
||||||
Size string `json:"size"`
|
Size string `json:"size"`
|
||||||
}{}
|
}{}
|
||||||
err := params.Unmarshal(&result)
|
err := params.Unmarshal(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Prompt == "" {
|
if result.Prompt == "" {
|
||||||
return action.ActionResult{}, fmt.Errorf("prompt is required")
|
return types.ActionResult{}, fmt.Errorf("prompt is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
req := openai.ImageRequest{
|
req := openai.ImageRequest{
|
||||||
@@ -60,22 +60,22 @@ func (a *GenImageAction) Run(ctx context.Context, params action.ActionParams) (a
|
|||||||
|
|
||||||
resp, err := a.client.CreateImage(ctx, req)
|
resp, err := a.client.CreateImage(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{Result: "Failed to generate image " + err.Error()}, err
|
return types.ActionResult{Result: "Failed to generate image " + err.Error()}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(resp.Data) == 0 {
|
if len(resp.Data) == 0 {
|
||||||
return action.ActionResult{Result: "Failed to generate image"}, nil
|
return types.ActionResult{Result: "Failed to generate image"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{
|
return types.ActionResult{
|
||||||
Result: fmt.Sprintf("The image was generated and available at: %s", resp.Data[0].URL),
|
Result: fmt.Sprintf("The image was generated and available at: %s", resp.Data[0].URL),
|
||||||
Metadata: map[string]interface{}{
|
Metadata: map[string]interface{}{
|
||||||
MetadataImages: []string{resp.Data[0].URL},
|
MetadataImages: []string{resp.Data[0].URL},
|
||||||
}}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GenImageAction) Definition() action.ActionDefinition {
|
func (a *GenImageAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "generate_image",
|
Name: "generate_image",
|
||||||
Description: "Generate image with.",
|
Description: "Generate image with.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
. "github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
|
|
||||||
. "github.com/mudler/LocalAgent/services/actions"
|
. "github.com/mudler/LocalAgent/services/actions"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
@@ -15,7 +15,7 @@ var _ = Describe("GenImageAction", func() {
|
|||||||
var (
|
var (
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
action *GenImageAction
|
action *GenImageAction
|
||||||
params ActionParams
|
params types.ActionParams
|
||||||
config map[string]string
|
config map[string]string
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ var _ = Describe("GenImageAction", func() {
|
|||||||
|
|
||||||
Describe("Run", func() {
|
Describe("Run", func() {
|
||||||
It("should generate an image with valid prompt and size", func() {
|
It("should generate an image with valid prompt and size", func() {
|
||||||
params = ActionParams{
|
params = types.ActionParams{
|
||||||
"prompt": "test prompt",
|
"prompt": "test prompt",
|
||||||
"size": "256x256",
|
"size": "256x256",
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ var _ = Describe("GenImageAction", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should return an error if the prompt is not provided", func() {
|
It("should return an error if the prompt is not provided", func() {
|
||||||
params = ActionParams{
|
params = types.ActionParams{
|
||||||
"size": "256x256",
|
"size": "256x256",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ func NewGithubIssueCloser(ctx context.Context, config map[string]string) *Github
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesCloser) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssuesCloser) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
@@ -37,7 +37,7 @@ func (g *GithubIssuesCloser) Run(ctx context.Context, params action.ActionParams
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" {
|
if g.repository != "" {
|
||||||
@@ -67,24 +67,24 @@ func (g *GithubIssuesCloser) Run(ctx context.Context, params action.ActionParams
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resultString := fmt.Sprintf("Closed issue %d in repository %s/%s", result.IssueNumber, result.Owner, result.Repository)
|
resultString := fmt.Sprintf("Closed issue %d in repository %s/%s", result.IssueNumber, result.Owner, result.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultString = fmt.Sprintf("Error closing issue %d in repository %s/%s: %v", result.IssueNumber, result.Owner, result.Repository, err)
|
resultString = fmt.Sprintf("Error closing issue %d in repository %s/%s: %v", result.IssueNumber, result.Owner, result.Repository, err)
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesCloser) Definition() action.ActionDefinition {
|
func (g *GithubIssuesCloser) Definition() types.ActionDefinition {
|
||||||
actionName := "close_github_issue"
|
actionName := "close_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Closes a Github issue.",
|
Description: "Closes a Github issue.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
@@ -96,8 +96,8 @@ func (g *GithubIssuesCloser) Definition() action.ActionDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Closes a Github issue.",
|
Description: "Closes a Github issue.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ func NewGithubIssueCommenter(ctx context.Context, config map[string]string) *Git
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesCommenter) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssuesCommenter) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
@@ -37,7 +37,7 @@ func (g *GithubIssuesCommenter) Run(ctx context.Context, params action.ActionPar
|
|||||||
}{}
|
}{}
|
||||||
err := params.Unmarshal(&result)
|
err := params.Unmarshal(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -53,18 +53,18 @@ func (g *GithubIssuesCommenter) Run(ctx context.Context, params action.ActionPar
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
resultString = fmt.Sprintf("Error adding comment to issue %d in repository %s/%s: %v", result.IssueNumber, result.Owner, result.Repository, err)
|
resultString = fmt.Sprintf("Error adding comment to issue %d in repository %s/%s: %v", result.IssueNumber, result.Owner, result.Repository, err)
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesCommenter) Definition() action.ActionDefinition {
|
func (g *GithubIssuesCommenter) Definition() types.ActionDefinition {
|
||||||
actionName := "add_comment_to_github_issue"
|
actionName := "add_comment_to_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
description := "Add a comment to a Github issue to a repository."
|
description := "Add a comment to a Github issue to a repository."
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
@@ -79,8 +79,8 @@ func (g *GithubIssuesCommenter) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"issue_number", "comment"},
|
Required: []string{"issue_number", "comment"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
@@ -39,7 +39,7 @@ func NewGithubIssueLabeler(ctx context.Context, config map[string]string) *Githu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesLabeler) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssuesLabeler) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
@@ -48,7 +48,7 @@ func (g *GithubIssuesLabeler) Run(ctx context.Context, params action.ActionParam
|
|||||||
}{}
|
}{}
|
||||||
err := params.Unmarshal(&result)
|
err := params.Unmarshal(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -67,17 +67,17 @@ func (g *GithubIssuesLabeler) Run(ctx context.Context, params action.ActionParam
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
resultString = fmt.Sprintf("Error adding label '%s' to issue %d in repository %s/%s: %v", result.Label, result.IssueNumber, result.Owner, result.Repository, err)
|
resultString = fmt.Sprintf("Error adding label '%s' to issue %d in repository %s/%s: %v", result.Label, result.IssueNumber, result.Owner, result.Repository, err)
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesLabeler) Definition() action.ActionDefinition {
|
func (g *GithubIssuesLabeler) Definition() types.ActionDefinition {
|
||||||
actionName := "add_label_to_github_issue"
|
actionName := "add_label_to_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Add a label to a Github issue. You might want to assign labels to issues to categorize them.",
|
Description: "Add a label to a Github issue. You might want to assign labels to issues to categorize them.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
@@ -93,8 +93,8 @@ func (g *GithubIssuesLabeler) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"issue_number", "label"},
|
Required: []string{"issue_number", "label"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Add a label to a Github issue. You might want to assign labels to issues to categorize them.",
|
Description: "Add a label to a Github issue. You might want to assign labels to issues to categorize them.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ func NewGithubIssueOpener(ctx context.Context, config map[string]string) *Github
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesOpener) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssuesOpener) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Body string `json:"text"`
|
Body string `json:"text"`
|
||||||
@@ -39,7 +39,7 @@ func (g *GithubIssuesOpener) Run(ctx context.Context, params action.ActionParams
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -60,17 +60,17 @@ func (g *GithubIssuesOpener) Run(ctx context.Context, params action.ActionParams
|
|||||||
resultString = fmt.Sprintf("Created issue %d in repository %s/%s: %s", createdIssue.GetNumber(), result.Owner, result.Repository, createdIssue.GetURL())
|
resultString = fmt.Sprintf("Created issue %d in repository %s/%s: %s", createdIssue.GetNumber(), result.Owner, result.Repository, createdIssue.GetURL())
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesOpener) Definition() action.ActionDefinition {
|
func (g *GithubIssuesOpener) Definition() types.ActionDefinition {
|
||||||
actionName := "create_github_issue"
|
actionName := "create_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Create a new issue on a GitHub repository.",
|
Description: "Create a new issue on a GitHub repository.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"text": {
|
"text": {
|
||||||
@@ -85,8 +85,8 @@ func (g *GithubIssuesOpener) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"title", "text"},
|
Required: []string{"title", "text"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Create a new issue on a GitHub repository.",
|
Description: "Create a new issue on a GitHub repository.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"text": {
|
"text": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ func NewGithubIssueReader(ctx context.Context, config map[string]string) *Github
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesReader) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssuesReader) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
@@ -37,7 +37,7 @@ func (g *GithubIssuesReader) Run(ctx context.Context, params action.ActionParams
|
|||||||
}{}
|
}{}
|
||||||
err := params.Unmarshal(&result)
|
err := params.Unmarshal(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -47,26 +47,26 @@ func (g *GithubIssuesReader) Run(ctx context.Context, params action.ActionParams
|
|||||||
|
|
||||||
issue, _, err := g.client.Issues.Get(g.context, result.Owner, result.Repository, result.IssueNumber)
|
issue, _, err := g.client.Issues.Get(g.context, result.Owner, result.Repository, result.IssueNumber)
|
||||||
if err == nil && issue != nil {
|
if err == nil && issue != nil {
|
||||||
return action.ActionResult{
|
return types.ActionResult{
|
||||||
Result: fmt.Sprintf(
|
Result: fmt.Sprintf(
|
||||||
"Issue %d Repository: %s\nTitle: %s\nBody: %s",
|
"Issue %d Repository: %s\nTitle: %s\nBody: %s",
|
||||||
*issue.Number, *issue.Repository.FullName, *issue.Title, *issue.Body)}, nil
|
*issue.Number, *issue.Repository.FullName, *issue.Title, *issue.Body)}, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{Result: fmt.Sprintf("Error fetching issue: %s", err.Error())}, err
|
return types.ActionResult{Result: fmt.Sprintf("Error fetching issue: %s", err.Error())}, err
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: fmt.Sprintf("No issue found")}, err
|
return types.ActionResult{Result: fmt.Sprintf("No issue found")}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssuesReader) Definition() action.ActionDefinition {
|
func (g *GithubIssuesReader) Definition() types.ActionDefinition {
|
||||||
actionName := "read_github_issue"
|
actionName := "read_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
description := "Read a Github issue."
|
description := "Read a Github issue."
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
@@ -77,8 +77,8 @@ func (g *GithubIssuesReader) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"issue_number"},
|
Required: []string{"issue_number"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"issue_number": {
|
"issue_number": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
@@ -29,7 +29,7 @@ func NewGithubIssueSearch(ctx context.Context, config map[string]string) *Github
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssueSearch) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubIssueSearch) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
@@ -39,7 +39,7 @@ func (g *GithubIssueSearch) Run(ctx context.Context, params action.ActionParams)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -56,7 +56,7 @@ func (g *GithubIssueSearch) Run(ctx context.Context, params action.ActionParams)
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultString = fmt.Sprintf("Error listing issues: %v", err)
|
resultString = fmt.Sprintf("Error listing issues: %v", err)
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
for _, i := range issues.Issues {
|
for _, i := range issues.Issues {
|
||||||
xlog.Info("Issue found", "title", i.GetTitle())
|
xlog.Info("Issue found", "title", i.GetTitle())
|
||||||
@@ -65,17 +65,17 @@ func (g *GithubIssueSearch) Run(ctx context.Context, params action.ActionParams)
|
|||||||
// resultString += fmt.Sprintf("Body: %s\n", i.GetBody())
|
// resultString += fmt.Sprintf("Body: %s\n", i.GetBody())
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssueSearch) Definition() action.ActionDefinition {
|
func (g *GithubIssueSearch) Definition() types.ActionDefinition {
|
||||||
actionName := "search_github_issue"
|
actionName := "search_github_issue"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Search between github issues",
|
Description: "Search between github issues",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"query": {
|
"query": {
|
||||||
@@ -86,8 +86,8 @@ func (g *GithubIssueSearch) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"query"},
|
Required: []string{"query"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: "Search between github issues",
|
Description: "Search between github issues",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"query": {
|
"query": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ func NewGithubRepositoryCreateOrUpdateContent(ctx context.Context, config map[st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryCreateOrUpdateContent) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubRepositoryCreateOrUpdateContent) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
@@ -44,7 +44,7 @@ func (g *GithubRepositoryCreateOrUpdateContent) Run(ctx context.Context, params
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Branch == "" {
|
if result.Branch == "" {
|
||||||
@@ -82,13 +82,13 @@ func (g *GithubRepositoryCreateOrUpdateContent) Run(ctx context.Context, params
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultString := fmt.Sprintf("Error creating content : %v", err)
|
resultString := fmt.Sprintf("Error creating content : %v", err)
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: fmt.Sprintf("File created/updated: %s\n", fileContent.GetURL())}, err
|
return types.ActionResult{Result: fmt.Sprintf("File created/updated: %s\n", fileContent.GetURL())}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryCreateOrUpdateContent) Definition() action.ActionDefinition {
|
func (g *GithubRepositoryCreateOrUpdateContent) Definition() types.ActionDefinition {
|
||||||
actionName := "github_repository_create_or_update_content"
|
actionName := "github_repository_create_or_update_content"
|
||||||
actionDescription := "Create or update a file in a GitHub repository"
|
actionDescription := "Create or update a file in a GitHub repository"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
@@ -117,8 +117,8 @@ func (g *GithubRepositoryCreateOrUpdateContent) Definition() action.ActionDefini
|
|||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: actionDescription,
|
Description: actionDescription,
|
||||||
Properties: properties,
|
Properties: properties,
|
||||||
Required: []string{"path", "content"},
|
Required: []string{"path", "content"},
|
||||||
@@ -135,8 +135,8 @@ func (g *GithubRepositoryCreateOrUpdateContent) Definition() action.ActionDefini
|
|||||||
Description: "The repository to search in",
|
Description: "The repository to search in",
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: actionDescription,
|
Description: actionDescription,
|
||||||
Properties: properties,
|
Properties: properties,
|
||||||
Required: []string{"path", "repository", "owner", "content"},
|
Required: []string{"path", "repository", "owner", "content"},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ func NewGithubRepositoryGetContent(ctx context.Context, config map[string]string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryGetContent) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubRepositoryGetContent) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
@@ -38,7 +38,7 @@ func (g *GithubRepositoryGetContent) Run(ctx context.Context, params action.Acti
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
@@ -49,7 +49,7 @@ func (g *GithubRepositoryGetContent) Run(ctx context.Context, params action.Acti
|
|||||||
fileContent, directoryContent, _, err := g.client.Repositories.GetContents(g.context, result.Owner, result.Repository, result.Path, nil)
|
fileContent, directoryContent, _, err := g.client.Repositories.GetContents(g.context, result.Owner, result.Repository, result.Path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultString := fmt.Sprintf("Error getting content : %v", err)
|
resultString := fmt.Sprintf("Error getting content : %v", err)
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(directoryContent) > 0 {
|
if len(directoryContent) > 0 {
|
||||||
@@ -57,26 +57,26 @@ func (g *GithubRepositoryGetContent) Run(ctx context.Context, params action.Acti
|
|||||||
for _, f := range directoryContent {
|
for _, f := range directoryContent {
|
||||||
resultString += fmt.Sprintf("File: %s\n", f.GetName())
|
resultString += fmt.Sprintf("File: %s\n", f.GetName())
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileContent.GetContent()
|
content, err := fileContent.GetContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: fmt.Sprintf("File %s\nContent:%s\n", result.Path, content)}, err
|
return types.ActionResult{Result: fmt.Sprintf("File %s\nContent:%s\n", result.Path, content)}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryGetContent) Definition() action.ActionDefinition {
|
func (g *GithubRepositoryGetContent) Definition() types.ActionDefinition {
|
||||||
actionName := "get_github_repository_content"
|
actionName := "get_github_repository_content"
|
||||||
actionDescription := "Get content of a file or directory in a github repository"
|
actionDescription := "Get content of a file or directory in a github repository"
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
if g.repository != "" && g.owner != "" {
|
if g.repository != "" && g.owner != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: actionDescription,
|
Description: actionDescription,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"path": {
|
"path": {
|
||||||
@@ -87,8 +87,8 @@ func (g *GithubRepositoryGetContent) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"path"},
|
Required: []string{"path"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: actionDescription,
|
Description: actionDescription,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"path": {
|
"path": {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ func NewGithubRepositoryREADME(ctx context.Context, config map[string]string) *G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryREADME) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (g *GithubRepositoryREADME) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Owner string `json:"owner"`
|
Owner string `json:"owner"`
|
||||||
@@ -35,30 +35,30 @@ func (g *GithubRepositoryREADME) Run(ctx context.Context, params action.ActionPa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
fileContent, _, err := g.client.Repositories.GetReadme(g.context, result.Owner, result.Repository, &github.RepositoryContentGetOptions{})
|
fileContent, _, err := g.client.Repositories.GetReadme(g.context, result.Owner, result.Repository, &github.RepositoryContentGetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resultString := fmt.Sprintf("Error getting content : %v", err)
|
resultString := fmt.Sprintf("Error getting content : %v", err)
|
||||||
return action.ActionResult{Result: resultString}, err
|
return types.ActionResult{Result: resultString}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileContent.GetContent()
|
content, err := fileContent.GetContent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: content}, err
|
return types.ActionResult{Result: content}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubRepositoryREADME) Definition() action.ActionDefinition {
|
func (g *GithubRepositoryREADME) Definition() types.ActionDefinition {
|
||||||
actionName := "github_readme"
|
actionName := "github_readme"
|
||||||
actionDescription := "Get the README file of a GitHub repository to have a basic understanding of the project."
|
actionDescription := "Get the README file of a GitHub repository to have a basic understanding of the project."
|
||||||
if g.customActionName != "" {
|
if g.customActionName != "" {
|
||||||
actionName = g.customActionName
|
actionName = g.customActionName
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(actionName),
|
Name: types.ActionDefinitionName(actionName),
|
||||||
Description: actionDescription,
|
Description: actionDescription,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"github.com/tmc/langchaingo/tools/scraper"
|
"github.com/tmc/langchaingo/tools/scraper"
|
||||||
)
|
)
|
||||||
@@ -16,7 +16,7 @@ func NewScraper(config map[string]string) *ScraperAction {
|
|||||||
|
|
||||||
type ScraperAction struct{}
|
type ScraperAction struct{}
|
||||||
|
|
||||||
func (a *ScraperAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *ScraperAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}{}
|
}{}
|
||||||
@@ -24,25 +24,25 @@ func (a *ScraperAction) Run(ctx context.Context, params action.ActionParams) (ac
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
scraper, err := scraper.New()
|
scraper, err := scraper.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
res, err := scraper.Call(ctx, result.URL)
|
res, err := scraper.Call(ctx, result.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: res}, nil
|
return types.ActionResult{Result: res}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ScraperAction) Definition() action.ActionDefinition {
|
func (a *ScraperAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "scrape",
|
Name: "scrape",
|
||||||
Description: "Scrapes a full website content and returns the entire site data.",
|
Description: "Scrapes a full website content and returns the entire site data.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"github.com/tmc/langchaingo/tools/duckduckgo"
|
"github.com/tmc/langchaingo/tools/duckduckgo"
|
||||||
"mvdan.cc/xurls/v2"
|
"mvdan.cc/xurls/v2"
|
||||||
@@ -34,7 +34,7 @@ func NewSearch(config map[string]string) *SearchAction {
|
|||||||
|
|
||||||
type SearchAction struct{ results int }
|
type SearchAction struct{ results int }
|
||||||
|
|
||||||
func (a *SearchAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *SearchAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
}{}
|
}{}
|
||||||
@@ -42,19 +42,19 @@ func (a *SearchAction) Run(ctx context.Context, params action.ActionParams) (act
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
ddg, err := duckduckgo.New(a.results, "LocalAgent")
|
ddg, err := duckduckgo.New(a.results, "LocalAgent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
res, err := ddg.Call(ctx, result.Query)
|
res, err := ddg.Call(ctx, result.Query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rxStrict := xurls.Strict()
|
rxStrict := xurls.Strict()
|
||||||
@@ -69,11 +69,11 @@ func (a *SearchAction) Run(ctx context.Context, params action.ActionParams) (act
|
|||||||
results = append(results, u)
|
results = append(results, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: res, Metadata: map[string]interface{}{MetadataUrls: results}}, nil
|
return types.ActionResult{Result: res, Metadata: map[string]interface{}{MetadataUrls: results}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SearchAction) Definition() action.ActionDefinition {
|
func (a *SearchAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "search_internet",
|
Name: "search_internet",
|
||||||
Description: "Search the internet for something.",
|
Description: "Search the internet for something.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ type SendMailAction struct {
|
|||||||
smtpPort string
|
smtpPort string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SendMailAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *SendMailAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
@@ -37,7 +37,7 @@ func (a *SendMailAction) Run(ctx context.Context, params action.ActionParams) (a
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authentication.
|
// Authentication.
|
||||||
@@ -50,13 +50,13 @@ func (a *SendMailAction) Run(ctx context.Context, params action.ActionParams) (a
|
|||||||
result.To,
|
result.To,
|
||||||
}, []byte(result.Message))
|
}, []byte(result.Message))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: fmt.Sprintf("Email sent to %s", result.To)}, nil
|
return types.ActionResult{Result: fmt.Sprintf("Email sent to %s", result.To)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SendMailAction) Definition() action.ActionDefinition {
|
func (a *SendMailAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "send_email",
|
Name: "send_email",
|
||||||
Description: "Send an email.",
|
Description: "Send an email.",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
@@ -27,7 +27,7 @@ type ShellAction struct {
|
|||||||
customDescription string
|
customDescription string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ShellAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *ShellAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
@@ -37,7 +37,7 @@ func (a *ShellAction) Run(ctx context.Context, params action.ActionParams) (acti
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.host != "" && a.user != "" {
|
if a.host != "" && a.user != "" {
|
||||||
@@ -47,13 +47,13 @@ func (a *ShellAction) Run(ctx context.Context, params action.ActionParams) (acti
|
|||||||
|
|
||||||
output, err := sshCommand(a.privateKey, result.Command, result.User, result.Host)
|
output, err := sshCommand(a.privateKey, result.Command, result.User, result.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: output}, nil
|
return types.ActionResult{Result: output}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ShellAction) Definition() action.ActionDefinition {
|
func (a *ShellAction) Definition() types.ActionDefinition {
|
||||||
name := "shell"
|
name := "shell"
|
||||||
description := "Run a shell command on a remote server."
|
description := "Run a shell command on a remote server."
|
||||||
if a.customName != "" {
|
if a.customName != "" {
|
||||||
@@ -63,8 +63,8 @@ func (a *ShellAction) Definition() action.ActionDefinition {
|
|||||||
description = a.customDescription
|
description = a.customDescription
|
||||||
}
|
}
|
||||||
if a.host != "" && a.user != "" {
|
if a.host != "" && a.user != "" {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(name),
|
Name: types.ActionDefinitionName(name),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"command": {
|
"command": {
|
||||||
@@ -75,8 +75,8 @@ func (a *ShellAction) Definition() action.ActionDefinition {
|
|||||||
Required: []string{"command"},
|
Required: []string{"command"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: action.ActionDefinitionName(name),
|
Name: types.ActionDefinitionName(name),
|
||||||
Description: description,
|
Description: description,
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
"command": {
|
"command": {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
)
|
)
|
||||||
@@ -21,7 +21,7 @@ type PostTweetAction struct {
|
|||||||
noCharacterLimit bool
|
noCharacterLimit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PostTweetAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *PostTweetAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
}{}
|
}{}
|
||||||
@@ -29,24 +29,24 @@ func (a *PostTweetAction) Run(ctx context.Context, params action.ActionParams) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !a.noCharacterLimit && len(result.Text) > 280 {
|
if !a.noCharacterLimit && len(result.Text) > 280 {
|
||||||
return action.ActionResult{}, fmt.Errorf("tweet is too long, max 280 characters")
|
return types.ActionResult{}, fmt.Errorf("tweet is too long, max 280 characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
client := twitter.NewTwitterClient(a.token)
|
client := twitter.NewTwitterClient(a.token)
|
||||||
|
|
||||||
if err := client.Post(result.Text); err != nil {
|
if err := client.Post(result.Text); err != nil {
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.ActionResult{Result: fmt.Sprintf("twitter post created")}, nil
|
return types.ActionResult{Result: fmt.Sprintf("twitter post created")}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PostTweetAction) Definition() action.ActionDefinition {
|
func (a *PostTweetAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "post_tweet",
|
Name: "post_tweet",
|
||||||
Description: "Post a tweet",
|
Description: "Post a tweet",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
"github.com/tmc/langchaingo/tools/wikipedia"
|
"github.com/tmc/langchaingo/tools/wikipedia"
|
||||||
)
|
)
|
||||||
@@ -15,7 +15,7 @@ func NewWikipedia(config map[string]string) *WikipediaAction {
|
|||||||
|
|
||||||
type WikipediaAction struct{}
|
type WikipediaAction struct{}
|
||||||
|
|
||||||
func (a *WikipediaAction) Run(ctx context.Context, params action.ActionParams) (action.ActionResult, error) {
|
func (a *WikipediaAction) Run(ctx context.Context, params types.ActionParams) (types.ActionResult, error) {
|
||||||
result := struct {
|
result := struct {
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
}{}
|
}{}
|
||||||
@@ -23,20 +23,20 @@ func (a *WikipediaAction) Run(ctx context.Context, params action.ActionParams) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
wiki := wikipedia.New("LocalAgent")
|
wiki := wikipedia.New("LocalAgent")
|
||||||
res, err := wiki.Call(ctx, result.Query)
|
res, err := wiki.Call(ctx, result.Query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error: %v", err)
|
fmt.Printf("error: %v", err)
|
||||||
|
|
||||||
return action.ActionResult{}, err
|
return types.ActionResult{}, err
|
||||||
}
|
}
|
||||||
return action.ActionResult{Result: res}, nil
|
return types.ActionResult{Result: res}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *WikipediaAction) Definition() action.ActionDefinition {
|
func (a *WikipediaAction) Definition() types.ActionDefinition {
|
||||||
return action.ActionDefinition{
|
return types.ActionDefinition{
|
||||||
Name: "wikipedia",
|
Name: "wikipedia",
|
||||||
Description: "Find wikipedia pages using the wikipedia api",
|
Description: "Find wikipedia pages using the wikipedia api",
|
||||||
Properties: map[string]jsonschema.Definition{
|
Properties: map[string]jsonschema.Definition{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,14 +25,14 @@ func NewDiscord(config map[string]string) *Discord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discord) AgentResultCallback() func(state agent.ActionState) {
|
func (d *Discord) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
// Send the result to the bot
|
// Send the result to the bot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discord) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (d *Discord) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
// Send the reasoning to the bot
|
// Send the reasoning to the bot
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -84,7 +85,7 @@ func (d *Discord) messageCreate(a *agent.Agent) func(s *discordgo.Session, m *di
|
|||||||
content = strings.ReplaceAll(content, "<@"+s.State.User.ID+"> ", "")
|
content = strings.ReplaceAll(content, "<@"+s.State.User.ID+"> ", "")
|
||||||
xlog.Info("Received message", "content", content)
|
xlog.Info("Received message", "content", content)
|
||||||
job := a.Ask(
|
job := a.Ask(
|
||||||
agent.WithText(
|
types.WithText(
|
||||||
content,
|
content,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -50,14 +51,14 @@ func NewGithubIssueWatcher(config map[string]string) *GithubIssues {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssues) AgentResultCallback() func(state agent.ActionState) {
|
func (g *GithubIssues) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
// Send the result to the bot
|
// Send the result to the bot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubIssues) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (g *GithubIssues) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
// Send the reasoning to the bot
|
// Send the reasoning to the bot
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ func (g *GithubIssues) issuesService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := g.agent.Ask(
|
res := g.agent.Ask(
|
||||||
agent.WithConversationHistory(messages),
|
types.WithConversationHistory(messages),
|
||||||
)
|
)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
xlog.Error("Error asking", "error", res.Error, "agent", g.agent.Character.Name)
|
xlog.Error("Error asking", "error", res.Error, "agent", g.agent.Character.Name)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-github/v69/github"
|
"github.com/google/go-github/v69/github"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
|
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -50,14 +51,14 @@ func NewGithubPRWatcher(config map[string]string) *GithubPRs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubPRs) AgentResultCallback() func(state agent.ActionState) {
|
func (g *GithubPRs) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
// Send the result to the bot
|
// Send the result to the bot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GithubPRs) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (g *GithubPRs) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
// Send the reasoning to the bot
|
// Send the reasoning to the bot
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -175,7 +176,7 @@ func (g *GithubPRs) prService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := g.agent.Ask(
|
res := g.agent.Ask(
|
||||||
agent.WithConversationHistory(messages),
|
types.WithConversationHistory(messages),
|
||||||
)
|
)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
xlog.Error("Error asking", "error", res.Error, "agent", g.agent.Character.Name)
|
xlog.Error("Error asking", "error", res.Error, "agent", g.agent.Character.Name)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/actions"
|
"github.com/mudler/LocalAgent/services/actions"
|
||||||
irc "github.com/thoj/go-ircevent"
|
irc "github.com/thoj/go-ircevent"
|
||||||
@@ -30,14 +31,14 @@ func NewIRC(config map[string]string) *IRC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IRC) AgentResultCallback() func(state agent.ActionState) {
|
func (i *IRC) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
// Send the result to the bot
|
// Send the result to the bot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IRC) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (i *IRC) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
// Send the reasoning to the bot
|
// Send the reasoning to the bot
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@ func (i *IRC) Start(a *agent.Agent) {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
agent.WithText(cleanedMessage),
|
types.WithText(cleanedMessage),
|
||||||
)
|
)
|
||||||
|
|
||||||
xlog.Info("Sending message", "message", res.Response, "channel", channel)
|
xlog.Info("Sending message", "message", res.Response, "channel", channel)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
|
|
||||||
"github.com/slack-go/slack/socketmode"
|
"github.com/slack-go/slack/socketmode"
|
||||||
|
|
||||||
@@ -39,14 +40,14 @@ func NewSlack(config map[string]string) *Slack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Slack) AgentResultCallback() func(state agent.ActionState) {
|
func (t *Slack) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
// Send the result to the bot
|
// Send the result to the bot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Slack) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (t *Slack) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
// Send the reasoning to the bot
|
// Send the reasoning to the bot
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,7 @@ func uniqueStringSlice(s []string) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateAttachmentsFromJobResponse(j *agent.JobResult) (attachments []slack.Attachment) {
|
func generateAttachmentsFromJobResponse(j *types.JobResult) (attachments []slack.Attachment) {
|
||||||
for _, state := range j.State {
|
for _, state := range j.State {
|
||||||
// coming from the search action
|
// coming from the search action
|
||||||
if urls, exists := state.Metadata[actions.MetadataUrls]; exists {
|
if urls, exists := state.Metadata[actions.MetadataUrls]; exists {
|
||||||
@@ -148,7 +149,7 @@ func (t *Slack) handleChannelMessage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
agentOptions := []agent.JobOption{agent.WithText(message)}
|
agentOptions := []types.JobOption{types.WithText(message)}
|
||||||
|
|
||||||
// If the last message has an image, we send it as a multi content message
|
// If the last message has an image, we send it as a multi content message
|
||||||
if len(imageBytes.Bytes()) > 0 {
|
if len(imageBytes.Bytes()) > 0 {
|
||||||
@@ -158,7 +159,7 @@ func (t *Slack) handleChannelMessage(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
xlog.Error(fmt.Sprintf("Error encoding image to base64: %v", err))
|
xlog.Error(fmt.Sprintf("Error encoding image to base64: %v", err))
|
||||||
} else {
|
} else {
|
||||||
agentOptions = append(agentOptions, agent.WithImage(fmt.Sprintf("data:%s;base64,%s", mimeType, imgBase64)))
|
agentOptions = append(agentOptions, types.WithImage(fmt.Sprintf("data:%s;base64,%s", mimeType, imgBase64)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,8 +351,8 @@ func (t *Slack) handleMention(
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
// agent.WithText(message),
|
// types.WithText(message),
|
||||||
agent.WithConversationHistory(threadMessages),
|
types.WithConversationHistory(threadMessages),
|
||||||
)
|
)
|
||||||
|
|
||||||
res.Response = githubmarkdownconvertergo.Slack(res.Response)
|
res.Response = githubmarkdownconvertergo.Slack(res.Response)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/go-telegram/bot"
|
"github.com/go-telegram/bot"
|
||||||
"github.com/go-telegram/bot/models"
|
"github.com/go-telegram/bot/models"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Telegram struct {
|
type Telegram struct {
|
||||||
@@ -20,16 +21,16 @@ type Telegram struct {
|
|||||||
|
|
||||||
// Send any text message to the bot after the bot has been started
|
// Send any text message to the bot after the bot has been started
|
||||||
|
|
||||||
func (t *Telegram) AgentResultCallback() func(state agent.ActionState) {
|
func (t *Telegram) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
t.bot.SetMyDescription(t.agent.Context(), &bot.SetMyDescriptionParams{
|
t.bot.SetMyDescription(t.agent.Context(), &bot.SetMyDescriptionParams{
|
||||||
Description: state.Reasoning,
|
Description: state.Reasoning,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Telegram) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (t *Telegram) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
t.bot.SetMyDescription(t.agent.Context(), &bot.SetMyDescriptionParams{
|
t.bot.SetMyDescription(t.agent.Context(), &bot.SetMyDescriptionParams{
|
||||||
Description: state.Reasoning,
|
Description: state.Reasoning,
|
||||||
})
|
})
|
||||||
@@ -45,7 +46,7 @@ func (t *Telegram) Start(a *agent.Agent) {
|
|||||||
bot.WithDefaultHandler(func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
bot.WithDefaultHandler(func(ctx context.Context, b *bot.Bot, update *models.Update) {
|
||||||
go func() {
|
go func() {
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
agent.WithText(
|
types.WithText(
|
||||||
update.Message.Text,
|
update.Message.Text,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
"github.com/mudler/LocalAgent/core/agent"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
"github.com/mudler/LocalAgent/services/connectors/twitter"
|
||||||
"github.com/sashabaranov/go-openai"
|
"github.com/sashabaranov/go-openai"
|
||||||
@@ -19,14 +20,14 @@ type Twitter struct {
|
|||||||
noCharacterLimit bool
|
noCharacterLimit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Twitter) AgentResultCallback() func(state agent.ActionState) {
|
func (t *Twitter) AgentResultCallback() func(state types.ActionState) {
|
||||||
return func(state agent.ActionState) {
|
return func(state types.ActionState) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Twitter) AgentReasoningCallback() func(state agent.ActionCurrentState) bool {
|
func (t *Twitter) AgentReasoningCallback() func(state types.ActionCurrentState) bool {
|
||||||
return func(state agent.ActionCurrentState) bool {
|
return func(state types.ActionCurrentState) bool {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,7 @@ func (t *Twitter) run(a *agent.Agent) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
agent.WithConversationHistory(
|
types.WithConversationHistory(
|
||||||
[]openai.ChatCompletionMessage{
|
[]openai.ChatCompletionMessage{
|
||||||
{
|
{
|
||||||
Role: "system",
|
Role: "system",
|
||||||
|
|||||||
13
webui/app.go
13
webui/app.go
@@ -9,14 +9,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
coreTypes "github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/llm"
|
"github.com/mudler/LocalAgent/pkg/llm"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services"
|
"github.com/mudler/LocalAgent/services"
|
||||||
"github.com/mudler/LocalAgent/webui/types"
|
"github.com/mudler/LocalAgent/webui/types"
|
||||||
"github.com/sashabaranov/go-openai/jsonschema"
|
"github.com/sashabaranov/go-openai/jsonschema"
|
||||||
|
|
||||||
"github.com/mudler/LocalAgent/core/action"
|
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
|
||||||
"github.com/mudler/LocalAgent/core/sse"
|
"github.com/mudler/LocalAgent/core/sse"
|
||||||
"github.com/mudler/LocalAgent/core/state"
|
"github.com/mudler/LocalAgent/core/state"
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ func (a *App) Notify(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
a := pool.GetAgent(c.Params("name"))
|
a := pool.GetAgent(c.Params("name"))
|
||||||
a.Ask(
|
a.Ask(
|
||||||
agent.WithText(query),
|
coreTypes.WithText(query),
|
||||||
)
|
)
|
||||||
_, _ = c.Write([]byte("Message sent"))
|
_, _ = c.Write([]byte("Message sent"))
|
||||||
|
|
||||||
@@ -275,7 +274,7 @@ func (a *App) Chat(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
agent.WithText(query),
|
coreTypes.WithText(query),
|
||||||
)
|
)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
xlog.Error("Error asking agent", "agent", agentName, "error", res.Error)
|
xlog.Error("Error asking agent", "agent", agentName, "error", res.Error)
|
||||||
@@ -307,8 +306,8 @@ func (a *App) Chat(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|||||||
func (a *App) ExecuteAction(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
func (a *App) ExecuteAction(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
payload := struct {
|
payload := struct {
|
||||||
Config map[string]string `json:"config"`
|
Config map[string]string `json:"config"`
|
||||||
Params action.ActionParams `json:"params"`
|
Params coreTypes.ActionParams `json:"params"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
if err := c.BodyParser(&payload); err != nil {
|
if err := c.BodyParser(&payload); err != nil {
|
||||||
@@ -365,7 +364,7 @@ func (a *App) Responses(pool *state.AgentPool) func(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := a.Ask(
|
res := a.Ask(
|
||||||
agent.WithConversationHistory(messages),
|
coreTypes.WithConversationHistory(messages),
|
||||||
)
|
)
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
xlog.Error("Error asking agent", "agent", agentName, "error", res.Error)
|
xlog.Error("Error asking agent", "agent", agentName, "error", res.Error)
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
fiber "github.com/gofiber/fiber/v2"
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
||||||
"github.com/gofiber/fiber/v2/middleware/keyauth"
|
"github.com/gofiber/fiber/v2/middleware/keyauth"
|
||||||
"github.com/mudler/LocalAgent/core/agent"
|
|
||||||
"github.com/mudler/LocalAgent/core/sse"
|
"github.com/mudler/LocalAgent/core/sse"
|
||||||
"github.com/mudler/LocalAgent/core/state"
|
"github.com/mudler/LocalAgent/core/state"
|
||||||
|
"github.com/mudler/LocalAgent/core/types"
|
||||||
"github.com/mudler/LocalAgent/pkg/xlog"
|
"github.com/mudler/LocalAgent/pkg/xlog"
|
||||||
"github.com/mudler/LocalAgent/services"
|
"github.com/mudler/LocalAgent/services"
|
||||||
)
|
)
|
||||||
@@ -95,7 +95,7 @@ func (app *App) registerRoutes(pool *state.AgentPool, webapp *fiber.App) {
|
|||||||
webapp.Get("/status/:name", func(c *fiber.Ctx) error {
|
webapp.Get("/status/:name", func(c *fiber.Ctx) error {
|
||||||
history := pool.GetStatusHistory(c.Params("name"))
|
history := pool.GetStatusHistory(c.Params("name"))
|
||||||
if history == nil {
|
if history == nil {
|
||||||
history = &state.Status{ActionResults: []agent.ActionState{}}
|
history = &state.Status{ActionResults: []types.ActionState{}}
|
||||||
}
|
}
|
||||||
// reverse history
|
// reverse history
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user