feat: background jobs & remove persistent shell (#1328)

Kujtim Hoxha , Christian Rocha , Raphael Amorim , and Andrey Nering created

Co-authored-by: Christian Rocha <christian@rocha.is>
Co-authored-by: Raphael Amorim <rapha850@gmail.com>
Co-authored-by: Andrey Nering <andreynering@users.noreply.github.com>

Change summary

internal/agent/agent_test.go                                                       |   2 
internal/agent/coordinator.go                                                      |   2 
internal/agent/templates/coder.md.tpl                                              |   1 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/bash_tool.yaml             |  25 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/download_tool.yaml         |  26 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/fetch_tool.yaml            |  24 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/glob_tool.yaml             |  26 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/grep_tool.yaml             |  25 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/ls_tool.yaml               |  28 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/multiedit_tool.yaml        |  25 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/parallel_tool_calls.yaml   |  30 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/read_a_file.yaml           |  23 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/simple_test.yaml           |  18 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/sourcegraph_tool.yaml      |  24 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/update_a_file.yaml         |  22 
internal/agent/testdata/TestCoderAgent/anthropic-sonnet/write_tool.yaml            |  24 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/bash_tool.yaml                 |  30 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/download_tool.yaml             |  24 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/fetch_tool.yaml                |  28 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/glob_tool.yaml                 |  28 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/grep_tool.yaml                 |  30 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/ls_tool.yaml                   |  30 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/multiedit_tool.yaml            |  38 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/parallel_tool_calls.yaml       |  30 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/read_a_file.yaml               |  20 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/simple_test.yaml               |  12 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/sourcegraph_tool.yaml          |  34 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/update_a_file.yaml             |  30 
internal/agent/testdata/TestCoderAgent/openai-gpt-5/write_tool.yaml                |  34 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/bash_tool.yaml           |   3 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/download_tool.yaml       |  24 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/fetch_tool.yaml          |   2 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/glob_tool.yaml           |  20 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/grep_tool.yaml           |  26 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/ls_tool.yaml             |  18 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/multiedit_tool.yaml      |  20 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/parallel_tool_calls.yaml |  20 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/read_a_file.yaml         |  18 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/simple_test.yaml         |  12 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/sourcegraph_tool.yaml    |  30 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/update_a_file.yaml       |  26 
internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/write_tool.yaml          |  16 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/bash_tool.yaml                   |  22 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/download_tool.yaml               |  22 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/fetch_tool.yaml                  |   2 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/glob_tool.yaml                   |  20 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/grep_tool.yaml                   |  22 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/ls_tool.yaml                     |   2 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/multiedit_tool.yaml              |  20 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/parallel_tool_calls.yaml         |  18 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/read_a_file.yaml                 |  16 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/simple_test.yaml                 |  10 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/sourcegraph_tool.yaml            |   2 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/update_a_file.yaml               |  24 
internal/agent/testdata/TestCoderAgent/zai-glm4.6/write_tool.yaml                  |  20 
internal/agent/tools/bash.go                                                       | 239 
internal/agent/tools/bash.tpl                                                      |  30 
internal/agent/tools/job_kill.go                                                   |  59 
internal/agent/tools/job_kill.md                                                   |  18 
internal/agent/tools/job_output.go                                                 |  85 
internal/agent/tools/job_output.md                                                 |  19 
internal/agent/tools/job_test.go                                                   | 371 
internal/app/app.go                                                                |   4 
internal/config/config.go                                                          |   2 
internal/config/load_test.go                                                       |   5 
internal/shell/background.go                                                       | 201 
internal/shell/background_test.go                                                  | 276 
internal/shell/doc.go                                                              |   7 
internal/shell/persistent.go                                                       |  43 
internal/shell/shell.go                                                            |  70 
internal/tui/components/chat/messages/renderer.go                                  | 158 
internal/tui/components/dialogs/permissions/permissions.go                         |  40 
internal/tui/styles/charmtone.go                                                   |   1 
internal/tui/styles/theme.go                                                       |   1 
74 files changed, 2,047 insertions(+), 710 deletions(-)

Detailed changes

internal/agent/agent_test.go 🔗

@@ -10,7 +10,6 @@ import (
 	"charm.land/fantasy"
 	"github.com/charmbracelet/crush/internal/agent/tools"
 	"github.com/charmbracelet/crush/internal/message"
-	"github.com/charmbracelet/crush/internal/shell"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
@@ -40,7 +39,6 @@ func setupAgent(t *testing.T, pair modelPair) (SessionAgent, fakeEnv) {
 
 	createSimpleGoProject(t, env.workingDir)
 	agent, err := coderAgent(r, env, large, small)
-	shell.Reset(env.workingDir)
 	require.NoError(t, err)
 	return agent, env
 }

internal/agent/coordinator.go 🔗

@@ -329,6 +329,8 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
 
 	allTools = append(allTools,
 		tools.NewBashTool(c.permissions, c.cfg.WorkingDir(), c.cfg.Options.Attribution),
+		tools.NewJobOutputTool(),
+		tools.NewJobKillTool(),
 		tools.NewDownloadTool(c.permissions, c.cfg.WorkingDir(), nil),
 		tools.NewEditTool(c.lspClients, c.permissions, c.history, c.cfg.WorkingDir()),
 		tools.NewMultiEditTool(c.lspClients, c.permissions, c.history, c.cfg.WorkingDir()),

internal/agent/templates/coder.md.tpl 🔗

@@ -267,6 +267,7 @@ After significant changes:
 - Run tools in parallel when safe (no dependencies)
 - When making multiple independent bash calls, send them in a single message with multiple tool calls for parallel execution
 - Summarize tool output for user (they don't see it)
+- Never use `curl` through the bash tool it is not allowed use the fetch tool instead.
 
 <bash_commands>
 When running non-trivial bash commands (especially those that modify the system):

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/bash_tool.yaml 🔗

@@ -25,52 +25,49 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01GbNg6Ry9zebpJZ4SxbcBWA","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":152,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}              }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01BW37WH53V4Z7Gf3DR8jPr3","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":152,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}}               }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}            }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}               }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Creating"}               }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Bash File"}   }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" a bash"}            }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Creation"}     }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" file"}            }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Comman"}              }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with hello"}      }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" message"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d"}}
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0        }
+      data: {"type":"content_block_stop","index":0            }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":152,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10} }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":152,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":8}          }
 
       event: message_stop
-      data: {"type":"message_stop"}
+      data: {"type":"message_stop"   }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.497832667s
+    duration: 623.712083ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46761
+    content_length: 48167
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/download_tool.yaml 🔗

@@ -25,52 +25,46 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01UXxqRskCGYn8pLqqgaFbfK","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":160,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}             }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01P5o6v2z5ytJajMbZyVnZ9f","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":160,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}            }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}         }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Downloa"}              }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Downloa"}           }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d File"}               }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d File"} }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" from"}            }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Example-"}         }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Files Website"}     }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" from Example URL"}          }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0    }
+      data: {"type":"content_block_stop","index":0      }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":160,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10}           }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":160,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":8} }
 
       event: message_stop
-      data: {"type":"message_stop"          }
+      data: {"type":"message_stop"       }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.152031084s
+    duration: 671.161959ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46786
+    content_length: 48192
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/fetch_tool.yaml 🔗

@@ -25,52 +25,52 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01QBUSTN71eh95F8NGHNVJ7r","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":167,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}        }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01EUnasCuquQGHSiynduKr65","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":167,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}}   }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}               }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Web"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Fetch HTML"}              }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Page Content Search"}         }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" an"}          }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Search"}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" John"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for John"} }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Doe"}     }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Doe"}         }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0    }
+      data: {"type":"content_block_stop","index":0       }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":167,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":11}   }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":167,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":12}         }
 
       event: message_stop
-      data: {"type":"message_stop"            }
+      data: {"type":"message_stop"              }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 840.714166ms
+    duration: 693.344541ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46804
+    content_length: 48210
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/glob_tool.yaml 🔗

@@ -25,52 +25,46 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_014RSxCeV1UGnPSQkNpEQTUq","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}            }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_012G4Ey7XfMSsGWGYiqxsRUU","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}          }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}              }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}        }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Fin"}}
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Fin"} }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Go"}         }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Go"} }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Files"}         }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"}}
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Glob"}    }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Files in Current Directory"}   }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0}
+      data: {"type":"content_block_stop","index":0              }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}             }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":142,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}          }
 
       event: message_stop
-      data: {"type":"message_stop"         }
+      data: {"type":"message_stop"          }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 546.158083ms
+    duration: 740.673625ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46722
+    content_length: 48128
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/grep_tool.yaml 🔗

@@ -25,52 +25,49 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01MMg192G5uVZkAaHV6NCB7T","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}}  }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_019nbTGENunFZWMy5WFQFGba","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}}          }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}              }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}               }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Searching"}        }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Searching"} }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Packages"}   }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for 'package'"}          }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" in Go Files"}     }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" in Go files with"}  }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"}          }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Grep"}         }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" grep"}   }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0              }
+      data: {"type":"content_block_stop","index":0        }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":13}    }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":144,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":15}          }
 
       event: message_stop
-      data: {"type":"message_stop"              }
+      data: {"type":"message_stop"               }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 781.230459ms
+    duration: 646.108708ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46720
+    content_length: 48126
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/ls_tool.yaml 🔗

@@ -25,49 +25,49 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01B7Qa35Q32jAQNEVkyd7y87","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}} }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_012GTzELAf2uYkkHHqg4T5ep","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":3,"service_tier":"standard"}}    }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}  }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}               }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Listing Files"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Listing Files"}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" in Current Directory"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"}               }
 
       event: ping
       data: {"type": "ping"}
 
-      event: content_block_stop
-      data: {"type":"content_block_stop","index":0         }
+      event: content_block_delta
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" ls Comman"}          }
 
-      event: ping
-      data: {"type": "ping"}
+      event: content_block_delta
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d"}  }
 
-      event: ping
-      data: {"type": "ping"}
+      event: content_block_stop
+      data: {"type":"content_block_stop","index":0        }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}   }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":140,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}    }
 
       event: message_stop
-      data: {"type":"message_stop"            }
+      data: {"type":"message_stop"       }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 750.596875ms
+    duration: 547.828833ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46714
+    content_length: 48120
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/multiedit_tool.yaml 🔗

@@ -25,52 +25,49 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_015YzXs6XaPmruFbmBEQmbzN","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}          }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01LzZGtFxbJYEwsj8JRLRXXx","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}  }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}          }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Edit"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Go"}    }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go"}    }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Mult"}  }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Code"}    }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"iedit Text"}           }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Greeting"}        }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Modification"}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Modification"}     }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0      }
+      data: {"type":"content_block_stop","index":0        }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10}               }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":170,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":11}     }
 
       event: message_stop
-      data: {"type":"message_stop"        }
+      data: {"type":"message_stop" }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 728.836709ms
+    duration: 623.774291ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46800
+    content_length: 48206
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/parallel_tool_calls.yaml 🔗

@@ -25,58 +25,52 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01PPi2LYDWFX14idF4WAuxdH","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}}        }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01MfzuLY7CdeN6m3jrCSh5cL","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}}     }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}  }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}        }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Parallel"}}
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Parallel"}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" File"}            }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go File"}}
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Discovery"}  }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Search"}               }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"}     }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" with"}           }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Glob"}            }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" and "}    }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"LS"}   }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Glob and Ls"}      }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0            }
+      data: {"type":"content_block_stop","index":0}
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":13}       }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":159,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":14}       }
 
       event: message_stop
-      data: {"type":"message_stop"}
+      data: {"type":"message_stop"      }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 774.758583ms
+    duration: 564.880666ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46811
+    content_length: 48217
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/read_a_file.yaml 🔗

@@ -25,49 +25,46 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_013ygFg57WnsbgYEgWKpUHgg","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}  }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01KuDqAdkBeMnewXBt4B1ngG","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}      }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}              }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Rea"}               }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Rea"}}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Go"}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d Go"}    }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Module"}         }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Details"}        }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Mod File"}       }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0         }
+      data: {"type":"content_block_stop","index":0}
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":7}       }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":134,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":8}}
 
       event: message_stop
-      data: {"type":"message_stop"             }
+      data: {"type":"message_stop"          }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 543.64625ms
+    duration: 600.296166ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46684
+    content_length: 48090
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/simple_test.yaml 🔗

@@ -25,22 +25,22 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01EmVyk4hid2PC6VniyWihaR","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}    }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01H4wGuG1Y65a7iaqwy3QUtz","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}          }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}     }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}        }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Quick"}  }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Quick"}   }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Greeting"}            }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Greeting"}       }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0            }
+      data: {"type":"content_block_stop","index":0      }
 
       event: ping
       data: {"type": "ping"}
@@ -49,25 +49,25 @@ interactions:
       data: {"type": "ping"}
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":6}          }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":131,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":6}   }
 
       event: message_stop
-      data: {"type":"message_stop"}
+      data: {"type":"message_stop"       }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.063515458s
+    duration: 596.61075ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46674
+    content_length: 48080
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/sourcegraph_tool.yaml 🔗

@@ -25,52 +25,52 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01KYmwLRQ7WjQjA2pbUzEhvU","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}} }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01EFWT9aj9NAQsXZyEJpLVH9","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard"}}  }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}  }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}              }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Go"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Searching"}        }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Repo"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Go"}}
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Main"}}
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Repos"}   }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Function"}      }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for Main"}     }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Search"}            }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Function"}     }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0}
+      data: {"type":"content_block_stop","index":0        }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}}
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":11}}
 
       event: message_stop
-      data: {"type":"message_stop"              }
+      data: {"type":"message_stop"        }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.002887292s
+    duration: 671.395959ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46734
+    content_length: 48140
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/update_a_file.yaml 🔗

@@ -25,49 +25,49 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01RwCAShrU1kRMXy4cvo5e5t","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}         }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01MneyV4KwU6z98RNMi7jfdx","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}    }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}  }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Update"}        }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Update"}          }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" main"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" main"}   }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".go Hello"}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".go Hello"}  }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Message"}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Print"}         }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0       }
+      data: {"type":"content_block_stop","index":0           }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9} }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":145,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":9}         }
 
       event: message_stop
-      data: {"type":"message_stop"     }
+      data: {"type":"message_stop"              }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 682.594041ms
+    duration: 528.097ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46740
+    content_length: 48146
     host: ""

internal/agent/testdata/TestCoderAgent/anthropic-sonnet/write_tool.yaml 🔗

@@ -25,52 +25,52 @@ interactions:
     content_length: -1
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01FXMC8aT9YaPtMV15mGZNsp","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} }
+      data: {"type":"message_start","message":{"model":"claude-3-5-haiku-20241022","id":"msg_01B7wz3JqCXJ8k1FCs7oiJRZ","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}}          }
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}              }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}  }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Creating"}         }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Create"}    }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" config"}        }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" config"}    }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".json with"}               }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":".json with"}     }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" JSON"}           }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" initial"}           }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" data"}              }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" settings"}   }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0               }
+      data: {"type":"content_block_stop","index":0   }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10}  }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":161,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":10}          }
 
       event: message_stop
