diff --git a/pkg/engine/cmd.go b/pkg/engine/cmd.go index 317f0d6a..33a67640 100644 --- a/pkg/engine/cmd.go +++ b/pkg/engine/cmd.go @@ -68,12 +68,14 @@ func compressEnv(envs []string) (result []string) { func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCategory ToolCategory) (cmdOut string, cmdErr error) { id := counter.Next() + var combinedOutput string defer func() { e.Progress <- types.CompletionStatus{ CompletionID: id, Response: map[string]any{ - "output": cmdOut, - "err": cmdErr, + "output": cmdOut, + "fullOutput": combinedOutput, + "err": cmdErr, }, } }() @@ -156,9 +158,11 @@ func (e *Engine) runCommand(ctx Context, tool types.Tool, input string, toolCate return fmt.Sprintf("ERROR: got (%v) while running tool, OUTPUT: %s", err, stdoutAndErr), nil } log.Errorf("failed to run tool [%s] cmd %v: %v", tool.Parameters.Name, cmd.Args, err) + combinedOutput = stdoutAndErr.String() return "", fmt.Errorf("ERROR: %s: %w", result, err) } + combinedOutput = stdoutAndErr.String() return result.String(), IsChatFinishMessage(result.String()) } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index d028d50b..0665991c 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -281,6 +281,25 @@ func populateMessageParams(ctx Context, completion *types.CompletionRequest, too return nil } +func (e *Engine) runCommandTools(ctx Context, tool types.Tool, input string) (*Return, error) { + if tool.IsHTTP() { + return e.runHTTP(ctx.Ctx, ctx.Program, tool, input) + } else if tool.IsDaemon() { + return e.runDaemon(ctx.Ctx, ctx.Program, tool, input) + } else if tool.IsOpenAPI() { + return e.runOpenAPI(tool, input) + } else if tool.IsEcho() { + return e.runEcho(tool) + } + s, err := e.runCommand(ctx, tool, input, ctx.ToolCategory) + if err != nil { + return nil, err + } + return &Return{ + Result: &s, + }, nil +} + func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) { tool := ctx.Tool @@ -291,22 +310,7 @@ func (e *Engine) Start(ctx Context, input string) (ret *Return, _ error) { }() if tool.IsCommand() { - if tool.IsHTTP() { - return e.runHTTP(ctx.Ctx, ctx.Program, tool, input) - } else if tool.IsDaemon() { - return e.runDaemon(ctx.Ctx, ctx.Program, tool, input) - } else if tool.IsOpenAPI() { - return e.runOpenAPI(tool, input) - } else if tool.IsEcho() { - return e.runEcho(tool) - } - s, err := e.runCommand(ctx, tool, input, ctx.ToolCategory) - if err != nil { - return nil, err - } - return &Return{ - Result: &s, - }, nil + return e.runCommandTools(ctx, tool, input) } if ctx.ToolCategory == CredentialToolCategory { @@ -431,6 +435,14 @@ func (e *Engine) complete(ctx context.Context, state *State) (*Return, error) { } func (e *Engine) Continue(ctx Context, state *State, results ...CallResult) (*Return, error) { + if ctx.Tool.IsCommand() { + var input string + if len(results) == 1 { + input = results[0].User + } + return e.runCommandTools(ctx, ctx.Tool, input) + } + if state == nil { return nil, fmt.Errorf("invalid continue call, missing state") } diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index c843b6b5..e6318c15 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -179,7 +179,6 @@ func (r *Runner) Chat(ctx context.Context, prevState ChatState, prg types.Progra } } else { state = state.WithResumeInput(&input) - state.ResumeInput = &input } state, err = r.resume(callCtx, monitor, env, state) @@ -683,7 +682,13 @@ func (r *Runner) subCall(ctx context.Context, parentContext engine.Context, moni }, nil } - return r.call(callCtx, monitor, env, input) + state, err := r.call(callCtx, monitor, env, input) + if finishErr := (*engine.ErrChatFinish)(nil); errors.As(err, &finishErr) && callCtx.Tool.Chat { + return &State{ + Result: &finishErr.Message, + }, nil + } + return state, err } func (r *Runner) subCallResume(ctx context.Context, parentContext engine.Context, monitor Monitor, env []string, toolID, callID string, state *State, toolCategory engine.ToolCategory) (*State, error) { @@ -692,7 +697,13 @@ func (r *Runner) subCallResume(ctx context.Context, parentContext engine.Context return nil, err } - return r.resume(callCtx, monitor, env, state) + state, err = r.resume(callCtx, monitor, env, state) + if finishErr := (*engine.ErrChatFinish)(nil); errors.As(err, &finishErr) && callCtx.Tool.Chat { + return &State{ + Result: &finishErr.Message, + }, nil + } + return state, err } type SubCallResult struct {