|
|
@@ -64,7 +64,7 @@ it.skipIf(!process.env.YAOYAO_HERMES_PYTHON||!process.env.YAOYAO_COMPUTER_IMAGE)
|
|
|
const current=input.messages.slice(input.messages.findLastIndex((message:any)=>message.role==='user')+1)
|
|
|
const called=current.some((message:any)=>message.role==='tool')
|
|
|
const exported=current.some((message:any)=>message.role==='tool'&&message.name==='computer_export')
|
|
|
- const message=called&&!team&&!helper&&!exported?{role:'assistant',content:null,tool_calls:['result.txt','bulk.bin'].map(path=>({id:randomUUID(),type:'function',function:{name:'computer_export',arguments:JSON.stringify({path})}}))}:called?{role:'assistant',content:'隔离任务完成'}:{role:'assistant',content:null,tool_calls:[{id:randomUUID(),type:'function',function:{name:helper?'workspace_create_helper':team?'workspace_create_agent':'computer_shell',arguments:JSON.stringify(helper?{requestId:randomUUID(),goalId:helper[1],name:'临时核验助手',title:'临时核验',brief:'在隔离电脑完成 fixture:helper-work 并导出结果'}:team?{requestId:randomUUID(),name:'隔离创建成员',profile:'default'}:{command:control?'sleep 2; printf paused > pause-proof.txt':slow?'sleep 30; printf forbidden > late-write.txt':(process.env.YAOYAO_WORKER_PUBLIC_NETWORK==='1'?'curl --fail --silent --show-error --max-time 20 https://example.com > public.html; ':'')+'printf worker-proof > result.txt; head -c 2100000 /dev/zero > bulk.bin; id -u; pwd'})}}]}
|
|
|
+ const message=called&&!team&&!helper&&!exported?{role:'assistant',content:null,tool_calls:['result.txt','bulk.bin'].map(path=>({id:randomUUID(),type:'function',function:{name:'computer_export',arguments:JSON.stringify({path})}}))}:called?{role:'assistant',content:'隔离任务完成'}:{role:'assistant',content:null,tool_calls:[{id:randomUUID(),type:'function',function:{name:helper?'workspace_create_helper':team?'workspace_create_agent':'computer_shell',arguments:JSON.stringify(helper?{requestId:randomUUID(),goalId:helper[1],name:'临时核验助手',title:'临时核验',brief:'在隔离电脑完成 fixture:helper-work 并导出结果'}:team?{requestId:randomUUID(),name:'隔离创建成员',profile:'default'}:{command:String(user).includes('fixture:shared-write')?'sleep 6; printf shared-proof > result.txt; head -c 10 /dev/zero > bulk.bin':String(user).includes('fixture:shared-read')?'cat result.txt':control?'sleep 2; printf paused > pause-proof.txt':slow?'sleep 30; printf forbidden > late-write.txt':(process.env.YAOYAO_WORKER_PUBLIC_NETWORK==='1'?'curl --fail --silent --show-error --max-time 20 https://example.com > public.html; ':'')+'printf worker-proof > result.txt; head -c 2100000 /dev/zero > bulk.bin; id -u; pwd'})}}]}
|
|
|
if(input.stream){res.setHeader('Content-Type','text/event-stream');res.end('data: '+JSON.stringify({id:randomUUID(),object:'chat.completion.chunk',model:'fixture-model',choices:[{index:0,delta:{...message,...(message.tool_calls?{tool_calls:message.tool_calls.map((tool:any,index:number)=>({...tool,index}))}:{})},finish_reason:message.tool_calls?'tool_calls':'stop'}]})+'\n\ndata: [DONE]\n\n')}
|
|
|
else res.end(JSON.stringify({id:randomUUID(),object:'chat.completion',model:'fixture-model',choices:[{index:0,message,finish_reason:message.tool_calls?'tool_calls':'stop'}],usage:{prompt_tokens:10,completion_tokens:10,total_tokens:20}}))
|
|
|
})
|
|
|
@@ -142,6 +142,28 @@ it.skipIf(!process.env.YAOYAO_HERMES_PYTHON||!process.env.YAOYAO_COMPUTER_IMAGE)
|
|
|
await app.workspaceRuntime.stop(owner,cancelling.id)
|
|
|
await expect.poll(()=>app.workspace.require<any>(owner,'run',cancelling.id).status,{timeout:20000}).toBe('interrupted')
|
|
|
await expect(access(join(runnerHome,'computer-workspaces',worker.id,'late-write.txt'))).rejects.toMatchObject({code:'ENOENT'})
|
|
|
+ const second=app.workspace.createAgent(owner,{name:'共享核验成员',profile:'default',execution:'computer'})
|
|
|
+ const secondChat=app.workspace.list<any>(owner,'conversation').find(c=>c.memberIds[0]===second.id)!
|
|
|
+ const sharedAPI=(method:'post'|'delete',path:string,data:unknown)=>request(app.app.callback())[method](path).set('Host',`127.0.0.1:${app.config.port}`).set('Origin',address).set('Cookie',cookies).set('X-CSRF-Token',fresh.body.csrfToken).send(data)
|
|
|
+ const shared=await sharedAPI('post','/api/app/computers/shared',{requestId:randomUUID(),name:'真实共享电脑',memberIds:[worker.id,second.id],trusted:true}).expect(201)
|
|
|
+ const sharedWrite=app.workspaceRuntime.send(owner,direct.id,{requestId:randomUUID(),content:'fixture:shared-write'})
|
|
|
+ await expect.poll(()=>app.workspace.messages(owner,direct.id).some(message=>message.runId===sharedWrite.id&&message.tools.some(tool=>tool.name==='computer_shell')),{timeout:30000}).toBe(true)
|
|
|
+ const sharedRead=app.workspaceRuntime.send(owner,secondChat.id,{requestId:randomUUID(),content:'fixture:shared-read'})
|
|
|
+ await expect.poll(()=>app.workspace.require<any>(owner,'run',sharedRead.id).status,{timeout:45000}).toMatch(/complete|failed/)
|
|
|
+ expect(app.workspace.require<any>(owner,'run',sharedWrite.id).status).toBe('complete')
|
|
|
+ expect(app.workspace.require<any>(owner,'run',sharedRead.id).status,JSON.stringify(app.workspace.messages(owner,secondChat.id))).toBe('complete')
|
|
|
+ expect(await readFile(join(runnerHome,'computer-workspaces',shared.body.computer.id,'result.txt'),'utf8')).toBe('shared-proof')
|
|
|
+ expect(await readFile(join(runnerHome,'computer-workspaces',worker.id,'result.txt'),'utf8')).toBe('worker-proof')
|
|
|
+ const sharedReaderRequests=commands.filter(input=>String(input.messages.filter((message:any)=>message.role==='user').at(-1)?.content).includes('fixture:shared-read'))
|
|
|
+ expect(sharedReaderRequests.length).toBeGreaterThan(0)
|
|
|
+ expect(sharedReaderRequests.some(input=>input.messages.some((message:any)=>message.role==='user'&&String(message.content).includes('fixture:shared-write')))).toBe(false)
|
|
|
+ expect(sharedReaderRequests.some(input=>input.messages.some((message:any)=>message.role==='tool'&&String(message.content).includes('shared-proof')))).toBe(true)
|
|
|
+ const sharedTake=await api('/take',{requestId:randomUUID()}).expect(200)
|
|
|
+ await sharedAPI('post',`/api/app/agents/${second.id}/computer/take`,{requestId:randomUUID()}).expect(409)
|
|
|
+ await sharedAPI('delete',`/api/app/computers/shared/${shared.body.computer.id}`,{}).expect(409)
|
|
|
+ await api('/giveback',{controlId:sharedTake.body.controlId,token:sharedTake.body.token,notes:''}).expect(200)
|
|
|
+ await sharedAPI('delete',`/api/app/computers/shared/${shared.body.computer.id}`,{}).expect(200)
|
|
|
+ expect(app.workspace.require<any>(owner,'agent',worker.id).computerEnvironmentId).toBeUndefined()
|
|
|
const manager=app.workspace.createAgent(owner,{name:'隔离组队者',profile:'default',execution:'computer',canManageTeam:true})
|
|
|
const managerChat=app.workspace.list<any>(owner,'conversation').find(c=>c.memberIds[0]===manager.id)!
|
|
|
const managed=app.workspaceRuntime.send(owner,managerChat.id,{requestId:randomUUID(),content:'fixture:team'})
|