11package root
22
3- import (
4- "context"
5- "fmt"
6- "log/slog"
7- "os"
8- "path/filepath"
9- "strings"
10- "time"
11-
12- "github.com/spf13/cobra"
13- "go.opentelemetry.io/otel"
14-
15- "github.com/docker/cagent/pkg/remote"
16- "github.com/docker/cagent/pkg/runtime"
17- "github.com/docker/cagent/pkg/session"
18- "github.com/docker/cagent/pkg/teamloader"
19- )
3+ import "github.com/spf13/cobra"
204
215func NewExecCmd () * cobra.Command {
226 cmd := & cobra.Command {
237 Use : "exec <agent-name>" ,
248 Short : "Execute an agent" ,
259 Args : cobra .ExactArgs (1 ),
26- RunE : execCommand ,
10+ RunE : func (cmd * cobra.Command , args []string ) error {
11+ return runCommand (cmd , args , true )
12+ },
2713 }
2814
2915 cmd .PersistentFlags ().StringVarP (& agentName , "agent" , "a" , "root" , "Name of the agent to run" )
@@ -35,118 +21,3 @@ func NewExecCmd() *cobra.Command {
3521
3622 return cmd
3723}
38-
39- func execCommand (_ * cobra.Command , args []string ) error {
40- ctx := context .Background ()
41-
42- slog .Debug ("Starting agent" , "agent" , agentName , "debug_mode" , debugMode )
43-
44- agentFilename := args [0 ]
45- if ! strings .Contains (agentFilename , "\n " ) {
46- if abs , err := filepath .Abs (agentFilename ); err == nil {
47- agentFilename = abs
48- }
49- }
50-
51- if enableOtel {
52- shutdown , err := initOTelSDK (ctx )
53- if err != nil {
54- slog .Warn ("Failed to initialize OpenTelemetry SDK" , "error" , err )
55- } else if shutdown != nil {
56- defer func () {
57- shutdownCtx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
58- defer cancel ()
59- if err := shutdown (shutdownCtx ); err != nil {
60- slog .Warn ("Failed to shutdown OpenTelemetry SDK" , "error" , err )
61- }
62- }()
63- slog .Debug ("OpenTelemetry SDK initialized successfully" )
64- }
65- }
66-
67- // If working-dir was provided, validate and change process working directory
68- if workingDir != "" {
69- absWd , err := filepath .Abs (workingDir )
70- if err != nil {
71- return fmt .Errorf ("invalid working directory: %w" , err )
72- }
73- info , err := os .Stat (absWd )
74- if err != nil || ! info .IsDir () {
75- return fmt .Errorf ("working directory does not exist or is not a directory: %s" , absWd )
76- }
77- if err := os .Chdir (absWd ); err != nil {
78- return fmt .Errorf ("failed to change working directory: %w" , err )
79- }
80- _ = os .Setenv ("PWD" , absWd )
81- slog .Debug ("Working directory set" , "dir" , absWd )
82- }
83-
84- // Determine how to obtain the agent definition
85- ext := strings .ToLower (filepath .Ext (agentFilename ))
86- if ext == ".yaml" || ext == ".yml" {
87- // Treat as local YAML file: resolve to absolute path so later chdir doesn't break it
88- if ! strings .Contains (agentFilename , "\n " ) {
89- if abs , err := filepath .Abs (agentFilename ); err == nil {
90- agentFilename = abs
91- }
92- }
93- if ! fileExists (agentFilename ) {
94- return fmt .Errorf ("agent file not found: %s" , agentFilename )
95- }
96- } else {
97- // Treat as an OCI image reference. Try local store first, otherwise pull then load.
98- a , err := fromStore (agentFilename )
99- if err != nil {
100- fmt .Println ("Pulling agent " , agentFilename )
101- if _ , pullErr := remote .Pull (agentFilename ); pullErr != nil {
102- return fmt .Errorf ("failed to pull OCI image %s: %w" , agentFilename , pullErr )
103- }
104- // Retry after pull
105- a , err = fromStore (agentFilename )
106- if err != nil {
107- return fmt .Errorf ("failed to load agent from store after pull: %w" , err )
108- }
109- }
110-
111- // Write the fetched content to a temporary YAML file
112- tmpFile , err := os .CreateTemp ("" , "agentfile-*.yaml" )
113- if err != nil {
114- return err
115- }
116- defer os .Remove (tmpFile .Name ())
117- if _ , err := tmpFile .WriteString (a ); err != nil {
118- tmpFile .Close ()
119- return err
120- }
121- if err := tmpFile .Close (); err != nil {
122- return err
123- }
124- agentFilename = tmpFile .Name ()
125- }
126-
127- agents , err := teamloader .Load (ctx , agentFilename , runConfig )
128- if err != nil {
129- return err
130- }
131- defer func () {
132- if err := agents .StopToolSets (); err != nil {
133- slog .Error ("Failed to stop tool sets" , "error" , err )
134- }
135- }()
136-
137- tracer := otel .Tracer (APP_NAME )
138-
139- rt , err := runtime .New (agents ,
140- runtime .WithCurrentAgent (agentName ),
141- runtime .WithAutoRunTools (autoApprove ),
142- runtime .WithTracer (tracer ),
143- )
144- if err != nil {
145- return fmt .Errorf ("failed to create runtime: %w" , err )
146- }
147-
148- sess := session .New ()
149- sess .Title = "Running agent"
150-
151- return runWithoutTUI (ctx , agentFilename , rt , sess , []string {"exec" , "Follow the default instructions" })
152- }
0 commit comments