-      data: {"type":"message_stop"}
+      data: {"type":"message_stop"  }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 950.954959ms
+    duration: 558.946333ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 46777
+    content_length: 48183
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/bash_tool.yaml 🔗

@@ -24,23 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pttO1OA8dsQGEG"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xLiPDtF21xnwQi"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Create"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0RUeMk1U5O"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Create"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PwKNji8dcY"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" File"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wLi9GRw5fqJ"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" test"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GeWxV4FpUBt"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"21x6SCO5rY2"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":".txt"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KTaSuKtdA6Yf"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Content"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0nwcSIkE"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"YMPRaUodANt"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"txtgsExxlu5Ep"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"M6Z0QVfV7wLokm"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Bash"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SouwjjVL0HG"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xjLRpLwa3l5"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"UIjY7l3Fq2"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" bash"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PP7y94GVGN0"}
 
-      data: {"id":"chatcmpl-CWhWs20Zop6sbl4OStZokp9a0vd9d","object":"chat.completion.chunk","created":1761909858,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":145,"completion_tokens":6,"total_tokens":151,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"FzDWgx8tnMDVXf"}
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mCO8D71d5qxSNKk"}
+
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"aGB93PWCfz5od"}
+
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Bash"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2682ZwpDVAT"}
+
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"IG69BayfAE"}
+
+      data: {"id":"chatcmpl-CZE57vWFBMUe0TGenONLCx4Jrdv7C","object":"chat.completion.chunk","created":1762511645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":145,"completion_tokens":10,"total_tokens":155,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"nkj887rNxnHhK"}
 
       data: [DONE]
 
@@ -49,15 +57,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 526.4125ms
+    duration: 551.169541ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45186
+    content_length: 46567
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/download_tool.yaml 🔗

@@ -24,23 +24,25 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pRl8hi4mKyV7v4"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GTxcS4ivcrRIk4"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Download"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6Ty98YpI"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Download"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"rx77h917"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"9QyOAidqj1g1"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CBKVidslQhiC"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Save"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vN0Iq39KAX0"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Save"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"decmrJboELm"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SUk4BJZ9jFVGsF"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" File"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KagCunbTrBc"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Text"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"9Ce03nGGaDK"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" from"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PmhdVz0RSCd"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" File"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GYeSvnujasB"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Online"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"yjuH6cQSl"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"tW1ZfW5I0o"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Source"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"yv1frYi2t"}
 
-      data: {"id":"chatcmpl-CWhX9tjyqID6dcImwmtScsTH2gMCA","object":"chat.completion.chunk","created":1761909875,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":148,"completion_tokens":6,"total_tokens":154,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"KCYAxQFjHWFd2L"}
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"JtIixFIwII"}
+
+      data: {"id":"chatcmpl-CZE5VvQ9Q9ZumcLZHy5fKHyUpuxZD","object":"chat.completion.chunk","created":1762511669,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":148,"completion_tokens":7,"total_tokens":155,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"gW8jKCv7ceq2gm"}
 
       data: [DONE]
 
@@ -49,15 +51,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 515.942833ms
+    duration: 832.200292ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45211
+    content_length: 46592
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/fetch_tool.yaml 🔗

@@ -24,25 +24,29 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"NmqSJ50vbN4r42"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"24lk9UzVZeMq0b"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Check"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sr4OJu3lLyu"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Check"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"b4k3JA5gfrQ"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" HTML"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KmaFu3GGouR"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6niy6mqasTfs"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"H245qWL5SGiq"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KTZiXZIhnWPRDO"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" John"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZUvzYSFf8lB"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"John"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HBPw2NZA7AqH"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Doe"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"s8QJh8k4MHNa"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Doe"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pfyDEyIsEl6K"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Occ"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"5isKdqUb0HOD"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Kex8pffaSwtllBZ"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"urrence"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ghVyn4TaC"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"aYxHlIo2CwLXT"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"IQcLjlqYzI"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" HTML"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"curPronOb82"}
 
-      data: {"id":"chatcmpl-CWhXOu4oZ9WdLk0MqlX7ErUyg1LEH","object":"chat.completion.chunk","created":1761909890,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":153,"completion_tokens":7,"total_tokens":160,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"4FTCmELUOWr1y1"}
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Content"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KNlozOLs"}
+
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"mbbUHWp6XA"}
+
+      data: {"id":"chatcmpl-CZE5itAHQitbsj8vl7asuegDY7eDi","object":"chat.completion.chunk","created":1762511682,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":153,"completion_tokens":9,"total_tokens":162,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"yelQdryrIspGgE"}
 
       data: [DONE]
 
@@ -51,15 +55,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 532.60175ms
+    duration: 997.974958ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45229
+    content_length: 46610
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/glob_tool.yaml 🔗

@@ -24,29 +24,29 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nUGlLYeV4PG3P7"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZeloaUmVXmV3UM"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Finding"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"aPwkd1hKI"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Finding"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"U0HylEx7I"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" ."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lzKg5YVSFHVwma"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" ."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"rGsm45qEg9oxMV"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"BEOfuOOPpuDTu1"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tZUkIujqqsxSp6"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"H5gIqlzUGQ"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"eSHrrqnqas"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Q63P87LfKEJ"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"v0wgfhKFLR"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Glob"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GoNoWnJtfSk"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Glob"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"si6SHfPPoUe"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tX6giDfA1VUuB"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fofLtCcZpilFs"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lpFxnTag"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ug7MGDYD"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Directory"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sFvWcn"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Directory"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fV1mcb"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"3bg73MZKl9"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"flF0Dw3RDp"}
 
-      data: {"id":"chatcmpl-CWhXWSMCr6qB3gnWTLgyqU7xhyNfD","object":"chat.completion.chunk","created":1761909898,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":137,"completion_tokens":9,"total_tokens":146,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"pSfi02ffdiVgGo"}
+      data: {"id":"chatcmpl-CZE5wkP6U7wWOAbK1Hh7xSoNtOw0G","object":"chat.completion.chunk","created":1762511696,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":137,"completion_tokens":9,"total_tokens":146,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"TR7tXS4LODDbMJ"}
 
       data: [DONE]
 
@@ -55,15 +55,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 420.291ms
+    duration: 474.71925ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45147
+    content_length: 46528
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/grep_tool.yaml 🔗

@@ -24,31 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GoaiUY1uzWtKYt"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HjRwF8F2qrEXKB"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Search"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZAPV7XTqck"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Searching"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"FGY00tN"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"J8yw8jrWnNUr"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zCT3ZgOp3iIE"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"XdxqK7R5JFw0F5"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jwNhjwJQcQ1TbU"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"package"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wkBDR8dQf"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"package"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7Ct9rW88T"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vXtbve7G3a8maN4"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MCab8IUajFVb0DR"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8wf45VJIxwFsZ"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"TluTK2tc2Ke2p"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pRsCVMZRQ070q"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"WC7Ziq9dJf0UX"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"x7uOQzDFpI"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UtinIyWPX0"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2IWrOTMyMS"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pUDmsovsz0"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" grep"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KxgMgUqrUvo"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" grep"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xohJTpJPeJ4"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"7ovkOmaQwj"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"bcFXOEK8iU"}
 
-      data: {"id":"chatcmpl-CWhXc3eVJlBmjRe4RlplK8Xv5mR1Z","object":"chat.completion.chunk","created":1761909904,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":138,"completion_tokens":10,"total_tokens":148,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"7o8VW7i5JEpVy"}
+      data: {"id":"chatcmpl-CZE68TPTAAGmYeatVSMaVIqqaGVcH","object":"chat.completion.chunk","created":1762511708,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":138,"completion_tokens":10,"total_tokens":148,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"XGxovtRLyNBgp"}
 
       data: [DONE]
 
@@ -57,15 +57,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.038688833s
+    duration: 534.6675ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45145
+    content_length: 46526
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/ls_tool.yaml 🔗

@@ -24,31 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MCWFcLhdK58FbJ"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6R26gKN5fZOjCV"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"3EBKxRkyeGg"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"List"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EOYC87ekHkmP"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xIi5UalBhOwMbg"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7UcrEFxbZr"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"ls"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CAVw4k1WmiwjLa"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0eovVXuRpM"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"F3Bq812chIUIzGX"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" ls"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7zlVbwEOq9WAR"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"95ULPKgMvp7To"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Command"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PJ6Bq75W"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" List"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"r5GrJW1wmqP"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"AzhDVIuZRX"}
 
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MxdLTHikvT"}
-
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QGNfitR1P70YY"}
-
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sUeNiG4y"}
-
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Directory"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"J0RDzd"}
-
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"5QOUpMs2Ml"}
-
-      data: {"id":"chatcmpl-CWhXkFTjwl5xUXnehGUg9PaN6qNq8","object":"chat.completion.chunk","created":1761909912,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":135,"completion_tokens":10,"total_tokens":145,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"vFQ6uI3Cg2SNR"}
+      data: {"id":"chatcmpl-CZE6HunYfEO9WVX01VDwX5eXEwzWn","object":"chat.completion.chunk","created":1762511717,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":135,"completion_tokens":5,"total_tokens":140,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"v3ls1TGGV9Wdi6"}
 
       data: [DONE]
 
@@ -57,15 +47,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 426.932792ms
+    duration: 534.293042ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45139
+    content_length: 46520
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/multiedit_tool.yaml 🔗

@@ -24,35 +24,39 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vib8DrjqB0M7hn"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VlrDKC9qcowk5h"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Modify"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1k07w3fzQu"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Change"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"WZMfcORtjX"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GyM9bWqkLw92Vr"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"M3wbFgfke25fgU"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CUtYPUorfpS"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"31PgIDjJBrt"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qJjRwbZDfVEbChS"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gvZBEhCpr1U6F8K"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" World"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"a8xCMyxcxi"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" World"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CkbIFImtJJ"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"!'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kaNX4o0E836bQf"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"!'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jA8WouAOCEZnzM"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KZw6b8gqUCMF"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"f3NeE7JwyHaBT"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Add"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"C7aH71QYiC4X"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"O6iQP9usvmSgw1"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Comment"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"rLwLkf9r"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"j1Em0GDCrzJ"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2jC9m9myYQL9E"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lvLlxmIVcwv393N"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"G4ZfwxDqjIx"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Crush"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"iqh403E0ip"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":".go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zOlVgRrJ3tTdH"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"!'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"p0K6GP22WHp5nJ"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"E7YvkSyrAi"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nhB0LVdgggJ"}
 
-      data: {"id":"chatcmpl-CWhXqpTXLkin7AKNshvJ7Z7SfYWRL","object":"chat.completion.chunk","created":1761909918,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":157,"completion_tokens":12,"total_tokens":169,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"gDJn2sP6sddQe"}
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Comment"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"X4k5nftg"}
+
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"e7aLkqat0S"}
+
+      data: {"id":"chatcmpl-CZE6QBIW9dSOd6O0DUYws6Pj5rf97","object":"chat.completion.chunk","created":1762511726,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":157,"completion_tokens":14,"total_tokens":171,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"itkVihRYyVrCq"}
 
       data: [DONE]
 
@@ -61,15 +65,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 911.194292ms
+    duration: 612.684916ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45225
+    content_length: 46606
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/parallel_tool_calls.yaml 🔗

@@ -24,29 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7Cz8ZXHoTLl4gu"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EErvf1Q5GMhWpX"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Run"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Kk1HPfHLJ3CkO"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Running"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"nAz9oAW16"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Glob"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"DR9fbWtQCxy"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Glob"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"TLrxQYmHbUA"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PftnV31ZNOAo"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" and"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"99ofC0wo5YQD"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" LS"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"NMfENqXfVuow8"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" LS"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gdqZbXgpibDvB"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"i7QWCjqbnVkyH"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"XcBcLXD3Tt5jA"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Parallel"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"V27SfNN"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Parallel"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sB7X8Ts"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"OFLkXlJfMYgH"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CmPPybRFi0e1"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"h0JrPavopghNT"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" ."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"uBYl83ZXX36yhv"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UgOZnrSTAV"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pkhTo8aKc9A2pw"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"s9vV5Zt6Af"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Files"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"j23Uu3IEGZ"}
 
-      data: {"id":"chatcmpl-CWhZJC0z3DUeuu1TL3VBI1UmbDPr2","object":"chat.completion.chunk","created":1761910009,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":154,"completion_tokens":9,"total_tokens":163,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"aZRwb8LKGbbiX9"}
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"Hwl6L1TjQO"}
+
+      data: {"id":"chatcmpl-CZE7jhyZcFfaPfZcvKjkRZl9ZuLZ1","object":"chat.completion.chunk","created":1762511807,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":154,"completion_tokens":10,"total_tokens":164,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"D38ImI3vBqV9P"}
 
       data: [DONE]
 
@@ -55,15 +57,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 515.978334ms
+    duration: 690.561417ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45236
+    content_length: 46617
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/read_a_file.yaml 🔗

@@ -24,17 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KwiQzorjHP4yXF"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tSkbP0peDKwsNC"}
 
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Understanding"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6p7"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Understanding"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zsG"}
 
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"idrszYUBJu5Xh"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"9UoUgZihousT"}
 
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Modules"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"yqcihFlL"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PJXtS6kFapQOZ"}
 
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"932OjQNMI8"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Mod"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UXEaNgpwS9Ud"}
 
