shennian 0.4.57 → 0.4.58
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.
|
@@ -891,8 +891,8 @@
|
|
|
891
891
|
},
|
|
892
892
|
{
|
|
893
893
|
"file": "src/session/queue-helpers.js",
|
|
894
|
-
"beforeBytes":
|
|
895
|
-
"afterBytes":
|
|
894
|
+
"beforeBytes": 7881,
|
|
895
|
+
"afterBytes": 3938
|
|
896
896
|
},
|
|
897
897
|
{
|
|
898
898
|
"file": "src/session/queue-retry.js",
|
|
@@ -906,8 +906,8 @@
|
|
|
906
906
|
},
|
|
907
907
|
{
|
|
908
908
|
"file": "src/session/queue.js",
|
|
909
|
-
"beforeBytes":
|
|
910
|
-
"afterBytes":
|
|
909
|
+
"beforeBytes": 42174,
|
|
910
|
+
"afterBytes": 19010
|
|
911
911
|
},
|
|
912
912
|
{
|
|
913
913
|
"file": "src/session/queued-chat-dispatch.js",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{listSessionRecords as p}from"./store.js";function I(n,
|
|
2
|
-
${n.map(
|
|
1
|
+
import{listSessionRecords as p}from"./store.js";function I(n,e){const r=u(e);if(r)return n.find(i=>u(i)===r)??null;if(e.origin!=="external")return null;const t=f(e);return n.find(i=>f(i)===t)??null}function x(n){const{origin:e,managedRoom:r,managedAgentDirect:t,trigger:i,...a}=n;return a}function b(n){const e=n.reduce((o,g)=>{const l=s(g);return o===null||l<o?l:o},null);if(e===null)return[];const r=n.filter(o=>s(o)===e),t=r[0];if(!t)return[];if(d(t))return[t];if(t.trigger?.kind==="manager_worker")return[t];const i=m(t),a=[];for(const o of r){if(m(o)!==i)break;a.push(o)}return a}function d(n){if(n.origin==="external"||n.origin==="room"||n.managedRoom)return!1;const e=n.trigger?.kind;return e==null||e==="personal"||e==="managed_direct"}function _(n){return n?.trim()||void 0}function M(n,e){const r=n.find(t=>t.id===e&&d(t));return r?[r]:[]}function s(n){const e=c(n).kind;return e==="personal"||e==="managed_direct"?0:e==="manager_event"||e==="manager_worker"?1:2}function c(n){const e=n.trigger;return e?e.kind==="room_activation"?{kind:e.kind,registryKey:e.registryKey}:e.kind==="manager_worker"?{kind:e.kind,parentSessionId:e.parentSessionId}:{kind:e.kind}:n.managedRoom?{kind:"room_activation",registryKey:n.managedRoom.registryKey}:n.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"}}function m(n){return JSON.stringify({agentType:n.agentType,sessionMode:n.sessionMode??null,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:_(n.modelId)??null,systemPrompt:n.systemPrompt??null,reasoningEffort:n.reasoningEffort??null,managerConfig:n.managerConfig??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId??null,externalChannel:n.externalChannel??null,replyTarget:n.replyTarget??null,roomRegistryKey:n.managedRoom?.registryKey??null,trigger:c(n)})}function D(n){return n.every(e=>e.managedRoom)?`[\u7FA4\u6D88\u606F]
|
|
2
|
+
${n.map(e=>y(e.text)).filter(Boolean).join(`
|
|
3
3
|
|
|
4
4
|
`)}`:`[\u8FDE\u7EED\u7528\u6237\u6D88\u606F]
|
|
5
|
-
${n.map((r
|
|
6
|
-
${
|
|
5
|
+
${n.map((e,r)=>`<\u6D88\u606F ${r+1}>
|
|
6
|
+
${e.text.trim()}`).join(`
|
|
7
7
|
|
|
8
|
-
`)}`}function y(n){const
|
|
9
|
-
${
|
|
10
|
-
`)?
|
|
11
|
-
`)}function u(n){const
|
|
8
|
+
`)}`}function y(n){const e=n.trim(),r=e.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);return r?`<${r[1]}>
|
|
9
|
+
${r[2]}`:e.startsWith(`[\u7FA4\u6D88\u606F]
|
|
10
|
+
`)?e.slice(6):e}function f(n){const e=u(n);return e?`id:${e}`:["body",k(n.text),...(n.attachments??[]).map(r=>r.path||`${r.name}:${r.mimeType}`)].join(`
|
|
11
|
+
`)}function u(n){const e=typeof n.clientMessageId=="string"?n.clientMessageId.trim():"";if(e)return e;const r=typeof n.id=="string"?n.id.trim():"";return r&&!r.startsWith("queue-")?r:""}function S(n){const e=new Set,r=[];for(const t of n){const i=t.path||`${t.name}:${t.mimeType}`;e.has(i)||(e.add(i),r.push(t))}return r.length?r:void 0}function k(n){return String(n||"").replace(/\s+/g," ").trim()}function $(n,e){const r=n.toLowerCase();if(r.includes("managed claim session conflicts with source binding"))return"managed_claim_source_binding_conflict";const t=r.match(/\b(?:managed_(?:agent|room)|agent_validation|acp|native)_[a-z0-9_]+\b/)?.[0];return t||(r.includes("no rollout found")?"missing_rollout":r.includes("managed_room_permission_snapshot_mismatch")?"managed_room_permission_snapshot_mismatch":r.includes("managed_room_prompt_snapshot_mismatch")?"managed_room_prompt_snapshot_mismatch":r.includes("managed_room_turn_preparer_unavailable")?"managed_room_turn_preparer_unavailable":r.includes("timeout")?"timeout":r.includes("connection")?"connection_error":e)}function v(n,e){if(n.sessions.has(e.sessionId))return null;const r=p().find(t=>t.sessionId===e.sessionId)?.agentSessionId?.trim();return!r||r.startsWith("managed:")?null:r}export{$ as classifyQueueError,S as dedupeQueuedAttachments,I as findDuplicateQueuedMessage,D as formatQueuedBatch,d as isControllableQueueMessage,_ as normalizeQueuedModelId,v as resolveManagedRoomNativeSessionId,x as stripLocalQueueFields,b as takeCompatibleBatch,M as takeControllableMessage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{NativeSourceDeletionStore as U}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as J}from"./queue-retry.js";import{findDuplicateQueuedMessage as E,stripLocalQueueFields as _,takeCompatibleBatch as G,formatQueuedBatch as Q,dedupeQueuedAttachments as B,classifyQueueError as T,isControllableQueueMessage as q,takeControllableMessage as H,normalizeQueuedModelId as C,resolveManagedRoomNativeSessionId as L}from"./queue-helpers.js";import{randomUUID as V}from"node:crypto";import{CODEX_DESKTOP_SEND_UNAVAILABLE as X,buildUserMessagePayload as Y}from"@shennian/wire";import{isCodexThreadTailInterrupted as Z}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as ee}from"./projection.js";import{parsePersonalAttachmentReferences as x}from"./attachment-reference.js";import{assertFinishedAttachmentReferences as W,markAttachmentReferences as F}from"./attachment-transfer-store.js";import{getPersonalSyncIdentity as R}from"../personal-sync/epoch.js";import{getDaemonInstallationId as D}from"../personal-sync/identity.js";import{appendMessage as b,getMessageDeliveryStatus as v,listSessionRecords as j,recordSession as N,tombstoneMessage as z,upsertMessage as A}from"./store.js";import{requestSessionIndexPublish as S}from"./index-publisher.js";import{purgeQueuedSessionData as te,readQueue as p,writeQueue as M}from"./queue-storage.js";import{getNativeSourceAgentType as se}from"./handlers/chat-events.js";import{purgeQueuedSessionData as Se}from"./queue-storage.js";class $ extends Error{constructor(e){super(e),this.name="TerminalQueuedChatDispatchError"}}function P(){return new Date().toISOString()}function O(u){const e=P(),s=u.managedWorkerParentSessionId?{kind:"manager_worker",parentSessionId:u.managedWorkerParentSessionId}:u.managerEventId?{kind:"manager_event",eventId:u.managerEventId}:u.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"};return{...R(D()),id:u.queueMessageId||u.clientMessageId||`queue-${V()}`,sessionId:u.sessionId,text:u.text,agentType:u.agentType,sessionMode:u.sessionMode,managerConfig:u.managerConfig,workDir:u.workDir,agentSessionId:u.agentSessionId??null,modelId:C(u.modelId)??null,systemPrompt:u.systemPrompt??null,managerDefaultWorkerAgentType:u.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:u.managerDefaultWorkerModelId??null,reasoningEffort:u.reasoningEffort??null,clientMessageId:u.clientMessageId??null,attachments:x(u.attachments),externalChannel:u.externalChannel??null,replyTarget:u.replyTarget??null,origin:u.origin,createdAt:e,updatedAt:e,trigger:s}}function w(u){return{id:u.clientMessageId??u.id,sessionId:u.sessionId,role:u.trigger?.kind==="manager_event"?"agent":"user",ts:Date.parse(u.createdAt),payload:Y(u.text,u.attachments)}}class ye{opts;draining=new Set;promoting=new Set;disposed=!1;retries=new J(e=>{this.wakeSession(e)});deletions=new U;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){const s=p().sessions[e]??[],t=this.inFlightMessageIds.get(e);return{...R(D()),sessionId:e,busy:!!this.opts.getRuntime().sessions.get(e)?.currentRunId,pending:s.map(_),controllablePending:s.filter(o=>q(o)&&!t?.has(o.id)).map(_)}}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const s=this.opts.getRuntime(),t=p(),o=new Set,i=new Map;let n=!1;for(const d of e){const r=d.params;if(this.deletions.hasSession(r.sessionId)){delete t.sessions[r.sessionId],n=!0;continue}if(!r.sessionId||!r.text||!r.agentType||!r.workDir)throw new Error("sessionId, text, agentType and workDir are required");const g=O({...R(D()),...r});g.origin="room",g.managedRoom=d.context,g.trigger={kind:"room_activation",...d.context};const c=t.sessions[r.sessionId]??[],h=E(c,g),I=g.clientMessageId??g.id,m=v(r.sessionId,I);if(!h&&m.state==="not_found")c.push(g),t.sessions[r.sessionId]=c,i.set(`${g.sessionId}\0${I}`,g),o.add(r.sessionId),n=!0;else if(h&&m.state==="not_found")i.set(`${h.sessionId}\0${I}`,h),o.add(r.sessionId);else if(h&&m.state==="queued")o.add(r.sessionId);else if(h){const l=c.filter(k=>k.id!==h.id);l.length?t.sessions[r.sessionId]=l:delete t.sessions[r.sessionId],n=!0}}n&&M(t);let a;for(const d of o)try{for(const r of i.values())r.sessionId===d&&(b(d,w(r),"queued"),N({sessionId:d,agentType:r.agentType,sessionMode:r.sessionMode,managerConfig:r.managerConfig,workDir:r.workDir,agentSessionId:L(s,r),modelId:r.modelId}));this.logLifecycle("enqueue.persisted",d,{origin:"room",pendingCount:p().sessions[d]?.length??0}),this.broadcast(d),this.wakeSession(d)}catch(r){a=r,this.logLifecycle("enqueue.commit-failed",d,{failureClass:T(r instanceof Error?r.message:"","canonical_commit_failed")},"error"),this.retries.schedule(d,!0)}if(o.size&&S(s.client),a)throw a}async handleEnqueue(e){const s=this.opts.getRuntime(),t=e.params;if(ee(t.sessionListProjection),!t.sessionId||!t.text||!t.agentType||!t.workDir)return s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const o=t.managedAgentDirect?await this.prepareManagedAgentDirectTurn?.(t.sessionId):null;if(t.managedAgentDirect&&!o)throw new Error("managed_agent_context_unavailable");const i=o?j().find(K=>K.sessionId===t.sessionId):null,n=o?{...t,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId,modelId:i?.modelId??void 0,systemPrompt:o.systemPrompt,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:t,a=s.resolvePath(n.workDir),d=x(n.attachments);d?.length&&W(a,d);const r={text:n.text,attachments:d,localized:!1},g=s.sessions.get(n.sessionId);if(n.agentType==="codex"&&n.agentSessionId&&g?.currentRunId?.startsWith("dispatch:")&&Z(n.agentSessionId))return s.client.sendRes({type:"res",id:e.id,ok:!1,error:X}),!1;o?.managedRoomContextToken&&s.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const c=await this.isSessionBusy(n.sessionId),h=p(),I=h.sessions[n.sessionId]??[],m=O({...n,text:r.text,attachments:r.attachments,systemPrompt:o?null:n.systemPrompt});o&&(m.managedAgentDirect=!0,m.trigger?.kind!=="manager_event"&&(m.trigger={kind:"managed_direct"}));const l=m.clientMessageId??m.id,k=v(n.sessionId,l);if(k.state!=="not_found")return s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:k.state==="queued",queueMessageId:m.id,...k,queue:this.getSnapshot(n.sessionId)}}),!0;const y=E(I,m);y||(h.sessions[n.sessionId]=[...I,m],M(h));const f=y??m;return N({sessionId:f.sessionId,agentType:f.agentType,sessionMode:f.sessionMode,managerConfig:f.managerConfig,workDir:f.workDir,agentSessionId:f.agentSessionId,modelId:f.modelId}),b(f.sessionId,w(f),"queued"),F(s.resolvePath(f.workDir),f.attachments??[]),S(s.client),this.logLifecycle("enqueue.persisted",n.sessionId,{origin:n.origin??"app",queueMessageId:f.id,pendingCount:(p().sessions[n.sessionId]??[]).length}),this.broadcast(n.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:y?.id??m.id,...v(n.sessionId,y?.clientMessageId??y?.id??m.clientMessageId??m.id),queue:this.getSnapshot(n.sessionId),...r.localized?{localizedAttachments:!0}:{}}}),c?this.retries.schedule(n.sessionId):this.wakeSession(n.sessionId),!0}async handleGet(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId is required"});return}s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handleEdit(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId||!t.queueMessageId||!t.text){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, queueMessageId and text are required"});return}const o=p(),i=o.sessions[t.sessionId]??[],n=i.findIndex(r=>r.id===t.queueMessageId);if(n<0){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"Queued message not found"});return}if(!q(i[n])||this.inFlightMessageIds.get(t.sessionId)?.has(t.queueMessageId)){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"managed_agent_queue_mutation_forbidden"});return}const a=x(t.attachments),d=s.resolvePath(i[n].workDir);a?.length&&W(d,a),i[n]={...i[n],text:t.text,attachments:a,updatedAt:P()},o.sessions[t.sessionId]=i,M(o),A(t.sessionId,w(i[n]),"queued"),i[n].attachments?.length&&F(d,i[n].attachments??[]),S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handleDelete(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId||!t.queueMessageId){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId and queueMessageId are required"});return}const o=p(),i=o.sessions[t.sessionId]??[],n=i.find(d=>d.id===t.queueMessageId);if(n&&(!q(n)||this.inFlightMessageIds.get(t.sessionId)?.has(t.queueMessageId))){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"managed_agent_queue_mutation_forbidden"});return}const a=i.filter(d=>d.id!==t.queueMessageId);if(a.length===i.length){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"Queued message not found"});return}a.length?o.sessions[t.sessionId]=a:delete o.sessions[t.sessionId],M(o),z(t.sessionId,n?.clientMessageId??n?.id??t.queueMessageId),S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handlePromote(e){const s=this.opts.getRuntime(),t=e.params,o=n=>s.client.sendRes({type:"res",id:e.id,ok:!1,error:n});if(!t.sessionId||!t.queueMessageId){o("sessionId and queueMessageId are required");return}if(this.promoting.has(t.sessionId)){o("queue_promotion_in_progress");return}this.promoting.add(t.sessionId);let i=[];try{for(;this.draining.has(t.sessionId);)await new Promise(d=>setTimeout(d,5));if(i=H(p().sessions[t.sessionId]??[],t.queueMessageId),!i.length){o("Queued message not found");return}this.inFlightMessageIds.set(t.sessionId,new Set(i.map(d=>d.id)));const n=s.sessions.get(t.sessionId);let a="idle";if(n?.currentRunId)if(this.canInjectActiveBatch(n,i)){const d=i.length===1?i[0].text:Q(i),r=i[0].clientMessageId??i[0].id;s.nativeFusion?.registerManagedSend({sessionId:t.sessionId,agentType:i[0].agentType,sourceAgentType:se(i[0].agentType,i[0].modelId),canonicalMessageId:r,sourceSessionKey:n.agentSessionId,text:d,managedEchoPolicy:"suppress_following"});const g=Date.now();try{await n.adapter.injectActiveInput({text:d,attachments:B(i.flatMap(c=>c.attachments??[])),clientMessageId:r})}catch(c){throw s.nativeFusion?.cancelManagedSend(r),c}for(const c of i)A(t.sessionId,{...w(c),ts:g},"executing");this.removeBatch(t.sessionId,i),a="injected"}else{if(!this.opts.interruptQueuedSession)throw new Error("queue_interrupt_unavailable");await this.opts.interruptQueuedSession(t.sessionId),await this.dispatchQueuedMessages(i),this.removeBatch(t.sessionId,i),a="restarted"}else await this.dispatchQueuedMessages(i),this.removeBatch(t.sessionId,i);S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId),promotedMessageIds:i.map(d=>d.id),mode:a}})}catch(n){o(n instanceof Error?n.message:"queue_promotion_failed"),this.broadcast(t.sessionId)}finally{this.inFlightMessageIds.delete(t.sessionId),this.promoting.delete(t.sessionId),p().sessions[t.sessionId]?.length&&this.wakeSession(t.sessionId)}}noteTerminal(e){this.wakeSession(e)}purgeSession(e){te(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const a=p().sessions[e]?.length??0;return this.purgeSession(e),a}const s=p(),t=s.sessions[e]??[],o=this.inFlightMessageIds.get(e)??new Set,i=t.filter(a=>a.managedRoom&&!o.has(a.id));if(i.length===0)return 0;const n=t.filter(a=>!i.includes(a));n.length?s.sessions[e]=n:delete s.sessions[e],M(s);for(const a of i)z(e,a.clientMessageId??a.id);return S(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:i.length,pendingCount:n.length}),this.broadcast(e),i.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=p();for(const s of Object.keys(e.sessions))this.wakeSession(s)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let s=!1,t=!1,o=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const g=p().sessions[e]?.length??0,c=this.deferredLogState.get(e),h=Date.now();(!c||c.pendingCount!==g||h-c.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:g}),this.deferredLogState.set(e,{at:h,pendingCount:g}));return}this.deferredLogState.delete(e);const i=p(),n=i.sessions[e]??[],a=n.filter(g=>{const c=g.clientMessageId??g.id,h=v(e,c).state;return h==="queued"||h==="not_found"});a.length!==n.length&&(a.length?i.sessions[e]=a:delete i.sessions[e],M(i),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:n.length-a.length,pendingCount:a.length}));const d=G(a);if(d.length===0){this.broadcast(e);return}o=d,this.inFlightMessageIds.set(e,new Set(d.map(g=>g.id))),this.logLifecycle("dispatch.start",e,{batchCount:d.length,queueMessageId:d[0].id,origin:d[0].origin??"app"});for(const g of d)A(e,w(g),"queued");await this.dispatchQueuedMessages(d);const r=this.removeBatch(e,d);this.logLifecycle("dispatch.accepted",e,{batchCount:d.length,queueMessageId:d[0].id,pendingCount:r}),this.deferredLogState.delete(e),s=r>0,this.broadcast(e)}catch(i){if(i instanceof $){const n=this.removeBatch(e,o);this.logLifecycle("dispatch.terminal-failure",e,{batchCount:o.length,queueMessageId:o[0]?.id,pendingCount:n,failureClass:T(i.message,"terminal_dispatch_failed")},"error"),s=n>0}else t=!0,this.logLifecycle("dispatch.transient-failure",e,{failureClass:T(i instanceof Error?i.message:String(i),"transient_dispatch_failed")},"error");this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e),p().sessions[e]?.length?s?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,t):this.retries.cancel(e)}}canInjectActiveBatch(e,s){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const t=this.opts.getRuntime().runJournal?.get(s[0].sessionId,e.journalRunId),o=s[0].trigger?.kind==="managed_direct"||s[0].managedAgentDirect?null:"personal";return!!(o&&s[0].systemPrompt==null&&t&&t.source===o&&t.deliveryMode==="direct"&&t.agentType===s[0].agentType&&t.workDir===e.workDir&&t.agentSessionId===e.agentSessionId&&t.modelId===(s[0].modelId??null)&&t.reasoningEffort===(s[0].reasoningEffort??null))}removeBatch(e,s){if(s.length===0)return p().sessions[e]?.length??0;const t=p(),o=new Set(s.map(n=>n.id)),i=(t.sessions[e]??[]).filter(n=>!o.has(n.id));return i.length?t.sessions[e]=i:delete t.sessions[e],M(t),i.length}logLifecycle(e,s,t,o="info"){const i=`[chat.queue] ${JSON.stringify({at:P(),event:e,sessionId:s,...t})}`;o==="error"?console.error(i):console.info(i)}async dispatchQueuedMessages(e){const s=e[0],t=e.flatMap(l=>{if(l.trigger?.kind==="room_activation"){const{kind:k,...y}=l.trigger;return[y]}return l.managedRoom?[l.managedRoom]:[]}),o=e.some(l=>l.trigger?.kind==="managed_direct"||!!l.managedAgentDirect),i=e.find(l=>l.trigger?.kind==="manager_event")?.trigger,n=e.find(l=>l.trigger?.kind==="manager_worker")?.trigger,a=t.length>0?await this.prepareManagedRoomTurn?.(t):o?await this.prepareManagedAgentDirectTurn?.(s.sessionId):void 0;if(t.length>0&&!a)throw new Error("managed_room_turn_preparer_unavailable");if(o&&!a)throw new Error("managed_agent_context_unavailable");const d=new Set((p().sessions[s.sessionId]??[]).map(l=>l.id));if(this.disposed||this.deletions.hasSession(s.sessionId)||e.some(l=>!d.has(l.id)))throw a?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(a.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new $("queued_dispatch_cancelled");const r=a??null,g=r?.sessionMode==="manager"?r.managerConfig:null,c=e.length===1?s.text:Q(e),h=B(e.flatMap(l=>l.attachments??[])),I=o?a.agentSessionId:t.length>0?L(this.opts.getRuntime(),s):s.agentSessionId??null,m=a?j().find(l=>l.sessionId===s.sessionId):null;await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${s.id}-${Date.now()}`,method:"chat.send",params:{...R(D()),sessionId:s.sessionId,text:c,agentType:o?a.agentType:s.agentType,sessionMode:r?.sessionMode??s.sessionMode,managerConfig:r?g:s.managerConfig,workDir:o?a.workDir:s.workDir,agentSessionId:I,modelId:C(m?.modelId)??C(s.modelId),systemPrompt:a?.systemPrompt??s.systemPrompt??null,managerDefaultWorkerAgentType:r?r.managerDefaultWorkerAgentType:s.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:r?r.managerDefaultWorkerModelId:s.managerDefaultWorkerModelId,reasoningEffort:s.reasoningEffort??void 0,clientMessageId:s.clientMessageId??s.id,attachments:h,externalChannel:s.externalChannel,replyTarget:s.replyTarget,roomContextRegistryKey:a?.roomContextRegistryKey,activationCauseMessageId:t.at(-1)?.causeMessageId,rootCauseMessageId:t.at(-1)?.rootCauseMessageId,activationSequence:t.at(-1)?.sequence,activationHopCount:t.at(-1)?.hopCount,managedRecoverySource:i?.kind==="manager_event"?"manager_event":o?"managed_direct":t.length>0?"managed_room":void 0,managerEventId:i?.kind==="manager_event"?i.eventId:void 0,managedWorkerParentSessionId:n?.kind==="manager_worker"?n.parentSessionId:void 0,managerWorkerNativeFull:n?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isNativeSkillManager(n.parentSessionId,s.workDir)||void 0,managedRoomContextToken:a?.managedRoomContextToken,suppressExternalOwnerEcho:t.length>0||void 0,queuedBatchItems:e.map(_),waitForDispatch:!0}},a??void 0)}async isSessionBusy(e){const s=this.opts.getRuntime().recoveryBarrier;if(s?.isDispatchFrozen()||s?.isRecovering(e))return!0;const t=this.opts.getRuntime().sessions.get(e);if(!t)return!1;if(t.currentRunId){if(!(t.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!t.journalRunId)||(t.adapter.getStatus?await t.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:t.currentRunId}),t.currentRunId=null,t.currentRunPhase=null}if(!t.adapter.getStatus)return!1;const o=await t.adapter.getStatus().catch(()=>null);return o?.active?(o.runId&&(t.currentRunId=o.runId,t.currentRunPhase=o.runPhase??t.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{ye as ChatQueueManager,$ as TerminalQueuedChatDispatchError,Se as purgeQueuedSessionData};
|
|
1
|
+
import{NativeSourceDeletionStore as U}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as J}from"./queue-retry.js";import{findDuplicateQueuedMessage as E,stripLocalQueueFields as v,takeCompatibleBatch as G,formatQueuedBatch as Q,dedupeQueuedAttachments as B,classifyQueueError as F,isControllableQueueMessage as T,takeControllableMessage as H,normalizeQueuedModelId as q,resolveManagedRoomNativeSessionId as L}from"./queue-helpers.js";import{randomUUID as V}from"node:crypto";import{CODEX_DESKTOP_SEND_UNAVAILABLE as X,buildUserMessagePayload as Y}from"@shennian/wire";import{isCodexThreadTailInterrupted as Z}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as ee}from"./projection.js";import{parsePersonalAttachmentReferences as x}from"./attachment-reference.js";import{assertFinishedAttachmentReferences as W,markAttachmentReferences as b}from"./attachment-transfer-store.js";import{getPersonalSyncIdentity as R}from"../personal-sync/epoch.js";import{getDaemonInstallationId as D}from"../personal-sync/identity.js";import{appendMessage as j,getMessageDeliveryStatus as _,listSessionRecords as N,recordSession as z,tombstoneMessage as $,upsertMessage as C}from"./store.js";import{requestSessionIndexPublish as S}from"./index-publisher.js";import{purgeQueuedSessionData as te,readQueue as p,writeQueue as M}from"./queue-storage.js";import{getNativeSourceAgentType as se}from"./handlers/chat-events.js";import{purgeQueuedSessionData as Se}from"./queue-storage.js";class A extends Error{constructor(e){super(e),this.name="TerminalQueuedChatDispatchError"}}function P(){return new Date().toISOString()}function O(u){const e=P(),s=u.managedWorkerParentSessionId?{kind:"manager_worker",parentSessionId:u.managedWorkerParentSessionId}:u.managerEventId?{kind:"manager_event",eventId:u.managerEventId}:u.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"};return{...R(D()),id:u.queueMessageId||u.clientMessageId||`queue-${V()}`,sessionId:u.sessionId,text:u.text,agentType:u.agentType,sessionMode:u.sessionMode,managerConfig:u.managerConfig,workDir:u.workDir,agentSessionId:u.agentSessionId??null,modelId:q(u.modelId)??null,systemPrompt:u.systemPrompt??null,managerDefaultWorkerAgentType:u.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:u.managerDefaultWorkerModelId??null,reasoningEffort:u.reasoningEffort??null,clientMessageId:u.clientMessageId??null,attachments:x(u.attachments),externalChannel:u.externalChannel??null,replyTarget:u.replyTarget??null,origin:u.origin,createdAt:e,updatedAt:e,trigger:s}}function w(u){return{id:u.clientMessageId??u.id,sessionId:u.sessionId,role:u.trigger?.kind==="manager_event"?"agent":"user",ts:Date.parse(u.createdAt),payload:Y(u.text,u.attachments)}}class ye{opts;draining=new Set;promoting=new Set;disposed=!1;retries=new J(e=>{this.wakeSession(e)});deletions=new U;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){const s=p().sessions[e]??[],t=this.inFlightMessageIds.get(e);return{...R(D()),sessionId:e,busy:!!this.opts.getRuntime().sessions.get(e)?.currentRunId,pending:s.map(v),controllablePending:s.filter(o=>T(o)&&!t?.has(o.id)).map(v)}}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const s=this.opts.getRuntime(),t=p(),o=new Set,i=new Map;let n=!1;for(const r of e){const a=r.params;if(this.deletions.hasSession(a.sessionId)){delete t.sessions[a.sessionId],n=!0;continue}if(!a.sessionId||!a.text||!a.agentType||!a.workDir)throw new Error("sessionId, text, agentType and workDir are required");const g=O({...R(D()),...a});g.origin="room",g.managedRoom=r.context,g.trigger={kind:"room_activation",...r.context};const c=t.sessions[a.sessionId]??[],h=E(c,g),I=g.clientMessageId??g.id,m=_(a.sessionId,I);if(!h&&m.state==="not_found")c.push(g),t.sessions[a.sessionId]=c,i.set(`${g.sessionId}\0${I}`,g),o.add(a.sessionId),n=!0;else if(h&&m.state==="not_found")i.set(`${h.sessionId}\0${I}`,h),o.add(a.sessionId);else if(h&&m.state==="queued")o.add(a.sessionId);else if(h){const l=c.filter(k=>k.id!==h.id);l.length?t.sessions[a.sessionId]=l:delete t.sessions[a.sessionId],n=!0}}n&&M(t);let d;for(const r of o)try{for(const a of i.values())a.sessionId===r&&(j(r,w(a),"queued"),z({sessionId:r,agentType:a.agentType,sessionMode:a.sessionMode,managerConfig:a.managerConfig,workDir:a.workDir,agentSessionId:L(s,a),modelId:a.modelId}));this.logLifecycle("enqueue.persisted",r,{origin:"room",pendingCount:p().sessions[r]?.length??0}),this.broadcast(r),this.wakeSession(r)}catch(a){d=a,this.logLifecycle("enqueue.commit-failed",r,{failureClass:F(a instanceof Error?a.message:"","canonical_commit_failed")},"error"),this.retries.schedule(r,!0)}if(o.size&&S(s.client),d)throw d}async handleEnqueue(e){const s=this.opts.getRuntime(),t=e.params;if(ee(t.sessionListProjection),!t.sessionId||!t.text||!t.agentType||!t.workDir)return s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const o=t.managedAgentDirect?await this.prepareManagedAgentDirectTurn?.(t.sessionId):null;if(t.managedAgentDirect&&!o)throw new Error("managed_agent_context_unavailable");const i=o?N().find(K=>K.sessionId===t.sessionId):null,n=o?{...t,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId,modelId:i?.modelId??void 0,systemPrompt:o.systemPrompt,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:t,d=s.resolvePath(n.workDir),r=x(n.attachments);r?.length&&W(d,r);const a={text:n.text,attachments:r,localized:!1},g=s.sessions.get(n.sessionId);if(n.agentType==="codex"&&n.agentSessionId&&g?.currentRunId?.startsWith("dispatch:")&&Z(n.agentSessionId))return s.client.sendRes({type:"res",id:e.id,ok:!1,error:X}),!1;o?.managedRoomContextToken&&s.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const c=await this.isSessionBusy(n.sessionId),h=p(),I=h.sessions[n.sessionId]??[],m=O({...n,text:a.text,attachments:a.attachments,systemPrompt:o?null:n.systemPrompt});o&&(m.managedAgentDirect=!0,m.trigger?.kind!=="manager_event"&&(m.trigger={kind:"managed_direct"}));const l=m.clientMessageId??m.id,k=_(n.sessionId,l);if(k.state!=="not_found")return s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:k.state==="queued",queueMessageId:m.id,...k,queue:this.getSnapshot(n.sessionId)}}),!0;const y=E(I,m);y||(h.sessions[n.sessionId]=[...I,m],M(h));const f=y??m;return z({sessionId:f.sessionId,agentType:f.agentType,sessionMode:f.sessionMode,managerConfig:f.managerConfig,workDir:f.workDir,agentSessionId:f.agentSessionId,modelId:f.modelId}),j(f.sessionId,w(f),"queued"),b(s.resolvePath(f.workDir),f.attachments??[]),S(s.client),this.logLifecycle("enqueue.persisted",n.sessionId,{origin:n.origin??"app",queueMessageId:f.id,pendingCount:(p().sessions[n.sessionId]??[]).length}),this.broadcast(n.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:y?.id??m.id,..._(n.sessionId,y?.clientMessageId??y?.id??m.clientMessageId??m.id),queue:this.getSnapshot(n.sessionId),...a.localized?{localizedAttachments:!0}:{}}}),c?this.retries.schedule(n.sessionId):this.wakeSession(n.sessionId),!0}async handleGet(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId is required"});return}s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handleEdit(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId||!t.queueMessageId||!t.text){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, queueMessageId and text are required"});return}const o=p(),i=o.sessions[t.sessionId]??[],n=i.findIndex(a=>a.id===t.queueMessageId);if(n<0){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"Queued message not found"});return}if(!T(i[n])||this.inFlightMessageIds.get(t.sessionId)?.has(t.queueMessageId)){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"managed_agent_queue_mutation_forbidden"});return}const d=x(t.attachments),r=s.resolvePath(i[n].workDir);d?.length&&W(r,d),i[n]={...i[n],text:t.text,attachments:d,updatedAt:P()},o.sessions[t.sessionId]=i,M(o),C(t.sessionId,w(i[n]),"queued"),i[n].attachments?.length&&b(r,i[n].attachments??[]),S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handleDelete(e){const s=this.opts.getRuntime(),t=e.params;if(!t.sessionId||!t.queueMessageId){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId and queueMessageId are required"});return}const o=p(),i=o.sessions[t.sessionId]??[],n=i.find(r=>r.id===t.queueMessageId);if(n&&(!T(n)||this.inFlightMessageIds.get(t.sessionId)?.has(t.queueMessageId))){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"managed_agent_queue_mutation_forbidden"});return}const d=i.filter(r=>r.id!==t.queueMessageId);if(d.length===i.length){s.client.sendRes({type:"res",id:e.id,ok:!1,error:"Queued message not found"});return}d.length?o.sessions[t.sessionId]=d:delete o.sessions[t.sessionId],M(o),$(t.sessionId,n?.clientMessageId??n?.id??t.queueMessageId),S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId)}})}async handlePromote(e){const s=this.opts.getRuntime(),t=e.params,o=n=>s.client.sendRes({type:"res",id:e.id,ok:!1,error:n});if(!t.sessionId||!t.queueMessageId){o("sessionId and queueMessageId are required");return}if(this.promoting.has(t.sessionId)){o("queue_promotion_in_progress");return}this.promoting.add(t.sessionId);let i=[];try{for(;this.draining.has(t.sessionId);)await new Promise(r=>setTimeout(r,5));if(i=H(p().sessions[t.sessionId]??[],t.queueMessageId),!i.length){o("Queued message not found");return}this.inFlightMessageIds.set(t.sessionId,new Set(i.map(r=>r.id)));const n=s.sessions.get(t.sessionId);let d="idle";if(n?.currentRunId)if(this.canInjectActiveBatch(n,i)){const r=i.length===1?i[0].text:Q(i),a=i[0].clientMessageId??i[0].id;s.nativeFusion?.registerManagedSend({sessionId:t.sessionId,agentType:i[0].agentType,sourceAgentType:se(i[0].agentType,i[0].modelId),canonicalMessageId:a,sourceSessionKey:n.agentSessionId,text:r,managedEchoPolicy:"suppress_following"});const g=Date.now();try{await n.adapter.injectActiveInput({text:r,attachments:B(i.flatMap(c=>c.attachments??[])),clientMessageId:a})}catch(c){throw s.nativeFusion?.cancelManagedSend(a),c}for(const c of i)C(t.sessionId,{...w(c),ts:g},"executing");this.removeBatch(t.sessionId,i),d="injected"}else{if(!this.opts.interruptQueuedSession)throw new Error("queue_interrupt_unavailable");await this.opts.interruptQueuedSession(t.sessionId),await this.dispatchQueuedMessages(i),this.removeBatch(t.sessionId,i),d="restarted"}else await this.dispatchQueuedMessages(i),this.removeBatch(t.sessionId,i);S(s.client),this.broadcast(t.sessionId),s.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queue:this.getSnapshot(t.sessionId),promotedMessageIds:i.map(r=>r.id),mode:d}})}catch(n){o(n instanceof Error?n.message:"queue_promotion_failed"),this.broadcast(t.sessionId)}finally{this.inFlightMessageIds.delete(t.sessionId),this.promoting.delete(t.sessionId),p().sessions[t.sessionId]?.length&&this.wakeSession(t.sessionId)}}noteTerminal(e){this.wakeSession(e)}purgeSession(e){te(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const d=p().sessions[e]?.length??0;return this.purgeSession(e),d}const s=p(),t=s.sessions[e]??[],o=this.inFlightMessageIds.get(e)??new Set,i=t.filter(d=>d.managedRoom&&!o.has(d.id));if(i.length===0)return 0;const n=t.filter(d=>!i.includes(d));n.length?s.sessions[e]=n:delete s.sessions[e],M(s);for(const d of i)$(e,d.clientMessageId??d.id);return S(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:i.length,pendingCount:n.length}),this.broadcast(e),i.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=p();for(const s of Object.keys(e.sessions))this.wakeSession(s)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let s=!1,t=!1,o=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const g=p().sessions[e]?.length??0,c=this.deferredLogState.get(e),h=Date.now();(!c||c.pendingCount!==g||h-c.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:g}),this.deferredLogState.set(e,{at:h,pendingCount:g}));return}this.deferredLogState.delete(e);const i=p(),n=i.sessions[e]??[],d=n.filter(g=>{const c=g.clientMessageId??g.id,h=_(e,c).state;return h==="queued"||h==="not_found"});d.length!==n.length&&(d.length?i.sessions[e]=d:delete i.sessions[e],M(i),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:n.length-d.length,pendingCount:d.length}));const r=G(d);if(r.length===0){this.broadcast(e);return}o=r,this.inFlightMessageIds.set(e,new Set(r.map(g=>g.id))),this.logLifecycle("dispatch.start",e,{batchCount:r.length,queueMessageId:r[0].id,origin:r[0].origin??"app"});for(const g of r)C(e,w(g),"queued");await this.dispatchQueuedMessages(r);const a=this.removeBatch(e,r);this.logLifecycle("dispatch.accepted",e,{batchCount:r.length,queueMessageId:r[0].id,pendingCount:a}),this.deferredLogState.delete(e),s=a>0,this.broadcast(e)}catch(i){const n=F(i instanceof Error?i.message:String(i),i instanceof A?"terminal_dispatch_failed":"transient_dispatch_failed");if(i instanceof A||n==="managed_claim_source_binding_conflict"){const r=this.removeBatch(e,o);this.logLifecycle("dispatch.terminal-failure",e,{batchCount:o.length,queueMessageId:o[0]?.id,pendingCount:r,failureClass:n},"error"),s=r>0}else t=!0,this.logLifecycle("dispatch.transient-failure",e,{failureClass:n},"error");this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e),p().sessions[e]?.length?s?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,t):this.retries.cancel(e)}}canInjectActiveBatch(e,s){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const t=this.opts.getRuntime().runJournal?.get(s[0].sessionId,e.journalRunId),o=s[0].trigger?.kind==="managed_direct"||s[0].managedAgentDirect?null:"personal";return!!(o&&s[0].systemPrompt==null&&t&&t.source===o&&t.deliveryMode==="direct"&&t.agentType===s[0].agentType&&t.workDir===e.workDir&&t.agentSessionId===e.agentSessionId&&t.modelId===(s[0].modelId??null)&&t.reasoningEffort===(s[0].reasoningEffort??null))}removeBatch(e,s){if(s.length===0)return p().sessions[e]?.length??0;const t=p(),o=new Set(s.map(n=>n.id)),i=(t.sessions[e]??[]).filter(n=>!o.has(n.id));return i.length?t.sessions[e]=i:delete t.sessions[e],M(t),i.length}logLifecycle(e,s,t,o="info"){const i=`[chat.queue] ${JSON.stringify({at:P(),event:e,sessionId:s,...t})}`;o==="error"?console.error(i):console.info(i)}async dispatchQueuedMessages(e){const s=e[0],t=e.flatMap(l=>{if(l.trigger?.kind==="room_activation"){const{kind:k,...y}=l.trigger;return[y]}return l.managedRoom?[l.managedRoom]:[]}),o=e.some(l=>l.trigger?.kind==="managed_direct"||!!l.managedAgentDirect),i=e.find(l=>l.trigger?.kind==="manager_event")?.trigger,n=e.find(l=>l.trigger?.kind==="manager_worker")?.trigger,d=t.length>0?await this.prepareManagedRoomTurn?.(t):o?await this.prepareManagedAgentDirectTurn?.(s.sessionId):void 0;if(t.length>0&&!d)throw new Error("managed_room_turn_preparer_unavailable");if(o&&!d)throw new Error("managed_agent_context_unavailable");const r=new Set((p().sessions[s.sessionId]??[]).map(l=>l.id));if(this.disposed||this.deletions.hasSession(s.sessionId)||e.some(l=>!r.has(l.id)))throw d?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(d.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new A("queued_dispatch_cancelled");const a=d??null,g=a?.sessionMode==="manager"?a.managerConfig:null,c=e.length===1?s.text:Q(e),h=B(e.flatMap(l=>l.attachments??[])),I=o?d.agentSessionId:t.length>0?L(this.opts.getRuntime(),s):s.agentSessionId??null,m=d?N().find(l=>l.sessionId===s.sessionId):null;await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${s.id}-${Date.now()}`,method:"chat.send",params:{...R(D()),sessionId:s.sessionId,text:c,agentType:o?d.agentType:s.agentType,sessionMode:a?.sessionMode??s.sessionMode,managerConfig:a?g:s.managerConfig,workDir:o?d.workDir:s.workDir,agentSessionId:I,modelId:q(m?.modelId)??q(s.modelId),systemPrompt:d?.systemPrompt??s.systemPrompt??null,managerDefaultWorkerAgentType:a?a.managerDefaultWorkerAgentType:s.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:a?a.managerDefaultWorkerModelId:s.managerDefaultWorkerModelId,reasoningEffort:s.reasoningEffort??void 0,clientMessageId:s.clientMessageId??s.id,attachments:h,externalChannel:s.externalChannel,replyTarget:s.replyTarget,roomContextRegistryKey:d?.roomContextRegistryKey,activationCauseMessageId:t.at(-1)?.causeMessageId,rootCauseMessageId:t.at(-1)?.rootCauseMessageId,activationSequence:t.at(-1)?.sequence,activationHopCount:t.at(-1)?.hopCount,managedRecoverySource:i?.kind==="manager_event"?"manager_event":o?"managed_direct":t.length>0?"managed_room":void 0,managerEventId:i?.kind==="manager_event"?i.eventId:void 0,managedWorkerParentSessionId:n?.kind==="manager_worker"?n.parentSessionId:void 0,managerWorkerNativeFull:n?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isNativeSkillManager(n.parentSessionId,s.workDir)||void 0,managedRoomContextToken:d?.managedRoomContextToken,suppressExternalOwnerEcho:t.length>0||void 0,queuedBatchItems:e.map(v),waitForDispatch:!0}},d??void 0)}async isSessionBusy(e){const s=this.opts.getRuntime().recoveryBarrier;if(s?.isDispatchFrozen()||s?.isRecovering(e))return!0;const t=this.opts.getRuntime().sessions.get(e);if(!t)return!1;if(t.currentRunId){if(!(t.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!t.journalRunId)||(t.adapter.getStatus?await t.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:t.currentRunId}),t.currentRunId=null,t.currentRunPhase=null}if(!t.adapter.getStatus)return!1;const o=await t.adapter.getStatus().catch(()=>null);return o?.active?(o.runId&&(t.currentRunId=o.runId,t.currentRunPhase=o.runPhase??t.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{ye as ChatQueueManager,A as TerminalQueuedChatDispatchError,Se as purgeQueuedSessionData};
|