MCPcopy
hub / github.com/docker/docker-agent / Run

Function Run

pkg/cli/runner.go:82–326  ·  view source on GitHub ↗

Run executes an agent in non-TUI mode, handling user input and runtime events. userMessages contains the user messages to send. If a single message is "-", input is read from stdin. If empty, an interactive prompt loop is started.

(ctx context.Context, out *Printer, cfg Config, rt runtime.Runtime, sess *session.Session, userMessages []string)

Source from the content-addressed store, hash-verified

80// userMessages contains the user messages to send. If a single message is "-",
81// input is read from stdin. If empty, an interactive prompt loop is started.
82func Run(ctx context.Context, out *Printer, cfg Config, rt runtime.Runtime, sess *session.Session, userMessages []string) error {
83 // Create a cancellable context for this agentic loop and wire Ctrl+C to cancel it
84 ctx, cancel := context.WithCancel(ctx)
85 defer cancel()
86
87 // Ensure telemetry is initialized and add to context so runtime can access it
88 telemetry.EnsureGlobalTelemetryInitialized(ctx)
89 if telemetryClient := telemetry.GetGlobalTelemetryClient(ctx); telemetryClient != nil {
90 ctx = telemetry.WithClient(ctx, telemetryClient)
91 }
92
93 sess.Title = "Running agent"
94 // If the last received event was an error, return it. That way the exit code
95 // will be non-zero if the agent failed.
96 var lastErr error
97
98 oneLoop := func(text string, rd io.Reader) error {
99 autoExtensions := 0
100
101 userInput := strings.TrimSpace(text)
102 if userInput == "" {
103 return nil
104 }
105
106 userMsg, attachedPath, err := PrepareUserMessage(ctx, rt, userInput, cfg.AttachmentPath)
107 if err != nil {
108 return fmt.Errorf("failed to prepare message: %w", err)
109 }
110 if userMsg == nil {
111 // Agent-only command with no content - agent switched but no message to send
112 return nil
113 }
114 sess.AddMessage(userMsg)
115 sess.AddAttachedFile(attachedPath)
116
117 if cfg.OutputJSON {
118 for event := range rt.RunStream(ctx, sess) {
119 switch e := event.(type) {
120 case *runtime.ToolCallConfirmationEvent:
121 // JSON mode has no user at stdin — reject unconditionally.
122 // A confirmation event under AutoApprove means a
123 // preempt-yolo hook overrode --yolo; the safe answer is
124 // still Reject (the hook said Ask, not Approve).
125 rt.Resume(ctx, runtime.ResumeReject(""))
126 case *runtime.ElicitationRequestEvent:
127 _ = rt.ResumeElicitation(ctx, "decline", nil)
128 case *runtime.MaxIterationsReachedEvent:
129 switch handleMaxIterationsAutoApprove(cfg.AutoApprove, &autoExtensions, e.MaxIterations) {
130 case maxIterContinue:
131 rt.Resume(ctx, runtime.ResumeApprove())
132 default: // maxIterStop or maxIterPrompt (no interactive prompt in JSON mode)
133 rt.Resume(ctx, runtime.ResumeReject(""))
134 return nil
135 }
136 case *runtime.ErrorEvent:
137 return fmt.Errorf("%s", e.Error)
138 }
139

Calls 15

GetGlobalTelemetryClientFunction · 0.92
WithClientFunction · 0.92
ResumeRejectFunction · 0.92
ResumeApproveFunction · 0.92
ResumeApproveSessionFunction · 0.92
ReadLineFunction · 0.92
PrepareUserMessageFunction · 0.85
AddAttachedFileMethod · 0.80
PrintlnMethod · 0.80
PrintAgentNameMethod · 0.80