@@ -14,6 +14,8 @@ import (
1414 "time"
1515
1616 batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
17+ "github.com/sourcegraph/sourcegraph/lib/batches/codingagent"
18+ codingagenttypes "github.com/sourcegraph/sourcegraph/lib/batches/codingagent/types"
1719 "github.com/sourcegraph/sourcegraph/lib/batches/execution"
1820 "github.com/sourcegraph/sourcegraph/lib/batches/git"
1921 "github.com/sourcegraph/sourcegraph/lib/batches/template"
@@ -272,12 +274,32 @@ func executeSingleStep(
272274 return bytes.Buffer {}, bytes.Buffer {}, err
273275 }
274276
275- runScriptFile , runScript , cleanup , err := createRunScriptFile (ctx , opts .TempDir , step .Run , stepContext )
277+ var (
278+ runScriptFile string
279+ runScript string
280+ runScriptCleanup func ()
281+ )
282+ if step .CodingAgent != nil {
283+ if opts .Task .ModelProviderURL == "" {
284+ err = errors .New ("codingAgent step requires WorkspacesExecutionInput.ModelProviderURL to be set" )
285+ opts .UI .StepPreparingFailed (stepIdx + 1 , err )
286+ return bytes.Buffer {}, bytes.Buffer {}, err
287+ }
288+ runScript , err = codingagent .RenderRunCommand (step .CodingAgent , opts .Task .ModelProviderURL , stepContext )
289+ if err != nil {
290+ err = errors .Wrap (err , "rendering codingAgent step" )
291+ opts .UI .StepPreparingFailed (stepIdx + 1 , err )
292+ return bytes.Buffer {}, bytes.Buffer {}, err
293+ }
294+ runScriptFile , runScriptCleanup , err = writeRunScriptFile (opts .TempDir , runScript )
295+ } else {
296+ runScriptFile , runScript , runScriptCleanup , err = createRunScriptFile (ctx , opts .TempDir , step .Run , stepContext )
297+ }
276298 if err != nil {
277299 opts .UI .StepPreparingFailed (stepIdx + 1 , err )
278300 return bytes.Buffer {}, bytes.Buffer {}, err
279301 }
280- defer cleanup ()
302+ defer runScriptCleanup ()
281303
282304 // Parse and render the step.Files.
283305 filesToMount , cleanup , err := createFilesToMount (opts .TempDir , step , stepContext )
@@ -303,6 +325,21 @@ func executeSingleStep(
303325 return bytes.Buffer {}, bytes.Buffer {}, err
304326 }
305327
328+ // For codingAgent steps, forward the model-provider auth env from the
329+ // executor's environment (injected via CliStep.Env and JobTokenEnvVar on
330+ // the server) into the user container so the agent CLI can talk to the
331+ // /model-provider/batches proxy.
332+ if step .CodingAgent != nil {
333+ for _ , key := range []string {codingagenttypes .ModelProviderTokenEnvVar , codingagenttypes .JobIDEnvVar } {
334+ for _ , e := range opts .GlobalEnv {
335+ if v , ok := strings .CutPrefix (e , key + "=" ); ok {
336+ env [key ] = v
337+ break
338+ }
339+ }
340+ }
341+ }
342+
306343 opts .UI .StepPreparingSuccess (stepIdx + 1 )
307344
308345 // ----------
@@ -573,6 +610,34 @@ func createRunScriptFile(ctx context.Context, tempDir string, stepRun string, st
573610 return runScriptFile .Name (), runScript .String (), cleanup , nil
574611}
575612
613+ // writeRunScriptFile writes a pre-rendered run script (e.g. a codingAgent
614+ // step desugared by the codingagent registry) verbatim to a temp file, with
615+ // the same permission semantics as createRunScriptFile. Unlike that helper,
616+ // this one does NOT pass the content through template.RenderStepTemplate:
617+ // the script is treated as opaque shell text so embedded sequences like
618+ // `{{` inside a shell-quoted prompt are not re-parsed as templates.
619+ func writeRunScriptFile (tempDir , script string ) (string , func (), error ) {
620+ runScriptFile , err := os .CreateTemp (tempDir , "" )
621+ if err != nil {
622+ return "" , nil , errors .Wrap (err , "creating temporary file" )
623+ }
624+ cleanup := func () { os .Remove (runScriptFile .Name ()) }
625+
626+ if _ , err := runScriptFile .WriteString (script ); err != nil {
627+ cleanup ()
628+ return "" , nil , errors .Wrap (err , "writing temporary file" )
629+ }
630+ if err := runScriptFile .Close (); err != nil {
631+ cleanup ()
632+ return "" , nil , errors .Wrap (err , "closing temporary file" )
633+ }
634+ if err := os .Chmod (runScriptFile .Name (), 0644 ); err != nil {
635+ cleanup ()
636+ return "" , nil , errors .Wrap (err , "setting permissions on the temporary file" )
637+ }
638+ return runScriptFile .Name (), cleanup , nil
639+ }
640+
576641// createCidFile creates a temporary file that will contain the container ID
577642// when executing steps.
578643// It returns the location of the file and a function that cleans up the
0 commit comments