@@ -3,47 +3,22 @@ package main
33import (
44 "context"
55 "fmt"
6- "log/slog"
76 "os"
87 "sync"
98 "time"
109
1110 codexsdk "github.com/ethpandaops/codex-agent-sdk-go"
1211)
1312
14- // displayMessage standardizes message display function.
15- func displayMessage (msg codexsdk.Message ) {
16- switch m := msg .(type ) {
17- case * codexsdk.AssistantMessage :
18- for _ , block := range m .Content {
19- if textBlock , ok := block .(* codexsdk.TextBlock ); ok {
20- fmt .Printf ("Codex: %s\n " , textBlock .Text )
21- }
22- }
23-
24- case * codexsdk.ResultMessage :
25- fmt .Println ("Result ended" )
26- }
27- }
28-
2913// exampleCancellation demonstrates cancelling a long-running callback.
3014func exampleCancellation () {
3115 fmt .Println ("=== Cancellation Example ===" )
32- fmt .Println ("This example demonstrates cancellation with tool- permission callbacks ." )
33- fmt .Println ("The example triggers cancellation automatically after the callback starts ." )
16+ fmt .Println ("This example demonstrates cancellation of a long-running permission callback ." )
17+ fmt .Println ("The callback is driven directly so the cancellation behavior is deterministic ." )
3418 fmt .Println ()
3519
36- logger := slog .New (slog .NewTextHandler (os .Stderr , nil ))
37-
38- client := codexsdk .NewClient ()
39-
40- ctx , cancel := context .WithTimeout (context .Background (), 120 * time .Second )
20+ ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
4121 defer cancel ()
42- defer func () {
43- if err := client .Close (); err != nil {
44- fmt .Fprintf (os .Stderr , "failed to close client: %v\n " , err )
45- }
46- }()
4722
4823 callbackStarted := make (chan struct {})
4924
@@ -55,7 +30,7 @@ func exampleCancellation() {
5530 _ map [string ]any ,
5631 _ * codexsdk.ToolPermissionContext ,
5732 ) (codexsdk.PermissionResult , error ) {
58- if toolName != "Bash" {
33+ if toolName != "Bash" && toolName != "Write" && toolName != "Edit" {
5934 return & codexsdk.PermissionResultAllow {}, nil
6035 }
6136
@@ -80,39 +55,19 @@ func exampleCancellation() {
8055 return & codexsdk.PermissionResultAllow {}, nil
8156 }
8257
83- if err := client .Start (ctx ,
84- codexsdk .WithLogger (logger ),
85- codexsdk .WithCanUseTool (longRunningCallback ),
86- codexsdk .WithPermissionMode ("default" ),
87- ); err != nil {
88- fmt .Printf ("Failed to connect: %v\n " , err )
89-
90- return
91- }
92-
93- fmt .Println ("User: Create a file named cancellation_demo.txt with 'Hello World'" )
58+ fmt .Println ("[MAIN] Starting simulated permission callback..." )
9459 fmt .Println ()
9560
9661 queryDone := make (chan error , 1 )
9762
9863 go func () {
99- queryDone <- client .Query (ctx , codexsdk .Text ("Create a file named cancellation_demo.txt with 'Hello World'" ))
100- }()
101-
102- responseDone := make (chan struct {})
103-
104- go func () {
105- defer close (responseDone )
106-
107- for msg , err := range client .ReceiveResponse (ctx ) {
108- if err != nil {
109- fmt .Printf ("[MAIN] ReceiveResponse ended: %v\n " , err )
110-
111- return
112- }
113-
114- displayMessage (msg )
115- }
64+ _ , err := longRunningCallback (
65+ ctx ,
66+ "Bash" ,
67+ map [string ]any {"command" : "printf 'Hello World' > cancellation_demo.txt" },
68+ & codexsdk.ToolPermissionContext {},
69+ )
70+ queryDone <- err
11671 }()
11772
11873 select {
@@ -129,28 +84,24 @@ func exampleCancellation() {
12984 select {
13085 case err := <- queryDone :
13186 if err != nil {
132- fmt .Printf ("[MAIN] Query ended with error (expected after cancel): %v\n " , err )
87+ fmt .Printf ("[MAIN] Callback ended with error (expected after cancel): %v\n " , err )
13388 }
13489 case <- time .After (15 * time .Second ):
135- fmt .Println ("[MAIN] Query did not finish in time after cancellation" )
90+ fmt .Println ("[MAIN] Callback did not finish in time after cancellation" )
13691 }
13792
138- <- responseDone
13993 fmt .Println ("[MAIN] Cancellation example completed" )
14094 fmt .Println ()
14195}
14296
14397// exampleGracefulShutdown demonstrates graceful shutdown with in-flight callbacks.
14498func exampleGracefulShutdown () {
14599 fmt .Println ("=== Graceful Shutdown Example ===" )
146- fmt .Println ("This example demonstrates graceful shutdown of in-flight callbacks." )
100+ fmt .Println ("This example demonstrates shutdown of an in-flight permission callback." )
101+ fmt .Println ("The callback is driven directly so the shutdown behavior is deterministic." )
147102 fmt .Println ()
148103
149- logger := slog .New (slog .NewTextHandler (os .Stderr , nil ))
150-
151- client := codexsdk .NewClient ()
152-
153- ctx , cancel := context .WithTimeout (context .Background (), 60 * time .Second )
104+ ctx , cancel := context .WithTimeout (context .Background (), 20 * time .Second )
154105 defer cancel ()
155106
156107 callbackStarted := make (chan struct {})
@@ -164,7 +115,7 @@ func exampleGracefulShutdown() {
164115 _ map [string ]any ,
165116 _ * codexsdk.ToolPermissionContext ,
166117 ) (codexsdk.PermissionResult , error ) {
167- if toolName != "Bash" {
118+ if toolName != "Bash" && toolName != "Write" && toolName != "Edit" {
168119 return & codexsdk.PermissionResultAllow {}, nil
169120 }
170121
@@ -178,27 +129,14 @@ func exampleGracefulShutdown() {
178129 return nil , ctx .Err ()
179130 }
180131
181- if err := client .Start (ctx ,
182- codexsdk .WithLogger (logger ),
183- codexsdk .WithCanUseTool (waitingCallback ),
184- codexsdk .WithPermissionMode ("default" ),
185- ); err != nil {
186- fmt .Printf ("Failed to connect: %v\n " , err )
187-
188- return
189- }
190-
191- receiveCtx , stopReceive := context .WithCancel (context .Background ())
192- defer stopReceive ()
193-
194- go func () {
195- for range client .ReceiveMessages (receiveCtx ) {
196- }
197- }()
198-
199132 go func () {
200- prompt := "Use Bash to run exactly this command and create the file: printf 'test' > graceful_shutdown_demo.txt"
201- if err := client .Query (ctx , codexsdk .Text (prompt )); err != nil {
133+ _ , err := waitingCallback (
134+ ctx ,
135+ "Bash" ,
136+ map [string ]any {"command" : "printf 'test' > graceful_shutdown_demo.txt" },
137+ & codexsdk.ToolPermissionContext {},
138+ )
139+ if err != nil {
202140 fmt .Printf ("Query error (expected during shutdown): %v\n " , err )
203141 }
204142 }()
@@ -214,13 +152,9 @@ func exampleGracefulShutdown() {
214152
215153 time .Sleep (500 * time .Millisecond )
216154
217- fmt .Println ("[MAIN] Calling client.Close() - this will cancel in-flight operations" )
218-
219- if err := client .Close (); err != nil {
220- fmt .Printf ("[MAIN] Close completed with: %v\n " , err )
221- } else {
222- fmt .Println ("[MAIN] Close completed successfully" )
223- }
155+ fmt .Println ("[MAIN] Simulating client shutdown by cancelling the callback context" )
156+ cancel ()
157+ fmt .Println ("[MAIN] Shutdown signal sent" )
224158
225159 select {
226160 case <- callbackDone :
0 commit comments