agentEnvs.test.ts 4.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // @vitest-environment node
  2. import {beforeEach,afterEach,expect,it,vi} from 'vitest'
  3. import {mkdtempSync,rmSync} from 'node:fs'
  4. import {join} from 'node:path'
  5. import {tmpdir} from 'node:os'
  6. import Koa from 'koa'
  7. import {bodyParser} from '@koa/bodyparser'
  8. import request from 'supertest'
  9. import {WorkspaceStore} from '../../src/server/workspaceStore'
  10. import {WorkspaceNodes} from '../../src/server/workspaceGateway'
  11. import {loadServerConfig} from '../../src/server/config'
  12. import {GrokCloud} from '../../src/server/grokCloud'
  13. import {agentEnvs,deriveComputer} from '../../src/shared/workspace'
  14. let home:string,store:WorkspaceStore,nodes:WorkspaceNodes
  15. const auth={require:(ctx:any)=>({id:ctx.get('x-user')||'owner',role:'admin'}),requireAdmin:(ctx:any)=>({id:ctx.get('x-user')||'owner',role:'admin'}),isUserActive:()=>true,pushAuthorizationVersion:()=>1} as any
  16. beforeEach(()=>{home=mkdtempSync(join(tmpdir(),'agent-envs-'));store=new WorkspaceStore(home);nodes=new WorkspaceNodes(store,loadServerConfig({HERMES_YAOYAO_HOME:home}),{} as any)})
  17. afterEach(()=>{nodes.close();store.close();rmSync(home,{recursive:true,force:true})})
  18. const app=(cloud:GrokCloud)=>{const a=new Koa();a.use(async(ctx,next)=>{try{await next()}catch(e:any){ctx.status=e.status??500;ctx.body={error:e.message,code:e.code}}});a.use(bodyParser());a.use(cloud.router().routes());return a.callback()}
  19. it('derives parallel environments from legacy single choices and auto',()=>{
  20. expect(agentEnvs({computer:'vm'})).toEqual({vm:true,cloud:false,desktop:false,browser:false})
  21. expect(agentEnvs({computer:'cloud'})).toEqual({vm:false,cloud:true,desktop:false,browser:false})
  22. expect(agentEnvs({computer:'local'})).toEqual({vm:false,cloud:false,desktop:true,browser:false})
  23. expect(agentEnvs({computer:'auto'})).toEqual({vm:true,cloud:true,desktop:true,browser:false})
  24. expect(agentEnvs({computer:'off'})).toEqual({vm:false,cloud:false,desktop:false,browser:false})
  25. expect(agentEnvs({envs:{cloud:true,desktop:true}})).toEqual({vm:false,cloud:true,desktop:true,browser:false})
  26. expect(deriveComputer({vm:true,cloud:true,desktop:true,browser:false})).toBe('vm')
  27. expect(deriveComputer({cloud:true,desktop:true})).toBe('cloud')
  28. expect(deriveComputer({desktop:true})).toBe('local')
  29. expect(deriveComputer({})).toBe('off')
  30. })
  31. it('writes envs through computer-selection and projects computer for older clients while the chat stays on the server',async()=>{
  32. const cloud=new GrokCloud(store,auth,nodes,{assertLocalVmIdle:()=>{}} as any,vi.fn(async()=>new Response('{}')))
  33. const agent=store.createAgent('owner',{name:'并行机器人',profile:'default',computer:'auto'})
  34. const path=`/api/app/agents/${agent.id}/computer-selection`
  35. const first=await request(app(cloud)).put(path).send({envs:{vm:true,cloud:true,desktop:true}}).expect(200)
  36. expect(first.body.agent).toMatchObject({envs:{vm:true,cloud:true,desktop:true},computer:'vm',execution:'profile'})
  37. const cleared=await request(app(cloud)).put(path).send({envs:{}}).expect(200)
  38. expect(cleared.body.agent).toMatchObject({envs:{},computer:'off',execution:'profile'})
  39. const desktopOnly=await request(app(cloud)).put(path).send({envs:{desktop:true}}).expect(200)
  40. expect(desktopOnly.body.agent).toMatchObject({envs:{desktop:true},computer:'local',execution:'profile',allowHostEnvironment:false})
  41. await request(app(cloud)).put(path).send({envs:{vm:true},desktopHost:'local'}).expect(200)
  42. expect(store.require<any>('owner','agent',agent.id)).toMatchObject({envs:{vm:true},desktopHost:'local',computer:'vm',execution:'profile'})
  43. })
  44. it('raw computer writes on an envs agent only toggle the VM leg',async()=>{
  45. const agent=store.createAgent('owner',{name:'混合',profile:'default',computer:'local'})
  46. store.updateAgent('owner',agent.id,{envs:{vm:true,cloud:true,desktop:true}})
  47. store.updateAgent('owner',agent.id,{computer:'off'})
  48. expect(store.require<any>('owner','agent',agent.id)).toMatchObject({envs:{vm:false,cloud:true,desktop:true},computer:'cloud',execution:'profile'})
  49. store.updateAgent('owner',agent.id,{computer:'vm'})
  50. expect(store.require<any>('owner','agent',agent.id)).toMatchObject({envs:{vm:true,cloud:true,desktop:true},computer:'vm',execution:'profile'})
  51. })
  52. it('selects the cloud environment in parallel regardless of desktop readiness',async()=>{
  53. const cloud=new GrokCloud(store,auth,nodes,{assertLocalVmIdle:()=>{}} as any,vi.fn(async()=>new Response('{}')))
  54. const agent=store.createAgent('owner',{name:'云桌面并列',profile:'default',computer:'off',envs:{vm:true,cloud:true,desktop:true}})
  55. expect(cloud.selected('owner',agent)).toBe(false)
  56. store.put('owner','grok-cloud','connection',{sealed:'x'})
  57. expect(cloud.selected('owner',agent)).toBe(true)
  58. cloud.preferDesktop=()=>true
  59. expect(cloud.selected('owner',agent)).toBe(true)
  60. })