@@ -29,10 +29,12 @@ package copilot
2929
3030import (
3131 "bufio"
32+ "bytes"
3233 "context"
3334 "encoding/json"
3435 "errors"
3536 "fmt"
37+ "io"
3638 "net"
3739 "os"
3840 "os/exec"
@@ -85,6 +87,8 @@ type Client struct {
8587 lifecycleHandlers []SessionLifecycleHandler
8688 typedLifecycleHandlers map [SessionLifecycleEventType ][]SessionLifecycleHandler
8789 lifecycleHandlersMux sync.Mutex
90+ stderrBuf bytes.Buffer // captures CLI stderr for error messages
91+ processDone chan error // signals when CLI process exits
8892
8993 // RPC provides typed server-scoped RPC methods.
9094 // This field is nil until the client is connected via Start().
@@ -149,6 +153,9 @@ func NewClient(options *ClientOptions) *Client {
149153 if options .CLIPath != "" {
150154 opts .CLIPath = options .CLIPath
151155 }
156+ if len (options .CLIArgs ) > 0 {
157+ opts .CLIArgs = append ([]string {}, options .CLIArgs ... )
158+ }
152159 if options .Cwd != "" {
153160 opts .Cwd = options .Cwd
154161 }
@@ -1022,7 +1029,10 @@ func (c *Client) startCLIServer(ctx context.Context) error {
10221029 // Default to "copilot" in PATH if no embedded CLI is available and no custom path is set
10231030 cliPath = "copilot"
10241031 }
1025- args := []string {"--headless" , "--no-auto-update" , "--log-level" , c .options .LogLevel }
1032+
1033+ // Start with user-provided CLIArgs, then add SDK-managed args
1034+ args := append ([]string {}, c .options .CLIArgs ... )
1035+ args = append (args , "--headless" , "--no-auto-update" , "--log-level" , c .options .LogLevel )
10261036
10271037 // Choose transport mode
10281038 if c .useStdio {
@@ -1087,21 +1097,32 @@ func (c *Client) startCLIServer(ctx context.Context) error {
10871097 return fmt .Errorf ("failed to create stderr pipe: %w" , err )
10881098 }
10891099
1090- // Read stderr in background
1100+ // Read stderr in background, capturing for error messages
10911101 go func () {
1092- scanner := bufio .NewScanner (stderr )
1093- for scanner .Scan () {
1094- // Optionally log stderr
1095- // fmt.Fprintf(os.Stderr, "CLI stderr: %s\n", scanner.Text())
1096- }
1102+ io .Copy (& c .stderrBuf , stderr )
10971103 }()
10981104
10991105 if err := c .process .Start (); err != nil {
11001106 return fmt .Errorf ("failed to start CLI server: %w" , err )
11011107 }
11021108
1109+ // Monitor process exit to signal pending requests
1110+ c .processDone = make (chan error , 1 )
1111+ go func () {
1112+ err := c .process .Wait ()
1113+ stderrOutput := strings .TrimSpace (c .stderrBuf .String ())
1114+ if stderrOutput != "" {
1115+ c .processDone <- fmt .Errorf ("CLI process exited: %v\n stderr: %s" , err , stderrOutput )
1116+ } else if err != nil {
1117+ c .processDone <- fmt .Errorf ("CLI process exited: %v" , err )
1118+ } else {
1119+ c .processDone <- fmt .Errorf ("CLI process exited unexpectedly" )
1120+ }
1121+ }()
1122+
11031123 // Create JSON-RPC client immediately
11041124 c .client = jsonrpc2 .NewClient (stdin , stdout )
1125+ c .client .SetProcessDone (c .processDone )
11051126 c .RPC = rpc .NewServerRpc (c .client )
11061127 c .setupNotificationHandler ()
11071128 c .client .Start ()
0 commit comments