-      data: {"id":"chatcmpl-CWhWHAhp1KAuQiNQHtVYJLkaqqgii","object":"chat.completion.chunk","created":1761909821,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":129,"completion_tokens":3,"total_tokens":132,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"u4zstHSs1oMWL5"}
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" File"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lJQMjSozHNn"}
+
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"xaJLU2Qyj1"}
+
+      data: {"id":"chatcmpl-CZE4Vub5QzBkY0HrdKPgTqDzqM1kh","object":"chat.completion.chunk","created":1762511607,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":129,"completion_tokens":5,"total_tokens":134,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"3yk8ixCu6Urx0Q"}
 
       data: [DONE]
 
@@ -43,15 +47,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.136475792s
+    duration: 1.660934167s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45109
+    content_length: 46490
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/simple_test.yaml 🔗

@@ -24,13 +24,13 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhWAKSjJG7aS3VQh2aSTFIcnAoGw","object":"chat.completion.chunk","created":1761909814,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_65564d8ba5","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kJ82cmYumWTGLC"}
+      data: {"id":"chatcmpl-CZE4P60PyiwEKOc0vHD9Zd8R7cQL7","object":"chat.completion.chunk","created":1762511601,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UxWQfg4b0pgp88"}
 
-      data: {"id":"chatcmpl-CWhWAKSjJG7aS3VQh2aSTFIcnAoGw","object":"chat.completion.chunk","created":1761909814,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_65564d8ba5","choices":[{"index":0,"delta":{"content":"Greetings"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jM0L3i7"}
+      data: {"id":"chatcmpl-CZE4P60PyiwEKOc0vHD9Zd8R7cQL7","object":"chat.completion.chunk","created":1762511601,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Greetings"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wei7Nvv"}
 
-      data: {"id":"chatcmpl-CWhWAKSjJG7aS3VQh2aSTFIcnAoGw","object":"chat.completion.chunk","created":1761909814,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_65564d8ba5","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"BcuY68lDzu"}
+      data: {"id":"chatcmpl-CZE4P60PyiwEKOc0vHD9Zd8R7cQL7","object":"chat.completion.chunk","created":1762511601,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"MDxZBqygCw"}
 
-      data: {"id":"chatcmpl-CWhWAKSjJG7aS3VQh2aSTFIcnAoGw","object":"chat.completion.chunk","created":1761909814,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_65564d8ba5","choices":[],"usage":{"prompt_tokens":126,"completion_tokens":1,"total_tokens":127,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"u4EbJXDAHkMaSU"}
+      data: {"id":"chatcmpl-CZE4P60PyiwEKOc0vHD9Zd8R7cQL7","object":"chat.completion.chunk","created":1762511601,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":126,"completion_tokens":1,"total_tokens":127,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"82Zut6C1LsIWuf"}
 
       data: [DONE]
 
@@ -39,15 +39,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.241931458s
+    duration: 1.593101333s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45099
+    content_length: 46480
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/sourcegraph_tool.yaml 🔗

@@ -24,35 +24,35 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KK8aYMSSiDELdH"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xTDnydqc4Q3cJv"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Searching"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mLGYZIS"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Searching"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oopdP1c"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2cbsMo2svk1BEP"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zbDyUSqVPoaQ3Q"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"func"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fV3z1rB74yfO"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"func"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oYyWzvkw2Ivp"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kHnjkHWN7YP"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"WisTYKaSJUb"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vDM2T7mSIPdYRY7"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RKtKBb37XbSlICz"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"4A8UqCAKl3ulb"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vendxEGi4AklA"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"epXxfMkv3UACx"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VWPDeg82meOZo"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Re"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"uXHKW1MHl43nQ"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Re"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"99MZ2mlTqRCK3"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"positories"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"94vXSJ"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"positories"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"FzkB8D"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"iiXaNVpsfub"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Using"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fD9nbAApi3"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Source"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8pmzsoxNg"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Source"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Z0UjDP1yt"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"graph"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Zf9Wv78IXa9"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"graph"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"hicH4MVg4PK"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"LzKLlUWW2m"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"FLn6DkXtAC"}
 
-      data: {"id":"chatcmpl-CWhYTIiw1PNfl5a13JwCrw4pIultS","object":"chat.completion.chunk","created":1761909957,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":138,"completion_tokens":12,"total_tokens":150,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"lva2Gdhcco8Ri"}
+      data: {"id":"chatcmpl-CZE6rEJGD4FAcemIDTxCBSJjm1X9R","object":"chat.completion.chunk","created":1762511753,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":138,"completion_tokens":12,"total_tokens":150,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"5jTeopIANXEHy"}
 
       data: [DONE]
 
@@ -61,15 +61,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 845.432125ms
+    duration: 578.982667ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45159
+    content_length: 46540
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/update_a_file.yaml 🔗

@@ -24,31 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PLDLeNZd82YM71"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jKkcqZCVKLgggZ"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oNiQ5GCygP3G"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Update"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HFWS1ehCwi"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":".go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LFVFeDtgmVuLq"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" main"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qZK4HvATbPn"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Update"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"t0AlYBr9y"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":".go"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KB04ECXlPjcJO"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"c9qMSV1Y8ekFTIo"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" to"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"PMeyGtHYkK3xF"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Print"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QcJdYyzl3Z"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Print"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"evY1J5NNOv"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" \""},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"js7cOcHrxK7UT"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" '"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8me65FPhVS91ie"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UOHtjq3TQlC"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"FtdHGfNtgfO"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" from"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"36Gr5Flq5LJ"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" from"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VWyHITscYzs"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Crush"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fYBXSUWUd9"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Crush"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"3d7qjLiKWh"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"\""},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QV42kvlcA9ibpc"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"'"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CdhLGQADtjr6FUj"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"yWaQRolC0O"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"eJ8m4hdrQL"}
 
-      data: {"id":"chatcmpl-CWhWUw6avqGtWuzPB9lUBctmnnIuj","object":"chat.completion.chunk","created":1761909834,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":139,"completion_tokens":10,"total_tokens":149,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"hw9iNRpmFNweD"}
+      data: {"id":"chatcmpl-CZE4iNWFRKr4aSD8MZpxVjIHSS3KP","object":"chat.completion.chunk","created":1762511620,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":139,"completion_tokens":10,"total_tokens":149,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"rIw9ZhU3nJxDE"}
 
       data: [DONE]
 
@@ -57,15 +57,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 469.220667ms
+    duration: 553.046209ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45165
+    content_length: 46546
     host: ""

internal/agent/testdata/TestCoderAgent/openai-gpt-5/write_tool.yaml 🔗

@@ -24,23 +24,35 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6nknPjuOLCwz2j"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"A2k24SWtC9ttxR"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Create"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UKbO0tOEx5"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"Create"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UQHsqWxm0w"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" JSON"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Zw7na2EwlSz"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Config"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ev9L0KLUa"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" File"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"a1Ti8eDKQqT"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":".json"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oZpnKxnvHGi"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"rRhBI7hB4p6"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" with"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"llNker8FKWy"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Config"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"VBjObVGZe"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Test"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RledXzprOmK"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Details"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sbKPiIhw"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" Version"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1m80KQSM"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"CgNioou140"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"h9JZMsUnDZXQhD9"}
 
-      data: {"id":"chatcmpl-CWhZ84hPjwruz42MM9mMzNrU0xGRh","object":"chat.completion.chunk","created":1761909998,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":153,"completion_tokens":6,"total_tokens":159,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"1GFTG66Q9TDJFr"}
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zz7aMNYf8tvKMWY"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"y87Y7OfWt1BYlgz"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"0"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"BtQG7bcel7ip5vp"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"5fhNLujWCOL74NH"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{"content":"0"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"umR68cbh4xPlTXw"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"EdNpTMoO42"}
+
+      data: {"id":"chatcmpl-CZE7NwLuScExSMezrAL8wm3ZTQjdh","object":"chat.completion.chunk","created":1762511785,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_b1442291a8","choices":[],"usage":{"prompt_tokens":153,"completion_tokens":12,"total_tokens":165,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"883cBS7AySSUP"}
 
       data: [DONE]
 
@@ -49,15 +61,15 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 495.299125ms
+    duration: 633.838ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45202
+    content_length: 46583
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/bash_tool.yaml 🔗

@@ -6,9 +6,9 @@ interactions:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 803
+    content_length: 46679
     host: ""
-    body: '{"messages":[{"content":"you will generate a short title based on the first message a user begins a conversation with\n\n<rules>\n- ensure it is not more than 50 characters long\n- the title should be a summary of the user''s message\n- it should be one line long\n- do not use quotes or colons\n- the entire text you return will be used as the title\n- never return anything that is more than one sentence (one line) long\n</rules>\n\n /no_think","role":"system"},{"content":"Generate a concise title for the following content:\n\nuse bash to create a file named test.txt with content ''hello bash''. do not print its timestamp\n <think>\n\n</think>","role":"user"}],"model":"qwen/qwen3-next-80b-a3b-instruct","max_tokens":40,"stream_options":{"include_usage":true},"usage":{"include":true},"stream":true}'

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/download_tool.yaml 🔗

@@ -24,25 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":"Download"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":"Download"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":" and save example.txt"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":" and save example.txt"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":" from given"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":" from example-files"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":" URL"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":".online"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":"-"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
-
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":"convert.com"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
-
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
-
-      data: {"id":"gen-1761910040-jpK7NLYwz180tBpsNAIV","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910040,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":150,"completion_tokens":13,"total_tokens":163,"cost":0.0000353,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000021,"upstream_inference_completions_cost":0.0000143},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511866-wCgza9h8FX9UVCqP0UDf","provider":"SiliconFlow","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511866,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":150,"completion_tokens":9,"total_tokens":159,"cost":0.0000336,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000021,"upstream_inference_completions_cost":0.0000126},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -51,15 +45,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 710.793208ms
+    duration: 618.794584ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45323
+    content_length: 46704
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/glob_tool.yaml 🔗

@@ -24,21 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":"Find"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":"Find"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":" all .go files"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":" all .go files"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":" in current directory using"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":" in current directory using"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":" glob"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":" glob"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
 
-      data: {"id":"gen-1761910052-uuOETI7IJpIcw17hHFAk","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910052,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":139,"completion_tokens":11,"total_tokens":150,"cost":0.00003156,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00001946,"upstream_inference_completions_cost":0.0000121},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511873-n76cNgD6teWmFVYX4pZr","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511874,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":139,"completion_tokens":11,"total_tokens":150,"cost":0.00003156,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00001946,"upstream_inference_completions_cost":0.0000121},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -47,15 +47,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 568.273625ms
+    duration: 673.102ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45259
+    content_length: 46640
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/grep_tool.yaml 🔗

@@ -24,17 +24,27 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":"Search"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":"Search"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":" for package in Go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" for"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":" files using grep"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" package"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761911360-yPPMIO7ueEGdqymanmPO","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761911360,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":140,"completion_tokens":9,"total_tokens":149,"cost":0.0000345,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000021,"upstream_inference_completions_cost":0.0000135},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" Go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" files"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" using"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":" grep"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+
+      data: {"id":"gen-1762511883-aN2m9jCbzCyb5mXObZMH","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511883,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":140,"completion_tokens":9,"total_tokens":149,"cost":0.0000239,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000014,"upstream_inference_completions_cost":0.0000099},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -43,15 +53,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 2.174957041s
+    duration: 821.99575ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45257
+    content_length: 46638
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/ls_tool.yaml 🔗

@@ -24,17 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":"List"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":" files in current directory"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":"List"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":" using ls"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":" files in current directory"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":" using ls"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910060-VJbmBjm0lLRDsPUFIR6S","provider":"Google","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910060,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":137,"completion_tokens":8,"total_tokens":145,"cost":0.00003015,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00002055,"upstream_inference_completions_cost":0.0000096},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+
+      data: {"id":"gen-1762511886-tTIfTmV5o1dnCbDyQhRL","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511886,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":137,"completion_tokens":8,"total_tokens":145,"cost":0.00002798,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00001918,"upstream_inference_completions_cost":0.0000088},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -43,15 +45,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 717.847333ms
+    duration: 228.087042ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45251
+    content_length: 46632
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/multiedit_tool.yaml 🔗

@@ -24,17 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":"Use multiedit to"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":"Use"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":" update greeting and add comment in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":" multiedit to"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":" main.go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":" update greeting"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":" and add comment in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910063-ujbWJwTviThqiNBCyUac","provider":"Hyperbolic","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910063,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":160,"completion_tokens":14,"total_tokens":174,"cost":0.0000522,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000048,"upstream_inference_completions_cost":0.0000042},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":" main.go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+
+      data: {"id":"gen-1762511891-Ea2drwdPE1d93DAxtlSZ","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511891,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":160,"completion_tokens":14,"total_tokens":174,"cost":0.000045,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000024,"upstream_inference_completions_cost":0.000021},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -43,15 +47,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.272179209s
+    duration: 805.685583ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45337
+    content_length: 46718
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/parallel_tool_calls.yaml 🔗

@@ -24,21 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":"Find"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":"Find"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":" .go files and"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":" .go files and"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":" list directory"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":" list directory"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":" in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":" in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":" parallel"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":" parallel"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
 
-      data: {"id":"gen-1761910105-3A4csdIPom3cGo1LJez4","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910105,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":160,"completion_tokens":9,"total_tokens":169,"cost":0.0000375,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000024,"upstream_inference_completions_cost":0.0000135},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511944-W69sbZmGj9Hzg8Nm9ikR","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511944,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":156,"completion_tokens":10,"total_tokens":166,"cost":0.0000384,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000234,"upstream_inference_completions_cost":0.000015},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -47,15 +47,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.345112459s
+    duration: 813.378ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45348
+    content_length: 46729
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/read_a_file.yaml 🔗

@@ -24,19 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":"Read"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":"Read"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":" the"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":" the"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":" go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":" go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":" mod"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":" mod"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
 
-      data: {"id":"gen-1761910020-fGmWbz6IBhnFHrolqfCi","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910020,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":131,"completion_tokens":5,"total_tokens":136,"cost":0.0000186,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000131,"upstream_inference_completions_cost":0.0000055},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511830-C7ltCx7l41SdcWzVs47M","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511830,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":131,"completion_tokens":5,"total_tokens":136,"cost":0.0000186,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000131,"upstream_inference_completions_cost":0.0000055},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -45,15 +45,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 572.50025ms
+    duration: 470.21025ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45221
+    content_length: 46602
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/simple_test.yaml 🔗

@@ -24,13 +24,13 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910017-kwKmQaoZRZJprbrCiwzP","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910017,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511827-5ePJDTkGVy6nVSY4nX2t","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511827,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910017-kwKmQaoZRZJprbrCiwzP","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910017,"choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511827-5ePJDTkGVy6nVSY4nX2t","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511827,"choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910017-kwKmQaoZRZJprbrCiwzP","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910017,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511827-5ePJDTkGVy6nVSY4nX2t","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511827,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
 
-      data: {"id":"gen-1761910017-kwKmQaoZRZJprbrCiwzP","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910017,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":128,"completion_tokens":2,"total_tokens":130,"cost":0.000015,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000128,"upstream_inference_completions_cost":0.0000022},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511827-5ePJDTkGVy6nVSY4nX2t","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511827,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":128,"completion_tokens":2,"total_tokens":130,"cost":0.000015,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000128,"upstream_inference_completions_cost":0.0000022},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -39,15 +39,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.304010709s
+    duration: 1.169144708s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45211
+    content_length: 46592
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/sourcegraph_tool.yaml 🔗

@@ -24,31 +24,23 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":"Search"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" for"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":"Search"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" func"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":" for func"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" main"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":" main in Go repositories"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" in"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":" using Source"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" Go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":"graph"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" repositories"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
 
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" using"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
-
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":" Source"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
-
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":"graph"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
-
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
-
-      data: {"id":"gen-1761910083-DMwj8ByxTb7hAGnhEawD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910083,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":140,"completion_tokens":11,"total_tokens":151,"cost":0.0000261,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000014,"upstream_inference_completions_cost":0.0000121},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511912-EZMMfQWa5XBgidcIxPA5","provider":"DeepInfra","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511912,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":140,"completion_tokens":11,"total_tokens":151,"cost":0.0000317,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000196,"upstream_inference_completions_cost":0.0000121},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -57,15 +49,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 781.411208ms
+    duration: 1.033064417s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45271
+    content_length: 46652
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/update_a_file.yaml 🔗

@@ -24,19 +24,27 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":"Update"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":"Update"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":" main.go to print"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" main"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":" hello"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":".go"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":" from crush"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" to"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}],"system_fingerprint":""}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" print"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
 
-      data: {"id":"gen-1761910023-cE8wcf03fPUk6DeRS4aD","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910023,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":145,"completion_tokens":8,"total_tokens":153,"cost":0.00003375,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00002175,"upstream_inference_completions_cost":0.000012},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" hello"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" from"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":" crush"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+
+      data: {"id":"gen-1762511834-S3KribObmYgM9PFWQlwD","provider":"Parasail","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511834,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":141,"completion_tokens":9,"total_tokens":150,"cost":0.000024,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.0000141,"upstream_inference_completions_cost":0.0000099},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -45,15 +53,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.368202375s
+    duration: 461.188667ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45277
+    content_length: 46658
     host: ""

internal/agent/testdata/TestCoderAgent/openrouter-kimi-k2/write_tool.yaml 🔗

@@ -24,17 +24,17 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":"Create"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":"Create"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":" config.json with name"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":" config.json with name"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":" and version values"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":" and version fields"},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}]}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop","native_finish_reason":"stop","logprobs":null}],"system_fingerprint":""}
 
