Prechádzať zdrojové kódy

修复 Profile 会话停止轮询向 active_list 误传 session_id 被契约拒收

rpc() 包装器给所有方法无条件注入 session_id,而 session.active_list 是
管理级接口(仅接受 profile/current_session_id,extra=forbid),Hermes
返回 invalid params 4000,导致恢复会话/回合结束/人工接管时 stop() 抛错、
Bot 无法聊天。active_list 改为传 profile 路由;测试 fixture 同步按契约
拒绝未知参数,防回归。
Samien 1 mesiac pred
rodič
commit
152bfcb00f

+ 2 - 0
src/runner/worker/profileSession.ts

@@ -75,6 +75,8 @@ export class ProfileComputerSession {
   }
   rpc(method:string,params:Record<string,unknown>={}){
     const {session_id:_virtual,workMarker:_marker,...options}=params
+    // session.active_list is manager-scoped: Hermes' contract is extra=forbid and rejects session_id.
+    if(method==='session.active_list')return this.gateway.rpc(method,{...options,profile:this.profile})
     return this.gateway.rpc(method,{...options,session_id:this.runtimeId})
   }
   async file(action:'read'|'write',path:string,data?:string){

+ 9 - 1
tests/server/profileComputer.test.ts

@@ -38,7 +38,11 @@ async function fixture(hermesManaged=false,bridgeVersion=2){
         const id=randomUUID(),stored=request.method==='session.resume'?request.params.session_id:randomUUID()
         sessions.set(id,{stored,running:false})
         result={session_id:id,stored_session_id:stored,running:false,info:{profile_name:request.params.profile,cwd:home}}
-      }else if(request.method==='session.active_list')result={sessions:[...sessions].map(([id,s])=>({id,status:s.running?'working':'idle'}))}
+      }else if(request.method==='session.active_list'){
+        const unknown=Object.keys(request.params??{}).filter(key=>!['profile','current_session_id'].includes(key))
+        if(unknown.length){connected.send(JSON.stringify({id:request.id,error:{message:`invalid params for session.active_list: ${unknown[0]}: Extra inputs are not permitted`}}));return}
+        result={sessions:[...sessions].map(([id,s])=>({id,status:s.running?'working':'idle'}))}
+      }
       else if(request.method==='session.usage')result={context_used:123,context_max:32000}
       else if(request.method==='image.attach_bytes')result={ref_text:'[image](/hermes/attachments/image.png)'}
       else if(request.method==='file.attach')result={ref_text:`[host attachment](${home}/input.txt)`}
@@ -157,6 +161,10 @@ it('waits for native termination and VM calls before human takeover, then resume
     expect((await f.runtime.controls.status(f.meta)).mode).toBe('agent')
     f.setInterruptStops(true);await g.rpc('session.interrupt',{session_id:session.session_id})
     expect((await f.runtime.controls.status(f.meta)).mode).toBe('off')
+    const poll=f.calls.find(c=>c.method==='session.active_list')
+    expect(poll).toBeDefined()
+    expect(poll!.params).not.toHaveProperty('session_id')
+    expect(poll!.params).toMatchObject({profile:'default'})
     await expect(f.post('/tools/list',{})).rejects.toThrow()
   }finally{await f.close()}
 })