Detailed changes
@@ -65,9 +65,10 @@ type SessionAgentCall struct {
SessionID string
Prompt string
ProviderOptions fantasy.ProviderOptions
- Attachments []message.Attachment
- MaxOutputTokens int64
- Temperature *float64
+ Attachments []message.Attachment
+ MaxOutputTokens int64
+ ShowToolCalls bool
+ Temperature *float64
TopP *float64
TopK *int64
FrequencyPenalty *float64
@@ -357,6 +358,9 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
// TODO: implement
},
OnToolCall: func(tc fantasy.ToolCallContent) error {
+ if call.ShowToolCalls {
+ slog.Default().WithGroup("TOOL").Info("call", "name", tc.ToolName, "input", tc.Input)
+ }
toolCall := message.ToolCall{
ID: tc.ToolCallID,
Name: tc.ToolName,
@@ -368,6 +372,30 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
return a.messages.Update(genCtx, *currentAssistant)
},
OnToolResult: func(result fantasy.ToolResultContent) error {
+ if call.ShowToolCalls {
+ content := ""
+ switch result.Result.GetType() {
+ case fantasy.ToolResultContentTypeText:
+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](result.Result); ok {
+ content = r.Text
+ }
+ case fantasy.ToolResultContentTypeError:
+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentError](result.Result); ok {
+ content = "Error: " + r.Error.Error()
+ }
+ case fantasy.ToolResultContentTypeMedia:
+ if r, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentMedia](result.Result); ok {
+ content = r.Text
+ if content == "" {
+ content = fmt.Sprintf("[%s content]", r.MediaType)
+ }
+ }
+ }
+ if len(content) > 200 {
+ content = content[:200] + "..."
+ }
+ slog.Default().WithGroup("TOOL").Info("result", "name", result.ToolName, "output", content)
+ }
toolResult := a.convertToToolResult(result)
_, createMsgErr := a.messages.Create(genCtx, currentAssistant.SessionID, message.CreateMessageParams{
Role: message.Tool,
@@ -46,7 +46,7 @@ import (
type Coordinator interface {
// INFO: (kujtim) this is not used yet we will use this when we have multiple agents
// SetMainAgent(string)
- Run(ctx context.Context, sessionID, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error)
+ Run(ctx context.Context, sessionID, prompt string, verbose bool, attachments ...message.Attachment) (*fantasy.AgentResult, error)
Cancel(sessionID string)
CancelAll()
IsSessionBusy(sessionID string) bool
@@ -116,7 +116,7 @@ func NewCoordinator(
}
// Run implements Coordinator.
-func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string, attachments ...message.Attachment) (*fantasy.AgentResult, error) {
+func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string, verbose bool, attachments ...message.Attachment) (*fantasy.AgentResult, error) {
if err := c.readyWg.Wait(); err != nil {
return nil, err
}
@@ -163,6 +163,7 @@ func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string,
Prompt: prompt,
Attachments: attachments,
MaxOutputTokens: maxTokens,
+ ShowToolCalls: verbose,
ProviderOptions: mergedOptions,
Temperature: temp,
TopP: topP,
@@ -145,7 +145,7 @@ func (app *App) Config() *config.Config {
// RunNonInteractive runs the application in non-interactive mode with the
// given prompt, printing to stdout.
-func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, largeModel, smallModel string, hideSpinner bool) error {
+func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, largeModel, smallModel string, hideSpinner bool, verbose bool) error {
slog.Info("Running in non-interactive mode")
ctx, cancel := context.WithCancel(ctx)
@@ -241,7 +241,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt,
done := make(chan response, 1)
go func(ctx context.Context, sessionID, prompt string) {
- result, err := app.AgentCoordinator.Run(ctx, sess.ID, prompt)
+ result, err := app.AgentCoordinator.Run(ctx, sess.ID, prompt, verbose)
if err != nil {
done <- response{
err: fmt.Errorf("failed to start agent processing stream: %w", err),
@@ -73,7 +73,7 @@ crush run --verbose "Generate a README for this project"
event.SetNonInteractive(true)
event.AppInitialized()
- return app.RunNonInteractive(ctx, os.Stdout, prompt, largeModel, smallModel, quiet || verbose)
+ return app.RunNonInteractive(ctx, os.Stdout, prompt, largeModel, smallModel, quiet || verbose, verbose)
},
PostRun: func(cmd *cobra.Command, args []string) {
event.AppExited()
@@ -2744,7 +2744,7 @@ func (m *UI) sendMessage(content string, attachments ...message.Attachment) tea.
// Capture session ID to avoid race with main goroutine updating m.session.
sessionID := m.session.ID
cmds = append(cmds, func() tea.Msg {
- _, err := m.com.App.AgentCoordinator.Run(context.Background(), sessionID, content, attachments...)
+ _, err := m.com.App.AgentCoordinator.Run(context.Background(), sessionID, content, false, attachments...)
if err != nil {
isCancelErr := errors.Is(err, context.Canceled)
isPermissionErr := errors.Is(err, permission.ErrorPermissionDenied)