-      data: {"id":"gen-1761910094-GtEfRGOYinkHCLBjmD3s","provider":"GMICloud","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1761910094,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":155,"completion_tokens":9,"total_tokens":164,"cost":0.00003675,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00002325,"upstream_inference_completions_cost":0.0000135},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
+      data: {"id":"gen-1762511936-Ktb0imwg9O1BitZ5kElo","provider":"Novita","model":"qwen/qwen3-next-80b-a3b-instruct","object":"chat.completion.chunk","created":1762511936,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null,"native_finish_reason":null,"logprobs":null}],"usage":{"prompt_tokens":159,"completion_tokens":8,"total_tokens":167,"cost":0.00003585,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00002385,"upstream_inference_completions_cost":0.000012},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}
 
       data: [DONE]
 
@@ -43,15 +43,15 @@ interactions:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.740511708s
+    duration: 1.216577375s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45314
+    content_length: 46695
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/bash_tool.yaml 🔗

@@ -24,21 +24,23 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"B"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Create"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"ash"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" test"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" file"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".txt"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" creation"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" with"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" without"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" hello"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" timestamp"}}]}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" bash"}}]}
 
-      data: {"id":"202510311928475a9131ca38d64af3","created":1761910127,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":140,"completion_tokens":10,"total_tokens":150,"prompt_tokens_details":{"cached_tokens":114}}}
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" content"}}]}
+
+      data: {"id":"20251107183930db1b2cbbde564dc0","created":1762511970,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":140,"completion_tokens":11,"total_tokens":151,"prompt_tokens_details":{"cached_tokens":114}}}
 
       data: [DONE]
 
@@ -47,15 +49,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 721.892875ms
+    duration: 648.9365ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45175
+    content_length: 46556
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/download_tool.yaml 🔗

@@ -24,23 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Download"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Download"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" file"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" and"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" and"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" save"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" save"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" example"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" as"}}]}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".txt"}}]}
 
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" example"}}]}
-
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".txt"}}]}
-
-      data: {"id":"202510311928525f9092beb5134db5","created":1761910133,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":143,"completion_tokens":11,"total_tokens":154,"prompt_tokens_details":{"cached_tokens":114}}}
+      data: {"id":"20251107183934ee7020b00d3842f9","created":1762511974,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":143,"completion_tokens":9,"total_tokens":152,"prompt_tokens_details":{"cached_tokens":4}}}
 
       data: [DONE]
 
@@ -49,15 +45,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 985.514791ms
+    duration: 562.0335ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45200
+    content_length: 46581
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/glob_tool.yaml 🔗

@@ -24,19 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Find"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Find"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Go"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" all"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Files"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Go"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" with"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" files"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Glob"}}]}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" with"}}]}
 
-      data: {"id":"20251031194927a02c47d9d61349e2","created":1761911367,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":132,"completion_tokens":9,"total_tokens":141,"prompt_tokens_details":{"cached_tokens":122}}}
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" glob"}}]}
+
+      data: {"id":"20251107183941b355551541d24475","created":1762511981,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":132,"completion_tokens":10,"total_tokens":142,"prompt_tokens_details":{"cached_tokens":115}}}
 
       data: [DONE]
 
@@ -45,15 +47,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.265072959s
+    duration: 577.557ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45136
+    content_length: 46517
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/grep_tool.yaml 🔗

@@ -24,23 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"G"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"grep"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"rep"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" package"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" for"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" in"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" package"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" go"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" in"}}]}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" files"}}]}
 
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Go"}}]}
-
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" files"}}]}
-
-      data: {"id":"202510311929138fde4a0b262745c5","created":1761910153,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":133,"completion_tokens":11,"total_tokens":144,"prompt_tokens_details":{"cached_tokens":4}}}
+      data: {"id":"2025110718394470967471d1824178","created":1762511984,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":133,"completion_tokens":9,"total_tokens":142,"prompt_tokens_details":{"cached_tokens":4}}}
 
       data: [DONE]
 
@@ -49,15 +45,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 674.16375ms
+    duration: 524.305667ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45134
+    content_length: 46515
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/multiedit_tool.yaml 🔗

@@ -24,21 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Mult"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Mult"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"ied"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"ied"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"it"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"it"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Go"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Go"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" File"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Code"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Modification"}}]}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" Modification"}}]}
 
-      data: {"id":"20251031192917320e615cfd094ad2","created":1761910157,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":153,"completion_tokens":10,"total_tokens":163,"prompt_tokens_details":{"cached_tokens":115}}}
+      data: {"id":"20251107183950ae1dcdfd8e774f1b","created":1762511990,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":153,"completion_tokens":10,"total_tokens":163,"prompt_tokens_details":{"cached_tokens":4}}}
 
       data: [DONE]
 
@@ -47,15 +47,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 825.229333ms
+    duration: 652.638708ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45214
+    content_length: 46595
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/parallel_tool_calls.yaml 🔗

@@ -24,19 +24,19 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"","reasoning_content":"\n"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Parallel"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Parallel"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" glob"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" glob"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" and"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" and"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" ls"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" ls"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" commands"}}]}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" commands"}}]}
 
-      data: {"id":"202510311929487b90bdbe3b9e4f2c","created":1761910188,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":149,"completion_tokens":9,"total_tokens":158,"prompt_tokens_details":{"cached_tokens":122}}}
+      data: {"id":"202511071840041498d38fadda4d21","created":1762512004,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":149,"completion_tokens":9,"total_tokens":158,"prompt_tokens_details":{"cached_tokens":122}}}
 
       data: [DONE]
 
@@ -45,15 +45,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 729.095834ms
+    duration: 778.965125ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45225
+    content_length: 46606
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/read_a_file.yaml 🔗

@@ -24,17 +24,15 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183914c6983431c3dc473e","created":1762511954,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Read"}}]}
+      data: {"id":"20251107183914c6983431c3dc473e","created":1762511954,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Read"}}]}
 
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" the"}}]}
+      data: {"id":"20251107183914c6983431c3dc473e","created":1762511954,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" go"}}]}
 
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" go"}}]}
+      data: {"id":"20251107183914c6983431c3dc473e","created":1762511954,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" mod"}}]}
 
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" mod"}}]}
-
-      data: {"id":"202510311928360f6fed40ae54414a","created":1761910116,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":124,"completion_tokens":8,"total_tokens":132,"prompt_tokens_details":{"cached_tokens":4}}}
+      data: {"id":"20251107183914c6983431c3dc473e","created":1762511954,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":124,"completion_tokens":7,"total_tokens":131,"prompt_tokens_details":{"cached_tokens":4}}}
 
       data: [DONE]
 
@@ -43,15 +41,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 784.494417ms
+    duration: 581.114625ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45098
+    content_length: 46479
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/simple_test.yaml 🔗

@@ -24,11 +24,11 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"20251031192833c9eb6e69b4dd4ae5","created":1761910113,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183910151773d0199b4ce2","created":1762511950,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"20251031192833c9eb6e69b4dd4ae5","created":1761910113,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"}}]}
+      data: {"id":"20251107183910151773d0199b4ce2","created":1762511950,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Hello"}}]}
 
-      data: {"id":"20251031192833c9eb6e69b4dd4ae5","created":1761910113,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":121,"completion_tokens":5,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":4}}}
+      data: {"id":"20251107183910151773d0199b4ce2","created":1762511950,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":121,"completion_tokens":5,"total_tokens":126,"prompt_tokens_details":{"cached_tokens":114}}}
 
       data: [DONE]
 
@@ -37,15 +37,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.120641833s
+    duration: 1.656718792s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45088
+    content_length: 46469
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/update_a_file.yaml 🔗

@@ -24,21 +24,25 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Update"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Update"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" main"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" main"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".go"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".go"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" to"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" to"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" print"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" print"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" hello"}}]}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" hello"}}]}
 
-      data: {"id":"2025103119284010db94ea823c4a22","created":1761910120,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":134,"completion_tokens":10,"total_tokens":144,"prompt_tokens_details":{"cached_tokens":4}}}
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" from"}}]}
+
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" crush"}}]}
+
+      data: {"id":"20251107183921e9396502659647b0","created":1762511961,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":134,"completion_tokens":12,"total_tokens":146,"prompt_tokens_details":{"cached_tokens":4}}}
 
       data: [DONE]
 
@@ -47,15 +51,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.158018209s
+    duration: 636.533125ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45154
+    content_length: 46535
     host: ""

internal/agent/testdata/TestCoderAgent/zai-glm4.6/write_tool.yaml 🔗

@@ -24,19 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"\n"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Create"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":"Create"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" config"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" config"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".json"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":".json"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" with"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" file"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" content"}}]}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" with"}}]}
 
-      data: {"id":"2025103119294422b16915b94e40a0","created":1761910184,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":148,"completion_tokens":9,"total_tokens":157,"prompt_tokens_details":{"cached_tokens":4}}}
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"delta":{"role":"assistant","content":" content"}}]}
+
+      data: {"id":"20251107184001af15393db23849a9","created":1762512002,"model":"glm-4.5-air","choices":[{"index":0,"finish_reason":"stop","delta":{"role":"assistant","content":""}}],"usage":{"prompt_tokens":148,"completion_tokens":10,"total_tokens":158,"prompt_tokens_details":{"cached_tokens":115}}}
 
       data: [DONE]
 
@@ -45,15 +47,15 @@ interactions:
       - text/event-stream;charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 781.244542ms
+    duration: 581.754ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 45191
+    content_length: 46572
     host: ""

internal/agent/tools/bash.go 🔗

