shennian 0.4.66 → 0.4.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/publish-build-manifest.json +39 -34
- package/dist/src/agents/acp/manifests.d.ts +2 -2
- package/dist/src/agents/adapter.d.ts +1 -1
- package/dist/src/agents/codex.js +5 -5
- package/dist/src/index.js +3 -3
- package/dist/src/manager/registry.d.ts +10 -0
- package/dist/src/manager/registry.js +1 -1
- package/dist/src/manager/runtime.d.ts +4 -2
- package/dist/src/manager/runtime.js +6 -6
- package/dist/src/manager/worker-ipc.d.ts +5 -3
- package/dist/src/manager/worker-ipc.js +1 -1
- package/dist/src/room/activation-service.d.ts +8 -2
- package/dist/src/room/activation-service.js +10 -5
- package/dist/src/room/managed-context.d.ts +3 -1
- package/dist/src/room/managed-context.js +1 -1
- package/dist/src/room/managed-room-ipc.d.ts +2 -0
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/session/handlers/chat-recovery.js +1 -1
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/manager-event-authority.d.ts +3 -0
- package/dist/src/session/manager-event-authority.js +1 -0
- package/dist/src/session/manager.d.ts +2 -2
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/queue-helpers.d.ts +5 -0
- package/dist/src/session/queue-helpers.js +8 -8
- package/dist/src/session/queue-message.d.ts +4 -1
- package/dist/src/session/queue-message.js +1 -1
- package/dist/src/session/queue-storage.d.ts +1 -0
- package/dist/src/session/queue-storage.js +2 -2
- package/dist/src/session/queue-types.d.ts +8 -0
- package/dist/src/session/queue.d.ts +3 -3
- package/dist/src/session/queue.js +1 -1
- package/dist/src/session/queued-chat-dispatch.js +1 -1
- package/dist/src/session/turn-trigger.d.ts +5 -0
- package/package.json +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
`).trim()}function $(d){return d==="worker.final"?"completed":d==="worker.error"?"failed":d==="worker.aborted"?"stopped":"progress"}function U(d,e){return`manager-inbox:${_("sha256").update(d).update("\0").update(e.map(r=>r.id).join("\0")).digest("hex").slice(0,32)}`}async function j(d){const e=[];let t=0;for await(const r of d){const n=Buffer.isBuffer(r)?r:Buffer.from(r);if(t+=n.length,t>H)throw new Error("Request body too large");e.push(n)}return e.length===0?{}:JSON.parse(Buffer.concat(e).toString("utf8"))}function G(d,e,t,r){d.client.sendRes({type:"res",id:e,ok:t,...t?{payload:r}:{error:String(r.error||"unknown error")}})}function S(){return F()?I.join(R.tmpdir(),"shennian-vitest-runtime",String(process.pid),"manager-ipc.json"):P("runtime","manager-ipc.json")}function F(){return(process.env.VITEST==="true"||!!process.env.VITEST_WORKER_ID)&&!process.env.SHENNIAN_HOME?.trim()}class ue{opts;managedPolicies=new Map;registry=new T;channelRuntime;server=null;ipcUrl=null;ipcToken=N(24).toString("hex");healthTimer=null;startPromise=null;workerTextAcc=new Map;constructor(e){this.opts=e,this.channelRuntime=e.channelRuntime??new q}async start(){return this.startPromise?this.startPromise:(this.startPromise=this.doStart(),this.startPromise)}async doStart(){if(this.server)return;this.server=x.createServer((t,r)=>{this.handleIpc(t,r)}),this.server.requestTimeout=p,this.server.timeout=p,this.server.keepAliveTimeout=p,this.server.headersTimeout=p+5e3,await new Promise((t,r)=>{this.server.once("error",r),this.server.listen(0,"127.0.0.1",()=>t())});const e=this.server.address();typeof e=="object"&&e&&(this.ipcUrl=`http://127.0.0.1:${e.port}`,this.writeIpcRuntimeFile()),this.server.unref(),await this.channelRuntime.start(),this.healthTimer=setInterval(()=>this.scanWorkerHealth(),6e4),this.healthTimer.unref(),this.recoverPersistedInboxDeliveries()}async ready(){await this.start()}async stop(){this.healthTimer&&clearInterval(this.healthTimer),this.healthTimer=null,await this.channelRuntime.stop(),await new Promise(e=>{if(!this.server)return e();this.server.close(()=>e())}),this.server=null,this.ipcUrl=null,this.removeIpcRuntimeFile()}writeIpcRuntimeFile(){if(this.ipcUrl)try{const e=S();l.mkdirSync(I.dirname(e),{recursive:!0}),l.writeFileSync(e,JSON.stringify({url:this.ipcUrl,token:this.ipcToken,pid:process.pid,updatedAt:new Date().toISOString()},null,2),{mode:384}),l.chmodSync(e,384)}catch{}}removeIpcRuntimeFile(){try{const e=S(),t=JSON.parse(l.readFileSync(e,"utf-8"));(t.url===this.ipcUrl||t.token===this.ipcToken)&&l.unlinkSync(e)}catch{}}getInjectedEnv(e,t,r,n){return this.ipcUrl?{SHENNIAN_MANAGER_SESSION_ID:e,SHENNIAN_MANAGER_AGENT_SESSION_ID:t??"",SHENNIAN_MANAGER_WORKDIR:g(r),SHENNIAN_MANAGER_MODEL:n,SHENNIAN_MANAGER_IPC_URL:this.ipcUrl,SHENNIAN_MANAGER_IPC_TOKEN:this.ipcToken}:{}}registerManager(e){this.registry.upsertManager({...e,workDir:g(e.workDir),machineId:process.env.SHENNIAN_MACHINE_ID??null,managedRoomBound:e.managedRoomBound??(this.managedPolicies.has(e.sessionId)||void 0)})}setManagedAgentPolicy(e,t){if(t){this.managedPolicies.set(e,t);const r=this.registry.getManager(e);r&&!r.managedRoomBound&&this.registry.upsertManager({...r,managedRoomBound:!0})}else this.managedPolicies.delete(e)}getManagedAgentPolicyForWorker(e,t){const r=this.registry.getManager(e),n=this.managedPolicies.get(e);return!r||!n||g(t)!==r.workDir?null:n}isNativeSkillManager(e,t){const r=this.registry.getManager(e);return r?.controllerKind==="native_skill"&&g(t)===r.workDir}isManagedWorkerSession(e){return!!this.findWorker(e)}isManagedRoomBoundManager(e){return this.registry.getManager(e)?.managedRoomBound===!0}async retireManagerAndWorkers(e){const t=this.registry.retireManager(e);this.managedPolicies.delete(e);const r=this.opts.getRuntime(),n=[],s=async(i,h)=>{const o=[];try{r.runJournal?.markSessionAborted(i)}catch(c){o.push(c)}try{r.recoveryBarrier?.end(i)}catch(c){o.push(c)}try{r.chatQueue?.purgeSession(i)}catch(c){o.push(c)}const a=r.sessions.get(i);let u=!a;if(a){if(a.managedRoomContextToken)try{r.revokeManagedRoomContextToken?.(a.managedRoomContextToken),a.managedRoomContextToken=null}catch(c){o.push(c)}try{await a.adapter.stop(),u=!0}catch(c){o.push(c)}}if(a&&u&&o.length===0&&(r.sessions.delete(i),a.heartbeatTimer&&clearInterval(a.heartbeatTimer),a.adapter.removeAllListeners()),u&&o.length===0)try{h?.()}catch(c){o.push(c),n.push(c)}else n.push(...o)};await s(e);for(const i of t)await s(i.sessionId,()=>this.registry.completeRetiredWorker(e,i.sessionId));if(n.length)throw new AggregateError(n,"Failed to retire every Manager or Worker session");return t.map(i=>i.sessionId)}setManagerWorkerDefaults(e,t,r){const n=this.registry.getManager(e);n&&this.registry.upsertManager({...n,defaultWorkerAgentType:t??null,defaultWorkerModelId:r??null})}getManagerWorkerDefaults(e){const t=this.registry.getManager(e);return{agentType:t?.defaultWorkerAgentType??null,modelId:t?.defaultWorkerModelId??null}}noteManagerAgentSession(e,t,r,n){const s=this.registry.getManager(e);this.registry.upsertManager({sessionId:e,agentSessionId:t,workDir:g(r),machineId:process.env.SHENNIAN_MACHINE_ID??null,modelId:n,agentType:s?.agentType,providerModelId:s?.providerModelId})}noteAgentEvent(e,t){const r=this.findWorker(e);if(!r)return;const n={lastActivityAt:new Date().toISOString(),runId:t.runId};t.agentSessionId&&(n.agentSessionId=t.agentSessionId);const s=`${e}:${t.runId}`;let i=t.message||r.summary||"(\u65E0\u53EF\u89C1\u5185\u5BB9)";if(t.state==="delta"&&t.text&&!t.thinking){const o=(this.workerTextAcc.get(s)??"")+t.text;this.workerTextAcc.set(s,o);const a=k(o);a&&(n.summary=a.length>160?`${a.slice(0,160)}...`:a)}if(t.state==="final"||t.state==="error"||t.state==="aborted"){n.status=t.state;const o=k(this.workerTextAcc.get(s)??"");o&&(n.summary=o.length>240?`${o.slice(0,240)}...`:o,i=t.message||o),this.workerTextAcc.delete(s)}else t.state==="start"&&(n.status="running");const h=this.registry.updateWorker(e,n);h&&(t.state==="final"||t.state==="error"||t.state==="aborted")&&this.enqueueWorkerEvent(h.managedBy,h,t.state,t.runId,i)}findWorker(e){return this.registry.load().workers[e]}async handleAppReq(e){G(this.opts.getRuntime(),e.id,!1,{error:"feature_retired"})}async handleIpc(e,t){if(e.headers.authorization!==`Bearer ${this.ipcToken}`){m(t,401,{ok:!1,error:"Unauthorized"});return}try{const r=new URL(e.url??"/","http://127.0.0.1"),n=await j(e);if(r.pathname.startsWith("/channel/")||r.pathname.startsWith("/external/")||r.pathname.startsWith("/wechat-rpa/")){m(t,410,{ok:!1,error:"feature_retired"});return}const s=await E({registry:this.registry,getRuntime:this.opts.getRuntime,dispatchReq:this.opts.dispatchReq,dispatchChatEnqueue:this.dispatchChatEnqueue.bind(this),appendManagerVisibleMarkdown:this.appendManagerVisibleMarkdown.bind(this)},r.pathname,n,String(e.headers["x-shennian-manager-session-id"]||""));if(s){m(t,s.status,s.body);return}m(t,404,{ok:!1,error:`Unknown manager IPC path: ${r.pathname}`})}catch(r){m(t,400,{ok:!1,error:r instanceof Error?r.message:String(r)})}}async executeScopedWorkerAction(e,t,r){const n={"manager.sessions.list":"/sessions/list","manager.sessions.start":"/sessions/start","manager.sessions.send":"/sessions/send","manager.sessions.queue":"/sessions/queue","manager.sessions.queue.edit":"/sessions/queue/edit","manager.sessions.queue.delete":"/sessions/queue/delete","manager.sessions.stop":"/sessions/stop","manager.sessions.read":"/sessions/read","manager.memory.path":"/memory/path"},s=await E({registry:this.registry,getRuntime:this.opts.getRuntime,dispatchReq:this.opts.dispatchReq,dispatchChatEnqueue:this.dispatchChatEnqueue.bind(this),appendManagerVisibleMarkdown:this.appendManagerVisibleMarkdown.bind(this)},n[t],r,e);if(!s||s.status<200||s.status>=300)throw new Error(String(s?.body.error||"Managed Manager action failed"));return JSON.parse(JSON.stringify(s.body))}async dispatchChatEnqueue(e,t,r,n,s,i,h){if((await this.opts.dispatchReq({type:"req",id:`manager-enqueue-${y()}`,method:"chat.enqueue",params:{...M(),sessionId:e,text:n,agentType:t,workDir:r,agentSessionId:s,modelId:i,managedWorkerParentSessionId:h}}))?.durableQueueHandoff===!1)throw new Error("manager_worker_queue_handoff_unconfirmed")}appendManagerVisibleMarkdown(e,t,r){this.registry.getManager(e)?.controllerKind!=="native_skill"&&(W(e,{id:r,sessionId:e,role:"agent",ts:Date.now(),payload:t},"committed"),D(this.opts.getRuntime().client))}enqueueWorkerEvent(e,t,r,n,s){const i=this.registry.enqueueInboxEvent({managerSessionId:e,workerSessionId:t.sessionId,kind:r==="final"?"worker.final":r==="error"?"worker.error":"worker.aborted",priority:"normal",runId:n??null,summary:s||t.summary||"(\u65E0\u53EF\u89C1\u6458\u8981)"}),h=this.registry.getManager(e);i&&h?.controllerKind!=="native_skill"&&this.drainManagerInbox(e)}scanWorkerHealth(){const e=Date.now(),t=this.registry.load(),r=this.opts.getRuntime();for(const n of Object.values(t.workers)){if(n.status!=="running")continue;const s=e-Date.parse(n.createdAt);if(s<10*6e4)continue;const i=e-Date.parse(n.lastActivityAt),h=r.sessions.get(n.sessionId)?.currentRunId,o=!!r.chatQueue?.getSnapshot(n.sessionId).pending.length;if(!h){if(!o&&i>=10*6e4){const v="\u672A\u627E\u5230\u6D3B\u52A8\u4E2D\u7684 Provider Run \u6216\u5F85\u5904\u7406\u6D88\u606F\uFF1B\u5DF2\u5C06\u9057\u7559\u7684\u8FD0\u884C\u72B6\u6001\u6536\u655B\u4E3A\u5931\u8D25\u3002\u539F Worker \u4F1A\u8BDD\u4ECD\u4FDD\u7559\uFF0C\u53EF\u7EE7\u7EED\u53D1\u9001\u65B0\u6D88\u606F\u3002",f=this.registry.updateWorker(n.sessionId,{status:"error",lastActivityAt:new Date(e).toISOString(),summary:v});f&&this.enqueueWorkerEvent(f.managedBy,f,"error",n.runId??void 0,v)}continue}const a=n.healthNotifiedAt?Date.parse(n.healthNotifiedAt):0;if(a&&e-a<10*6e4)continue;const u=t.managers[n.managedBy];if(!u)continue;const c=Math.max(0,Math.floor(i/6e4)),b=k(n.runId?this.workerTextAcc.get(`${n.sessionId}:${n.runId}`)??"":""),w=`\u5DF2\u8FD0\u884C ${Math.floor(s/6e4)} \u5206\u949F\uFF0C\u5C1A\u672A\u7ED3\u675F\u3002
|
|
1
|
+
import N from"node:http";import{createHash as _,randomBytes as T,randomUUID as k}from"node:crypto";import m from"node:fs";import E from"node:os";import M from"node:path";import{ManagerRegistry as W}from"./registry.js";import{appendMessage as O}from"../session/store.js";import{requestSessionIndexPublish as D}from"../session/index-publisher.js";import{RetiredChannelRuntime as q}from"./retired-external-channel-compat.js";import{resolveShennianPath as P}from"../config/index.js";import{buildExternalChannelInstructions as C}from"../agents/external-channel-instructions.js";import{getPersonalSyncIdentity as w}from"../personal-sync/epoch.js";import{handleWorkerIpcRoute as A}from"./worker-ipc.js";import{deriveWorkerTitle as B,formatWorkerMarkdown as H}from"./worker-markdown.js";import{markTrustedManagerEvent as S}from"../session/manager-event-authority.js";const $=Number(process.env.SHENNIAN_MANAGER_IPC_BODY_MAX_BYTES||2*1024*1024),y=12*6e4;let b=null;function ue(u){b=u}function ge(){return b}function p(u){return M.resolve(u||E.homedir())}function f(u,e,t){u.writeHead(e,{"content-type":"application/json; charset=utf-8"}),u.end(JSON.stringify(t))}function R(u){return u.replace(/\r\n/g,`
|
|
2
|
+
`).trim()}function U(u){return u==="worker.final"?"completed":u==="worker.error"?"failed":u==="worker.aborted"?"stopped":"progress"}function j(u,e){return`manager-inbox:${_("sha256").update(u).update("\0").update(e.map(r=>r.id).join("\0")).digest("hex").slice(0,32)}`}async function G(u){const e=[];let t=0;for await(const r of u){const n=Buffer.isBuffer(r)?r:Buffer.from(r);if(t+=n.length,t>$)throw new Error("Request body too large");e.push(n)}return e.length===0?{}:JSON.parse(Buffer.concat(e).toString("utf8"))}function F(u,e,t,r){u.client.sendRes({type:"res",id:e,ok:t,...t?{payload:r}:{error:String(r.error||"unknown error")}})}function x(){return J()?M.join(E.tmpdir(),"shennian-vitest-runtime",String(process.pid),"manager-ipc.json"):P("runtime","manager-ipc.json")}function J(){return(process.env.VITEST==="true"||!!process.env.VITEST_WORKER_ID)&&!process.env.SHENNIAN_HOME?.trim()}class de{opts;managedPolicies=new Map;registry=new W;channelRuntime;server=null;ipcUrl=null;ipcToken=T(24).toString("hex");healthTimer=null;startPromise=null;workerTextAcc=new Map;pendingWorkerOrigins=new Map;prepareWorkerTurnOrigin(e,t){t?this.pendingWorkerOrigins.set(e,t):this.pendingWorkerOrigins.delete(e)}constructor(e){this.opts=e,this.channelRuntime=e.channelRuntime??new q}async start(){return this.startPromise?this.startPromise:(this.startPromise=this.doStart(),this.startPromise)}async doStart(){if(this.server)return;this.registry.clearWorkerRunOrigins(),this.server=N.createServer((t,r)=>{this.handleIpc(t,r)}),this.server.requestTimeout=y,this.server.timeout=y,this.server.keepAliveTimeout=y,this.server.headersTimeout=y+5e3,await new Promise((t,r)=>{this.server.once("error",r),this.server.listen(0,"127.0.0.1",()=>t())});const e=this.server.address();typeof e=="object"&&e&&(this.ipcUrl=`http://127.0.0.1:${e.port}`,this.writeIpcRuntimeFile()),this.server.unref(),await this.channelRuntime.start(),this.healthTimer=setInterval(()=>this.scanWorkerHealth(),6e4),this.healthTimer.unref(),this.recoverPersistedInboxDeliveries()}async ready(){await this.start()}async stop(){this.healthTimer&&clearInterval(this.healthTimer),this.healthTimer=null,await this.channelRuntime.stop(),await new Promise(e=>{if(!this.server)return e();this.server.close(()=>e())}),this.server=null,this.ipcUrl=null,this.removeIpcRuntimeFile()}writeIpcRuntimeFile(){if(this.ipcUrl)try{const e=x();m.mkdirSync(M.dirname(e),{recursive:!0}),m.writeFileSync(e,JSON.stringify({url:this.ipcUrl,token:this.ipcToken,pid:process.pid,updatedAt:new Date().toISOString()},null,2),{mode:384}),m.chmodSync(e,384)}catch{}}removeIpcRuntimeFile(){try{const e=x(),t=JSON.parse(m.readFileSync(e,"utf-8"));(t.url===this.ipcUrl||t.token===this.ipcToken)&&m.unlinkSync(e)}catch{}}getInjectedEnv(e,t,r,n){return this.ipcUrl?{SHENNIAN_MANAGER_SESSION_ID:e,SHENNIAN_MANAGER_AGENT_SESSION_ID:t??"",SHENNIAN_MANAGER_WORKDIR:p(r),SHENNIAN_MANAGER_MODEL:n,SHENNIAN_MANAGER_IPC_URL:this.ipcUrl,SHENNIAN_MANAGER_IPC_TOKEN:this.ipcToken}:{}}registerManager(e){this.registry.upsertManager({...e,workDir:p(e.workDir),machineId:process.env.SHENNIAN_MACHINE_ID??null,managedRoomBound:e.managedRoomBound??(this.managedPolicies.has(e.sessionId)||void 0)})}setManagedAgentPolicy(e,t){if(t){this.managedPolicies.set(e,t);const r=this.registry.getManager(e);r&&!r.managedRoomBound&&this.registry.upsertManager({...r,managedRoomBound:!0})}else this.managedPolicies.delete(e)}getManagedAgentPolicyForWorker(e,t){const r=this.registry.getManager(e),n=this.managedPolicies.get(e);return!r||!n||p(t)!==r.workDir?null:n}isNativeSkillManager(e,t){const r=this.registry.getManager(e);return r?.controllerKind==="native_skill"&&p(t)===r.workDir}isManagedWorkerSession(e){return!!this.findWorker(e)}isManagedRoomBoundManager(e){return this.registry.getManager(e)?.managedRoomBound===!0}async retireManagerAndWorkers(e){const t=this.registry.retireManager(e);this.managedPolicies.delete(e);const r=this.opts.getRuntime(),n=[],i=async(s,d)=>{const a=[];try{r.runJournal?.markSessionAborted(s)}catch(l){a.push(l)}try{r.recoveryBarrier?.end(s)}catch(l){a.push(l)}try{r.chatQueue?.purgeSession(s)}catch(l){a.push(l)}const o=r.sessions.get(s);let c=!o;if(o){if(o.managedRoomContextToken)try{r.revokeManagedRoomContextToken?.(o.managedRoomContextToken),o.managedRoomContextToken=null}catch(l){a.push(l)}try{await o.adapter.stop(),c=!0}catch(l){a.push(l)}}if(o&&c&&a.length===0&&(r.sessions.delete(s),o.heartbeatTimer&&clearInterval(o.heartbeatTimer),o.adapter.removeAllListeners()),c&&a.length===0)try{d?.()}catch(l){a.push(l),n.push(l)}else n.push(...a)};await i(e);for(const s of t)await i(s.sessionId,()=>this.registry.completeRetiredWorker(e,s.sessionId));if(n.length)throw new AggregateError(n,"Failed to retire every Manager or Worker session");return t.map(s=>s.sessionId)}setManagerWorkerDefaults(e,t,r){const n=this.registry.getManager(e);n&&this.registry.upsertManager({...n,defaultWorkerAgentType:t??null,defaultWorkerModelId:r??null})}getManagerWorkerDefaults(e){const t=this.registry.getManager(e);return{agentType:t?.defaultWorkerAgentType??null,modelId:t?.defaultWorkerModelId??null}}noteManagerAgentSession(e,t,r,n){const i=this.registry.getManager(e);this.registry.upsertManager({sessionId:e,agentSessionId:t,workDir:p(r),machineId:process.env.SHENNIAN_MACHINE_ID??null,modelId:n,agentType:i?.agentType,providerModelId:i?.providerModelId})}noteAgentEvent(e,t){const r=this.findWorker(e);if(!r)return;const n={lastActivityAt:new Date().toISOString(),runId:t.runId};if(t.agentSessionId&&(n.agentSessionId=t.agentSessionId),t.state==="start"){const a=this.pendingWorkerOrigins.get(e);this.pendingWorkerOrigins.delete(e),a&&(n.runRoomOrigins={...r.runRoomOrigins??{},[t.runId]:a})}const i=`${e}:${t.runId}`;let s=t.message||r.summary||"(\u65E0\u53EF\u89C1\u5185\u5BB9)";if(t.state==="delta"&&t.text&&!t.thinking){const a=(this.workerTextAcc.get(i)??"")+t.text;this.workerTextAcc.set(i,a);const o=R(a);o&&(n.summary=o.length>160?`${o.slice(0,160)}...`:o)}if(t.state==="final"||t.state==="error"||t.state==="aborted"){n.status=t.state;const a=R(this.workerTextAcc.get(i)??"");if(a&&(n.summary=a.length>240?`${a.slice(0,240)}...`:a,s=t.message||a),this.workerTextAcc.delete(i),r.runRoomOrigins?.[t.runId]){const o={...r.runRoomOrigins};delete o[t.runId],n.runRoomOrigins=o}}else t.state==="start"&&(n.status="running");const d=this.registry.updateWorker(e,n);d&&(t.state==="final"||t.state==="error"||t.state==="aborted")&&this.enqueueWorkerEvent(d.managedBy,d,t.state,t.runId,s,r.runRoomOrigins?.[t.runId]??null)}findWorker(e){return this.registry.load().workers[e]}async handleAppReq(e){F(this.opts.getRuntime(),e.id,!1,{error:"feature_retired"})}async handleIpc(e,t){if(e.headers.authorization!==`Bearer ${this.ipcToken}`){f(t,401,{ok:!1,error:"Unauthorized"});return}try{const r=new URL(e.url??"/","http://127.0.0.1"),n=await G(e);if(r.pathname.startsWith("/channel/")||r.pathname.startsWith("/external/")||r.pathname.startsWith("/wechat-rpa/")){f(t,410,{ok:!1,error:"feature_retired"});return}const i=await A({registry:this.registry,getRuntime:this.opts.getRuntime,dispatchReq:this.opts.dispatchReq,dispatchChatEnqueue:this.dispatchChatEnqueue.bind(this),appendManagerVisibleMarkdown:this.appendManagerVisibleMarkdown.bind(this)},r.pathname,n,String(e.headers["x-shennian-manager-session-id"]||""));if(i){f(t,i.status,i.body);return}f(t,404,{ok:!1,error:`Unknown manager IPC path: ${r.pathname}`})}catch(r){f(t,400,{ok:!1,error:r instanceof Error?r.message:String(r)})}}async executeScopedWorkerAction(e,t,r,n){const i={"manager.sessions.list":"/sessions/list","manager.sessions.start":"/sessions/start","manager.sessions.send":"/sessions/send","manager.sessions.queue":"/sessions/queue","manager.sessions.queue.edit":"/sessions/queue/edit","manager.sessions.queue.delete":"/sessions/queue/delete","manager.sessions.stop":"/sessions/stop","manager.sessions.read":"/sessions/read","manager.memory.path":"/memory/path"},s=await A({registry:this.registry,getRuntime:this.opts.getRuntime,dispatchReq:this.opts.dispatchReq,dispatchChatEnqueue:this.dispatchChatEnqueue.bind(this),appendManagerVisibleMarkdown:this.appendManagerVisibleMarkdown.bind(this)},i[t],r,e,{roomOrigin:n});if(!s||s.status<200||s.status>=300)throw new Error(String(s?.body.error||"Managed Manager action failed"));return JSON.parse(JSON.stringify(s.body))}async dispatchChatEnqueue(e,t,r,n,i,s,d,a){if((await this.opts.dispatchReq(S({type:"req",id:`manager-enqueue-${k()}`,method:"chat.enqueue",params:{...w(),sessionId:e,text:n,agentType:t,workDir:r,agentSessionId:i,modelId:s,managedWorkerParentSessionId:d,managerWorkerRoomOrigin:a}})))?.durableQueueHandoff===!1)throw new Error("manager_worker_queue_handoff_unconfirmed")}appendManagerVisibleMarkdown(e,t,r){this.registry.getManager(e)?.controllerKind!=="native_skill"&&(O(e,{id:r,sessionId:e,role:"agent",ts:Date.now(),payload:t},"committed"),D(this.opts.getRuntime().client))}enqueueWorkerEvent(e,t,r,n,i,s){const d=this.registry.enqueueInboxEvent({managerSessionId:e,workerSessionId:t.sessionId,kind:r==="final"?"worker.final":r==="error"?"worker.error":"worker.aborted",priority:"normal",runId:n??null,roomOrigin:s??null,summary:i||t.summary||"(\u65E0\u53EF\u89C1\u6458\u8981)"}),a=this.registry.getManager(e);d&&a?.controllerKind!=="native_skill"&&this.drainManagerInbox(e)}scanWorkerHealth(){const e=Date.now(),t=this.registry.load(),r=this.opts.getRuntime();for(const n of Object.values(t.workers)){if(n.status!=="running")continue;const i=e-Date.parse(n.createdAt);if(i<10*6e4)continue;const s=e-Date.parse(n.lastActivityAt),d=r.sessions.get(n.sessionId)?.currentRunId,a=!!r.chatQueue?.getSnapshot(n.sessionId).pending.length;if(!d){if(!a&&s>=10*6e4){const v="\u672A\u627E\u5230\u6D3B\u52A8\u4E2D\u7684 Provider Run \u6216\u5F85\u5904\u7406\u6D88\u606F\uFF1B\u5DF2\u5C06\u9057\u7559\u7684\u8FD0\u884C\u72B6\u6001\u6536\u655B\u4E3A\u5931\u8D25\u3002\u539F Worker \u4F1A\u8BDD\u4ECD\u4FDD\u7559\uFF0C\u53EF\u7EE7\u7EED\u53D1\u9001\u65B0\u6D88\u606F\u3002",I=this.registry.updateWorker(n.sessionId,{status:"error",lastActivityAt:new Date(e).toISOString(),summary:v});I&&this.enqueueWorkerEvent(I.managedBy,I,"error",n.runId??void 0,v)}continue}const o=n.healthNotifiedAt?Date.parse(n.healthNotifiedAt):0;if(o&&e-o<10*6e4)continue;const c=t.managers[n.managedBy];if(!c)continue;const l=Math.max(0,Math.floor(s/6e4)),g=R(n.runId?this.workerTextAcc.get(`${n.sessionId}:${n.runId}`)??"":""),h=`\u5DF2\u8FD0\u884C ${Math.floor(i/6e4)} \u5206\u949F\uFF0C\u5C1A\u672A\u7ED3\u675F\u3002
|
|
3
3
|
|
|
4
4
|
\u5F53\u524D\u53EF\u89C1\u8FDB\u5C55\uFF1A
|
|
5
|
-
- \u6700\u8FD1\u6587\u672C\uFF1A${
|
|
5
|
+
- \u6700\u8FD1\u6587\u672C\uFF1A${g||n.summary||"(\u65E0\u53EF\u89C1\u5185\u5BB9)"}
|
|
6
6
|
- \u6700\u8FD1\u6D3B\u52A8\u65F6\u95F4\uFF1A${n.lastActivityAt}
|
|
7
|
-
- \u6700\u8FD1 ${
|
|
7
|
+
- \u6700\u8FD1 ${l} \u5206\u949F\u6CA1\u6709\u65B0\u6D3B\u52A8\u3002`;this.registry.updateWorker(n.sessionId,{healthNotifiedAt:new Date(e).toISOString(),lastHealthSummary:h}),this.registry.enqueueInboxEvent({managerSessionId:c.sessionId,workerSessionId:n.sessionId,kind:"worker.health",priority:"normal",runId:n.runId??null,roomOrigin:n.runRoomOrigins?.[n.runId??""]??null,summary:h})&&c.controllerKind!=="native_skill"&&this.drainManagerInbox(c.sessionId)}}async interruptAndResumeManager(e,t,r,n){this.opts.getRuntime().sessions.get(e.sessionId)?.currentRunId&&await this.opts.dispatchReq({type:"req",id:`manager-interrupt-${k()}`,method:"chat.abort",params:{...w(),sessionId:e.sessionId}}),await this.dispatchManagerContinuation(e,t,!1,r,n)}bindManagerAdapterEvents(e,t){t.on("agentEvent",r=>{if(r.state==="start"&&r.agentSessionId){const n=this.registry.getManager(e);n&&this.noteManagerAgentSession(e,r.agentSessionId,n.workDir,n.modelId)}r.state==="start"&&(this.acknowledgeManagerInboxDelivery(e),this.updateManagerStatus(e,"running")),(r.state==="final"||r.state==="error"||r.state==="aborted")&&(this.updateManagerStatus(e,"idle"),queueMicrotask(()=>{this.drainManagerInbox(e)}))})}updateManagerStatus(e,t){const r=this.registry.getManager(e);r&&this.registry.upsertManager({...r,status:t})}async drainManagerInbox(e){const t=this.registry.getManager(e);if(!t||t.deliveringInboxEventIds?.length)return;const r=this.registry.listInboxEvents(e);if(!r.length)return;const n=r.find(g=>g.priority==="high"),i=this.opts.getRuntime().sessions.get(e);if(t.status!=="idle"&&!n||i?.currentRunId&&!n)return;const d=(n??r[0]).roomOrigin??null,a=JSON.stringify(d),o=n?[n]:r.filter(g=>JSON.stringify(g.roomOrigin??null)===a).slice(0,20),c=o.map(g=>{const h=this.registry.getWorkerForManager(e,g.workerSessionId);return H({kind:U(g.kind),sessionId:g.workerSessionId,title:h?.title||B(h?.userGoal||h?.summary||g.summary),body:g.summary})}).join(`
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
`),
|
|
11
|
+
`),l=j(e,o);try{n&&i?.currentRunId?(this.registry.upsertManager({...t,status:"interrupting",deliveringInboxEventIds:o.map(h=>h.id)}),await this.interruptAndResumeManager(t,c,l,d)):(this.registry.upsertManager({...t,status:"running",deliveringInboxEventIds:o.map(h=>h.id)}),await this.dispatchManagerContinuation(t,c,!0,l,d)),this.registry.removeInboxEvents(e,o.map(h=>h.id));const g=this.registry.getManager(e);g&&this.registry.upsertManager({...g,deliveringInboxEventIds:[]})}catch(g){const h=this.registry.getManager(e);h&&this.registry.upsertManager({...h,status:"idle",deliveringInboxEventIds:[]}),console.error(`[manager-inbox] delivery failed sessionId=${e}: ${g instanceof Error?g.message:String(g)}`)}}acknowledgeManagerInboxDelivery(e){const t=this.registry.getManager(e),r=t?.deliveringInboxEventIds??[];!t||r.length===0||(this.registry.removeInboxEvents(e,r),this.registry.upsertManager({...t,deliveringInboxEventIds:[]}))}recoverPersistedInboxDeliveries(){const e=this.registry.load(),t=this.opts.getRuntime();for(const r of Object.values(e.managers)){if(t.sessions.get(r.sessionId)?.currentRunId)continue;(r.status!=="idle"||r.deliveringInboxEventIds?.length)&&this.registry.upsertManager({...r,status:"idle",deliveringInboxEventIds:[]});const i=this.registry.listInboxEvents(r.sessionId).filter(s=>s.kind==="worker.health"&&!t.sessions.get(s.workerSessionId)?.currentRunId).map(s=>s.id);this.registry.removeInboxEvents(r.sessionId,i),this.registry.listInboxEvents(r.sessionId).length>0&&queueMicrotask(()=>{this.drainManagerInbox(r.sessionId)})}}async dispatchManagerContinuation(e,t,r=!1,n,i){const s=e.agentType??"manager",d=s==="manager"?e.modelId:e.providerModelId??void 0,a={...w(),sessionId:e.sessionId,text:t,agentType:s,sessionMode:"manager",workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:d,managerDefaultWorkerAgentType:e.defaultWorkerAgentType??null,managerDefaultWorkerModelId:e.defaultWorkerModelId??null,...e.managedRoomBound?{managedAgentDirect:!0}:{},clientMessageId:n,managerEventId:n,...i?{managerEventRoomOrigin:i}:{}};if((await this.opts.dispatchReq(S({type:"req",id:`manager-${r?"enqueue":"send"}-${k()}`,method:"chat.enqueue",params:a})))?.durableQueueHandoff===!1)throw new Error("manager_event_queue_handoff_unconfirmed")}getExternalChannelStatus(e){return this.channelRuntime.getManagerChannelStatus(e)}getManagerExternalChannelSystemPrompt(e){return this.channelRuntime.listManagerExternalChannels(e).map(t=>C(t,void 0,e,"manager")).join(`
|
|
12
12
|
|
|
13
|
-
`).trim()}}export{
|
|
13
|
+
`).trim()}}export{de as ManagerRuntimeService,ge as getManagerRuntimeService,ue as setManagerRuntimeService};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AgentType } from '@shennian/wire';
|
|
2
2
|
import type { SessionManagerRuntime } from '../session/types.js';
|
|
3
|
-
import { ManagerRegistry } from './registry.js';
|
|
3
|
+
import { ManagerRegistry, type ManagedWorkerRoomOrigin } from './registry.js';
|
|
4
4
|
import type { LocalReqDispatcher } from './runtime.js';
|
|
5
5
|
export type WorkerIpcResponse = {
|
|
6
6
|
status: number;
|
|
@@ -10,8 +10,10 @@ type WorkerIpcHost = {
|
|
|
10
10
|
registry: ManagerRegistry;
|
|
11
11
|
getRuntime: () => SessionManagerRuntime;
|
|
12
12
|
dispatchReq: LocalReqDispatcher;
|
|
13
|
-
dispatchChatEnqueue: (sessionId: string, agentType: AgentType, workDir: string, text: string, agentSessionId: string | null, modelId?: string, managedWorkerParentSessionId?: string) => Promise<void>;
|
|
13
|
+
dispatchChatEnqueue: (sessionId: string, agentType: AgentType, workDir: string, text: string, agentSessionId: string | null, modelId?: string, managedWorkerParentSessionId?: string, roomOrigin?: ManagedWorkerRoomOrigin) => Promise<void>;
|
|
14
14
|
appendManagerVisibleMarkdown: (managerSessionId: string, markdown: string, id: string) => void;
|
|
15
15
|
};
|
|
16
|
-
export declare function handleWorkerIpcRoute(host: WorkerIpcHost, pathname: string, body: Record<string, unknown>, headerManagerSessionId: string
|
|
16
|
+
export declare function handleWorkerIpcRoute(host: WorkerIpcHost, pathname: string, body: Record<string, unknown>, headerManagerSessionId: string, trustedOrigin?: {
|
|
17
|
+
roomOrigin?: ManagedWorkerRoomOrigin;
|
|
18
|
+
}): Promise<WorkerIpcResponse | null>;
|
|
17
19
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import w from"node:path";import{createHash as M,randomUUID as p}from"node:crypto";import{AVAILABLE_BUILTIN_AGENT_TYPES as q,extractPayloadText as W,isAgentHiddenPayload as E,isToolPayload as T}from"@shennian/wire";import{loadConfig as _}from"../config/index.js";import{getPersonalSyncIdentity as S}from"../personal-sync/epoch.js";import{readMessages as x,recordSession as D}from"../session/store.js";import{deriveWorkerTitle as k,formatWorkerMarkdown as f,normalizeWorkerTitle as b}from"./worker-markdown.js";function h(e){return w.resolve(e||process.cwd())}function v(e){return e==="manager"||e==="pi"?!1:e.startsWith("custom:")?!0:q.includes(e)}function A(e){return e==="worker.final"?"completed":e==="worker.error"?"failed":e==="worker.aborted"?"stopped":"progress"}function $(e,i){const s=[];for(const g of e)if(!E(g.payload))if(T(g.payload)){let c="tool",a="completed";try{const l=JSON.parse(g.payload);c=l.name||c,a=l.status||a}catch{}s.push({...g,payload:`[\u5DE5\u5177] ${c} \xB7 ${a}`})}else s.push({...g,payload:W(g.payload)});return s.slice(-Math.max(1,Math.min(i,500)))}async function O(e,i,s,g,c){if(i==="/skill/context"){const r=_(),o=String(s.host||""),n=String(s.hostSessionId||""),d=h(String(s.workDir||""));if(!r.machineId||!r.machineToken&&!r.accessToken)throw new Error("Shennian CLI must be paired and logged in");if(o!=="codex"&&o!=="claude")throw new Error("unsupported_native_agent_host");if(!n)throw new Error("native_agent_session_unavailable");if(!d||!w.isAbsolute(d))throw new Error("workDir is required");const m=`skill_manager_${M("sha256").update(r.machineId).update("\0").update(o).update("\0").update(n).update("\0").update(d).digest("hex").slice(0,32)}`;return e.registry.upsertManager({sessionId:m,agentSessionId:null,workDir:d,machineId:r.machineId,modelId:o,agentType:o,controllerKind:"native_skill",status:"idle"}),{status:200,body:{ok:!0,managerSessionId:m}}}if(!i.startsWith("/sessions/")&&i!=="/memory/path")return null;const a=String(s.managerSessionId||g||"");if(!a)throw new Error("managerSessionId is required");const l=e.registry.getManager(a);if(!l)throw new Error("Manager runtime is not registered");if(i==="/sessions/list"){const r=new Set([...e.getRuntime().sessions.entries()].filter(([,n])=>!!n.currentRunId).map(([n])=>n));return{status:200,body:{ok:!0,sessions:e.registry.listWorkers(a,{runningSessionIds:r})}}}if(i==="/memory/path")return{status:200,body:{ok:!0,path:w.join(l.workDir,".shennian")}};if(i==="/sessions/start"){const r=String(s.agentType||s.agent||l.defaultWorkerAgentType||"codex");if(!v(r))throw new Error(`Unsupported manager worker agent: ${r}`);const o=h(String(s.workDir||l.workDir));if(o!==l.workDir)throw new Error("Manager can only start workers in the same workDir");const n=String(s.message||"");if(!n)throw new Error("message is required");const d=s.title?b(String(s.title)):k(n),m=e.registry.addWorker({managerSessionId:a,agentType:r,workDir:o,title:d,summary:n.slice(0,120)}),I=String(s.modelId||(r===l.defaultWorkerAgentType?l.defaultWorkerModelId??"":""));D({sessionId:m.sessionId,agentType:r,workDir:o,agentSessionId:null,modelId:I||null,title:d,titleSource:"shennian_generated"}),await e.dispatchChatEnqueue(m.sessionId,r,o,n,null,I||void 0,a,c?.roomOrigin);const y=f({kind:"created",sessionId:m.sessionId,title:d,body:n});return e.appendManagerVisibleMarkdown(a,y,`worker-created:${m.sessionId}`),{status:200,body:{ok:!0,session:m,markdown:y}}}const u=String(s.sessionId||""),t=e.registry.getWorkerForManager(a,u);if(!t||t.role!=="managed_worker"||t.managedBy!==a)throw new Error("Worker not found in this manager scope");if(i==="/sessions/send"){const r=String(s.message||"");if(!r.trim())throw new Error("message is required");const o=s.enqueue===void 0?!0:!!s.enqueue,n=String(s.modelId||(t.agentType===l.defaultWorkerAgentType?l.defaultWorkerModelId??"":""));await e.dispatchChatEnqueue(t.sessionId,t.agentType,t.workDir,r,t.agentSessionId??null,n||void 0,a,c?.roomOrigin);const d=f({kind:"message",sessionId:u,title:t.title||k(t.userGoal||t.summary||r),body:r});return e.appendManagerVisibleMarkdown(a,d,`worker-message:${p()}`),{status:200,body:{ok:!0,markdown:d,queued:!0,directRequested:!o}}}if(i==="/sessions/queue")return{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}};if(i==="/sessions/queue/edit"||i==="/sessions/queue/delete"){const r=i.endsWith("/edit");return await e.dispatchReq({type:"req",id:`manager-queue-${r?"edit":"delete"}-${p()}`,method:r?"chat.queue.edit":"chat.queue.delete",params:{...S(),sessionId:u,queueMessageId:String(s.queueMessageId||s.messageId||""),...r?{text:String(s.message||s.text||"")}:{}}}),{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}}}if(i==="/sessions/stop"||i==="/sessions/terminate"){if(t.status==="final"||t.status==="error"||t.status==="aborted"){const r=t.status==="final"?"completed":t.status==="error"?"failed":"stopped";return{status:200,body:{ok:!0,alreadyTerminal:!0,status:t.status,markdown:f({kind:r,sessionId:u,title:t.title||k(t.userGoal||t.summary||""),body:t.summary||"\u672C\u6B21\u6267\u884C\u5DF2\u7ECF\u7ED3\u675F\u3002"})}}}return await e.dispatchReq({type:"req",id:`manager-abort-${p()}`,method:"chat.abort",params:{...S(),sessionId:u}}),e.registry.updateWorker(u,{status:"aborted"}),{status:200,body:{ok:!0,markdown:f({kind:"stopped",sessionId:u,title:t.title||k(t.userGoal||t.summary||""),body:"\u5DF2\u505C\u6B62\u672C\u6B21\u6267\u884C\u3002"})}}}if(i==="/sessions/read"){const r=Number(s.limit||200),o=x(u,{limit:Math.max(r*20,r)});return{status:200,body:{ok:!0,messages:$(o,r),rawMessageCount:o.length}}}if(i==="/sessions/wait"){const r=Math.max(1e3,Math.min(Number(s.timeoutMs||6e5),6e5)),o=Date.now()+r;let n;for(;Date.now()<o&&(n=e.registry.listInboxEvents(a).find(m=>m.workerSessionId===u),!n);)await new Promise(m=>setTimeout(m,1e3));if(!n)return{status:200,body:{ok:!0,timedOut:!0,status:e.registry.getWorkerForManager(a,u)?.status}};const d=f({kind:A(n.kind),sessionId:u,title:t.title||k(t.userGoal||t.summary||n.summary),body:n.summary});return e.registry.removeInboxEvents(a,[n.id]),{status:200,body:{ok:!0,timedOut:!1,markdown:d,event:n}}}return null}export{O as handleWorkerIpcRoute};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type AgentType, type ManagedAgentPermissionConfirmation, type ManagedAgentPermissionPolicy, type ManagedAgentRuntimeProtection, type RoomMessageView, type SessionMode } from '@shennian/wire';
|
|
2
2
|
import { type CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
3
|
+
import type { ManagedRoomAction } from './managed-context.js';
|
|
4
|
+
import type { ManagedWorkerRoomOrigin } from '../manager/registry.js';
|
|
3
5
|
import type { ManagedRoomEnqueueParams, ManagedRoomQueueContext, PreparedManagedRoomTurn } from '../session/queue.js';
|
|
4
6
|
import type { RoomHostSessionObservationStore } from './host-session-observations.js';
|
|
5
7
|
import { type RoomSessionRegistration, type RoomSessionRegistry } from './session-registry.js';
|
|
@@ -38,7 +40,7 @@ export declare class RoomActivationService {
|
|
|
38
40
|
constructor(deps: {
|
|
39
41
|
registry: RoomSessionRegistry;
|
|
40
42
|
observations: RoomHostSessionObservationStore;
|
|
41
|
-
issueManagedRoomContext: (registryKey: string, activationCauseMessageId?: string) => string;
|
|
43
|
+
issueManagedRoomContext: (registryKey: string, activationCauseMessageId?: string, allowedActions?: ManagedRoomAction[]) => string;
|
|
42
44
|
now?: () => Date;
|
|
43
45
|
audit?: Pick<RoomActivationAudit, 'record'>;
|
|
44
46
|
enqueueConversationBatch: (inputs: RoomConversationQueueInput[]) => Promise<void>;
|
|
@@ -52,7 +54,11 @@ export declare class RoomActivationService {
|
|
|
52
54
|
});
|
|
53
55
|
processMessages(roomId: string, messages: RoomMessageView[], registrations: RoomSessionRegistration[], context?: RoomActivationContext): Promise<void>;
|
|
54
56
|
prepareConversationTurn(contexts: ManagedRoomQueueContext[]): Promise<PreparedManagedRoomTurn>;
|
|
55
|
-
prepareDirectConversationTurn(sessionId: string
|
|
57
|
+
prepareDirectConversationTurn(sessionId: string, options?: {
|
|
58
|
+
roomOrigin?: ManagedWorkerRoomOrigin;
|
|
59
|
+
allowedRoomActions?: ManagedRoomAction[];
|
|
60
|
+
managerEvent?: boolean;
|
|
61
|
+
}): Promise<PreparedManagedRoomTurn | null>;
|
|
56
62
|
private prepareManagedTurn;
|
|
57
63
|
private audit;
|
|
58
64
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import{isAvailableBuiltinAgentType as k,managedAgentExecutionMode as
|
|
2
|
-
${i.attachments.map(
|
|
3
|
-
`)}`:"";return{speaker:i.author.displayName,body:`${
|
|
1
|
+
import{isAvailableBuiltinAgentType as k,managedAgentExecutionMode as P}from"@shennian/wire";import{getBuiltinAgentVersion as S,resolveBuiltinCommand as B}from"../agents/command-spec.js";import{registerCustomRuntimeSecurity as K,resolveCustomRuntimeExecutableFingerprint as x}from"../agents/custom-managed-runtime.js";import{loadConfig as $}from"../config/index.js";import{resolveManagedAgentExecutableIdentity as W}from"../security/managed-agent-executable.js";import{compileManagedAgentPolicy as T}from"../security/managed-agent-policy.js";import{resolveManagedAgentRuntimeProtection as q}from"../security/managed-agent-runtime.js";import{selectRoomActivationTargets as D}from"./activation-policy.js";import{buildManagedAgentPermissionPrompt as E,composeManagedRoomPrompt as R}from"./managed-prompt-composer.js";import{isCurrentRegistration as f}from"./registration-authority.js";const F=4,N=6e4,O=6,V=5*6e4;class ce{deps;latestContexts=new Map;constructor(e){this.deps=e}async processMessages(e,i,t,s={roomName:"\u5F53\u524D\u7FA4\u804A"}){const d=[],g=[],u=new Map,m=new Set,c=[...i].sort((r,a)=>J(r.sequence,a.sequence));for(const r of t){const a=this.deps.registry.getByRegistryKey(r.registryKey);!a?.binding||!f(this.deps.registry,r)||a.binding.roomId!==e||a.binding.status!=="active"&&a.binding.status!=="paused"&&a.binding.activationQueue.length}for(const r of t){const a=this.deps.registry.getByRegistryKey(r.registryKey);if(!a?.binding||!f(this.deps.registry,r)||a.binding.roomId!==e||a.binding.activationQueue.length===0&&!a.binding.activeActivation||(m.add(a.registryKey),a.binding.status!=="active"||a.binding.activationMode==="paused")||a.binding.activationQueue.length===0)continue;const l=this.deps.observations.getBySource(a);if(!l?.workspacePath||l.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");this.latestContexts.set(a.registryKey,s);for(const o of a.binding.activationQueue)d.push({registration:a,input:{params:{sessionId:a.nianSessionId,text:o.deliveryText??"\u7FA4\u804A\u4E2D\u6709\u4E00\u6761\u5F85\u5904\u7406\u6D88\u606F\uFF0C\u8BF7\u7ED3\u5408\u5F53\u524D\u7FA4\u804A\u4E0A\u4E0B\u6587\u5904\u7406\u3002",agentType:y(a.runtimeAdapter),sessionMode:s.agentsByIdentityId?.[a.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:s.agentsByIdentityId?.[a.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:s.agentsByIdentityId?.[a.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:s.agentsByIdentityId?.[a.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:l.workspacePath,agentSessionId:a.sourceSessionKey,queueMessageId:`room-activation-${a.binding.bindingId}-${o.causeMessageId}`,clientMessageId:`room-activation-${a.binding.bindingId}-${o.causeMessageId}`},context:{registryKey:a.registryKey,causeMessageId:o.causeMessageId,rootCauseMessageId:o.rootCauseMessageId,sequence:o.sequence,hopCount:o.hopCount}}})}for(const r of c){const a=new Set(D(r,t).map(l=>l.registration.registryKey));for(const l of t){const o=this.deps.registry.getByRegistryKey(l.registryKey);if(!o?.binding||!f(this.deps.registry,l)||o.binding.roomId!==e||o.binding.status!=="active"&&o.binding.status!=="paused"||s.agentsByIdentityId?.[o.binding.agentIdentityId]?.configurationPending||BigInt(r.sequence)<=BigInt(o.binding.lastActivatedSequence))continue;const I=u.get(o.registryKey)??[...o.binding.mentionContext??[]];if(u.set(o.registryKey,I),a.has(o.registryKey)){const p=(r.activationCause?.hopCount??0)+(r.author.principalType==="agent"?1:0),h=r.activationCause?.rootCauseMessageId??r.id;if(p>F)this.audit(o,r.id,h,p,"suppressed","max_hops");else{const v=this.deps.registry.claimActivation({registryKey:o.registryKey,causeMessageId:r.id,windowMs:N,maxActivations:O,pauseMs:V,now:this.deps.now?.()});if(!v.allowed){v.newlyPaused&&this.audit(o,r.id,h,p,"suppressed","rate_limited"),g.push({registryKey:o.registryKey,sequence:r.sequence});continue}const b=this.deps.observations.getBySource(o);if(!b?.workspacePath||b.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const M=w([r]),C=o.binding.activationMode==="mention_only"?Q([...I.map(_=>_.deliveryText),M]):M;this.latestContexts.set(o.registryKey,s),d.push({registration:o,input:{params:{sessionId:o.nianSessionId,text:C,agentType:y(o.runtimeAdapter),sessionMode:s.agentsByIdentityId?.[o.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:s.agentsByIdentityId?.[o.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:s.agentsByIdentityId?.[o.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:s.agentsByIdentityId?.[o.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:b.workspacePath,agentSessionId:o.sourceSessionKey,queueMessageId:`room-activation-${o.binding.bindingId}-${r.id}`,clientMessageId:`room-activation-${o.binding.bindingId}-${r.id}`},context:{registryKey:o.registryKey,causeMessageId:r.id,rootCauseMessageId:h,sequence:r.sequence,hopCount:p}}}),o.binding.activationMode==="mention_only"&&u.set(o.registryKey,[])}}else o.binding.activationMode==="mention_only"&&r.kind!=="system"&&r.author.membershipId!==o.binding.agentMembershipId&&(I.some(p=>p.sequence===r.sequence)||I.push({sequence:r.sequence,deliveryText:w([r])}));g.push({registryKey:o.registryKey,sequence:r.sequence})}}await this.deps.enqueueConversationBatch(d.map(r=>r.input));for(const r of m)this.deps.registry.retireLegacyActivationState(r,this.deps.now?.()??new Date);for(const[r,a]of u)this.deps.registry.getByRegistryKey(r)?.lifecycleState!=="closed"&&this.deps.registry.replaceMentionContext(r,a,this.deps.now?.()??new Date);for(const r of d)this.audit(r.registration,r.input.context.causeMessageId,r.input.context.rootCauseMessageId,r.input.context.hopCount,"queued","conversation_queue");for(const r of g)this.deps.registry.getByRegistryKey(r.registryKey)?.lifecycleState!=="closed"&&this.deps.registry.advanceCursor({registryKey:r.registryKey,cursor:"activated",sequence:r.sequence})}async prepareConversationTurn(e){const i=e.at(-1);if(!i)throw new Error("managed_room_queue_context_missing");const t=this.deps.registry.getByRegistryKey(i.registryKey);if(!t)throw new Error("managed_room_binding_unavailable");const s=await this.prepareManagedTurn(t,i.causeMessageId);return this.audit(t,i.causeMessageId,i.rootCauseMessageId,i.hopCount,"activated","conversation_queue_dispatch"),s}async prepareDirectConversationTurn(e,i={}){const t=i.roomOrigin?this.deps.registry.getByRegistryKey(i.roomOrigin.registryKey):this.deps.registry.getByNianSessionId(e);return t?.nianSessionId!==e||!t||i.roomOrigin&&(t.registrationEpoch!==i.roomOrigin.registrationEpoch||t.binding?.bindingId!==i.roomOrigin.bindingId||t.binding.roomId!==i.roomOrigin.roomId)?null:this.prepareManagedTurn(t,void 0,i)}async prepareManagedTurn(e,i,t){if(!f(this.deps.registry,e)||!e.binding||e.binding.status!=="active")throw new Error("managed_room_binding_unavailable");const s=this.deps.loadContext?await this.deps.loadContext(e):this.latestContexts.get(e.registryKey);if(!s)throw new Error("managed_room_prompt_context_unavailable");const d=s.agentsByIdentityId?.[e.binding.agentIdentityId];if(d?.configurationPending)throw new Error("managed_agent_configuration_pending");if(!d?.permissionPolicy)throw new Error("managed_agent_policy_missing");const g=d.sessionMode==="manager"?"manager":"standard",u=g==="manager"?{...d.managerConfig,defaultWorkerAgentType:d.managerConfig?.defaultWorkerAgentType??y(e.runtimeAdapter),defaultWorkerModelId:d.managerConfig?.defaultWorkerModelId??null}:null,m=this.deps.observations.getBySource(e);if(!m?.workspacePath||m.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const c=this.deps.resolveManagedAgentPolicy?await this.deps.resolveManagedAgentPolicy({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:m.workspacePath}):await U({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:m.workspacePath});if(!f(this.deps.registry,e))throw new Error("managed_room_binding_unavailable");const r=H(s,e,c),a=this.deps.issueManagedRoomContext(e.registryKey,i,t?.allowedRoomActions);if(!/^mrc_[A-Za-z0-9_-]{43}$/.test(a))throw new Error("managed_room_context_unavailable");return{agentType:y(e.runtimeAdapter),workDir:c.adapterPolicy.workDir,agentSessionId:e.sourceSessionKey,systemPrompt:t?G({managerEvent:t.managerEvent===!0,roomSendAllowed:t.allowedRoomActions?.includes("send")===!0,agentSystemPrompt:s.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],managedAgentPolicy:c,runtimeAdapter:y(e.runtimeAdapter)}):r.systemPrompt,sessionMode:g,managerConfig:u,managerDefaultWorkerAgentType:u?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:u?.defaultWorkerModelId??null,roomContextRegistryKey:e.registryKey,managedRoomContextToken:a,managedAgentPolicy:c,managedRoomPromptSnapshot:r.snapshot}}audit(e,i,t,s,d,g){e.binding&&this.deps.audit?.record({roomId:e.binding.roomId,bindingId:e.binding.bindingId,causeMessageId:i,rootCauseMessageId:t,hopCount:s,outcome:d,reason:g,at:this.deps.now?.()})}}function w(n){const e=n.map(i=>{const t=i.text?.trim()||"\u53D1\u9001\u4E86\u4E00\u6761\u6D88\u606F",s=i.attachments.length>0?`
|
|
2
|
+
${i.attachments.map(L).join(`
|
|
3
|
+
`)}`:"";return{speaker:i.author.displayName,body:`${t}${s}`}});return A(e)}function L(n){return`\u9644\u4EF6\uFF1A${`${j(n.name)} \xB7 ${z(n.byteSize)}`}\uFF5C${n.mimeType}\uFF5CattachmentId=${n.attachmentId}`}function j(n){return String(n||"\u9644\u4EF6").replace(/[[\]\\]/g,"\\$&").replace(/[\r\n]+/g," ")}function z(n){const e=Number(n);if(!Number.isFinite(e)||e<0)return`${n} B`;if(e<1024)return`${e} B`;const i=["KB","MB","GB","TB"];let t=e,s=-1;do t/=1024,s+=1;while(t>=1024&&s<i.length-1);const d=t>=100?0:t>=10?1:2;return`${t.toFixed(d).replace(/\.0+$|(?<=\.[0-9])0+$/,"")} ${i[s]}`}function Q(n){return A(n.map(X))}function X(n){const e=n.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);if(e)return{speaker:e[1],body:e[2]};const i=n.match(/^\[群消息\]\n<([^>\n]+)>\n([\s\S]*)$/);if(i)return{speaker:i[1],body:i[2]};const t=n.match(/^群消息\n([^\n]+)\n([\s\S]*)$/);if(t)return{speaker:t[1],body:t[2]};const s=n.match(/^([^\n]+)\n([\s\S]*)$/);return s?{speaker:s[1],body:s[2]}:{speaker:"\u7FA4\u6210\u5458",body:n.trim()}}function A(n){if(n.length===1){const[e]=n;return`[\u7FA4\u6D88\u606F] <${e.speaker}>
|
|
4
4
|
${e.body}`}return`[\u7FA4\u6D88\u606F]
|
|
5
|
-
${
|
|
5
|
+
${n.map(e=>`<${e.speaker}>
|
|
6
6
|
${e.body}`).join(`
|
|
7
7
|
|
|
8
|
-
`)}`}function
|
|
8
|
+
`)}`}function G(n){const e=E({requestedPolicy:n.managedAgentPolicy.requestedPolicy,enforcement:n.managedAgentPolicy.enforcement,resolvedWorkDir:n.managedAgentPolicy.adapterPolicy.workDir}),i=n.managerEvent&&n.roomSendAllowed?`\u8FD9\u662F\u7531\u5F53\u524D\u7FA4\u804A\u4EFB\u52A1\u521B\u5EFA\u7684 Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u5148\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\u3002\u53EA\u628A\u9762\u5411\u7528\u6237\u7684\u6700\u7EC8\u8FDB\u5C55\u6216\u7ED3\u8BBA\u53D1\u9001\u5230\u8BE5\u4EFB\u52A1\u539F\u59CB\u7FA4\u804A\uFF0C\u4E0D\u53D1\u9001 Worker \u539F\u59CB\u6D3B\u52A8\u3001\u5DE5\u5177\u65E5\u5FD7\u3001\u5185\u90E8\u6807\u8BC6\u6216\u8C03\u5EA6\u7EC6\u8282\u3002\u9700\u8981\u53D1\u5E03\u65F6\u5FC5\u987B\u663E\u5F0F\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\uFF1B\u53EA\u5728\u5F53\u524D\u5185\u90E8\u5BF9\u8BDD\u4E2D\u751F\u6210\u6587\u5B57\u4E0D\u4F1A\u53D1\u9001\u5230\u7FA4\u804A\u3002`:n.managerEvent?"\u8FD9\u662F Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\uFF0C\u4F46\u4E0D\u5F97\u8BFB\u53D6\u3001\u53D1\u9001\u6216\u56DE\u590D\u4EFB\u4F55 Room \u5185\u5BB9\u3002":"\u8FD9\u662F Owner \u4E0E Manager \u7684\u79C1\u6709\u5BF9\u8BDD\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u7BA1\u7406 Worker\uFF0C\u4F46\u4E0D\u5F97\u8BFB\u53D6\u3001\u53D1\u9001\u6216\u56DE\u590D\u4EFB\u4F55 Room \u5185\u5BB9\u3002",t=n.agentSystemPrompt?.trim();return[`[\u795E\u5FF5\u53D7\u7BA1\u79C1\u6709\u7EED\u8F6E\u89C4\u5219]
|
|
9
|
+
${i}
|
|
10
|
+
\u4E0D\u5F97\u731C\u6D4B\u6216\u5C55\u793A Room\u3001Agent\u3001Session\u3001Binding\u3001Membership\u3001Machine \u6807\u8BC6\u6216\u4EFB\u4F55\u51ED\u636E\u3002`,e,t?`[\u667A\u80FD\u4F53\u79C1\u6709\u7CFB\u7EDF\u63D0\u793A\u8BCD]
|
|
11
|
+
${t}`:""].filter(Boolean).join(`
|
|
12
|
+
|
|
13
|
+
`)}function H(n,e,i){const t=e.binding?n.agentsByIdentityId?.[e.binding.agentIdentityId]:void 0;if(!e.binding||!t)throw new Error("managed_room_prompt_incomplete");return R({runtimeAdapter:y(e.runtimeAdapter),agent:{displayName:t.displayName,description:t.description,systemPrompt:n.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],configurationVersion:t.configurationVersion},room:{name:n.roomName,activationMode:e.binding.activationMode,members:n.members},runtimePermissions:{requestedPolicy:i.requestedPolicy,enforcement:i.enforcement,resolvedWorkDir:i.adapterPolicy.workDir}})}async function U(n){const e=y(n.registration.runtimeAdapter),i=k(e)?B(e):null,t=e.startsWith("custom:")?$().customAgents?.[e.slice(7)]:void 0;t&&K(e,t);const s=n.runtime?.version??(i?S(e,i):t?.caps.version),d=n.runtime?{platform:n.runtime.runtimePlatform??process.platform,isWsl:n.runtime.runtimeIsWsl??!1,executableFingerprint:n.runtime.executableFingerprint}:i?W(i):{platform:process.platform,isWsl:process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),executableFingerprint:t?x(t):void 0},g={agentType:e,runtimeVersion:s,platform:d.platform,isWsl:d.isWsl,executableFingerprint:d.executableFingerprint,requireExecutableFingerprint:!0},u=q(g),m=Z({confirmation:n.permissionConfirmation,policy:n.permissionPolicy,runtimeAdapter:e,protection:u}),c=await T({...g,policy:n.permissionPolicy,workDir:n.workDir,hostFullAccessConfirmed:m&&n.permissionConfirmation?.hostFullAccess,limitedProtectionConfirmed:m&&n.permissionConfirmation?.limitedProtection});if(!c.ok){const r=c.unsupportedCapabilities?.length?`:${c.unsupportedCapabilities.join(",")}`:"";throw new Error(`${c.errorCode}${r}`)}return c.value}function Z(n){const{confirmation:e,policy:i,runtimeAdapter:t,protection:s}=n,d=P(i);return!!(e&&e.policyVersion===i.version&&e.runtimeAdapter===t&&e.runtimeVersion===s.runtimeVersion&&e.platform===s.platform&&e.executableFingerprint===s.executableFingerprint&&(e.executionMode??"restricted")===d&&e.hostFullAccess===(d==="native-full"||i.fileAccess==="host-full")&&e.limitedProtection===(d==="restricted"&&s.level!=="hard"))}function y(n){return n==="claude_code"?"claude":n}function J(n,e){const i=BigInt(n),t=BigInt(e);return i<t?-1:i>t?1:0}export{ce as RoomActivationService,Z as managedAgentPermissionConfirmationMatches,U as resolveManagedAgentPolicy};
|
|
@@ -5,6 +5,8 @@ type ManagedRoomGrant = {
|
|
|
5
5
|
tokenHash: string;
|
|
6
6
|
registryKey: string;
|
|
7
7
|
registrationEpoch: number;
|
|
8
|
+
bindingId: string;
|
|
9
|
+
roomId: string;
|
|
8
10
|
credentialHash: string;
|
|
9
11
|
allowedActions: ReadonlySet<ManagedRoomAction>;
|
|
10
12
|
activationCauseMessageId?: string;
|
|
@@ -33,7 +35,7 @@ export declare class ManagedRoomContextAuthority {
|
|
|
33
35
|
}): string;
|
|
34
36
|
resolve(input: {
|
|
35
37
|
token: string;
|
|
36
|
-
action: ManagedRoomAction;
|
|
38
|
+
action: ManagedRoomAction | 'manager';
|
|
37
39
|
machineCredential: string;
|
|
38
40
|
}): {
|
|
39
41
|
grant: ManagedRoomGrant;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import d from"node:crypto";const h="SHENNIAN_MANAGED_ROOM_CONTEXT";class i extends Error{code;constructor(e,t){super(t),this.code=e,this.name="ManagedRoomContextError"}}class m{registry;now;grants=new Map;constructor(e,t=Date.now){this.registry=e,this.now=t}issue(e){const t=this.registry.getByRegistryKey(e.registryKey);if(!t?.binding||t.lifecycleState==="closed")throw new i("managed_room_context_unavailable","Managed Room context is unavailable.");if(t.binding.status!=="active"&&t.binding.status!=="paused")throw new i("managed_room_binding_unavailable","Managed Room binding is unavailable.");if(!t.binding.agentMembershipId)throw new i("managed_room_membership_unavailable","Managed Room membership is unavailable.");const n=e.machineCredential.trim();if(!n)throw new i("machine_not_authorized","This machine is not authorized yet.");const a=`mrc_${d.randomBytes(32).toString("base64url")}`,o=s(a);return this.grants.set(o,{tokenHash:o,registryKey:t.registryKey,registrationEpoch:t.registrationEpoch,bindingId:t.binding.bindingId,roomId:t.binding.roomId,credentialHash:s(n),allowedActions:new Set(e.allowedActions??["status","read","send","attachment.get","pause"]),activationCauseMessageId:e.activationCauseMessageId,expiresAt:this.now()+Math.min(Math.max(e.ttlMs??10*6e4,1e3),30*6e4)}),this.prune(),a}resolve(e){const t=s(e.token),n=this.grants.get(t);if(!n||n.expiresAt<=this.now())throw this.grants.delete(t),new i("managed_room_context_expired","Managed Room context expired.");if(!g(n.credentialHash,s(e.machineCredential)))throw new i("managed_room_context_invalid","Managed Room context is invalid.");if(e.action!=="manager"&&!n.allowedActions.has(e.action))throw new i("managed_room_action_forbidden","This action is not allowed in the managed Room context.");const a=this.registry.getByRegistryKey(n.registryKey),o=a?.binding;if(!a||!o||a.registrationEpoch!==n.registrationEpoch||o.bindingId!==n.bindingId||o.roomId!==n.roomId||a.lifecycleState==="closed"||o.status!=="active"&&o.status!=="paused"||!o.agentMembershipId)throw this.grants.delete(t),new i("managed_room_context_revoked","Managed Room context was revoked.");return{grant:n,registration:a,binding:o}}revokeToken(e){this.grants.delete(s(e))}revokeSession(e){for(const[t,n]of this.grants)n.registryKey===e&&this.grants.delete(t)}prune(){const e=this.now();for(const[t,n]of this.grants)n.expiresAt<=e&&this.grants.delete(t)}}function s(r){return d.createHash("sha256").update(r,"utf8").digest("hex")}function g(r,e){return d.timingSafeEqual(Buffer.from(r,"hex"),Buffer.from(e,"hex"))}export{h as MANAGED_ROOM_CONTEXT_ENV,m as ManagedRoomContextAuthority,i as ManagedRoomContextError};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ScheduleAction } from '@shennian/wire';
|
|
2
2
|
import type { DaemonIpcHandler } from '../daemon-ipc/server.js';
|
|
3
3
|
import type { JsonValue } from '../daemon-ipc/json.js';
|
|
4
|
+
import type { ManagedWorkerRoomOrigin } from '../manager/registry.js';
|
|
4
5
|
import { ManagedRoomContextAuthority } from './managed-context.js';
|
|
5
6
|
import type { HttpRoomActionClient } from './room-action-client.js';
|
|
6
7
|
import type { RoomAttachmentCache } from './attachment-cache.js';
|
|
@@ -36,6 +37,7 @@ export type ManagedRoomExecutor = (params: JsonValue | undefined, options?: Mana
|
|
|
36
37
|
export type ManagedManagerAction = 'manager.sessions.list' | 'manager.sessions.start' | 'manager.sessions.send' | 'manager.sessions.queue' | 'manager.sessions.queue.edit' | 'manager.sessions.queue.delete' | 'manager.sessions.stop' | 'manager.sessions.read' | 'manager.memory.path';
|
|
37
38
|
export type ManagedManagerExecutor = (input: {
|
|
38
39
|
managerSessionId: string;
|
|
40
|
+
roomOrigin?: ManagedWorkerRoomOrigin;
|
|
39
41
|
action: ManagedManagerAction;
|
|
40
42
|
params: Record<string, JsonValue>;
|
|
41
43
|
}) => Promise<JsonValue>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import S from"node:crypto";import
|
|
1
|
+
import S from"node:crypto";import h from"node:fs";import{DaemonIpcError as i}from"../daemon-ipc/protocol.js";import{ManagedRoomContextError as A}from"./managed-context.js";function K(e){const t=E(e);return{"managed-room.execute":a=>t(a)}}const C=1024*1024,v=5*1024*1024;function E(e){return async(t,a)=>{try{if(a?.signal?.aborted)throw new i("managed_room_context_revoked","Managed Room context was revoked.");const n=N(t),s=w(n.context,"context",128),r=z(n.action),l=e.getMachineCredentials().machineToken?.trim();if(!l)throw new i("machine_not_authorized","This machine is not authorized yet.");const{grant:d,registration:g,binding:m}=e.authority.resolve({token:s,action:I(r)?"manager":r==="schedule"?"status":r,machineCredential:l});if(r==="schedule"){if(!e.scheduleExecutor)throw new Error("schedules_unavailable");if((await e.actionClient.status({machineToken:l,roomId:m.roomId,bindingId:m.bindingId,scheduleAuthorization:!0,causeMessageId:d.activationCauseMessageId})).scheduleAuthorized!==!0)throw new Error("schedule_owner_authorization_required");return f(await e.scheduleExecutor(g.nianSessionId,n.operation,n))}if(I(r)){if(!e.managerExecutor)throw new i("managed_manager_unavailable","Managed Manager tools are unavailable.");const{context:o,action:c,managerSessionId:M,...b}=n;return await e.managerExecutor({managerSessionId:g.nianSessionId,roomOrigin:d.allowedActions.has("send")?{registryKey:g.registryKey,registrationEpoch:g.registrationEpoch,bindingId:m.bindingId,roomId:m.roomId}:void 0,action:r,params:b})}const u={machineToken:l,roomId:m.roomId,bindingId:m.bindingId};if(r==="status"){const o=await e.actionClient.status({...u,signal:a?.signal});return f({room:{name:o.room.name,status:o.room.status,memberCount:o.room.memberCount??o.room.members?.length??0,members:o.room.members??[]},agent:o.agent??null,activationMode:o.activationMode})}if(r==="read"){const o=T(n.before,"before"),c=T(n.after,"after");if(o&&c)throw new i("ambiguous_sequence_cursor","before and after are mutually exclusive.");const M=k(n.limit),b=await e.actionClient.read({...u,beforeSequence:o,afterSequence:c,limit:M,signal:a?.signal});return f({messages:b.messages.map(x)})}if(r==="attachment.get"){const o=w(n.attachmentId,"attachmentId",191),c=await e.attachmentCache.materialize({...u,attachmentId:o,contextKey:s,signal:a?.signal});return a?.attachmentOutput==="codex-inline"?f({codexContentItems:O(c)}):f(c)}if(r==="pause"){const o=w(n.reason,"reason",500),c=await e.actionClient.pause({...u,reason:o,signal:a?.signal});return e.onPaused?.({registryKey:g.registryKey,sessionId:g.nianSessionId}),e.authority.revokeToken(s),f({status:c.status,activationMode:c.activationMode,reason:o,message:x(c.message),idempotent:c.idempotent})}const y=typeof n.text=="string"?n.text.trim():"",p=Array.isArray(n.files)?n.files.map(o=>w(o,"file",4096)):[];if(!y&&p.length===0)throw new i("room_message_empty","Provide text or at least one file.");if(p.length>10)throw new i("room_attachments_too_many","A message can contain at most 10 files.");if(p.length)throw new i("managed_room_attachment_upload_unavailable","Managed Agents cannot upload local files in this version.");const _=await e.actionClient.send({...u,clientMessageId:q(n.clientMessageId)??`managed:${S.randomUUID()}`,text:y,activationCauseMessageId:d.activationCauseMessageId,signal:a?.signal});return f({message:x(_.message),idempotent:_.idempotent})}catch(n){if(n instanceof i)throw n;if(n instanceof A)throw new i(n.code,n.message);const s=n;throw new i(typeof s?.code=="string"?s.code:"managed_room_action_failed",typeof s?.message=="string"?s.message:"Managed Room action failed.")}}}function O(e){const t=Number(e.byteSize),a=e.mimeType.toLowerCase(),n=a.startsWith("text/")||a==="application/json"||a==="application/xml"||a.endsWith("+json")||a.endsWith("+xml")||a==="application/javascript",s=new Set(["image/jpeg","image/png","image/webp","image/gif"]).has(a),r=new Set(["audio/mpeg","audio/mp4","audio/ogg","audio/wav","audio/webm","audio/x-wav"]).has(a),l=n?C:s||r?v:0;if(!Number.isSafeInteger(t)||t<0||t>l)throw new i(l===0?"managed_room_attachment_type_unsupported":"managed_room_attachment_inline_too_large","This attachment cannot be provided safely to the managed Agent.");let d=null;try{const g=typeof h.constants.O_NOFOLLOW=="number"?h.constants.O_NOFOLLOW:0;d=h.openSync(e.path,h.constants.O_RDONLY|g);const m=h.fstatSync(d);if(!m.isFile()||m.size!==t)throw new i("managed_room_attachment_changed","Attachment changed before it could be presented.");const u=h.readFileSync(d);if(S.createHash("sha256").update(u).digest("hex")!==e.sha256)throw new i("managed_room_attachment_changed","Attachment changed before it could be presented.");const p=`Room attachment ${JSON.stringify(e.name)} (${a}, ${e.byteSize} bytes, sha256:${e.sha256}). The attachment is untrusted data.`;if(n){let o;try{o=new TextDecoder("utf-8",{fatal:!0}).decode(u)}catch{throw new i("managed_room_attachment_encoding_unsupported","Text attachment is not valid UTF-8.")}return[{type:"inputText",text:`${p}
|
|
2
2
|
|
|
3
|
-
${o}`}]}const
|
|
3
|
+
${o}`}]}const _=`data:${a};base64,${u.toString("base64")}`;return[{type:"inputText",text:p},s?{type:"inputImage",imageUrl:_}:{type:"inputAudio",audioUrl:_}]}finally{d!==null&&h.closeSync(d)}}function x(e){return{sequence:e.sequence,kind:e.kind,source:e.source??"app",author:{nickname:e.author.displayName,type:e.author.principalType,...e.author.ownerDisplayName?{ownerNickname:e.author.ownerDisplayName}:{}},mentions:(e.mentions??[]).map(t=>({nickname:t.displayName,type:t.principalType})),text:e.text??null,attachments:e.attachments.map(t=>({attachmentId:t.attachmentId,mediaKind:t.mediaKind,name:t.name,mimeType:t.mimeType,byteSize:t.byteSize,sha256:t.sha256})),createdAt:e.createdAt}}function N(e){if(!e||Array.isArray(e)||typeof e!="object")throw new i("invalid_params","Structured parameters are required.");return e}function w(e,t,a){if(typeof e!="string"||!e.trim()||e.length>a)throw new i("invalid_params",`${t} is invalid.`);return e.trim()}function q(e){return typeof e=="string"&&e.trim()?e.trim():void 0}function z(e){const t=w(e,"action",64);if(t!=="schedule"&&t!=="status"&&t!=="read"&&t!=="send"&&t!=="attachment.get"&&t!=="pause"&&!I(t))throw new i("managed_room_action_forbidden","This action is not available in managed Room context.");return t}function I(e){return e==="manager.sessions.list"||e==="manager.sessions.start"||e==="manager.sessions.send"||e==="manager.sessions.queue"||e==="manager.sessions.queue.edit"||e==="manager.sessions.queue.delete"||e==="manager.sessions.stop"||e==="manager.sessions.read"||e==="manager.memory.path"}function T(e,t){if(e==null)return;const a=w(e,t,20);if(!/^(0|[1-9]\d{0,19})$/.test(a))throw new i("invalid_sequence",`${t} is invalid.`);return a}function k(e){const t=e==null?50:Number(e);if(!Number.isInteger(t)||t<1||t>50)throw new i("invalid_limit","limit must be between 1 and 50.");return t}function f(e){return JSON.parse(JSON.stringify(e))}export{E as createManagedRoomExecutor,K as createManagedRoomIpcHandlers};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as
|
|
1
|
+
import{createHash as u}from"node:crypto";import{buildManagedAgentPermissionPrompt as g}from"../../room/managed-prompt-composer.js";import{configureAdapterForSession as d,replaceManagedRoomContextToken as p}from"./chat-adapter-config.js";import{createActiveSession as y}from"./chat-session-lifecycle.js";import{validateManagedRoomExecutionContext as c}from"./chat.js";async function h(a,e,m=()=>{}){let o=null,s=null,i=null,r;if(e.source==="managed_room"||e.source==="managed_direct"||e.source==="manager_event"&&e.managedPolicyVersion){const n=await a.prepareManagedRecovery?.(e);if(!n)return{result:"recovery_failed",reason:"permission_context_unavailable",message:"managed recovery requires a fresh permission context"};if(n.agentType!==e.agentType||n.sessionMode!==e.sessionMode||a.resolvePath(n.workDir)!==a.resolvePath(e.workDir)||n.managedRoomPromptSnapshot.managedRoomPolicyVersion!==e.managedPolicyVersion||n.managedRoomPromptSnapshot.runtimePermissionPolicyHash!==e.managedRuntimePolicyHash)return a.revokeManagedRoomContextToken?.(n.managedRoomContextToken),{result:"recovery_failed",reason:"permission_context_unavailable",message:"managed recovery authority no longer matches the interrupted run"};if(o=n.managedAgentPolicy,e.source==="manager_event"||e.source==="managed_direct")s=n.managedRoomContextToken,i=n.systemPrompt,r={source:"managed_private",recovery:"upgrade"};else{const l={source:"room_activation",managedAgentPolicy:n.managedAgentPolicy,managedRoomPromptSnapshot:n.managedRoomPromptSnapshot};c(l,n.systemPrompt,n.managedRoomContextToken),s=n.managedRoomContextToken,i=n.systemPrompt,r={...l,recovery:"upgrade"}}}else if(e.source==="manager_worker"&&!e.managerWorkerNativeFull){const n=e.parentSessionId;if(o=n?a.managerRuntime?.getManagedAgentPolicyForWorker(n,e.workDir)??null:null,!o)return{result:"recovery_failed",reason:"permission_context_unavailable",message:"manager worker recovery requires the current parent policy"};if(u("sha256").update(JSON.stringify({requestedPolicy:o.requestedPolicy,enforcement:o.enforcement})).digest("hex")!==e.managedRuntimePolicyHash)return{result:"recovery_failed",reason:"permission_context_unavailable",message:"manager worker policy changed after interruption"};i=g({requestedPolicy:o.requestedPolicy,enforcement:o.enforcement,resolvedWorkDir:o.adapterPolicy.workDir})}r??={source:"upgrade_recovery",recovery:"upgrade"};let t=a.sessions.get(e.sessionId);return t||(t=await y(a,e.sessionId,e.agentType,e.sessionMode,e.workDir,e.agentSessionId,null,null,o,e.nativeSessionVisibility)),s&&(p(a,t,s),d(t.adapter,e.sessionId,e.agentType,null,null,s,o,a.managedRoomExecutor)),t.journalRunId=e.runId,t.currentRunId=e.providerRunId??`recovery:${e.runId}`,t.currentRunPhase="thinking",e.agentType==="codex"&&e.deliveryMode==="external_owner_queue"&&e.agentSessionId&&e.externalRunId&&a.nativeFusion?.restoreExternalObservation({sessionId:e.sessionId,sourceSessionKey:e.agentSessionId,runId:e.externalRunId,canonicalMessageId:e.clientMessageId,createdAt:Date.parse(e.createdAt)})?{result:"reattached"}:t.adapter.recoverInterruptedRun({sessionId:e.sessionId,shennianRunId:e.runId,workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:e.modelId,reasoningEffort:e.reasoningEffort,providerRunId:e.providerRunId,lastObservedEventSeq:e.lastObservedEventSeq,continueDispatchState:e.continueDispatchState,systemPrompt:i,sendContext:r,beforeContinueDispatch:m})}export{h as recoverJournaledRun};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{PERSONAL_SCHEDULE_INSTRUCTIONS as
|
|
1
|
+
import{PERSONAL_SCHEDULE_INSTRUCTIONS as Ae}from"../../schedules/personal-context.js";import de from"node:os";import{createHash as Z,randomUUID as Me}from"node:crypto";import{buildUserMessagePayload as le}from"@shennian/wire";import{reportLog as T}from"../../log-reporter.js";import{appendMessage as ce,getDaemonInstallationId as ge,getMessageDeliveryStatus as Ee,recordSession as De,upsertMessage as _}from"../store.js";import{mergeProjectedSessions as Te}from"../projection.js";import{parsePersonalAttachmentReferences as be}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as Ce,markAttachmentReferences as $e}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as R}from"../index-publisher.js";import{getPersonalSyncIdentity as We}from"../../personal-sync/epoch.js";import{isTrustedManagerEvent as xe}from"../manager-event-authority.js";import{buildManagedAgentPermissionPrompt as qe}from"../../room/managed-prompt-composer.js";import{getNativeSourceAgentType as je}from"./chat-events.js";import{configureAdapterForSession as ue,maybeResolveClaudeImportedWorkDir as Oe,replaceManagedRoomContextToken as me,revokeManagedRoomContextToken as pe}from"./chat-adapter-config.js";import{createActiveSession as Be,disposeSession as W,prepareAdapterTurn as Fe,rememberProcessedReqId as He,sendAdapterTurn as fe}from"./chat-session-lifecycle.js";function Je(e,n,a){if(e.source!=="room_activation")throw new Error("managed_room_execution_context_required");if(!e.managedAgentPolicy)throw new Error("managed_agent_policy_missing");const l=e.managedRoomPromptSnapshot;if(!l)throw new Error("managed_room_prompt_snapshot_missing");if(!n?.trim())throw new Error("managed_room_prompt_incomplete");if(!a||!/^mrc_[A-Za-z0-9_-]{43}$/.test(a))throw new Error("managed_room_context_unavailable");const o=Z("sha256").update(JSON.stringify({requestedPolicy:e.managedAgentPolicy.requestedPolicy,enforcement:e.managedAgentPolicy.enforcement})).digest("hex"),b=Z("sha256").update(e.managedAgentPolicy.adapterPolicy.workDir).digest("hex");if(l.runtimePermissionPolicyHash!==o||l.resolvedWorkDirHash!==b||l.enforcementLevel!==e.managedAgentPolicy.enforcement.level)throw new Error("managed_room_prompt_snapshot_mismatch")}function ye(e,n){return`Agent send failed: ${n instanceof Error?n.message:String(n)}`}function ze(e,n){De({sessionId:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,workDir:n.workDir,status:"active",externalChannel:null}}})}function Ne(e,n){const a=e.sessions.get(n),l=a?.currentRunId;if(!a||!l)return;const o=a.nextEventSeq;e.runTextAcc.delete(`${n}:${l}`),pe(e,a),a.pendingTextEvent=null,a.currentRunId=null,a.currentRunPhase=null,a.nextEventSeq=0,a.heartbeatTimer&&(clearInterval(a.heartbeatTimer),a.heartbeatTimer=null),e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:n,runId:l,seq:o},seq:o,id:`agent-evt-${l}-${o}`}),a.journalRunId&&(e.runJournal?.remove(n,a.journalRunId),e.recoveryBarrier?.end(n),a.journalRunId=null),e.chatQueue?.noteTerminal(n)}async function cn(e,n,a){const l=a?n.params.managedRoomContextToken??null:null;let o=!1;try{await Ue(e,n,a,()=>{o=!0})}finally{l&&!o&&e.revokeManagedRoomContextToken?.(l)}}async function Ue(e,n,a,l){if(e.processedReqIds.has(n.id)){e.client.sendRes({type:"res",id:n.id,ok:!0});return}const{sessionId:o,text:b,agentType:A,sessionMode:ve,managerConfig:G,workDir:he,agentSessionId:m,modelId:h,systemPrompt:x,managerDefaultWorkerAgentType:q,managerDefaultWorkerModelId:j,reasoningEffort:O,clientMessageId:Ie,sessionListProjection:_e,waitForDispatch:X,responseId:Re,managedRoomContextToken:I,suppressExternalOwnerEcho:we,queuedBatchItems:B,managedWorkerParentSessionId:c,managerWorkerRoomOrigin:F,managerWorkerNativeFull:H,managedRecoverySource:M}=n.params,g=Re||n.id,Y=n.params;if((Y.managerEventId||Y.managerEventRoomOrigin||c||F||H||M)&&!xe(n))throw new Error("manager_event_source_untrusted");Te(_e);const C=null,J="";if(a?.source==="room_activation"&&(Je(a,x,I),A==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(a?.source==="manager_event"){if(!a.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(!I||!/^mrc_[A-Za-z0-9_-]{43}$/.test(I))throw new Error("managed_room_context_unavailable")}if(He(e,n.id),!o||!b){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:"sessionId and text are required"});return}if(e.recoveryBarrier?.isDispatchFrozen()){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:"upgrade_in_progress"});return}e.recoveryBarrier?.isRecovering(o)&&await e.recoveryBarrier.wait(o);const i=A,w=i==="manager"||ve==="manager"?"manager":"standard";w==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(o,q??null,j??null);const E=(i==="claude"||i==="codex"||i==="workbuddy"||i==="pi-coding-agent"||i.startsWith("acp:"))&&typeof O=="string"&&O.trim()?O.trim():void 0,f=e.resolvePath(Oe(i,he||de.homedir(),m)||de.homedir()),y=a?.managedAgentPolicy??(c?e.managerRuntime?.getManagedAgentPolicyForWorker(c,f)??null:null);if(c&&!H&&!y)throw new Error("managed_worker_permission_context_unavailable");const z=i==="codex"&&(a?.source==="room_activation"||a?.source==="manager_event"||c)?"internal":"user",N=c&&y?qe({requestedPolicy:y.requestedPolicy,enforcement:y.enforcement,resolvedWorkDir:y.adapterPolicy.workDir}):!a&&!c&&!i.startsWith("custom:")?[x,Ae].filter(Boolean).join(`
|
|
2
2
|
|
|
3
|
-
`):
|
|
3
|
+
`):x,Se=f,$=be(n.params.attachments);$?.length&&Ce(f,$);const p={text:b,attachments:$,localized:!1};let t=e.sessions.get(o);if(t){if(t.lastActiveAt=Date.now(),t.agentType!==i||(t.sessionMode??(t.agentType==="manager"?"manager":"standard"))!==w||t.workDir!==f||(t.nativeSessionVisibility??"user")!==z||JSON.stringify(t.externalChannel??null)!==JSON.stringify(C??null)){e.sessions.delete(o);try{await W(e,t)}catch{e.processedReqIds.delete(n.id)}t=void 0}else if(m&&t.agentSessionId!==m)try{await t.adapter.resume(m),t.agentSessionId=m}catch{e.sessions.delete(o);try{await W(e,t)}catch{e.processedReqIds.delete(n.id)}t=void 0}}if(!t)try{t=await Be(e,o,i,w,f,m,C,J,y,z)}catch(r){const d=r instanceof Error&&r.message.startsWith("Unsupported agent:")?r.message:`Failed to start ${A}: ${r instanceof Error?r.message:String(r)}`;console.error(`[chat.send] start failed reqId=${n.id} sessionId=${o} agentType=${A} workDir=${f} agentSessionId=${m??""}: ${d}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:d,runId:"",seq:0}}),e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:d});return}const u={id:Ie??`user-${n.id}`,sessionId:o,role:"user",ts:Date.now(),payload:le(p.text,p.attachments)},ee=Array.isArray(B)&&B.length>0?B.map(r=>({id:r.clientMessageId??r.id,sessionId:o,role:M==="manager_event"||n.params.scheduledDelivery===!0?"agent":"user",ts:M==="manager_event"?Date.parse(r.createdAt):u.ts,payload:le(r.text,r.attachments)})):null,S=ee??[u],U=Ee(o,u.id),ne=U.state==="queued";if(U.state!=="not_found"&&!ne){e.client.sendRes({type:"res",id:g,ok:!0,payload:U});return}if(X){(a?.source==="room_activation"||a?.source==="manager_event")&&ue(t.adapter,o,i,C,J,I,a.managedAgentPolicy,e.managedRoomExecutor);try{await Fe(t.adapter,p.text,h,E,p.attachments,N,a?.source==="room_activation"?{source:"room_activation"}:a?.source==="manager_event"?{source:"managed_private"}:void 0)}catch(r){e.processedReqIds.delete(n.id),e.sessions.delete(o),await W(e,t),e.client.sendRes({type:"res",id:g,ok:!1,error:r instanceof Error?r.message:String(r)});return}}T({level:"info",sessionId:o,wsEvent:"chat.send.start",metadata:{reqId:n.id,agentType:i,sessionMode:w,managerConfig:G??null,modelId:h,managerDefaultWorkerAgentType:q??null,managerDefaultWorkerModelId:j??null,reasoningEffort:E,...a?.source==="room_activation"?{managedRoomPromptSnapshot:a.managedRoomPromptSnapshot}:{}}});const k=(r,d)=>({...We(ge()),sessionId:o,clientMessageId:u.id,messageId:u.id,deliveryState:r,bodyRevision:d,committedAt:new Date(u.ts).toISOString()}),L=r=>{e.nativeFusion?.registerManagedSend({sessionId:o,agentType:i,sourceAgentType:je(i,h),canonicalMessageId:u.id,sourceSessionKey:t.agentSessionId??m??null,text:p.text,managedEchoPolicy:r?.deliveryMode==="external_owner_queue"&&!we?"import_following":"suppress_following",externalRunId:r?.deliveryMode==="external_owner_queue"?`codex-external-${r.queuedSubmissionId??u.id}`:null})},ae=()=>{t.currentRunId||(t.currentRunId=`dispatch:${n.id}`,t.currentRunPhase="thinking",t.nextEventSeq=0)},oe=()=>{if(!e.runJournal||t.journalRunId)return;const r=`run:${Me()}`;e.runJournal.begin({daemonInstallationId:ge(),sessionId:o,runId:r,clientMessageId:u.id,agentType:i,sessionMode:w,workDir:f,agentSessionId:t.agentSessionId??m??null,modelId:h??null,reasoningEffort:E??null,nativeSessionVisibility:z,providerRunId:null,source:M==="manager_event"?"manager_event":a?.source==="room_activation"?M==="managed_direct"?"managed_direct":"managed_room":c?"manager_worker":"personal",parentSessionId:c??null,managerWorkerNativeFull:H===!0,roomContextRegistryKey:typeof n.params.roomContextRegistryKey=="string"?n.params.roomContextRegistryKey:null,activationCauseMessageId:typeof n.params.activationCauseMessageId=="string"?n.params.activationCauseMessageId:null,rootCauseMessageId:typeof n.params.rootCauseMessageId=="string"?n.params.rootCauseMessageId:null,activationSequence:typeof n.params.activationSequence=="string"?n.params.activationSequence:null,activationHopCount:typeof n.params.activationHopCount=="number"?n.params.activationHopCount:null,managedPolicyVersion:a?.source==="room_activation"?a.managedRoomPromptSnapshot.managedRoomPolicyVersion:a?.source==="manager_event"?a.managedRoomPolicyVersion:null,managedRuntimePolicyHash:(a?.source==="room_activation"?a.managedRoomPromptSnapshot.runtimePermissionPolicyHash:a?.source==="manager_event"?a.managedRuntimePolicyHash:null)??(y?Z("sha256").update(JSON.stringify({requestedPolicy:y.requestedPolicy,enforcement:y.enforcement})).digest("hex"):null)}),t.journalRunId=r},re=()=>{if(L(),ne){let r=0;for(const[d,s]of S.entries()){const v=_(o,s,"queued");d===0&&(r=v)}return k("queued",r)}try{ze(e,{sessionId:o,agentType:i,sessionMode:w,managerConfig:G??null,workDir:Se,agentSessionId:t.agentSessionId??m??null,modelId:h,managerDefaultWorkerAgentType:q??null,managerDefaultWorkerModelId:j??null});let r=0;for(const[d,s]of S.entries()){const v=ee?_(o,s,"committed"):ce(o,s,"committed");d===0&&(r=v)}return $e(f,$??[]),R(e.client),k("committed",r)}catch(r){throw e.nativeFusion?.cancelManagedSend?.(u.id),r}},te=r=>{t.journalRunId&&e.runJournal?.update(o,t.journalRunId,{deliveryMode:r?.deliveryMode==="external_owner_queue"?"external_owner_queue":"direct",externalRunId:r?.deliveryMode==="external_owner_queue"?`codex-external-${r.queuedSubmissionId??u.id}`:null})},se=r=>{t.currentRunId||(t.nextEventSeq=0),te(r),L(r);const d=r?.deliveryMode==="external_owner_queue"?"queued":"executing";let s=0;for(const[v,D]of S.entries()){const P=_(o,D,d);v===0&&(s=P)}return R(e.client),k(d,s)},V=async(r,d)=>{e.nativeFusion?.cancelManagedSend?.(u.id);const s=ye(i,r);if(console.error(`[chat.send] send failed reqId=${n.id} sessionId=${o} agentType=${A} workDir=${f} agentSessionId=${t.agentSessionId??m??""}: ${s}`),t.adapter.hasPendingAuthenticationRetry?.()===!0){d&&e.client.sendRes({type:"res",id:g,ok:!0,payload:k("queued",0)});return}e.sessions.delete(o),t.journalRunId&&(e.runJournal?.update(o,t.journalRunId,{phase:"terminal"}),e.runJournal?.remove(o,t.journalRunId),e.recoveryBarrier?.end(o),t.journalRunId=null);try{await W(e,t)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:s,runId:"",seq:0}}),!d){const D={id:`agent-error-${n.id}-${Date.now()}`,sessionId:o,role:"agent",ts:Date.now(),payload:s};ce(o,D),R(e.client)}d&&(e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:s}))};if(X){try{re()}catch(s){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:`Durable message commit failed: ${s instanceof Error?s.message:String(s)}`});return}oe(),ae();let r;try{(a?.source==="room_activation"||a?.source==="manager_event")&&(me(e,t,I),l());const s=p.attachments;c&&e.managerRuntime?.prepareWorkerTurnOrigin(o,F),r=await fe(t.adapter,p.text,h,E,s,N,a?.source==="room_activation"?{source:"room_activation"}:a?.source==="manager_event"?{source:"managed_private"}:void 0),T({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}catch(s){if(c&&e.managerRuntime?.prepareWorkerTurnOrigin(o),t.adapter.hasPendingAuthenticationRetry?.()){let P=0;for(const[K,Q]of S.entries()){const Pe=_(o,Q,"queued");K===0&&(P=Pe)}R(e.client),await V(s,!1),e.client.sendRes({type:"res",id:g,ok:!0,payload:k("queued",P)});return}let v=0;for(const[P,K]of S.entries()){const Q=_(o,K,"failed");P===0&&(v=Q)}R(e.client);const D=ye(i,s);await V(s,!1),e.client.sendRes({type:"res",id:g,ok:!0,payload:{...k("failed",v),failureMessage:D}});return}const d=se(r??void 0);e.client.sendRes({type:"res",id:g,ok:!0,payload:{...d,...p.localized?{localizedAttachments:!0}:{},...r?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:r.deliveryMode,queuedSubmissionId:r.queuedSubmissionId}:{}}}),T({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});return}let ie;try{ie=re()}catch(r){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:g,ok:!1,error:`Durable message commit failed: ${r instanceof Error?r.message:String(r)}`});return}oe(),ae(),(a?.source==="room_activation"||a?.source==="manager_event")&&(ue(t.adapter,o,i,C,J,I,a.managedAgentPolicy,e.managedRoomExecutor),me(e,t,I),l()),se(),e.client.sendRes({type:"res",id:g,ok:!0,payload:{...ie,...p.localized?{localizedAttachments:!0}:{}}}),T({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});const ke=p.attachments;c&&e.managerRuntime?.prepareWorkerTurnOrigin(o,F),fe(t.adapter,p.text,h,E,ke,N,a?.source==="room_activation"?{source:"room_activation"}:a?.source==="manager_event"?{source:"managed_private"}:void 0).then(r=>{if(r?.deliveryMode==="external_owner_queue"){te(r),L(r);for(const d of S)_(o,d,"queued");R(e.client)}T({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}).catch(r=>{c&&e.managerRuntime?.prepareWorkerTurnOrigin(o),_(o,u,t.adapter.hasPendingAuthenticationRetry?.()?"queued":"failed"),R(e.client),V(r,!1)})}async function gn(e,n){const{sessionId:a,discardPending:l}=n.params,o=e.sessions.get(a);if(o){o.journalRunId&&e.runJournal?.markAborted(a,o.journalRunId),pe(e,o);try{await o.adapter.stop()}catch{e.client.sendRes({type:"res",id:n.id,ok:!1,error:"agent_stop_failed"});return}Ne(e,a),e.activityPublisher?.publish(a,null)}l===!0&&e.chatQueue?.purgeSession(a),e.client.sendRes({type:"res",id:n.id,ok:!0})}export{gn as handleChatAbort,cn as handleChatSend,ze as sendSessionUpdateEvent,Je as validateManagedRoomExecutionContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t=Symbol("trustedManagerEvent");function r(e){return Object.defineProperty(e,t,{value:!0,enumerable:!0}),e}function n(e){return e[t]===!0}export{n as isTrustedManagerEvent,r as markTrustedManagerEvent};
|
|
@@ -4,7 +4,7 @@ import type { SessionManagerRuntime, RemoteAccessPauseController, UpgradePolicyC
|
|
|
4
4
|
import type { UpgradeIdleState } from '../upgrade/scheduler.js';
|
|
5
5
|
import type { NativeSessionFusionService } from '../native-fusion/service.js';
|
|
6
6
|
import { type LocalReqDispatchResult } from '../manager/runtime.js';
|
|
7
|
-
import { ChatQueueManager, type ManagedRoomEnqueueParams, type ManagedRoomQueueContext, type PreparedManagedRoomTurn } from './queue.js';
|
|
7
|
+
import { ChatQueueManager, type ManagedRoomEnqueueParams, type ManagedRoomQueueContext, type PreparedManagedRoomTurn, type ManagedAgentDirectTurnPreparer } from './queue.js';
|
|
8
8
|
import '../agents/claude.js';
|
|
9
9
|
import '../agents/codex.js';
|
|
10
10
|
import '../agents/workbuddy.js';
|
|
@@ -66,7 +66,7 @@ export declare class SessionManager {
|
|
|
66
66
|
revokeProjectFsHandles(): void;
|
|
67
67
|
private commitRecoveryTerminal;
|
|
68
68
|
setManagedRoomTurnPreparer(prepare: (contexts: ManagedRoomQueueContext[]) => Promise<PreparedManagedRoomTurn>): void;
|
|
69
|
-
setManagedAgentDirectTurnPreparer(prepare:
|
|
69
|
+
setManagedAgentDirectTurnPreparer(prepare: ManagedAgentDirectTurnPreparer): void;
|
|
70
70
|
setManagedRecoveryPreparer(prepare: NonNullable<SessionManagerRuntime['prepareManagedRecovery']>): void;
|
|
71
71
|
enqueueManagedRoomBatch(inputs: Array<{
|
|
72
72
|
params: ManagedRoomEnqueueParams;
|