on main help sign in
feat(shell): add blocking wait option to job_output tool (#2189)
commit9ec46b8d439646a505018576e7197b2daacfb7b3 authorSean Porter <portertech@gmail.com> dateMon 2 Mar 2026, 12:22 (8 months ago) parentda2eef2
5 files changed+45−6
internal/agent/common_test.go+3−6 internal/agent/tools/job_output.go+5 internal/agent/tools/job_output.md+3 internal/shell/background.go+9 internal/shell/background_test.go+25
internal/agent/common_test.go+3−6
@@ -182,12 +182,9 @@ func coderAgent(r *vcr.Recorder, env fakeEnv, large, small fantasy.LanguageModel
182182 GeneratedWith: true,
183183 }
184184
185− // Clear skills paths to ensure test reproducibility - user's skills
186− // would be included in prompt and break VCR cassette matching.
187− cfg.Options.SkillsPaths = []string{}
188−
189− // Clear LSP config to ensure test reproducibility - user's LSP config
190− // would be included in prompt and break VCR cassette matching.
185+ // Clear some fields to avoid issues with VCR cassette matching.
186+ cfg.Options.SkillsPaths = nil
187+ cfg.Options.ContextPaths = nil
191188 cfg.LSP = nil
192189
193190 systemPrompt, err := prompt.Build(context.TODO(), large.Provider(), large.Model(), *cfg)
internal/agent/tools/job_output.go+5
@@ -19,6 +19,7 @@ var jobOutputDescription []byte
1919
2020type JobOutputParams struct {
2121 ShellID string `json:"shell_id" description:"The ID of the background shell to retrieve output from"`
22+ Wait bool `json:"wait" description:"If true, block until the background shell completes before returning output"`
2223}
2324
2425type JobOutputResponseMetadata struct {
@@ -44,6 +45,10 @@ func NewJobOutputTool() fantasy.AgentTool {
4445 return fantasy.NewTextErrorResponse(fmt.Sprintf("background shell not found: %s", params.ShellID)), nil
4546 }
4647
48+ if params.Wait {
49+ bgShell.WaitContext(ctx)
50+ }
51+
4752 stdout, stderr, done, err := bgShell.GetOutput()
4853
4954 var outputParts []string
internal/agent/tools/job_output.md+3
@@ -4,16 +4,19 @@ Retrieves the current output from a background shell.
44- Provide the shell ID returned from a background bash execution
55- Returns the current stdout and stderr output
66- Indicates whether the shell has completed execution
7+- Set wait=true to block until the shell completes or the request context is done
78</usage>
89
910<features>
1011- View output from running background processes
1112- Check if background process has completed
1213- Get cumulative output from process start
14+- Optionally wait for process completion (returns early on context cancel)
1315</features>
1416
1517<tips>
1618- Use this to monitor long-running processes
1719- Check the 'done' status to see if process completed
1820- Can be called multiple times to view incremental output
21+- Use wait=true when you need the final output and exit status (or current output if the request cancels)
1922</tips>
internal/shell/background.go+9
@@ -234,3 +234,12 @@ func (bs *BackgroundShell) IsDone() bool {
234234func (bs *BackgroundShell) Wait() {
235235 <-bs.done
236236}
237+
238+func (bs *BackgroundShell) WaitContext(ctx context.Context) bool {
239+ select {
240+ case <-bs.done:
241+ return true
242+ case <-ctx.Done():
243+ return false
244+ }
245+}
internal/shell/background_test.go+25
@@ -307,3 +307,28 @@ func TestBackgroundShellManager_KillAll_Timeout(t *testing.T) {
307307 // Must return promptly after timeout, not hang for 60 seconds.
308308 require.Less(t, elapsed, 2*time.Second)
309309}
310+
311+func TestBackgroundShell_WaitContext_Completed(t *testing.T) {
312+ t.Parallel()
313+
314+ done := make(chan struct{})
315+ close(done)
316+
317+ bgShell := &BackgroundShell{done: done}
318+
319+ ctx, cancel := context.WithTimeout(t.Context(), time.Second)
320+ t.Cleanup(cancel)
321+
322+ require.True(t, bgShell.WaitContext(ctx))
323+}
324+
325+func TestBackgroundShell_WaitContext_Canceled(t *testing.T) {
326+ t.Parallel()
327+
328+ bgShell := &BackgroundShell{done: make(chan struct{})}
329+
330+ ctx, cancel := context.WithCancel(t.Context())
331+ cancel()
332+
333+ require.False(t, bgShell.WaitContext(ctx))
334+}