@@ -2,6 +2,7 @@ package tools
 
 import (
 	"bytes"
+	"cmp"
 	"context"
 	_ "embed"
 	"fmt"
@@ -19,15 +20,17 @@ import (
 )
 
 type BashParams struct {
-	Command     string `json:"command" description:"The command to execute"`
-	Description string `json:"description,omitempty" description:"A brief description of what the command does"`
-	Timeout     int    `json:"timeout,omitempty" description:"Optional timeout in milliseconds (max 600000)"`
+	Description     string `json:"description" description:"A brief description of what the command does, try to keep it under 30 characters or so"`
+	Command         string `json:"command" description:"The command to execute"`
+	WorkingDir      string `json:"working_dir,omitempty" description:"The working directory to execute the command in (defaults to current directory)"`
+	RunInBackground bool   `json:"run_in_background,omitempty" description:"Set to true (boolean) to run this command in the background. Use job_output to read the output later."`
 }
 
 type BashPermissionsParams struct {
-	Command     string `json:"command"`
-	Description string `json:"description"`
-	Timeout     int    `json:"timeout"`
+	Description     string `json:"description"`
+	Command         string `json:"command"`
+	WorkingDir      string `json:"working_dir"`
+	RunInBackground bool   `json:"run_in_background"`
 }
 
 type BashResponseMetadata struct {
@@ -36,15 +39,16 @@ type BashResponseMetadata struct {
 	Output           string `json:"output"`
 	Description      string `json:"description"`
 	WorkingDirectory string `json:"working_directory"`
+	Background       bool   `json:"background,omitempty"`
+	ShellID          string `json:"shell_id,omitempty"`
 }
 
 const (
 	BashToolName = "bash"
 
-	DefaultTimeout  = 1 * 60 * 1000  // 1 minutes in milliseconds
-	MaxTimeout      = 10 * 60 * 1000 // 10 minutes in milliseconds
-	MaxOutputLength = 30000
-	BashNoOutput    = "no output"
+	AutoBackgroundThreshold = 1 * time.Minute // Commands taking longer automatically become background jobs
+	MaxOutputLength         = 30000
+	BashNoOutput            = "no output"
 )
 
 //go:embed bash.tpl
@@ -181,23 +185,17 @@ func blockFuncs() []shell.BlockFunc {
 }
 
 func NewBashTool(permissions permission.Service, workingDir string, attribution *config.Attribution) fantasy.AgentTool {
-	// Set up command blocking on the persistent shell
-	persistentShell := shell.GetPersistentShell(workingDir)
-	persistentShell.SetBlockFuncs(blockFuncs())
 	return fantasy.NewAgentTool(
 		BashToolName,
 		string(bashDescription(attribution)),
 		func(ctx context.Context, params BashParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
-			if params.Timeout > MaxTimeout {
-				params.Timeout = MaxTimeout
-			} else if params.Timeout <= 0 {
-				params.Timeout = DefaultTimeout
-			}
-
 			if params.Command == "" {
 				return fantasy.NewTextErrorResponse("missing command"), nil
 			}
 
+			// Determine working directory
+			execWorkingDir := cmp.Or(params.WorkingDir, workingDir)
+
 			isSafeReadOnly := false
 			cmdLower := strings.ToLower(params.Command)
 
@@ -215,88 +213,197 @@ func NewBashTool(permissions permission.Service, workingDir string, attribution
 				return fantasy.ToolResponse{}, fmt.Errorf("session ID is required for executing shell command")
 			}
 			if !isSafeReadOnly {
-				shell := shell.GetPersistentShell(workingDir)
 				p := permissions.Request(
 					permission.CreatePermissionRequest{
 						SessionID:   sessionID,
-						Path:        shell.GetWorkingDir(),
+						Path:        execWorkingDir,
 						ToolCallID:  call.ID,
 						ToolName:    BashToolName,
 						Action:      "execute",
 						Description: fmt.Sprintf("Execute command: %s", params.Command),
-						Params: BashPermissionsParams{
-							Command:     params.Command,
-							Description: params.Description,
-						},
+						Params:      BashPermissionsParams(params),
 					},
 				)
 				if !p {
 					return fantasy.ToolResponse{}, permission.ErrorPermissionDenied
 				}
 			}
-			startTime := time.Now()
-			if params.Timeout > 0 {
-				var cancel context.CancelFunc
-				ctx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Millisecond)
-				defer cancel()
-			}
 
-			persistentShell := shell.GetPersistentShell(workingDir)
-			stdout, stderr, err := persistentShell.Exec(ctx, params.Command)
+			// If explicitly requested as background, start immediately with detached context
+			if params.RunInBackground {
+				startTime := time.Now()
+				bgManager := shell.GetBackgroundShellManager()
+				bgManager.Cleanup()
+				// Use background context so it continues after tool returns
+				bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(), params.Command, params.Description)
+				if err != nil {
+					return fantasy.ToolResponse{}, fmt.Errorf("error starting background shell: %w", err)
+				}
 
-			// Get the current working directory after command execution
-			currentWorkingDir := persistentShell.GetWorkingDir()
-			interrupted := shell.IsInterrupt(err)
-			exitCode := shell.ExitCode(err)
-			if exitCode == 0 && !interrupted && err != nil {
-				return fantasy.ToolResponse{}, fmt.Errorf("error executing command: %w", err)
-			}
+				// Wait a short time to detect fast failures (blocked commands, syntax errors, etc.)
+				time.Sleep(1 * time.Second)
+				stdout, stderr, done, execErr := bgShell.GetOutput()
 
-			stdout = truncateOutput(stdout)
-			stderr = truncateOutput(stderr)
+				if done {
+					// Command failed or completed very quickly
+					bgManager.Remove(bgShell.ID)
 
-			errorMessage := stderr
-			if errorMessage == "" && err != nil {
-				errorMessage = err.Error()
-			}
+					interrupted := shell.IsInterrupt(execErr)
+					exitCode := shell.ExitCode(execErr)
+					if exitCode == 0 && !interrupted && execErr != nil {
+						return fantasy.ToolResponse{}, fmt.Errorf("[Job %s] error executing command: %w", bgShell.ID, execErr)
+					}
+
+					stdout = formatOutput(stdout, stderr, execErr)
 
-			if interrupted {
-				if errorMessage != "" {
-					errorMessage += "\n"
+					metadata := BashResponseMetadata{
+						StartTime:        startTime.UnixMilli(),
+						EndTime:          time.Now().UnixMilli(),
+						Output:           stdout,
+						Description:      params.Description,
+						Background:       params.RunInBackground,
+						WorkingDirectory: bgShell.WorkingDir,
+					}
+					if stdout == "" {
+						return fantasy.WithResponseMetadata(fantasy.NewTextResponse(BashNoOutput), metadata), nil
+					}
+					stdout += fmt.Sprintf("\n\n<cwd>%s</cwd>", normalizeWorkingDir(bgShell.WorkingDir))
+					return fantasy.WithResponseMetadata(fantasy.NewTextResponse(stdout), metadata), nil
 				}
-				errorMessage += "Command was aborted before completion"
-			} else if exitCode != 0 {
-				if errorMessage != "" {
-					errorMessage += "\n"
+
+				// Still running after fast-failure check - return as background job
+				metadata := BashResponseMetadata{
+					StartTime:        startTime.UnixMilli(),
+					EndTime:          time.Now().UnixMilli(),
+					Description:      params.Description,
+					WorkingDirectory: bgShell.WorkingDir,
+					Background:       true,
+					ShellID:          bgShell.ID,
 				}
-				errorMessage += fmt.Sprintf("Exit code %d", exitCode)
+				response := fmt.Sprintf("Background shell started with ID: %s\n\nUse job_output tool to view output or job_kill to terminate.", bgShell.ID)
+				return fantasy.WithResponseMetadata(fantasy.NewTextResponse(response), metadata), nil
 			}
 
-			hasBothOutputs := stdout != "" && stderr != ""
+			// Start synchronous execution with auto-background support
+			startTime := time.Now()
+
+			// Start with detached context so it can survive if moved to background
+			bgManager := shell.GetBackgroundShellManager()
+			bgManager.Cleanup()
+			bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(), params.Command, params.Description)
+			if err != nil {
+				return fantasy.ToolResponse{}, fmt.Errorf("error starting shell: %w", err)
+			}
 
-			if hasBothOutputs {
-				stdout += "\n"
+			// Wait for either completion, auto-background threshold, or context cancellation
+			ticker := time.NewTicker(100 * time.Millisecond)
+			defer ticker.Stop()
+			timeout := time.After(AutoBackgroundThreshold)
+
+			var stdout, stderr string
+			var done bool
+			var execErr error
+
+		waitLoop:
+			for {
+				select {
+				case <-ticker.C:
+					stdout, stderr, done, execErr = bgShell.GetOutput()
+					if done {
+						break waitLoop
+					}
+				case <-timeout:
+					stdout, stderr, done, execErr = bgShell.GetOutput()
+					break waitLoop
+				case <-ctx.Done():
+					// Incoming context was cancelled before we moved to background
+					// Kill the shell and return error
+					bgManager.Kill(bgShell.ID)
+					return fantasy.ToolResponse{}, ctx.Err()
+				}
 			}
 
-			if errorMessage != "" {
-				stdout += "\n" + errorMessage
+			if done {
+				// Command completed within threshold - return synchronously
+				// Remove from background manager since we're returning directly
+				// Don't call Kill() as it cancels the context and corrupts the exit code
+				bgManager.Remove(bgShell.ID)
+
+				interrupted := shell.IsInterrupt(execErr)
+				exitCode := shell.ExitCode(execErr)
+				if exitCode == 0 && !interrupted && execErr != nil {
+					return fantasy.ToolResponse{}, fmt.Errorf("[Job %s] error executing command: %w", bgShell.ID, execErr)
+				}
+
+				stdout = formatOutput(stdout, stderr, execErr)
+
+				metadata := BashResponseMetadata{
+					StartTime:        startTime.UnixMilli(),
+					EndTime:          time.Now().UnixMilli(),
+					Output:           stdout,
+					Description:      params.Description,
+					Background:       params.RunInBackground,
+					WorkingDirectory: bgShell.WorkingDir,
+				}
+				if stdout == "" {
+					return fantasy.WithResponseMetadata(fantasy.NewTextResponse(BashNoOutput), metadata), nil
+				}
+				stdout += fmt.Sprintf("\n\n<cwd>%s</cwd>", normalizeWorkingDir(bgShell.WorkingDir))
+				return fantasy.WithResponseMetadata(fantasy.NewTextResponse(stdout), metadata), nil
 			}
 
+			// Still running - keep as background job
 			metadata := BashResponseMetadata{
 				StartTime:        startTime.UnixMilli(),
 				EndTime:          time.Now().UnixMilli(),
-				Output:           stdout,
 				Description:      params.Description,
-				WorkingDirectory: currentWorkingDir,
-			}
-			if stdout == "" {
-				return fantasy.WithResponseMetadata(fantasy.NewTextResponse(BashNoOutput), metadata), nil
+				WorkingDirectory: bgShell.WorkingDir,
+				Background:       true,
+				ShellID:          bgShell.ID,
 			}
-			stdout += fmt.Sprintf("\n\n<cwd>%s</cwd>", normalizeWorkingDir(currentWorkingDir))
-			return fantasy.WithResponseMetadata(fantasy.NewTextResponse(stdout), metadata), nil
+			response := fmt.Sprintf("Command is taking longer than expected and has been moved to background.\n\nBackground shell ID: %s\n\nUse job_output tool to view output or job_kill to terminate.", bgShell.ID)
+			return fantasy.WithResponseMetadata(fantasy.NewTextResponse(response), metadata), nil
 		})
 }
 
+// formatOutput formats the output of a completed command with error handling
+func formatOutput(stdout, stderr string, execErr error) string {
+	interrupted := shell.IsInterrupt(execErr)
+	exitCode := shell.ExitCode(execErr)
+
+	stdout = truncateOutput(stdout)
+	stderr = truncateOutput(stderr)
+
+	errorMessage := stderr
+	if errorMessage == "" && execErr != nil {
+		errorMessage = execErr.Error()
+	}
+
+	if interrupted {
+		if errorMessage != "" {
+			errorMessage += "\n"
+		}
+		errorMessage += "Command was aborted before completion"
+	} else if exitCode != 0 {
+		if errorMessage != "" {
+			errorMessage += "\n"
+		}
+		errorMessage += fmt.Sprintf("Exit code %d", exitCode)
+	}
+
+	hasBothOutputs := stdout != "" && stderr != ""
+
+	if hasBothOutputs {
+		stdout += "\n"
+	}
+
+	if errorMessage != "" {
+		stdout += "\n" + errorMessage
+	}
+
+	return stdout
+}
+
 func truncateOutput(content string) string {
 	if len(content) <= MaxOutputLength {
 		return content

internal/agent/tools/bash.tpl 🔗

@@ -1,4 +1,4 @@
-Executes bash commands in persistent shell session with timeout and security measures.
+Executes bash commands with automatic background conversion for long-running tasks.
 
 <cross_platform>
 Uses mvdan/sh interpreter (Bash-compatible on all platforms including Windows).
@@ -10,18 +10,38 @@ Common shell builtins and core utils available on Windows.
 1. Directory Verification: If creating directories/files, use LS tool to verify parent exists
 2. Security Check: Banned commands ({{ .BannedCommands }}) return error - explain to user. Safe read-only commands execute without prompts
 3. Command Execution: Execute with proper quoting, capture output
-4. Output Processing: Truncate if exceeds {{ .MaxOutputLength }} characters
-5. Return Result: Include errors, metadata with <cwd></cwd> tags
+4. Auto-Background: Commands exceeding 1 minute automatically move to background and return shell ID
+5. Output Processing: Truncate if exceeds {{ .MaxOutputLength }} characters
+6. Return Result: Include errors, metadata with <cwd></cwd> tags
 </execution_steps>
 
 <usage_notes>
-- Command required, timeout optional (max 600000ms/10min, default 30min if unspecified)
+- Command required, working_dir optional (defaults to current directory)
 - IMPORTANT: Use Grep/Glob/Agent tools instead of 'find'/'grep'. Use View/LS tools instead of 'cat'/'head'/'tail'/'ls'
 - Chain with ';' or '&&', avoid newlines except in quoted strings
-- Shell state persists (env vars, virtual envs, cwd, etc.)
+- Each command runs in independent shell (no state persistence between calls)
 - Prefer absolute paths over 'cd' (use 'cd' only if user explicitly requests)
 </usage_notes>
 
+<background_execution>
+- Set run_in_background=true to run commands in a separate background shell
+- Returns a shell ID for managing the background process
+- Use job_output tool to view current output from background shell
+- Use job_kill tool to terminate a background shell
+- IMPORTANT: NEVER use `&` at the end of commands to run in background - use run_in_background parameter instead
+- Commands that should run in background:
+  * Long-running servers (e.g., `npm start`, `python -m http.server`, `node server.js`)
+  * Watch/monitoring tasks (e.g., `npm run watch`, `tail -f logfile`)
+  * Continuous processes that don't exit on their own
+  * Any command expected to run indefinitely
+- Commands that should NOT run in background:
+  * Build commands (e.g., `npm run build`, `go build`)
+  * Test suites (e.g., `npm test`, `pytest`)
+  * Git operations
+  * File operations
+  * Short-lived scripts
+</background_execution>
+
 <git_commits>
 When user asks to create git commit:
 

internal/agent/tools/job_kill.go 🔗

@@ -0,0 +1,59 @@
+package tools
+
+import (
+	"context"
+	_ "embed"
+	"fmt"
+
+	"charm.land/fantasy"
+	"github.com/charmbracelet/crush/internal/shell"
+)
+
+const (
+	JobKillToolName = "job_kill"
+)
+
+//go:embed job_kill.md
+var jobKillDescription []byte
+
+type JobKillParams struct {
+	ShellID string `json:"shell_id" description:"The ID of the background shell to terminate"`
+}
+
+type JobKillResponseMetadata struct {
+	ShellID     string `json:"shell_id"`
+	Command     string `json:"command"`
+	Description string `json:"description"`
+}
+
+func NewJobKillTool() fantasy.AgentTool {
+	return fantasy.NewAgentTool(
+		JobKillToolName,
+		string(jobKillDescription),
+		func(ctx context.Context, params JobKillParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
+			if params.ShellID == "" {
+				return fantasy.NewTextErrorResponse("missing shell_id"), nil
+			}
+
+			bgManager := shell.GetBackgroundShellManager()
+
+			bgShell, ok := bgManager.Get(params.ShellID)
+			if !ok {
+				return fantasy.NewTextErrorResponse(fmt.Sprintf("background shell not found: %s", params.ShellID)), nil
+			}
+
+			metadata := JobKillResponseMetadata{
+				ShellID:     params.ShellID,
+				Command:     bgShell.Command,
+				Description: bgShell.Description,
+			}
+
+			err := bgManager.Kill(params.ShellID)
+			if err != nil {
+				return fantasy.NewTextErrorResponse(err.Error()), nil
+			}
+
+			result := fmt.Sprintf("Background shell %s terminated successfully", params.ShellID)
+			return fantasy.WithResponseMetadata(fantasy.NewTextResponse(result), metadata), nil
+		})
+}

internal/agent/tools/job_kill.md 🔗

@@ -0,0 +1,18 @@
+Terminates a background shell process.
+
+<usage>
+- Provide the shell ID returned from a background bash execution
+- Cancels the running process and cleans up resources
+</usage>
+
+<features>
+- Stop long-running background processes
+- Clean up completed background shells
+- Immediately terminates the process
+</features>
+
+<tips>
+- Use this when you need to stop a background process
+- The process is terminated immediately (similar to SIGTERM)
+- After killing, the shell ID becomes invalid
+</tips>

internal/agent/tools/job_output.go 🔗

@@ -0,0 +1,85 @@
+package tools
+
+import (
+	"context"
+	_ "embed"
+	"fmt"
+	"strings"
+
+	"charm.land/fantasy"
+	"github.com/charmbracelet/crush/internal/shell"
+)
+
+const (
+	JobOutputToolName = "job_output"
+)
+
+//go:embed job_output.md
+var jobOutputDescription []byte
+
+type JobOutputParams struct {
+	ShellID string `json:"shell_id" description:"The ID of the background shell to retrieve output from"`
+}
+
+type JobOutputResponseMetadata struct {
+	ShellID          string `json:"shell_id"`
+	Command          string `json:"command"`
+	Description      string `json:"description"`
+	Done             bool   `json:"done"`
+	WorkingDirectory string `json:"working_directory"`
+}
+
+func NewJobOutputTool() fantasy.AgentTool {
+	return fantasy.NewAgentTool(
+		JobOutputToolName,
+		string(jobOutputDescription),
+		func(ctx context.Context, params JobOutputParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
+			if params.ShellID == "" {
+				return fantasy.NewTextErrorResponse("missing shell_id"), nil
+			}
+
+			bgManager := shell.GetBackgroundShellManager()
+			bgShell, ok := bgManager.Get(params.ShellID)
+			if !ok {
+				return fantasy.NewTextErrorResponse(fmt.Sprintf("background shell not found: %s", params.ShellID)), nil
+			}
+
+			stdout, stderr, done, err := bgShell.GetOutput()
+
+			var outputParts []string
+			if stdout != "" {
+				outputParts = append(outputParts, stdout)
+			}
+			if stderr != "" {
+				outputParts = append(outputParts, stderr)
+			}
+
+			status := "running"
+			if done {
+				status = "completed"
+				if err != nil {
+					exitCode := shell.ExitCode(err)
+					if exitCode != 0 {
+						outputParts = append(outputParts, fmt.Sprintf("Exit code %d", exitCode))
+					}
+				}
+			}
+
+			output := strings.Join(outputParts, "\n")
+
+			metadata := JobOutputResponseMetadata{
+				ShellID:          params.ShellID,
+				Command:          bgShell.Command,
+				Description:      bgShell.Description,
+				Done:             done,
+				WorkingDirectory: bgShell.WorkingDir,
+			}
+
+			if output == "" {
+				output = BashNoOutput
+			}
+
+			result := fmt.Sprintf("Status: %s\n\n%s", status, output)
+			return fantasy.WithResponseMetadata(fantasy.NewTextResponse(result), metadata), nil
+		})
+}

internal/agent/tools/job_output.md 🔗

@@ -0,0 +1,19 @@
+Retrieves the current output from a background shell.
+
+<usage>
+- Provide the shell ID returned from a background bash execution
+- Returns the current stdout and stderr output
+- Indicates whether the shell has completed execution
+</usage>
+
+<features>
+- View output from running background processes
+- Check if background process has completed
+- Get cumulative output from process start
+</features>
+
+<tips>
+- Use this to monitor long-running processes
+- Check the 'done' status to see if process completed
+- Can be called multiple times to view incremental output
+</tips>

internal/agent/tools/job_test.go 🔗

@@ -0,0 +1,371 @@
+package tools
+
+import (
+	"context"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/charmbracelet/crush/internal/shell"
+	"github.com/stretchr/testify/require"
+)
+
+func TestBackgroundShell_Integration(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "echo 'hello background' && echo 'done'", "")
+	require.NoError(t, err)
+	require.NotEmpty(t, bgShell.ID)
+
+	// Wait for completion
+	bgShell.Wait()
+
+	// Check final output
+	stdout, stderr, done, err := bgShell.GetOutput()
+	require.NoError(t, err)
+	require.Contains(t, stdout, "hello background")
+	require.Contains(t, stdout, "done")
+	require.True(t, done)
+	require.Empty(t, stderr)
+
+	// Clean up
+	bgManager.Kill(bgShell.ID)
+}
+
+func TestBackgroundShell_Kill(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a long-running background shell
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "sleep 100", "")
+	require.NoError(t, err)
+
+	// Kill it
+	err = bgManager.Kill(bgShell.ID)
+	require.NoError(t, err)
+
+	// Verify it's gone
+	_, ok := bgManager.Get(bgShell.ID)
+	require.False(t, ok)
+
+	// Verify the shell is done
+	require.True(t, bgShell.IsDone())
+}
+
+func TestBackgroundShell_GetOutput_NoHang(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a long-running background shell
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "while true; do echo \"Hello from background job - $(date +%T)\"; sleep 1; done", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+	// wait for 2 seconds
+	time.Sleep(2 * time.Second)
+	stdout, _, _, err := bgShell.GetOutput()
+	require.NoError(t, err)
+	require.Len(t, strings.Split(stdout, "\n"), 3)
+}
+
+func TestBackgroundShell_MultipleOutputCalls(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "echo 'step 1' && echo 'step 2' && echo 'step 3'", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Check that we can call GetOutput multiple times while running
+	for range 5 {
+		_, _, done, _ := bgShell.GetOutput()
+		if done {
+			break
+		}
+		time.Sleep(10 * time.Millisecond)
+	}
+
+	// Wait for completion
+	bgShell.Wait()
+
+	// Multiple calls after completion should return the same result
+	stdout1, _, done1, _ := bgShell.GetOutput()
+	require.True(t, done1)
+	require.Contains(t, stdout1, "step 1")
+	require.Contains(t, stdout1, "step 2")
+	require.Contains(t, stdout1, "step 3")
+
+	stdout2, _, done2, _ := bgShell.GetOutput()
+	require.True(t, done2)
+	require.Equal(t, stdout1, stdout2, "Multiple GetOutput calls should return same result")
+}
+
+func TestBackgroundShell_EmptyOutput(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell with no output
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "sleep 0.1", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Wait for completion
+	bgShell.Wait()
+
+	stdout, stderr, done, err := bgShell.GetOutput()
+	require.NoError(t, err)
+	require.Empty(t, stdout)
+	require.Empty(t, stderr)
+	require.True(t, done)
+}
+
+func TestBackgroundShell_ExitCode(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell that exits with non-zero code
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "echo 'failing' && exit 42", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Wait for completion
+	bgShell.Wait()
+
+	stdout, _, done, execErr := bgShell.GetOutput()
+	require.True(t, done)
+	require.Contains(t, stdout, "failing")
+	require.Error(t, execErr)
+
+	exitCode := shell.ExitCode(execErr)
+	require.Equal(t, 42, exitCode)
+}
+
+func TestBackgroundShell_WithBlockFuncs(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	blockFuncs := []shell.BlockFunc{
+		shell.CommandsBlocker([]string{"curl", "wget"}),
+	}
+
+	// Start a background shell with a blocked command
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, blockFuncs, "curl example.com", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Wait for completion
+	bgShell.Wait()
+
+	stdout, stderr, done, execErr := bgShell.GetOutput()
+	require.True(t, done)
+
+	// The command should have been blocked, check stderr or error
+	if execErr != nil {
+		// Error might contain the message
+		require.Contains(t, execErr.Error(), "not allowed")
+	} else {
+		// Or it might be in stderr
+		output := stdout + stderr
+		require.Contains(t, output, "not allowed")
+	}
+}
+
+func TestBackgroundShell_StdoutAndStderr(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell with both stdout and stderr
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "echo 'stdout message' && echo 'stderr message' >&2", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Wait for completion
+	bgShell.Wait()
+
+	stdout, stderr, done, err := bgShell.GetOutput()
+	require.NoError(t, err)
+	require.True(t, done)
+	require.Contains(t, stdout, "stdout message")
+	require.Contains(t, stderr, "stderr message")
+}
+
+func TestBackgroundShell_ConcurrentAccess(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Start a background shell
+	bgManager := shell.GetBackgroundShellManager()
+	bgShell, err := bgManager.Start(ctx, workingDir, nil, "for i in 1 2 3 4 5; do echo \"line $i\"; sleep 0.05; done", "")
+	require.NoError(t, err)
+	defer bgManager.Kill(bgShell.ID)
+
+	// Access output concurrently from multiple goroutines
+	done := make(chan struct{})
+	errors := make(chan error, 10)
+
+	for range 10 {
+		go func() {
+			for {
+				select {
+				case <-done:
+					return
+				default:
+					_, _, _, err := bgShell.GetOutput()
+					if err != nil {
+						errors <- err
+					}
+					dir := bgShell.WorkingDir
+					if dir == "" {
+						errors <- err
+					}
+					time.Sleep(10 * time.Millisecond)
+				}
+			}
+		}()
+	}
+
+	// Let it run for a bit
+	time.Sleep(300 * time.Millisecond)
+	close(done)
+
+	// Check for any errors
+	select {
+	case err := <-errors:
+		t.Fatalf("Concurrent access caused error: %v", err)
+	case <-time.After(100 * time.Millisecond):
+		// No errors - success
+	}
+}
+
+func TestBackgroundShell_List(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	bgManager := shell.GetBackgroundShellManager()
+
+	// Start multiple background shells
+	shells := make([]*shell.BackgroundShell, 3)
+	for i := range 3 {
+		bgShell, err := bgManager.Start(ctx, workingDir, nil, "sleep 1", "")
+		require.NoError(t, err)
+		shells[i] = bgShell
+	}
+
+	// Get the list
+	ids := bgManager.List()
+
+	// Verify all our shells are in the list
+	for _, sh := range shells {
+		require.Contains(t, ids, sh.ID, "Shell %s not found in list", sh.ID)
+	}
+
+	// Clean up
+	for _, sh := range shells {
+		bgManager.Kill(sh.ID)
+	}
+}
+
+func TestBackgroundShell_AutoBackground(t *testing.T) {
+	t.Parallel()
+
+	workingDir := t.TempDir()
+	ctx := context.Background()
+
+	// Test that a quick command completes synchronously
+	t.Run("quick command completes synchronously", func(t *testing.T) {
+		t.Parallel()
+		bgManager := shell.GetBackgroundShellManager()
+		bgShell, err := bgManager.Start(ctx, workingDir, nil, "echo 'quick'", "")
+		require.NoError(t, err)
+
+		// Wait threshold time
+		time.Sleep(5 * time.Second)
+
+		// Should be done by now
+		stdout, stderr, done, err := bgShell.GetOutput()
+		require.NoError(t, err)
+		require.True(t, done, "Quick command should be done")
+		require.Contains(t, stdout, "quick")
+		require.Empty(t, stderr)
+
+		// Clean up
+		bgManager.Kill(bgShell.ID)
+	})
+
+	// Test that a long command stays in background
+	t.Run("long command stays in background", func(t *testing.T) {
+		t.Parallel()
+		bgManager := shell.GetBackgroundShellManager()
+		bgShell, err := bgManager.Start(ctx, workingDir, nil, "sleep 20 && echo '20 seconds completed'", "")
+		require.NoError(t, err)
+		defer bgManager.Kill(bgShell.ID)
+
+		// Wait threshold time
+		time.Sleep(5 * time.Second)
+
+		// Should still be running
+		stdout, stderr, done, err := bgShell.GetOutput()
+		require.NoError(t, err)
+		require.False(t, done, "Long command should still be running")
+		require.Empty(t, stdout, "No output yet from sleep command")
+		require.Empty(t, stderr)
+
+		// Verify we can get the shell from manager
+		retrieved, ok := bgManager.Get(bgShell.ID)
+		require.True(t, ok, "Should be able to retrieve background shell")
+		require.Equal(t, bgShell.ID, retrieved.ID)
+	})
+
+	// Test that we can check output of long-running command later
+	t.Run("can check output after completion", func(t *testing.T) {
+		t.Parallel()
+		bgManager := shell.GetBackgroundShellManager()
+		bgShell, err := bgManager.Start(ctx, workingDir, nil, "sleep 3 && echo 'completed'", "")
+		require.NoError(t, err)
+		defer bgManager.Kill(bgShell.ID)
+
+		// Initially should be running
+		_, _, done, _ := bgShell.GetOutput()
+		require.False(t, done, "Should be running initially")
+
+		// Wait for completion
+		time.Sleep(4 * time.Second)
+
+		// Now should be done
+		stdout, stderr, done, err := bgShell.GetOutput()
+		require.NoError(t, err)
+		require.True(t, done, "Should be done after waiting")
+		require.Contains(t, stdout, "completed")
+		require.Empty(t, stderr)
+	})
+}

internal/app/app.go 🔗

@@ -29,6 +29,7 @@ import (
 	"github.com/charmbracelet/crush/internal/permission"
 	"github.com/charmbracelet/crush/internal/pubsub"
 	"github.com/charmbracelet/crush/internal/session"
+	"github.com/charmbracelet/crush/internal/shell"
 	"github.com/charmbracelet/crush/internal/term"
 	"github.com/charmbracelet/crush/internal/tui/components/anim"
 	"github.com/charmbracelet/crush/internal/tui/styles"
@@ -368,6 +369,9 @@ func (app *App) Shutdown() {
 		app.AgentCoordinator.CancelAll()
 	}
 
+	// Kill all background shells.
+	shell.GetBackgroundShellManager().KillAll()
+
 	// Shutdown all LSP clients.
 	for name, client := range app.LSPClients.Seq2() {
 		shutdownCtx, cancel := context.WithTimeout(app.globalCtx, 5*time.Second)

internal/config/config.go 🔗

@@ -469,6 +469,8 @@ func allToolNames() []string {
 	return []string{
 		"agent",
 		"bash",
+		"job_output",
+		"job_kill",
 		"download",
 		"edit",
 		"multiedit",

internal/config/load_test.go 🔗

@@ -485,7 +485,8 @@ func TestConfig_setupAgentsWithDisabledTools(t *testing.T) {
 	cfg.SetupAgents()
 	coderAgent, ok := cfg.Agents[AgentCoder]
 	require.True(t, ok)
-	assert.Equal(t, []string{"agent", "bash", "multiedit", "lsp_diagnostics", "lsp_references", "fetch", "agentic_fetch", "glob", "ls", "sourcegraph", "view", "write"}, coderAgent.AllowedTools)
+
+	assert.Equal(t, []string{"agent", "bash", "job_output", "job_kill", "multiedit", "lsp_diagnostics", "lsp_references", "fetch", "agentic_fetch", "glob", "ls", "sourcegraph", "view", "write"}, coderAgent.AllowedTools)
 
 	taskAgent, ok := cfg.Agents[AgentTask]
 	require.True(t, ok)
@@ -508,7 +509,7 @@ func TestConfig_setupAgentsWithEveryReadOnlyToolDisabled(t *testing.T) {
 	cfg.SetupAgents()
 	coderAgent, ok := cfg.Agents[AgentCoder]
 	require.True(t, ok)
-	assert.Equal(t, []string{"agent", "bash", "download", "edit", "multiedit", "lsp_diagnostics", "lsp_references", "fetch", "agentic_fetch", "write"}, coderAgent.AllowedTools)
+	assert.Equal(t, []string{"agent", "bash", "job_output", "job_kill", "download", "edit", "multiedit", "lsp_diagnostics", "lsp_references", "fetch", "agentic_fetch", "write"}, coderAgent.AllowedTools)
 
 	taskAgent, ok := cfg.Agents[AgentTask]
 	require.True(t, ok)

internal/shell/background.go 🔗

@@ -0,0 +1,201 @@
+package shell
+
+import (
+	"bytes"
+	"context"
+	"fmt"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/charmbracelet/crush/internal/csync"
+)
+
+const (
+	// MaxBackgroundJobs is the maximum number of concurrent background jobs allowed
+	MaxBackgroundJobs = 50
+	// CompletedJobRetentionMinutes is how long to keep completed jobs before auto-cleanup (8 hours)
+	CompletedJobRetentionMinutes = 8 * 60
+)
+
+// BackgroundShell represents a shell running in the background.
+type BackgroundShell struct {
+	ID          string
+	Command     string
+	Description string
+	Shell       *Shell
+	WorkingDir  string
+	ctx         context.Context
+	cancel      context.CancelFunc
+	stdout      *bytes.Buffer
+	stderr      *bytes.Buffer
+	done        chan struct{}
+	exitErr     error
+	completedAt int64 // Unix timestamp when job completed (0 if still running)
+}
+
+// BackgroundShellManager manages background shell instances.
+type BackgroundShellManager struct {
+	shells *csync.Map[string, *BackgroundShell]
+}
+
+var (
+	backgroundManager     *BackgroundShellManager
+	backgroundManagerOnce sync.Once
+	idCounter             atomic.Uint64
+)
+
+// GetBackgroundShellManager returns the singleton background shell manager.
+func GetBackgroundShellManager() *BackgroundShellManager {
+	backgroundManagerOnce.Do(func() {
+		backgroundManager = &BackgroundShellManager{
+			shells: csync.NewMap[string, *BackgroundShell](),
+		}
+	})
+	return backgroundManager
+}
+
+// Start creates and starts a new background shell with the given command.
+func (m *BackgroundShellManager) Start(ctx context.Context, workingDir string, blockFuncs []BlockFunc, command string, description string) (*BackgroundShell, error) {
+	// Check job limit
+	if m.shells.Len() >= MaxBackgroundJobs {
+		return nil, fmt.Errorf("maximum number of background jobs (%d) reached. Please terminate or wait for some jobs to complete", MaxBackgroundJobs)
+	}
+
+	id := fmt.Sprintf("%03X", idCounter.Add(1))
+
+	shell := NewShell(&Options{
+		WorkingDir: workingDir,
+		BlockFuncs: blockFuncs,
+	})
+
+	shellCtx, cancel := context.WithCancel(ctx)
+
+	bgShell := &BackgroundShell{
+		ID:          id,
+		Command:     command,
+		Description: description,
+		WorkingDir:  workingDir,
+		Shell:       shell,
+		ctx:         shellCtx,
+		cancel:      cancel,
+		stdout:      &bytes.Buffer{},
+		stderr:      &bytes.Buffer{},
+		done:        make(chan struct{}),
+	}
+
+	m.shells.Set(id, bgShell)
+
+	go func() {
+		defer close(bgShell.done)
+
+		err := shell.ExecStream(shellCtx, command, bgShell.stdout, bgShell.stderr)
+
+		bgShell.exitErr = err
+		atomic.StoreInt64(&bgShell.completedAt, time.Now().Unix())
+	}()
+
+	return bgShell, nil
+}
+
+// Get retrieves a background shell by ID.
+func (m *BackgroundShellManager) Get(id string) (*BackgroundShell, bool) {
+	return m.shells.Get(id)
+}
+
+// Remove removes a background shell from the manager without terminating it.
+// This is useful when a shell has already completed and you just want to clean up tracking.
+func (m *BackgroundShellManager) Remove(id string) error {
+	_, ok := m.shells.Take(id)
+	if !ok {
+		return fmt.Errorf("background shell not found: %s", id)
+	}
+	return nil
+}
+
+// Kill terminates a background shell by ID.
+func (m *BackgroundShellManager) Kill(id string) error {
+	shell, ok := m.shells.Take(id)
+	if !ok {
+		return fmt.Errorf("background shell not found: %s", id)
+	}
+
+	shell.cancel()
+	<-shell.done
+	return nil
+}
+
+// BackgroundShellInfo contains information about a background shell.
+type BackgroundShellInfo struct {
+	ID          string
+	Command     string
+	Description string
+}
+
+// List returns all background shell IDs.
+func (m *BackgroundShellManager) List() []string {
+	ids := make([]string, 0, m.shells.Len())
+	for id := range m.shells.Seq2() {
+		ids = append(ids, id)
+	}
+	return ids
+}
+
+// Cleanup removes completed jobs that have been finished for more than the retention period
+func (m *BackgroundShellManager) Cleanup() int {
+	now := time.Now().Unix()
+	retentionSeconds := int64(CompletedJobRetentionMinutes * 60)
+
+	var toRemove []string
+	for shell := range m.shells.Seq() {
+		completedAt := atomic.LoadInt64(&shell.completedAt)
+		if completedAt > 0 && now-completedAt > retentionSeconds {
+			toRemove = append(toRemove, shell.ID)
+		}
+	}
+
+	for _, id := range toRemove {
+		m.Remove(id)
+	}
+
+	return len(toRemove)
+}
+
+// KillAll terminates all background shells.
+func (m *BackgroundShellManager) KillAll() {
+	shells := make([]*BackgroundShell, 0, m.shells.Len())
+	for shell := range m.shells.Seq() {
+		shells = append(shells, shell)
+	}
+	m.shells.Reset(map[string]*BackgroundShell{})
+
+	for _, shell := range shells {
+		shell.cancel()
+		<-shell.done
+	}
+}
+
+// GetOutput returns the current output of a background shell.
+func (bs *BackgroundShell) GetOutput() (stdout string, stderr string, done bool, err error) {
+	select {
+	case <-bs.done:
+		return bs.stdout.String(), bs.stderr.String(), true, bs.exitErr
+	default:
+		return bs.stdout.String(), bs.stderr.String(), false, nil
+	}
+}
+
+// IsDone checks if the background shell has finished execution.
+func (bs *BackgroundShell) IsDone() bool {
+	select {
+	case <-bs.done:
+		return true
+	default:
+		return false
+	}
+}
+
+// Wait blocks until the background shell completes.
+func (bs *BackgroundShell) Wait() {
+	<-bs.done
+}

internal/shell/background_test.go 🔗

@@ -0,0 +1,276 @@
+package shell
+
+import (
+	"context"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestBackgroundShellManager_Start(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'hello world'", "")
+	if err != nil {
+		t.Fatalf("failed to start background shell: %v", err)
+	}
+
+	if bgShell.ID == "" {
+		t.Error("expected shell ID to be non-empty")
+	}
+
+	// Wait for the command to complete
+	bgShell.Wait()
+
+	stdout, stderr, done, err := bgShell.GetOutput()
+	if !done {
+		t.Error("expected shell to be done")
+	}
+
+	if err != nil {
+		t.Errorf("expected no error, got: %v", err)
+	}
+
+	if !strings.Contains(stdout, "hello world") {
+		t.Errorf("expected stdout to contain 'hello world', got: %s", stdout)
+	}
+
+	if stderr != "" {
+		t.Errorf("expected empty stderr, got: %s", stderr)
+	}
+}
+
+func TestBackgroundShellManager_Get(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'test'", "")
+	if err != nil {
+		t.Fatalf("failed to start background shell: %v", err)
+	}
+
+	// Retrieve the shell
+	retrieved, ok := manager.Get(bgShell.ID)
+	if !ok {
+		t.Error("expected to find the background shell")
+	}
+
+	if retrieved.ID != bgShell.ID {
+		t.Errorf("expected shell ID %s, got %s", bgShell.ID, retrieved.ID)
+	}
+
+	// Clean up
+	manager.Kill(bgShell.ID)
+}
+
+func TestBackgroundShellManager_Kill(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	// Start a long-running command
+	bgShell, err := manager.Start(ctx, workingDir, nil, "sleep 10", "")
+	if err != nil {
+		t.Fatalf("failed to start background shell: %v", err)
+	}
+
+	// Kill it
+	err = manager.Kill(bgShell.ID)
+	if err != nil {
+		t.Errorf("failed to kill background shell: %v", err)
+	}
+
+	// Verify it's no longer in the manager
+	_, ok := manager.Get(bgShell.ID)
+	if ok {
+		t.Error("expected shell to be removed after kill")
+	}
+
+	// Verify the shell is done
+	if !bgShell.IsDone() {
+		t.Error("expected shell to be done after kill")
+	}
+}
+
+func TestBackgroundShellManager_KillNonExistent(t *testing.T) {
+	t.Parallel()
+
+	manager := GetBackgroundShellManager()
+
+	err := manager.Kill("non-existent-id")
+	if err == nil {
+		t.Error("expected error when killing non-existent shell")
+	}
+}
+
+func TestBackgroundShell_IsDone(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'quick'", "")
+	if err != nil {
+		t.Fatalf("failed to start background shell: %v", err)
+	}
+
+	// Wait a bit for the command to complete
+	time.Sleep(100 * time.Millisecond)
+
+	if !bgShell.IsDone() {
+		t.Error("expected shell to be done")
+	}
+
+	// Clean up
+	manager.Kill(bgShell.ID)
+}
+
+func TestBackgroundShell_WithBlockFuncs(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	blockFuncs := []BlockFunc{
+		CommandsBlocker([]string{"curl", "wget"}),
+	}
+
+	bgShell, err := manager.Start(ctx, workingDir, blockFuncs, "curl example.com", "")
+	if err != nil {
+		t.Fatalf("failed to start background shell: %v", err)
+	}
+
+	// Wait for the command to complete
+	bgShell.Wait()
+
+	stdout, stderr, done, execErr := bgShell.GetOutput()
+	if !done {
+		t.Error("expected shell to be done")
+	}
+
+	// The command should have been blocked
+	output := stdout + stderr
+	if !strings.Contains(output, "not allowed") && execErr == nil {
+		t.Errorf("expected command to be blocked, got stdout: %s, stderr: %s, err: %v", stdout, stderr, execErr)
+	}
+
+	// Clean up
+	manager.Kill(bgShell.ID)
+}
+
+func TestBackgroundShellManager_List(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	// Start two shells
+	bgShell1, err := manager.Start(ctx, workingDir, nil, "sleep 1", "")
+	if err != nil {
+		t.Fatalf("failed to start first background shell: %v", err)
+	}
+
+	bgShell2, err := manager.Start(ctx, workingDir, nil, "sleep 1", "")
+	if err != nil {
+		t.Fatalf("failed to start second background shell: %v", err)
+	}
+
+	ids := manager.List()
+
+	// Check that both shells are in the list
+	found1 := false
+	found2 := false
+	for _, id := range ids {
+		if id == bgShell1.ID {
+			found1 = true
+		}
+		if id == bgShell2.ID {
+			found2 = true
+		}
+	}
+
+	if !found1 {
+		t.Errorf("expected to find shell %s in list", bgShell1.ID)
+	}
+	if !found2 {
+		t.Errorf("expected to find shell %s in list", bgShell2.ID)
+	}
+
+	// Clean up
+	manager.Kill(bgShell1.ID)
+	manager.Kill(bgShell2.ID)
+}
+
+func TestBackgroundShellManager_KillAll(t *testing.T) {
+	t.Parallel()
+
+	ctx := context.Background()
+	workingDir := t.TempDir()
+	manager := GetBackgroundShellManager()
+
+	// Start multiple long-running shells
+	shell1, err := manager.Start(ctx, workingDir, nil, "sleep 10", "")
+	if err != nil {
+		t.Fatalf("failed to start shell 1: %v", err)
+	}
+
+	shell2, err := manager.Start(ctx, workingDir, nil, "sleep 10", "")
+	if err != nil {
+		t.Fatalf("failed to start shell 2: %v", err)
+	}
+
+	shell3, err := manager.Start(ctx, workingDir, nil, "sleep 10", "")
+	if err != nil {
+		t.Fatalf("failed to start shell 3: %v", err)
+	}
+
+	// Verify shells are running
+	if shell1.IsDone() || shell2.IsDone() || shell3.IsDone() {
+		t.Error("shells should not be done yet")
+	}
+
+	// Kill all shells
+	manager.KillAll()
+
+	// Verify all shells are done
+	if !shell1.IsDone() {
+		t.Error("shell1 should be done after KillAll")
+	}
+	if !shell2.IsDone() {
+		t.Error("shell2 should be done after KillAll")
+	}
+	if !shell3.IsDone() {
+		t.Error("shell3 should be done after KillAll")
+	}
+
+	// Verify they're removed from the manager
+	if _, ok := manager.Get(shell1.ID); ok {
+		t.Error("shell1 should be removed from manager")
+	}
+	if _, ok := manager.Get(shell2.ID); ok {
+		t.Error("shell2 should be removed from manager")
+	}
+	if _, ok := manager.Get(shell3.ID); ok {
+		t.Error("shell3 should be removed from manager")
+	}
+
+	// Verify list is empty (or doesn't contain our shells)
+	ids := manager.List()
+	for _, id := range ids {
+		if id == shell1.ID || id == shell2.ID || id == shell3.ID {
+			t.Errorf("shell %s should not be in list after KillAll", id)
+		}
+	}
+}

internal/shell/doc.go 🔗

@@ -16,12 +16,7 @@ package shell
 //	shell.Exec(ctx, "export FOO=bar")
 //	shell.Exec(ctx, "echo $FOO")  // Will print "bar"
 //
-// 3. For the singleton persistent shell (used by tools):
-//
-//	shell := shell.GetPersistentShell("/path/to/cwd")
-//	stdout, stderr, err := shell.Exec(ctx, "ls -la")
-//
-// 4. Managing environment and working directory:
+// 3. Managing environment and working directory:
 //
 //	shell := shell.NewShell(nil)
 //	shell.SetEnv("MY_VAR", "value")

internal/shell/persistent.go 🔗

@@ -1,43 +0,0 @@
-package shell
-
-import (
-	"log/slog"
-	"sync"
-)
-
-// PersistentShell is a singleton shell instance that maintains state across the application
-type PersistentShell struct {
-	*Shell
-}
-
-var (
-	once          sync.Once
-	shellInstance *PersistentShell
-)
-
-// GetPersistentShell returns the singleton persistent shell instance
-// This maintains backward compatibility with the existing API
-func GetPersistentShell(cwd string) *PersistentShell {
-	once.Do(func() {
-		shellInstance = &PersistentShell{
-			Shell: NewShell(&Options{
-				WorkingDir: cwd,
-				Logger:     &loggingAdapter{},
-			}),
-		}
-	})
-	return shellInstance
-}
-
-// INFO: only used for tests
-func Reset(cwd string) {
-	once = sync.Once{}
-	_ = GetPersistentShell(cwd)
-}
-
-// slog.dapter adapts the internal slog.package to the Logger interface
-type loggingAdapter struct{}
-
-func (l *loggingAdapter) InfoPersist(msg string, keysAndValues ...any) {
-	slog.Info(msg, keysAndValues...)
-}

internal/shell/shell.go 🔗

@@ -1,13 +1,12 @@
 // Package shell provides cross-platform shell execution capabilities.
 //
-// This package offers two main types:
-// - Shell: A general-purpose shell executor for one-off or managed commands
-// - PersistentShell: A singleton shell that maintains state across the application
+// This package provides Shell instances for executing commands with their own
+// working directory and environment. Each shell execution is independent.
 //
 // WINDOWS COMPATIBILITY:
-// This implementation provides both POSIX shell emulation (mvdan.cc/sh/v3),
-// even on Windows. Some caution has to be taken: commands should have forward
-// slashes (/) as path separators to work, even on Windows.
+// This implementation provides POSIX shell emulation (mvdan.cc/sh/v3) even on
+// Windows. Commands should use forward slashes (/) as path separators to work
+// correctly on all platforms.
 package shell
 
 import (
@@ -15,6 +14,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"io"
 	"os"
 	"slices"
 	"strings"
@@ -103,6 +103,14 @@ func (s *Shell) Exec(ctx context.Context, command string) (string, string, error
 	return s.exec(ctx, command)
 }
 
+// ExecStream executes a command in the shell with streaming output to provided writers
+func (s *Shell) ExecStream(ctx context.Context, command string, stdout, stderr io.Writer) error {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+
+	return s.execStream(ctx, command, stdout, stderr)
+}
+
 // GetWorkingDir returns the current working directory
 func (s *Shell) GetWorkingDir() string {
 	s.mu.Lock()
@@ -228,34 +236,56 @@ func (s *Shell) blockHandler() func(next interp.ExecHandlerFunc) interp.ExecHand
 	}
 }
 
-// exec executes commands using a cross-platform shell interpreter.
-func (s *Shell) exec(ctx context.Context, command string) (string, string, error) {
-	line, err := syntax.NewParser().Parse(strings.NewReader(command), "")
-	if err != nil {
-		return "", "", fmt.Errorf("could not parse command: %w", err)
-	}
-
-	var stdout, stderr bytes.Buffer
-	runner, err := interp.New(
-		interp.StdIO(nil, &stdout, &stderr),
+// newInterp creates a new interpreter with the current shell state
+func (s *Shell) newInterp(stdout, stderr io.Writer) (*interp.Runner, error) {
+	return interp.New(
+		interp.StdIO(nil, stdout, stderr),
 		interp.Interactive(false),
 		interp.Env(expand.ListEnviron(s.env...)),
 		interp.Dir(s.cwd),
 		interp.ExecHandlers(s.execHandlers()...),
 	)
-	if err != nil {
-		return "", "", fmt.Errorf("could not run command: %w", err)
-	}
+}
 
-	err = runner.Run(ctx, line)
+// updateShellFromRunner updates the shell from the interpreter after execution
+func (s *Shell) updateShellFromRunner(runner *interp.Runner) {
 	s.cwd = runner.Dir
+	s.env = nil
 	for name, vr := range runner.Vars {
 		s.env = append(s.env, fmt.Sprintf("%s=%s", name, vr.Str))
 	}
+}
+
+// execCommon is the shared implementation for executing commands
+func (s *Shell) execCommon(ctx context.Context, command string, stdout, stderr io.Writer) error {
+	line, err := syntax.NewParser().Parse(strings.NewReader(command), "")
+	if err != nil {
+		return fmt.Errorf("could not parse command: %w", err)
+	}
+
+	runner, err := s.newInterp(stdout, stderr)
+	if err != nil {
+		return fmt.Errorf("could not run command: %w", err)
+	}
+
+	err = runner.Run(ctx, line)
+	s.updateShellFromRunner(runner)
 	s.logger.InfoPersist("command finished", "command", command, "err", err)
+	return err
+}
+
+// exec executes commands using a cross-platform shell interpreter.
+func (s *Shell) exec(ctx context.Context, command string) (string, string, error) {
+	var stdout, stderr bytes.Buffer
+	err := s.execCommon(ctx, command, &stdout, &stderr)
 	return stdout.String(), stderr.String(), err
 }
 
+// execStream executes commands using POSIX shell emulation with streaming output
+func (s *Shell) execStream(ctx context.Context, command string, stdout, stderr io.Writer) error {
+	return s.execCommon(ctx, command, stdout, stderr)
+}
+
 func (s *Shell) execHandlers() []func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {
 	handlers := []func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc{
 		s.blockHandler(),

internal/tui/components/chat/messages/renderer.go 🔗

@@ -1,6 +1,7 @@
 package messages
 
 import (
+	"cmp"
 	"encoding/json"
 	"fmt"
 	"strings"
@@ -163,6 +164,8 @@ func (br baseRenderer) renderError(v *toolCallCmp, message string) string {
 // Register tool renderers
 func init() {
 	registry.register(tools.BashToolName, func() renderer { return bashRenderer{} })
+	registry.register(tools.JobOutputToolName, func() renderer { return bashOutputRenderer{} })
+	registry.register(tools.JobKillToolName, func() renderer { return bashKillRenderer{} })
 	registry.register(tools.DownloadToolName, func() renderer { return downloadRenderer{} })
 	registry.register(tools.ViewToolName, func() renderer { return viewRenderer{} })
 	registry.register(tools.EditToolName, func() renderer { return editRenderer{} })
@@ -213,7 +216,31 @@ func (br bashRenderer) Render(v *toolCallCmp) string {
 
 	cmd := strings.ReplaceAll(params.Command, "\n", " ")
 	cmd = strings.ReplaceAll(cmd, "\t", "    ")
-	args := newParamBuilder().addMain(cmd).build()
+	args := newParamBuilder().
+		addMain(cmd).
+		addFlag("background", params.RunInBackground).
+		build()
+	if v.call.Finished {
+		var meta tools.BashResponseMetadata
+		_ = br.unmarshalParams(v.result.Metadata, &meta)
+		if meta.Background {
+			description := cmp.Or(meta.Description, params.Command)
+			width := v.textWidth()
+			if v.isNested {
+				width -= 4 // Adjust for nested tool call indentation
+			}
+			header := makeJobHeader(v, "Start", fmt.Sprintf("PID %s", meta.ShellID), description, width)
+			if v.isNested {
+				return v.style().Render(header)
+			}
+			if res, done := earlyState(header, v); done {
+				return res
+			}
+			content := "Command: " + params.Command + "\n" + v.result.Content
+			body := renderPlainContent(v, content)
+			return joinHeaderBody(header, body)
+		}
+	}
 
 	return br.renderWithParams(v, "Bash", args, func() string {
 		var meta tools.BashResponseMetadata
@@ -232,6 +259,131 @@ func (br bashRenderer) Render(v *toolCallCmp) string {
 	})
 }
 
+// -----------------------------------------------------------------------------
+//  Bash Output renderer
+// -----------------------------------------------------------------------------
+
+func makeJobHeader(v *toolCallCmp, subcommand, pid, description string, width int) string {
+	t := styles.CurrentTheme()
+	icon := t.S().Base.Foreground(t.GreenDark).Render(styles.ToolPending)
+	if v.result.ToolCallID != "" {
+		if v.result.IsError {
+			icon = t.S().Base.Foreground(t.RedDark).Render(styles.ToolError)
+		} else {
+			icon = t.S().Base.Foreground(t.Green).Render(styles.ToolSuccess)
+		}
+	} else if v.cancelled {
+		icon = t.S().Muted.Render(styles.ToolPending)
+	}
+
+	jobPart := t.S().Base.Foreground(t.Blue).Render("Job")
+	subcommandPart := t.S().Base.Foreground(t.BlueDark).Render("(" + subcommand + ")")
+	pidPart := t.S().Muted.Render(pid)
+	descPart := ""
+	if description != "" {
+		descPart = " " + t.S().Subtle.Render(description)
+	}
+
+	// Build the complete header
+	prefix := fmt.Sprintf("%s %s %s %s", icon, jobPart, subcommandPart, pidPart)
+	fullHeader := prefix + descPart
+
+	// Truncate if needed
+	if lipgloss.Width(fullHeader) > width {
+		availableWidth := width - lipgloss.Width(prefix) - 1 // -1 for space
+		if availableWidth < 10 {
+			// Not enough space for description, just show prefix
+			return prefix
+		}
+		descPart = " " + t.S().Subtle.Render(ansi.Truncate(description, availableWidth, "…"))
+		fullHeader = prefix + descPart
+	}
+
+	return fullHeader
+}
+
+// bashOutputRenderer handles bash output retrieval display
+type bashOutputRenderer struct {
+	baseRenderer
+}
+
+// Render displays the shell ID and output from a background shell
+func (bor bashOutputRenderer) Render(v *toolCallCmp) string {
+	var params tools.JobOutputParams
+	if err := bor.unmarshalParams(v.call.Input, &params); err != nil {
+		return bor.renderError(v, "Invalid job_output parameters")
+	}
+
+	var meta tools.JobOutputResponseMetadata
+	var description string
+	if v.result.Metadata != "" {
+		if err := bor.unmarshalParams(v.result.Metadata, &meta); err == nil {
+			if meta.Description != "" {
+				description = meta.Description
+			} else {
+				description = meta.Command
+			}
+		}
+	}
+
+	width := v.textWidth()
+	if v.isNested {
+		width -= 4 // Adjust for nested tool call indentation
+	}
+	header := makeJobHeader(v, "Output", fmt.Sprintf("PID %s", params.ShellID), description, width)
+	if v.isNested {
+		return v.style().Render(header)
+	}
+	if res, done := earlyState(header, v); done {
+		return res
+	}
+	body := renderPlainContent(v, v.result.Content)
+	return joinHeaderBody(header, body)
+}
+
+// -----------------------------------------------------------------------------
+//  Bash Kill renderer
+// -----------------------------------------------------------------------------
+
+// bashKillRenderer handles bash process termination display
+type bashKillRenderer struct {
+	baseRenderer
+}
+
+// Render displays the shell ID being terminated
+func (bkr bashKillRenderer) Render(v *toolCallCmp) string {
+	var params tools.JobKillParams
+	if err := bkr.unmarshalParams(v.call.Input, &params); err != nil {
+		return bkr.renderError(v, "Invalid job_kill parameters")
+	}
+
+	var meta tools.JobKillResponseMetadata
+	var description string
+	if v.result.Metadata != "" {
+		if err := bkr.unmarshalParams(v.result.Metadata, &meta); err == nil {
+			if meta.Description != "" {
+				description = meta.Description
+			} else {
+				description = meta.Command
+			}
+		}
+	}
+
+	width := v.textWidth()
+	if v.isNested {
+		width -= 4 // Adjust for nested tool call indentation
+	}
+	header := makeJobHeader(v, "Kill", fmt.Sprintf("PID %s", params.ShellID), description, width)
+	if v.isNested {
+		return v.style().Render(header)
+	}
+	if res, done := earlyState(header, v); done {
+		return res
+	}
+	body := renderPlainContent(v, v.result.Content)
+	return joinHeaderBody(header, body)
+}
+
 // -----------------------------------------------------------------------------
 //  View renderer
 // -----------------------------------------------------------------------------
@@ -1013,6 +1165,10 @@ func prettifyToolName(name string) string {
 		return "Agent"
 	case tools.BashToolName:
 		return "Bash"
+	case tools.JobOutputToolName:
+		return "Job: Output"
+	case tools.JobKillToolName:
+		return "Job: Kill"
 	case tools.DownloadToolName:
 		return "Download"
 	case tools.EditToolName:

internal/tui/components/dialogs/permissions/permissions.go 🔗

@@ -291,19 +291,30 @@ func (p *permissionDialogCmp) renderHeader() string {
 			toolKey,
 			toolValue,
 		),
-		baseStyle.Render(strings.Repeat(" ", p.width)),
 		lipgloss.JoinHorizontal(
 			lipgloss.Left,
 			pathKey,
 			pathValue,
 		),
-		baseStyle.Render(strings.Repeat(" ", p.width)),
 	}
 
 	// Add tool-specific header information
 	switch p.permission.ToolName {
 	case tools.BashToolName:
-		headerParts = append(headerParts, t.S().Muted.Width(p.width).Render("Command"))
+		params := p.permission.Params.(tools.BashPermissionsParams)
+		descKey := t.S().Muted.Render("Desc")
+		descValue := t.S().Text.
+			Width(p.width - lipgloss.Width(descKey)).
+			Render(fmt.Sprintf(" %s", params.Description))
+		headerParts = append(headerParts,
+			lipgloss.JoinHorizontal(
+				lipgloss.Left,
+				descKey,
+				descValue,
+			),
+			baseStyle.Render(strings.Repeat(" ", p.width)),
+			t.S().Muted.Width(p.width).Render("Command"),
+		)
 	case tools.DownloadToolName:
 		params := p.permission.Params.(tools.DownloadPermissionsParams)
 		urlKey := t.S().Muted.Render("URL")
@@ -320,7 +331,6 @@ func (p *permissionDialogCmp) renderHeader() string {
 				urlKey,
 				urlValue,
 			),
-			baseStyle.Render(strings.Repeat(" ", p.width)),
 			lipgloss.JoinHorizontal(
 				lipgloss.Left,
 				fileKey,
@@ -372,9 +382,15 @@ func (p *permissionDialogCmp) renderHeader() string {
 			baseStyle.Render(strings.Repeat(" ", p.width)),
 		)
 	case tools.FetchToolName:
-		headerParts = append(headerParts, t.S().Muted.Width(p.width).Bold(true).Render("URL"))
+		headerParts = append(headerParts,
+			baseStyle.Render(strings.Repeat(" ", p.width)),
+			t.S().Muted.Width(p.width).Bold(true).Render("URL"),
+		)
 	case tools.AgenticFetchToolName:
-		headerParts = append(headerParts, t.S().Muted.Width(p.width).Bold(true).Render("URL"))
+		headerParts = append(headerParts,
+			baseStyle.Render(strings.Repeat(" ", p.width)),
+			t.S().Muted.Width(p.width).Bold(true).Render("URL"),
+		)
 	case tools.ViewToolName:
 		params := p.permission.Params.(tools.ViewPermissionsParams)
 		fileKey := t.S().Muted.Render("File")
@@ -466,6 +482,17 @@ func (p *permissionDialogCmp) generateBashContent() string {
 				Render(ln))
 		}
 
+		// Ensure minimum of 7 lines for command display
+		minLines := 7
+		for len(out) < minLines {
+			out = append(out, t.S().Muted.
+				Width(width).
+				Padding(0, 3).
+				Foreground(t.FgBase).
+				Background(t.BgSubtle).
+				Render(""))
+		}
+
 		// Use the cache for markdown rendering
 		renderedContent := strings.Join(out, "\n")
 		finalContent := baseStyle.
@@ -741,6 +768,7 @@ func (p *permissionDialogCmp) render() string {
 		title,
 		"",
 		headerContent,
+		"",
 		p.styleViewport(),
 		"",
 		buttons,

internal/tui/styles/charmtone.go 🔗

@@ -42,6 +42,7 @@ func NewCharmtoneTheme() *Theme {
 		White: charmtone.Butter,
 
 		BlueLight: charmtone.Sardine,
+		BlueDark:  charmtone.Damson,
 		Blue:      charmtone.Malibu,
 
 		Yellow: charmtone.Mustard,