shennian 0.5.2 → 0.5.4
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/bin/shennian-adapter-host.js +4 -0
- package/dist/publish-build-manifest.json +144 -74
- package/dist/resources/agent-adapters/claude.md +33 -0
- package/dist/resources/agent-adapters/codex.md +33 -0
- package/dist/resources/agent-adapters/cursor.md +32 -0
- package/dist/resources/agent-adapters/custom.md +40 -0
- package/dist/resources/agent-adapters/opencode.md +31 -0
- package/dist/resources/agent-adapters/pi-coding-agent.md +31 -0
- package/dist/resources/agent-adapters/workbuddy.md +32 -0
- package/dist/src/adapter-kit/check.js +4 -0
- package/dist/src/adapter-kit/host.js +2 -0
- package/dist/src/adapter-kit/official-adapters.js +1 -0
- package/dist/src/adapter-kit/registry.js +2 -0
- package/dist/src/adapter-kit/submission-client.js +1 -0
- package/dist/src/adapter-kit/types.js +1 -0
- package/dist/src/agents/acp/client-services.js +1 -1
- package/dist/src/agents/acp/process-client.js +1 -1
- package/dist/src/agents/config-status.js +1 -1
- package/dist/src/agents/custom.js +5 -4
- package/dist/src/agents/detect.js +1 -1
- package/dist/src/agents/model-registry/cache.js +1 -1
- package/dist/src/agents/model-registry/discovery.js +3 -3
- package/dist/src/agents/model-registry/opencode-api.js +1 -1
- package/dist/src/agents/model-registry/service.js +1 -1
- package/dist/src/agents/node-adapter.js +7 -0
- package/dist/src/agents/opencode.js +1 -1
- package/dist/src/agents/pi-coding-agent.js +3 -3
- package/dist/src/agents/pi-turn-diagnostics.js +1 -0
- package/dist/src/agents/process-tree.js +1 -0
- package/dist/src/agents/public-agent-client.js +1 -0
- package/dist/src/commands/adapter.js +49 -0
- package/dist/src/commands/agent-readiness.js +2 -2
- package/dist/src/commands/agent-workspace.js +3 -0
- package/dist/src/commands/agent.js +2 -2
- package/dist/src/commands/room.js +4 -3
- package/dist/src/commands/runtime.js +5 -5
- package/dist/src/commands/support.js +4 -0
- package/dist/src/daemon-ipc/agent-readiness.js +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/manager/runtime.js +4 -4
- package/dist/src/room/activation-policy.js +1 -1
- package/dist/src/room/activation-service.js +2 -1
- package/dist/src/room/attachment-upload.js +1 -1
- package/dist/src/room/invite-bootstrap.js +1 -1
- package/dist/src/room/live-delivery.js +1 -1
- package/dist/src/room/managed-prompt-composer.js +2 -2
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/room/mirror-sync-service.js +1 -1
- package/dist/src/room/public-room-client.js +1 -1
- package/dist/src/room/room-action-client.js +1 -1
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
- package/dist/src/session/handlers/chat-recovery.js +1 -1
- package/dist/src/session/handlers/chat.js +1 -1
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/queue-helpers.js +8 -3
- package/dist/src/session/queue.js +1 -1
- package/dist/src/support/support-client.js +1 -0
- package/node_modules/@shennian/wire/dist/adapter-submission.js +1 -0
- package/node_modules/@shennian/wire/dist/index.js +1 -1
- package/node_modules/@shennian/wire/dist/session.js +1 -1
- package/node_modules/@shennian/wire/dist/support.js +1 -0
- package/package.json +4 -4
- package/dist/src/agents/acp/process-tree.js +0 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import{listSessionRecords as p}from"./store.js";const _={allowedRoomActions:["send"],propagateWorkerRoomOrigin:!1};function I(n,r){return n?{roomOrigin:n.roomOrigin,allowedRoomActions:n.roomOrigin?["send"]:[],managerEvent:!0}:r?_:void 0}function
|
|
1
|
+
import{listSessionRecords as p}from"./store.js";const _={allowedRoomActions:["send"],propagateWorkerRoomOrigin:!1};function I(n,r){return n?{roomOrigin:n.roomOrigin,allowedRoomActions:n.roomOrigin?["send"]:[],managerEvent:!0}:r?_:void 0}function R(n,r){const e=l(r);if(e)return n.find(i=>l(i)===e)??null;if(r.origin!=="external")return null;const t=g(r);return n.find(i=>g(i)===t)??null}function b(n){const{dispatchBlock:r,origin:e,managedRoom:t,managedAgentDirect:i,trigger:a,externalQueuedSubmissionId:o,...u}=n;return u}function S(n){const r=n.reduce((o,u)=>{const d=c(u);return o===null||d<o?d:o},null);if(r===null)return[];const e=n.filter(o=>c(o)===r),t=e[0];if(!t)return[];if(s(t))return[t];if(t.trigger?.kind==="manager_worker"||t.trigger?.kind==="scheduled")return[t];const i=f(t),a=[];for(const o of e){if(f(o)!==i)break;a.push(o)}return a}function s(n){if(n.origin==="external"||n.origin==="room"||n.managedRoom)return!1;const r=n.trigger?.kind;return r==null||r==="personal"||r==="managed_direct"}function y(n){return n?.trim()||void 0}function D(n,r){const e=n.find(t=>t.id===r&&s(t));return e?[e]:[]}function c(n){const r=m(n).kind;return r==="personal"||r==="managed_direct"?0:r==="manager_event"||r==="manager_worker"?1:2}function m(n){const r=n.trigger;return r?r.kind==="room_activation"?{kind:r.kind,registryKey:r.registryKey}:r.kind==="manager_worker"?{kind:r.kind,parentSessionId:r.parentSessionId,roomOrigin:r.roomOrigin??null}:r.kind==="manager_event"?{kind:r.kind,roomOrigin:r.roomOrigin??null}:{kind:r.kind}:n.managedRoom?{kind:"room_activation",registryKey:n.managedRoom.registryKey}:n.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"}}function f(n){return JSON.stringify({agentType:n.agentType,sessionMode:n.sessionMode??null,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:y(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,roomInputKind:n.managedRoom?n.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
|
|
2
|
+
`)?"event":"message":null,trigger:m(n)})}function M(n){return n.every(r=>r.managedRoom)?n.every(r=>r.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
|
|
3
|
+
`))?`[\u7FA4\u4E8B\u4EF6]
|
|
4
|
+
${n.map(r=>r.text.trim().slice(6)).filter(Boolean).join(`
|
|
5
|
+
|
|
6
|
+
`)}`:`[\u7FA4\u6D88\u606F]
|
|
2
7
|
${n.map(r=>k(r.text)).filter(Boolean).join(`
|
|
3
8
|
|
|
4
9
|
`)}`:`[\u8FDE\u7EED\u7528\u6237\u6D88\u606F]
|
|
@@ -7,5 +12,5 @@ ${r.text.trim()}`).join(`
|
|
|
7
12
|
|
|
8
13
|
`)}`}function k(n){const r=n.trim(),e=r.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);return e?`<${e[1]}>
|
|
9
14
|
${e[2]}`:r.startsWith(`[\u7FA4\u6D88\u606F]
|
|
10
|
-
`)?r.slice(6):r}function g(n){const r=
|
|
11
|
-
`)}function
|
|
15
|
+
`)?r.slice(6):r}function g(n){const r=l(n);return r?`id:${r}`:["body",h(n.text),...(n.attachments??[]).map(e=>e.path||`${e.name}:${e.mimeType}`)].join(`
|
|
16
|
+
`)}function l(n){const r=typeof n.clientMessageId=="string"?n.clientMessageId.trim():"";if(r)return r;const e=typeof n.id=="string"?n.id.trim():"";return e&&!e.startsWith("queue-")?e:""}function v(n){const r=new Set,e=[];for(const t of n){const i=t.path||`${t.name}:${t.mimeType}`;r.has(i)||(r.add(i),e.push(t))}return e.length?e:void 0}function h(n){return String(n||"").replace(/\s+/g," ").trim()}function O(n,r){const e=n.toLowerCase();if(e.includes("managed claim session conflicts with source binding"))return"managed_claim_source_binding_conflict";const t=e.match(/\b(?:managed_(?:agent|room)|agent_validation|acp|native|codex)_[a-z0-9_]+\b/)?.[0];return t||(e.includes("no rollout found")?"missing_rollout":e.includes("managed_room_permission_snapshot_mismatch")?"managed_room_permission_snapshot_mismatch":e.includes("managed_room_prompt_snapshot_mismatch")?"managed_room_prompt_snapshot_mismatch":e.includes("managed_room_turn_preparer_unavailable")?"managed_room_turn_preparer_unavailable":e.includes("timeout")?"timeout":e.includes("connection")?"connection_error":r)}function T(n,r){if(n.sessions.has(r.sessionId))return null;const e=p().find(t=>t.sessionId===r.sessionId)?.agentSessionId?.trim();return!e||e.startsWith("managed:")?null:e}export{_ as OWNER_DIRECT_TURN_OPTIONS,O as classifyQueueError,v as dedupeQueuedAttachments,R as findDuplicateQueuedMessage,M as formatQueuedBatch,s as isControllableQueueMessage,I as managedDirectTurnOptions,y as normalizeQueuedModelId,T as resolveManagedRoomNativeSessionId,b as stripLocalQueueFields,S as takeCompatibleBatch,D as takeControllableMessage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{NativeSourceDeletionStore as N}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as z}from"./queue-retry.js";import{findDuplicateQueuedMessage as x,stripLocalQueueFields as $,takeCompatibleBatch as T,formatQueuedBatch as J,dedupeQueuedAttachments as K,classifyQueueError as G,normalizeQueuedModelId as _,resolveManagedRoomNativeSessionId as D,managedDirectTurnOptions as q}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as U}from"@shennian/wire";import{isCodexThreadTailInterrupted as H}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as V}from"./projection.js";import{assertFinishedAttachmentReferences as X,markAttachmentReferences as Y}from"./attachment-transfer-store.js";import{appendMessage as A,getMessageDeliveryStatus as R,listSessionRecords as E,recordSession as B,tombstoneMessage as Z,upsertMessage as ee}from"./store.js";import{handleQueueDispatchFailure as te,queueBlockedUntil as Q,resolveQueueRecoveryNotice as P}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as ne}from"../agents/command-spec.js";import{requestSessionIndexPublish as w}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as se,purgeQueuedSessionData as ie,readQueue as m,writeQueue as M}from"./queue-storage.js";import{parsePersonalAttachmentReferences as re}from"./attachment-reference.js";import{getPersonalSyncIdentity as b}from"../personal-sync/epoch.js";import{getDaemonInstallationId as W}from"../personal-sync/identity.js";import{isTrustedManagerEvent as ae}from"./manager-event-authority.js";import{getQueueSnapshot as oe,handleQueueDelete as de,handleQueueEdit as ue,handleQueueGet as ge,handleQueuePromote as le}from"./queue-control.js";import{TerminalQueuedChatDispatchError as L,nowIso as F,queueEnvelope as C,queueMessageFromParams as O}from"./queue-message.js";import{purgeQueuedSessionData as Qe}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as be}from"./queue-message.js";class Ae{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new z(e=>{this.wakeSession(e)});deletions=new N;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,se(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return oe({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=m(),i=new Set,o=new Map;let d=!1;for(const a of e){const s=a.params;if(this.deletions.hasSession(s.sessionId)){delete n.sessions[s.sessionId],d=!0;continue}if(!s.sessionId||!s.text||!s.agentType||!s.workDir)throw new Error("sessionId, text, agentType and workDir are required");const u=O({...b(W()),...s});typeof s.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(s.roomMessageCreatedAt))&&(u.createdAt=new Date(s.roomMessageCreatedAt).toISOString()),u.origin="room",u.managedRoom=a.context,u.trigger={kind:"room_activation",...a.context};const g=n.sessions[s.sessionId]??[],l=x(g,u),f=u.clientMessageId??u.id,S=R(s.sessionId,f);if(!l&&S.state==="not_found")g.push(u),n.sessions[s.sessionId]=g,o.set(`${u.sessionId}\0${f}`,u),i.add(s.sessionId),d=!0;else if(l&&S.state==="not_found")o.set(`${l.sessionId}\0${f}`,l),i.add(s.sessionId);else if(l&&S.state==="queued")i.add(s.sessionId);else if(l){const y=g.filter(k=>k.id!==l.id);y.length?n.sessions[s.sessionId]=y:delete n.sessions[s.sessionId],d=!0}}d&&M(n);let r;for(const a of i)try{for(const s of o.values())s.sessionId===a&&(A(a,C(s),"queued"),B({sessionId:a,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:D(t,s),modelId:s.modelId}));this.logLifecycle("enqueue.persisted",a,{origin:"room",pendingCount:m().sessions[a]?.length??0}),this.broadcast(a),this.wakeSession(a)}catch(s){r=s,this.logLifecycle("enqueue.commit-failed",a,{failureClass:G(s instanceof Error?s.message:"","canonical_commit_failed")},"error"),this.retries.schedule(a,!0)}if(i.size&&w(t.client),r)throw r}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)&&!ae(e))throw new Error("manager_event_source_untrusted");const o=!!(t&&i.scheduledTask?.bindingId);if(V(i.sessionListProjection),!i.sessionId||!i.text||!i.agentType||!i.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const d=q(i.managerEventId?{roomOrigin:i.managerEventRoomOrigin}:null,!!i.managedAgentDirect),r=i.managedAgentDirect||o?await this.prepareManagedAgentDirectTurn?.(i.sessionId,d):null;if((i.managedAgentDirect||o)&&!r)throw new Error("managed_agent_context_unavailable");const a=r?E().find(j=>j.sessionId===i.sessionId):null,s=r?{...i,...r,agentType:r.agentType,sessionMode:r.sessionMode,managerConfig:r.managerConfig,workDir:r.workDir,agentSessionId:r.agentSessionId?.startsWith("managed:")?a?.agentSessionId&&!a.agentSessionId.startsWith("managed:")?a.agentSessionId:null:r.agentSessionId,modelId:a?.modelId??void 0,systemPrompt:r.systemPrompt,externalChannel:i.managedAgentDirect?null:i.externalChannel,replyTarget:i.managedAgentDirect?null:i.replyTarget,managerDefaultWorkerAgentType:r.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:r.managerDefaultWorkerModelId}:i,u=n.resolvePath(s.workDir),g=re(s.attachments);g?.length&&X(u,g);const l={text:s.text,attachments:g,localized:!1},f=n.sessions.get(s.sessionId);if(s.agentType==="codex"&&s.agentSessionId&&f?.currentRunId?.startsWith("dispatch:")&&H(s.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:U}),!1;r?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(r.managedRoomContextToken);const S=await this.isSessionBusy(s.sessionId),y=m(),k=y.sessions[s.sessionId]??[],h=O({...s,text:l.text,attachments:l.attachments,systemPrompt:r?null:s.systemPrompt});r&&(i.managedAgentDirect&&(h.managedAgentDirect=!0),h.trigger?.kind!=="manager_event"&&h.trigger?.kind!=="scheduled"&&(h.trigger={kind:"managed_direct"}));const v=h.clientMessageId??h.id,c=R(s.sessionId,v);if(c.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:c.state==="queued",queueMessageId:h.id,...c,queue:this.getSnapshot(s.sessionId)}}),!0;const I=x(k,h);I||(y.sessions[s.sessionId]=[...k,h],M(y));const p=I??h;return B({sessionId:p.sessionId,agentType:p.agentType,sessionMode:p.sessionMode,managerConfig:p.managerConfig,workDir:p.workDir,agentSessionId:p.agentSessionId,modelId:p.modelId}),A(p.sessionId,C(p),"queued"),Y(n.resolvePath(p.workDir),p.attachments??[]),w(n.client),this.logLifecycle("enqueue.persisted",s.sessionId,{origin:s.origin??"app",queueMessageId:p.id,pendingCount:(m().sessions[s.sessionId]??[]).length}),this.broadcast(s.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:I?.id??h.id,...R(s.sessionId,I?.clientMessageId??I?.id??h.clientMessageId??h.id),queue:this.getSnapshot(s.sessionId),...l.localized?{localizedAttachments:!0}:{}}}),S?this.retries.schedule(s.sessionId):this.wakeSession(s.sessionId),!0}async handleGet(e){await ge(this.queueControlContext(),e)}async handleEdit(e){await ue(this.queueControlContext(),e)}async handleDelete(e){await de(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await le({...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=m().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){ie(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const r=m().sessions[e]?.length??0;return this.purgeSession(e),r}const t=m(),n=t.sessions[e]??[],i=this.inFlightMessageIds.get(e)??new Set,o=n.filter(r=>r.managedRoom&&!i.has(r.id));if(o.length===0)return 0;const d=n.filter(r=>!o.includes(r));d.length?t.sessions[e]=d:delete t.sessions[e],M(t);for(const r of o)Z(e,r.clientMessageId??r.id);return w(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:o.length,pendingCount:d.length}),this.broadcast(e),o.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=m();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 g=m().sessions[e]?.length??0,l=this.deferredLogState.get(e),f=Date.now();(!l||l.pendingCount!==g||f-l.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:g}),this.deferredLogState.set(e,{at:f,pendingCount:g}));return}this.deferredLogState.delete(e);const o=m(),d=o.sessions[e]??[],r=d.filter(g=>{const l=g.clientMessageId??g.id,f=R(e,l).state;return f==="queued"||f==="not_found"});if(r.length!==d.length&&(r.length?o.sessions[e]=r:delete o.sessions[e],M(o),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:d.length-r.length,pendingCount:r.length})),r.some(g=>!!g.externalQueuedSubmissionId)){this.broadcast(e);return}const a=T(r);if(a.length===0){this.broadcast(e);return}if(Q(a))return;a.some(g=>(g.dispatchBlock?.retryAt??0)>0)&&ne(),i=a,this.inFlightMessageIds.set(e,new Set(a.map(g=>g.id))),this.logLifecycle("dispatch.start",e,{batchCount:a.length,queueMessageId:a[0].id,origin:a[0].origin??"app"}),this.broadcast(e);for(const g of a)ee(e,C(g),"queued");const s=await this.dispatchQueuedMessages(a);if(s.deliveryMode==="external_owner_queue"){this.markExternalQueued(a,s.queuedSubmissionId),P(a),a.some(g=>g.dispatchBlock)&&w(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:a.length,queueMessageId:a[0].id}),this.broadcast(e);return}const u=this.removeBatch(e,a);P(a),a.some(g=>g.dispatchBlock)&&w(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:a.length,queueMessageId:a[0].id,pendingCount:u}),this.deferredLogState.delete(e),t=u>0,this.broadcast(e)}catch(o){const d=te({error:o,sessionId:e,batch:i,publish:()=>w(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,i),log:(r,a)=>this.logLifecycle(r,e,a,"error")});t=d.drainAgain,n=d.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const o=m().sessions[e]??[];o.length?(this.broadcast(e),o.some(d=>!!d.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,Q(T(o)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=m(),i=n.sessions[e]??[],o=i.filter(d=>(d.clientMessageId??d.id)!==t);o.length!==i.length&&(o.length?n.sessions[e]=o:delete n.sessions[e],M(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 m().sessions[e]?.length??0;const n=m(),i=new Set(t.map(d=>d.id)),o=(n.sessions[e]??[]).filter(d=>!i.has(d.id));return o.length?n.sessions[e]=o:delete n.sessions[e],M(n),o.length}logLifecycle(e,t,n,i="info"){const o=`[chat.queue] ${JSON.stringify({at:F(),event:e,sessionId:t,...n})}`;i==="error"?console.error(o):console.info(o)}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 L("schedule_target_unavailable");const i=e.flatMap(c=>{if(c.trigger?.kind==="room_activation"){const{kind:I,...p}=c.trigger;return[p]}return!c.trigger&&c.managedRoom?[c.managedRoom]:[]}),o=e.find(c=>c.trigger?.kind==="manager_event")?.trigger,d=e.some(c=>c.trigger?.kind==="managed_direct"||!!c.managedAgentDirect),r=d||!!n?.bindingId,a=e.find(c=>c.trigger?.kind==="manager_worker")?.trigger,s=o?.kind==="manager_event"||d,u=i.length>0?await this.prepareManagedRoomTurn?.(i):r||o?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,q(o?.kind==="manager_event"?o:null,d)):void 0;if(i.length>0&&!u)throw new Error("managed_room_turn_preparer_unavailable");if(r&&!u)throw new Error("managed_agent_context_unavailable");if(o?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!u)throw new Error("managed_agent_context_unavailable");const g=new Set((m().sessions[t.sessionId]??[]).map(c=>c.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(c=>!g.has(c.id)))throw u?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(u.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new L("queued_dispatch_cancelled");const l=u??null,f=l?.sessionMode==="manager"?l.managerConfig:null,S=e.length===1?t.text:J(e),y=K(e.flatMap(c=>c.attachments??[])),k=r||o?.kind==="manager_event"&&!!u,h=k?u.agentSessionId?.startsWith("managed:")?D(this.opts.getRuntime(),t):u.agentSessionId:i.length>0?D(this.opts.getRuntime(),t):t.agentSessionId??null,v=u?E().find(c=>c.sessionId===t.sessionId):null;return await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${t.id}-${Date.now()}`,method:"chat.send",params:{...b(W()),sessionId:t.sessionId,text:S,agentType:k?u.agentType:t.agentType,sessionMode:l?.sessionMode??t.sessionMode,managerConfig:l?f:t.managerConfig,workDir:k?u.workDir:t.workDir,agentSessionId:h,modelId:_(v?.modelId)??_(t.modelId),systemPrompt:u?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:l?l.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:l?l.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:y,externalChannel:s?void 0:t.externalChannel,replyTarget:s?void 0:t.replyTarget,roomContextRegistryKey:s?void 0:u?.roomContextRegistryKey,activationCauseMessageId:s?void 0:i.at(-1)?.causeMessageId,rootCauseMessageId:s?void 0:i.at(-1)?.rootCauseMessageId,activationSequence:s?void 0:i.at(-1)?.sequence,activationHopCount:s?void 0:i.at(-1)?.hopCount,managedRecoverySource:o?.kind==="manager_event"?"manager_event":r?"managed_direct":i.length>0?"managed_room":void 0,managerEventId:o?.kind==="manager_event"?o.eventId:void 0,managedWorkerParentSessionId:a?.kind==="manager_worker"?a.parentSessionId:void 0,managerWorkerRoomOrigin:a?.kind==="manager_worker"?a.roomOrigin:void 0,managerWorkerNativeFull:a?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(a.parentSessionId,t.workDir)||void 0,managedRoomContextToken:u?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:i.length>0||!!n||void 0,queuedBatchItems:e.map(c=>{const I=$(c);return s?{...I,systemPrompt:u?.systemPrompt??null,externalChannel:null,replyTarget:null}:I}),waitForDispatch:!0}},u??void 0)??{}}markExternalQueued(e,t){const n=m(),i=new Set(e.map(r=>r.id)),o=n.sessions[e[0].sessionId]??[];let d=!1;for(const r of o)i.has(r.id)&&(r.externalQueuedSubmissionId=t||r.id,r.updatedAt=F(),d=!0);d&&M(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{Ae as ChatQueueManager,be as TerminalQueuedChatDispatchError,Qe as purgeQueuedSessionData};
|
|
1
|
+
import{NativeSourceDeletionStore as $}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as J}from"./queue-retry.js";import{findDuplicateQueuedMessage as q,stripLocalQueueFields as K,takeCompatibleBatch as A,formatQueuedBatch as G,dedupeQueuedAttachments as U,classifyQueueError as H,normalizeQueuedModelId as w,resolveManagedRoomNativeSessionId as x,managedDirectTurnOptions as E}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as V}from"@shennian/wire";import{isCodexThreadTailInterrupted as X}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as Y}from"./projection.js";import{assertFinishedAttachmentReferences as Z,markAttachmentReferences as ee}from"./attachment-transfer-store.js";import{appendMessage as B,getMessageDeliveryStatus as C,listSessionRecords as Q,recordSession as P,tombstoneMessage as te,upsertMessage as ne}from"./store.js";import{handleQueueDispatchFailure as se,queueBlockedUntil as b,resolveQueueRecoveryNotice as W}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as ie}from"../agents/command-spec.js";import{requestSessionIndexPublish as R}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as re,purgeQueuedSessionData as ae,readQueue as m,writeQueue as y}from"./queue-storage.js";import{parsePersonalAttachmentReferences as oe}from"./attachment-reference.js";import{getPersonalSyncIdentity as L}from"../personal-sync/epoch.js";import{getDaemonInstallationId as F}from"../personal-sync/identity.js";import{isTrustedManagerEvent as de}from"./manager-event-authority.js";import{getQueueSnapshot as ue,handleQueueDelete as le,handleQueueEdit as ge,handleQueueGet as ce,handleQueuePromote as me}from"./queue-control.js";import{TerminalQueuedChatDispatchError as O,nowIso as j,queueEnvelope as T,queueMessageFromParams as N}from"./queue-message.js";import{purgeQueuedSessionData as be}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as Le}from"./queue-message.js";class Be{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new J(e=>{this.wakeSession(e)});deletions=new $;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,re(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return ue({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=m(),r=new Set,o=new Map;let i=!1;for(const d of e){const s=d.params;if(this.deletions.hasSession(s.sessionId)){delete n.sessions[s.sessionId],i=!0;continue}if(!s.sessionId||!s.text||!s.agentType||!s.workDir)throw new Error("sessionId, text, agentType and workDir are required");const u=N({...L(F()),...s});typeof s.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(s.roomMessageCreatedAt))&&(u.createdAt=new Date(s.roomMessageCreatedAt).toISOString()),u.origin="room",u.managedRoom=d.context,u.trigger={kind:"room_activation",...d.context};const a=n.sessions[s.sessionId]??[],c=q(a,u),h=u.clientMessageId??u.id,I=C(s.sessionId,h);if(!c&&I.state==="not_found")a.push(u),n.sessions[s.sessionId]=a,o.set(`${u.sessionId}\0${h}`,u),r.add(s.sessionId),i=!0;else if(c&&I.state==="not_found")o.set(`${c.sessionId}\0${h}`,c),r.add(s.sessionId);else if(c&&I.state==="queued")r.add(s.sessionId);else if(c){const M=a.filter(k=>k.id!==c.id);M.length?n.sessions[s.sessionId]=M:delete n.sessions[s.sessionId],i=!0}}i&&y(n);let l;for(const d of r)try{for(const s of o.values())s.sessionId===d&&(B(d,T(s),"queued"),P({sessionId:d,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:x(t,s),modelId:s.modelId}));this.logLifecycle("enqueue.persisted",d,{origin:"room",pendingCount:m().sessions[d]?.length??0}),this.broadcast(d),this.wakeSession(d)}catch(s){l=s,this.logLifecycle("enqueue.commit-failed",d,{failureClass:H(s instanceof Error?s.message:"","canonical_commit_failed")},"error"),this.retries.schedule(d,!0)}if(r.size&&R(t.client),l)throw l}async handleEnqueue(e,t=!1){const n=this.opts.getRuntime(),r=e.params;if(r.scheduledTask&&!t)throw new Error("schedule_source_untrusted");if((r.managerEventId||r.managerEventRoomOrigin||r.managedWorkerParentSessionId||r.managerWorkerRoomOrigin||e.params.managerWorkerNativeFull||e.params.managedRecoverySource)&&!de(e))throw new Error("manager_event_source_untrusted");const o=!t&&!r.managedWorkerParentSessionId?n.managerRuntime?.getWorkerControllerSessionId?.(String(r.sessionId??""),String(r.workDir??"")):null,i=o?{...r,managedWorkerParentSessionId:o}:r,l=!!(t&&i.scheduledTask?.bindingId);if(Y(i.sessionListProjection),!i.sessionId||!i.text||!i.agentType||!i.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const d=E(i.managerEventId?{roomOrigin:i.managerEventRoomOrigin}:null,!!i.managedAgentDirect),s=i.managedAgentDirect||l?await this.prepareManagedAgentDirectTurn?.(i.sessionId,d):null;if((i.managedAgentDirect||l)&&!s)throw new Error("managed_agent_context_unavailable");const u=s?Q().find(z=>z.sessionId===i.sessionId):null,a=s?{...i,...s,agentType:s.agentType,sessionMode:s.sessionMode,managerConfig:s.managerConfig,workDir:s.workDir,agentSessionId:s.agentSessionId?.startsWith("managed:")?u?.agentSessionId&&!u.agentSessionId.startsWith("managed:")?u.agentSessionId:null:s.agentSessionId,modelId:s.effectiveModelId!==void 0?w(s.effectiveModelId):u?.modelId??void 0,systemPrompt:s.systemPrompt,externalChannel:i.managedAgentDirect?null:i.externalChannel,replyTarget:i.managedAgentDirect?null:i.replyTarget,managerDefaultWorkerAgentType:s.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:s.managerDefaultWorkerModelId}:i,c=n.resolvePath(a.workDir),h=oe(a.attachments);h?.length&&Z(c,h);const I={text:a.text,attachments:h,localized:!1},M=n.sessions.get(a.sessionId);if(a.agentType==="codex"&&a.agentSessionId&&M?.currentRunId?.startsWith("dispatch:")&&X(a.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:V}),!1;s?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(s.managedRoomContextToken);const k=await this.isSessionBusy(a.sessionId),v=m(),D=v.sessions[a.sessionId]??[],p=N({...a,text:I.text,attachments:I.attachments,systemPrompt:s?null:a.systemPrompt});s&&(i.managedAgentDirect&&(p.managedAgentDirect=!0),p.trigger?.kind!=="manager_event"&&p.trigger?.kind!=="scheduled"&&(p.trigger={kind:"managed_direct"}));const _=p.clientMessageId??p.id,g=C(a.sessionId,_);if(g.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:g.state==="queued",queueMessageId:p.id,...g,queue:this.getSnapshot(a.sessionId)}}),!0;const S=q(D,p);S||(v.sessions[a.sessionId]=[...D,p],y(v));const f=S??p;return P({sessionId:f.sessionId,agentType:f.agentType,sessionMode:f.sessionMode,managerConfig:f.managerConfig,workDir:f.workDir,agentSessionId:f.agentSessionId,modelId:f.modelId}),B(f.sessionId,T(f),"queued"),ee(n.resolvePath(f.workDir),f.attachments??[]),R(n.client),this.logLifecycle("enqueue.persisted",a.sessionId,{origin:a.origin??"app",queueMessageId:f.id,pendingCount:(m().sessions[a.sessionId]??[]).length}),this.broadcast(a.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:S?.id??p.id,...C(a.sessionId,S?.clientMessageId??S?.id??p.clientMessageId??p.id),queue:this.getSnapshot(a.sessionId),...I.localized?{localizedAttachments:!0}:{}}}),k?this.retries.schedule(a.sessionId):this.wakeSession(a.sessionId),!0}async handleGet(e){await ce(this.queueControlContext(),e)}async handleEdit(e){await ge(this.queueControlContext(),e)}async handleDelete(e){await le(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await me({...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=m().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){ae(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const l=m().sessions[e]?.length??0;return this.purgeSession(e),l}const t=m(),n=t.sessions[e]??[],r=this.inFlightMessageIds.get(e)??new Set,o=n.filter(l=>l.managedRoom&&!r.has(l.id));if(o.length===0)return 0;const i=n.filter(l=>!o.includes(l));i.length?t.sessions[e]=i:delete t.sessions[e],y(t);for(const l of o)te(e,l.clientMessageId??l.id);return R(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:o.length,pendingCount:i.length}),this.broadcast(e),o.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=m();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,r=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const a=m().sessions[e]?.length??0,c=this.deferredLogState.get(e),h=Date.now();(!c||c.pendingCount!==a||h-c.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:a}),this.deferredLogState.set(e,{at:h,pendingCount:a}));return}this.deferredLogState.delete(e);const o=m(),i=o.sessions[e]??[],l=i.filter(a=>{const c=a.clientMessageId??a.id,h=C(e,c).state;return h==="queued"||h==="not_found"});if(l.length!==i.length&&(l.length?o.sessions[e]=l:delete o.sessions[e],y(o),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:i.length-l.length,pendingCount:l.length})),l.some(a=>!!a.externalQueuedSubmissionId)){this.broadcast(e);return}const d=A(l);if(d.length===0){this.broadcast(e);return}if(b(d))return;d.some(a=>(a.dispatchBlock?.retryAt??0)>0)&&ie(),r=d,this.inFlightMessageIds.set(e,new Set(d.map(a=>a.id))),this.logLifecycle("dispatch.start",e,{batchCount:d.length,queueMessageId:d[0].id,origin:d[0].origin??"app"}),this.broadcast(e);for(const a of d)ne(e,T(a),"queued");const s=await this.dispatchQueuedMessages(d);if(s.deliveryMode==="external_owner_queue"){this.markExternalQueued(d,s.queuedSubmissionId),W(d),d.some(a=>a.dispatchBlock)&&R(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:d.length,queueMessageId:d[0].id}),this.broadcast(e);return}const u=this.removeBatch(e,d);W(d),d.some(a=>a.dispatchBlock)&&R(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:d.length,queueMessageId:d[0].id,pendingCount:u}),this.deferredLogState.delete(e),t=u>0,this.broadcast(e)}catch(o){const i=se({error:o,sessionId:e,batch:r,publish:()=>R(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,r),log:(l,d)=>this.logLifecycle(l,e,d,"error")});t=i.drainAgain,n=i.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const o=m().sessions[e]??[];o.length?(this.broadcast(e),o.some(i=>!!i.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,b(A(o)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=m(),r=n.sessions[e]??[],o=r.filter(i=>(i.clientMessageId??i.id)!==t);o.length!==r.length&&(o.length?n.sessions[e]=o:delete n.sessions[e],y(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),r=t[0].trigger?.kind==="managed_direct"||t[0].managedAgentDirect?null:"personal";return!!(r&&t[0].systemPrompt==null&&n&&n.source===r&&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 m().sessions[e]?.length??0;const n=m(),r=new Set(t.map(i=>i.id)),o=(n.sessions[e]??[]).filter(i=>!r.has(i.id));return o.length?n.sessions[e]=o:delete n.sessions[e],y(n),o.length}logLifecycle(e,t,n,r="info"){const o=`[chat.queue] ${JSON.stringify({at:j(),event:e,sessionId:t,...n})}`;r==="error"?console.error(o):console.info(o)}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 O("schedule_target_unavailable");const r=e.flatMap(g=>{if(g.trigger?.kind==="room_activation"){const{kind:S,...f}=g.trigger;return[f]}return!g.trigger&&g.managedRoom?[g.managedRoom]:[]}),o=e.find(g=>g.trigger?.kind==="manager_event")?.trigger,i=e.some(g=>g.trigger?.kind==="managed_direct"||!!g.managedAgentDirect),l=i||!!n?.bindingId,d=e.find(g=>g.trigger?.kind==="manager_worker")?.trigger,s=o?.kind==="manager_event"||i,u=r.length>0?await this.prepareManagedRoomTurn?.(r):l||o?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,E(o?.kind==="manager_event"?o:null,i)):void 0;if(r.length>0&&!u)throw new Error("managed_room_turn_preparer_unavailable");if(l&&!u)throw new Error("managed_agent_context_unavailable");if(o?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!u)throw new Error("managed_agent_context_unavailable");const a=new Set((m().sessions[t.sessionId]??[]).map(g=>g.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(g=>!a.has(g.id)))throw u?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(u.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new O("queued_dispatch_cancelled");const c=u??null,h=c?.sessionMode==="manager"?c.managerConfig:null,I=e.length===1?t.text:G(e),M=U(e.flatMap(g=>g.attachments??[])),k=l||o?.kind==="manager_event"&&!!u,v=k?u.agentSessionId?.startsWith("managed:")?x(this.opts.getRuntime(),t):u.agentSessionId:r.length>0?x(this.opts.getRuntime(),t):t.agentSessionId??null,D=u?Q().find(g=>g.sessionId===t.sessionId):null,p=u?.effectiveModelId!==void 0?w(u.effectiveModelId):w(D?.modelId)??w(t.modelId),_=u?.effectiveModelId!==void 0?"room_effective_model":w(D?.modelId)?"persisted_session_model":w(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:{...L(F()),sessionId:t.sessionId,text:I,agentType:k?u.agentType:t.agentType,sessionMode:c?.sessionMode??t.sessionMode,managerConfig:c?h:t.managerConfig,workDir:k?u.workDir:t.workDir,agentSessionId:v,modelId:p,modelSelectionSource:_,systemPrompt:u?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:c?c.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:c?c.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:M,externalChannel:s?void 0:t.externalChannel,replyTarget:s?void 0:t.replyTarget,roomContextRegistryKey:s?void 0:u?.roomContextRegistryKey,activationCauseMessageId:s?void 0:r.at(-1)?.causeMessageId,rootCauseMessageId:s?void 0:r.at(-1)?.rootCauseMessageId,activationSequence:s?void 0:r.at(-1)?.sequence,activationHopCount:s?void 0:r.at(-1)?.hopCount,managedRecoverySource:o?.kind==="manager_event"?"manager_event":l?"managed_direct":r.length>0?"managed_room":void 0,managerEventId:o?.kind==="manager_event"?o.eventId:void 0,managedWorkerParentSessionId:d?.kind==="manager_worker"?d.parentSessionId:void 0,managerWorkerRoomOrigin:d?.kind==="manager_worker"?d.roomOrigin:void 0,managerWorkerNativeFull:d?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(d.parentSessionId,t.workDir)||void 0,managedRoomContextToken:u?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:r.length>0||!!n||void 0,queuedBatchItems:e.map(g=>{const S=K(g);return s?{...S,systemPrompt:u?.systemPrompt??null,externalChannel:null,replyTarget:null}:S}),waitForDispatch:!0}},u??void 0)??{}}markExternalQueued(e,t){const n=m(),r=new Set(e.map(l=>l.id)),o=n.sessions[e[0].sessionId]??[];let i=!1;for(const l of o)r.has(l.id)&&(l.externalQueuedSubmissionId=t||l.id,l.updatedAt=j(),i=!0);i&&y(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 r=await n.adapter.getStatus().catch(()=>null);return r?.active?(r.runId&&(n.currentRunId=r.runId,n.currentRunPhase=r.runPhase??n.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{Be as ChatQueueManager,Le as TerminalQueuedChatDispatchError,be as purgeQueuedSessionData};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadConfig as m}from"../config/index.js";import{SERVERS as d}from"../region.js";class a extends Error{code;nextAction;constructor(e,t,o=null){super(t),this.code=e,this.nextAction=o}}class b{fetchImpl;constructor(e=fetch){this.fetchImpl=e}status(){return this.request("GET","/api/support-cli/status")}ask(e){return this.request("POST","/api/support-cli/ask",{text:e})}read(e){const t=new URLSearchParams({limit:String(e.limit)});return e.before&&t.set("before",e.before),e.after&&t.set("after",e.after),this.request("GET",`/api/support-cli/read?${t}`)}async request(e,t,o){const c=m();if(!c.machineToken)throw new a("not_paired","Shennian CLI is not paired.",{type:"run_command",command:"shennian pair --browser"});const p=(c.serverUrl??d.cn.url).replace(/\/+$/,"");let s;try{s=await this.fetchImpl(`${p}${t}`,{method:e,headers:{authorization:`Bearer ${c.machineToken}`,...o==null?{}:{"content-type":"application/json"}},...o==null?{}:{body:JSON.stringify(o)},signal:AbortSignal.timeout(2e4)})}catch{throw new a("server_unavailable","Shennian service is unavailable.")}const i=await S(s);if(!s.ok){const n=l(i)?i:{},u=typeof n.error=="string"?n.error:`http_${s.status}`,f=typeof n.message=="string"?n.message:"Support request failed.",h=y(n.nextAction)?n.nextAction:null;throw new a(u,f,h)}if(!l(i))throw new a("invalid_server_response","Shennian returned an invalid support response.");return i}}function y(r){return l(r)&&Object.values(r).every(e=>typeof e=="string")}async function S(r){try{return await r.json()}catch{return null}}function l(r){return!!r&&typeof r=="object"&&!Array.isArray(r)}export{b as SupportClient,a as SupportClientError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const _="adapter.mjs",o="text/javascript; charset=utf-8",b=262144,a=[/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/i,/\b(?:sk|rk|pk)-(?:live|test|proj)-[A-Za-z0-9_-]{12,}\b/,/\bgh[opusr]_[A-Za-z0-9]{20,}\b/,/\bAKIA[0-9A-Z]{16}\b/,/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/i,/\b(?:api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|password)\b\s*[:=]\s*["'\x60][^"'\x60\r\n]{8,}["'\x60]/i],A=[/\bprocess\.env(?:\.[A-Za-z_][A-Za-z0-9_]*|\[['"][A-Za-z_][A-Za-z0-9_]*['"]\])\s*=\s*["'\x60][^"'\x60\r\n]+["'\x60]/,/\b(?:env|environment)\s*:\s*\{[^}]*\b[A-Z][A-Z0-9_]{2,}\s*:\s*["'\x60][^"'\x60\r\n]{4,}["'\x60]/s],i=[/["'\x60]\/(?!\/)[^"'\x60\r\n]+["'\x60]/,/["'\x60][A-Za-z]:[\\/][^"'\x60\r\n]+["'\x60]/,/["'\x60]\\\\[^\\\s"'\x60]+\\[^"'\x60\r\n]+["'\x60]/],r=[/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,/\b(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3})\b/,/\b[A-Za-z0-9.-]+\.(?:internal|corp|lan)\b/i,/(?:仅限内部|公司机密|客户机密|confidential|proprietary business logic)/i];function d(e){const n=new TextEncoder().encode(e).byteLength,t=new Set;return(e.includes("\0")||/[\u0001-\u0008\u000b\u000c\u000e-\u001f]/.test(e))&&t.add("binary_content"),a.some(s=>s.test(e))&&t.add("credential_material"),A.some(s=>s.test(e))&&t.add("environment_value"),i.some(s=>s.test(e))&&t.add("absolute_path"),r.some(s=>s.test(e))&&t.add("private_content"),{ok:t.size===0,byteSize:n,issues:[...t]}}export{o as ADAPTER_SUBMISSION_CONTENT_TYPE,_ as ADAPTER_SUBMISSION_FILENAME,b as ADAPTER_SUBMISSION_MAX_BYTES,d as scanAdapterSubmissionSource};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./envelope.js";export*from"./events.js";export*from"./machine.js";export*from"./methods.js";export*from"./frames.js";export*from"./fs.js";export*from"./session.js";export*from"./session-sync.js";export*from"./message-payload.js";export*from"./external-message-format.js";export*from"./native-session.js";export*from"./tool-detail.js";export*from"./voice-chief.js";export*from"./project.js";export*from"./project-fs.js";export*from"./room.js";export*from"./agent-capabilities.js";export*from"./agent-workspace.js";export*from"./relay-connectivity.js";export*from"./project-path.js";export*from"./schedule.js";
|
|
1
|
+
export*from"./envelope.js";export*from"./events.js";export*from"./machine.js";export*from"./methods.js";export*from"./frames.js";export*from"./fs.js";export*from"./session.js";export*from"./session-sync.js";export*from"./message-payload.js";export*from"./external-message-format.js";export*from"./native-session.js";export*from"./tool-detail.js";export*from"./voice-chief.js";export*from"./project.js";export*from"./project-fs.js";export*from"./room.js";export*from"./agent-capabilities.js";export*from"./agent-workspace.js";export*from"./relay-connectivity.js";export*from"./project-path.js";export*from"./schedule.js";export*from"./support.js";export*from"./adapter-submission.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const p="codex_desktop_send_unavailable",a=["gemini","openclaw"],i=["claude","codex","workbuddy","cursor","opencode","pi","pi-coding-agent"],s=new Set(i);function c(e){return typeof e.supportsAgent=="boolean"?e.supportsAgent:e.supportsManagedAgent===!0||e.supportsManagedNativeFull===!0}function A(e,n){return Array.isArray(e.supportedAgentExecutionModes)?e.supportedAgentExecutionModes.includes(n):n==="native-full"?e.supportsManagedNativeFull===!0:e.supportsManagedAgent===!0}function u(e){return s.has(e)}function r(e){return e.startsWith("custom:")||/^acp:[a-z0-9][a-z0-9._-]{0,63}$/.test(e)||u(e)}function l(e){const n=[],o=new Set;for(const t of e)!r(t)||o.has(t)||(o.add(t),n.push(t));return n}function d(e){if(!e?.length)return[];const n=[],o=new Set;for(const t of e)!r(t.type)||o.has(t.type)||(o.add(t.type),n.push(t));return n}function f(e){return e.nativeSessionVisibility==="internal"||e.id.startsWith("sess_worker_")||e.agentType==="manager"||e.sessionMode==="manager"||!!e.agentIdentityId}export{i as AVAILABLE_BUILTIN_AGENT_TYPES,p as CODEX_DESKTOP_SEND_UNAVAILABLE,a as DISABLED_BUILTIN_AGENT_TYPES,c as agentInfoSupportsAgent,A as agentInfoSupportsExecutionMode,d as filterAvailableAgentInfos,l as filterAvailableAgentTypes,r as isAvailableAgentType,u as isAvailableBuiltinAgentType,f as isInternalSession};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shennian",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "Shennian
|
|
3
|
+
"version": "0.5.4",
|
|
4
|
+
"description": "Shennian \u2014 AI Agent Control Plane CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"shennian": "dist/bin/shennian.js"
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"node": ">=18"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
|
-
"build": "node -e \"require('node:fs').rmSync('dist/native/macos-background-client', { recursive: true, force: true })\" && tsc && node -e \"require('node:fs').chmodSync('dist/bin/shennian.js', 0o755)\"",
|
|
44
|
-
"build:publish": "pnpm --filter @shennian/wire build:publish && node -e \"const fs=require('node:fs'); fs.rmSync('dist', { recursive: true, force: true }); fs.rmSync('.tsbuildinfo.publish', { force: true })\" && tsc -p tsconfig.publish.json && node scripts/minify-publish-js.mjs && node scripts/strip-publish-types.mjs dist && node -e \"require('node:fs').chmodSync('dist/bin/shennian.js', 0o755)\" && node scripts/check-publish-artifact.mjs",
|
|
43
|
+
"build": "node -e \"require('node:fs').rmSync('dist/native/macos-background-client', { recursive: true, force: true })\" && tsc && node -e \"require('node:fs').chmodSync('dist/bin/shennian.js', 0o755)\" && node scripts/copy-agent-adapter-docs.mjs",
|
|
44
|
+
"build:publish": "pnpm --filter @shennian/wire build:publish && node -e \"const fs=require('node:fs'); fs.rmSync('dist', { recursive: true, force: true }); fs.rmSync('.tsbuildinfo.publish', { force: true })\" && tsc -p tsconfig.publish.json && node scripts/minify-publish-js.mjs && node scripts/strip-publish-types.mjs dist && node -e \"require('node:fs').chmodSync('dist/bin/shennian.js', 0o755)\" && node scripts/copy-agent-adapter-docs.mjs && node scripts/check-publish-artifact.mjs",
|
|
45
45
|
"test:security:codex": "tsx scripts/verify-managed-codex-sandbox.ts",
|
|
46
46
|
"test:security:codex-tools": "tsx scripts/verify-managed-codex-dynamic-tools.ts",
|
|
47
47
|
"dev": "tsc --watch",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{spawn as i}from"node:child_process";function s(e,r=!1){if(!(!e.pid||e.exitCode!==null||e.signalCode!==null)){if(process.platform==="win32"){i("taskkill",["/PID",String(e.pid),"/T",...r?["/F"]:[]],{stdio:"ignore",windowsHide:!0}).unref();return}try{process.kill(-e.pid,r?"SIGKILL":"SIGTERM")}catch{e.kill(r?"SIGKILL":"SIGTERM")}}}export{s as terminateProcessTree};
|