shennian 0.4.5 → 0.4.6
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import de from"node:os";import{createHash as K}from"node:crypto";import{createAgent as Ee}from"../../agents/adapter.js";import{buildApprovalPendingPayload as
|
|
2
|
-
`),a=t>0?Math.min(t,80):Math.min(e.length,80);return e.slice(0,a)}function ue(e,t,a){return`${e}:${K("sha256").update(`${t}\0${a??""}`).digest("hex")}`}function He(e,t,a={}){if(e.state==="tool-call"||e.state==="tool-result"){const s={runId:e.runId,sourceSeq:e.seq};return{state:e.state,runId:e.runId,seq:e.seq,sessionId:t,detailRef:s,status:e.state==="tool-call"?"running":"completed",detailAvailable:!0,...e.durationMs!==void 0?{durationMs:e.durationMs}:{},...e.name?{name:e.name}:{},...e.source?{source:e.source}:{},...e.agentSessionId?{agentSessionId:e.agentSessionId}:{},...a}}return{...e,sessionId:t,...a}}const ze=3e4;function Be(e){return e.state==="heartbeat"?e.runPhase??null:e.state==="tool-call"||e.state==="tool-result"?"tool_running":e.state==="approval-pending"?"waiting_approval":e.state==="delta"?e.thinking?"thinking":"streaming_text":e.state==="init"||e.state==="start"?"thinking":null}function ge(e,t){return`Agent send failed: ${t instanceof Error?t.message:String(t)}`}function fe(e,t){return e!=="manager"?e:t==="claude"?"claude":"codex"}function Le(e,t){H({sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode,managerConfig:t.managerConfig,workDir:t.workDir,agentSessionId:t.agentSessionId??null,modelId:t.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode,managerConfig:t.managerConfig,agentSessionId:t.agentSessionId??null,modelId:t.modelId??null,workDir:t.workDir,status:"active",externalChannel:null}}})}function me(e){return be(e)}function pe(e,t,a){return{}}function X(e,t,a,s,r,l,c,R){const S=a==="codex";e.configure?.({sessionId:t,externalChannel:s??null,env:{...me(a),...pe(t,s,r),...l&&!S?{SHENNIAN_MANAGED_ROOM_CONTEXT:l,[Oe]:We()}:{}},...c?{managedAgentPolicy:c}:{},...S?{managedRoomContextToken:l??null,managedRoomExecutor:R??null}:{}})}function he(e,t,a){const s=t.managedRoomContextToken;s&&s!==a&&e.revokeManagedRoomContextToken?.(s),t.managedRoomContextToken=a}function v(e,t){const a=t?.managedRoomContextToken;!t||!a||(t.managedRoomContextToken=null,e.revokeManagedRoomContextToken?.(a))}function Ue(e,t,a){if(e!=="claude"||!a)return t;const s=t.trim();return!!s&&s.startsWith("-")&&!s.includes("/")?Te(a)??t:t}function Je(e,t,a,s){let r=null;function l(n,o={}){e.client.sendAgentEvent({type:"event",event:"agent",payload:He(n,t,o),seq:n.seq,id:`agent-evt-${n.runId}-${n.seq}`})}function c(n){n?.heartbeatTimer&&(clearInterval(n.heartbeatTimer),n.heartbeatTimer=null)}function R(n){if(!n.currentRunId||!n.currentRunPhase)return;const o=n.heartbeatSeq++;e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:t,runId:n.currentRunId,seq:o,runPhase:n.currentRunPhase},seq:o,id:`agent-heartbeat-${n.currentRunId}-${o}-${Date.now()}`})}function S(n){!n||n.heartbeatTimer||(n.heartbeatTimer=setInterval(()=>{R(n)},ze),n.heartbeatTimer.unref?.())}function h(n){const o=n?.pendingTextEvent;!n||!o||!o.text||(b(t,{id:`agent-${o.runId}-${o.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:o.text}),M(e.client),l({state:"delta",runId:o.runId,seq:o.seq,text:o.text,thinking:o.thinking||void 0}),n.pendingTextEvent=null)}s.on("agentEvent",n=>{const o=e.sessions.get(t),q=Be(n),T=n.state==="final"||n.state==="error"||n.state==="aborted";if(o&&(o.nextEventSeq=n.seq+1,T||(o.currentRunId=n.runId),!T&&q&&(o.currentRunPhase=q,S(o)),n.agentSessionId&&(o.agentSessionId=n.agentSessionId)),e.managerRuntime?.noteAgentEvent(t,n),n.state==="delta"&&n.thinking)return;n.state!=="delta"&&D({level:"info",sessionId:t,wsEvent:`agent.${n.state}`,wsDirection:"out",metadata:{runId:n.runId,seq:n.seq,agentType:a}});let k=!1;if(n.state==="tool-call"||n.state==="tool-result"){const m=`agent-${n.runId}-${n.seq}`;ve({sessionId:t,toolCallId:m,detailRevision:n.seq,ts:Date.now(),name:n.name??"tool",...n.args!==void 0?{args:n.args}:{},...n.result!==void 0?{result:n.result}:{},status:n.state==="tool-call"?"running":"completed",...n.durationMs!==void 0?{durationMs:n.durationMs}:{},detailRef:{runId:n.runId,sourceSeq:n.seq}}),b(t,{id:m,sessionId:t,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:n.state==="tool-call"?"tool_use":"tool_result",name:n.name,toolCallId:m,status:n.state==="tool-call"?"running":"completed",...n.durationMs!==void 0?{durationMs:n.durationMs}:{},detailRef:{runId:n.runId,sourceSeq:n.seq},detailRevision:n.seq,detailAvailable:!0,resultOmitted:n.state==="tool-result"})}),k=!0}else n.state==="approval-pending"?(b(t,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:xe(n.approval)}),k=!0,o&&H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:o.agentSessionId,attentionId:ue("approval",n.runId,n.seq)})):(n.state==="error"||n.state==="aborted")&&n.message&&(b(t,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:n.message}),k=!0);k&&M(e.client);const A=`${t}:${n.runId}`;if(n.state==="delta"&&!n.thinking&&n.text&&e.runTextAcc.set(A,(e.runTextAcc.get(A)??"")+n.text),n.agentSessionId&&n.agentSessionId!==r&&(r=n.agentSessionId,e.nativeFusion?.noteManagedSourceSession(t,fe(a,n.source),n.agentSessionId),o&&H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:n.agentSessionId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:t,agentType:a,agentSessionId:n.agentSessionId}}})),n.state==="delta"){const m=n.text??"";if(!m)return;o?.pendingTextEvent&&o.pendingTextEvent.runId!==n.runId&&h(o),o&&!o.pendingTextEvent&&(o.pendingTextEvent={runId:n.runId,seq:n.seq,text:"",thinking:!1}),o?.pendingTextEvent&&(o.pendingTextEvent.text+=m,o.pendingTextEvent.seq=n.seq);return}let C={};if(n.state==="final"){h(o);const m=e.runTextAcc.get(A)??"";m&&(C={messageSummary:Fe(m)}),e.runTextAcc.delete(A)}else n.state==="error"||n.state==="aborted"?(h(o),e.runTextAcc.delete(A)):(n.state==="tool-call"||n.state==="tool-result"||n.state==="approval-pending")&&h(o);T&&o?.currentRunId===n.runId&&(v(e,o),o.currentRunId=null,o.currentRunPhase=null,o.nextEventSeq=0,c(o),e.chatQueue?.noteTerminal(t),H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:o.agentSessionId,status:n.state==="final"?"completed":"failed",attentionId:ue("terminal",n.runId),lastActivityAt:new Date().toISOString()}),M(e.client)),l(n,C)}),s.on("error",n=>{console.error(`[chat.send] adapter error sessionId=${t} agentType=${a}: ${n.message}`),v(e,e.sessions.get(t)),e.sessions.delete(t),e.chatQueue?.noteTerminal(t),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:t,message:n.message,runId:"",seq:0}})})}function Qe(e,t){if(e.processedReqIds.add(t),e.processedReqIds.size>1e3){const a=e.processedReqIds.values().next().value;e.processedReqIds.delete(a)}}async function B(e,t){v(e,t),t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})}function ye(e,t,a,s,r,l,c){return c?e.send(t,a,s,r,l,c):l?.trim()?e.send(t,a,s,r,l):r?.length?e.send(t,a,s,r):s?e.send(t,a,s):e.send(t,a)}function Ve(e,t,a,s,r,l,c){return e.prepareSend?e.prepareSend(t,a,s,r,l,c):Promise.resolve()}async function je(e,t,a,s,r,l,c,R,S){e.evictIdleSessions();const h=Ee(a);if(!h)throw new Error(`Unsupported agent: ${a}`);const n=s==="manager"&&a!=="manager"?new Me(h,a):h;X(n,t,a,c,R,null,S,e.managedRoomExecutor),await n.start(t,r,l);const o={adapter:n,workDir:r,agentType:a,sessionMode:s,agentSessionId:l??null,lastActiveAt:Date.now(),currentRunId:null,currentRunPhase:null,nextEventSeq:0,heartbeatSeq:0,heartbeatTimer:null,pendingTextEvent:null,externalChannel:c??null,externalReplyTarget:R??null,externalChannelEnv:{...me(a),...pe(t,c,R)},managedRoomContextToken:null};return e.sessions.set(t,o),Je(e,t,a,n),o}function Ge(e,t){const a=e.sessions.get(t),s=a?.currentRunId;if(!a||!s)return;const r=a.nextEventSeq;e.runTextAcc.delete(`${t}:${s}`),v(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:t,runId:s,seq:r},seq:r,id:`agent-evt-${s}-${r}`}),e.chatQueue?.noteTerminal(t)}async function pt(e,t,a){const s=a?t.params.managedRoomContextToken??null:null;let r=!1;try{await Ke(e,t,a,()=>{r=!0})}finally{s&&!r&&e.revokeManagedRoomContextToken?.(s)}}async function Ke(e,t,a,s){if(e.processedReqIds.has(t.id)){e.client.sendRes({type:"res",id:t.id,ok:!0});return}const{sessionId:r,text:l,agentType:c,sessionMode:R,managerConfig:S,workDir:h,agentSessionId:n,modelId:o,systemPrompt:q,managerDefaultWorkerAgentType:T,managerDefaultWorkerModelId:k,reasoningEffort:A,clientMessageId:C,sessionListProjection:m,waitForDispatch:Y,responseId:Ie,managedRoomContextToken:P,suppressExternalOwnerEcho:Re,queuedBatchItems:L,managedWorkerParentSessionId:W}=t.params,y=Ie||t.id;De(m);const O=null,U="";if(a?.source==="room_activation"&&(Ne(a,q,P),c==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(Qe(e,t.id),!r||!l){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:"sessionId and text are required"});return}const g=c,$=g==="manager"||R==="manager"?"manager":"standard";$==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(r,T??null,k??null);const N=(g==="claude"||g==="codex"||g==="workbuddy"||g==="pi-coding-agent")&&typeof A=="string"&&A.trim()?A.trim():void 0,w=e.resolvePath(Ue(g,h||de.homedir(),n)||de.homedir()),_=a?.managedAgentPolicy??(W?e.managerRuntime?.getManagedAgentPolicyForWorker(W,w)??null:null);if(W&&!_)throw new Error("managed_worker_permission_context_unavailable");const J=W&&_?Ce({requestedPolicy:_.requestedPolicy,enforcement:_.enforcement,resolvedWorkDir:_.adapterPolicy.workDir}):q,Se=w,F=qe(t.params.attachments);F?.length&&Pe(w,F);const p={text:l,attachments:F,localized:!1};let i=e.sessions.get(r);if(i){if(i.lastActiveAt=Date.now(),i.agentType!==g||(i.sessionMode??(i.agentType==="manager"?"manager":"standard"))!==$||i.workDir!==w||JSON.stringify(i.externalChannel??null)!==JSON.stringify(O??null)){e.sessions.delete(r);try{await B(e,i)}catch{e.processedReqIds.delete(t.id)}i=void 0}else if(n&&i.agentSessionId!==n)try{await i.adapter.resume(n),i.agentSessionId=n}catch{e.sessions.delete(r);try{await B(e,i)}catch{e.processedReqIds.delete(t.id)}i=void 0}}if(!i)try{i=await je(e,r,g,$,w,n,O,U,_)}catch(d){const f=d instanceof Error&&d.message.startsWith("Unsupported agent:")?d.message:`Failed to start ${c}: ${d instanceof Error?d.message:String(d)}`;console.error(`[chat.send] start failed reqId=${t.id} sessionId=${r} agentType=${c} workDir=${w} agentSessionId=${n??""}: ${f}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:f,runId:"",seq:0}}),e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:f});return}const I={id:C??`user-${t.id}`,sessionId:r,role:"user",ts:Date.now(),payload:ie(p.text,p.attachments)},Z=Array.isArray(L)&&L.length>0?L.map(d=>({id:d.clientMessageId??d.id,sessionId:r,role:"user",ts:Date.parse(d.createdAt),payload:ie(d.text,d.attachments)})):null,Q=Z??[I],E=_e(r,I.id),ee=E.state==="queued";if(E.state!=="not_found"&&!ee){e.client.sendRes({type:"res",id:y,ok:!0,payload:E});return}if(Y){a?.source==="room_activation"&&X(i.adapter,r,g,O,U,P,a.managedAgentPolicy,e.managedRoomExecutor);try{await Ve(i.adapter,p.text,o,N,p.attachments,J,a?{source:a.source}:void 0)}catch(d){e.processedReqIds.delete(t.id),e.sessions.delete(r),await B(e,i),e.client.sendRes({type:"res",id:y,ok:!1,error:d instanceof Error?d.message:String(d)});return}}D({level:"info",sessionId:r,wsEvent:"chat.send.start",metadata:{reqId:t.id,agentType:g,sessionMode:$,managerConfig:S??null,modelId:o,managerDefaultWorkerAgentType:T??null,managerDefaultWorkerModelId:k??null,reasoningEffort:N,...a?.source==="room_activation"?{managedRoomPromptSnapshot:a.managedRoomPromptSnapshot}:{}}});const V=(d,f)=>({...ce(le()),sessionId:r,clientMessageId:I.id,messageId:I.id,deliveryState:d,bodyRevision:f,committedAt:new Date(I.ts).toISOString()}),te=d=>{e.nativeFusion?.registerManagedSend({sessionId:r,agentType:g,sourceAgentType:fe(g,o),canonicalMessageId:I.id,sourceSessionKey:i.agentSessionId??n??null,text:p.text,managedEchoPolicy:d?.deliveryMode==="external_owner_queue"&&!Re?"import_following":"suppress_following",externalRunId:d?.deliveryMode==="external_owner_queue"?`codex-external-${d.queuedSubmissionId??I.id}`:null})},ne=()=>{i.currentRunId||(i.currentRunId=`dispatch:${t.id}`,i.currentRunPhase="thinking",i.nextEventSeq=0)},ae=()=>{if(te(),ee)return{...ce(le()),sessionId:r,clientMessageId:E.clientMessageId,messageId:E.messageId,deliveryState:E.deliveryState,bodyRevision:E.bodyRevision,committedAt:E.committedAt};try{Le(e,{sessionId:r,agentType:g,sessionMode:$,managerConfig:S??null,workDir:Se,agentSessionId:i.agentSessionId??n??null,modelId:o,managerDefaultWorkerAgentType:T??null,managerDefaultWorkerModelId:k??null});let d=0;for(const[f,u]of Q.entries()){const x=Z?z(r,u,"committed"):b(r,u,"committed");f===0&&(d=x)}return $e(w,F??[]),M(e.client),V("committed",d)}catch(d){throw e.nativeFusion?.cancelManagedSend?.(I.id),d}},re=d=>{i.currentRunId||(i.nextEventSeq=0),te(d);const f=d?.deliveryMode==="external_owner_queue"?"queued":"executing";let u=0;for(const[x,j]of Q.entries()){const G=z(r,j,f);x===0&&(u=G)}return M(e.client),V(f,u)},oe=async(d,f)=>{e.nativeFusion?.cancelManagedSend?.(I.id);const u=ge(g,d);console.error(`[chat.send] send failed reqId=${t.id} sessionId=${r} agentType=${c} workDir=${w} agentSessionId=${i.agentSessionId??n??""}: ${u}`),e.sessions.delete(r);try{await B(e,i)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:u,runId:"",seq:0}}),!f){const x={id:`agent-error-${t.id}-${Date.now()}`,sessionId:r,role:"agent",ts:Date.now(),payload:u};b(r,x),M(e.client)}f&&(e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:u}))};if(Y){try{ae()}catch(u){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:`Durable message commit failed: ${u instanceof Error?u.message:String(u)}`});return}ne();let d;try{a?.source==="room_activation"&&(he(e,i,P),s());const u=p.attachments;d=await ye(i.adapter,p.text,o,N,u,J,a?{source:a.source}:void 0),D({level:"info",sessionId:r,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}catch(u){let x=0;for(const[G,ke]of Q.entries()){const we=z(r,ke,"failed");G===0&&(x=we)}M(e.client);const j=ge(g,u);await oe(u,!1),e.client.sendRes({type:"res",id:y,ok:!0,payload:{...V("failed",x),failureMessage:j}});return}const f=re(d??void 0);e.client.sendRes({type:"res",id:y,ok:!0,payload:{...f,...p.localized?{localizedAttachments:!0}:{},...d?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:d.deliveryMode,queuedSubmissionId:d.queuedSubmissionId}:{}}}),D({level:"info",sessionId:r,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});return}let se;try{se=ae()}catch(d){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:`Durable message commit failed: ${d instanceof Error?d.message:String(d)}`});return}ne(),a?.source==="room_activation"&&(X(i.adapter,r,g,O,U,P,a.managedAgentPolicy,e.managedRoomExecutor),he(e,i,P),s()),re(),e.client.sendRes({type:"res",id:y,ok:!0,payload:{...se,...p.localized?{localizedAttachments:!0}:{}}}),D({level:"info",sessionId:r,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});const Ae=p.attachments;ye(i.adapter,p.text,o,N,Ae,J,a?{source:a.source}:void 0).then(()=>{D({level:"info",sessionId:r,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}).catch(d=>{z(r,I,"failed"),M(e.client),oe(d,!1)})}async function ht(e,t){const{sessionId:a}=t.params,s=e.sessions.get(a);if(s){v(e,s);try{await s.adapter.stop()}catch{e.client.sendRes({type:"res",id:t.id,ok:!1,error:"agent_stop_failed"});return}Ge(e,a),e.activityPublisher?.publish(a,null)}e.client.sendRes({type:"res",id:t.id,ok:!0})}export{ht as handleChatAbort,pt as handleChatSend,Le as sendSessionUpdateEvent};
|
|
1
|
+
import de from"node:os";import{createHash as K}from"node:crypto";import{createAgent as Ee}from"../../agents/adapter.js";import{buildApprovalPendingPayload as Me,buildUserMessagePayload as ie}from"@shennian/wire";import{ManagerModeAdapter as xe}from"../../agents/manager.js";import{reportLog as D}from"../../log-reporter.js";import{lookupClaudeTranscriptCwd as Te}from"../../native-fusion/parsers.js";import{appendMessage as b,getDaemonInstallationId as le,getMessageDeliveryStatus as _e,recordSession as H,upsertMessage as z}from"../store.js";import{mergeProjectedSessions as De}from"../projection.js";import{buildManagedAgentEnv as be}from"../../agents/config-status.js";import{parsePersonalAttachmentReferences as qe}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as Pe,markAttachmentReferences as $e}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as x}from"../index-publisher.js";import{writeToolDetail as ve}from"../tool-detail-store.js";import{getPersonalSyncIdentity as ce}from"../../personal-sync/epoch.js";import{buildManagedAgentPermissionPrompt as Ce}from"../../room/managed-prompt-composer.js";import{getManagedRoomIpcRoot as We,MANAGED_ROOM_IPC_ROOT_ENV as Oe}from"../../daemon-ipc/paths.js";function Ne(e,t,a){if(!e.managedAgentPolicy)throw new Error("managed_agent_policy_missing");const s=e.managedRoomPromptSnapshot;if(!s)throw new Error("managed_room_prompt_snapshot_missing");if(!t?.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 r=K("sha256").update(JSON.stringify({requestedPolicy:e.managedAgentPolicy.requestedPolicy,enforcement:e.managedAgentPolicy.enforcement})).digest("hex"),l=K("sha256").update(e.managedAgentPolicy.adapterPolicy.workDir).digest("hex");if(s.runtimePermissionPolicyHash!==r||s.resolvedWorkDirHash!==l||s.enforcementLevel!==e.managedAgentPolicy.enforcement.level)throw new Error("managed_room_prompt_snapshot_mismatch")}function Fe(e){const t=e.indexOf(`
|
|
2
|
+
`),a=t>0?Math.min(t,80):Math.min(e.length,80);return e.slice(0,a)}function ue(e,t,a){return`${e}:${K("sha256").update(`${t}\0${a??""}`).digest("hex")}`}function He(e,t,a={}){if(e.state==="tool-call"||e.state==="tool-result"){const s={runId:e.runId,sourceSeq:e.seq};return{state:e.state,runId:e.runId,seq:e.seq,sessionId:t,detailRef:s,status:e.state==="tool-call"?"running":"completed",detailAvailable:!0,...e.durationMs!==void 0?{durationMs:e.durationMs}:{},...e.name?{name:e.name}:{},...e.source?{source:e.source}:{},...e.agentSessionId?{agentSessionId:e.agentSessionId}:{},...a}}return{...e,sessionId:t,...a}}const ze=3e4;function Be(e){return e.state==="heartbeat"?e.runPhase??null:e.state==="tool-call"||e.state==="tool-result"?"tool_running":e.state==="approval-pending"?"waiting_approval":e.state==="delta"?e.thinking?"thinking":"streaming_text":e.state==="init"||e.state==="start"?"thinking":null}function ge(e,t){return`Agent send failed: ${t instanceof Error?t.message:String(t)}`}function fe(e,t){return e!=="manager"?e:t==="claude"?"claude":"codex"}function Le(e,t){H({sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode,managerConfig:t.managerConfig,workDir:t.workDir,agentSessionId:t.agentSessionId??null,modelId:t.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode,managerConfig:t.managerConfig,agentSessionId:t.agentSessionId??null,modelId:t.modelId??null,workDir:t.workDir,status:"active",externalChannel:null}}})}function me(e){return be(e)}function pe(e,t,a){return{}}function X(e,t,a,s,r,l,c,R){const S=a==="codex";e.configure?.({sessionId:t,externalChannel:s??null,env:{...me(a),...pe(t,s,r),...l&&!S?{SHENNIAN_MANAGED_ROOM_CONTEXT:l,[Oe]:We()}:{}},...c?{managedAgentPolicy:c}:{},...S?{managedRoomContextToken:l??null,managedRoomExecutor:l?R??null:null}:{}})}function he(e,t,a){const s=t.managedRoomContextToken;s&&s!==a&&e.revokeManagedRoomContextToken?.(s),t.managedRoomContextToken=a}function v(e,t){const a=t?.managedRoomContextToken;!t||!a||(t.managedRoomContextToken=null,e.revokeManagedRoomContextToken?.(a))}function Ue(e,t,a){if(e!=="claude"||!a)return t;const s=t.trim();return!!s&&s.startsWith("-")&&!s.includes("/")?Te(a)??t:t}function Je(e,t,a,s){let r=null;function l(n,o={}){e.client.sendAgentEvent({type:"event",event:"agent",payload:He(n,t,o),seq:n.seq,id:`agent-evt-${n.runId}-${n.seq}`})}function c(n){n?.heartbeatTimer&&(clearInterval(n.heartbeatTimer),n.heartbeatTimer=null)}function R(n){if(!n.currentRunId||!n.currentRunPhase)return;const o=n.heartbeatSeq++;e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:t,runId:n.currentRunId,seq:o,runPhase:n.currentRunPhase},seq:o,id:`agent-heartbeat-${n.currentRunId}-${o}-${Date.now()}`})}function S(n){!n||n.heartbeatTimer||(n.heartbeatTimer=setInterval(()=>{R(n)},ze),n.heartbeatTimer.unref?.())}function h(n){const o=n?.pendingTextEvent;!n||!o||!o.text||(b(t,{id:`agent-${o.runId}-${o.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:o.text}),x(e.client),l({state:"delta",runId:o.runId,seq:o.seq,text:o.text,thinking:o.thinking||void 0}),n.pendingTextEvent=null)}s.on("agentEvent",n=>{const o=e.sessions.get(t),q=Be(n),T=n.state==="final"||n.state==="error"||n.state==="aborted";if(o&&(o.nextEventSeq=n.seq+1,T||(o.currentRunId=n.runId),!T&&q&&(o.currentRunPhase=q,S(o)),n.agentSessionId&&(o.agentSessionId=n.agentSessionId)),e.managerRuntime?.noteAgentEvent(t,n),n.state==="delta"&&n.thinking)return;n.state!=="delta"&&D({level:"info",sessionId:t,wsEvent:`agent.${n.state}`,wsDirection:"out",metadata:{runId:n.runId,seq:n.seq,agentType:a}});let k=!1;if(n.state==="tool-call"||n.state==="tool-result"){const m=`agent-${n.runId}-${n.seq}`;ve({sessionId:t,toolCallId:m,detailRevision:n.seq,ts:Date.now(),name:n.name??"tool",...n.args!==void 0?{args:n.args}:{},...n.result!==void 0?{result:n.result}:{},status:n.state==="tool-call"?"running":"completed",...n.durationMs!==void 0?{durationMs:n.durationMs}:{},detailRef:{runId:n.runId,sourceSeq:n.seq}}),b(t,{id:m,sessionId:t,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:n.state==="tool-call"?"tool_use":"tool_result",name:n.name,toolCallId:m,status:n.state==="tool-call"?"running":"completed",...n.durationMs!==void 0?{durationMs:n.durationMs}:{},detailRef:{runId:n.runId,sourceSeq:n.seq},detailRevision:n.seq,detailAvailable:!0,resultOmitted:n.state==="tool-result"})}),k=!0}else n.state==="approval-pending"?(b(t,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:Me(n.approval)}),k=!0,o&&H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:o.agentSessionId,attentionId:ue("approval",n.runId,n.seq)})):(n.state==="error"||n.state==="aborted")&&n.message&&(b(t,{id:`agent-${n.runId||"run"}-${n.seq}`,sessionId:t,role:"agent",ts:Date.now(),payload:n.message}),k=!0);k&&x(e.client);const A=`${t}:${n.runId}`;if(n.state==="delta"&&!n.thinking&&n.text&&e.runTextAcc.set(A,(e.runTextAcc.get(A)??"")+n.text),n.agentSessionId&&n.agentSessionId!==r&&(r=n.agentSessionId,e.nativeFusion?.noteManagedSourceSession(t,fe(a,n.source),n.agentSessionId),o&&H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:n.agentSessionId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:t,agentType:a,agentSessionId:n.agentSessionId}}})),n.state==="delta"){const m=n.text??"";if(!m)return;o?.pendingTextEvent&&o.pendingTextEvent.runId!==n.runId&&h(o),o&&!o.pendingTextEvent&&(o.pendingTextEvent={runId:n.runId,seq:n.seq,text:"",thinking:!1}),o?.pendingTextEvent&&(o.pendingTextEvent.text+=m,o.pendingTextEvent.seq=n.seq);return}let C={};if(n.state==="final"){h(o);const m=e.runTextAcc.get(A)??"";m&&(C={messageSummary:Fe(m)}),e.runTextAcc.delete(A)}else n.state==="error"||n.state==="aborted"?(h(o),e.runTextAcc.delete(A)):(n.state==="tool-call"||n.state==="tool-result"||n.state==="approval-pending")&&h(o);T&&o?.currentRunId===n.runId&&(v(e,o),o.currentRunId=null,o.currentRunPhase=null,o.nextEventSeq=0,c(o),e.chatQueue?.noteTerminal(t),H({sessionId:t,agentType:a,workDir:o.workDir,agentSessionId:o.agentSessionId,status:n.state==="final"?"completed":"failed",attentionId:ue("terminal",n.runId),lastActivityAt:new Date().toISOString()}),x(e.client)),l(n,C)}),s.on("error",n=>{console.error(`[chat.send] adapter error sessionId=${t} agentType=${a}: ${n.message}`),v(e,e.sessions.get(t)),e.sessions.delete(t),e.chatQueue?.noteTerminal(t),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:t,message:n.message,runId:"",seq:0}})})}function Qe(e,t){if(e.processedReqIds.add(t),e.processedReqIds.size>1e3){const a=e.processedReqIds.values().next().value;e.processedReqIds.delete(a)}}async function B(e,t){v(e,t),t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})}function ye(e,t,a,s,r,l,c){return c?e.send(t,a,s,r,l,c):l?.trim()?e.send(t,a,s,r,l):r?.length?e.send(t,a,s,r):s?e.send(t,a,s):e.send(t,a)}function Ve(e,t,a,s,r,l,c){return e.prepareSend?e.prepareSend(t,a,s,r,l,c):Promise.resolve()}async function je(e,t,a,s,r,l,c,R,S){e.evictIdleSessions();const h=Ee(a);if(!h)throw new Error(`Unsupported agent: ${a}`);const n=s==="manager"&&a!=="manager"?new xe(h,a):h;X(n,t,a,c,R,null,S,e.managedRoomExecutor),await n.start(t,r,l);const o={adapter:n,workDir:r,agentType:a,sessionMode:s,agentSessionId:l??null,lastActiveAt:Date.now(),currentRunId:null,currentRunPhase:null,nextEventSeq:0,heartbeatSeq:0,heartbeatTimer:null,pendingTextEvent:null,externalChannel:c??null,externalReplyTarget:R??null,externalChannelEnv:{...me(a),...pe(t,c,R)},managedRoomContextToken:null};return e.sessions.set(t,o),Je(e,t,a,n),o}function Ge(e,t){const a=e.sessions.get(t),s=a?.currentRunId;if(!a||!s)return;const r=a.nextEventSeq;e.runTextAcc.delete(`${t}:${s}`),v(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:t,runId:s,seq:r},seq:r,id:`agent-evt-${s}-${r}`}),e.chatQueue?.noteTerminal(t)}async function pt(e,t,a){const s=a?t.params.managedRoomContextToken??null:null;let r=!1;try{await Ke(e,t,a,()=>{r=!0})}finally{s&&!r&&e.revokeManagedRoomContextToken?.(s)}}async function Ke(e,t,a,s){if(e.processedReqIds.has(t.id)){e.client.sendRes({type:"res",id:t.id,ok:!0});return}const{sessionId:r,text:l,agentType:c,sessionMode:R,managerConfig:S,workDir:h,agentSessionId:n,modelId:o,systemPrompt:q,managerDefaultWorkerAgentType:T,managerDefaultWorkerModelId:k,reasoningEffort:A,clientMessageId:C,sessionListProjection:m,waitForDispatch:Y,responseId:Ie,managedRoomContextToken:P,suppressExternalOwnerEcho:Re,queuedBatchItems:L,managedWorkerParentSessionId:W}=t.params,y=Ie||t.id;De(m);const O=null,U="";if(a?.source==="room_activation"&&(Ne(a,q,P),c==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(Qe(e,t.id),!r||!l){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:"sessionId and text are required"});return}const g=c,$=g==="manager"||R==="manager"?"manager":"standard";$==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(r,T??null,k??null);const N=(g==="claude"||g==="codex"||g==="workbuddy"||g==="pi-coding-agent")&&typeof A=="string"&&A.trim()?A.trim():void 0,w=e.resolvePath(Ue(g,h||de.homedir(),n)||de.homedir()),_=a?.managedAgentPolicy??(W?e.managerRuntime?.getManagedAgentPolicyForWorker(W,w)??null:null);if(W&&!_)throw new Error("managed_worker_permission_context_unavailable");const J=W&&_?Ce({requestedPolicy:_.requestedPolicy,enforcement:_.enforcement,resolvedWorkDir:_.adapterPolicy.workDir}):q,Se=w,F=qe(t.params.attachments);F?.length&&Pe(w,F);const p={text:l,attachments:F,localized:!1};let i=e.sessions.get(r);if(i){if(i.lastActiveAt=Date.now(),i.agentType!==g||(i.sessionMode??(i.agentType==="manager"?"manager":"standard"))!==$||i.workDir!==w||JSON.stringify(i.externalChannel??null)!==JSON.stringify(O??null)){e.sessions.delete(r);try{await B(e,i)}catch{e.processedReqIds.delete(t.id)}i=void 0}else if(n&&i.agentSessionId!==n)try{await i.adapter.resume(n),i.agentSessionId=n}catch{e.sessions.delete(r);try{await B(e,i)}catch{e.processedReqIds.delete(t.id)}i=void 0}}if(!i)try{i=await je(e,r,g,$,w,n,O,U,_)}catch(d){const f=d instanceof Error&&d.message.startsWith("Unsupported agent:")?d.message:`Failed to start ${c}: ${d instanceof Error?d.message:String(d)}`;console.error(`[chat.send] start failed reqId=${t.id} sessionId=${r} agentType=${c} workDir=${w} agentSessionId=${n??""}: ${f}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:f,runId:"",seq:0}}),e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:f});return}const I={id:C??`user-${t.id}`,sessionId:r,role:"user",ts:Date.now(),payload:ie(p.text,p.attachments)},Z=Array.isArray(L)&&L.length>0?L.map(d=>({id:d.clientMessageId??d.id,sessionId:r,role:"user",ts:Date.parse(d.createdAt),payload:ie(d.text,d.attachments)})):null,Q=Z??[I],E=_e(r,I.id),ee=E.state==="queued";if(E.state!=="not_found"&&!ee){e.client.sendRes({type:"res",id:y,ok:!0,payload:E});return}if(Y){a?.source==="room_activation"&&X(i.adapter,r,g,O,U,P,a.managedAgentPolicy,e.managedRoomExecutor);try{await Ve(i.adapter,p.text,o,N,p.attachments,J,a?{source:a.source}:void 0)}catch(d){e.processedReqIds.delete(t.id),e.sessions.delete(r),await B(e,i),e.client.sendRes({type:"res",id:y,ok:!1,error:d instanceof Error?d.message:String(d)});return}}D({level:"info",sessionId:r,wsEvent:"chat.send.start",metadata:{reqId:t.id,agentType:g,sessionMode:$,managerConfig:S??null,modelId:o,managerDefaultWorkerAgentType:T??null,managerDefaultWorkerModelId:k??null,reasoningEffort:N,...a?.source==="room_activation"?{managedRoomPromptSnapshot:a.managedRoomPromptSnapshot}:{}}});const V=(d,f)=>({...ce(le()),sessionId:r,clientMessageId:I.id,messageId:I.id,deliveryState:d,bodyRevision:f,committedAt:new Date(I.ts).toISOString()}),te=d=>{e.nativeFusion?.registerManagedSend({sessionId:r,agentType:g,sourceAgentType:fe(g,o),canonicalMessageId:I.id,sourceSessionKey:i.agentSessionId??n??null,text:p.text,managedEchoPolicy:d?.deliveryMode==="external_owner_queue"&&!Re?"import_following":"suppress_following",externalRunId:d?.deliveryMode==="external_owner_queue"?`codex-external-${d.queuedSubmissionId??I.id}`:null})},ne=()=>{i.currentRunId||(i.currentRunId=`dispatch:${t.id}`,i.currentRunPhase="thinking",i.nextEventSeq=0)},ae=()=>{if(te(),ee)return{...ce(le()),sessionId:r,clientMessageId:E.clientMessageId,messageId:E.messageId,deliveryState:E.deliveryState,bodyRevision:E.bodyRevision,committedAt:E.committedAt};try{Le(e,{sessionId:r,agentType:g,sessionMode:$,managerConfig:S??null,workDir:Se,agentSessionId:i.agentSessionId??n??null,modelId:o,managerDefaultWorkerAgentType:T??null,managerDefaultWorkerModelId:k??null});let d=0;for(const[f,u]of Q.entries()){const M=Z?z(r,u,"committed"):b(r,u,"committed");f===0&&(d=M)}return $e(w,F??[]),x(e.client),V("committed",d)}catch(d){throw e.nativeFusion?.cancelManagedSend?.(I.id),d}},re=d=>{i.currentRunId||(i.nextEventSeq=0),te(d);const f=d?.deliveryMode==="external_owner_queue"?"queued":"executing";let u=0;for(const[M,j]of Q.entries()){const G=z(r,j,f);M===0&&(u=G)}return x(e.client),V(f,u)},oe=async(d,f)=>{e.nativeFusion?.cancelManagedSend?.(I.id);const u=ge(g,d);console.error(`[chat.send] send failed reqId=${t.id} sessionId=${r} agentType=${c} workDir=${w} agentSessionId=${i.agentSessionId??n??""}: ${u}`),e.sessions.delete(r);try{await B(e,i)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:u,runId:"",seq:0}}),!f){const M={id:`agent-error-${t.id}-${Date.now()}`,sessionId:r,role:"agent",ts:Date.now(),payload:u};b(r,M),x(e.client)}f&&(e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:u}))};if(Y){try{ae()}catch(u){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:`Durable message commit failed: ${u instanceof Error?u.message:String(u)}`});return}ne();let d;try{a?.source==="room_activation"&&(he(e,i,P),s());const u=p.attachments;d=await ye(i.adapter,p.text,o,N,u,J,a?{source:a.source}:void 0),D({level:"info",sessionId:r,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}catch(u){let M=0;for(const[G,ke]of Q.entries()){const we=z(r,ke,"failed");G===0&&(M=we)}x(e.client);const j=ge(g,u);await oe(u,!1),e.client.sendRes({type:"res",id:y,ok:!0,payload:{...V("failed",M),failureMessage:j}});return}const f=re(d??void 0);e.client.sendRes({type:"res",id:y,ok:!0,payload:{...f,...p.localized?{localizedAttachments:!0}:{},...d?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:d.deliveryMode,queuedSubmissionId:d.queuedSubmissionId}:{}}}),D({level:"info",sessionId:r,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});return}let se;try{se=ae()}catch(d){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:y,ok:!1,error:`Durable message commit failed: ${d instanceof Error?d.message:String(d)}`});return}ne(),a?.source==="room_activation"&&(X(i.adapter,r,g,O,U,P,a.managedAgentPolicy,e.managedRoomExecutor),he(e,i,P),s()),re(),e.client.sendRes({type:"res",id:y,ok:!0,payload:{...se,...p.localized?{localizedAttachments:!0}:{}}}),D({level:"info",sessionId:r,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});const Ae=p.attachments;ye(i.adapter,p.text,o,N,Ae,J,a?{source:a.source}:void 0).then(()=>{D({level:"info",sessionId:r,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}).catch(d=>{z(r,I,"failed"),x(e.client),oe(d,!1)})}async function ht(e,t){const{sessionId:a}=t.params,s=e.sessions.get(a);if(s){v(e,s);try{await s.adapter.stop()}catch{e.client.sendRes({type:"res",id:t.id,ok:!1,error:"agent_stop_failed"});return}Ge(e,a),e.activityPublisher?.publish(a,null)}e.client.sendRes({type:"res",id:t.id,ok:!0})}export{ht as handleChatAbort,pt as handleChatSend,Le as sendSessionUpdateEvent};
|