@@ -86,12 +86,16 @@ async def _stream_claude_code(question: str, api_base_url: str):
8686
8787async def _stream_modal_sandbox (question : str , api_base_url : str ):
8888 """Stream output from Claude Code running in Modal Sandbox."""
89+ import logfire
8990
90- from policyengine_api .agent_sandbox import run_claude_code_in_sandbox
91+ sb = None
92+ try :
93+ from policyengine_api .agent_sandbox import run_claude_code_in_sandbox
9194
92- sb , process = run_claude_code_in_sandbox (question , api_base_url )
95+ logfire .info ("Creating Modal sandbox" , question = question [:100 ], api_base_url = api_base_url )
96+ sb , process = run_claude_code_in_sandbox (question , api_base_url )
97+ logfire .info ("Modal sandbox created, streaming output" )
9398
94- try :
9599 # Stream stdout line by line
96100 for line in process .stdout :
97101 yield f"data: { json .dumps ({'type' : 'output' , 'content' : line })} \n \n "
@@ -100,11 +104,20 @@ async def _stream_modal_sandbox(question: str, api_base_url: str):
100104
101105 if process .returncode != 0 :
102106 stderr = process .stderr .read ()
107+ logfire .error ("Claude Code failed in sandbox" , returncode = process .returncode , stderr = stderr [:500 ])
103108 yield f"data: { json .dumps ({'type' : 'error' , 'content' : stderr })} \n \n "
104109
105110 yield f"data: { json .dumps ({'type' : 'done' , 'returncode' : process .returncode })} \n \n "
111+ except Exception as e :
112+ logfire .exception ("Modal sandbox failed" , error = str (e ))
113+ yield f"data: { json .dumps ({'type' : 'error' , 'content' : f'Sandbox error: { str (e )} ' })} \n \n "
114+ yield f"data: { json .dumps ({'type' : 'done' , 'returncode' : 1 })} \n \n "
106115 finally :
107- sb .terminate ()
116+ if sb is not None :
117+ try :
118+ sb .terminate ()
119+ except Exception :
120+ pass
108121
109122
110123@router .post ("/stream" )
0 commit comments