shennian 0.5.15 → 0.5.17
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 +18 -13
- package/dist/src/session/handlers/chat-events.js +2 -2
- package/dist/src/session/handlers/chat.js +2 -1
- package/dist/src/session/handlers/steward.js +1 -1
- package/dist/src/session/queue.js +1 -1
- package/dist/src/session/store.js +2 -2
- package/dist/src/steward/failover.js +1 -0
- package/dist/src/steward/templates.js +3 -3
- package/node_modules/@shennian/wire/dist/message-payload.js +4 -4
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 279,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian-adapter-host.js",
|
|
@@ -1091,8 +1091,8 @@
|
|
|
1091
1091
|
},
|
|
1092
1092
|
{
|
|
1093
1093
|
"file": "src/session/handlers/chat-events.js",
|
|
1094
|
-
"beforeBytes":
|
|
1095
|
-
"afterBytes":
|
|
1094
|
+
"beforeBytes": 20267,
|
|
1095
|
+
"afterBytes": 8130
|
|
1096
1096
|
},
|
|
1097
1097
|
{
|
|
1098
1098
|
"file": "src/session/handlers/chat-recovery.js",
|
|
@@ -1106,8 +1106,8 @@
|
|
|
1106
1106
|
},
|
|
1107
1107
|
{
|
|
1108
1108
|
"file": "src/session/handlers/chat.js",
|
|
1109
|
-
"beforeBytes":
|
|
1110
|
-
"afterBytes":
|
|
1109
|
+
"beforeBytes": 36868,
|
|
1110
|
+
"afterBytes": 15693
|
|
1111
1111
|
},
|
|
1112
1112
|
{
|
|
1113
1113
|
"file": "src/session/handlers/control.js",
|
|
@@ -1146,8 +1146,8 @@
|
|
|
1146
1146
|
},
|
|
1147
1147
|
{
|
|
1148
1148
|
"file": "src/session/handlers/steward.js",
|
|
1149
|
-
"beforeBytes":
|
|
1150
|
-
"afterBytes":
|
|
1149
|
+
"beforeBytes": 8421,
|
|
1150
|
+
"afterBytes": 3939
|
|
1151
1151
|
},
|
|
1152
1152
|
{
|
|
1153
1153
|
"file": "src/session/handlers/title.js",
|
|
@@ -1246,8 +1246,8 @@
|
|
|
1246
1246
|
},
|
|
1247
1247
|
{
|
|
1248
1248
|
"file": "src/session/queue.js",
|
|
1249
|
-
"beforeBytes":
|
|
1250
|
-
"afterBytes":
|
|
1249
|
+
"beforeBytes": 43664,
|
|
1250
|
+
"afterBytes": 19298
|
|
1251
1251
|
},
|
|
1252
1252
|
{
|
|
1253
1253
|
"file": "src/session/queued-chat-dispatch.js",
|
|
@@ -1286,8 +1286,8 @@
|
|
|
1286
1286
|
},
|
|
1287
1287
|
{
|
|
1288
1288
|
"file": "src/session/store.js",
|
|
1289
|
-
"beforeBytes":
|
|
1290
|
-
"afterBytes":
|
|
1289
|
+
"beforeBytes": 34234,
|
|
1290
|
+
"afterBytes": 17184
|
|
1291
1291
|
},
|
|
1292
1292
|
{
|
|
1293
1293
|
"file": "src/session/tool-detail-store.js",
|
|
@@ -1314,6 +1314,11 @@
|
|
|
1314
1314
|
"beforeBytes": 18411,
|
|
1315
1315
|
"afterBytes": 9229
|
|
1316
1316
|
},
|
|
1317
|
+
{
|
|
1318
|
+
"file": "src/steward/failover.js",
|
|
1319
|
+
"beforeBytes": 4394,
|
|
1320
|
+
"afterBytes": 2607
|
|
1321
|
+
},
|
|
1317
1322
|
{
|
|
1318
1323
|
"file": "src/steward/session.js",
|
|
1319
1324
|
"beforeBytes": 2700,
|
|
@@ -1321,8 +1326,8 @@
|
|
|
1321
1326
|
},
|
|
1322
1327
|
{
|
|
1323
1328
|
"file": "src/steward/templates.js",
|
|
1324
|
-
"beforeBytes":
|
|
1325
|
-
"afterBytes":
|
|
1329
|
+
"beforeBytes": 4650,
|
|
1330
|
+
"afterBytes": 7878
|
|
1326
1331
|
},
|
|
1327
1332
|
{
|
|
1328
1333
|
"file": "src/steward/workspace.js",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{buildApprovalPendingPayload as
|
|
2
|
-
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function
|
|
1
|
+
import{buildApprovalPendingPayload as M}from"@shennian/wire";import{createHash as w}from"node:crypto";import{AgentEventTerminalGate as D}from"../../agents/event-terminal-gate.js";import{recordAcpAgentModels as k}from"../../agents/model-registry.js";import{reportLog as _}from"../../log-reporter.js";import{registerInternalNativeSource as P}from"../../native-fusion/source-visibility.js";import{requestSessionIndexPublish as c}from"../index-publisher.js";import{noteRunActivity as j}from"../run-stall.js";import{appendMessage as s,recordSession as I,upsertMessage as O}from"../store.js";import{writeToolDetail as C}from"../tool-detail-store.js";import{refreshMachineAgents as F}from"./agents.js";import{roomReplyFailureNotice as N}from"../room-reply-notice.js";import{commitStewardFallback as S,tryStewardFailover as B}from"./steward.js";import{clearStewardSwitched as H,resetStewardChain as J}from"../../steward/failover.js";function L(a){const r=a.indexOf(`
|
|
2
|
+
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function R(a,r,o){return`${a}:${w("sha256").update(`${r}\0${o??""}`).digest("hex")}`}function V(a,r,o={}){if(a.state==="tool-call"||a.state==="tool-result"){const l={runId:a.runId,sourceSeq:a.seq};return{state:a.state,runId:a.runId,seq:a.seq,sessionId:r,detailRef:l,status:a.state==="tool-call"?"running":"completed",detailAvailable:!0,...a.durationMs!==void 0?{durationMs:a.durationMs}:{},...a.name?{name:a.name}:{},...a.source?{source:a.source}:{},...a.agentSessionId?{agentSessionId:a.agentSessionId}:{},...o}}return{...a,sessionId:r,...o}}const Q=3e4;function G(a){return a.state==="heartbeat"?a.runPhase??null:a.state==="tool-call"||a.state==="tool-result"?"tool_running":a.state==="approval-pending"?"waiting_approval":a.state==="delta"?a.thinking?"thinking":"streaming_text":a.state==="init"||a.state==="start"?"thinking":null}function A(a,r){return a!=="manager"?a:r==="claude"?"claude":"codex"}function y(a,r,o,l){if(l.state!=="error"){S(a,r,o,l);return}B(a,r,o,l).catch(()=>!1).then(g=>{g||S(a,r,o,l)})}function lt(a,r,o,l){let g=null;const E=new D;function x(t,n={}){a.client.sendAgentEvent({type:"event",event:"agent",payload:V(t,r,n),seq:t.seq,id:`agent-evt-${t.runId}-${t.seq}`})}o.startsWith("acp:")&&l.on("sessionOptions",()=>{try{const t=l.getSessionOptions?.().models??[];if(!k(o,t))return;const n=a.getAgentSnapshot?.();if(!n)return;a.client.sendEvent({type:"event",event:"machine.agents",payload:{agentList:n.map(e=>e.type),agents:n}})}catch{}});function $(t){t?.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null)}function b(t){if(!t.currentRunId||!t.currentRunPhase)return;const n=t.heartbeatSeq++;a.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:r,runId:t.currentRunId,seq:n,runPhase:t.currentRunPhase},seq:n,id:`agent-heartbeat-${t.currentRunId}-${n}-${Date.now()}`})}function T(t){!t||t.heartbeatTimer||(t.heartbeatTimer=setInterval(()=>{b(t)},Q),t.heartbeatTimer.unref?.())}function f(t){const n=t?.pendingTextEvent;!t||!n||!n.text||(s(r,{id:`agent-${n.runId}-${n.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:n.text}),c(a.client),x({state:"delta",runId:n.runId,seq:n.seq,text:n.text,thinking:n.thinking||void 0}),t.sessionScope==="steward"&&(t.stewardLastText=n.text),t.pendingTextEvent=null)}l.on("agentEvent",t=>{if(!E.accept(t))return;let n=!1;t.errorCode==="acp_auth_required"&&F(a).catch(()=>{});const e=a.sessions.get(r),h=G(t),u=t.state==="final"||t.state==="error"||t.state==="aborted";if(e&&j(r,e,u),e&&(e.nextEventSeq=t.seq+1,!u&&e.currentRunId!==t.runId&&e.sessionScope==="steward"&&(e.stewardSay={count:0},e.stewardLastText="",H(r)),u||(e.currentRunId=t.runId),!u&&h&&(e.currentRunPhase=h,T(e)),t.agentSessionId&&(e.agentSessionId=t.agentSessionId),e.journalRunId)){const i={agentSessionId:t.agentSessionId??e.agentSessionId,providerRunId:t.runId||null,lastObservedEventSeq:t.seq,...u?{}:{phase:h==="waiting_approval"?"waiting_approval":"running"}};a.runJournal?.update(r,e.journalRunId,i)}if(a.managerRuntime?.noteAgentEvent(r,t),t.state==="delta"&&t.thinking)return;t.state!=="delta"&&_({level:"info",sessionId:r,wsEvent:`agent.${t.state}`,wsDirection:"out",metadata:{runId:t.runId,seq:t.seq,agentType:o}});let p=!1;if(t.state==="tool-call"||t.state==="tool-result"){const i=t.toolCallId?`agent-tool-${w("sha256").update(`${t.runId}\0${t.toolCallId}`).digest("hex")}`:`agent-${t.runId}-${t.seq}`;C({sessionId:r,toolCallId:i,detailRevision:t.seq,ts:Date.now(),name:t.name??"tool",...t.args!==void 0?{args:t.args}:{},...t.result!==void 0?{result:t.result}:{},status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq}}),(t.toolCallId?O:s)(r,{id:i,sessionId:r,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:t.state==="tool-call"?"tool_use":"tool_result",name:t.name,toolCallId:i,status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq},detailRevision:t.seq,detailAvailable:!0,resultOmitted:t.state==="tool-result"})}),p=!0}else t.state==="approval-pending"?(s(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:M({...t.approval,permission:t.permission})}),p=!0,e&&I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,attentionId:R("approval",t.runId,t.seq)})):(t.state==="error"||t.state==="aborted")&&t.message&&(s(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),p=!0);p&&c(a.client);const d=`${r}:${t.runId}`;if(t.state==="delta"&&!t.thinking&&t.text&&a.runTextAcc.set(d,(a.runTextAcc.get(d)??"")+t.text),t.agentSessionId&&t.agentSessionId!==g&&(e?.nativeSessionVisibility==="internal"&&P(r,A(o,t.source)??o,t.agentSessionId),g=t.agentSessionId,a.nativeFusion?.noteManagedSourceSession(r,A(o,t.source),t.agentSessionId),e&&I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:t.agentSessionId}),a.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:r,agentType:o,agentSessionId:t.agentSessionId}}})),t.state==="delta"){const i=t.text??"";if(!i)return;e?.pendingTextEvent&&e.pendingTextEvent.runId!==t.runId&&f(e),e&&!e.pendingTextEvent&&(e.pendingTextEvent={runId:t.runId,seq:t.seq,text:"",thinking:!1}),e?.pendingTextEvent&&(e.pendingTextEvent.text+=i,e.pendingTextEvent.seq=t.seq);return}let q={};if(t.state==="final"){f(e),e&&(S(a,r,e,t),J(r));const i=e?N(e):null;i&&(n=!0,s(r,{id:`room-reply-notice-${t.runId}`,sessionId:r,role:"agent",ts:Date.now(),payload:i}),c(a.client));const m=a.runTextAcc.get(d)??"";m&&(q={messageSummary:L(m)}),a.runTextAcc.delete(d)}else t.state==="error"||t.state==="aborted"?(f(e),e&&y(a,r,e,t),a.runTextAcc.delete(d)):(t.state==="tool-call"||t.state==="tool-result"||t.state==="approval-pending")&&f(e);u&&e?.currentRunId===t.runId&&(e.currentRunId=null,e.currentRunPhase=null,e.nextEventSeq=0,$(e),a.chatQueue?.noteTerminal(r),I({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,status:t.state==="final"&&!n?"completed":"failed",attentionId:R("terminal",t.runId),lastActivityAt:new Date().toISOString()}),c(a.client),e.journalRunId&&(a.runJournal?.remove(r,e.journalRunId),a.recoveryBarrier?.end(r),e.journalRunId=null)),x(t,q)}),l.on("error",t=>{console.error(`[chat.send] adapter error sessionId=${r} agentType=${o}: ${t.message}`);const n=a.sessions.get(r);n&&y(a,r,n,{state:"error",runId:n.currentRunId??"",message:t.message}),n?.journalRunId&&(a.runJournal?.update(r,n.journalRunId,{phase:"terminal"}),a.runJournal?.remove(r,n.journalRunId),a.recoveryBarrier?.end(r),n.journalRunId=null),a.sessions.delete(r),a.chatQueue?.noteTerminal(r),a.chatQueue?.isDispatching?.(r)||(s(r,{id:`agent-error-${r}-${Date.now()}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),c(a.client)),a.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:t.message,runId:"",seq:0}})})}export{lt as bindAdapterEvents,A as getNativeSourceAgentType};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{buildUserMessagePayload as pe}from"@shennian/wire";import{createHash as be,randomUUID as xe}from"node:crypto";import me from"node:os";import{reportLog as b}from"../../log-reporter.js";import{getPersonalSyncIdentity as $e}from"../../personal-sync/epoch.js";import{buildManagedAgentPermissionPrompt as Ce}from"../../room/managed-prompt-composer.js";import{parsePersonalAttachmentReferences as We}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as qe,markAttachmentReferences as je}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as S}from"../index-publisher.js";import{isTrustedManagerEvent as Oe}from"../manager-event-authority.js";import{mergeProjectedSessions as Fe}from"../projection.js";import{appendMessage as fe,getDaemonInstallationId as ye,getMessageDeliveryStatus as Be,listSessionRecords as Je,recordSession as ze,upsertMessage as w}from"../store.js";import{STEWARD_SYSTEM_PROMPT as Ue,isStewardSessionId as X,pinStewardWorkDir as ve}from"../../steward/session.js";import{configureAdapterForSession as he,maybeResolveClaudeImportedWorkDir as He,replaceManagedRoomContextToken as Ie,revokeManagedRoomContextToken as Re}from"./chat-adapter-config.js";import{resolveNativeSessionVisibility as Ne,sendSessionUpdateEvent as Ve,validateManagedRoomExecutionContext as Ke}from"./chat-context.js";import{getNativeSourceAgentType as Le}from"./chat-events.js";import{noteRunActivity as Qe}from"../run-stall.js";import{createActiveSession as Ye,disposeSession as C,prepareAdapterTurn as Ze,rememberProcessedReqId as Ge,sendAdapterTurn as _e}from"./chat-session-lifecycle.js";import{sendSessionUpdateEvent as Pn,validateManagedRoomExecutionContext as En}from"./chat-context.js";function Se(e,t){return`Agent send failed: ${t instanceof Error?t.message:String(t)}`}function Xe(e,t){const o=e.sessions.get(t),i=o?.currentRunId;if(!o||!i)return;const n=o.nextEventSeq;e.runTextAcc.delete(`${t}:${i}`),Re(e,o),o.pendingTextEvent=null,Qe(t,o,!0),o.currentRunId=null,o.currentRunPhase=null,o.nextEventSeq=0,o.heartbeatTimer&&(clearInterval(o.heartbeatTimer),o.heartbeatTimer=null),e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:t,runId:i,seq:n},seq:n,id:`agent-evt-${i}-${n}`}),o.journalRunId&&(e.runJournal?.remove(t,o.journalRunId),e.recoveryBarrier?.end(t),o.journalRunId=null),e.chatQueue?.noteTerminal(t)}async function wn(e,t,o){const i=o?t.params.managedRoomContextToken??null:null;let n=!1;try{await en(e,t,o,()=>{n=!0})}finally{i&&!n&&e.revokeManagedRoomContextToken?.(i)}}async function en(e,t,o,i){if(e.processedReqIds.has(t.id)){e.client.sendRes({type:"res",id:t.id,ok:!0});return}const{sessionId:n,text:p,agentType:R,sessionMode:W,managerConfig:ee,workDir:we,agentSessionId:m,modelId:y,modelSelectionSource:q,systemPrompt:ne,managerDefaultWorkerAgentType:j,managerDefaultWorkerModelId:O,reasoningEffort:F,clientMessageId:ke,sessionListProjection:Ae,waitForDispatch:ae,responseId:Me,managedRoomContextToken:k,suppressExternalOwnerEcho:Pe,queuedBatchItems:B,managedWorkerParentSessionId:g,managerWorkerRoomOrigin:J,managerWorkerNativeFull:z,managedRecoverySource:E}=t.params,c=Me||t.id,te=t.params;if((te.managerEventId||te.managerEventRoomOrigin||g||J||z||E)&&!Oe(t))throw new Error("manager_event_source_untrusted");Fe(Ae);const x=null,U="";if(o?.source==="room_activation"&&(Ke(o,ne,k),R==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(o?.source==="manager_event"){if(!o.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(!k||!/^mrc_[A-Za-z0-9_-]{43}$/.test(k))throw new Error("managed_room_context_unavailable")}if(Ge(e,t.id),!n||!p){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"sessionId and text are required"});return}if(e.recoveryBarrier?.isDispatchFrozen()){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"upgrade_in_progress"});return}e.recoveryBarrier?.isRecovering(n)&&await e.recoveryBarrier.wait(n);const s=R,_=s==="manager"||W==="manager"?"manager":"standard";_==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(n,j??null,O??null);const D=(s==="claude"||s==="codex"||s==="workbuddy"||s==="pi-coding-agent"||s.startsWith("acp:"))&&typeof F=="string"&&F.trim()?F.trim():void 0,H=o?.source==="room_activation"?{source:"room_activation",...s==="pi-coding-agent"?{modelSelectionSource:q??(y?"request_model":"pi_default_model")}:{}}:o?.source==="manager_event"?{source:"managed_private",...s==="pi-coding-agent"?{modelSelectionSource:q??(y?"request_model":"pi_default_model")}:{}}:s==="pi-coding-agent"?{source:"personal",modelSelectionSource:q??(y?"request_model":"pi_default_model")}:void 0,oe=X(n)||t.params.sessionScope==="steward",h=oe?ve():e.resolvePath(He(s,we||me.homedir(),m)||me.homedir()),v=o?.managedAgentPolicy??(g?e.managerRuntime?.getManagedAgentPolicyForWorker(g,h)??null:null);if(g&&!z&&!v)throw new Error("managed_worker_permission_context_unavailable");const N=oe;if(N){if(_!=="standard")throw new Error("steward_session_mode_invalid");if(!X(n)&&Je().some(a=>a.sessionId===n))throw new Error("steward_scope_conflict");X(n)||ze({sessionId:n,agentType:s,workDir:ve(),sessionScope:"steward"})}const V=Ne(n,s,_,!!(v||g||o)),K=N?Ue:g&&v?Ce({requestedPolicy:v.requestedPolicy,enforcement:v.enforcement,resolvedWorkDir:v.adapterPolicy.workDir}):ne??null,Ee=h,$=We(t.params.attachments);$?.length&&qe(h,$);const f={text:p,attachments:$,localized:!1};let r=e.sessions.get(n);if(r){if(r.lastActiveAt=Date.now(),r.agentType!==s||(r.sessionMode??(r.agentType==="manager"?"manager":"standard"))!==_||r.workDir!==h||r.sessionScope==="steward"!==N||(r.nativeSessionVisibility??"user")!==V||JSON.stringify(r.externalChannel??null)!==JSON.stringify(x??null)){e.sessions.delete(n);try{await C(e,r)}catch{e.processedReqIds.delete(t.id)}r=void 0}else if(m&&r.agentSessionId!==m)try{await r.adapter.resume(m),r.agentSessionId=m}catch{e.sessions.delete(n);try{await C(e,r)}catch{e.processedReqIds.delete(t.id)}r=void 0}}if(!r)try{r=await Ye(e,n,s,_,h,m,x,U,v,V)}catch(a){const l=a instanceof Error&&a.message.startsWith("Unsupported agent:")?a.message:`Failed to start ${R}: ${a instanceof Error?a.message:String(a)}`;console.error(`[chat.send] start failed reqId=${t.id} sessionId=${n} agentType=${R} workDir=${h} agentSessionId=${m??""}: ${l}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:n,message:l,runId:"",seq:0}}),e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:l});return}const u={id:ke??`user-${t.id}`,sessionId:n,role:"user",ts:Date.now(),payload:pe(f.text,f.attachments)},re=Array.isArray(B)&&B.length>0?B.map(a=>({id:a.clientMessageId??a.id,sessionId:n,role:E==="manager_event"||t.params.scheduledDelivery===!0?"agent":"user",ts:E==="manager_event"||o?.source==="room_activation"?Date.parse(a.createdAt):u.ts,payload:pe(a.text,a.attachments)})):null,A=re??[u],L=Be(n,u.id),se=L.state==="queued";if(L.state!=="not_found"&&!se){e.client.sendRes({type:"res",id:c,ok:!0,payload:L});return}if(ae){(o?.source==="room_activation"||o?.source==="manager_event")&&he(r.adapter,n,s,x,U,k,o.managedAgentPolicy,e.managedRoomExecutor);try{await Ze(r.adapter,f.text,y,D,f.attachments,K,H)}catch(a){e.processedReqIds.delete(t.id),e.sessions.delete(n),await C(e,r),e.client.sendRes({type:"res",id:c,ok:!1,error:a instanceof Error?a.message:String(a)});return}}b({level:"info",sessionId:n,wsEvent:"chat.send.start",metadata:{reqId:t.id,agentType:s,sessionMode:_,managerConfig:ee??null,modelId:y,managerDefaultWorkerAgentType:j??null,managerDefaultWorkerModelId:O??null,reasoningEffort:D,...o?.source==="room_activation"?{managedRoomPromptSnapshot:o.managedRoomPromptSnapshot}:{}}});const M=(a,l)=>({...$e(ye()),sessionId:n,clientMessageId:u.id,messageId:u.id,deliveryState:a,bodyRevision:l,committedAt:new Date(u.ts).toISOString()}),Q=a=>{e.nativeFusion?.registerManagedSend({sessionId:n,agentType:s,sourceAgentType:Le(s,y),canonicalMessageId:u.id,sourceSessionKey:r.agentSessionId??m??null,text:f.text,managedEchoPolicy:a?.deliveryMode==="external_owner_queue"&&!Pe?"import_following":"suppress_following",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ie=()=>{r.currentRunId||(r.currentRunId=`dispatch:${t.id}`,r.currentRunPhase="thinking",r.nextEventSeq=0,r.lastProviderActivityAt=Date.now())},de=()=>{if(!e.runJournal||r.journalRunId)return;const a=`run:${xe()}`;e.runJournal.begin({daemonInstallationId:ye(),sessionId:n,runId:a,clientMessageId:u.id,agentType:s,sessionMode:_,workDir:h,agentSessionId:r.agentSessionId??m??null,modelId:y??null,reasoningEffort:D??null,nativeSessionVisibility:V,providerRunId:null,source:E==="manager_event"?"manager_event":o?.source==="room_activation"?E==="managed_direct"?"managed_direct":"managed_room":g?"manager_worker":"personal",parentSessionId:g??null,managerWorkerNativeFull:z===!0,roomContextRegistryKey:typeof t.params.roomContextRegistryKey=="string"?t.params.roomContextRegistryKey:null,activationCauseMessageId:typeof t.params.activationCauseMessageId=="string"?t.params.activationCauseMessageId:null,rootCauseMessageId:typeof t.params.rootCauseMessageId=="string"?t.params.rootCauseMessageId:null,activationSequence:typeof t.params.activationSequence=="string"?t.params.activationSequence:null,activationHopCount:typeof t.params.activationHopCount=="number"?t.params.activationHopCount:null,managedPolicyVersion:o?.source==="room_activation"?o.managedRoomPromptSnapshot.managedRoomPolicyVersion:o?.source==="manager_event"?o.managedRoomPolicyVersion:null,managedRuntimePolicyHash:(o?.source==="room_activation"?o.managedRoomPromptSnapshot.runtimePermissionPolicyHash:o?.source==="manager_event"?o.managedRuntimePolicyHash:null)??(v?be("sha256").update(JSON.stringify({requestedPolicy:v.requestedPolicy,enforcement:v.enforcement})).digest("hex"):null)}),r.journalRunId=a},le=()=>{if(Q(),se){let a=0;for(const[l,d]of A.entries()){const I=w(n,d,"queued");l===0&&(a=I)}return M("queued",a)}try{Ve(e,{sessionId:n,agentType:s,sessionMode:_,managerConfig:ee??null,workDir:Ee,agentSessionId:r.agentSessionId??m??null,modelId:y,managerDefaultWorkerAgentType:j??null,managerDefaultWorkerModelId:O??null});let a=0;for(const[l,d]of A.entries()){const I=re?w(n,d,"committed"):fe(n,d,"committed");l===0&&(a=I)}return je(h,$??[]),S(e.client),M("committed",a)}catch(a){throw e.nativeFusion?.cancelManagedSend?.(u.id),a}},ce=a=>{r.journalRunId&&e.runJournal?.update(n,r.journalRunId,{deliveryMode:a?.deliveryMode==="external_owner_queue"?"external_owner_queue":"direct",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ue=a=>{r.currentRunId||(r.nextEventSeq=0),ce(a),Q(a);const l=a?.deliveryMode==="external_owner_queue"?"queued":"executing";let d=0;for(const[I,T]of A.entries()){const P=w(n,T,l);I===0&&(d=P)}return S(e.client),M(l,d)},Y=async(a,l)=>{e.nativeFusion?.cancelManagedSend?.(u.id);const d=Se(s,a);if(console.error(`[chat.send] send failed reqId=${t.id} sessionId=${n} agentType=${R} workDir=${h} agentSessionId=${r.agentSessionId??m??""}: ${d}`),r.adapter.hasPendingAuthenticationRetry?.()===!0){l&&e.client.sendRes({type:"res",id:c,ok:!0,payload:M("queued",0)});return}e.sessions.delete(n),r.journalRunId&&(e.runJournal?.update(n,r.journalRunId,{phase:"terminal"}),e.runJournal?.remove(n,r.journalRunId),e.recoveryBarrier?.end(n),r.journalRunId=null);try{await C(e,r)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:n,message:d,runId:"",seq:0}}),!l){const T={id:`agent-error-${t.id}-${Date.now()}`,sessionId:n,role:"agent",ts:Date.now(),payload:d};fe(n,T),S(e.client)}l&&(e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:d}))};if(ae){try{le()}catch(d){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${d instanceof Error?d.message:String(d)}`});return}de(),ie();let a;try{(o?.source==="room_activation"||o?.source==="manager_event")&&(Ie(e,r,k),i());const d=f.attachments;g&&e.managerRuntime?.prepareWorkerTurnOrigin(n,J),a=await _e(r.adapter,f.text,y,D,d,K,H),b({level:"info",sessionId:n,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}catch(d){if(g&&e.managerRuntime?.prepareWorkerTurnOrigin(n),r.adapter.hasPendingAuthenticationRetry?.()){let P=0;for(const[Z,G]of A.entries()){const Te=w(n,G,"queued");Z===0&&(P=Te)}S(e.client),await Y(d,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:M("queued",P)});return}let I=0;for(const[P,Z]of A.entries()){const G=w(n,Z,"failed");P===0&&(I=G)}S(e.client);const T=Se(s,d);await Y(d,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...M("failed",I),failureMessage:T}});return}const l=ue(a??void 0);e.client.sendRes({type:"res",id:c,ok:!0,payload:{...l,...f.localized?{localizedAttachments:!0}:{},...a?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:a.deliveryMode,queuedSubmissionId:a.queuedSubmissionId}:{}}}),b({level:"info",sessionId:n,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});return}let ge;try{ge=le()}catch(a){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${a instanceof Error?a.message:String(a)}`});return}de(),ie(),(o?.source==="room_activation"||o?.source==="manager_event")&&(he(r.adapter,n,s,x,U,k,o.managedAgentPolicy,e.managedRoomExecutor),Ie(e,r,k),i()),ue(),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...ge,...f.localized?{localizedAttachments:!0}:{}}}),b({level:"info",sessionId:n,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});const De=f.attachments;g&&e.managerRuntime?.prepareWorkerTurnOrigin(n,J),_e(r.adapter,f.text,y,D,De,K,H).then(a=>{if(a?.deliveryMode==="external_owner_queue"){ce(a),Q(a);for(const l of A)w(n,l,"queued");S(e.client)}b({level:"info",sessionId:n,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}).catch(a=>{g&&e.managerRuntime?.prepareWorkerTurnOrigin(n),w(n,u,r.adapter.hasPendingAuthenticationRetry?.()?"queued":"failed"),S(e.client),Y(a,!1)})}const nn=2e4;async function an(e,t){let o;const i=new Promise(n=>{o=setTimeout(()=>n("timed_out"),t)});try{return await Promise.race([e.adapter.stop().then(()=>"stopped"),i])}finally{clearTimeout(o)}}async function kn(e,t,o=nn){const{sessionId:i,discardPending:n}=t.params,p=e.sessions.get(i);if(p){p.journalRunId&&e.runJournal?.markAborted(i,p.journalRunId),Re(e,p);let R;try{R=await an(p,o)}catch{e.client.sendRes({type:"res",id:t.id,ok:!1,error:"agent_stop_failed"});return}const W=p.currentRunId;Xe(e,i),R==="timed_out"&&(e.sessions.delete(i),p.adapter.removeAllListeners(),p.adapter.stop().catch(()=>{}),console.error(`[chat.abort] agent did not stop within ${o}ms; ended the run by force sessionId=${i}`),w(i,{id:`stop-forced-${W??t.id}`,sessionId:i,role:"agent",ts:Date.now(),payload:"AI \u6CA1\u6709\u54CD\u5E94\u201C\u505C\u6B62\u201D\u8BF7\u6C42\uFF0C\u795E\u5FF5\u5DF2\u5F3A\u5236\u7ED3\u675F\u8FD9\u4E00\u8F6E\u3002\u53EF\u4EE5\u76F4\u63A5\u53D1\u9001\u65B0\u6D88\u606F\u7EE7\u7EED\uFF1B\u5982\u679C\u53CD\u590D\u51FA\u73B0\uFF0C\u8BF7\u68C0\u67E5\u8FD9\u53F0\u7535\u8111\u4E0A\u8BE5 AI \u7684\u8FD0\u884C\u72B6\u6001\u3002"}),S(e.client)),e.activityPublisher?.publish(i,null)}n===!0&&e.chatQueue?.purgeSession(i),e.client.sendRes({type:"res",id:t.id,ok:!0})}export{nn as STOP_TIMEOUT_MS,kn as handleChatAbort,wn as handleChatSend,Pn as sendSessionUpdateEvent,En as validateManagedRoomExecutionContext};
|
|
1
|
+
import{buildUserMessagePayload as pe}from"@shennian/wire";import{createHash as be,randomUUID as xe}from"node:crypto";import me from"node:os";import{reportLog as b}from"../../log-reporter.js";import{getPersonalSyncIdentity as $e}from"../../personal-sync/epoch.js";import{buildManagedAgentPermissionPrompt as Ce}from"../../room/managed-prompt-composer.js";import{parsePersonalAttachmentReferences as We}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as qe,markAttachmentReferences as je}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as _}from"../index-publisher.js";import{isTrustedManagerEvent as Oe}from"../manager-event-authority.js";import{mergeProjectedSessions as Be}from"../projection.js";import{appendMessage as fe,getDaemonInstallationId as ye,getMessageDeliveryStatus as Fe,listSessionRecords as Je,recordSession as ze,upsertMessage as w}from"../store.js";import{STEWARD_SYSTEM_PROMPT as Ue,isStewardSessionId as X,pinStewardWorkDir as ve}from"../../steward/session.js";import{rememberStewardTurn as He,takeStewardHandover as Ne}from"../../steward/failover.js";import{configureAdapterForSession as he,maybeResolveClaudeImportedWorkDir as Ve,replaceManagedRoomContextToken as Ie,revokeManagedRoomContextToken as Re}from"./chat-adapter-config.js";import{resolveNativeSessionVisibility as Ke,sendSessionUpdateEvent as Le,validateManagedRoomExecutionContext as Qe}from"./chat-context.js";import{getNativeSourceAgentType as Ye}from"./chat-events.js";import{noteRunActivity as Ze}from"../run-stall.js";import{createActiveSession as Ge,disposeSession as W,prepareAdapterTurn as Xe,rememberProcessedReqId as en,sendAdapterTurn as Se}from"./chat-session-lifecycle.js";import{sendSessionUpdateEvent as Tn,validateManagedRoomExecutionContext as bn}from"./chat-context.js";function _e(e,t){return`Agent send failed: ${t instanceof Error?t.message:String(t)}`}function nn(e,t){const o=e.sessions.get(t),i=o?.currentRunId;if(!o||!i)return;const n=o.nextEventSeq;e.runTextAcc.delete(`${t}:${i}`),Re(e,o),o.pendingTextEvent=null,Ze(t,o,!0),o.currentRunId=null,o.currentRunPhase=null,o.nextEventSeq=0,o.heartbeatTimer&&(clearInterval(o.heartbeatTimer),o.heartbeatTimer=null),e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:t,runId:i,seq:n},seq:n,id:`agent-evt-${i}-${n}`}),o.journalRunId&&(e.runJournal?.remove(t,o.journalRunId),e.recoveryBarrier?.end(t),o.journalRunId=null),e.chatQueue?.noteTerminal(t)}async function Mn(e,t,o){const i=o?t.params.managedRoomContextToken??null:null;let n=!1;try{await an(e,t,o,()=>{n=!0})}finally{i&&!n&&e.revokeManagedRoomContextToken?.(i)}}async function an(e,t,o,i){if(e.processedReqIds.has(t.id)){e.client.sendRes({type:"res",id:t.id,ok:!0});return}const{sessionId:n,text:g,agentType:R,sessionMode:q,managerConfig:ee,workDir:we,agentSessionId:m,modelId:y,modelSelectionSource:j,systemPrompt:ne,managerDefaultWorkerAgentType:O,managerDefaultWorkerModelId:B,reasoningEffort:F,clientMessageId:ke,sessionListProjection:Ae,waitForDispatch:ae,responseId:Me,managedRoomContextToken:k,suppressExternalOwnerEcho:Pe,queuedBatchItems:J,managedWorkerParentSessionId:p,managerWorkerRoomOrigin:z,managerWorkerNativeFull:U,managedRecoverySource:E}=t.params,c=Me||t.id,te=t.params;if((te.managerEventId||te.managerEventRoomOrigin||p||z||U||E)&&!Oe(t))throw new Error("manager_event_source_untrusted");Be(Ae);const x=null,H="";if(o?.source==="room_activation"&&(Qe(o,ne,k),R==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(o?.source==="manager_event"){if(!o.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(!k||!/^mrc_[A-Za-z0-9_-]{43}$/.test(k))throw new Error("managed_room_context_unavailable")}if(en(e,t.id),!n||!g){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"sessionId and text are required"});return}if(e.recoveryBarrier?.isDispatchFrozen()){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"upgrade_in_progress"});return}e.recoveryBarrier?.isRecovering(n)&&await e.recoveryBarrier.wait(n);const s=R,S=s==="manager"||q==="manager"?"manager":"standard";S==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(n,O??null,B??null);const D=(s==="claude"||s==="codex"||s==="workbuddy"||s==="pi-coding-agent"||s.startsWith("acp:"))&&typeof F=="string"&&F.trim()?F.trim():void 0,N=o?.source==="room_activation"?{source:"room_activation",...s==="pi-coding-agent"?{modelSelectionSource:j??(y?"request_model":"pi_default_model")}:{}}:o?.source==="manager_event"?{source:"managed_private",...s==="pi-coding-agent"?{modelSelectionSource:j??(y?"request_model":"pi_default_model")}:{}}:s==="pi-coding-agent"?{source:"personal",modelSelectionSource:j??(y?"request_model":"pi_default_model")}:void 0,oe=X(n)||t.params.sessionScope==="steward",h=oe?ve():e.resolvePath(Ve(s,we||me.homedir(),m)||me.homedir()),v=o?.managedAgentPolicy??(p?e.managerRuntime?.getManagedAgentPolicyForWorker(p,h)??null:null);if(p&&!U&&!v)throw new Error("managed_worker_permission_context_unavailable");const $=oe;if($){if(S!=="standard")throw new Error("steward_session_mode_invalid");if(!X(n)&&Je().some(a=>a.sessionId===n))throw new Error("steward_scope_conflict");X(n)||ze({sessionId:n,agentType:s,workDir:ve(),sessionScope:"steward"})}const V=Ke(n,s,S,!!(v||p||o));$&&He(n,String(g??""));const K=$?[Ue,Ne(n)].filter(Boolean).join(`
|
|
2
|
+
`):p&&v?Ce({requestedPolicy:v.requestedPolicy,enforcement:v.enforcement,resolvedWorkDir:v.adapterPolicy.workDir}):ne??null,Ee=h,C=We(t.params.attachments);C?.length&&qe(h,C);const f={text:g,attachments:C,localized:!1};let r=e.sessions.get(n);if(r){if(r.lastActiveAt=Date.now(),r.agentType!==s||(r.sessionMode??(r.agentType==="manager"?"manager":"standard"))!==S||r.workDir!==h||r.sessionScope==="steward"!==$||(r.nativeSessionVisibility??"user")!==V||JSON.stringify(r.externalChannel??null)!==JSON.stringify(x??null)){e.sessions.delete(n);try{await W(e,r)}catch{e.processedReqIds.delete(t.id)}r=void 0}else if(m&&r.agentSessionId!==m)try{await r.adapter.resume(m),r.agentSessionId=m}catch{e.sessions.delete(n);try{await W(e,r)}catch{e.processedReqIds.delete(t.id)}r=void 0}}if(!r)try{r=await Ge(e,n,s,S,h,m,x,H,v,V)}catch(a){const l=a instanceof Error&&a.message.startsWith("Unsupported agent:")?a.message:`Failed to start ${R}: ${a instanceof Error?a.message:String(a)}`;console.error(`[chat.send] start failed reqId=${t.id} sessionId=${n} agentType=${R} workDir=${h} agentSessionId=${m??""}: ${l}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:n,message:l,runId:"",seq:0}}),e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:l});return}const u={id:ke??`user-${t.id}`,sessionId:n,role:"user",ts:Date.now(),payload:pe(f.text,f.attachments)},re=Array.isArray(J)&&J.length>0?J.map(a=>({id:a.clientMessageId??a.id,sessionId:n,role:E==="manager_event"||t.params.scheduledDelivery===!0?"agent":"user",ts:E==="manager_event"||o?.source==="room_activation"?Date.parse(a.createdAt):u.ts,payload:pe(a.text,a.attachments)})):null,A=re??[u],L=Fe(n,u.id),se=L.state==="queued";if(L.state!=="not_found"&&!se){e.client.sendRes({type:"res",id:c,ok:!0,payload:L});return}if(ae){(o?.source==="room_activation"||o?.source==="manager_event")&&he(r.adapter,n,s,x,H,k,o.managedAgentPolicy,e.managedRoomExecutor);try{await Xe(r.adapter,f.text,y,D,f.attachments,K,N)}catch(a){e.processedReqIds.delete(t.id),e.sessions.delete(n),await W(e,r),e.client.sendRes({type:"res",id:c,ok:!1,error:a instanceof Error?a.message:String(a)});return}}b({level:"info",sessionId:n,wsEvent:"chat.send.start",metadata:{reqId:t.id,agentType:s,sessionMode:S,managerConfig:ee??null,modelId:y,managerDefaultWorkerAgentType:O??null,managerDefaultWorkerModelId:B??null,reasoningEffort:D,...o?.source==="room_activation"?{managedRoomPromptSnapshot:o.managedRoomPromptSnapshot}:{}}});const M=(a,l)=>({...$e(ye()),sessionId:n,clientMessageId:u.id,messageId:u.id,deliveryState:a,bodyRevision:l,committedAt:new Date(u.ts).toISOString()}),Q=a=>{e.nativeFusion?.registerManagedSend({sessionId:n,agentType:s,sourceAgentType:Ye(s,y),canonicalMessageId:u.id,sourceSessionKey:r.agentSessionId??m??null,text:f.text,managedEchoPolicy:a?.deliveryMode==="external_owner_queue"&&!Pe?"import_following":"suppress_following",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ie=()=>{r.currentRunId||(r.currentRunId=`dispatch:${t.id}`,r.currentRunPhase="thinking",r.nextEventSeq=0,r.lastProviderActivityAt=Date.now())},de=()=>{if(!e.runJournal||r.journalRunId)return;const a=`run:${xe()}`;e.runJournal.begin({daemonInstallationId:ye(),sessionId:n,runId:a,clientMessageId:u.id,agentType:s,sessionMode:S,workDir:h,agentSessionId:r.agentSessionId??m??null,modelId:y??null,reasoningEffort:D??null,nativeSessionVisibility:V,providerRunId:null,source:E==="manager_event"?"manager_event":o?.source==="room_activation"?E==="managed_direct"?"managed_direct":"managed_room":p?"manager_worker":"personal",parentSessionId:p??null,managerWorkerNativeFull:U===!0,roomContextRegistryKey:typeof t.params.roomContextRegistryKey=="string"?t.params.roomContextRegistryKey:null,activationCauseMessageId:typeof t.params.activationCauseMessageId=="string"?t.params.activationCauseMessageId:null,rootCauseMessageId:typeof t.params.rootCauseMessageId=="string"?t.params.rootCauseMessageId:null,activationSequence:typeof t.params.activationSequence=="string"?t.params.activationSequence:null,activationHopCount:typeof t.params.activationHopCount=="number"?t.params.activationHopCount:null,managedPolicyVersion:o?.source==="room_activation"?o.managedRoomPromptSnapshot.managedRoomPolicyVersion:o?.source==="manager_event"?o.managedRoomPolicyVersion:null,managedRuntimePolicyHash:(o?.source==="room_activation"?o.managedRoomPromptSnapshot.runtimePermissionPolicyHash:o?.source==="manager_event"?o.managedRuntimePolicyHash:null)??(v?be("sha256").update(JSON.stringify({requestedPolicy:v.requestedPolicy,enforcement:v.enforcement})).digest("hex"):null)}),r.journalRunId=a},le=()=>{if(Q(),se){let a=0;for(const[l,d]of A.entries()){const I=w(n,d,"queued");l===0&&(a=I)}return M("queued",a)}try{Le(e,{sessionId:n,agentType:s,sessionMode:S,managerConfig:ee??null,workDir:Ee,agentSessionId:r.agentSessionId??m??null,modelId:y,managerDefaultWorkerAgentType:O??null,managerDefaultWorkerModelId:B??null});let a=0;for(const[l,d]of A.entries()){const I=re?w(n,d,"committed"):fe(n,d,"committed");l===0&&(a=I)}return je(h,C??[]),_(e.client),M("committed",a)}catch(a){throw e.nativeFusion?.cancelManagedSend?.(u.id),a}},ce=a=>{r.journalRunId&&e.runJournal?.update(n,r.journalRunId,{deliveryMode:a?.deliveryMode==="external_owner_queue"?"external_owner_queue":"direct",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ue=a=>{r.currentRunId||(r.nextEventSeq=0),ce(a),Q(a);const l=a?.deliveryMode==="external_owner_queue"?"queued":"executing";let d=0;for(const[I,T]of A.entries()){const P=w(n,T,l);I===0&&(d=P)}return _(e.client),M(l,d)},Y=async(a,l)=>{e.nativeFusion?.cancelManagedSend?.(u.id);const d=_e(s,a);if(console.error(`[chat.send] send failed reqId=${t.id} sessionId=${n} agentType=${R} workDir=${h} agentSessionId=${r.agentSessionId??m??""}: ${d}`),r.adapter.hasPendingAuthenticationRetry?.()===!0){l&&e.client.sendRes({type:"res",id:c,ok:!0,payload:M("queued",0)});return}e.sessions.delete(n),r.journalRunId&&(e.runJournal?.update(n,r.journalRunId,{phase:"terminal"}),e.runJournal?.remove(n,r.journalRunId),e.recoveryBarrier?.end(n),r.journalRunId=null);try{await W(e,r)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:n,message:d,runId:"",seq:0}}),!l){const T={id:`agent-error-${t.id}-${Date.now()}`,sessionId:n,role:"agent",ts:Date.now(),payload:d};fe(n,T),_(e.client)}l&&(e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:d}))};if(ae){try{le()}catch(d){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${d instanceof Error?d.message:String(d)}`});return}de(),ie();let a;try{(o?.source==="room_activation"||o?.source==="manager_event")&&(Ie(e,r,k),i());const d=f.attachments;p&&e.managerRuntime?.prepareWorkerTurnOrigin(n,z),a=await Se(r.adapter,f.text,y,D,d,K,N),b({level:"info",sessionId:n,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}catch(d){if(p&&e.managerRuntime?.prepareWorkerTurnOrigin(n),r.adapter.hasPendingAuthenticationRetry?.()){let P=0;for(const[Z,G]of A.entries()){const Te=w(n,G,"queued");Z===0&&(P=Te)}_(e.client),await Y(d,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:M("queued",P)});return}let I=0;for(const[P,Z]of A.entries()){const G=w(n,Z,"failed");P===0&&(I=G)}_(e.client);const T=_e(s,d);await Y(d,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...M("failed",I),failureMessage:T}});return}const l=ue(a??void 0);e.client.sendRes({type:"res",id:c,ok:!0,payload:{...l,...f.localized?{localizedAttachments:!0}:{},...a?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:a.deliveryMode,queuedSubmissionId:a.queuedSubmissionId}:{}}}),b({level:"info",sessionId:n,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});return}let ge;try{ge=le()}catch(a){e.processedReqIds.delete(t.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${a instanceof Error?a.message:String(a)}`});return}de(),ie(),(o?.source==="room_activation"||o?.source==="manager_event")&&(he(r.adapter,n,s,x,H,k,o.managedAgentPolicy,e.managedRoomExecutor),Ie(e,r,k),i()),ue(),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...ge,...f.localized?{localizedAttachments:!0}:{}}}),b({level:"info",sessionId:n,wsEvent:"chat.send.res",metadata:{reqId:t.id,ok:!0}});const De=f.attachments;p&&e.managerRuntime?.prepareWorkerTurnOrigin(n,z),Se(r.adapter,f.text,y,D,De,K,N).then(a=>{if(a?.deliveryMode==="external_owner_queue"){ce(a),Q(a);for(const l of A)w(n,l,"queued");_(e.client)}b({level:"info",sessionId:n,wsEvent:"chat.send.done",metadata:{reqId:t.id}})}).catch(a=>{p&&e.managerRuntime?.prepareWorkerTurnOrigin(n),w(n,u,r.adapter.hasPendingAuthenticationRetry?.()?"queued":"failed"),_(e.client),Y(a,!1)})}const tn=2e4;async function on(e,t){let o;const i=new Promise(n=>{o=setTimeout(()=>n("timed_out"),t)});try{return await Promise.race([e.adapter.stop().then(()=>"stopped"),i])}finally{clearTimeout(o)}}async function Pn(e,t,o=tn){const{sessionId:i,discardPending:n}=t.params,g=e.sessions.get(i);if(g){g.journalRunId&&e.runJournal?.markAborted(i,g.journalRunId),Re(e,g);let R;try{R=await on(g,o)}catch{e.client.sendRes({type:"res",id:t.id,ok:!1,error:"agent_stop_failed"});return}const q=g.currentRunId;nn(e,i),R==="timed_out"&&(e.sessions.delete(i),g.adapter.removeAllListeners(),g.adapter.stop().catch(()=>{}),console.error(`[chat.abort] agent did not stop within ${o}ms; ended the run by force sessionId=${i}`),w(i,{id:`stop-forced-${q??t.id}`,sessionId:i,role:"agent",ts:Date.now(),payload:"AI \u6CA1\u6709\u54CD\u5E94\u201C\u505C\u6B62\u201D\u8BF7\u6C42\uFF0C\u795E\u5FF5\u5DF2\u5F3A\u5236\u7ED3\u675F\u8FD9\u4E00\u8F6E\u3002\u53EF\u4EE5\u76F4\u63A5\u53D1\u9001\u65B0\u6D88\u606F\u7EE7\u7EED\uFF1B\u5982\u679C\u53CD\u590D\u51FA\u73B0\uFF0C\u8BF7\u68C0\u67E5\u8FD9\u53F0\u7535\u8111\u4E0A\u8BE5 AI \u7684\u8FD0\u884C\u72B6\u6001\u3002"}),_(e.client)),e.activityPublisher?.publish(i,null)}n===!0&&e.chatQueue?.purgeSession(i),e.client.sendRes({type:"res",id:t.id,ok:!0})}export{tn as STOP_TIMEOUT_MS,Pn as handleChatAbort,Mn as handleChatSend,Tn as sendSessionUpdateEvent,bn as validateManagedRoomExecutionContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash as
|
|
1
|
+
import{createHash as T,randomUUID as m}from"node:crypto";import{buildStewardSayPayload as x,parseStewardSayPayload as E,STEWARD_FAILOVER_USER_MESSAGE_ID_PREFIX as A,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as $}from"@shennian/wire";import{DaemonIpcError as D}from"../../daemon-ipc/protocol.js";import{STEWARD_SAY_MAX_CHARS as l,isStewardSessionId as S}from"../../steward/session.js";import{requestSessionIndexPublish as R}from"../index-publisher.js";import{appendMessage as y,getDaemonInstallationId as I,listSessionRecords as M,readMessages as L,recordSession as g}from"../store.js";import{pinStewardWorkDir as h}from"../../steward/session.js";import{buildHandoverNote as b,carryStewardChain as N,classifyStewardFailure as k,clearStewardSwitched as _,lastStewardUserText as F,markStewardSwitched as C,pickFailoverAgent as P,setStewardHandover as U,wasStewardJustSwitched as W,stewardFailureLabel as q,stewardTriedAgents as H}from"../../steward/failover.js";class c extends D{}function w(t,e,a,r="say",d){if(!S(e))throw new c("steward_session_required","This session is not a Shennian steward session.");const s=typeof a=="string"?a.trim():"";if(!s)throw new c("steward_say_empty","There is nothing to say.");if(s.length>l)throw new c("steward_say_too_long",`A message may hold at most ${l} characters.`);const n=d??`steward-say-${m()}`;y(e,{id:n,sessionId:e,role:"agent",ts:Date.now(),payload:x(s,r)});const o=t.sessions.get(e);return o&&r==="say"&&(o.stewardSay={count:(o.stewardSay?.count??0)+1}),R(t.client),{messageId:n}}function O(t){for(const e of L(t,{limit:40})){if(e.role==="user")return!1;if(e.role==="agent"&&E(String(e.payload))?.source==="say")return!0}return!1}function te(t,e,a,r){if(!S(e)||(a.stewardSay?.count??0)>0||W(e)||O(e))return;const s=(a.stewardLastText?.trim()??"")||(r.state==="final"?"\u5DF2\u5904\u7406\uFF0C\u4F46\u6CA1\u6709\u53EF\u663E\u793A\u7684\u56DE\u590D\u3002":r.message?.trim()||"\u8FD9\u6B21\u5904\u7406\u6CA1\u6709\u5B8C\u6210\u3002");try{w(t,e,s.slice(0,l),"fallback",`steward-fallback-${r.runId||"run"}`)}catch{}}const G="\u6765\u81EA\u7EC8\u7AEF",X=new Set(["manager","pi"]);function v(t){const e=T("sha256").update(`${t}\0steward-terminal`).digest("hex"),a=(Number.parseInt(e[16],16)&3|8).toString(16);return`sess_${e.slice(0,8)}-${e.slice(8,12)}-4${e.slice(13,16)}-${a}${e.slice(17,20)}-${e.slice(20,32)}`}function ae(t,e){const a=v(I()),r=M().find(d=>d.sessionId===a);if(r&&r.sessionScope!=="steward")throw new c("steward_scope_conflict","The terminal conversation id is already in use.");if(!r){const s=(t.getAgentSnapshot?.()??[]).find(n=>n.supportsStandardSession!==!1&&!X.has(n.type))?.type??"codex";g({sessionId:a,agentType:s,workDir:h(),sessionScope:"steward",sessionMode:"standard"}),y(a,{id:`${$}${a}`,sessionId:a,role:"user",ts:Date.now(),payload:G})}return{...w(t,a,e),sessionId:a}}const Q={codex:"Codex",claude:"Claude Code",opencode:"OpenCode"},p=t=>Q[t]??t.replace(/^acp:/,"");async function re(t,e,a,r,d){if(r.state!=="error"||!S(e)||(a.stewardSay?.count??0)>0||!t.chatQueue)return!1;const s=d||F(e);if(!s)return!1;const n=H(e,a.agentType),o=P(t.getAgentSnapshot?.()??[],n);if(!o)return!1;const u=k(r.message);C(e);const i=`sess_${m()}`,f=h();g({sessionId:i,agentType:o,workDir:f,sessionScope:"steward",sessionMode:"standard"}),N(e,i,[...n,o]),U(i,b(p(a.agentType),u));try{if(!await t.chatQueue.handleEnqueue({type:"req",id:`steward-failover-${i}`,method:"chat.enqueue",params:{sessionId:i,text:s,agentType:o,workDir:f,sessionMode:"standard",sessionScope:"steward",clientMessageId:`${A}${i}`}}))return _(e),!1}catch{return _(e),!1}return w(t,i,`\u5DF2\u81EA\u52A8\u5207\u6362\u5230 ${p(o)}\uFF08\u539F\u56E0\uFF1A${p(a.agentType)}${q(u)}\uFF09`,"say",`steward-failover-note-${i}`),!0}export{G as STEWARD_TERMINAL_TITLE,c as StewardSayError,te as commitStewardFallback,w as commitStewardSay,ae as commitTerminalStewardSay,v as stewardTerminalSessionId,re as tryStewardFailover};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{NativeSourceDeletionStore as G}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as U}from"./queue-retry.js";import{findDuplicateQueuedMessage as Q,stripLocalQueueFields as H,takeCompatibleBatch as P,formatQueuedBatch as V,dedupeQueuedAttachments as X,classifyQueueError as Y,normalizeQueuedModelId as M,resolveManagedRoomNativeSessionId as E,managedDirectTurnOptions as b}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as Z}from"@shennian/wire";import{isCodexThreadTailInterrupted as ee}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as te}from"./projection.js";import{assertFinishedAttachmentReferences as ne,markAttachmentReferences as se}from"./attachment-transfer-store.js";import{appendMessage as W,getMessageDeliveryStatus as x,listSessionRecords as A,recordSession as L,tombstoneMessage as ie,upsertMessage as re}from"./store.js";import{handleQueueDispatchFailure as ae,queueBlockedUntil as F,resolveQueueRecoveryNotice as O}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as oe}from"../agents/command-spec.js";import{requestSessionIndexPublish as w}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as de,purgeQueuedSessionData as ue,readQueue as h,writeQueue as k}from"./queue-storage.js";import{parsePersonalAttachmentReferences as le}from"./attachment-reference.js";import{getPersonalSyncIdentity as j}from"../personal-sync/epoch.js";import{getDaemonInstallationId as N}from"../personal-sync/identity.js";import{isStewardSessionId as z,pinStewardWorkDir as ge}from"../steward/session.js";import{isTrustedManagerEvent as ce}from"./manager-event-authority.js";import{getQueueSnapshot as me,handleQueueDelete as he,handleQueueEdit as pe,handleQueueGet as fe,handleQueuePromote as Ie}from"./queue-control.js";import{TerminalQueuedChatDispatchError as $,nowIso as J,queueEnvelope as B,queueMessageFromParams as K}from"./queue-message.js";import{purgeQueuedSessionData as je}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as ze}from"./queue-message.js";class Le{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new U(e=>{this.wakeSession(e)});deletions=new G;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,de(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return me({getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:t=>this.broadcast(t)},e)}isImmediateSendAvailable(e){const t=this.opts.getRuntime(),n=t.sessions.get(e);return n?.currentRunId?n.journalRunId?t.runJournal?.get(e,n.journalRunId)?.deliveryMode==="direct":!1:!0}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const t=this.opts.getRuntime(),n=h(),i=new Set,r=new Map;let d=!1;for(const s of e){const a=s.params;if(this.deletions.hasSession(a.sessionId)){delete n.sessions[a.sessionId],d=!0;continue}if(!a.sessionId||!a.text||!a.agentType||!a.workDir)throw new Error("sessionId, text, agentType and workDir are required");const l=K({...j(N()),...a});typeof a.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(a.roomMessageCreatedAt))&&(l.createdAt=new Date(a.roomMessageCreatedAt).toISOString()),l.origin="room",l.managedRoom=s.context,l.trigger={kind:"room_activation",...s.context};const o=n.sessions[a.sessionId]??[],m=Q(o,l),c=l.clientMessageId??l.id,S=x(a.sessionId,c);if(!m&&S.state==="not_found")o.push(l),n.sessions[a.sessionId]=o,r.set(`${l.sessionId}\0${c}`,l),i.add(a.sessionId),d=!0;else if(m&&S.state==="not_found")r.set(`${m.sessionId}\0${c}`,m),i.add(a.sessionId);else if(m&&S.state==="queued")i.add(a.sessionId);else if(m){const I=o.filter(f=>f.id!==m.id);I.length?n.sessions[a.sessionId]=I:delete n.sessions[a.sessionId],d=!0}}d&&k(n);let u;for(const s of i)try{for(const a of r.values())a.sessionId===s&&(W(s,B(a),"queued"),L({sessionId:s,agentType:a.agentType,sessionMode:a.sessionMode,managerConfig:a.managerConfig,workDir:a.workDir,agentSessionId:E(t,a),modelId:a.modelId}));this.logLifecycle("enqueue.persisted",s,{origin:"room",pendingCount:h().sessions[s]?.length??0}),this.broadcast(s),this.wakeSession(s)}catch(a){u=a,this.logLifecycle("enqueue.commit-failed",s,{failureClass:Y(a instanceof Error?a.message:"","canonical_commit_failed")},"error"),this.retries.schedule(s,!0)}if(i.size&&w(t.client),u)throw u}async handleEnqueue(e,t=!1){const n=this.opts.getRuntime(),i=e.params;if(i.scheduledTask&&!t)throw new Error("schedule_source_untrusted");if((i.managerEventId||i.managerEventRoomOrigin||i.managedWorkerParentSessionId||i.managerWorkerRoomOrigin||e.params.managerWorkerNativeFull||e.params.managedRecoverySource)&&!ce(e))throw new Error("manager_event_source_untrusted");const r=!t&&!i.managedWorkerParentSessionId?n.managerRuntime?.getWorkerControllerSessionId?.(String(i.sessionId??""),String(i.workDir??"")):null,d=r?{...i,managedWorkerParentSessionId:r}:i,u=!t&&(z(String(d.sessionId??""))||d.sessionScope==="steward");if(u){if((d.sessionMode??"standard")!=="standard")throw new Error("steward_session_mode_invalid");if(!z(d.sessionId)&&A().some(q=>q.sessionId===d.sessionId))throw new Error("steward_scope_conflict")}const s=u?{...d,workDir:ge(),sessionMode:"standard"}:d,a=!!(t&&s.scheduledTask?.bindingId);if(te(s.sessionListProjection),!s.sessionId||!s.text||!s.agentType||!s.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const l=b(s.managerEventId?{roomOrigin:s.managerEventRoomOrigin}:null,!!s.managedAgentDirect),o=s.managedAgentDirect||a?await this.prepareManagedAgentDirectTurn?.(s.sessionId,l):null;if((s.managedAgentDirect||a)&&!o)throw new Error("managed_agent_context_unavailable");const m=o?A().find(q=>q.sessionId===s.sessionId):null,c=o?{...s,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId?.startsWith("managed:")?m?.agentSessionId&&!m.agentSessionId.startsWith("managed:")?m.agentSessionId:null:o.agentSessionId,modelId:o.effectiveModelId!==void 0?M(o.effectiveModelId):m?.modelId??void 0,systemPrompt:o.systemPrompt,externalChannel:s.managedAgentDirect?null:s.externalChannel,replyTarget:s.managedAgentDirect?null:s.replyTarget,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:s,S=n.resolvePath(c.workDir),I=le(c.attachments);I?.length&&ne(S,I);const f={text:c.text,attachments:I,localized:!1},T=n.sessions.get(c.sessionId);if(c.agentType==="codex"&&c.agentSessionId&&T?.currentRunId?.startsWith("dispatch:")&&ee(c.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:Z}),!1;o?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const C=await this.isSessionBusy(c.sessionId),y=h(),_=y.sessions[c.sessionId]??[],g=K({...c,text:f.text,attachments:f.attachments,systemPrompt:o?null:c.systemPrompt});o&&(s.managedAgentDirect&&(g.managedAgentDirect=!0),g.trigger?.kind!=="manager_event"&&g.trigger?.kind!=="scheduled"&&(g.trigger={kind:"managed_direct"}));const v=g.clientMessageId??g.id,R=x(c.sessionId,v);if(R.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:R.state==="queued",queueMessageId:g.id,...R,queue:this.getSnapshot(c.sessionId)}}),!0;const D=Q(_,g);D||(y.sessions[c.sessionId]=[..._,g],k(y));const p=D??g;return L({sessionId:p.sessionId,agentType:p.agentType,sessionMode:p.sessionMode,managerConfig:p.managerConfig,workDir:p.workDir,agentSessionId:p.agentSessionId,modelId:p.modelId,...u?{sessionScope:"steward"}:{}}),W(p.sessionId,B(p),"queued"),se(n.resolvePath(p.workDir),p.attachments??[]),w(n.client),this.logLifecycle("enqueue.persisted",c.sessionId,{origin:c.origin??"app",queueMessageId:p.id,pendingCount:(h().sessions[c.sessionId]??[]).length}),this.broadcast(c.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:D?.id??g.id,...x(c.sessionId,D?.clientMessageId??D?.id??g.clientMessageId??g.id),queue:this.getSnapshot(c.sessionId),...f.localized?{localizedAttachments:!0}:{}}}),C?this.retries.schedule(c.sessionId):this.wakeSession(c.sessionId),!0}async handleGet(e){await fe(this.queueControlContext(),e)}async handleEdit(e){await pe(this.queueControlContext(),e)}async handleDelete(e){await he(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await Ie({...this.queueControlContext(),promoting:this.promoting,draining:this.draining,isImmediateSendAvailable:t=>this.isImmediateSendAvailable(t),canInjectActiveBatch:(t,n)=>this.canInjectActiveBatch(t,n),interruptQueuedSession:this.opts.interruptQueuedSession,dispatchQueuedMessages:t=>this.dispatchQueuedMessages(t),markExternalQueued:(t,n)=>this.markExternalQueued(t,n),removeBatch:(t,n)=>this.removeBatch(t,n),wakeSession:t=>this.wakeSession(t)},e)}isDispatching(e){return this.inFlightMessageIds.has(e)}noteTerminal(e){const t=h().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){ue(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const u=h().sessions[e]?.length??0;return this.purgeSession(e),u}const t=h(),n=t.sessions[e]??[],i=this.inFlightMessageIds.get(e)??new Set,r=n.filter(u=>u.managedRoom&&!i.has(u.id));if(r.length===0)return 0;const d=n.filter(u=>!r.includes(u));d.length?t.sessions[e]=d:delete t.sessions[e],k(t);for(const u of r)ie(e,u.clientMessageId??u.id);return w(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:r.length,pendingCount:d.length}),this.broadcast(e),r.length}wakeSession(e){this.drainNext(e).catch(()=>{this.logLifecycle("drain.retry-required",e,{},"error"),this.retries.schedule(e,!0)})}drainIdleQueues(){if(this.disposed)return;const e=h();for(const t of Object.keys(e.sessions))this.wakeSession(t)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let t=!1,n=!1,i=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const o=h().sessions[e]?.length??0,m=this.deferredLogState.get(e),c=Date.now();(!m||m.pendingCount!==o||c-m.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:o}),this.deferredLogState.set(e,{at:c,pendingCount:o}));return}this.deferredLogState.delete(e);const r=h(),d=r.sessions[e]??[],u=d.filter(o=>{const m=o.clientMessageId??o.id,c=x(e,m).state;return c==="queued"||c==="not_found"});if(u.length!==d.length&&(u.length?r.sessions[e]=u:delete r.sessions[e],k(r),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:d.length-u.length,pendingCount:u.length})),u.some(o=>!!o.externalQueuedSubmissionId)){this.broadcast(e);return}const s=P(u);if(s.length===0){this.broadcast(e);return}if(F(s))return;s.some(o=>(o.dispatchBlock?.retryAt??0)>0)&&oe(),i=s,this.inFlightMessageIds.set(e,new Set(s.map(o=>o.id))),this.logLifecycle("dispatch.start",e,{batchCount:s.length,queueMessageId:s[0].id,origin:s[0].origin??"app"}),this.broadcast(e);for(const o of s)re(e,B(o),"queued");const a=await this.dispatchQueuedMessages(s);if(a.deliveryMode==="external_owner_queue"){this.markExternalQueued(s,a.queuedSubmissionId),O(s),s.some(o=>o.dispatchBlock)&&w(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:s.length,queueMessageId:s[0].id}),this.broadcast(e);return}const l=this.removeBatch(e,s);O(s),s.some(o=>o.dispatchBlock)&&w(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:s.length,queueMessageId:s[0].id,pendingCount:l}),this.deferredLogState.delete(e),t=l>0,this.broadcast(e)}catch(r){const d=ae({error:r,sessionId:e,batch:i,publish:()=>w(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,i),log:(u,s)=>this.logLifecycle(u,e,s,"error")});t=d.drainAgain,n=d.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const r=h().sessions[e]??[];r.length?(this.broadcast(e),r.some(d=>!!d.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,F(P(r)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=h(),i=n.sessions[e]??[],r=i.filter(d=>(d.clientMessageId??d.id)!==t);r.length!==i.length&&(r.length?n.sessions[e]=r:delete n.sessions[e],k(n),this.broadcast(e))}canInjectActiveBatch(e,t){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const n=this.opts.getRuntime().runJournal?.get(t[0].sessionId,e.journalRunId),i=t[0].trigger?.kind==="managed_direct"||t[0].managedAgentDirect?null:"personal";return!!(i&&t[0].systemPrompt==null&&n&&n.source===i&&n.deliveryMode==="direct"&&n.agentType===t[0].agentType&&n.workDir===e.workDir&&n.agentSessionId===e.agentSessionId&&n.modelId===(t[0].modelId??null)&&n.reasoningEffort===(t[0].reasoningEffort??null))}removeBatch(e,t){if(t.length===0)return h().sessions[e]?.length??0;const n=h(),i=new Set(t.map(d=>d.id)),r=(n.sessions[e]??[]).filter(d=>!i.has(d.id));return r.length?n.sessions[e]=r:delete n.sessions[e],k(n),r.length}logLifecycle(e,t,n,i="info"){const r=`[chat.queue] ${JSON.stringify({at:J(),event:e,sessionId:t,...n})}`;i==="error"?console.error(r):console.info(r)}async dispatchQueuedMessages(e){const t=e[0],n=t.trigger?.kind==="scheduled"?t.trigger:null;if(n&&await this.validateScheduledTarget?.({sessionId:t.sessionId,...n})!=="ready")throw new $("schedule_target_unavailable");const i=e.flatMap(g=>{if(g.trigger?.kind==="room_activation"){const{kind:v,...R}=g.trigger;return[R]}return!g.trigger&&g.managedRoom?[g.managedRoom]:[]}),r=e.find(g=>g.trigger?.kind==="manager_event")?.trigger,d=e.some(g=>g.trigger?.kind==="managed_direct"||!!g.managedAgentDirect),u=d||!!n?.bindingId,s=e.find(g=>g.trigger?.kind==="manager_worker")?.trigger,a=r?.kind==="manager_event"||d,l=i.length>0?await this.prepareManagedRoomTurn?.(i):u||r?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,b(r?.kind==="manager_event"?r:null,d)):void 0;if(i.length>0&&!l)throw new Error("managed_room_turn_preparer_unavailable");if(u&&!l)throw new Error("managed_agent_context_unavailable");if(r?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!l)throw new Error("managed_agent_context_unavailable");const o=new Set((h().sessions[t.sessionId]??[]).map(g=>g.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(g=>!o.has(g.id)))throw l?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(l.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new $("queued_dispatch_cancelled");const m=l??null,c=m?.sessionMode==="manager"?m.managerConfig:null,S=e.length===1?t.text:V(e),I=X(e.flatMap(g=>g.attachments??[])),f=u||r?.kind==="manager_event"&&!!l,T=f?l.agentSessionId?.startsWith("managed:")?E(this.opts.getRuntime(),t):l.agentSessionId:i.length>0?E(this.opts.getRuntime(),t):t.agentSessionId??null,C=l?A().find(g=>g.sessionId===t.sessionId):null,y=l?.effectiveModelId!==void 0?M(l.effectiveModelId):M(C?.modelId)??M(t.modelId),_=l?.effectiveModelId!==void 0?"room_effective_model":M(C?.modelId)?"persisted_session_model":M(t.modelId)?"queued_message_model":"pi_default_model";return await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${t.id}-${Date.now()}`,method:"chat.send",params:{...j(N()),sessionId:t.sessionId,text:S,agentType:f?l.agentType:t.agentType,sessionMode:m?.sessionMode??t.sessionMode,managerConfig:m?c:t.managerConfig,workDir:f?l.workDir:t.workDir,agentSessionId:T,modelId:y,modelSelectionSource:_,systemPrompt:l?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:m?m.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:m?m.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:I,externalChannel:a?void 0:t.externalChannel,replyTarget:a?void 0:t.replyTarget,roomContextRegistryKey:a?void 0:l?.roomContextRegistryKey,activationCauseMessageId:a?void 0:i.at(-1)?.causeMessageId,rootCauseMessageId:a?void 0:i.at(-1)?.rootCauseMessageId,activationSequence:a?void 0:i.at(-1)?.sequence,activationHopCount:a?void 0:i.at(-1)?.hopCount,managedRecoverySource:r?.kind==="manager_event"?"manager_event":u?"managed_direct":i.length>0?"managed_room":void 0,managerEventId:r?.kind==="manager_event"?r.eventId:void 0,managedWorkerParentSessionId:s?.kind==="manager_worker"?s.parentSessionId:void 0,managerWorkerRoomOrigin:s?.kind==="manager_worker"?s.roomOrigin:void 0,managerWorkerNativeFull:s?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(s.parentSessionId,t.workDir)||void 0,managedRoomContextToken:l?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:i.length>0||!!n||void 0,queuedBatchItems:e.map(g=>{const v=H(g);return a?{...v,systemPrompt:l?.systemPrompt??null,externalChannel:null,replyTarget:null}:v}),waitForDispatch:!0}},l??void 0)??{}}markExternalQueued(e,t){const n=h(),i=new Set(e.map(u=>u.id)),r=n.sessions[e[0].sessionId]??[];let d=!1;for(const u of r)i.has(u.id)&&(u.externalQueuedSubmissionId=t||u.id,u.updatedAt=J(),d=!0);d&&k(n)}async isSessionBusy(e){const t=this.opts.getRuntime().recoveryBarrier;if(t?.isDispatchFrozen()||t?.isRecovering(e))return!0;const n=this.opts.getRuntime().sessions.get(e);if(!n)return!1;if(n.currentRunId){if(!(n.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!n.journalRunId)||(n.adapter.getStatus?await n.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:n.currentRunId}),n.currentRunId=null,n.currentRunPhase=null}if(!n.adapter.getStatus)return!1;const i=await n.adapter.getStatus().catch(()=>null);return i?.active?(i.runId&&(n.currentRunId=i.runId,n.currentRunPhase=i.runPhase??n.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{Le as ChatQueueManager,ze as TerminalQueuedChatDispatchError,je as purgeQueuedSessionData};
|
|
1
|
+
import{NativeSourceDeletionStore as K}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as G}from"./queue-retry.js";import{findDuplicateQueuedMessage as P,stripLocalQueueFields as H,takeCompatibleBatch as b,formatQueuedBatch as V,dedupeQueuedAttachments as X,classifyQueueError as Y,normalizeQueuedModelId as k,resolveManagedRoomNativeSessionId as E,managedDirectTurnOptions as W}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as Z}from"@shennian/wire";import{isCodexThreadTailInterrupted as ee}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as te}from"./projection.js";import{assertFinishedAttachmentReferences as ne,markAttachmentReferences as se}from"./attachment-transfer-store.js";import{appendMessage as F,getMessageDeliveryStatus as x,listSessionRecords as A,recordSession as L,tombstoneMessage as ie,upsertMessage as re}from"./store.js";import{handleQueueDispatchFailure as ae,queueBlockedUntil as O,resolveQueueRecoveryNotice as j}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as oe}from"../agents/command-spec.js";import{requestSessionIndexPublish as y}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as de,purgeQueuedSessionData as ue,readQueue as h,writeQueue as w}from"./queue-storage.js";import{parsePersonalAttachmentReferences as le}from"./attachment-reference.js";import{getPersonalSyncIdentity as N}from"../personal-sync/epoch.js";import{getDaemonInstallationId as z}from"../personal-sync/identity.js";import{isStewardSessionId as B,pinStewardWorkDir as ge}from"../steward/session.js";import{classifyStewardFailure as ce}from"../steward/failover.js";import{tryStewardFailover as me}from"./handlers/steward.js";import{isTrustedManagerEvent as he}from"./manager-event-authority.js";import{getQueueSnapshot as pe,handleQueueDelete as fe,handleQueueEdit as Ie,handleQueueGet as Se,handleQueuePromote as we}from"./queue-control.js";import{TerminalQueuedChatDispatchError as $,nowIso as J,queueEnvelope as Q,queueMessageFromParams as U}from"./queue-message.js";import{purgeQueuedSessionData as Je}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as Ke}from"./queue-message.js";class Ne{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new G(e=>{this.wakeSession(e)});deletions=new K;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,de(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return pe({getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:t=>this.broadcast(t)},e)}async switchUnavailableSteward(e,t,n){const i=n instanceof Error?n.message:String(n);return ce(i)==="crashed"||!t.text?!1:me(this.opts.getRuntime(),e,{agentType:t.agentType},{state:"error",runId:"",message:i},t.text).catch(()=>!1)}isImmediateSendAvailable(e){const t=this.opts.getRuntime(),n=t.sessions.get(e);return n?.currentRunId?n.journalRunId?t.runJournal?.get(e,n.journalRunId)?.deliveryMode==="direct":!1:!0}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const t=this.opts.getRuntime(),n=h(),i=new Set,r=new Map;let d=!1;for(const s of e){const a=s.params;if(this.deletions.hasSession(a.sessionId)){delete n.sessions[a.sessionId],d=!0;continue}if(!a.sessionId||!a.text||!a.agentType||!a.workDir)throw new Error("sessionId, text, agentType and workDir are required");const l=U({...N(z()),...a});typeof a.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(a.roomMessageCreatedAt))&&(l.createdAt=new Date(a.roomMessageCreatedAt).toISOString()),l.origin="room",l.managedRoom=s.context,l.trigger={kind:"room_activation",...s.context};const o=n.sessions[a.sessionId]??[],m=P(o,l),c=l.clientMessageId??l.id,S=x(a.sessionId,c);if(!m&&S.state==="not_found")o.push(l),n.sessions[a.sessionId]=o,r.set(`${l.sessionId}\0${c}`,l),i.add(a.sessionId),d=!0;else if(m&&S.state==="not_found")r.set(`${m.sessionId}\0${c}`,m),i.add(a.sessionId);else if(m&&S.state==="queued")i.add(a.sessionId);else if(m){const I=o.filter(f=>f.id!==m.id);I.length?n.sessions[a.sessionId]=I:delete n.sessions[a.sessionId],d=!0}}d&&w(n);let u;for(const s of i)try{for(const a of r.values())a.sessionId===s&&(F(s,Q(a),"queued"),L({sessionId:s,agentType:a.agentType,sessionMode:a.sessionMode,managerConfig:a.managerConfig,workDir:a.workDir,agentSessionId:E(t,a),modelId:a.modelId}));this.logLifecycle("enqueue.persisted",s,{origin:"room",pendingCount:h().sessions[s]?.length??0}),this.broadcast(s),this.wakeSession(s)}catch(a){u=a,this.logLifecycle("enqueue.commit-failed",s,{failureClass:Y(a instanceof Error?a.message:"","canonical_commit_failed")},"error"),this.retries.schedule(s,!0)}if(i.size&&y(t.client),u)throw u}async handleEnqueue(e,t=!1){const n=this.opts.getRuntime(),i=e.params;if(i.scheduledTask&&!t)throw new Error("schedule_source_untrusted");if((i.managerEventId||i.managerEventRoomOrigin||i.managedWorkerParentSessionId||i.managerWorkerRoomOrigin||e.params.managerWorkerNativeFull||e.params.managedRecoverySource)&&!he(e))throw new Error("manager_event_source_untrusted");const r=!t&&!i.managedWorkerParentSessionId?n.managerRuntime?.getWorkerControllerSessionId?.(String(i.sessionId??""),String(i.workDir??"")):null,d=r?{...i,managedWorkerParentSessionId:r}:i,u=!t&&(B(String(d.sessionId??""))||d.sessionScope==="steward");if(u){if((d.sessionMode??"standard")!=="standard")throw new Error("steward_session_mode_invalid");if(!B(d.sessionId)&&A().some(q=>q.sessionId===d.sessionId))throw new Error("steward_scope_conflict")}const s=u?{...d,workDir:ge(),sessionMode:"standard"}:d,a=!!(t&&s.scheduledTask?.bindingId);if(te(s.sessionListProjection),!s.sessionId||!s.text||!s.agentType||!s.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const l=W(s.managerEventId?{roomOrigin:s.managerEventRoomOrigin}:null,!!s.managedAgentDirect),o=s.managedAgentDirect||a?await this.prepareManagedAgentDirectTurn?.(s.sessionId,l):null;if((s.managedAgentDirect||a)&&!o)throw new Error("managed_agent_context_unavailable");const m=o?A().find(q=>q.sessionId===s.sessionId):null,c=o?{...s,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId?.startsWith("managed:")?m?.agentSessionId&&!m.agentSessionId.startsWith("managed:")?m.agentSessionId:null:o.agentSessionId,modelId:o.effectiveModelId!==void 0?k(o.effectiveModelId):m?.modelId??void 0,systemPrompt:o.systemPrompt,externalChannel:s.managedAgentDirect?null:s.externalChannel,replyTarget:s.managedAgentDirect?null:s.replyTarget,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:s,S=n.resolvePath(c.workDir),I=le(c.attachments);I?.length&&ne(S,I);const f={text:c.text,attachments:I,localized:!1},T=n.sessions.get(c.sessionId);if(c.agentType==="codex"&&c.agentSessionId&&T?.currentRunId?.startsWith("dispatch:")&&ee(c.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:Z}),!1;o?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const C=await this.isSessionBusy(c.sessionId),M=h(),_=M.sessions[c.sessionId]??[],g=U({...c,text:f.text,attachments:f.attachments,systemPrompt:o?null:c.systemPrompt});o&&(s.managedAgentDirect&&(g.managedAgentDirect=!0),g.trigger?.kind!=="manager_event"&&g.trigger?.kind!=="scheduled"&&(g.trigger={kind:"managed_direct"}));const v=g.clientMessageId??g.id,R=x(c.sessionId,v);if(R.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:R.state==="queued",queueMessageId:g.id,...R,queue:this.getSnapshot(c.sessionId)}}),!0;const D=P(_,g);D||(M.sessions[c.sessionId]=[..._,g],w(M));const p=D??g;return L({sessionId:p.sessionId,agentType:p.agentType,sessionMode:p.sessionMode,managerConfig:p.managerConfig,workDir:p.workDir,agentSessionId:p.agentSessionId,modelId:p.modelId,...u?{sessionScope:"steward"}:{}}),F(p.sessionId,Q(p),"queued"),se(n.resolvePath(p.workDir),p.attachments??[]),y(n.client),this.logLifecycle("enqueue.persisted",c.sessionId,{origin:c.origin??"app",queueMessageId:p.id,pendingCount:(h().sessions[c.sessionId]??[]).length}),this.broadcast(c.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:D?.id??g.id,...x(c.sessionId,D?.clientMessageId??D?.id??g.clientMessageId??g.id),queue:this.getSnapshot(c.sessionId),...f.localized?{localizedAttachments:!0}:{}}}),C?this.retries.schedule(c.sessionId):this.wakeSession(c.sessionId),!0}async handleGet(e){await Se(this.queueControlContext(),e)}async handleEdit(e){await Ie(this.queueControlContext(),e)}async handleDelete(e){await fe(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await we({...this.queueControlContext(),promoting:this.promoting,draining:this.draining,isImmediateSendAvailable:t=>this.isImmediateSendAvailable(t),canInjectActiveBatch:(t,n)=>this.canInjectActiveBatch(t,n),interruptQueuedSession:this.opts.interruptQueuedSession,dispatchQueuedMessages:t=>this.dispatchQueuedMessages(t),markExternalQueued:(t,n)=>this.markExternalQueued(t,n),removeBatch:(t,n)=>this.removeBatch(t,n),wakeSession:t=>this.wakeSession(t)},e)}isDispatching(e){return this.inFlightMessageIds.has(e)}noteTerminal(e){const t=h().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){ue(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const u=h().sessions[e]?.length??0;return this.purgeSession(e),u}const t=h(),n=t.sessions[e]??[],i=this.inFlightMessageIds.get(e)??new Set,r=n.filter(u=>u.managedRoom&&!i.has(u.id));if(r.length===0)return 0;const d=n.filter(u=>!r.includes(u));d.length?t.sessions[e]=d:delete t.sessions[e],w(t);for(const u of r)ie(e,u.clientMessageId??u.id);return y(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:r.length,pendingCount:d.length}),this.broadcast(e),r.length}wakeSession(e){this.drainNext(e).catch(()=>{this.logLifecycle("drain.retry-required",e,{},"error"),this.retries.schedule(e,!0)})}drainIdleQueues(){if(this.disposed)return;const e=h();for(const t of Object.keys(e.sessions))this.wakeSession(t)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let t=!1,n=!1,i=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const o=h().sessions[e]?.length??0,m=this.deferredLogState.get(e),c=Date.now();(!m||m.pendingCount!==o||c-m.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:o}),this.deferredLogState.set(e,{at:c,pendingCount:o}));return}this.deferredLogState.delete(e);const r=h(),d=r.sessions[e]??[],u=d.filter(o=>{const m=o.clientMessageId??o.id,c=x(e,m).state;return c==="queued"||c==="not_found"});if(u.length!==d.length&&(u.length?r.sessions[e]=u:delete r.sessions[e],w(r),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:d.length-u.length,pendingCount:u.length})),u.some(o=>!!o.externalQueuedSubmissionId)){this.broadcast(e);return}const s=b(u);if(s.length===0){this.broadcast(e);return}if(O(s))return;s.some(o=>(o.dispatchBlock?.retryAt??0)>0)&&oe(),i=s,this.inFlightMessageIds.set(e,new Set(s.map(o=>o.id))),this.logLifecycle("dispatch.start",e,{batchCount:s.length,queueMessageId:s[0].id,origin:s[0].origin??"app"}),this.broadcast(e);for(const o of s)re(e,Q(o),"queued");const a=await this.dispatchQueuedMessages(s);if(a.deliveryMode==="external_owner_queue"){this.markExternalQueued(s,a.queuedSubmissionId),j(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:s.length,queueMessageId:s[0].id}),this.broadcast(e);return}const l=this.removeBatch(e,s);j(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:s.length,queueMessageId:s[0].id,pendingCount:l}),this.deferredLogState.delete(e),t=l>0,this.broadcast(e)}catch(r){const d=i[0];if(d&&B(e)&&await this.switchUnavailableSteward(e,d,r)){this.removeBatch(e,i),this.broadcast(e);return}const u=ae({error:r,sessionId:e,batch:i,publish:()=>y(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,i),log:(s,a)=>this.logLifecycle(s,e,a,"error")});t=u.drainAgain,n=u.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const r=h().sessions[e]??[];r.length?(this.broadcast(e),r.some(d=>!!d.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,O(b(r)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=h(),i=n.sessions[e]??[],r=i.filter(d=>(d.clientMessageId??d.id)!==t);r.length!==i.length&&(r.length?n.sessions[e]=r:delete n.sessions[e],w(n),this.broadcast(e))}canInjectActiveBatch(e,t){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const n=this.opts.getRuntime().runJournal?.get(t[0].sessionId,e.journalRunId),i=t[0].trigger?.kind==="managed_direct"||t[0].managedAgentDirect?null:"personal";return!!(i&&t[0].systemPrompt==null&&n&&n.source===i&&n.deliveryMode==="direct"&&n.agentType===t[0].agentType&&n.workDir===e.workDir&&n.agentSessionId===e.agentSessionId&&n.modelId===(t[0].modelId??null)&&n.reasoningEffort===(t[0].reasoningEffort??null))}removeBatch(e,t){if(t.length===0)return h().sessions[e]?.length??0;const n=h(),i=new Set(t.map(d=>d.id)),r=(n.sessions[e]??[]).filter(d=>!i.has(d.id));return r.length?n.sessions[e]=r:delete n.sessions[e],w(n),r.length}logLifecycle(e,t,n,i="info"){const r=`[chat.queue] ${JSON.stringify({at:J(),event:e,sessionId:t,...n})}`;i==="error"?console.error(r):console.info(r)}async dispatchQueuedMessages(e){const t=e[0],n=t.trigger?.kind==="scheduled"?t.trigger:null;if(n&&await this.validateScheduledTarget?.({sessionId:t.sessionId,...n})!=="ready")throw new $("schedule_target_unavailable");const i=e.flatMap(g=>{if(g.trigger?.kind==="room_activation"){const{kind:v,...R}=g.trigger;return[R]}return!g.trigger&&g.managedRoom?[g.managedRoom]:[]}),r=e.find(g=>g.trigger?.kind==="manager_event")?.trigger,d=e.some(g=>g.trigger?.kind==="managed_direct"||!!g.managedAgentDirect),u=d||!!n?.bindingId,s=e.find(g=>g.trigger?.kind==="manager_worker")?.trigger,a=r?.kind==="manager_event"||d,l=i.length>0?await this.prepareManagedRoomTurn?.(i):u||r?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,W(r?.kind==="manager_event"?r:null,d)):void 0;if(i.length>0&&!l)throw new Error("managed_room_turn_preparer_unavailable");if(u&&!l)throw new Error("managed_agent_context_unavailable");if(r?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!l)throw new Error("managed_agent_context_unavailable");const o=new Set((h().sessions[t.sessionId]??[]).map(g=>g.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(g=>!o.has(g.id)))throw l?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(l.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new $("queued_dispatch_cancelled");const m=l??null,c=m?.sessionMode==="manager"?m.managerConfig:null,S=e.length===1?t.text:V(e),I=X(e.flatMap(g=>g.attachments??[])),f=u||r?.kind==="manager_event"&&!!l,T=f?l.agentSessionId?.startsWith("managed:")?E(this.opts.getRuntime(),t):l.agentSessionId:i.length>0?E(this.opts.getRuntime(),t):t.agentSessionId??null,C=l?A().find(g=>g.sessionId===t.sessionId):null,M=l?.effectiveModelId!==void 0?k(l.effectiveModelId):k(C?.modelId)??k(t.modelId),_=l?.effectiveModelId!==void 0?"room_effective_model":k(C?.modelId)?"persisted_session_model":k(t.modelId)?"queued_message_model":"pi_default_model";return await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${t.id}-${Date.now()}`,method:"chat.send",params:{...N(z()),sessionId:t.sessionId,text:S,agentType:f?l.agentType:t.agentType,sessionMode:m?.sessionMode??t.sessionMode,managerConfig:m?c:t.managerConfig,workDir:f?l.workDir:t.workDir,agentSessionId:T,modelId:M,modelSelectionSource:_,systemPrompt:l?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:m?m.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:m?m.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:I,externalChannel:a?void 0:t.externalChannel,replyTarget:a?void 0:t.replyTarget,roomContextRegistryKey:a?void 0:l?.roomContextRegistryKey,activationCauseMessageId:a?void 0:i.at(-1)?.causeMessageId,rootCauseMessageId:a?void 0:i.at(-1)?.rootCauseMessageId,activationSequence:a?void 0:i.at(-1)?.sequence,activationHopCount:a?void 0:i.at(-1)?.hopCount,managedRecoverySource:r?.kind==="manager_event"?"manager_event":u?"managed_direct":i.length>0?"managed_room":void 0,managerEventId:r?.kind==="manager_event"?r.eventId:void 0,managedWorkerParentSessionId:s?.kind==="manager_worker"?s.parentSessionId:void 0,managerWorkerRoomOrigin:s?.kind==="manager_worker"?s.roomOrigin:void 0,managerWorkerNativeFull:s?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(s.parentSessionId,t.workDir)||void 0,managedRoomContextToken:l?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:i.length>0||!!n||void 0,queuedBatchItems:e.map(g=>{const v=H(g);return a?{...v,systemPrompt:l?.systemPrompt??null,externalChannel:null,replyTarget:null}:v}),waitForDispatch:!0}},l??void 0)??{}}markExternalQueued(e,t){const n=h(),i=new Set(e.map(u=>u.id)),r=n.sessions[e[0].sessionId]??[];let d=!1;for(const u of r)i.has(u.id)&&(u.externalQueuedSubmissionId=t||u.id,u.updatedAt=J(),d=!0);d&&w(n)}async isSessionBusy(e){const t=this.opts.getRuntime().recoveryBarrier;if(t?.isDispatchFrozen()||t?.isRecovering(e))return!0;const n=this.opts.getRuntime().sessions.get(e);if(!n)return!1;if(n.currentRunId){if(!(n.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!n.journalRunId)||(n.adapter.getStatus?await n.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:n.currentRunId}),n.currentRunId=null,n.currentRunPhase=null}if(!n.adapter.getStatus)return!1;const i=await n.adapter.getStatus().catch(()=>null);return i?.active?(i.runId&&(n.currentRunId=i.runId,n.currentRunPhase=i.runPhase??n.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{Ne as ChatQueueManager,Ke as TerminalQueuedChatDispatchError,Je as purgeQueuedSessionData};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{SESSION_SYNC_DATA_EPOCH as I,SESSION_SYNC_PROTOCOL_VERSION as p,SESSION_TITLE_SOURCE_PRIORITY as A,isInternalSession as C,isToolPayload as h,parseStewardSayPayload as L,sessionPreviewFromPayload as D}from"@shennian/wire";import _ from"node:crypto";import u from"node:fs";import{renameSyncWithRetry as q}from"../fs/atomic-rename.js";import w from"node:path";import{NativeSourceDeletionStore as j}from"../native-fusion/native-source-deletions.js";import{registerInternalNativeSource as W}from"../native-fusion/source-visibility.js";import{getDaemonInstallationId as S}from"../personal-sync/identity.js";import{PERSONAL_SYNC_V1_ROOT_NAME as F,resolvePersonalSyncV1Path as $}from"../personal-sync/paths.js";import{CanonicalSessionStore as Q}from"./canonical-store.js";const k=120;function R(t){if(t.length<=k)return t;let e=t.slice(0,k);const n=e.charCodeAt(e.length-1);return n>=55296&&n<=56319&&(e=e.slice(0,-1)),e}let M=null,T=null;function b(){return $()}function c(){const t=w.join(b(),"canonical");return(!M||T!==t)&&(M=new Q(t,S()),T=t),M}function N(){return w.join(b(),"session-index.json")}function d(){const t=N();if(!u.existsSync(t))return{};const e=JSON.parse(u.readFileSync(t,"utf8"));if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`invalid personal session index: ${t}`);const n=S();for(const s of Object.values(e))if(s.daemonInstallationId!==n)throw new Error(`personal session index belongs to another daemon installation: ${t}`);return e}function g(t){ee(N(),t)}function E(t){return D(t.payload,120)}function x(t){if(new j({rootDir:b(),daemonInstallationId:S()}).hasSession(t))throw new Error(`session_deleted:${t}`)}function Y(t){x(t.sessionId),S();const e=d(),n=e[t.sessionId],s=new Date().toISOString(),i=c().getManifest(t.sessionId)?.bodyRevision??n?.bodyRevision??0,o=c().getManifest(t.sessionId),a=Z(n,t),l=t.attentionId?.trim()||null,r=Array.from(new Set([...n?.seenAttentionIds??[],...n?.lastAttentionId?[n.lastAttentionId]:[]])),f=!!(l&&!r.includes(l)),v=t.lastMessagePreview===null?{preview:null,messageId:null,at:null}:t.lastMessagePreview!==void 0&&t.lastMessagePreviewMessageId&&t.lastMessagePreviewAt?{preview:t.lastMessagePreview,messageId:t.lastMessagePreviewMessageId,at:t.lastMessagePreviewAt}:{preview:n?.lastMessagePreview??null,messageId:n?.lastMessagePreviewMessageId??null,at:n?.lastMessagePreviewAt??null},y=Date.parse(t.lastVisibleEventAt??""),O=Date.parse(n?.lastVisibleEventAt??""),G=Number.isFinite(y)&&(!Number.isFinite(O)||y>=O)?t.lastVisibleEventAt:n?.lastVisibleEventAt??null,P=n?n.sessionScope==="steward"?"steward":"personal":t.sessionScope==="steward"?"steward":"personal",m={daemonInstallationId:S(),sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:P,nativeSessionVisibility:C({...n,id:t.sessionId})||C({...n,...t,id:t.sessionId,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:P})?"internal":"user",managerConfig:t.managerConfig??n?.managerConfig??null,workDir:t.workDir,agentSessionId:t.agentSessionId??n?.agentSessionId??null,modelId:t.modelId??n?.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType??n?.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId??n?.managerDefaultWorkerModelId??null,status:t.status??n?.status??"active",createdAt:n?.createdAt??s,updatedAt:s,lastActivityAt:t.lastActivityAt??n?.lastActivityAt??s,lastMessagePreview:v.preview,lastMessagePreviewMessageId:v.messageId,lastMessagePreviewAt:v.at,lastVisibleEventAt:G,localReady:n?.localReady===!0||t.localReady===!0,firstUserMessageId:n?.firstUserMessageId??t.firstUserMessageId??null,firstUserBodyRevision:n?.firstUserBodyRevision??t.firstUserBodyRevision??null,bodyRevision:i,indexRevision:(n?.indexRevision??0)+1,...a,firstAvailableSeq:o?.firstAvailableSeq??n?.firstAvailableSeq??null,visibleMessageCount:o?.visibleMessageCount??n?.visibleMessageCount??0,lastVisibleMessageId:o?.lastVisibleMessageId??n?.lastVisibleMessageId??null,attentionCount:(n?.attentionCount??0)+(f?1:0),lastAttentionId:f?l:n?.lastAttentionId??null,seenAttentionIds:f&&l?[...r,l]:r,lastBodyCommittedAt:o?.lastBodyCommittedAt??n?.lastBodyCommittedAt??null,deletionRevision:n?.deletionRevision??0,deletedAt:t.deletedAt??n?.deletedAt??null,syncedIndexRevision:n?.syncedIndexRevision??0,indexSyncState:"pending",indexSyncStateRevision:(n?.indexRevision??0)+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,titleGenerationAttemptedAt:n?.titleGenerationAttemptedAt&&n.titleGenerationNextAttemptAt!==void 0?n.titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:n?.titleGenerationNextAttemptAt??null,titleGenerationAttempts:n?.titleGenerationAttempts??0};return m.nativeSessionVisibility==="internal"&&m.agentSessionId&&W(m.sessionId,m.agentType,m.agentSessionId),e[t.sessionId]=m,g(e),m}function z(){return Object.values(d())}function ue(t){if(!t)throw new Error("sessionId is required");const e=d();e[t]&&(delete e[t],g(e))}function Se(t){c().purgeSession(t)}function J(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){const o=R(i.title);if(o===i.title)continue;const a=i.indexRevision+1;t[s]={...i,title:o,indexRevision:a,indexSyncState:"pending",indexSyncStateRevision:a,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,updatedAt:n},e=!0}e&&g(t)}function ge(){const t=S();return K(),X(),J(),z().filter(e=>{const n=e.indexSyncStateRevision===e.indexRevision;return e.indexQuarantineCode||n&&(e.indexSyncState==="quarantined"||e.indexSyncState==="terminal")||n&&e.indexSyncNextAttemptAt&&Date.parse(e.indexSyncNextAttemptAt)>Date.now()?!1:e.indexRevision>e.syncedIndexRevision&&e.localReady&&!!e.firstUserMessageId&&e.firstUserBodyRevision!=null}).sort((e,n)=>e.indexRevision-n.indexRevision).map(e=>{const n=!!(e.lastMessagePreview&&e.lastMessagePreviewMessageId&&e.lastMessagePreviewAt);return{protocolVersion:p,dataEpoch:I,daemonInstallationId:t,session:{id:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,nativeSessionVisibility:e.nativeSessionVisibility,...e.sessionScope==="steward"?{sessionScope:"steward"}:{},managerConfig:e.managerConfig,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,managerDefaultWorkerAgentType:e.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:e.managerDefaultWorkerModelId??null,title:e.title,titleSource:e.titleSource,titleRevision:e.titleRevision,titleLockedByUser:e.titleLockedByUser,titleOriginEventId:e.titleOriginEventId,status:e.status??"active",workDir:e.workDir,lastMessagePreview:n?e.lastMessagePreview:null,lastMessagePreviewMessageId:n?e.lastMessagePreviewMessageId:null,lastMessagePreviewAt:n?e.lastMessagePreviewAt:null,lastVisibleEventAt:e.lastVisibleEventAt??e.lastMessagePreviewAt??null,bodyStorageMode:"machine_local",localReady:!0,firstUserBoundary:{role:"user",messageId:e.firstUserMessageId,bodyRevision:e.firstUserBodyRevision},bodyRevision:e.bodyRevision,indexRevision:e.indexRevision,firstAvailableSeq:e.firstAvailableSeq,visibleMessageCount:e.visibleMessageCount,lastVisibleMessageId:e.lastVisibleMessageId,attentionCount:e.attentionCount??0,lastAttentionId:e.lastAttentionId??null,lastBodyCommittedAt:e.lastBodyCommittedAt,deletionRevision:e.deletionRevision,lastActivityAt:e.lastActivityAt,createdAt:e.createdAt,updatedAt:e.updatedAt,deletedAt:e.deletedAt}}})}function fe(t,e){const n=d(),s=n[t];if(!(!s||e<=s.syncedIndexRevision)){if(e>s.indexRevision)throw new Error(`cannot acknowledge future index revision ${e} for ${t}`);n[t]={...s,syncedIndexRevision:e,indexSyncState:"applied",indexSyncStateRevision:e,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null},g(n)}}function ve(){const t=d();let e=0;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(i.deletedAt||i.indexQuarantineCode||!i.localReady)continue;const o=i.indexRevision+1;t[s]={...i,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e+=1}return e>0&&g(t),e}function me(t){const e=d(),n=e[t.sessionId];if(!n||n.indexRevision!==t.indexRevision)return"terminal";const i=(n.indexSyncStateRevision===t.indexRevision?n.indexSyncAttempts??0:0)+1;let o=t.disposition;o==="retry"&&i>=(t.maxAttempts??8)&&(o="terminal");const a=t.now??Date.now(),l=Math.min(5e3*2**Math.max(0,i-1),360*60*1e3),r=Math.round(l*.2*(Math.random()*2-1));return e[t.sessionId]={...n,indexSyncState:o==="retry"?"pending":o,indexSyncStateRevision:t.indexRevision,indexSyncAttempts:i,indexSyncNextAttemptAt:o==="retry"?new Date(a+l+r).toISOString():null,indexSyncErrorCode:t.code,indexQuarantineCode:o==="quarantined"?t.code:n.indexQuarantineCode??null},g(e),o}const H=2*6e4;function ye(t=Date.now(),e=H){const n=d(),s=[],i=new Date(t).toISOString();for(const o of Object.values(n)){if(o.titleSource!=="first_user_fallback"||o.titleLockedByUser||o.titleGenerationAttemptedAt||!o.title.trim()||o.syncedIndexRevision<o.indexRevision||o.titleGenerationNextAttemptAt&&Date.parse(o.titleGenerationNextAttemptAt)>t)continue;const a=o.status==="completed"||o.status==="failed",l=o.visibleMessageCount>=2;let r=null;if(o.agentType==="claude"&&l?r="agent_native_unavailable":a?r="terminal":l&&t-Date.parse(o.createdAt)>=e&&(r="grace_elapsed"),!r)continue;const f=D(o.title,240);if(!f)continue;const v=_.randomUUID();n[o.sessionId]={...o,titleGenerationAttemptedAt:i,titleGenerationNextAttemptAt:null,titleGenerationAttempts:(o.titleGenerationAttempts??0)+1},s.push({sessionId:o.sessionId,requestId:v,titleSeed:f,baseTitleRevision:o.titleRevision,eligibility:r})}return s.length>0&&g(n),s}function Ae(t,e=Date.now()){const n=d(),s=n[t];if(!s?.titleGenerationAttemptedAt||s.titleSource!=="first_user_fallback")return null;const i=Math.max(1,s.titleGenerationAttempts??1),o=Math.min(10*6e4,3e4*2**Math.min(i-1,5)),a=new Date(e+o).toISOString();return n[t]={...s,titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:a},g(n),a}function xe(t,e){const s=d()[t];return!s||s.titleLockedByUser||A[s.titleSource]>=A.shennian_generated||e.titleRevision<=s.titleRevision?!1:(Y({sessionId:t,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:s.agentSessionId,modelId:s.modelId,status:s.status,title:e.title,titleSource:"shennian_generated",titleRevision:e.titleRevision,titleLockedByUser:!1,titleOriginEventId:e.titleOriginEventId}),!0)}function Ie(t,e,n){x(t),S();const s=c().append(t,e,n);return V(t,e,s.bodyRevision),s.bodyRevision}function pe(t,e,n){x(t),S();const s=c().upsert(t,e,n);return V(t,e,s.bodyRevision),s.bodyRevision}function we(t,e){const n=c().getMessageState(t,e);return!n||n.tombstoned||!n.message||!n.deliveryState?{protocolVersion:p,dataEpoch:I,daemonInstallationId:S(),state:"not_found",sessionId:t,clientMessageId:e}:{protocolVersion:p,dataEpoch:I,daemonInstallationId:S(),state:n.deliveryState,sessionId:t,clientMessageId:e,messageId:n.message.id,deliveryState:n.deliveryState,bodyRevision:n.lastRevision,committedAt:new Date(n.message.ts).toISOString()}}function Re(t,e){x(t),S();const n=c().tombstone(t,e),s=d(),i=s[t];if(i){const o=e===i.lastMessagePreviewMessageId?B(t):{preview:i.lastMessagePreview??null,messageId:i.lastMessagePreviewMessageId??null,at:i.lastMessagePreviewAt??null};s[t]={...i,bodyRevision:n.bodyRevision,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,lastVisibleEventAt:U(t)},g(s)}return n.bodyRevision}function V(t,e,n){const s=d(),i=s[t];if(!i)return;const a=i.sessionScope==="steward"&&e.role==="agent"&&!L(e.payload)?null:E(e),l=a?{lastMessagePreview:a,lastMessagePreviewMessageId:e.id,lastMessagePreviewAt:new Date(e.ts).toISOString()}:null,r=a||h(e.payload)?new Date(e.ts).toISOString():i.lastVisibleEventAt,f=c().getManifest(t),v=e.role==="user"&&a&&!i.title?{title:R(a),titleSource:"first_user_fallback",titleRevision:i.titleRevision+1,titleLockedByUser:!1,titleOriginEventId:e.id}:null,y=e.role==="user"&&!i.localReady?{localReady:!0,firstUserMessageId:e.id,firstUserBodyRevision:n}:null;s[t]={...i,...v??{},...y??{},bodyRevision:n,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastActivityAt:new Date(e.ts).toISOString(),lastVisibleEventAt:r,...l??{},firstAvailableSeq:f?.firstAvailableSeq??i.firstAvailableSeq,visibleMessageCount:f?.visibleMessageCount??i.visibleMessageCount,lastVisibleMessageId:f?.lastVisibleMessageId??i.lastVisibleMessageId,attentionCount:i.attentionCount??0,lastAttentionId:i.lastAttentionId??null,lastBodyCommittedAt:f?.lastBodyCommittedAt??i.lastBodyCommittedAt},g(s)}function B(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s],o=E(i.message);if(o)return{preview:o,messageId:i.message.id,at:new Date(i.message.ts).toISOString()}}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return{preview:null,messageId:null,at:null}}function U(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s].message;if(!(!E(i)&&!h(i.payload)))return new Date(i.ts).toISOString()}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return null}function X(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastVisibleEventAt"))continue;const o=i.indexRevision+1;t[s]={...i,lastVisibleEventAt:U(s)??i.lastMessagePreviewAt??null,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function K(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewMessageId")&&Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewAt"))continue;const o=B(s);t[s]={...i,lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function Z(t,e){const n={title:t?.title??"",titleSource:t?.titleSource??"first_user_fallback",titleRevision:t?.titleRevision??0,titleLockedByUser:t?.titleLockedByUser??!1,titleOriginEventId:t?.titleOriginEventId??null},s=R(e.title?.trim()??"");if(!s)return n;if(!e.titleSource)throw new Error("titleSource is required with title");if(n.title&&n.titleSource==="first_user_fallback"&&e.titleSource==="first_user_fallback")return n;const i=e.titleSource==="shennian_manual";if(e.titleLockedByUser!==void 0&&e.titleLockedByUser!==i)throw new Error("titleLockedByUser conflicts with titleSource");const o=s===n.title&&e.titleSource===n.titleSource,a=e.titleRevision??n.titleRevision+(o?0:1);if(!Number.isSafeInteger(a)||a<0)throw new Error("invalid titleRevision");const l=A[e.titleSource],r=A[n.titleSource];return l<r||a<n.titleRevision||o&&a===n.titleRevision||a===n.titleRevision&&!o?n:{title:s,titleSource:e.titleSource,titleRevision:a,titleLockedByUser:i,titleOriginEventId:e.titleOriginEventId??n.titleOriginEventId}}function Me(t,e){const n=e?.limit&&e.limit>0?Math.min(e.limit,500):500;let i=c().readRecent(t,n).messages;return e?.before!==void 0&&(i=i.filter(o=>o.ts<e.before)),[...i].sort((o,a)=>a.ts-o.ts)}function be(){return c().listSessionIds()}function Ee(){return c()}function ee(t,e){const n=w.dirname(t);u.mkdirSync(n,{recursive:!0,mode:448});const s=`${t}.tmp-${process.pid}-${_.randomBytes(6).toString("hex")}`;let i;try{if(i=u.openSync(s,"wx",384),u.writeFileSync(i,`${JSON.stringify(e,null,2)}
|
|
2
|
-
`,"utf8"),u.fsyncSync(i),u.closeSync(i),i=void 0,
|
|
1
|
+
import{SESSION_SYNC_DATA_EPOCH as R,SESSION_SYNC_PROTOCOL_VERSION as M,SESSION_TITLE_SOURCE_PRIORITY as I,isInternalSession as C,isToolPayload as D,parseStewardSayPayload as q,sessionPreviewFromPayload as _,STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX as T}from"@shennian/wire";import k from"node:crypto";import u from"node:fs";import{renameSyncWithRetry as j}from"../fs/atomic-rename.js";import b from"node:path";import{NativeSourceDeletionStore as W}from"../native-fusion/native-source-deletions.js";import{registerInternalNativeSource as F}from"../native-fusion/source-visibility.js";import{getDaemonInstallationId as S}from"../personal-sync/identity.js";import{PERSONAL_SYNC_V1_ROOT_NAME as $,resolvePersonalSyncV1Path as Q}from"../personal-sync/paths.js";import{CanonicalSessionStore as Y}from"./canonical-store.js";const N=120;function E(t){if(t.length<=N)return t;let e=t.slice(0,N);const n=e.charCodeAt(e.length-1);return n>=55296&&n<=56319&&(e=e.slice(0,-1)),e}let P=null,V=null;function O(){return Q()}function c(){const t=b.join(O(),"canonical");return(!P||V!==t)&&(P=new Y(t,S()),V=t),P}function B(){return b.join(O(),"session-index.json")}function d(){const t=B();if(!u.existsSync(t))return{};const e=JSON.parse(u.readFileSync(t,"utf8"));if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`invalid personal session index: ${t}`);const n=S();for(const s of Object.values(e))if(s.daemonInstallationId!==n)throw new Error(`personal session index belongs to another daemon installation: ${t}`);return e}function g(t){te(B(),t)}function h(t){return _(t.payload,120)}function p(t){if(new W({rootDir:O(),daemonInstallationId:S()}).hasSession(t))throw new Error(`session_deleted:${t}`)}function z(t){p(t.sessionId),S();const e=d(),n=e[t.sessionId],s=new Date().toISOString(),i=c().getManifest(t.sessionId)?.bodyRevision??n?.bodyRevision??0,o=c().getManifest(t.sessionId),a=ee(n,t),r=t.attentionId?.trim()||null,l=Array.from(new Set([...n?.seenAttentionIds??[],...n?.lastAttentionId?[n.lastAttentionId]:[]])),f=!!(r&&!l.includes(r)),v=t.lastMessagePreview===null?{preview:null,messageId:null,at:null}:t.lastMessagePreview!==void 0&&t.lastMessagePreviewMessageId&&t.lastMessagePreviewAt?{preview:t.lastMessagePreview,messageId:t.lastMessagePreviewMessageId,at:t.lastMessagePreviewAt}:{preview:n?.lastMessagePreview??null,messageId:n?.lastMessagePreviewMessageId??null,at:n?.lastMessagePreviewAt??null},A=Date.parse(t.lastVisibleEventAt??""),m=Date.parse(n?.lastVisibleEventAt??""),w=Number.isFinite(A)&&(!Number.isFinite(m)||A>=m)?t.lastVisibleEventAt:n?.lastVisibleEventAt??null,x=n?n.sessionScope==="steward"?"steward":"personal":t.sessionScope==="steward"?"steward":"personal",y={daemonInstallationId:S(),sessionId:t.sessionId,agentType:t.agentType,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x,nativeSessionVisibility:C({...n,id:t.sessionId})||C({...n,...t,id:t.sessionId,sessionMode:t.sessionMode??n?.sessionMode,sessionScope:x})?"internal":"user",managerConfig:t.managerConfig??n?.managerConfig??null,workDir:t.workDir,agentSessionId:t.agentSessionId??n?.agentSessionId??null,modelId:t.modelId??n?.modelId??null,managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType??n?.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:t.managerDefaultWorkerModelId??n?.managerDefaultWorkerModelId??null,status:t.status??n?.status??"active",createdAt:n?.createdAt??s,updatedAt:s,lastActivityAt:t.lastActivityAt??n?.lastActivityAt??s,lastMessagePreview:v.preview,lastMessagePreviewMessageId:v.messageId,lastMessagePreviewAt:v.at,lastVisibleEventAt:w,localReady:n?.localReady===!0||t.localReady===!0,firstUserMessageId:n?.firstUserMessageId??t.firstUserMessageId??null,firstUserBodyRevision:n?.firstUserBodyRevision??t.firstUserBodyRevision??null,bodyRevision:i,indexRevision:(n?.indexRevision??0)+1,...a,firstAvailableSeq:o?.firstAvailableSeq??n?.firstAvailableSeq??null,visibleMessageCount:o?.visibleMessageCount??n?.visibleMessageCount??0,lastVisibleMessageId:o?.lastVisibleMessageId??n?.lastVisibleMessageId??null,attentionCount:(n?.attentionCount??0)+(f?1:0),lastAttentionId:f?r:n?.lastAttentionId??null,seenAttentionIds:f&&r?[...l,r]:l,lastBodyCommittedAt:o?.lastBodyCommittedAt??n?.lastBodyCommittedAt??null,deletionRevision:n?.deletionRevision??0,deletedAt:t.deletedAt??n?.deletedAt??null,syncedIndexRevision:n?.syncedIndexRevision??0,indexSyncState:"pending",indexSyncStateRevision:(n?.indexRevision??0)+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,titleGenerationAttemptedAt:n?.titleGenerationAttemptedAt&&n.titleGenerationNextAttemptAt!==void 0?n.titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:n?.titleGenerationNextAttemptAt??null,titleGenerationAttempts:n?.titleGenerationAttempts??0};return y.nativeSessionVisibility==="internal"&&y.agentSessionId&&F(y.sessionId,y.agentType,y.agentSessionId),e[t.sessionId]=y,g(e),y}function J(){return Object.values(d())}function Se(t){if(!t)throw new Error("sessionId is required");const e=d();e[t]&&(delete e[t],g(e))}function ge(t){c().purgeSession(t)}function H(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){const o=E(i.title);if(o===i.title)continue;const a=i.indexRevision+1;t[s]={...i,title:o,indexRevision:a,indexSyncState:"pending",indexSyncStateRevision:a,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,indexQuarantineCode:null,updatedAt:n},e=!0}e&&g(t)}function fe(){const t=S();return Z(),K(),H(),J().filter(e=>{const n=e.indexSyncStateRevision===e.indexRevision;return e.indexQuarantineCode||n&&(e.indexSyncState==="quarantined"||e.indexSyncState==="terminal")||n&&e.indexSyncNextAttemptAt&&Date.parse(e.indexSyncNextAttemptAt)>Date.now()?!1:e.indexRevision>e.syncedIndexRevision&&e.localReady&&!!e.firstUserMessageId&&e.firstUserBodyRevision!=null}).sort((e,n)=>e.indexRevision-n.indexRevision).map(e=>{const n=!!(e.lastMessagePreview&&e.lastMessagePreviewMessageId&&e.lastMessagePreviewAt);return{protocolVersion:M,dataEpoch:R,daemonInstallationId:t,session:{id:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,nativeSessionVisibility:e.nativeSessionVisibility,...e.sessionScope==="steward"?{sessionScope:"steward"}:{},managerConfig:e.managerConfig,agentSessionId:e.agentSessionId??null,modelId:e.modelId??null,managerDefaultWorkerAgentType:e.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:e.managerDefaultWorkerModelId??null,title:e.title,titleSource:e.titleSource,titleRevision:e.titleRevision,titleLockedByUser:e.titleLockedByUser,titleOriginEventId:e.titleOriginEventId,status:e.status??"active",workDir:e.workDir,lastMessagePreview:n?e.lastMessagePreview:null,lastMessagePreviewMessageId:n?e.lastMessagePreviewMessageId:null,lastMessagePreviewAt:n?e.lastMessagePreviewAt:null,lastVisibleEventAt:e.lastVisibleEventAt??e.lastMessagePreviewAt??null,bodyStorageMode:"machine_local",localReady:!0,firstUserBoundary:{role:"user",messageId:e.firstUserMessageId,bodyRevision:e.firstUserBodyRevision},bodyRevision:e.bodyRevision,indexRevision:e.indexRevision,firstAvailableSeq:e.firstAvailableSeq,visibleMessageCount:e.visibleMessageCount,lastVisibleMessageId:e.lastVisibleMessageId,attentionCount:e.attentionCount??0,lastAttentionId:e.lastAttentionId??null,lastBodyCommittedAt:e.lastBodyCommittedAt,deletionRevision:e.deletionRevision,lastActivityAt:e.lastActivityAt,createdAt:e.createdAt,updatedAt:e.updatedAt,deletedAt:e.deletedAt}}})}function ve(t,e){const n=d(),s=n[t];if(!(!s||e<=s.syncedIndexRevision)){if(e>s.indexRevision)throw new Error(`cannot acknowledge future index revision ${e} for ${t}`);n[t]={...s,syncedIndexRevision:e,indexSyncState:"applied",indexSyncStateRevision:e,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null},g(n)}}function me(){const t=d();let e=0;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(i.deletedAt||i.indexQuarantineCode||!i.localReady)continue;const o=i.indexRevision+1;t[s]={...i,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e+=1}return e>0&&g(t),e}function ye(t){const e=d(),n=e[t.sessionId];if(!n||n.indexRevision!==t.indexRevision)return"terminal";const i=(n.indexSyncStateRevision===t.indexRevision?n.indexSyncAttempts??0:0)+1;let o=t.disposition;o==="retry"&&i>=(t.maxAttempts??8)&&(o="terminal");const a=t.now??Date.now(),r=Math.min(5e3*2**Math.max(0,i-1),360*60*1e3),l=Math.round(r*.2*(Math.random()*2-1));return e[t.sessionId]={...n,indexSyncState:o==="retry"?"pending":o,indexSyncStateRevision:t.indexRevision,indexSyncAttempts:i,indexSyncNextAttemptAt:o==="retry"?new Date(a+r+l).toISOString():null,indexSyncErrorCode:t.code,indexQuarantineCode:o==="quarantined"?t.code:n.indexQuarantineCode??null},g(e),o}const X=2*6e4;function Ae(t=Date.now(),e=X){const n=d(),s=[],i=new Date(t).toISOString();for(const o of Object.values(n)){if(o.titleSource!=="first_user_fallback"||o.titleLockedByUser||o.titleGenerationAttemptedAt||!o.title.trim()||o.syncedIndexRevision<o.indexRevision||o.titleGenerationNextAttemptAt&&Date.parse(o.titleGenerationNextAttemptAt)>t)continue;const a=o.status==="completed"||o.status==="failed",r=o.visibleMessageCount>=2;let l=null;if(o.agentType==="claude"&&r?l="agent_native_unavailable":a?l="terminal":r&&t-Date.parse(o.createdAt)>=e&&(l="grace_elapsed"),!l)continue;const f=_(o.title,240);if(!f)continue;const v=k.randomUUID();n[o.sessionId]={...o,titleGenerationAttemptedAt:i,titleGenerationNextAttemptAt:null,titleGenerationAttempts:(o.titleGenerationAttempts??0)+1},s.push({sessionId:o.sessionId,requestId:v,titleSeed:f,baseTitleRevision:o.titleRevision,eligibility:l})}return s.length>0&&g(n),s}function xe(t,e=Date.now()){const n=d(),s=n[t];if(!s?.titleGenerationAttemptedAt||s.titleSource!=="first_user_fallback")return null;const i=Math.max(1,s.titleGenerationAttempts??1),o=Math.min(10*6e4,3e4*2**Math.min(i-1,5)),a=new Date(e+o).toISOString();return n[t]={...s,titleGenerationAttemptedAt:null,titleGenerationNextAttemptAt:a},g(n),a}function Ie(t,e){const s=d()[t];return!s||s.titleLockedByUser||I[s.titleSource]>=I.shennian_generated||e.titleRevision<=s.titleRevision?!1:(z({sessionId:t,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:s.agentSessionId,modelId:s.modelId,status:s.status,title:e.title,titleSource:"shennian_generated",titleRevision:e.titleRevision,titleLockedByUser:!1,titleOriginEventId:e.titleOriginEventId}),!0)}function pe(t,e,n){p(t),S();const s=c().append(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function we(t,e,n){p(t),S();const s=c().upsert(t,e,n);return U(t,e,s.bodyRevision),s.bodyRevision}function Re(t,e){const n=c().getMessageState(t,e);return!n||n.tombstoned||!n.message||!n.deliveryState?{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:"not_found",sessionId:t,clientMessageId:e}:{protocolVersion:M,dataEpoch:R,daemonInstallationId:S(),state:n.deliveryState,sessionId:t,clientMessageId:e,messageId:n.message.id,deliveryState:n.deliveryState,bodyRevision:n.lastRevision,committedAt:new Date(n.message.ts).toISOString()}}function Me(t,e){p(t),S();const n=c().tombstone(t,e),s=d(),i=s[t];if(i){const o=e===i.lastMessagePreviewMessageId?G(t):{preview:i.lastMessagePreview??null,messageId:i.lastMessagePreviewMessageId??null,at:i.lastMessagePreviewAt??null};s[t]={...i,bodyRevision:n.bodyRevision,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,lastVisibleEventAt:L(t)},g(s)}return n.bodyRevision}function U(t,e,n){const s=d(),i=s[t];if(!i)return;const o=i.sessionScope==="steward"&&e.role==="agent"&&!q(e.payload),a=e.id.startsWith(T),r=h(e),l=o||a?null:r,f=a?r:l,v=l?{lastMessagePreview:l,lastMessagePreviewMessageId:e.id,lastMessagePreviewAt:new Date(e.ts).toISOString()}:null,A=l||D(e.payload)?new Date(e.ts).toISOString():i.lastVisibleEventAt,m=c().getManifest(t),w=e.role==="user"&&f&&!i.title?{title:E(f),titleSource:"first_user_fallback",titleRevision:i.titleRevision+1,titleLockedByUser:!1,titleOriginEventId:e.id}:null,x=e.role==="user"&&!i.localReady?{localReady:!0,firstUserMessageId:e.id,firstUserBodyRevision:n}:null;s[t]={...i,...w??{},...x??{},bodyRevision:n,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:new Date().toISOString(),lastActivityAt:new Date(e.ts).toISOString(),lastVisibleEventAt:A,...v??{},firstAvailableSeq:m?.firstAvailableSeq??i.firstAvailableSeq,visibleMessageCount:m?.visibleMessageCount??i.visibleMessageCount,lastVisibleMessageId:m?.lastVisibleMessageId??i.lastVisibleMessageId,attentionCount:i.attentionCount??0,lastAttentionId:i.lastAttentionId??null,lastBodyCommittedAt:m?.lastBodyCommittedAt??i.lastBodyCommittedAt},g(s)}function G(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s];if(i.message.id.startsWith(T))continue;const o=h(i.message);if(o)return{preview:o,messageId:i.message.id,at:new Date(i.message.ts).toISOString()}}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return{preview:null,messageId:null,at:null}}function L(t){let e;do{const n=c().readPage(t,{limit:500,beforeSequence:e});for(let s=n.entries.length-1;s>=0;s-=1){const i=n.entries[s].message;if(!(!h(i)&&!D(i.payload)))return new Date(i.ts).toISOString()}if(!n.hasOlder||n.entries.length===0)break;e=n.entries[0].sequence}while(e!==void 0);return null}function K(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastVisibleEventAt"))continue;const o=i.indexRevision+1;t[s]={...i,lastVisibleEventAt:L(s)??i.lastMessagePreviewAt??null,indexRevision:o,indexSyncState:"pending",indexSyncStateRevision:o,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function Z(){const t=d();let e=!1;const n=new Date().toISOString();for(const[s,i]of Object.entries(t)){if(Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewMessageId")&&Object.prototype.hasOwnProperty.call(i,"lastMessagePreviewAt"))continue;const o=G(s);t[s]={...i,lastMessagePreview:o.preview,lastMessagePreviewMessageId:o.messageId,lastMessagePreviewAt:o.at,indexRevision:i.indexRevision+1,indexSyncState:"pending",indexSyncStateRevision:i.indexRevision+1,indexSyncAttempts:0,indexSyncNextAttemptAt:null,indexSyncErrorCode:null,updatedAt:n},e=!0}e&&g(t)}function ee(t,e){const n={title:t?.title??"",titleSource:t?.titleSource??"first_user_fallback",titleRevision:t?.titleRevision??0,titleLockedByUser:t?.titleLockedByUser??!1,titleOriginEventId:t?.titleOriginEventId??null},s=E(e.title?.trim()??"");if(!s)return n;if(!e.titleSource)throw new Error("titleSource is required with title");if(n.title&&n.titleSource==="first_user_fallback"&&e.titleSource==="first_user_fallback")return n;const i=e.titleSource==="shennian_manual";if(e.titleLockedByUser!==void 0&&e.titleLockedByUser!==i)throw new Error("titleLockedByUser conflicts with titleSource");const o=s===n.title&&e.titleSource===n.titleSource,a=e.titleRevision??n.titleRevision+(o?0:1);if(!Number.isSafeInteger(a)||a<0)throw new Error("invalid titleRevision");const r=I[e.titleSource],l=I[n.titleSource];return r<l||a<n.titleRevision||o&&a===n.titleRevision||a===n.titleRevision&&!o?n:{title:s,titleSource:e.titleSource,titleRevision:a,titleLockedByUser:i,titleOriginEventId:e.titleOriginEventId??n.titleOriginEventId}}function be(t,e){const n=e?.limit&&e.limit>0?Math.min(e.limit,500):500;let i=c().readRecent(t,n).messages;return e?.before!==void 0&&(i=i.filter(o=>o.ts<e.before)),[...i].sort((o,a)=>a.ts-o.ts)}function Ee(){return c().listSessionIds()}function Pe(){return c()}function te(t,e){const n=b.dirname(t);u.mkdirSync(n,{recursive:!0,mode:448});const s=`${t}.tmp-${process.pid}-${k.randomBytes(6).toString("hex")}`;let i;try{if(i=u.openSync(s,"wx",384),u.writeFileSync(i,`${JSON.stringify(e,null,2)}
|
|
2
|
+
`,"utf8"),u.fsyncSync(i),u.closeSync(i),i=void 0,j(s,t),process.platform!=="win32"){const o=u.openSync(n,"r");try{u.fsyncSync(o)}finally{u.closeSync(o)}}}finally{i!==void 0&&u.closeSync(i);try{u.unlinkSync(s)}catch{}}}export{$ as PERSONAL_SYNC_V1_ROOT_NAME,ve as acknowledgeSessionIndexUpdate,pe as appendMessage,Ie as applyGeneratedSessionTitle,Ae as claimSessionTitleGenerationCandidates,xe as deferSessionTitleGeneration,Pe as getCanonicalSessionStore,S as getDaemonInstallationId,Re as getMessageDeliveryStatus,fe as listPendingSessionIndexUpdates,J as listSessionRecords,Ee as listSessions,me as markAllSessionIndexesForRepublish,ge as purgeCanonicalSession,Se as purgeSessionRecord,be as readMessages,z as recordSession,ye as recordSessionIndexRejection,Me as tombstoneMessage,we as upsertMessage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const d={not_installed:"\u6CA1\u6709\u5B89\u88C5\u6216\u627E\u4E0D\u5230\u7A0B\u5E8F",not_logged_in:"\u6CA1\u6709\u767B\u5F55\u6216\u6388\u6743\u5931\u6548",quota:"\u989D\u5EA6\u7528\u5B8C\u6216\u88AB\u9650\u6D41",crashed:"\u542F\u52A8\u5931\u8D25\u6216\u8FD0\u884C\u4E2D\u65AD"};function p(e){return d[e]}function S(e){const t=(e??"").toLowerCase();return/enoent|command not found|not installed|command_unavailable|runtime_unavailable|no such file|未找到|未安装/.test(t)?"not_installed":/log ?in|logged in|sign in|unauthori[sz]ed|\b401\b|\b403\b|auth(?:entication|_required)?\b|api key|credential|未登录|登录/.test(t)?"not_logged_in":/quota|usage limit|rate limit|too many requests|\b429\b|insufficient|credit|billing|exceeded|额度|用完|限流/.test(t)?"quota":"crashed"}const c=new Set(["manager","pi","pi-coding-agent"]);function x(e,t){const n=new Set(t);return e.find(r=>r.supportsStandardSession!==!1&&!c.has(r.type)&&r.authState!=="required"&&r.authState!=="error"&&!n.has(r.type))?.type??null}function h(e,t){return[`\u8FD9\u6BB5\u5BF9\u8BDD\u662F\u4ECE\u300C${e}\u300D\u81EA\u52A8\u5207\u6362\u8FC7\u6765\u7684\uFF08\u539F\u56E0\uFF1A${d[t]}\uFF09\u3002`,"\u4E0A\u4E00\u4E2A AI \u53EF\u80FD\u5DF2\u7ECF\u505A\u4E86\u4E00\u90E8\u5206\u64CD\u4F5C\uFF1A\u52A8\u624B\u524D\u5148\u6838\u5BF9\u73B0\u72B6\uFF08\u4F8B\u5982 shennian project task list \u770B\u5DF2\u5EFA\u7684\u4EFB\u52A1\uFF09\uFF0C","\u4E0D\u8981\u91CD\u590D\u6267\u884C\u6709\u526F\u4F5C\u7528\u7684\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u8981\u91CD\u590D\u521B\u5EFA\u5DF2\u5B58\u5728\u7684\u4EFB\u52A1\uFF1B\u6838\u5BF9\u540E\u518D\u7EE7\u7EED\u56DE\u5E94\u7528\u6237\u7684\u8FD9\u6761\u6D88\u606F\u3002"].join("")}const u=new Map,o=new Map,a=new Map,l=200;function i(e){for(;e.size>l;)e.delete(e.keys().next().value);return e}function _(e,t){i(u).set(e,t)}function g(e){return u.get(e)??""}function b(e,t){const n=o.get(e)??[];return n.includes(t)?n:[...n,t]}function A(e,t,n){i(o).set(t,[...n]),o.delete(e)}function T(e,t){i(a).set(e,t)}function m(e){const t=a.get(e)??"";return a.delete(e),t}function y(e){o.delete(e)}const s=new Map,w=6e4;function v(e){i(s).set(e,Date.now())}function k(e){const t=s.get(e);return t!==void 0&&Date.now()-t<w}function E(e){s.delete(e)}export{h as buildHandoverNote,A as carryStewardChain,S as classifyStewardFailure,E as clearStewardSwitched,g as lastStewardUserText,v as markStewardSwitched,x as pickFailoverAgent,_ as rememberStewardTurn,y as resetStewardChain,T as setStewardHandover,p as stewardFailureLabel,b as stewardTriedAgents,m as takeStewardHandover,k as wasStewardJustSwitched};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const e=
|
|
1
|
+
const e=2,n=`<!-- shennian-steward-template: 2 -->
|
|
2
2
|
# \u795E\u5FF5\u7BA1\u5BB6
|
|
3
3
|
|
|
4
4
|
\u4F60\u662F\u795E\u5FF5\u7BA1\u5BB6\uFF0C\u662F\u7528\u6237\u5728\u8FD9\u53F0\u7535\u8111\u4E0A\u7684\u4E2A\u4EBA\u8C03\u5EA6\u8005\u3002\u4F60\u7684\u5DE5\u4F5C\u76EE\u5F55\u662F\u672C\u76EE\u5F55\uFF1B\u5148\u8BFB index.md\uFF0C\u53EA\u6CBF\u4E0E\u672C\u6B21\u95EE\u9898\u76F8\u5173\u7684\u94FE\u63A5\u8BFB\u53D6\uFF0C\u4E0D\u626B\u63CF\u6574\u4E2A\u78C1\u76D8\u3002
|
|
@@ -17,7 +17,7 @@ const e=1,n=`<!-- shennian-steward-template: 1 -->
|
|
|
17
17
|
|
|
18
18
|
- \u6536\u5230\u8BF7\u6C42\u5148\u7528\u4E00\u53E5\u8BDD\u56DE\u5E94\uFF08\u4F8B\u5982\u201C\u6536\u5230\uFF0C\u6211\u53BB\u67E5\u201D\uFF09\uFF0C\u5904\u7406\u5B8C\u518D\u53D1\u7ED3\u679C\u3002\u9700\u8981\u7528\u6237\u56DE\u7B54\u65F6\u76F4\u63A5\u95EE\uFF0C\u95EE\u9898\u91CC\u5199\u6E05\u9009\u9879\u3002
|
|
19
19
|
- \u4E0D\u8981\u628A\u547D\u4EE4\u8F93\u51FA\u539F\u6837\u8D34\u7ED9\u7528\u6237\uFF1B\u7528\u7B80\u77ED\u7684\u81EA\u7136\u8BED\u8A00\u8BF4\u660E\u7ED3\u679C\u3001\u5931\u8D25\u539F\u56E0\u548C\u4E0B\u4E00\u6B65\u3002
|
|
20
|
-
- \u7528\u6237\u4F7F\u7528\u54EA\u79CD\u8BED\u8A00\uFF0C\u5C31\u7528\u54EA\u79CD\u8BED\u8A00\u3002
|
|
20
|
+
- \u7528\u6237\u4F7F\u7528\u54EA\u79CD\u8BED\u8A00\uFF0C\u5C31\u7528\u54EA\u79CD\u8BED\u8A00\uFF1B\u8FD8\u770B\u4E0D\u51FA\u7528\u6237\u7528\u4EC0\u4E48\u8BED\u8A00\u65F6\uFF08\u4F8B\u5982\u5BF9\u8BDD\u521A\u5F00\u59CB\u3001\u7CFB\u7EDF\u81EA\u52A8\u89E6\u53D1\u7684\u4E00\u8F6E\uFF09\uFF0C\u9ED8\u8BA4\u7528\u4E2D\u6587\uFF0C\u4E0D\u8981\u7528\u82F1\u6587\u3002
|
|
21
21
|
|
|
22
22
|
## \u5B9E\u65F6\u4FE1\u606F\u4ECE\u54EA\u91CC\u6765
|
|
23
23
|
|
|
@@ -48,7 +48,7 @@ const e=1,n=`<!-- shennian-steward-template: 1 -->
|
|
|
48
48
|
- \u53EA\u5728\u7528\u6237\u8981\u6C42\uFF0C\u6216\u51FA\u73B0\u957F\u671F\u6709\u7528\u7684\u4FE1\u606F\uFF08\u65B0\u9879\u76EE\u7684\u7528\u9014\u3001\u5E38\u7528\u7FA4\u7684\u7EA6\u5B9A\uFF09\u65F6\uFF0C\u624D\u66F4\u65B0 index.md \u7B49\u6587\u4EF6\u3002\u4E0D\u8981\u5199\u6D88\u606F\u6570\u3001\u5728\u7EBF\u72B6\u6001\u3001\u6210\u5458\u540D\u5355\u8FD9\u7C7B\u5B9E\u65F6\u5185\u5BB9\u3002
|
|
49
49
|
- \u7F16\u8F91\u524D\u91CD\u65B0\u8BFB\u53D6\u6587\u4EF6\uFF0C\u53EA\u6539\u9700\u8981\u6539\u7684\u90E8\u5206\uFF1B\u53D1\u73B0\u4E0E\u522B\u4EBA\u7684\u4FEE\u6539\u51B2\u7A81\u65F6\u7559\u7ED9\u7528\u6237\u5224\u65AD\u3002
|
|
50
50
|
- \u5982\u679C\u4F60\u662F\u5207\u6362\u5DE5\u5177\u540E\u63A5\u624B\u7684\u65B0\u5BF9\u8BDD\uFF0C\u5148\u6838\u5BF9\u54EA\u4E9B\u4E8B\u5DF2\u7ECF\u505A\u8FC7\uFF08\u4F8B\u5982\u4EFB\u52A1\u662F\u5426\u5DF2\u521B\u5EFA\u3001\u6D88\u606F\u662F\u5426\u5DF2\u53D1\u9001\uFF09\uFF0C\u4E0D\u8981\u91CD\u590D\u6267\u884C\u3002
|
|
51
|
-
`,t=`<!-- shennian-steward-template:
|
|
51
|
+
`,t=`<!-- shennian-steward-template: 2 -->
|
|
52
52
|
# \u8D44\u6599\u5730\u56FE
|
|
53
53
|
|
|
54
54
|
\u8FD9\u91CC\u53EA\u5199\u7528\u6237\u9009\u62E9\u8BA9\u795E\u5FF5\u7BA1\u5BB6\u4E86\u89E3\u7684\u8D44\u6599\u5165\u53E3\u3002\u6BCF\u4E00\u9879\u6307\u5411\u539F\u4F4D\u7F6E\uFF0C\u4E0D\u590D\u5236\u5168\u6587\u3002
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const
|
|
1
|
+
const E=/^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm,g=/^\s*\{\s*"v"\s*:\s*1\s*,\s*"type"\s*:\s*"(tool|tool_use|tool_result)"/,R=/^\s*<environment_context>\s*[^]*?<\/environment_context>\s*$/i,S=/<(cwd|shell|current_date|timezone)>[^<]*<\/\1>/gi,x=/^\s*<recommended_plugins>[^]*?<\/recommended_plugins>\s*/i,P=/^\s*<turn_aborted>[^]*?<\/turn_aborted>\s*$/i,b=/^\s*<codex_internal_context\b[^>]*>[^]*?<\/codex_internal_context>\s*$/i,T=/^\s*# AGENTS\.md instructions for [^\n]+\n+\s*<INSTRUCTIONS>\s*[^]*?<\/INSTRUCTIONS>\s*(?:<environment_context>[^]*?<\/environment_context>)?\s*$/i,A=/^\s*\{\s*"v"\s*:\s*1\s*,\s*"type"\s*:\s*"approval_pending"/,I=/(?:<\/?(?:environment_context|instructions|system|developer|codex_internal_context|recommended_plugins)\b|#\s*AGENTS\.md instructions\b)/i,h=/\bdata:[a-z0-9.+-]+\/[a-z0-9.+-]+;base64,[a-z0-9+/=\s]+/i,N=/(?:^|\s)(?=[A-Za-z0-9+/]{80,}={0,2}(?=\s|$))(?=[A-Za-z0-9+/]*[A-Z])(?=[A-Za-z0-9+/]*[a-z])(?=[A-Za-z0-9+/]*[0-9])[A-Za-z0-9+/]{80,}={0,2}(?=\s|$)/,v=new Set(["tool","tool_use","tool_result","thinking","system","developer","context","environment_context","channel_delivery_status"]),L="steward-terminal-open-",G="steward-failover-user-";function O(e){return e.replace(/[[\]\\]/g,"\\$&")}function C(e){const t=O(e.name);return e.kind==="image"?``:`[${t}](<${e.path}>)`}function w(e,t){if(!t?.length)return e;const n=new Set(t.map(C));return e.split(`
|
|
2
2
|
`).filter(s=>!n.has(s.trim())).join(`
|
|
3
3
|
`).replace(/\n{3,}/g,`
|
|
4
4
|
|
|
5
|
-
`).trim()}function u(e){if(!e||e[0]!=="{")return null;try{const t=JSON.parse(e);if(typeof t=="object"&&t!==null)return t}catch{}return null}function D(e){if(typeof e!="object"||e===null)return null;const t=e,n=typeof t.path=="string"?t.path:"",r=typeof t.name=="string"?t.name:"",s=typeof t.mimeType=="string"?t.mimeType:"",l=t.kind==="image"||t.kind==="file"||t.kind==="folder"?t.kind:null;if(!n||!r||!s||!l)return null;const f=typeof t.previewData=="string"&&t.previewData.trim()?t.previewData.trim():void 0,p=typeof t.byteSize=="number"&&Number.isSafeInteger(t.byteSize)&&t.byteSize>=0?t.byteSize:void 0,d=typeof t.sha256=="string"&&/^[a-f0-9]{64}$/i.test(t.sha256)?t.sha256.toLowerCase():void 0;return{path:n,name:r,mimeType:s,kind:l,...p!==void 0?{byteSize:p}:{},...d?{sha256:d}:{},...f?{previewData:f}:{}}}function o(e){const t=u(e);if(!t||t.v!==1)return null;if(t.type==="user"&&typeof t.content=="string"){const n=Array.isArray(t.attachments)?t.attachments.map(D).filter(r=>r!=null):void 0;return{v:1,type:"user",content:t.content,...n?.length?{attachments:n}:{}}}return t}function z(e){const t=o(e);return t?.type==="user"?t:null}function
|
|
6
|
-
`);if(!/(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(t))return t;const r=t.replace(
|
|
5
|
+
`).trim()}function u(e){if(!e||e[0]!=="{")return null;try{const t=JSON.parse(e);if(typeof t=="object"&&t!==null)return t}catch{}return null}function D(e){if(typeof e!="object"||e===null)return null;const t=e,n=typeof t.path=="string"?t.path:"",r=typeof t.name=="string"?t.name:"",s=typeof t.mimeType=="string"?t.mimeType:"",l=t.kind==="image"||t.kind==="file"||t.kind==="folder"?t.kind:null;if(!n||!r||!s||!l)return null;const f=typeof t.previewData=="string"&&t.previewData.trim()?t.previewData.trim():void 0,p=typeof t.byteSize=="number"&&Number.isSafeInteger(t.byteSize)&&t.byteSize>=0?t.byteSize:void 0,d=typeof t.sha256=="string"&&/^[a-f0-9]{64}$/i.test(t.sha256)?t.sha256.toLowerCase():void 0;return{path:n,name:r,mimeType:s,kind:l,...p!==void 0?{byteSize:p}:{},...d?{sha256:d}:{},...f?{previewData:f}:{}}}function o(e){const t=u(e);if(!t||t.v!==1)return null;if(t.type==="user"&&typeof t.content=="string"){const n=Array.isArray(t.attachments)?t.attachments.map(D).filter(r=>r!=null):void 0;return{v:1,type:"user",content:t.content,...n?.length?{attachments:n}:{}}}return t}function z(e){const t=o(e);return t?.type==="user"?t:null}function F(e,t){return t?.length?JSON.stringify({v:1,type:"user",content:e,attachments:t}):e}function $(e){if(g.test(e))return!0;const t=o(e);return!t||typeof t!="object"?!1:t.type==="tool"||t.type==="tool_use"||t.type==="tool_result"}function k(e){return A.test(e)?!0:o(e)?.type==="approval_pending"}function j(e,t="say"){return JSON.stringify({v:1,type:"steward_say",content:e,source:t})}function J(e){const t=o(e);if(!t||t.type!=="steward_say")return null;const n=t;return typeof n.content!="string"||!n.content.trim()?null:{v:1,type:"steward_say",content:n.content,source:n.source==="fallback"?"fallback":"say"}}function W(e){return V(e)?.agentVisible===!1}function V(e){const t=o(e);if(!t||t.type!=="channel_delivery_status")return null;const n=t;if(n.v!==1||n.channel!=="wechat"||n.agentVisible!==!1)return null;const r=typeof n.status=="string"&&n.status.trim()?n.status.trim():"";if(!r)return null;const s=typeof n.content=="string"&&n.content.trim()?n.content:r==="manual_review"?"\u53D1\u9001\u72B6\u6001\u4E0D\u786E\u5B9A\uFF0C\u8BF7\u68C0\u67E5\u5FAE\u4FE1":"\u672A\u80FD\u81EA\u52A8\u53D1\u9001\u5230\u5FAE\u4FE1";return{v:1,type:"channel_delivery_status",channel:"wechat",status:r,agentVisible:!1,content:s,replyId:i(n.replyId),idempotencyKey:i(n.idempotencyKey),bindingId:i(n.bindingId),reasonCode:i(n.reasonCode),copyText:i(n.copyText),copyableContentRef:i(n.copyableContentRef),errorSummary:i(n.errorSummary)}}function X(e){const t=e?.trim();return`${!t||t==="codex"?"Codex":t==="workbuddy"?"WorkBuddy":t} \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002`}function Z(e){return JSON.stringify({v:1,type:"approval_pending",title:e?.title?.trim()||"\u9700\u8981\u7528\u6237\u786E\u8BA4",content:e?.content?.trim()||X(e?.source),source:e?.source?.trim()||"codex",actionHint:e?.permission?e?.actionHint?.trim():e?.actionHint?.trim()||"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002",...e?.permission?{permission:e.permission}:{}})}function _(e){if(!R.test(e))return!1;const t=new Set;for(const n of e.matchAll(S))n[1]&&t.add(n[1].toLowerCase());return t.has("current_date")&&t.has("timezone")&&e.includes("<workspace_roots>")?!0:t.has("cwd")&&t.has("shell")&&t.has("current_date")&&t.has("timezone")}function M(e){return P.test(e)}function y(e){return T.test(e)}function U(e){const t=e.match(x);if(t){const n=e.slice(t[0].length).trim();return!n||_(n)||y(n)}return _(e)||M(e)||b.test(e)||y(e)}function c(e){if(!e)return"";const t=e.replace(/\r\n/g,`
|
|
6
|
+
`);if(!/(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(t))return t;const r=t.replace(E,"");return r.trim()?r.replace(/[ \t]+\n/g,`
|
|
7
7
|
`).replace(/\n+$/g,""):""}function m(e){if(!e)return"";const t=z(e);if(t)return w(t.content,t.attachments);const n=o(e);if(n){if(typeof n.content=="string")return c(n.content);if("text"in n&&typeof n.text=="string")return c(n.text)}try{const r=JSON.parse(e);if(typeof r=="string")return r;if(typeof r=="object"&&r!==null){const s=r;if(typeof s.content=="string")return c(s.content);if(typeof s.text=="string")return c(s.text)}}catch{}return c(e)}function a(e,t=160){if(typeof e!="string"||!Number.isSafeInteger(t)||t<1)return null;const n=e.replace(/\r\n/g,`
|
|
8
|
-
`).trim();if(!n||
|
|
8
|
+
`).trim();if(!n||I.test(n)||h.test(n)||N.test(n)||u(n))return null;const r=n.replace(/\s+/g," ");return r.length>t?`${r.slice(0,t)}\u2026`:r}function B(e,t=160){if(!e||$(e)||U(e))return null;if(k(e))return a("\u9700\u8981\u7528\u6237\u786E\u8BA4",t);const n=o(e);if(n){const r=typeof n.type=="string"?n.type.toLowerCase():"";return!r||v.has(r)?null:a(m(e),t)}return u(e)?null:a(m(e),t)}function i(e){return typeof e=="string"&&e.trim()?e:void 0}export{G as STEWARD_FAILOVER_USER_MESSAGE_ID_PREFIX,L as STEWARD_TERMINAL_OPEN_MESSAGE_ID_PREFIX,Z as buildApprovalPendingPayload,j as buildStewardSayPayload,F as buildUserMessagePayload,m as extractPayloadText,W as isAgentHiddenPayload,k as isApprovalPendingPayload,y as isCodexProjectInstructionsPayload,M as isCodexTurnAbortedPayload,U as isSystemControlPayload,_ as isSystemEnvironmentContextPayload,$ as isToolPayload,V as parseChannelDeliveryStatusPayload,J as parseStewardSayPayload,o as parseStructuredMessagePayload,z as parseUserMessagePayload,a as sanitizeSessionPreview,B as sessionPreviewFromPayload,c as stripGitDirectiveArtifacts};
|