shennian 0.4.61 → 0.4.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/publish-build-manifest.json +50 -25
- package/dist/src/agents/acp/manifests.d.ts +4 -4
- package/dist/src/agents/codex-managed-room-tools.d.ts +1 -1
- package/dist/src/agents/codex-managed-room-tools.js +1 -1
- package/dist/src/agents/pi-managed-extension.js +1 -1
- package/dist/src/commands/room.js +2 -2
- package/dist/src/commands/schedule.d.ts +2 -0
- package/dist/src/commands/schedule.js +2 -0
- package/dist/src/index.js +3 -3
- package/dist/src/room/managed-prompt-composer.js +7 -7
- package/dist/src/room/managed-room-ipc.d.ts +3 -0
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/room/room-action-client-types.d.ts +1 -0
- package/dist/src/room/room-action-client.d.ts +4 -1
- package/dist/src/room/room-action-client.js +1 -1
- package/dist/src/schedules/personal-context.d.ts +3 -0
- package/dist/src/schedules/personal-context.js +1 -0
- package/dist/src/schedules/server-client.d.ts +19 -0
- package/dist/src/schedules/server-client.js +1 -0
- package/dist/src/session/handlers/chat-adapter-config.js +1 -1
- package/dist/src/session/handlers/chat.js +3 -1
- package/dist/src/session/manager.d.ts +3 -1
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/queue-helpers.js +1 -1
- package/dist/src/session/queue-message.d.ts +30 -0
- package/dist/src/session/queue-message.js +1 -0
- package/dist/src/session/queue-types.d.ts +20 -0
- package/dist/src/session/queue-types.js +1 -0
- package/dist/src/session/queue.d.ts +13 -32
- package/dist/src/session/queue.js +1 -1
- package/dist/src/session/turn-trigger.d.ts +5 -0
- package/node_modules/@shennian/wire/dist/index.d.ts +1 -0
- package/node_modules/@shennian/wire/dist/index.js +1 -0
- package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
- package/node_modules/@shennian/wire/dist/schedule.d.ts +37 -0
- package/node_modules/@shennian/wire/dist/schedule.js +1 -0
- package/package.json +1 -1
|
@@ -42,7 +42,10 @@ export declare class HttpRoomActionClient {
|
|
|
42
42
|
activationCapability: 'managed' | 'idle_resume' | 'notify_only';
|
|
43
43
|
activationMode: RoomActivationMode;
|
|
44
44
|
}): Promise<RemoteRoomJoinResult>;
|
|
45
|
-
status(target: BindingTarget
|
|
45
|
+
status(target: BindingTarget & {
|
|
46
|
+
scheduleAuthorization?: boolean;
|
|
47
|
+
causeMessageId?: string;
|
|
48
|
+
}): Promise<RemoteRoomAgentStatus>;
|
|
46
49
|
getAttachmentCapability(target: BindingTarget & {
|
|
47
50
|
attachmentId: string;
|
|
48
51
|
}): Promise<RemoteRoomAttachmentCapability>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isAvailableAgentType as j,parseManagedAgentPermissionPolicy as _}from"@shennian/wire";import M from"node:path";import{RoomActionHttpError as c}from"./room-action-client-types.js";export*from"./room-action-client-types.js";class k{fetchImpl;baseUrl;constructor(e,t=fetch){this.fetchImpl=t,this.baseUrl=e.replace(/\/+$/,"")}async createOperatorRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/operator/create`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({name:e.name}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return N(n,e,this.baseUrl)}async resolveNativeSession(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/resolve-session`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({runtimeAdapter:e.runtimeAdapter,sourceSessionKey:e.sourceSessionKey}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);(!n||typeof n!="object")&&r();const o=n;return(typeof o.nianSessionId!="string"||!/^[A-Za-z0-9_.:@/-]{1,512}$/.test(o.nianSessionId)||typeof o.created!="boolean")&&r(),o}async createRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/create`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({bindingIntentId:e.bindingIntentId,nianSessionId:e.nianSessionId,runtimeAdapter:e.runtimeAdapter,sessionRegistryKey:e.sessionRegistryKey,name:e.name,agentAlias:e.agentAlias,agentDescription:e.agentDescription,activationCapability:e.activationCapability,activationMode:e.activationMode}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return T(n,e,this.baseUrl)}async joinRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/join`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({bindingIntentId:e.bindingIntentId,nianSessionId:e.nianSessionId,runtimeAdapter:e.runtimeAdapter,sessionRegistryKey:e.sessionRegistryKey,inviteToken:e.inviteToken,message:e.message,agentAlias:e.agentAlias,agentDescription:e.agentDescription,activationCapability:e.activationCapability,activationMode:e.activationMode}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return $(n,e,this.baseUrl)}async status(e){const t=await this.request(e,"status");return q(t,e)}async getAttachmentCapability(e){const t=await this.request(e,`attachments/${encodeURIComponent(e.attachmentId)}/download-capability`);(!t||typeof t!="object")&&r();const n=t;return(n.attachmentId!==e.attachmentId||n.roomId!==e.roomId||typeof n.safeName!="string"||!I(n.safeName)||typeof n.mimeType!="string"||n.mimeType.length<1||n.mimeType.length>191||typeof n.byteSize!="string"||!m(n.byteSize)||typeof n.sha256!="string"||!/^[a-f0-9]{64}$/.test(n.sha256)||!S(n.downloadUrl)||typeof n.expiresAt!="string"||!Number.isFinite(Date.parse(n.expiresAt)))&&r(),n}async initializeAttachment(e){const t=await this.request(e,"attachments/init",{method:"POST",body:JSON.stringify({clientUploadId:e.clientUploadId,name:e.name,mediaKind:e.mediaKind,mimeType:e.mimeType,byteSize:e.byteSize,sha256:e.sha256})});(!t||typeof t!="object")&&r();const n=t,o=n.attachment,s=n.upload;return(!o||typeof o.id!="string"||o.roomId!==e.roomId||typeof o.name!="string"||!I(o.name)||o.mimeType!==e.mimeType||o.byteSize!==String(e.byteSize)||o.sha256!==e.sha256||o.status!=="pending"&&o.status!=="uploaded"||!s||s.method!=="PUT"||!S(s.url)||!s.headers||typeof s.headers!="object"||s.headers["content-type"]!==e.mimeType||s.headers["x-oss-meta-sha256"]!==e.sha256||typeof s.expiresAt!="string"||!Number.isFinite(Date.parse(s.expiresAt))||Date.parse(s.expiresAt)<=Date.now()||typeof n.idempotent!="boolean")&&r(),n}async completeAttachment(e){const t=await this.request(e,`attachments/${encodeURIComponent(e.attachmentId)}/complete`,{method:"POST"});(!t||typeof t!="object")&&r();const n=t;typeof n.idempotent!="boolean"&&r();const o=n.attachment;return(!o||o.attachmentId!==e.attachmentId||o.mediaKind!=="image"&&o.mediaKind!=="audio"&&o.mediaKind!=="file"||typeof o.name!="string"||typeof o.mimeType!="string"||typeof o.byteSize!="string"||!m(o.byteSize)||typeof o.sha256!="string"||!/^[a-f0-9]{64}$/.test(o.sha256)||o.status!=="ready")&&r(),{attachment:o,idempotent:n.idempotent}}async read(e){if(e.beforeSequence&&e.afterSequence)throw new c("ambiguous_sequence_cursor","beforeSequence and afterSequence are mutually exclusive.");const t=new URLSearchParams({limit:String(e.limit)});e.beforeSequence&&t.set("before",e.beforeSequence),e.afterSequence&&t.set("after",e.afterSequence);const n=await this.request(e,`messages?${t}`);(!n||typeof n!="object")&&r();const o=n;return(!Array.isArray(o.messages)||typeof o.nextSequence!="string"||!m(o.nextSequence)||typeof o.hasMore!="boolean"||typeof o.historyFromSequence!="string"||!m(o.historyFromSequence)||typeof o.roomName!="string")&&r(),{messages:o.messages.map(a=>h(a,e.roomId)),nextSequence:o.nextSequence,hasMore:o.hasMore,historyFromSequence:o.historyFromSequence,roomName:o.roomName}}async send(e){const t=await this.request(e,"messages",{method:"POST",body:JSON.stringify({clientMessageId:e.clientMessageId,text:e.text,mentionMembershipIds:e.mentionMembershipIds,replyToMessageId:e.replyToMessageId,activationCauseMessageId:e.activationCauseMessageId,attachmentIds:e.attachmentIds})});(!t||typeof t!="object")&&r();const n=t;return typeof n.idempotent!="boolean"&&r(),{message:h(n.message,e.roomId),idempotent:n.idempotent}}async mode(e){const t=await this.request(e,"mode",{method:"PATCH",body:JSON.stringify({activationMode:e.activationMode})});(!t||typeof t!="object")&&r();const n=t;return(n.bindingId!==e.bindingId||n.roomId!==e.roomId||n.status!=="active"&&n.status!=="paused"||!v(n.activationMode)||n.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),n}async pause(e){const t=await this.request(e,"pause",{method:"POST",body:JSON.stringify({reason:e.reason})});(!t||typeof t!="object")&&r();const n=t;return(n.bindingId!==e.bindingId||n.roomId!==e.roomId||n.status!=="paused"||n.activationMode!=="paused"||typeof n.idempotent!="boolean")&&r(),{...n,message:h(n.message,e.roomId)}}async request(e,t,n={}){let o;const s=C(e.signal,1e4);try{o=await this.fetchImpl(`${this.baseUrl}/api/rooms/${encodeURIComponent(e.roomId)}/bindings/${encodeURIComponent(e.bindingId)}/${t}`,{...n,headers:{authorization:`Bearer ${e.machineToken}`,...n.body?{"content-type":"application/json"}:{}},signal:s.signal})}catch{throw e.signal?.aborted?new c("managed_room_context_revoked","Managed Room context was revoked."):new c("room_action_server_unavailable","Shennian Room service is unavailable.")}finally{s.dispose()}if(!o.ok){let a=`room_action_http_${o.status}`;try{const d=await o.json();typeof d.error=="string"&&/^[a-z0-9_-]{1,80}$/.test(d.error)&&(a=d.error)}catch{}throw new c(a,"Shennian Room action failed.")}try{return await o.json()}catch{r()}}}function C(i,e){const t=new AbortController,n=()=>t.abort();i?.aborted?t.abort():i?.addEventListener("abort",n,{once:!0});const o=setTimeout(()=>t.abort(),e);return o.unref?.(),{signal:t.signal,dispose:()=>{clearTimeout(o),i?.removeEventListener("abort",n)}}}function q(i,e){(!i||typeof i!="object")&&r();const t=i,n=t.room,o=t.agent;(t.nianSessionId!==void 0&&t.nianSessionId!==null&&(typeof t.nianSessionId!="string"||!t.nianSessionId)||t.sessionRegistryKey!==void 0&&(typeof t.sessionRegistryKey!="string"||!/^[a-f0-9]{64}$/.test(t.sessionRegistryKey))||t.bindingId!==e.bindingId||t.roomId!==e.roomId||typeof t.agentIdentityId!="string"||t.agentMembershipId!==null&&typeof t.agentMembershipId!="string"||t.status!=="pending_approval"&&t.status!=="active"&&t.status!=="paused"&&t.status!=="detached"||!v(t.activationMode)||t.activationCapability!==void 0&&t.activationCapability!=="managed"&&t.activationCapability!=="idle_resume"&&t.activationCapability!=="notify_only"||t.managedWorkspacePath!==void 0&&t.managedWorkspacePath!==null&&(typeof t.managedWorkspacePath!="string"||t.managedWorkspacePath.length>4096||!M.isAbsolute(t.managedWorkspacePath))||typeof t.lastDeliveredSequence!="string"||!m(t.lastDeliveredSequence)||typeof t.lastActivatedSequence!="string"||!m(t.lastActivatedSequence)||t.appliedConfigurationVersion!==void 0&&(!Number.isSafeInteger(t.appliedConfigurationVersion)||Number(t.appliedConfigurationVersion)<1)||t.pendingConfigurationVersion!==void 0&&t.pendingConfigurationVersion!==null&&(!Number.isSafeInteger(t.pendingConfigurationVersion)||Number(t.pendingConfigurationVersion)<1)||!n||typeof n!="object"||o!==void 0&&(!o||typeof o!="object"))&&r(),(t.status==="pending_approval"&&t.agentMembershipId!==null||(t.status==="active"||t.status==="paused")&&typeof t.agentMembershipId!="string")&&r();const s=n,a=o,d=a?_(a.permissionPolicy):null,g=a?R(a.permissionConfirmation):null,A=a?Object.prototype.hasOwnProperty.call(a,"permissionConfirmation"):!1,l=s.members;return(a!==void 0&&(typeof a.displayName!="string"||!a.displayName.trim()||typeof a.description!="string"||a.sessionMode!=="standard"&&a.sessionMode!=="manager"||a.configurationVersion!==void 0&&(!Number.isSafeInteger(a.configurationVersion)||Number(a.configurationVersion)<1)||a.configurationPending!==void 0&&typeof a.configurationPending!="boolean"||!d||!A||a.permissionConfirmation!==null&&!g)||typeof s.name!="string"||typeof s.status!="string"||s.memberCount!==void 0&&(typeof s.memberCount!="number"||!Number.isInteger(s.memberCount)||s.memberCount<0)||typeof s.lastSequence!="string"||!m(s.lastSequence)||l!==void 0&&(!Array.isArray(l)||l.some(u=>{if(!u||typeof u!="object")return!0;const y=u;return typeof y.displayName!="string"||y.principalType!=="human"&&y.principalType!=="agent"})))&&r(),{...t,...a&&d?{agent:{...a,permissionPolicy:d,permissionConfirmation:g}}:{}}}function R(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const e=i;return!Number.isSafeInteger(e.policyVersion)||Number(e.policyVersion)<1||typeof e.runtimeAdapter!="string"||!j(e.runtimeAdapter)||typeof e.runtimeVersion!="string"||!e.runtimeVersion.trim()||typeof e.platform!="string"||!e.platform.trim()||typeof e.executableFingerprint!="string"||!/^sha256:[a-f0-9]{64}$/.test(e.executableFingerprint)||typeof e.hostFullAccess!="boolean"||typeof e.limitedProtection!="boolean"||typeof e.confirmedAt!="string"||!Number.isFinite(Date.parse(e.confirmedAt))?null:{policyVersion:Number(e.policyVersion),runtimeAdapter:e.runtimeAdapter,runtimeVersion:e.runtimeVersion,platform:e.platform,executableFingerprint:e.executableFingerprint,executionMode:e.executionMode==="native-full"?"native-full":"restricted",hostFullAccess:e.hostFullAccess,limitedProtection:e.limitedProtection,confirmedAt:e.confirmedAt}}function h(i,e){(!i||typeof i!="object")&&r();const t=i;if((typeof t.id!="string"||t.roomId!==e||typeof t.sequence!="string"||!m(t.sequence)||!t.author||typeof t.author.membershipId!="string"||!Array.isArray(t.attachments)||typeof t.createdAt!="string")&&r(),t.activationCause!=null){const n=t.activationCause;(typeof n.causeMessageId!="string"||typeof n.rootCauseMessageId!="string"||!Number.isInteger(n.hopCount)||n.hopCount<1||n.hopCount>32)&&r()}return t}function T(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room,s=n.agentIdentity,a=n.binding;return(n.outcome!=="created"||!o||typeof o.id!="string"||o.name!==e.name||o.visibility!=="private"||o.joinPolicy!=="open"||!b(o.canonicalUrl,t,`/spaces/${o.id}`)||!P(o.inviteUrl,t,o.id)||!s||typeof s.id!="string"||s.displayName!==e.agentAlias||!a||typeof a.id!="string"||a.roomId!==o.id||a.agentIdentityId!==s.id||typeof a.agentMembershipId!="string"||a.status!=="active"&&a.status!=="paused"||a.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),n}function N(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room;return(n.outcome!=="created"||!o||typeof o.id!="string"||o.name!==e.name||o.visibility!=="private"||o.joinPolicy!=="open"||!b(o.canonicalUrl,t,`/spaces/${o.id}`))&&r(),n}function $(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room,s=n.agentIdentity,a=n.binding;return(n.outcome!=="joined"&&n.outcome!=="pending_approval"||!o||typeof o.id!="string"||typeof o.name!="string"||!b(o.canonicalUrl,t,`/spaces/${o.id}`)||!s||typeof s.id!="string"||s.displayName!==e.agentAlias||!a||typeof a.id!="string"||a.roomId!==o.id||a.agentIdentityId!==s.id||a.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),(n.outcome==="pending_approval"&&(a.status!=="pending_approval"||a.agentMembershipId!==null||typeof n.joinRequestId!="string")||n.outcome==="joined"&&(a.status!=="active"&&a.status!=="paused"||typeof a.agentMembershipId!="string"||n.joinRequestId!==void 0))&&r(),n}function m(i){return/^(0|[1-9]\d{0,19})$/.test(i)}function I(i){return i.length<=255&&i===i.trim()&&i!=="."&&i!==".."&&!/[\\/\0-\x1f\x7f]/.test(i)}function S(i){if(typeof i!="string")return!1;try{const e=new URL(i);return e.protocol==="https:"&&!e.username&&!e.password&&!e.hash}catch{return!1}}function v(i){return i==="auto_follow"||i==="mention_only"||i==="paused"}function r(){throw new c("invalid_room_action_response","Invalid Room action response.")}async function p(i){try{return await i.json()}catch{r()}}function f(i,e){let t=`room_action_http_${i}`;if(e&&typeof e=="object"){const n=e.error;typeof n=="string"&&/^[a-z0-9_-]{1,80}$/.test(n)&&(t=n)}return new c(t,"Shennian Room action failed.")}function b(i,e,t){return w(i,e,n=>n.pathname===t)}function P(i,e,t){if(typeof i!="string")return!1;try{const n=new URL(i);return w(`${n.origin}${n.pathname}`,e,o=>o.pathname===`/spaces/${t}`)?n.searchParams.size===1&&/^[A-Za-z0-9_-]{32,256}$/.test(n.searchParams.get("invite")??"")&&!n.hash&&!n.username&&!n.password:!1}catch{return!1}}function w(i,e,t){if(typeof i!="string")return!1;try{const n=new URL(i),o=new URL(e),s=n.origin===o.origin,a=o.protocol==="http:"&&n.protocol==="http:"&&n.hostname===o.hostname,d=n.protocol==="https:"&&n.port===""&&n.hostname==="app.shennian.net";return(s||a||d)&&!n.username&&!n.password&&!n.search&&!n.hash&&t(n)}catch{return!1}}export{k as HttpRoomActionClient};
|
|
1
|
+
import{isAvailableAgentType as j,parseManagedAgentPermissionPolicy as M}from"@shennian/wire";import _ from"node:path";import{RoomActionHttpError as c}from"./room-action-client-types.js";export*from"./room-action-client-types.js";class z{fetchImpl;baseUrl;constructor(e,t=fetch){this.fetchImpl=t,this.baseUrl=e.replace(/\/+$/,"")}async createOperatorRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/operator/create`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({name:e.name}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return $(n,e,this.baseUrl)}async resolveNativeSession(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/resolve-session`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({runtimeAdapter:e.runtimeAdapter,sourceSessionKey:e.sourceSessionKey}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);(!n||typeof n!="object")&&r();const o=n;return(typeof o.nianSessionId!="string"||!/^[A-Za-z0-9_.:@/-]{1,512}$/.test(o.nianSessionId)||typeof o.created!="boolean")&&r(),o}async createRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/create`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({bindingIntentId:e.bindingIntentId,nianSessionId:e.nianSessionId,runtimeAdapter:e.runtimeAdapter,sessionRegistryKey:e.sessionRegistryKey,name:e.name,agentAlias:e.agentAlias,agentDescription:e.agentDescription,activationCapability:e.activationCapability,activationMode:e.activationMode}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return T(n,e,this.baseUrl)}async joinRoom(e){let t;try{t=await this.fetchImpl(`${this.baseUrl}/api/rooms/actions/join`,{method:"POST",headers:{authorization:`Bearer ${e.machineToken}`,"content-type":"application/json"},body:JSON.stringify({bindingIntentId:e.bindingIntentId,nianSessionId:e.nianSessionId,runtimeAdapter:e.runtimeAdapter,sessionRegistryKey:e.sessionRegistryKey,inviteToken:e.inviteToken,message:e.message,agentAlias:e.agentAlias,agentDescription:e.agentDescription,activationCapability:e.activationCapability,activationMode:e.activationMode}),signal:AbortSignal.timeout(1e4)})}catch{throw new c("room_action_server_unavailable","Shennian Room service is unavailable.")}const n=await p(t);if(!t.ok)throw f(t.status,n);return N(n,e,this.baseUrl)}async status(e){const t=e.scheduleAuthorization?`?scheduleAuthorization=1${e.causeMessageId?`&causeMessageId=${encodeURIComponent(e.causeMessageId)}`:""}`:"",n=await this.request(e,`status${t}`);return q(n,e)}async getAttachmentCapability(e){const t=await this.request(e,`attachments/${encodeURIComponent(e.attachmentId)}/download-capability`);(!t||typeof t!="object")&&r();const n=t;return(n.attachmentId!==e.attachmentId||n.roomId!==e.roomId||typeof n.safeName!="string"||!I(n.safeName)||typeof n.mimeType!="string"||n.mimeType.length<1||n.mimeType.length>191||typeof n.byteSize!="string"||!m(n.byteSize)||typeof n.sha256!="string"||!/^[a-f0-9]{64}$/.test(n.sha256)||!S(n.downloadUrl)||typeof n.expiresAt!="string"||!Number.isFinite(Date.parse(n.expiresAt)))&&r(),n}async initializeAttachment(e){const t=await this.request(e,"attachments/init",{method:"POST",body:JSON.stringify({clientUploadId:e.clientUploadId,name:e.name,mediaKind:e.mediaKind,mimeType:e.mimeType,byteSize:e.byteSize,sha256:e.sha256})});(!t||typeof t!="object")&&r();const n=t,o=n.attachment,a=n.upload;return(!o||typeof o.id!="string"||o.roomId!==e.roomId||typeof o.name!="string"||!I(o.name)||o.mimeType!==e.mimeType||o.byteSize!==String(e.byteSize)||o.sha256!==e.sha256||o.status!=="pending"&&o.status!=="uploaded"||!a||a.method!=="PUT"||!S(a.url)||!a.headers||typeof a.headers!="object"||a.headers["content-type"]!==e.mimeType||a.headers["x-oss-meta-sha256"]!==e.sha256||typeof a.expiresAt!="string"||!Number.isFinite(Date.parse(a.expiresAt))||Date.parse(a.expiresAt)<=Date.now()||typeof n.idempotent!="boolean")&&r(),n}async completeAttachment(e){const t=await this.request(e,`attachments/${encodeURIComponent(e.attachmentId)}/complete`,{method:"POST"});(!t||typeof t!="object")&&r();const n=t;typeof n.idempotent!="boolean"&&r();const o=n.attachment;return(!o||o.attachmentId!==e.attachmentId||o.mediaKind!=="image"&&o.mediaKind!=="audio"&&o.mediaKind!=="file"||typeof o.name!="string"||typeof o.mimeType!="string"||typeof o.byteSize!="string"||!m(o.byteSize)||typeof o.sha256!="string"||!/^[a-f0-9]{64}$/.test(o.sha256)||o.status!=="ready")&&r(),{attachment:o,idempotent:n.idempotent}}async read(e){if(e.beforeSequence&&e.afterSequence)throw new c("ambiguous_sequence_cursor","beforeSequence and afterSequence are mutually exclusive.");const t=new URLSearchParams({limit:String(e.limit)});e.beforeSequence&&t.set("before",e.beforeSequence),e.afterSequence&&t.set("after",e.afterSequence);const n=await this.request(e,`messages?${t}`);(!n||typeof n!="object")&&r();const o=n;return(!Array.isArray(o.messages)||typeof o.nextSequence!="string"||!m(o.nextSequence)||typeof o.hasMore!="boolean"||typeof o.historyFromSequence!="string"||!m(o.historyFromSequence)||typeof o.roomName!="string")&&r(),{messages:o.messages.map(s=>h(s,e.roomId)),nextSequence:o.nextSequence,hasMore:o.hasMore,historyFromSequence:o.historyFromSequence,roomName:o.roomName}}async send(e){const t=await this.request(e,"messages",{method:"POST",body:JSON.stringify({clientMessageId:e.clientMessageId,text:e.text,mentionMembershipIds:e.mentionMembershipIds,replyToMessageId:e.replyToMessageId,activationCauseMessageId:e.activationCauseMessageId,attachmentIds:e.attachmentIds})});(!t||typeof t!="object")&&r();const n=t;return typeof n.idempotent!="boolean"&&r(),{message:h(n.message,e.roomId),idempotent:n.idempotent}}async mode(e){const t=await this.request(e,"mode",{method:"PATCH",body:JSON.stringify({activationMode:e.activationMode})});(!t||typeof t!="object")&&r();const n=t;return(n.bindingId!==e.bindingId||n.roomId!==e.roomId||n.status!=="active"&&n.status!=="paused"||!v(n.activationMode)||n.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),n}async pause(e){const t=await this.request(e,"pause",{method:"POST",body:JSON.stringify({reason:e.reason})});(!t||typeof t!="object")&&r();const n=t;return(n.bindingId!==e.bindingId||n.roomId!==e.roomId||n.status!=="paused"||n.activationMode!=="paused"||typeof n.idempotent!="boolean")&&r(),{...n,message:h(n.message,e.roomId)}}async request(e,t,n={}){let o;const a=C(e.signal,1e4);try{o=await this.fetchImpl(`${this.baseUrl}/api/rooms/${encodeURIComponent(e.roomId)}/bindings/${encodeURIComponent(e.bindingId)}/${t}`,{...n,headers:{authorization:`Bearer ${e.machineToken}`,...n.body?{"content-type":"application/json"}:{}},signal:a.signal})}catch{throw e.signal?.aborted?new c("managed_room_context_revoked","Managed Room context was revoked."):new c("room_action_server_unavailable","Shennian Room service is unavailable.")}finally{a.dispose()}if(!o.ok){let s=`room_action_http_${o.status}`;try{const d=await o.json();typeof d.error=="string"&&/^[a-z0-9_-]{1,80}$/.test(d.error)&&(s=d.error)}catch{}throw new c(s,"Shennian Room action failed.")}try{return await o.json()}catch{r()}}}function C(i,e){const t=new AbortController,n=()=>t.abort();i?.aborted?t.abort():i?.addEventListener("abort",n,{once:!0});const o=setTimeout(()=>t.abort(),e);return o.unref?.(),{signal:t.signal,dispose:()=>{clearTimeout(o),i?.removeEventListener("abort",n)}}}function q(i,e){(!i||typeof i!="object")&&r();const t=i,n=t.room,o=t.agent;(t.nianSessionId!==void 0&&t.nianSessionId!==null&&(typeof t.nianSessionId!="string"||!t.nianSessionId)||t.sessionRegistryKey!==void 0&&(typeof t.sessionRegistryKey!="string"||!/^[a-f0-9]{64}$/.test(t.sessionRegistryKey))||t.bindingId!==e.bindingId||t.roomId!==e.roomId||typeof t.agentIdentityId!="string"||t.agentMembershipId!==null&&typeof t.agentMembershipId!="string"||t.status!=="pending_approval"&&t.status!=="active"&&t.status!=="paused"&&t.status!=="detached"||!v(t.activationMode)||t.activationCapability!==void 0&&t.activationCapability!=="managed"&&t.activationCapability!=="idle_resume"&&t.activationCapability!=="notify_only"||t.managedWorkspacePath!==void 0&&t.managedWorkspacePath!==null&&(typeof t.managedWorkspacePath!="string"||t.managedWorkspacePath.length>4096||!_.isAbsolute(t.managedWorkspacePath))||typeof t.lastDeliveredSequence!="string"||!m(t.lastDeliveredSequence)||typeof t.lastActivatedSequence!="string"||!m(t.lastActivatedSequence)||t.appliedConfigurationVersion!==void 0&&(!Number.isSafeInteger(t.appliedConfigurationVersion)||Number(t.appliedConfigurationVersion)<1)||t.pendingConfigurationVersion!==void 0&&t.pendingConfigurationVersion!==null&&(!Number.isSafeInteger(t.pendingConfigurationVersion)||Number(t.pendingConfigurationVersion)<1)||!n||typeof n!="object"||o!==void 0&&(!o||typeof o!="object"))&&r(),(t.status==="pending_approval"&&t.agentMembershipId!==null||(t.status==="active"||t.status==="paused")&&typeof t.agentMembershipId!="string")&&r();const a=n,s=o,d=s?M(s.permissionPolicy):null,g=s?R(s.permissionConfirmation):null,w=s?Object.prototype.hasOwnProperty.call(s,"permissionConfirmation"):!1,l=a.members;return(s!==void 0&&(typeof s.displayName!="string"||!s.displayName.trim()||typeof s.description!="string"||s.sessionMode!=="standard"&&s.sessionMode!=="manager"||s.configurationVersion!==void 0&&(!Number.isSafeInteger(s.configurationVersion)||Number(s.configurationVersion)<1)||s.configurationPending!==void 0&&typeof s.configurationPending!="boolean"||!d||!w||s.permissionConfirmation!==null&&!g)||typeof a.name!="string"||typeof a.status!="string"||a.memberCount!==void 0&&(typeof a.memberCount!="number"||!Number.isInteger(a.memberCount)||a.memberCount<0)||typeof a.lastSequence!="string"||!m(a.lastSequence)||l!==void 0&&(!Array.isArray(l)||l.some(u=>{if(!u||typeof u!="object")return!0;const y=u;return typeof y.displayName!="string"||y.principalType!=="human"&&y.principalType!=="agent"})))&&r(),{...t,...s&&d?{agent:{...s,permissionPolicy:d,permissionConfirmation:g}}:{}}}function R(i){if(!i||typeof i!="object"||Array.isArray(i))return null;const e=i;return!Number.isSafeInteger(e.policyVersion)||Number(e.policyVersion)<1||typeof e.runtimeAdapter!="string"||!j(e.runtimeAdapter)||typeof e.runtimeVersion!="string"||!e.runtimeVersion.trim()||typeof e.platform!="string"||!e.platform.trim()||typeof e.executableFingerprint!="string"||!/^sha256:[a-f0-9]{64}$/.test(e.executableFingerprint)||typeof e.hostFullAccess!="boolean"||typeof e.limitedProtection!="boolean"||typeof e.confirmedAt!="string"||!Number.isFinite(Date.parse(e.confirmedAt))?null:{policyVersion:Number(e.policyVersion),runtimeAdapter:e.runtimeAdapter,runtimeVersion:e.runtimeVersion,platform:e.platform,executableFingerprint:e.executableFingerprint,executionMode:e.executionMode==="native-full"?"native-full":"restricted",hostFullAccess:e.hostFullAccess,limitedProtection:e.limitedProtection,confirmedAt:e.confirmedAt}}function h(i,e){(!i||typeof i!="object")&&r();const t=i;if((typeof t.id!="string"||t.roomId!==e||typeof t.sequence!="string"||!m(t.sequence)||!t.author||typeof t.author.membershipId!="string"||!Array.isArray(t.attachments)||typeof t.createdAt!="string")&&r(),t.activationCause!=null){const n=t.activationCause;(typeof n.causeMessageId!="string"||typeof n.rootCauseMessageId!="string"||!Number.isInteger(n.hopCount)||n.hopCount<1||n.hopCount>32)&&r()}return t}function T(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room,a=n.agentIdentity,s=n.binding;return(n.outcome!=="created"||!o||typeof o.id!="string"||o.name!==e.name||o.visibility!=="private"||o.joinPolicy!=="open"||!b(o.canonicalUrl,t,`/spaces/${o.id}`)||!P(o.inviteUrl,t,o.id)||!a||typeof a.id!="string"||a.displayName!==e.agentAlias||!s||typeof s.id!="string"||s.roomId!==o.id||s.agentIdentityId!==a.id||typeof s.agentMembershipId!="string"||s.status!=="active"&&s.status!=="paused"||s.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),n}function $(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room;return(n.outcome!=="created"||!o||typeof o.id!="string"||o.name!==e.name||o.visibility!=="private"||o.joinPolicy!=="open"||!b(o.canonicalUrl,t,`/spaces/${o.id}`))&&r(),n}function N(i,e,t){(!i||typeof i!="object")&&r();const n=i,o=n.room,a=n.agentIdentity,s=n.binding;return(n.outcome!=="joined"&&n.outcome!=="pending_approval"||!o||typeof o.id!="string"||typeof o.name!="string"||!b(o.canonicalUrl,t,`/spaces/${o.id}`)||!a||typeof a.id!="string"||a.displayName!==e.agentAlias||!s||typeof s.id!="string"||s.roomId!==o.id||s.agentIdentityId!==a.id||s.activationMode!==e.activationMode||typeof n.idempotent!="boolean")&&r(),(n.outcome==="pending_approval"&&(s.status!=="pending_approval"||s.agentMembershipId!==null||typeof n.joinRequestId!="string")||n.outcome==="joined"&&(s.status!=="active"&&s.status!=="paused"||typeof s.agentMembershipId!="string"||n.joinRequestId!==void 0))&&r(),n}function m(i){return/^(0|[1-9]\d{0,19})$/.test(i)}function I(i){return i.length<=255&&i===i.trim()&&i!=="."&&i!==".."&&!/[\\/\0-\x1f\x7f]/.test(i)}function S(i){if(typeof i!="string")return!1;try{const e=new URL(i);return e.protocol==="https:"&&!e.username&&!e.password&&!e.hash}catch{return!1}}function v(i){return i==="auto_follow"||i==="mention_only"||i==="paused"}function r(){throw new c("invalid_room_action_response","Invalid Room action response.")}async function p(i){try{return await i.json()}catch{r()}}function f(i,e){let t=`room_action_http_${i}`;if(e&&typeof e=="object"){const n=e.error;typeof n=="string"&&/^[a-z0-9_-]{1,80}$/.test(n)&&(t=n)}return new c(t,"Shennian Room action failed.")}function b(i,e,t){return A(i,e,n=>n.pathname===t)}function P(i,e,t){if(typeof i!="string")return!1;try{const n=new URL(i);return A(`${n.origin}${n.pathname}`,e,o=>o.pathname===`/spaces/${t}`)?n.searchParams.size===1&&/^[A-Za-z0-9_-]{32,256}$/.test(n.searchParams.get("invite")??"")&&!n.hash&&!n.username&&!n.password:!1}catch{return!1}}function A(i,e,t){if(typeof i!="string")return!1;try{const n=new URL(i),o=new URL(e),a=n.origin===o.origin,s=o.protocol==="http:"&&n.protocol==="http:"&&n.hostname===o.hostname,d=n.protocol==="https:"&&n.port===""&&n.hostname==="app.shennian.net";return(a||s||d)&&!n.username&&!n.password&&!n.search&&!n.hash&&t(n)}catch{return!1}}export{z as HttpRoomActionClient};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function issuePersonalScheduleContext(sessionId: string): string;
|
|
2
|
+
export declare function resolvePersonalScheduleContext(value: unknown): string;
|
|
3
|
+
export declare const PERSONAL_SCHEDULE_INSTRUCTIONS = "\u5982\u7528\u6237\u5B89\u6392\u7A0D\u540E\u6216\u5B9A\u671F\u5DE5\u4F5C\uFF0C\u4F7F\u7528 shennian schedule --operation create --operation-id <\u7A33\u5B9AID> --time-description <\u65F6\u95F4\u63CF\u8FF0> --timezone <IANA\u65F6\u533A> --prompt <\u5DE5\u4F5C\u5185\u5BB9>\u3002\u652F\u6301\u6BCF\u592909:00\u3001\u6BCF\u5468\u4E0009:00\u3001\u6BCF\u67081\u65E509:00\u3001\u6BCF\u969424\u5C0F\u65F6\u300130\u5206\u949F\u540E\u6216ISO\u65F6\u95F4\u3002\u67E5\u8BE2\u7528 --operation list\uFF1B\u4FEE\u6539/\u6682\u505C/\u6062\u590D/\u5220\u9664\u7528 update/pause/resume/delete\uFF0C\u5E76\u5E26\u67E5\u8BE2\u5F97\u5230\u7684 --id \u548C --version\u3002\u53EA\u5728\u771F\u5B9E\u4FDD\u5B58\u6210\u529F\u540E\u7528\u666E\u901A\u6587\u672C\u786E\u8BA4\u3002\u65F6\u95F4\u548C\u5DE5\u4F5C\u5185\u5BB9\u5206\u5F00\uFF0C\u4E0D\u5728\u5DE5\u4F5CPrompt\u91CC\u91CD\u590D\u521B\u5EFA\u5B9A\u65F6\u4EFB\u52A1\u3002";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomBytes as i}from"node:crypto";const o=new Map;function a(t){const e=Date.now();for(const[s,n]of o)if(n.expires<=e)o.delete(s);else if(n.sessionId===t)return n.expires=e+30*6e4,s;const r=i(32).toString("base64url");return o.set(r,{sessionId:t,expires:e+30*6e4}),r}function c(t){const e=typeof t=="string"?o.get(t):null;if(!e||e.expires<=Date.now())throw new Error("schedule_context_expired");return e.sessionId}const u="\u5982\u7528\u6237\u5B89\u6392\u7A0D\u540E\u6216\u5B9A\u671F\u5DE5\u4F5C\uFF0C\u4F7F\u7528 shennian schedule --operation create --operation-id <\u7A33\u5B9AID> --time-description <\u65F6\u95F4\u63CF\u8FF0> --timezone <IANA\u65F6\u533A> --prompt <\u5DE5\u4F5C\u5185\u5BB9>\u3002\u652F\u6301\u6BCF\u592909:00\u3001\u6BCF\u5468\u4E0009:00\u3001\u6BCF\u67081\u65E509:00\u3001\u6BCF\u969424\u5C0F\u65F6\u300130\u5206\u949F\u540E\u6216ISO\u65F6\u95F4\u3002\u67E5\u8BE2\u7528 --operation list\uFF1B\u4FEE\u6539/\u6682\u505C/\u6062\u590D/\u5220\u9664\u7528 update/pause/resume/delete\uFF0C\u5E76\u5E26\u67E5\u8BE2\u5F97\u5230\u7684 --id \u548C --version\u3002\u53EA\u5728\u771F\u5B9E\u4FDD\u5B58\u6210\u529F\u540E\u7528\u666E\u901A\u6587\u672C\u786E\u8BA4\u3002\u65F6\u95F4\u548C\u5DE5\u4F5C\u5185\u5BB9\u5206\u5F00\uFF0C\u4E0D\u5728\u5DE5\u4F5CPrompt\u91CC\u91CD\u590D\u521B\u5EFA\u5B9A\u65F6\u4EFB\u52A1\u3002";export{u as PERSONAL_SCHEDULE_INSTRUCTIONS,a as issuePersonalScheduleContext,c as resolvePersonalScheduleContext};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReqFrame, ScheduleAction } from '@shennian/wire';
|
|
2
|
+
import type { CliRelayClient } from '../relay/client.js';
|
|
3
|
+
import type { ChatQueueManager } from '../session/queue.js';
|
|
4
|
+
import type { RoomSessionRegistry } from '../room/session-registry.js';
|
|
5
|
+
export declare function executeServerSchedule(input: {
|
|
6
|
+
serverUrl: string;
|
|
7
|
+
machineToken: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
action: ScheduleAction;
|
|
10
|
+
args: Record<string, unknown>;
|
|
11
|
+
}): Promise<unknown>;
|
|
12
|
+
export declare function deliverServerSchedule(input: {
|
|
13
|
+
serverUrl: string;
|
|
14
|
+
machineToken: string;
|
|
15
|
+
req: ReqFrame;
|
|
16
|
+
client: CliRelayClient;
|
|
17
|
+
queue: ChatQueueManager;
|
|
18
|
+
registry: RoomSessionRegistry;
|
|
19
|
+
}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{listSessionRecords as a}from"../session/store.js";import{getPersonalSyncIdentity as d}from"../personal-sync/epoch.js";import{getDaemonInstallationId as c}from"../personal-sync/identity.js";import{NativeSourceDeletionStore as l}from"../native-fusion/native-source-deletions.js";async function t(e,s,n,o){const i=await fetch(`${e.replace(/\/$/,"")}/api/schedules${n}`,{method:"POST",headers:{authorization:`Bearer ${s}`,"content-type":"application/json"},body:JSON.stringify(o),signal:AbortSignal.timeout(15e3)}),r=await i.json();if(!i.ok)throw new Error(r.error??"schedules_unavailable");return r}async function g(e){const{context:s,action:n,...o}=e.args;return t(e.serverUrl,e.machineToken,"",{...o,sessionId:e.sessionId,action:e.action,timezone:o.timezone??Intl.DateTimeFormat().resolvedOptions().timeZone})}async function f(e){const s=await t(e.serverUrl,e.machineToken,"/delivery",e.req.params);if(typeof s.sessionId!="string"||typeof s.prompt!="string"||s.messageId!==e.req.params.deliveryId)throw new Error("schedule_delivery_invalid");const n=a().find(r=>r.sessionId===s.sessionId);if(!n||new l().hasSession(s.sessionId))throw new Error("schedule_session_unavailable");if((e.registry.getByNianSessionId(s.sessionId)?.binding?.bindingId??null)!==(s.bindingId??null))throw new Error("schedule_binding_mismatch");if(!await e.queue.enqueueScheduled({...e.req,method:"chat.enqueue",params:{...n,...d(c()),sessionId:s.sessionId,text:s.prompt,queueMessageId:s.messageId,clientMessageId:s.messageId,scheduledTask:{id:String(e.req.params.id),bindingId:s.bindingId??void 0,roomId:s.roomId??void 0}}}))throw new Error("schedule_enqueue_failed")}export{f as deliverServerSchedule,g as executeServerSchedule};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildManagedAgentEnv as
|
|
1
|
+
import{issuePersonalScheduleContext as i}from"../../schedules/personal-context.js";import{buildManagedAgentEnv as m}from"../../agents/config-status.js";import{lookupClaudeTranscriptCwd as p}from"../../native-fusion/parsers.js";import{getManagedRoomIpcRoot as d,MANAGED_ROOM_IPC_ROOT_ENV as f}from"../../daemon-ipc/paths.js";function x(n){return m(n)}function C(n,e,o){return{}}function N(n,e,o,t,a,r,u,c){const l=o==="codex";n.configure?.({sessionId:e,externalChannel:t??null,env:{...x(o),...!r&&!u?{SHENNIAN_SCHEDULE_CONTEXT:i(e)}:{},...C(e,t,a),...r&&!l?{SHENNIAN_MANAGED_ROOM_CONTEXT:r,[f]:d()}:{}},...u?{managedAgentPolicy:u}:{},...l?{managedRoomContextToken:r??null,managedRoomExecutor:r?c??null:null}:{}})}function g(n,e,o){const t=e.managedRoomContextToken;t&&t!==o&&n.revokeManagedRoomContextToken?.(t),e.managedRoomContextToken=o}function k(n,e){const o=e?.managedRoomContextToken;!e||!o||(e.managedRoomContextToken=null,n.revokeManagedRoomContextToken?.(o))}function v(n,e,o){if(n!=="claude"||!o)return e;const t=e.trim();return!!t&&t.startsWith("-")&&!t.includes("/")?p(o)??e:e}export{N as configureAdapterForSession,C as externalChannelEnv,x as managedProviderEnv,v as maybeResolveClaudeImportedWorkDir,g as replaceManagedRoomContextToken,k as revokeManagedRoomContextToken};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import se from"node:os";import{createHash as K,randomUUID as ke}from"node:crypto";import{buildUserMessagePayload as ie}from"@shennian/wire";import{reportLog as E}from"../../log-reporter.js";import{appendMessage as de,getDaemonInstallationId as le,getMessageDeliveryStatus as Pe,recordSession as Ae,upsertMessage as I}from"../store.js";import{mergeProjectedSessions as Me}from"../projection.js";import{parsePersonalAttachmentReferences as De}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as Ee,markAttachmentReferences as be}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as R}from"../index-publisher.js";import{getPersonalSyncIdentity as xe}from"../../personal-sync/epoch.js";import{buildManagedAgentPermissionPrompt as Te}from"../../room/managed-prompt-composer.js";import{getNativeSourceAgentType as Ce}from"./chat-events.js";import{configureAdapterForSession as ce,maybeResolveClaudeImportedWorkDir as $e,replaceManagedRoomContextToken as ue,revokeManagedRoomContextToken as ge}from"./chat-adapter-config.js";import{createActiveSession as qe,disposeSession as $,prepareAdapterTurn as We,rememberProcessedReqId as je,sendAdapterTurn as me}from"./chat-session-lifecycle.js";function Fe(e,n,t){if(e.source!=="room_activation")throw new Error("managed_room_execution_context_required");if(!e.managedAgentPolicy)throw new Error("managed_agent_policy_missing");const l=e.managedRoomPromptSnapshot;if(!l)throw new Error("managed_room_prompt_snapshot_missing");if(!n?.trim())throw new Error("managed_room_prompt_incomplete");if(!t||!/^mrc_[A-Za-z0-9_-]{43}$/.test(t))throw new Error("managed_room_context_unavailable");const o=K("sha256").update(JSON.stringify({requestedPolicy:e.managedAgentPolicy.requestedPolicy,enforcement:e.managedAgentPolicy.enforcement})).digest("hex"),b=K("sha256").update(e.managedAgentPolicy.adapterPolicy.workDir).digest("hex");if(l.runtimePermissionPolicyHash!==o||l.resolvedWorkDirHash!==b||l.enforcementLevel!==e.managedAgentPolicy.enforcement.level)throw new Error("managed_room_prompt_snapshot_mismatch")}function pe(e,n){return`Agent send failed: ${n instanceof Error?n.message:String(n)}`}function Be(e,n){Ae({sessionId:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,workDir:n.workDir,status:"active",externalChannel:null}}})}function Je(e,n){const t=e.sessions.get(n),l=t?.currentRunId;if(!t||!l)return;const o=t.nextEventSeq;e.runTextAcc.delete(`${n}:${l}`),ge(e,t),t.pendingTextEvent=null,t.currentRunId=null,t.currentRunPhase=null,t.nextEventSeq=0,t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:n,runId:l,seq:o},seq:o,id:`agent-evt-${l}-${o}`}),t.journalRunId&&(e.runJournal?.remove(n,t.journalRunId),e.recoveryBarrier?.end(n),t.journalRunId=null),e.chatQueue?.noteTerminal(n)}async function on(e,n,t){const l=t?n.params.managedRoomContextToken??null:null;let o=!1;try{await He(e,n,t,()=>{o=!0})}finally{l&&!o&&e.revokeManagedRoomContextToken?.(l)}}async function He(e,n,t,l){if(e.processedReqIds.has(n.id)){e.client.sendRes({type:"res",id:n.id,ok:!0});return}const{sessionId:o,text:b,agentType:P,sessionMode:fe,managerConfig:L,workDir:ye,agentSessionId:g,modelId:v,systemPrompt:Q,managerDefaultWorkerAgentType:q,managerDefaultWorkerModelId:W,reasoningEffort:j,clientMessageId:ve,sessionListProjection:he,waitForDispatch:Z,responseId:Ie,managedRoomContextToken:A,suppressExternalOwnerEcho:Re,queuedBatchItems:F,managedWorkerParentSessionId:h,managerWorkerNativeFull:G,managedRecoverySource:x}=n.params,c=Ie||n.id;Me(he);const T=null,B="";if(t?.source==="room_activation"&&(Fe(t,Q,A),P==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(je(e,n.id),!o||!b){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"sessionId and text are required"});return}if(e.recoveryBarrier?.isDispatchFrozen()){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"upgrade_in_progress"});return}e.recoveryBarrier?.isRecovering(o)&&await e.recoveryBarrier.wait(o);const d=P,_=d==="manager"||fe==="manager"?"manager":"standard";_==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(o,q??null,W??null);const M=(d==="claude"||d==="codex"||d==="workbuddy"||d==="pi-coding-agent"||d.startsWith("acp:"))&&typeof j=="string"&&j.trim()?j.trim():void 0,p=e.resolvePath($e(d,ye||se.homedir(),g)||se.homedir()),f=t?.managedAgentPolicy??(h?e.managerRuntime?.getManagedAgentPolicyForWorker(h,p)??null:null);if(h&&!G&&!f)throw new Error("managed_worker_permission_context_unavailable");const J=d==="codex"&&(t?.source==="room_activation"||t?.source==="manager_event"||h)?"internal":"user",H=h&&f?Te({requestedPolicy:f.requestedPolicy,enforcement:f.enforcement,resolvedWorkDir:f.adapterPolicy.workDir}):Q,_e=p,C=De(n.params.attachments);C?.length&&Ee(p,C);const m={text:b,attachments:C,localized:!1};let r=e.sessions.get(o);if(r){if(r.lastActiveAt=Date.now(),r.agentType!==d||(r.sessionMode??(r.agentType==="manager"?"manager":"standard"))!==_||r.workDir!==p||(r.nativeSessionVisibility??"user")!==J||JSON.stringify(r.externalChannel??null)!==JSON.stringify(T??null)){e.sessions.delete(o);try{await $(e,r)}catch{e.processedReqIds.delete(n.id)}r=void 0}else if(g&&r.agentSessionId!==g)try{await r.adapter.resume(g),r.agentSessionId=g}catch{e.sessions.delete(o);try{await $(e,r)}catch{e.processedReqIds.delete(n.id)}r=void 0}}if(!r)try{r=await qe(e,o,d,_,p,g,T,B,f,J)}catch(a){const i=a instanceof Error&&a.message.startsWith("Unsupported agent:")?a.message:`Failed to start ${P}: ${a instanceof Error?a.message:String(a)}`;console.error(`[chat.send] start failed reqId=${n.id} sessionId=${o} agentType=${P} workDir=${p} agentSessionId=${g??""}: ${i}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:i,runId:"",seq:0}}),e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:i});return}const u={id:ve??`user-${n.id}`,sessionId:o,role:"user",ts:Date.now(),payload:ie(m.text,m.attachments)},X=Array.isArray(F)&&F.length>0?F.map(a=>({id:a.clientMessageId??a.id,sessionId:o,role:x==="manager_event"?"agent":"user",ts:x==="manager_event"?Date.parse(a.createdAt):u.ts,payload:ie(a.text,a.attachments)})):null,w=X??[u],z=Pe(o,u.id),Y=z.state==="queued";if(z.state!=="not_found"&&!Y){e.client.sendRes({type:"res",id:c,ok:!0,payload:z});return}if(Z){(t?.source==="room_activation"||t?.source==="manager_event")&&ce(r.adapter,o,d,T,B,t.source==="room_activation"?A:null,t.managedAgentPolicy,e.managedRoomExecutor);try{await We(r.adapter,m.text,v,M,m.attachments,H,t?.source==="room_activation"?{source:"room_activation"}:void 0)}catch(a){e.processedReqIds.delete(n.id),e.sessions.delete(o),await $(e,r),e.client.sendRes({type:"res",id:c,ok:!1,error:a instanceof Error?a.message:String(a)});return}}E({level:"info",sessionId:o,wsEvent:"chat.send.start",metadata:{reqId:n.id,agentType:d,sessionMode:_,managerConfig:L??null,modelId:v,managerDefaultWorkerAgentType:q??null,managerDefaultWorkerModelId:W??null,reasoningEffort:M,...t?.source==="room_activation"?{managedRoomPromptSnapshot:t.managedRoomPromptSnapshot}:{}}});const S=(a,i)=>({...xe(le()),sessionId:o,clientMessageId:u.id,messageId:u.id,deliveryState:a,bodyRevision:i,committedAt:new Date(u.ts).toISOString()}),N=a=>{e.nativeFusion?.registerManagedSend({sessionId:o,agentType:d,sourceAgentType:Ce(d,v),canonicalMessageId:u.id,sourceSessionKey:r.agentSessionId??g??null,text:m.text,managedEchoPolicy:a?.deliveryMode==="external_owner_queue"&&!Re?"import_following":"suppress_following",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ee=()=>{r.currentRunId||(r.currentRunId=`dispatch:${n.id}`,r.currentRunPhase="thinking",r.nextEventSeq=0)},ne=()=>{if(!e.runJournal||r.journalRunId)return;const a=`run:${ke()}`;e.runJournal.begin({daemonInstallationId:le(),sessionId:o,runId:a,clientMessageId:u.id,agentType:d,sessionMode:_,workDir:p,agentSessionId:r.agentSessionId??g??null,modelId:v??null,reasoningEffort:M??null,nativeSessionVisibility:J,providerRunId:null,source:x==="manager_event"?"manager_event":t?.source==="room_activation"?x==="managed_direct"?"managed_direct":"managed_room":h?"manager_worker":"personal",parentSessionId:h??null,managerWorkerNativeFull:G===!0,roomContextRegistryKey:typeof n.params.roomContextRegistryKey=="string"?n.params.roomContextRegistryKey:null,activationCauseMessageId:typeof n.params.activationCauseMessageId=="string"?n.params.activationCauseMessageId:null,rootCauseMessageId:typeof n.params.rootCauseMessageId=="string"?n.params.rootCauseMessageId:null,activationSequence:typeof n.params.activationSequence=="string"?n.params.activationSequence:null,activationHopCount:typeof n.params.activationHopCount=="number"?n.params.activationHopCount:null,managedPolicyVersion:t?.source==="room_activation"?t.managedRoomPromptSnapshot.managedRoomPolicyVersion:t?.source==="manager_event"?t.managedRoomPolicyVersion:null,managedRuntimePolicyHash:(t?.source==="room_activation"?t.managedRoomPromptSnapshot.runtimePermissionPolicyHash:t?.source==="manager_event"?t.managedRuntimePolicyHash:null)??(f?K("sha256").update(JSON.stringify({requestedPolicy:f.requestedPolicy,enforcement:f.enforcement})).digest("hex"):null)}),r.journalRunId=a},ae=()=>{if(N(),Y){let a=0;for(const[i,s]of w.entries()){const y=I(o,s,"queued");i===0&&(a=y)}return S("queued",a)}try{Be(e,{sessionId:o,agentType:d,sessionMode:_,managerConfig:L??null,workDir:_e,agentSessionId:r.agentSessionId??g??null,modelId:v,managerDefaultWorkerAgentType:q??null,managerDefaultWorkerModelId:W??null});let a=0;for(const[i,s]of w.entries()){const y=X?I(o,s,"committed"):de(o,s,"committed");i===0&&(a=y)}return be(p,C??[]),R(e.client),S("committed",a)}catch(a){throw e.nativeFusion?.cancelManagedSend?.(u.id),a}},oe=a=>{r.journalRunId&&e.runJournal?.update(o,r.journalRunId,{deliveryMode:a?.deliveryMode==="external_owner_queue"?"external_owner_queue":"direct",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},te=a=>{r.currentRunId||(r.nextEventSeq=0),oe(a),N(a);const i=a?.deliveryMode==="external_owner_queue"?"queued":"executing";let s=0;for(const[y,D]of w.entries()){const k=I(o,D,i);y===0&&(s=k)}return R(e.client),S(i,s)},U=async(a,i)=>{e.nativeFusion?.cancelManagedSend?.(u.id);const s=pe(d,a);if(console.error(`[chat.send] send failed reqId=${n.id} sessionId=${o} agentType=${P} workDir=${p} agentSessionId=${r.agentSessionId??g??""}: ${s}`),r.adapter.hasPendingAuthenticationRetry?.()===!0){i&&e.client.sendRes({type:"res",id:c,ok:!0,payload:S("queued",0)});return}e.sessions.delete(o),r.journalRunId&&(e.runJournal?.update(o,r.journalRunId,{phase:"terminal"}),e.runJournal?.remove(o,r.journalRunId),e.recoveryBarrier?.end(o),r.journalRunId=null);try{await $(e,r)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:s,runId:"",seq:0}}),!i){const D={id:`agent-error-${n.id}-${Date.now()}`,sessionId:o,role:"agent",ts:Date.now(),payload:s};de(o,D),R(e.client)}i&&(e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:s}))};if(Z){try{ae()}catch(s){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${s instanceof Error?s.message:String(s)}`});return}ne(),ee();let a;try{t?.source==="room_activation"&&(ue(e,r,A),l());const s=m.attachments;a=await me(r.adapter,m.text,v,M,s,H,t?.source==="room_activation"?{source:"room_activation"}:void 0),E({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}catch(s){if(r.adapter.hasPendingAuthenticationRetry?.()){let k=0;for(const[O,V]of w.entries()){const Se=I(o,V,"queued");O===0&&(k=Se)}R(e.client),await U(s,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:S("queued",k)});return}let y=0;for(const[k,O]of w.entries()){const V=I(o,O,"failed");k===0&&(y=V)}R(e.client);const D=pe(d,s);await U(s,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...S("failed",y),failureMessage:D}});return}const i=te(a??void 0);e.client.sendRes({type:"res",id:c,ok:!0,payload:{...i,...m.localized?{localizedAttachments:!0}:{},...a?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:a.deliveryMode,queuedSubmissionId:a.queuedSubmissionId}:{}}}),E({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});return}let re;try{re=ae()}catch(a){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${a instanceof Error?a.message:String(a)}`});return}ne(),ee(),t?.source==="room_activation"&&(ce(r.adapter,o,d,T,B,A,t.managedAgentPolicy,e.managedRoomExecutor),ue(e,r,A),l()),te(),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...re,...m.localized?{localizedAttachments:!0}:{}}}),E({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});const we=m.attachments;me(r.adapter,m.text,v,M,we,H,t?.source==="room_activation"?{source:"room_activation"}:void 0).then(a=>{if(a?.deliveryMode==="external_owner_queue"){oe(a),N(a);for(const i of w)I(o,i,"queued");R(e.client)}E({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}).catch(a=>{I(o,u,r.adapter.hasPendingAuthenticationRetry?.()?"queued":"failed"),R(e.client),U(a,!1)})}async function tn(e,n){const{sessionId:t,discardPending:l}=n.params,o=e.sessions.get(t);if(o){o.journalRunId&&e.runJournal?.markAborted(t,o.journalRunId),ge(e,o);try{await o.adapter.stop()}catch{e.client.sendRes({type:"res",id:n.id,ok:!1,error:"agent_stop_failed"});return}Je(e,t),e.activityPublisher?.publish(t,null)}l===!0&&e.chatQueue?.purgeSession(t),e.client.sendRes({type:"res",id:n.id,ok:!0})}export{tn as handleChatAbort,on as handleChatSend,Be as sendSessionUpdateEvent,Fe as validateManagedRoomExecutionContext};
|
|
1
|
+
import{PERSONAL_SCHEDULE_INSTRUCTIONS as ke}from"../../schedules/personal-context.js";import se from"node:os";import{createHash as K,randomUUID as Pe}from"node:crypto";import{buildUserMessagePayload as ie}from"@shennian/wire";import{reportLog as E}from"../../log-reporter.js";import{appendMessage as de,getDaemonInstallationId as le,getMessageDeliveryStatus as Ae,recordSession as Me,upsertMessage as I}from"../store.js";import{mergeProjectedSessions as De}from"../projection.js";import{parsePersonalAttachmentReferences as Ee}from"../attachment-reference.js";import{assertFinishedAttachmentReferences as Te,markAttachmentReferences as Ce}from"../attachment-transfer-store.js";import{requestSessionIndexPublish as R}from"../index-publisher.js";import{getPersonalSyncIdentity as be}from"../../personal-sync/epoch.js";import{buildManagedAgentPermissionPrompt as xe}from"../../room/managed-prompt-composer.js";import{getNativeSourceAgentType as $e}from"./chat-events.js";import{configureAdapterForSession as ce,maybeResolveClaudeImportedWorkDir as qe,replaceManagedRoomContextToken as ue,revokeManagedRoomContextToken as ge}from"./chat-adapter-config.js";import{createActiveSession as We,disposeSession as $,prepareAdapterTurn as je,rememberProcessedReqId as Be,sendAdapterTurn as me}from"./chat-session-lifecycle.js";function Fe(e,n,t){if(e.source!=="room_activation")throw new Error("managed_room_execution_context_required");if(!e.managedAgentPolicy)throw new Error("managed_agent_policy_missing");const l=e.managedRoomPromptSnapshot;if(!l)throw new Error("managed_room_prompt_snapshot_missing");if(!n?.trim())throw new Error("managed_room_prompt_incomplete");if(!t||!/^mrc_[A-Za-z0-9_-]{43}$/.test(t))throw new Error("managed_room_context_unavailable");const o=K("sha256").update(JSON.stringify({requestedPolicy:e.managedAgentPolicy.requestedPolicy,enforcement:e.managedAgentPolicy.enforcement})).digest("hex"),T=K("sha256").update(e.managedAgentPolicy.adapterPolicy.workDir).digest("hex");if(l.runtimePermissionPolicyHash!==o||l.resolvedWorkDirHash!==T||l.enforcementLevel!==e.managedAgentPolicy.enforcement.level)throw new Error("managed_room_prompt_snapshot_mismatch")}function pe(e,n){return`Agent send failed: ${n instanceof Error?n.message:String(n)}`}function He(e,n){Me({sessionId:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId}),e.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:n.sessionId,agentType:n.agentType,sessionMode:n.sessionMode,managerConfig:n.managerConfig,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,workDir:n.workDir,status:"active",externalChannel:null}}})}function Je(e,n){const t=e.sessions.get(n),l=t?.currentRunId;if(!t||!l)return;const o=t.nextEventSeq;e.runTextAcc.delete(`${n}:${l}`),ge(e,t),t.pendingTextEvent=null,t.currentRunId=null,t.currentRunPhase=null,t.nextEventSeq=0,t.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null),e.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"aborted",sessionId:n,runId:l,seq:o},seq:o,id:`agent-evt-${l}-${o}`}),t.journalRunId&&(e.runJournal?.remove(n,t.journalRunId),e.recoveryBarrier?.end(n),t.journalRunId=null),e.chatQueue?.noteTerminal(n)}async function rn(e,n,t){const l=t?n.params.managedRoomContextToken??null:null;let o=!1;try{await Ne(e,n,t,()=>{o=!0})}finally{l&&!o&&e.revokeManagedRoomContextToken?.(l)}}async function Ne(e,n,t,l){if(e.processedReqIds.has(n.id)){e.client.sendRes({type:"res",id:n.id,ok:!0});return}const{sessionId:o,text:T,agentType:P,sessionMode:fe,managerConfig:Q,workDir:ye,agentSessionId:g,modelId:h,systemPrompt:q,managerDefaultWorkerAgentType:W,managerDefaultWorkerModelId:j,reasoningEffort:B,clientMessageId:ve,sessionListProjection:he,waitForDispatch:Z,responseId:Ie,managedRoomContextToken:A,suppressExternalOwnerEcho:Re,queuedBatchItems:F,managedWorkerParentSessionId:v,managerWorkerNativeFull:G,managedRecoverySource:C}=n.params,c=Ie||n.id;De(he);const b=null,H="";if(t?.source==="room_activation"&&(Fe(t,q,A),P==="manager"))throw new Error("managed_agent_manager_mode_unsupported");if(Be(e,n.id),!o||!T){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"sessionId and text are required"});return}if(e.recoveryBarrier?.isDispatchFrozen()){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:"upgrade_in_progress"});return}e.recoveryBarrier?.isRecovering(o)&&await e.recoveryBarrier.wait(o);const i=P,_=i==="manager"||fe==="manager"?"manager":"standard";_==="manager"&&e.managerRuntime?.setManagerWorkerDefaults(o,W??null,j??null);const M=(i==="claude"||i==="codex"||i==="workbuddy"||i==="pi-coding-agent"||i.startsWith("acp:"))&&typeof B=="string"&&B.trim()?B.trim():void 0,p=e.resolvePath(qe(i,ye||se.homedir(),g)||se.homedir()),f=t?.managedAgentPolicy??(v?e.managerRuntime?.getManagedAgentPolicyForWorker(v,p)??null:null);if(v&&!G&&!f)throw new Error("managed_worker_permission_context_unavailable");const J=i==="codex"&&(t?.source==="room_activation"||t?.source==="manager_event"||v)?"internal":"user",N=v&&f?xe({requestedPolicy:f.requestedPolicy,enforcement:f.enforcement,resolvedWorkDir:f.adapterPolicy.workDir}):!t&&!v&&!i.startsWith("custom:")?[q,ke].filter(Boolean).join(`
|
|
2
|
+
|
|
3
|
+
`):q,_e=p,x=Ee(n.params.attachments);x?.length&&Te(p,x);const m={text:T,attachments:x,localized:!1};let r=e.sessions.get(o);if(r){if(r.lastActiveAt=Date.now(),r.agentType!==i||(r.sessionMode??(r.agentType==="manager"?"manager":"standard"))!==_||r.workDir!==p||(r.nativeSessionVisibility??"user")!==J||JSON.stringify(r.externalChannel??null)!==JSON.stringify(b??null)){e.sessions.delete(o);try{await $(e,r)}catch{e.processedReqIds.delete(n.id)}r=void 0}else if(g&&r.agentSessionId!==g)try{await r.adapter.resume(g),r.agentSessionId=g}catch{e.sessions.delete(o);try{await $(e,r)}catch{e.processedReqIds.delete(n.id)}r=void 0}}if(!r)try{r=await We(e,o,i,_,p,g,b,H,f,J)}catch(a){const d=a instanceof Error&&a.message.startsWith("Unsupported agent:")?a.message:`Failed to start ${P}: ${a instanceof Error?a.message:String(a)}`;console.error(`[chat.send] start failed reqId=${n.id} sessionId=${o} agentType=${P} workDir=${p} agentSessionId=${g??""}: ${d}`),e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:d,runId:"",seq:0}}),e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:d});return}const u={id:ve??`user-${n.id}`,sessionId:o,role:"user",ts:Date.now(),payload:ie(m.text,m.attachments)},X=Array.isArray(F)&&F.length>0?F.map(a=>({id:a.clientMessageId??a.id,sessionId:o,role:C==="manager_event"||n.params.scheduledDelivery===!0?"agent":"user",ts:C==="manager_event"?Date.parse(a.createdAt):u.ts,payload:ie(a.text,a.attachments)})):null,S=X??[u],z=Ae(o,u.id),Y=z.state==="queued";if(z.state!=="not_found"&&!Y){e.client.sendRes({type:"res",id:c,ok:!0,payload:z});return}if(Z){(t?.source==="room_activation"||t?.source==="manager_event")&&ce(r.adapter,o,i,b,H,t.source==="room_activation"?A:null,t.managedAgentPolicy,e.managedRoomExecutor);try{await je(r.adapter,m.text,h,M,m.attachments,N,t?.source==="room_activation"?{source:"room_activation"}:void 0)}catch(a){e.processedReqIds.delete(n.id),e.sessions.delete(o),await $(e,r),e.client.sendRes({type:"res",id:c,ok:!1,error:a instanceof Error?a.message:String(a)});return}}E({level:"info",sessionId:o,wsEvent:"chat.send.start",metadata:{reqId:n.id,agentType:i,sessionMode:_,managerConfig:Q??null,modelId:h,managerDefaultWorkerAgentType:W??null,managerDefaultWorkerModelId:j??null,reasoningEffort:M,...t?.source==="room_activation"?{managedRoomPromptSnapshot:t.managedRoomPromptSnapshot}:{}}});const w=(a,d)=>({...be(le()),sessionId:o,clientMessageId:u.id,messageId:u.id,deliveryState:a,bodyRevision:d,committedAt:new Date(u.ts).toISOString()}),U=a=>{e.nativeFusion?.registerManagedSend({sessionId:o,agentType:i,sourceAgentType:$e(i,h),canonicalMessageId:u.id,sourceSessionKey:r.agentSessionId??g??null,text:m.text,managedEchoPolicy:a?.deliveryMode==="external_owner_queue"&&!Re?"import_following":"suppress_following",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},ee=()=>{r.currentRunId||(r.currentRunId=`dispatch:${n.id}`,r.currentRunPhase="thinking",r.nextEventSeq=0)},ne=()=>{if(!e.runJournal||r.journalRunId)return;const a=`run:${Pe()}`;e.runJournal.begin({daemonInstallationId:le(),sessionId:o,runId:a,clientMessageId:u.id,agentType:i,sessionMode:_,workDir:p,agentSessionId:r.agentSessionId??g??null,modelId:h??null,reasoningEffort:M??null,nativeSessionVisibility:J,providerRunId:null,source:C==="manager_event"?"manager_event":t?.source==="room_activation"?C==="managed_direct"?"managed_direct":"managed_room":v?"manager_worker":"personal",parentSessionId:v??null,managerWorkerNativeFull:G===!0,roomContextRegistryKey:typeof n.params.roomContextRegistryKey=="string"?n.params.roomContextRegistryKey:null,activationCauseMessageId:typeof n.params.activationCauseMessageId=="string"?n.params.activationCauseMessageId:null,rootCauseMessageId:typeof n.params.rootCauseMessageId=="string"?n.params.rootCauseMessageId:null,activationSequence:typeof n.params.activationSequence=="string"?n.params.activationSequence:null,activationHopCount:typeof n.params.activationHopCount=="number"?n.params.activationHopCount:null,managedPolicyVersion:t?.source==="room_activation"?t.managedRoomPromptSnapshot.managedRoomPolicyVersion:t?.source==="manager_event"?t.managedRoomPolicyVersion:null,managedRuntimePolicyHash:(t?.source==="room_activation"?t.managedRoomPromptSnapshot.runtimePermissionPolicyHash:t?.source==="manager_event"?t.managedRuntimePolicyHash:null)??(f?K("sha256").update(JSON.stringify({requestedPolicy:f.requestedPolicy,enforcement:f.enforcement})).digest("hex"):null)}),r.journalRunId=a},ae=()=>{if(U(),Y){let a=0;for(const[d,s]of S.entries()){const y=I(o,s,"queued");d===0&&(a=y)}return w("queued",a)}try{He(e,{sessionId:o,agentType:i,sessionMode:_,managerConfig:Q??null,workDir:_e,agentSessionId:r.agentSessionId??g??null,modelId:h,managerDefaultWorkerAgentType:W??null,managerDefaultWorkerModelId:j??null});let a=0;for(const[d,s]of S.entries()){const y=X?I(o,s,"committed"):de(o,s,"committed");d===0&&(a=y)}return Ce(p,x??[]),R(e.client),w("committed",a)}catch(a){throw e.nativeFusion?.cancelManagedSend?.(u.id),a}},oe=a=>{r.journalRunId&&e.runJournal?.update(o,r.journalRunId,{deliveryMode:a?.deliveryMode==="external_owner_queue"?"external_owner_queue":"direct",externalRunId:a?.deliveryMode==="external_owner_queue"?`codex-external-${a.queuedSubmissionId??u.id}`:null})},te=a=>{r.currentRunId||(r.nextEventSeq=0),oe(a),U(a);const d=a?.deliveryMode==="external_owner_queue"?"queued":"executing";let s=0;for(const[y,D]of S.entries()){const k=I(o,D,d);y===0&&(s=k)}return R(e.client),w(d,s)},O=async(a,d)=>{e.nativeFusion?.cancelManagedSend?.(u.id);const s=pe(i,a);if(console.error(`[chat.send] send failed reqId=${n.id} sessionId=${o} agentType=${P} workDir=${p} agentSessionId=${r.agentSessionId??g??""}: ${s}`),r.adapter.hasPendingAuthenticationRetry?.()===!0){d&&e.client.sendRes({type:"res",id:c,ok:!0,payload:w("queued",0)});return}e.sessions.delete(o),r.journalRunId&&(e.runJournal?.update(o,r.journalRunId,{phase:"terminal"}),e.runJournal?.remove(o,r.journalRunId),e.recoveryBarrier?.end(o),r.journalRunId=null);try{await $(e,r)}catch{}if(e.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:o,message:s,runId:"",seq:0}}),!d){const D={id:`agent-error-${n.id}-${Date.now()}`,sessionId:o,role:"agent",ts:Date.now(),payload:s};de(o,D),R(e.client)}d&&(e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:s}))};if(Z){try{ae()}catch(s){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${s instanceof Error?s.message:String(s)}`});return}ne(),ee();let a;try{t?.source==="room_activation"&&(ue(e,r,A),l());const s=m.attachments;a=await me(r.adapter,m.text,h,M,s,N,t?.source==="room_activation"?{source:"room_activation"}:void 0),E({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}catch(s){if(r.adapter.hasPendingAuthenticationRetry?.()){let k=0;for(const[L,V]of S.entries()){const we=I(o,V,"queued");L===0&&(k=we)}R(e.client),await O(s,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:w("queued",k)});return}let y=0;for(const[k,L]of S.entries()){const V=I(o,L,"failed");k===0&&(y=V)}R(e.client);const D=pe(i,s);await O(s,!1),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...w("failed",y),failureMessage:D}});return}const d=te(a??void 0);e.client.sendRes({type:"res",id:c,ok:!0,payload:{...d,...m.localized?{localizedAttachments:!0}:{},...a?.deliveryMode==="external_owner_queue"?{queued:!0,deliveryMode:a.deliveryMode,queuedSubmissionId:a.queuedSubmissionId}:{}}}),E({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});return}let re;try{re=ae()}catch(a){e.processedReqIds.delete(n.id),e.client.sendRes({type:"res",id:c,ok:!1,error:`Durable message commit failed: ${a instanceof Error?a.message:String(a)}`});return}ne(),ee(),t?.source==="room_activation"&&(ce(r.adapter,o,i,b,H,A,t.managedAgentPolicy,e.managedRoomExecutor),ue(e,r,A),l()),te(),e.client.sendRes({type:"res",id:c,ok:!0,payload:{...re,...m.localized?{localizedAttachments:!0}:{}}}),E({level:"info",sessionId:o,wsEvent:"chat.send.res",metadata:{reqId:n.id,ok:!0}});const Se=m.attachments;me(r.adapter,m.text,h,M,Se,N,t?.source==="room_activation"?{source:"room_activation"}:void 0).then(a=>{if(a?.deliveryMode==="external_owner_queue"){oe(a),U(a);for(const d of S)I(o,d,"queued");R(e.client)}E({level:"info",sessionId:o,wsEvent:"chat.send.done",metadata:{reqId:n.id}})}).catch(a=>{I(o,u,r.adapter.hasPendingAuthenticationRetry?.()?"queued":"failed"),R(e.client),O(a,!1)})}async function sn(e,n){const{sessionId:t,discardPending:l}=n.params,o=e.sessions.get(t);if(o){o.journalRunId&&e.runJournal?.markAborted(t,o.journalRunId),ge(e,o);try{await o.adapter.stop()}catch{e.client.sendRes({type:"res",id:n.id,ok:!1,error:"agent_stop_failed"});return}Je(e,t),e.activityPublisher?.publish(t,null)}l===!0&&e.chatQueue?.purgeSession(t),e.client.sendRes({type:"res",id:n.id,ok:!0})}export{sn as handleChatAbort,rn as handleChatSend,He as sendSessionUpdateEvent,Fe as validateManagedRoomExecutionContext};
|
|
@@ -4,7 +4,7 @@ import type { SessionManagerRuntime, RemoteAccessPauseController, UpgradePolicyC
|
|
|
4
4
|
import type { UpgradeIdleState } from '../upgrade/scheduler.js';
|
|
5
5
|
import type { NativeSessionFusionService } from '../native-fusion/service.js';
|
|
6
6
|
import { type LocalReqDispatchResult } from '../manager/runtime.js';
|
|
7
|
-
import { type ManagedRoomEnqueueParams, type ManagedRoomQueueContext, type PreparedManagedRoomTurn } from './queue.js';
|
|
7
|
+
import { ChatQueueManager, type ManagedRoomEnqueueParams, type ManagedRoomQueueContext, type PreparedManagedRoomTurn } from './queue.js';
|
|
8
8
|
import '../agents/claude.js';
|
|
9
9
|
import '../agents/codex.js';
|
|
10
10
|
import '../agents/workbuddy.js';
|
|
@@ -28,6 +28,8 @@ export declare class SessionManager {
|
|
|
28
28
|
private managedRoomContextRevoker;
|
|
29
29
|
private managedRoomExecutor;
|
|
30
30
|
private trustedProjectFsRequestResolver;
|
|
31
|
+
scheduleHandler?: (req: ReqFrame) => Promise<void>;
|
|
32
|
+
getScheduleQueue(): ChatQueueManager;
|
|
31
33
|
private sessions;
|
|
32
34
|
/** Track processed request IDs to deduplicate replayed offline messages */
|
|
33
35
|
private processedReqIds;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{SESSION_SYNC_PROTOCOL_VERSION as g,SESSION_SYNC_DATA_EPOCH as f}from"@shennian/wire";import h from"node:crypto";import{getRegisteredAgents as w,unregisterAgent as I}from"../agents/adapter.js";import{resetCommandSpecCache as A}from"../agents/command-spec.js";import{loadConfig as T}from"../config/index.js";import{handleUpgradeStart as P,handleUpgradeStatus as C}from"../commands/upgrade.js";import{handleAgentsRefresh as M,handleModelsRefresh as D,refreshMachineAgents as x}from"./handlers/agents.js";import{AcpDiscoveryWatcher as E}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as F}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as O,handleAgentConfigGet as _,handleAgentConfigTest as j,handleAgentConfigUpsert as Q}from"./handlers/agent-config.js";import{handleChatAbort as B,handleChatSend as U}from"./handlers/chat.js";import{recoverJournaledRun as z}from"./handlers/chat-recovery.js";import{handleSessionRefresh as W}from"./handlers/session-refresh.js";import{handleSessionToolDetail as $}from"./handlers/tool-detail.js";import{handleSessionTitleSet as H}from"./handlers/title.js";import{handleSessionMessageStatus as J}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as N}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as V}from"./handlers/voice-window.js";import{handleRemoteAccessPause as L}from"./handlers/remote-access.js";import{cleanupPendingTransfers as G,handleFsLs as Y,handleFsRead as K,handleFsRename as X,handleFsWrite as Z,handleFsTransferAbort as q,handleFsTransferChunk as ee,handleFsTransferFinish as se,handleFsTransferStart as te,handleFsExportMarkdownPdf as ae,handleFsExportMarkdownPdfSetup as ne,handleFsArchiveZip as re}from"./handlers/fs.js";import{handleRegionProbe as ie,handleRegionSwitch as oe,handleUpgradeSetPolicy as ce}from"./handlers/control.js";import{ManagerRuntimeService as le,setManagerRuntimeService as v}from"../manager/runtime.js";import{ChatQueueManager as de}from"./queue.js";import{createAuthorizedFsRoot as he,createAuthorizedFsRootAsync as ue,resolveAuthorizedPath as pe,resolveAuthorizedPathAsync as me,resolveSessionWorkDir as ge}from"../fs/boundary.js";import"../agents/claude.js";import"../agents/codex.js";import"../agents/workbuddy.js";import"../agents/gemini.js";import"../agents/cursor.js";import"../agents/opencode.js";import"../agents/pi-coding-agent.js";import"../agents/manager.js";import{registerCustomAgent as fe}from"../agents/custom.js";import{handleManagedRoomBind as ve,handleManagedRoomRestart as ye,discardPreBindingSession as Re}from"./handlers/room-managed.js";import{getDaemonInstallationId as u,listSessionRecords as p,purgeCanonicalSession as be,purgeSessionRecord as Se,recordSession as ke,upsertMessage as we}from"./store.js";import{requestSessionIndexPublish as Ie}from"./index-publisher.js";import{reportUpgradeAggregateMetric as Ae}from"../log-reporter.js";import{PersonalHistorySubscriptions as Te}from"./history-subscriptions.js";import{sweepAttachmentTransfers as Pe}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Ce}from"../native-fusion/native-source-deletions.js";import{purgeToolDetails as Me}from"./tool-detail-store.js";import{readDeletionSyncRevision as De,writeDeletionSyncRevision as y}from"./deletion-sync-state.js";import{assertDeletionSyncRunnable as xe,clearDeletionSyncFailure as Ee,DeletionSyncRetryWaitError as Fe,DeletionSyncTerminalError as Oe,recordDeletionSyncFailure as m}from"./deletion-sync-state.js";import{NativeSessionCleanupOutbox as _e}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as c}from"../personal-sync/epoch.js";import{ActiveRunJournal as je}from"./run-recovery/journal.js";import{RunRecoveryBarrier as Qe}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Be}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as Ue}from"./project-fs-store.js";import{handleProjectFsRequest as ze}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as We,handleAcpAgentRequest as $e}from"./handlers/agent-control.js";import{validateDeletionSyncResponse as He}from"./deletion-sync-validation.js";import{dispatchManagedChat as Je,dispatchQueuedChat as Ne,interruptQueuedChat as Ve}from"./queued-chat-dispatch.js";const Le=50;import{resolveSessionWorkDir as Xs}from"../fs/boundary.js";class Gs{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;sessions=new Map;processedReqIds=new Set;runTextAcc=new Map;pendingTransfers=new Map;managerRuntime;chatQueue;historySubscriptions;nativeCleanupOutbox;activityProbeTimer=null;attachmentCleanupTimer=null;activeRequests=0;acpDiscoveryWatcher;runJournal;recoveryBarrier=new Qe;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new Ue;constructor(e,t=null,s,r=null,n=null,d=null,o=null,R=null,b=null,S=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=r,this.managedRoomBinder=n,this.remoteAccessPauseController=d,this.managedRoomContextRevoker=o,this.managedRoomExecutor=R,this.trustedProjectFsRequestResolver=S,this.runJournal=b??new je(u());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Be({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>z(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=p().find(k=>k.sessionId===a.sessionId),l=`terminal:${h.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===l},onOutcome:a=>Ae({kind:"recovery",adapterType:a.adapterType,result:a.result,stage:a.result==="continued"?"continue":a.result==="reattached"?"reattach":a.result==="resumed"?"resume":a.result==="terminal_reconciled"?"inspect":"terminal",durationMs:a.durationMs,retries:Math.max(0,a.attempts-1),...a.reason?{errorCode:a.reason}:{}})}),this.managerRuntime=new le({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new de({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Je(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>Ne(this.getRuntime(),a,i),interruptQueuedSession:a=>Ve(this.getRuntime(),a)}),this.historySubscriptions=new Te(this.client),this.nativeCleanupOutbox=new _e({logger:console.info}),this.acpDiscoveryWatcher=new E(async()=>{A(),await x(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeCleanupOutbox.start(),v(this.managerRuntime),this.managerRuntime.start(),this.reloadCustomAgents();try{this.acpDiscoveryWatcher.start()}catch(a){console.warn(`[acp.discovery] watcher unavailable: ${a instanceof Error?a.message:String(a)}`)}this.activityProbeTimer=setInterval(()=>{this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.attachmentCleanupTimer=setInterval(()=>{const a=new Set([...p().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{Pe(this.resolvePath(i))}catch(l){console.error("[attachment.cleanup] failed",l instanceof Error?l.message:String(l))}},6e4),this.attachmentCleanupTimer.unref?.()}executeManagedManagerAction(e){return this.managerRuntime.executeScopedWorkerAction(e.managerSessionId,e.action,e.params)}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),resolvePath:e=>this.resolvePath(e),resolveAuthorizedPath:(e,t)=>this.resolveAuthorizedPath(e,t),resolveAuthorizedPathAsync:(e,t)=>this.resolveAuthorizedPathAsync(e,t),runTextAcc:this.runTextAcc,sessions:this.sessions,evictIdleSessions:()=>this.evictIdleSessions(),nativeFusion:this.nativeFusion,managerRuntime:this.managerRuntime,chatQueue:this.chatQueue,activityPublisher:{publish:(e,t)=>this.publishSessionActivity(e,t)},upgradePolicyController:this.upgradePolicyController,revokeManagedRoomContextToken:this.managedRoomContextRevoker,managedRoomExecutor:this.managedRoomExecutor,runJournal:this.runJournal,recoveryBarrier:this.recoveryBarrier,prepareManagedRecovery:this.prepareManagedRecovery}}async resumePendingAcpAuthentication(e){const t=[...this.sessions.values()].find(s=>s.agentType===e&&s.adapter.hasPendingAuthenticationRetry?.());return t?.adapter.resumeAfterExternalAuthentication?(await t.adapter.resumeAfterExternalAuthentication(),!0):!1}getUpgradeIdleState(){const e=[];return[...this.sessions.values()].some(t=>t.currentRunId!==null)&&e.push("active-agent-turn"),this.pendingTransfers.size>0&&e.push("file-transfer"),this.activeRequests>0&&e.push("active-daemon-request"),{idle:e.length===0,reasons:e}}prepareForUpgrade(e){this.recoveryBarrier.freezeDispatch();const t=this.runJournal.markPlannedUpgrade(e);return this.runJournal.sync(),{activeRunCount:t}}cancelUpgradePreparation(){this.recoveryBarrier.unfreezeDispatch()}async recoverInterruptedRuns(){this.recoveryPass??=this.recoveryCoordinator.recoverAll(),await this.recoveryPass}getPendingRecoveryCount(){return this.runJournal.loadPendingReconciliation().records.length}revokeProjectFsHandles(){this.projectFsHandleStore.revokeAll()}async commitRecoveryTerminal(e,t){const s=this.sessions.get(e.sessionId);s&&(s.currentRunId=null,s.currentRunPhase=null,s.journalRunId=null,s.heartbeatTimer&&(clearInterval(s.heartbeatTimer),s.heartbeatTimer=null)),this.runTextAcc.delete(`${e.sessionId}:${e.providerRunId??e.runId}`),this.publishSessionActivity(e.sessionId,null);const r=t.result==="interrupted_by_upgrade"?`\u4EFB\u52A1\u56E0\u795E\u5FF5\u5347\u7EA7\u800C\u4E2D\u65AD\uFF08${t.reason}\uFF09\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\uFF0C\u53EF\u7EE7\u7EED\u53D1\u9001\u65B0\u6D88\u606F\u3002
|
|
1
|
+
import{SESSION_SYNC_PROTOCOL_VERSION as g,SESSION_SYNC_DATA_EPOCH as f}from"@shennian/wire";import h from"node:crypto";import{getRegisteredAgents as k,unregisterAgent as I}from"../agents/adapter.js";import{resetCommandSpecCache as A}from"../agents/command-spec.js";import{loadConfig as T}from"../config/index.js";import{handleUpgradeStart as P,handleUpgradeStatus as C}from"../commands/upgrade.js";import{handleAgentsRefresh as M,handleModelsRefresh as D,refreshMachineAgents as x}from"./handlers/agents.js";import{AcpDiscoveryWatcher as E}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as F}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as _,handleAgentConfigGet as O,handleAgentConfigTest as Q,handleAgentConfigUpsert as j}from"./handlers/agent-config.js";import{handleChatAbort as B,handleChatSend as U}from"./handlers/chat.js";import{recoverJournaledRun as z}from"./handlers/chat-recovery.js";import{handleSessionRefresh as W}from"./handlers/session-refresh.js";import{handleSessionToolDetail as $}from"./handlers/tool-detail.js";import{handleSessionTitleSet as H}from"./handlers/title.js";import{handleSessionMessageStatus as J}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as N}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as V}from"./handlers/voice-window.js";import{handleRemoteAccessPause as L}from"./handlers/remote-access.js";import{cleanupPendingTransfers as G,handleFsLs as Y,handleFsRead as K,handleFsRename as X,handleFsWrite as Z,handleFsTransferAbort as q,handleFsTransferChunk as ee,handleFsTransferFinish as se,handleFsTransferStart as te,handleFsExportMarkdownPdf as ae,handleFsExportMarkdownPdfSetup as re,handleFsArchiveZip as ne}from"./handlers/fs.js";import{handleRegionProbe as ie,handleRegionSwitch as oe,handleUpgradeSetPolicy as ce}from"./handlers/control.js";import{ManagerRuntimeService as le,setManagerRuntimeService as v}from"../manager/runtime.js";import{ChatQueueManager as de}from"./queue.js";import{createAuthorizedFsRoot as he,createAuthorizedFsRootAsync as ue,resolveAuthorizedPath as pe,resolveAuthorizedPathAsync as me,resolveSessionWorkDir as ge}from"../fs/boundary.js";import"../agents/claude.js";import"../agents/codex.js";import"../agents/workbuddy.js";import"../agents/gemini.js";import"../agents/cursor.js";import"../agents/opencode.js";import"../agents/pi-coding-agent.js";import"../agents/manager.js";import{registerCustomAgent as fe}from"../agents/custom.js";import{handleManagedRoomBind as ve,handleManagedRoomRestart as ye,discardPreBindingSession as Re}from"./handlers/room-managed.js";import{getDaemonInstallationId as u,listSessionRecords as p,purgeCanonicalSession as be,purgeSessionRecord as Se,recordSession as we,upsertMessage as ke}from"./store.js";import{requestSessionIndexPublish as Ie}from"./index-publisher.js";import{reportUpgradeAggregateMetric as Ae}from"../log-reporter.js";import{PersonalHistorySubscriptions as Te}from"./history-subscriptions.js";import{sweepAttachmentTransfers as Pe}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Ce}from"../native-fusion/native-source-deletions.js";import{purgeToolDetails as Me}from"./tool-detail-store.js";import{readDeletionSyncRevision as De,writeDeletionSyncRevision as y}from"./deletion-sync-state.js";import{assertDeletionSyncRunnable as xe,clearDeletionSyncFailure as Ee,DeletionSyncRetryWaitError as Fe,DeletionSyncTerminalError as _e,recordDeletionSyncFailure as m}from"./deletion-sync-state.js";import{NativeSessionCleanupOutbox as Oe}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as c}from"../personal-sync/epoch.js";import{ActiveRunJournal as Qe}from"./run-recovery/journal.js";import{RunRecoveryBarrier as je}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Be}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as Ue}from"./project-fs-store.js";import{handleProjectFsRequest as ze}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as We,handleAcpAgentRequest as $e}from"./handlers/agent-control.js";import{validateDeletionSyncResponse as He}from"./deletion-sync-validation.js";import{dispatchManagedChat as Je,dispatchQueuedChat as Ne,interruptQueuedChat as Ve}from"./queued-chat-dispatch.js";const Le=50;import{resolveSessionWorkDir as Xs}from"../fs/boundary.js";class Gs{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;scheduleHandler;getScheduleQueue(){return this.chatQueue}sessions=new Map;processedReqIds=new Set;runTextAcc=new Map;pendingTransfers=new Map;managerRuntime;chatQueue;historySubscriptions;nativeCleanupOutbox;activityProbeTimer=null;attachmentCleanupTimer=null;activeRequests=0;acpDiscoveryWatcher;runJournal;recoveryBarrier=new je;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new Ue;constructor(e,t=null,s,n=null,r=null,d=null,o=null,R=null,b=null,S=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=d,this.managedRoomContextRevoker=o,this.managedRoomExecutor=R,this.trustedProjectFsRequestResolver=S,this.runJournal=b??new Qe(u());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Be({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>z(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=p().find(w=>w.sessionId===a.sessionId),l=`terminal:${h.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===l},onOutcome:a=>Ae({kind:"recovery",adapterType:a.adapterType,result:a.result,stage:a.result==="continued"?"continue":a.result==="reattached"?"reattach":a.result==="resumed"?"resume":a.result==="terminal_reconciled"?"inspect":"terminal",durationMs:a.durationMs,retries:Math.max(0,a.attempts-1),...a.reason?{errorCode:a.reason}:{}})}),this.managerRuntime=new le({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new de({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Je(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>Ne(this.getRuntime(),a,i),interruptQueuedSession:a=>Ve(this.getRuntime(),a)}),this.historySubscriptions=new Te(this.client),this.nativeCleanupOutbox=new Oe({logger:console.info}),this.acpDiscoveryWatcher=new E(async()=>{A(),await x(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeCleanupOutbox.start(),v(this.managerRuntime),this.managerRuntime.start(),this.reloadCustomAgents();try{this.acpDiscoveryWatcher.start()}catch(a){console.warn(`[acp.discovery] watcher unavailable: ${a instanceof Error?a.message:String(a)}`)}this.activityProbeTimer=setInterval(()=>{this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.attachmentCleanupTimer=setInterval(()=>{const a=new Set([...p().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{Pe(this.resolvePath(i))}catch(l){console.error("[attachment.cleanup] failed",l instanceof Error?l.message:String(l))}},6e4),this.attachmentCleanupTimer.unref?.()}executeManagedManagerAction(e){return this.managerRuntime.executeScopedWorkerAction(e.managerSessionId,e.action,e.params)}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),resolvePath:e=>this.resolvePath(e),resolveAuthorizedPath:(e,t)=>this.resolveAuthorizedPath(e,t),resolveAuthorizedPathAsync:(e,t)=>this.resolveAuthorizedPathAsync(e,t),runTextAcc:this.runTextAcc,sessions:this.sessions,evictIdleSessions:()=>this.evictIdleSessions(),nativeFusion:this.nativeFusion,managerRuntime:this.managerRuntime,chatQueue:this.chatQueue,activityPublisher:{publish:(e,t)=>this.publishSessionActivity(e,t)},upgradePolicyController:this.upgradePolicyController,revokeManagedRoomContextToken:this.managedRoomContextRevoker,managedRoomExecutor:this.managedRoomExecutor,runJournal:this.runJournal,recoveryBarrier:this.recoveryBarrier,prepareManagedRecovery:this.prepareManagedRecovery}}async resumePendingAcpAuthentication(e){const t=[...this.sessions.values()].find(s=>s.agentType===e&&s.adapter.hasPendingAuthenticationRetry?.());return t?.adapter.resumeAfterExternalAuthentication?(await t.adapter.resumeAfterExternalAuthentication(),!0):!1}getUpgradeIdleState(){const e=[];return[...this.sessions.values()].some(t=>t.currentRunId!==null)&&e.push("active-agent-turn"),this.pendingTransfers.size>0&&e.push("file-transfer"),this.activeRequests>0&&e.push("active-daemon-request"),{idle:e.length===0,reasons:e}}prepareForUpgrade(e){this.recoveryBarrier.freezeDispatch();const t=this.runJournal.markPlannedUpgrade(e);return this.runJournal.sync(),{activeRunCount:t}}cancelUpgradePreparation(){this.recoveryBarrier.unfreezeDispatch()}async recoverInterruptedRuns(){this.recoveryPass??=this.recoveryCoordinator.recoverAll(),await this.recoveryPass}getPendingRecoveryCount(){return this.runJournal.loadPendingReconciliation().records.length}revokeProjectFsHandles(){this.projectFsHandleStore.revokeAll()}async commitRecoveryTerminal(e,t){const s=this.sessions.get(e.sessionId);s&&(s.currentRunId=null,s.currentRunPhase=null,s.journalRunId=null,s.heartbeatTimer&&(clearInterval(s.heartbeatTimer),s.heartbeatTimer=null)),this.runTextAcc.delete(`${e.sessionId}:${e.providerRunId??e.runId}`),this.publishSessionActivity(e.sessionId,null);const n=t.result==="interrupted_by_upgrade"?`\u4EFB\u52A1\u56E0\u795E\u5FF5\u5347\u7EA7\u800C\u4E2D\u65AD\uFF08${t.reason}\uFF09\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\uFF0C\u53EF\u7EE7\u7EED\u53D1\u9001\u65B0\u6D88\u606F\u3002
|
|
2
2
|
Task interrupted by the Shennian upgrade (${t.reason}). The session is preserved and ready for a new message.`:`\u795E\u5FF5\u5347\u7EA7\u540E\u672A\u80FD\u6062\u590D\u4EFB\u52A1\uFF08${t.reason}\uFF09\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\uFF0C\u53EF\u91CD\u8BD5\u6216\u7EE7\u7EED\u53D1\u9001\u65B0\u6D88\u606F\u3002
|
|
3
|
-
The task could not be recovered after the Shennian upgrade (${t.reason}). The session is preserved; retry or send a new message.`;we(e.sessionId,{id:`upgrade-recovery-terminal-${e.runId}`,sessionId:e.sessionId,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:"error",content:r,error:!0,recoveryState:t.result,recoveryReason:t.reason})}),ke({sessionId:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:e.modelId,status:"failed",attentionId:`upgrade-recovery:${e.runId}`,lastActivityAt:new Date().toISOString()}),this.managerRuntime.noteAgentEvent(e.sessionId,{state:"error",runId:e.providerRunId??e.runId,seq:e.lastObservedEventSeq+1,message:r}),Ie(this.client);const n=e.lastObservedEventSeq+1;this.client.sendAgentEvent({type:"event",event:"agent",payload:t.result==="interrupted_by_upgrade"?{state:"interrupted_by_upgrade",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:n,reason:t.reason}:{state:"recovery_failed",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:n,reason:t.reason,...t.message?{message:t.message}:{}},seq:n,id:`agent-recovery-terminal-${e.runId}`}),this.chatQueue.noteTerminal(e.sessionId)}setManagedRoomTurnPreparer(e){this.chatQueue.setManagedRoomTurnPreparer(e)}setManagedAgentDirectTurnPreparer(e){this.chatQueue.setManagedAgentDirectTurnPreparer(e)}setManagedRecoveryPreparer(e){this.prepareManagedRecovery=e}async enqueueManagedRoomBatch(e){const t=e.map(s=>{const r=p().find(n=>n.sessionId===s.params.sessionId);return{context:s.context,params:{...s.params,modelId:r?.modelId??s.params.modelId,sessionMode:r?.sessionMode??s.params.sessionMode,managerConfig:r?.managerConfig??s.params.managerConfig,managerDefaultWorkerAgentType:r?.managerDefaultWorkerAgentType??s.params.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:r?.managerDefaultWorkerModelId??s.params.managerDefaultWorkerModelId}}});await this.chatQueue.enqueueManagedRoomBatch(t)}async retireManagedRoomSession(e){this.chatQueue.purgeSession(e),await Re(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){xe();try{await this.synchronizeSessionDeletionsOnce(),Ee()}catch(e){if(e instanceof Fe||e instanceof Oe)throw e;const t=e instanceof Error?e.message:String(e),s=/offline|not connected|disconnect|timed out|timeout|temporar|unavailable|ECONN|ENOTFOUND|EIO|EBUSY/i.test(t)?"transport_unavailable":/invalid (?:deletion sync|session deletion)|deletion revision gap/i.test(t)?"invalid_deletion_sync_response":"deletion_sync_failed";throw console.warn("[session.deletions] retrying failed synchronization",{code:s}),m({code:s,retryable:!0}),e}}async synchronizeSessionDeletionsOnce(){const e=u(),t=De(),s=await this.client.sendReq({type:"req",id:`session-deletions-sync-${h.randomUUID()}`,method:"session.deletions.sync",params:{protocolVersion:g,dataEpoch:f,daemonInstallationId:e,afterRevision:t}});if(!s.ok){const o=s.rejection;throw o?(m({code:o.code,retryable:o.retryable&&o.requiredAction==="retry"}),new Error(o.code)):(m({code:"unstructured_rejection",retryable:!0}),new Error(s.error??"unstructured_rejection"))}const r=s.payload;c(r),He(r,t);let n=r.baselineRevision;n>t&&y(n);for(const o of r.deletions)o.deletionRevision<=n||(await this.applySessionDeletion(o),n=o.deletionRevision,y(n));if(n!==r.latestRevision)throw new Error(`deletion revision gap: applied ${n}, latest ${r.latestRevision}`);if(n===0)return;const d=await this.client.sendReq({type:"req",id:`session-deletions-ack-${h.randomUUID()}`,method:"session.deletions.ack",params:{protocolVersion:g,dataEpoch:f,daemonInstallationId:e,deletionRevision:n}});if(!d.ok)throw new Error(d.error??"session deletion acknowledgement failed")}async applySessionDeletion(e){const t=new Ce({daemonInstallationId:u()});t.recordSession(e);for(const r of e.sources){const n=t.find(r.agentType,r.sourceSessionKey);n&&n.sessionId!==e.sessionId||t.record({...e,...r})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const s=this.sessions.get(e.sessionId);if(s){this.revokeManagedRoomToken(s);try{await s.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),Me(e.sessionId),be(e.sessionId),Se(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e),this.nativeCleanupOutbox.kick()}publishSessionActivity(e,t){this.client.sendEvent({type:"event",event:"session.activity",payload:{sessionId:e,activity:t}})}async handleExternalTerminal(e){const t=this.sessions.get(e);t&&(t.journalRunId&&(this.recoveryCoordinator.completeFromProvider(e,t.journalRunId),t.journalRunId=null),this.sessions.delete(e),this.revokeManagedRoomToken(t),t.heartbeatTimer&&clearInterval(t.heartbeatTimer),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})),this.chatQueue.noteTerminal(e)}async publishManagedActivitySnapshots(){for(const[e,t]of this.sessions.entries()){if(t.heartbeatTimer||!t.currentRunId||!t.adapter.getStatus)continue;const s=await t.adapter.getStatus().catch(()=>null);if(!s?.active||!s.runPhase)continue;const r=new Date().toISOString();this.publishSessionActivity(e,{sessionId:e,runId:s.runId||t.currentRunId,runPhase:s.runPhase,startedAt:new Date(t.lastActiveAt).toISOString(),updatedAt:r,canStop:s.canStop??!0});const n=t.heartbeatSeq++;this.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:s.runId||t.currentRunId,seq:n,runPhase:s.runPhase,canStop:s.canStop??!0},seq:n,id:`agent-status-${s.runId||t.currentRunId}-${Date.now()}`})}}reloadCustomAgents(){for(const t of w())t.startsWith("custom:")&&I(t);const e=T();for(const[t,s]of Object.entries(e.customAgents??{}))fe(t,s)}async handleReq(e,t={}){const s=this.getRuntime();let r;this.activeRequests++;try{switch(e.method){case"chat.send":c(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?r={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await U(s,e);break;case"chat.enqueue":c(e.params),r={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.queue.get":c(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":c(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":c(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":c(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":c(e.params),await B(s,e);break;case"session.refresh":c(e.params),await W(s,e);break;case"session.history.open":this.historySubscriptions.handleOpen(e);break;case"session.history.sync":this.historySubscriptions.handleSync(e);break;case"session.history.page":this.historySubscriptions.handlePage(e);break;case"session.history.close":this.historySubscriptions.handleClose(e);break;case"session.body.replica.subscribe":this.historySubscriptions.handleReplicaSubscribe(e);break;case"session.body.replica.unsubscribe":this.historySubscriptions.handleReplicaUnsubscribe(e);break;case"session.history":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"upgrade_required"});break;case"session.message.status":J(s,e);break;case"session.tool.detail":await $(s,e);break;case"voice.session.body.window":V(s,e);break;case"session.title.set":await H(s,e);break;case"room.agent.bind-managed":await ve(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await ye(s,this.managedRoomBinder,e);break;case"fs.ls":await Y(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await ze(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await K(s,e);break;case"fs.write":await Z(s,e);break;case"fs.export.markdown-pdf":await ae(s,e);break;case"fs.export.markdown-pdf.setup":await ne(s,e);break;case"fs.archive.zip":await re(s,e);break;case"fs.rename":await X(s,e);break;case"fs.transfer.start":await te(s,e);break;case"fs.transfer.chunk":await ee(s,e);break;case"fs.transfer.finish":await se(s,e);break;case"fs.transfer.abort":await q(s,e);break;case"region.probe":await ie(s,e);break;case"region.switch":await oe(s,e);break;case"upgrade.start":await P(this.client,e.id,e.params.version,{currentVersion:this.cliVersion,confirmedMajor:e.params.confirmedMajor===!0,prepareForUpgrade:n=>this.prepareForUpgrade(n),cancelUpgradePreparation:()=>this.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()}});break;case"upgrade.status":await C(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await ce(s,e);break;case"machine.remote-access.pause":await L(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await M(s,e);break;case"agent.permission.respond":await We(s,e);break;case"agent.auth.start":case"agent.auth.logout":case"agent.session-options.get":case"agent.external-sessions.list":case"agent.external-sessions.import":case"agent.external-sessions.close":case"agent.external-sessions.delete":await $e(s,e);break;case"models.refresh":await D(s,e);break;case"agent.config.get":await _(s,e);break;case"agent.config.upsert":await Q(s,e);break;case"agent.config.clear":await O(s,e);break;case"agent.config.test":await j(s,e);break;case"agent.workspace.validate":await N(s,e);break;case"agent.capabilities.list":await F(s,e);break;case"skill.list":case"skill.install":case"skill.doctor":case"skill.setup":case"skill.use":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;case"session.wechat-rpa.channel.get":case"session.wechat-rpa.channel.upsert":case"session.wechat-rpa.channel.sync":case"manager.wechat-rpa.channel.get":case"manager.wechat-rpa.channel.upsert":case"manager.wechat-rpa.channel.sync":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;default:this.client.sendRes({type:"res",id:e.id,ok:!1,error:`Unknown method: ${e.method}`})}}catch(n){if(t.propagateErrors)throw n;this.client.sendRes({type:"res",id:e.id,ok:!1,error:n instanceof Error?n.message:String(n)})}finally{this.activeRequests--}return r}evictIdleSessions(){if(this.sessions.size<Le)return;let e=null;for(const[t,s]of this.sessions)(!e||s.lastActiveAt<e.session.lastActiveAt)&&(e={key:t,session:s});e&&(this.revokeManagedRoomToken(e.session),e.session.heartbeatTimer&&(clearInterval(e.session.heartbeatTimer),e.session.heartbeatTimer=null),e.session.adapter.removeAllListeners(),e.session.adapter.stop().catch(()=>{}),this.sessions.delete(e.key))}resolvePath(e){return ge(e)}resolveAuthorizedPath(e,t){return pe(e,he(t))}async resolveAuthorizedPathAsync(e,t){return me(e,await ue(t))}async cleanup(){this.chatQueue.stop(),this.projectFsHandleStore.revokeAll(),this.acpDiscoveryWatcher.stop(),this.nativeFusion?.setExternalTerminalHandler?.(null),this.nativeCleanupOutbox.stop(),this.historySubscriptions.closeAll(),this.activityProbeTimer&&(clearInterval(this.activityProbeTimer),this.activityProbeTimer=null),this.attachmentCleanupTimer&&(clearInterval(this.attachmentCleanupTimer),this.attachmentCleanupTimer=null);for(const[,e]of this.sessions)this.revokeManagedRoomToken(e),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.adapter.removeAllListeners(),await e.adapter.stop().catch(()=>{});this.sessions.clear(),this.runTextAcc.clear(),G(this.getRuntime()),await this.managerRuntime.stop(),v(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Gs as SessionManager,Xs as resolveSessionWorkDir};
|
|
3
|
+
The task could not be recovered after the Shennian upgrade (${t.reason}). The session is preserved; retry or send a new message.`;ke(e.sessionId,{id:`upgrade-recovery-terminal-${e.runId}`,sessionId:e.sessionId,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:"error",content:n,error:!0,recoveryState:t.result,recoveryReason:t.reason})}),we({sessionId:e.sessionId,agentType:e.agentType,sessionMode:e.sessionMode,workDir:e.workDir,agentSessionId:e.agentSessionId,modelId:e.modelId,status:"failed",attentionId:`upgrade-recovery:${e.runId}`,lastActivityAt:new Date().toISOString()}),this.managerRuntime.noteAgentEvent(e.sessionId,{state:"error",runId:e.providerRunId??e.runId,seq:e.lastObservedEventSeq+1,message:n}),Ie(this.client);const r=e.lastObservedEventSeq+1;this.client.sendAgentEvent({type:"event",event:"agent",payload:t.result==="interrupted_by_upgrade"?{state:"interrupted_by_upgrade",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason}:{state:"recovery_failed",sessionId:e.sessionId,runId:e.providerRunId??e.runId,seq:r,reason:t.reason,...t.message?{message:t.message}:{}},seq:r,id:`agent-recovery-terminal-${e.runId}`}),this.chatQueue.noteTerminal(e.sessionId)}setManagedRoomTurnPreparer(e){this.chatQueue.setManagedRoomTurnPreparer(e)}setManagedAgentDirectTurnPreparer(e){this.chatQueue.setManagedAgentDirectTurnPreparer(e)}setManagedRecoveryPreparer(e){this.prepareManagedRecovery=e}async enqueueManagedRoomBatch(e){const t=e.map(s=>{const n=p().find(r=>r.sessionId===s.params.sessionId);return{context:s.context,params:{...s.params,modelId:n?.modelId??s.params.modelId,sessionMode:n?.sessionMode??s.params.sessionMode,managerConfig:n?.managerConfig??s.params.managerConfig,managerDefaultWorkerAgentType:n?.managerDefaultWorkerAgentType??s.params.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:n?.managerDefaultWorkerModelId??s.params.managerDefaultWorkerModelId}}});await this.chatQueue.enqueueManagedRoomBatch(t)}async retireManagedRoomSession(e){this.chatQueue.purgeSession(e),await Re(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){xe();try{await this.synchronizeSessionDeletionsOnce(),Ee()}catch(e){if(e instanceof Fe||e instanceof _e)throw e;const t=e instanceof Error?e.message:String(e),s=/offline|not connected|disconnect|timed out|timeout|temporar|unavailable|ECONN|ENOTFOUND|EIO|EBUSY/i.test(t)?"transport_unavailable":/invalid (?:deletion sync|session deletion)|deletion revision gap/i.test(t)?"invalid_deletion_sync_response":"deletion_sync_failed";throw console.warn("[session.deletions] retrying failed synchronization",{code:s}),m({code:s,retryable:!0}),e}}async synchronizeSessionDeletionsOnce(){const e=u(),t=De(),s=await this.client.sendReq({type:"req",id:`session-deletions-sync-${h.randomUUID()}`,method:"session.deletions.sync",params:{protocolVersion:g,dataEpoch:f,daemonInstallationId:e,afterRevision:t}});if(!s.ok){const o=s.rejection;throw o?(m({code:o.code,retryable:o.retryable&&o.requiredAction==="retry"}),new Error(o.code)):(m({code:"unstructured_rejection",retryable:!0}),new Error(s.error??"unstructured_rejection"))}const n=s.payload;c(n),He(n,t);let r=n.baselineRevision;r>t&&y(r);for(const o of n.deletions)o.deletionRevision<=r||(await this.applySessionDeletion(o),r=o.deletionRevision,y(r));if(r!==n.latestRevision)throw new Error(`deletion revision gap: applied ${r}, latest ${n.latestRevision}`);if(r===0)return;const d=await this.client.sendReq({type:"req",id:`session-deletions-ack-${h.randomUUID()}`,method:"session.deletions.ack",params:{protocolVersion:g,dataEpoch:f,daemonInstallationId:e,deletionRevision:r}});if(!d.ok)throw new Error(d.error??"session deletion acknowledgement failed")}async applySessionDeletion(e){const t=new Ce({daemonInstallationId:u()});t.recordSession(e);for(const n of e.sources){const r=t.find(n.agentType,n.sourceSessionKey);r&&r.sessionId!==e.sessionId||t.record({...e,...n})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const s=this.sessions.get(e.sessionId);if(s){this.revokeManagedRoomToken(s);try{await s.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),Me(e.sessionId),be(e.sessionId),Se(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e),this.nativeCleanupOutbox.kick()}publishSessionActivity(e,t){this.client.sendEvent({type:"event",event:"session.activity",payload:{sessionId:e,activity:t}})}async handleExternalTerminal(e){const t=this.sessions.get(e);t&&(t.journalRunId&&(this.recoveryCoordinator.completeFromProvider(e,t.journalRunId),t.journalRunId=null),this.sessions.delete(e),this.revokeManagedRoomToken(t),t.heartbeatTimer&&clearInterval(t.heartbeatTimer),t.adapter.removeAllListeners(),await t.adapter.stop().catch(()=>{})),this.chatQueue.noteTerminal(e)}async publishManagedActivitySnapshots(){for(const[e,t]of this.sessions.entries()){if(t.heartbeatTimer||!t.currentRunId||!t.adapter.getStatus)continue;const s=await t.adapter.getStatus().catch(()=>null);if(!s?.active||!s.runPhase)continue;const n=new Date().toISOString();this.publishSessionActivity(e,{sessionId:e,runId:s.runId||t.currentRunId,runPhase:s.runPhase,startedAt:new Date(t.lastActiveAt).toISOString(),updatedAt:n,canStop:s.canStop??!0});const r=t.heartbeatSeq++;this.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:e,runId:s.runId||t.currentRunId,seq:r,runPhase:s.runPhase,canStop:s.canStop??!0},seq:r,id:`agent-status-${s.runId||t.currentRunId}-${Date.now()}`})}}reloadCustomAgents(){for(const t of k())t.startsWith("custom:")&&I(t);const e=T();for(const[t,s]of Object.entries(e.customAgents??{}))fe(t,s)}async handleReq(e,t={}){const s=this.getRuntime();let n;this.activeRequests++;try{switch(e.method){case"schedule.deliver":if(!this.scheduleHandler)throw new Error("schedules_unavailable");await this.scheduleHandler(e);break;case"chat.send":if(e.params.scheduledDelivery)throw new Error("schedule_source_untrusted");c(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?n={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await U(s,e);break;case"chat.enqueue":c(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.queue.get":c(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":c(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":c(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":c(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":c(e.params),await B(s,e);break;case"session.refresh":c(e.params),await W(s,e);break;case"session.history.open":this.historySubscriptions.handleOpen(e);break;case"session.history.sync":this.historySubscriptions.handleSync(e);break;case"session.history.page":this.historySubscriptions.handlePage(e);break;case"session.history.close":this.historySubscriptions.handleClose(e);break;case"session.body.replica.subscribe":this.historySubscriptions.handleReplicaSubscribe(e);break;case"session.body.replica.unsubscribe":this.historySubscriptions.handleReplicaUnsubscribe(e);break;case"session.history":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"upgrade_required"});break;case"session.message.status":J(s,e);break;case"session.tool.detail":await $(s,e);break;case"voice.session.body.window":V(s,e);break;case"session.title.set":await H(s,e);break;case"room.agent.bind-managed":await ve(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await ye(s,this.managedRoomBinder,e);break;case"fs.ls":await Y(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await ze(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await K(s,e);break;case"fs.write":await Z(s,e);break;case"fs.export.markdown-pdf":await ae(s,e);break;case"fs.export.markdown-pdf.setup":await re(s,e);break;case"fs.archive.zip":await ne(s,e);break;case"fs.rename":await X(s,e);break;case"fs.transfer.start":await te(s,e);break;case"fs.transfer.chunk":await ee(s,e);break;case"fs.transfer.finish":await se(s,e);break;case"fs.transfer.abort":await q(s,e);break;case"region.probe":await ie(s,e);break;case"region.switch":await oe(s,e);break;case"upgrade.start":await P(this.client,e.id,e.params.version,{currentVersion:this.cliVersion,confirmedMajor:e.params.confirmedMajor===!0,prepareForUpgrade:r=>this.prepareForUpgrade(r),cancelUpgradePreparation:()=>this.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()}});break;case"upgrade.status":await C(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await ce(s,e);break;case"machine.remote-access.pause":await L(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await M(s,e);break;case"agent.permission.respond":await We(s,e);break;case"agent.auth.start":case"agent.auth.logout":case"agent.session-options.get":case"agent.external-sessions.list":case"agent.external-sessions.import":case"agent.external-sessions.close":case"agent.external-sessions.delete":await $e(s,e);break;case"models.refresh":await D(s,e);break;case"agent.config.get":await O(s,e);break;case"agent.config.upsert":await j(s,e);break;case"agent.config.clear":await _(s,e);break;case"agent.config.test":await Q(s,e);break;case"agent.workspace.validate":await N(s,e);break;case"agent.capabilities.list":await F(s,e);break;case"skill.list":case"skill.install":case"skill.doctor":case"skill.setup":case"skill.use":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;case"session.wechat-rpa.channel.get":case"session.wechat-rpa.channel.upsert":case"session.wechat-rpa.channel.sync":case"manager.wechat-rpa.channel.get":case"manager.wechat-rpa.channel.upsert":case"manager.wechat-rpa.channel.sync":this.client.sendRes({type:"res",id:e.id,ok:!1,error:"feature_retired"});break;default:this.client.sendRes({type:"res",id:e.id,ok:!1,error:`Unknown method: ${e.method}`})}}catch(r){if(t.propagateErrors)throw r;this.client.sendRes({type:"res",id:e.id,ok:!1,error:r instanceof Error?r.message:String(r)})}finally{this.activeRequests--}return n}evictIdleSessions(){if(this.sessions.size<Le)return;let e=null;for(const[t,s]of this.sessions)(!e||s.lastActiveAt<e.session.lastActiveAt)&&(e={key:t,session:s});e&&(this.revokeManagedRoomToken(e.session),e.session.heartbeatTimer&&(clearInterval(e.session.heartbeatTimer),e.session.heartbeatTimer=null),e.session.adapter.removeAllListeners(),e.session.adapter.stop().catch(()=>{}),this.sessions.delete(e.key))}resolvePath(e){return ge(e)}resolveAuthorizedPath(e,t){return pe(e,he(t))}async resolveAuthorizedPathAsync(e,t){return me(e,await ue(t))}async cleanup(){this.chatQueue.stop(),this.projectFsHandleStore.revokeAll(),this.acpDiscoveryWatcher.stop(),this.nativeFusion?.setExternalTerminalHandler?.(null),this.nativeCleanupOutbox.stop(),this.historySubscriptions.closeAll(),this.activityProbeTimer&&(clearInterval(this.activityProbeTimer),this.activityProbeTimer=null),this.attachmentCleanupTimer&&(clearInterval(this.attachmentCleanupTimer),this.attachmentCleanupTimer=null);for(const[,e]of this.sessions)this.revokeManagedRoomToken(e),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.adapter.removeAllListeners(),await e.adapter.stop().catch(()=>{});this.sessions.clear(),this.runTextAcc.clear(),G(this.getRuntime()),await this.managerRuntime.stop(),v(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Gs as SessionManager,Xs as resolveSessionWorkDir};
|
|
@@ -1,4 +1,4 @@
|
|
|
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]
|
|
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"||t.trigger?.kind==="scheduled")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
2
|
${n.map(e=>y(e.text)).filter(Boolean).join(`
|
|
3
3
|
|
|
4
4
|
`)}`:`[\u8FDE\u7EED\u7528\u6237\u6D88\u606F]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ChatEnqueueParams, type QueuedChatMessage } from '@shennian/wire';
|
|
2
|
+
import type { ManagedRoomTriggerContext, TurnTrigger } from './turn-trigger.js';
|
|
3
|
+
export type LocalQueuedChatMessage = QueuedChatMessage & {
|
|
4
|
+
origin?: 'app' | 'external' | 'room';
|
|
5
|
+
trigger?: TurnTrigger;
|
|
6
|
+
/** Legacy persisted fields remain readable until all v1 queue files drain. */
|
|
7
|
+
managedRoom?: ManagedRoomTriggerContext;
|
|
8
|
+
managedAgentDirect?: true;
|
|
9
|
+
};
|
|
10
|
+
export type InternalEnqueueParams = ChatEnqueueParams & {
|
|
11
|
+
managedWorkerParentSessionId?: string;
|
|
12
|
+
scheduledTask?: {
|
|
13
|
+
id: string;
|
|
14
|
+
bindingId?: string;
|
|
15
|
+
roomId?: string;
|
|
16
|
+
};
|
|
17
|
+
managerEventId?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare class TerminalQueuedChatDispatchError extends Error {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare function nowIso(): string;
|
|
23
|
+
export declare function queueMessageFromParams(params: InternalEnqueueParams): LocalQueuedChatMessage;
|
|
24
|
+
export declare function queueEnvelope(message: LocalQueuedChatMessage): {
|
|
25
|
+
id: string;
|
|
26
|
+
sessionId: string;
|
|
27
|
+
role: "agent" | "user";
|
|
28
|
+
ts: number;
|
|
29
|
+
payload: string;
|
|
30
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUID as o}from"node:crypto";import{buildUserMessagePayload as r}from"@shennian/wire";import{parsePersonalAttachmentReferences as d}from"./attachment-reference.js";import{normalizeQueuedModelId as i}from"./queue-helpers.js";import{getPersonalSyncIdentity as l}from"../personal-sync/epoch.js";import{getDaemonInstallationId as s}from"../personal-sync/identity.js";class h extends Error{constructor(n){super(n),this.name="TerminalQueuedChatDispatchError"}}function u(){return new Date().toISOString()}function m(e){const n=u(),t=e.scheduledTask?{kind:"scheduled",taskId:e.scheduledTask.id,bindingId:e.scheduledTask.bindingId,roomId:e.scheduledTask.roomId}:e.managedWorkerParentSessionId?{kind:"manager_worker",parentSessionId:e.managedWorkerParentSessionId}:e.managerEventId?{kind:"manager_event",eventId:e.managerEventId}:e.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"};return{...l(s()),id:e.queueMessageId||e.clientMessageId||`queue-${o()}`,sessionId:e.sessionId,text:e.text,agentType:e.agentType,sessionMode:e.sessionMode,managerConfig:e.managerConfig,workDir:e.workDir,agentSessionId:e.agentSessionId??null,modelId:i(e.modelId)??null,systemPrompt:e.systemPrompt??null,managerDefaultWorkerAgentType:e.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:e.managerDefaultWorkerModelId??null,reasoningEffort:e.reasoningEffort??null,clientMessageId:e.clientMessageId??null,attachments:d(e.attachments),externalChannel:e.externalChannel??null,replyTarget:e.replyTarget??null,origin:e.origin,createdAt:n,updatedAt:n,trigger:t}}function D(e){return{id:e.clientMessageId??e.id,sessionId:e.sessionId,role:e.trigger?.kind==="manager_event"||e.trigger?.kind==="scheduled"?"agent":"user",ts:Date.parse(e.createdAt),payload:r(e.text,e.attachments)}}export{h as TerminalQueuedChatDispatchError,u as nowIso,D as queueEnvelope,m as queueMessageFromParams};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentType, ChatEnqueueParams, SessionMode, ManagerConfig } from '@shennian/wire';
|
|
2
|
+
import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
3
|
+
import type { ManagedRoomPromptSnapshot } from '../room/managed-prompt-composer.js';
|
|
4
|
+
export type PreparedManagedTurnContext = {
|
|
5
|
+
agentType: AgentType;
|
|
6
|
+
workDir: string;
|
|
7
|
+
agentSessionId: string;
|
|
8
|
+
systemPrompt: string;
|
|
9
|
+
sessionMode: SessionMode;
|
|
10
|
+
managerConfig: ManagerConfig | null;
|
|
11
|
+
managerDefaultWorkerAgentType: AgentType | null;
|
|
12
|
+
managerDefaultWorkerModelId: string | null;
|
|
13
|
+
roomContextRegistryKey: string;
|
|
14
|
+
managedRoomContextToken: string;
|
|
15
|
+
managedAgentPolicy: CompiledManagedAgentPolicy;
|
|
16
|
+
managedRoomPromptSnapshot: ManagedRoomPromptSnapshot;
|
|
17
|
+
};
|
|
18
|
+
/** @deprecated Compatibility name for callers migrated incrementally. */
|
|
19
|
+
export type PreparedManagedRoomTurn = PreparedManagedTurnContext;
|
|
20
|
+
export type ManagedRoomEnqueueParams = Omit<ChatEnqueueParams, 'protocolVersion' | 'dataEpoch' | 'daemonInstallationId'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -1,40 +1,21 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ChatQueueSnapshot, type ReqFrame } from '@shennian/wire';
|
|
2
2
|
import type { LocalReqDispatcher } from '../manager/runtime.js';
|
|
3
3
|
import type { SessionManagerRuntime } from './types.js';
|
|
4
|
-
import type {
|
|
5
|
-
import type { ManagedRoomPromptSnapshot } from '../room/managed-prompt-composer.js';
|
|
6
|
-
import type { ManagedRoomTriggerContext, TurnTrigger } from './turn-trigger.js';
|
|
4
|
+
import type { ManagedRoomTriggerContext } from './turn-trigger.js';
|
|
7
5
|
export { purgeQueuedSessionData } from './queue-storage.js';
|
|
8
6
|
export type ManagedRoomQueueContext = ManagedRoomTriggerContext;
|
|
9
|
-
export type PreparedManagedTurnContext
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
systemPrompt: string;
|
|
14
|
-
sessionMode: SessionMode;
|
|
15
|
-
managerConfig: ManagerConfig | null;
|
|
16
|
-
managerDefaultWorkerAgentType: AgentType | null;
|
|
17
|
-
managerDefaultWorkerModelId: string | null;
|
|
18
|
-
roomContextRegistryKey: string;
|
|
19
|
-
managedRoomContextToken: string;
|
|
20
|
-
managedAgentPolicy: CompiledManagedAgentPolicy;
|
|
21
|
-
managedRoomPromptSnapshot: ManagedRoomPromptSnapshot;
|
|
22
|
-
};
|
|
23
|
-
/** @deprecated Compatibility name for callers migrated incrementally. */
|
|
24
|
-
export type PreparedManagedRoomTurn = PreparedManagedTurnContext;
|
|
25
|
-
export type ManagedRoomEnqueueParams = Omit<ChatEnqueueParams, 'protocolVersion' | 'dataEpoch' | 'daemonInstallationId'>;
|
|
26
|
-
export type LocalQueuedChatMessage = QueuedChatMessage & {
|
|
27
|
-
origin?: 'app' | 'external' | 'room';
|
|
28
|
-
trigger?: TurnTrigger;
|
|
29
|
-
/** Legacy persisted fields remain readable until all v1 queue files drain. */
|
|
30
|
-
managedRoom?: ManagedRoomQueueContext;
|
|
31
|
-
managedAgentDirect?: true;
|
|
32
|
-
};
|
|
33
|
-
export declare class TerminalQueuedChatDispatchError extends Error {
|
|
34
|
-
constructor(message: string);
|
|
35
|
-
}
|
|
7
|
+
export type { PreparedManagedTurnContext, PreparedManagedRoomTurn, ManagedRoomEnqueueParams } from './queue-types.js';
|
|
8
|
+
import type { PreparedManagedRoomTurn, ManagedRoomEnqueueParams } from './queue-types.js';
|
|
9
|
+
export { TerminalQueuedChatDispatchError } from './queue-message.js';
|
|
10
|
+
export type { LocalQueuedChatMessage } from './queue-message.js';
|
|
36
11
|
export declare class ChatQueueManager {
|
|
37
12
|
private opts;
|
|
13
|
+
validateScheduledTarget?: (target: {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
bindingId?: string;
|
|
16
|
+
roomId?: string;
|
|
17
|
+
}) => Promise<string>;
|
|
18
|
+
enqueueScheduled(req: ReqFrame): Promise<boolean>;
|
|
38
19
|
private draining;
|
|
39
20
|
private promoting;
|
|
40
21
|
private disposed;
|
|
@@ -59,7 +40,7 @@ export declare class ChatQueueManager {
|
|
|
59
40
|
params: ManagedRoomEnqueueParams;
|
|
60
41
|
context: ManagedRoomQueueContext;
|
|
61
42
|
}>): Promise<void>;
|
|
62
|
-
handleEnqueue(req: ReqFrame): Promise<boolean>;
|
|
43
|
+
handleEnqueue(req: ReqFrame, trustedSchedule?: boolean): Promise<boolean>;
|
|
63
44
|
handleGet(req: ReqFrame): Promise<void>;
|
|
64
45
|
handleEdit(req: ReqFrame): Promise<void>;
|
|
65
46
|
handleDelete(req: ReqFrame): Promise<void>;
|