import json,subprocess,os,threading,http.server,pathlib
root=pathlib.Path('/tmp/t3-25191-run'); home=root/'home';home.mkdir(exist_ok=True)
requests=[]
class Handler(http.server.BaseHTTPRequestHandler):
 def log_message(self,*a): pass
 def do_POST(self):
  data=json.loads(self.rfile.read(int(self.headers['Content-Length'])));requests.append(data)
  self.send_response(200);self.send_header('Content-Type','text/event-stream');self.end_headers()
  item={'id':'msg_1','type':'message','role':'assistant','content':[{'type':'output_text','text':'Hi','annotations':[]}]}
  response={'id':'resp_1','object':'response','status':'completed','output':[item],'usage':{'input_tokens':1,'output_tokens':1,'total_tokens':2}}
  for event in [{'type':'response.created','response':dict(response,status='in_progress',output=[])},{'type':'response.output_item.done','output_index':0,'item':item},{'type':'response.completed','response':response}]:
   self.wfile.write(('event: '+event['type']+'\ndata: '+json.dumps(event)+'\n\n').encode());self.wfile.flush()
s=http.server.HTTPServer(('127.0.0.1',0),Handler);threading.Thread(target=s.serve_forever,daemon=True).start()
(home/'config.toml').write_text(f'model="mock"\nmodel_provider="mock"\n[model_providers.mock]\nname="mock"\nbase_url="http://127.0.0.1:{s.server_port}/v1"\nwire_api="responses"\nrequires_openai_auth=false\n')
seq=0
p=None
def rpc(method,params):
 global seq
 seq+=1;p.stdin.write(json.dumps({'id':seq,'method':method,'params':params})+'\n');p.stdin.flush()
 while True:
  line=p.stdout.readline()
  if not line: raise RuntimeError('app-server exited')
  msg=json.loads(line)
  if msg.get('id')==seq:
   if 'error' in msg: raise RuntimeError(msg['error'])
   return msg['result']
def start():
 global p
 p=subprocess.Popen(['codex','app-server'],env=dict(os.environ,CODEX_HOME=str(home)),stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=open(root/'stderr.log','a'),text=True)
 rpc('initialize',{'clientInfo':{'name':'repro','version':'1'},'capabilities':{'experimentalApi':True}})
def turn(t):
 rpc('turn/start',{'threadId':t,'input':[{'type':'text','text':'Say hi'}],'additionalContext':{'t3_code_repro':{'kind':'application','value':'UNIQUE_T3_CONTEXT_MARKER'}}})
 while True:
  msg=json.loads(p.stdout.readline())
  if msg.get('method')=='turn/completed': break
 print('model-visible copies:',sum('UNIQUE_T3_CONTEXT_MARKER' in json.dumps(x) for x in requests[-1]['input']),flush=True)
try:
 start(); t=rpc('thread/start',{'cwd':str(root),'approvalPolicy':'never','sandbox':'read-only'})['thread']['id'];turn(t);turn(t)
 p.terminate();p.wait();start();rpc('thread/resume',{'threadId':t,'excludeTurns':True});turn(t);turn(t)
finally:
 if p: p.terminate();p.wait()
 s.shutdown();(root/'requests.json').write_text(json.dumps(requests,indent=2))
