RunWithMessage runs the agent loop with a pre-constructed message. This is used for special cases like image attachments.
(ctx context.Context, cancel context.CancelFunc, msg *session.Message)
| 680 | // RunWithMessage runs the agent loop with a pre-constructed message. |
| 681 | // This is used for special cases like image attachments. |
| 682 | func (a *App) RunWithMessage(ctx context.Context, cancel context.CancelFunc, msg *session.Message) { |
| 683 | a.cancel = cancel |
| 684 | |
| 685 | // If this is the first message and no title exists, start local title generation |
| 686 | if a.session.Title == "" && a.titleGen != nil { |
| 687 | a.titleGenerating.Store(true) |
| 688 | // Extract text content from the message for title generation |
| 689 | userMessage := msg.Message.Content |
| 690 | if userMessage == "" && len(msg.Message.MultiContent) > 0 { |
| 691 | for _, part := range msg.Message.MultiContent { |
| 692 | if part.Type == chat.MessagePartTypeText { |
| 693 | userMessage = part.Text |
| 694 | break |
| 695 | } |
| 696 | } |
| 697 | } |
| 698 | go a.generateTitle(ctx, []string{userMessage}) |
| 699 | } |
| 700 | |
| 701 | go func() { |
| 702 | a.session.AddMessage(msg) |
| 703 | for event := range a.runtime.RunStream(ctx, a.session) { |
| 704 | // If context is cancelled, continue draining but don't forward events |
| 705 | // — except StreamStoppedEvent, which must always propagate so the |
| 706 | // supervisor can mark the session as no longer running. |
| 707 | if ctx.Err() != nil { |
| 708 | if _, ok := event.(*runtime.StreamStoppedEvent); ok { |
| 709 | // ctx is cancelled; detach cancellation but keep its trace |
| 710 | // context so the stop event still reaches subscribers. |
| 711 | a.sendEvent(context.WithoutCancel(ctx), event) |
| 712 | } |
| 713 | continue |
| 714 | } |
| 715 | |
| 716 | // Clear titleGenerating flag when title is generated (from server for remote runtime) |
| 717 | if _, ok := event.(*runtime.SessionTitleEvent); ok { |
| 718 | a.titleGenerating.Store(false) |
| 719 | } |
| 720 | |
| 721 | a.sendEvent(ctx, event) |
| 722 | } |
| 723 | }() |
| 724 | } |
| 725 | |
| 726 | func (a *App) RunBangCommand(ctx context.Context, command string) { |
| 727 | command = strings.TrimSpace(command) |
no test coverage detected