shennian 0.5.42 → 0.5.44
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 +12 -7
- package/dist/src/agents/custom.js +4 -4
- package/dist/src/session/attachment-cleanup-loop.js +1 -0
- package/dist/src/session/attachment-transfer-store.js +2 -2
- package/dist/src/session/handlers/personal-workspace.js +1 -1
- package/dist/src/session/manager.js +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 325,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian-adapter-host.js",
|
|
@@ -1184,6 +1184,11 @@
|
|
|
1184
1184
|
"beforeBytes": 8037,
|
|
1185
1185
|
"afterBytes": 3438
|
|
1186
1186
|
},
|
|
1187
|
+
{
|
|
1188
|
+
"file": "src/session/attachment-cleanup-loop.js",
|
|
1189
|
+
"beforeBytes": 1269,
|
|
1190
|
+
"afterBytes": 476
|
|
1191
|
+
},
|
|
1187
1192
|
{
|
|
1188
1193
|
"file": "src/session/attachment-reference.js",
|
|
1189
1194
|
"beforeBytes": 1717,
|
|
@@ -1191,8 +1196,8 @@
|
|
|
1191
1196
|
},
|
|
1192
1197
|
{
|
|
1193
1198
|
"file": "src/session/attachment-transfer-store.js",
|
|
1194
|
-
"beforeBytes":
|
|
1195
|
-
"afterBytes":
|
|
1199
|
+
"beforeBytes": 19536,
|
|
1200
|
+
"afterBytes": 9713
|
|
1196
1201
|
},
|
|
1197
1202
|
{
|
|
1198
1203
|
"file": "src/session/canonical-store.js",
|
|
@@ -1306,8 +1311,8 @@
|
|
|
1306
1311
|
},
|
|
1307
1312
|
{
|
|
1308
1313
|
"file": "src/session/handlers/personal-workspace.js",
|
|
1309
|
-
"beforeBytes":
|
|
1310
|
-
"afterBytes":
|
|
1314
|
+
"beforeBytes": 804,
|
|
1315
|
+
"afterBytes": 444
|
|
1311
1316
|
},
|
|
1312
1317
|
{
|
|
1313
1318
|
"file": "src/session/handlers/personal.js",
|
|
@@ -1371,8 +1376,8 @@
|
|
|
1371
1376
|
},
|
|
1372
1377
|
{
|
|
1373
1378
|
"file": "src/session/manager.js",
|
|
1374
|
-
"beforeBytes":
|
|
1375
|
-
"afterBytes":
|
|
1379
|
+
"beforeBytes": 42272,
|
|
1380
|
+
"afterBytes": 22324
|
|
1376
1381
|
},
|
|
1377
1382
|
{
|
|
1378
1383
|
"file": "src/session/native-cleanup-outbox.js",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{createInterface as g}from"node:readline";import{createHash as f,randomUUID as a}from"node:crypto";import{AgentAdapter as w,registerAgent as P}from"./adapter.js";import{spawnCommandString as l}from"./command-spec.js";import{buildAgentProcessEnv as v,buildManagedAgentProcessEnv as S,buildManagedNativeFullProcessEnv as y}from"../agent-env.js";import{buildInlineChannelPreamble as u,buildPlatformInstructions as D}from"./platform-instructions.js";import{isManagedAgentNativeFull as C}from"../security/managed-agent-policy.js";import{assertPublicAgentPolicy as I}from"../security/public-agent-policy.js";import{collectPolicyEnforcementGaps as E}from"../security/managed-agent-runtime.js";import{assessCustomRuntimeSecurity as R,createCustomManagedPolicyFile as b,CUSTOM_RUNTIME_POLICY_ENV as x,disposeCustomManagedPolicyFile as k,registerCustomRuntimeSecurity as _,resolveCustomRuntimeExecutableFingerprint as p}from"./custom-managed-runtime.js";import{hasCustomResumeConformance as q,recordCustomResumeConformance as A}from"./custom-recovery-conformance.js";const m=3e3;class M extends w{type;get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:this.entry.caps.resume===!0&&this.resumeConformant}}command;mode;proactive;entry;sessionId=null;agentSessionId=null;workDir=null;runId="";seq=0;externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;configurationRestartRequired=!1;executableFingerprint;resumeConformant;expectedResumedSessionId=null;stoppingStdioProcess=!1;pendingProtocolRequests=new Map;stdioProcess=null;spawnProcess=null;dispatchGuard=null;dispatchObservedEvent=!1;constructor(e,t){super(),this.type=`custom:${e}`,this.entry=t,this.command=t.command,this.mode=t.caps.mode,this.proactive=t.caps.proactive??!1,this.executableFingerprint=p(t),this.resumeConformant=q(this.type,this.executableFingerprint,t.caps.version)}get usesNodeStdioV2(){return this.entry.caps.protocol==="shennian-node-stdio"&&this.entry.caps.protocolVersion===2}async start(e,t,s){if(this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,s&&(this.agentSessionId=s,this.expectedResumedSessionId=s),this.mode==="stdio"){if(await this.startStdioProcess(),this.usesNodeStdioV2){const n=await this.sendProtocolRequest("start",{sessionId:e,workDir:this.workDir});n?.nativeSessionId&&(this.agentSessionId=n.nativeSessionId)}s&&await this.resume(s)}}configure(e){const t=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir),t!==this.configurationFingerprint()&&(this.stdioProcess||this.spawnProcess)&&(this.configurationRestartRequired=!0)}async send(e,t,s,n,r
|
|
2
|
-
`)}}async stop(){this.mode==="stdio"?await this.stopStdioProcess():await this.killSpawnProcess()}async runSpawn(e,t){await this.killSpawnProcess();const s=
|
|
3
|
-
`),await s.promise}async sendStdioV2(e,t,s,n,
|
|
4
|
-
`)}await t,this.stdioProcess=null,await this.disposeManagedConfig(this.managedConfigDir),this.stoppingStdioProcess=!1}async prepareManagedLaunch(){const e=this.managedAgentPolicy;if(!e)return{env:v(this.extraEnv),configDir:null};if(C(e))return{env:y(this.extraEnv),configDir:null};const t=p(this.entry);if(!e.enforcement.executableFingerprint||t!==e.enforcement.executableFingerprint)throw new Error("custom_managed_runtime_executable_changed");if(e.enforcement.level!=="unverified")throw new Error("custom_managed_runtime_protection_must_be_unverified");const s=R(this.entry);if(s.state==="declared"&&e.enforcement.runtimeVersion!==this.entry.caps.version)throw new Error("custom_managed_runtime_version_changed");if(s.state==="declared"){const
|
|
1
|
+
import{createInterface as g}from"node:readline";import{createHash as f,randomUUID as a}from"node:crypto";import{AgentAdapter as w,registerAgent as P}from"./adapter.js";import{spawnCommandString as l}from"./command-spec.js";import{buildAgentProcessEnv as v,buildManagedAgentProcessEnv as S,buildManagedNativeFullProcessEnv as y}from"../agent-env.js";import{buildInlineChannelPreamble as u,buildPlatformInstructions as D}from"./platform-instructions.js";import{isManagedAgentNativeFull as C}from"../security/managed-agent-policy.js";import{assertPublicAgentPolicy as I}from"../security/public-agent-policy.js";import{collectPolicyEnforcementGaps as E}from"../security/managed-agent-runtime.js";import{assessCustomRuntimeSecurity as R,createCustomManagedPolicyFile as b,CUSTOM_RUNTIME_POLICY_ENV as x,disposeCustomManagedPolicyFile as k,registerCustomRuntimeSecurity as _,resolveCustomRuntimeExecutableFingerprint as p}from"./custom-managed-runtime.js";import{hasCustomResumeConformance as q,recordCustomResumeConformance as A}from"./custom-recovery-conformance.js";const m=3e3;class M extends w{type;get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:this.entry.caps.resume===!0&&this.resumeConformant}}command;mode;proactive;entry;sessionId=null;agentSessionId=null;workDir=null;runId="";seq=0;externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;configurationRestartRequired=!1;executableFingerprint;resumeConformant;expectedResumedSessionId=null;stoppingStdioProcess=!1;pendingProtocolRequests=new Map;stdioProcess=null;spawnProcess=null;dispatchGuard=null;dispatchObservedEvent=!1;constructor(e,t){super(),this.type=`custom:${e}`,this.entry=t,this.command=t.command,this.mode=t.caps.mode,this.proactive=t.caps.proactive??!1,this.executableFingerprint=p(t),this.resumeConformant=q(this.type,this.executableFingerprint,t.caps.version)}get usesNodeStdioV2(){return this.entry.caps.protocol==="shennian-node-stdio"&&this.entry.caps.protocolVersion===2}async start(e,t,s){if(this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,s&&(this.agentSessionId=s,this.expectedResumedSessionId=s),this.mode==="stdio"){if(await this.startStdioProcess(),this.usesNodeStdioV2){const n=await this.sendProtocolRequest("start",{sessionId:e,workDir:this.workDir});n?.nativeSessionId&&(this.agentSessionId=n.nativeSessionId)}s&&await this.resume(s)}}configure(e){const t=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir),t!==this.configurationFingerprint()&&(this.stdioProcess||this.spawnProcess)&&(this.configurationRestartRequired=!0)}async send(e,t,s,n,i,r){if(r?.source==="published_agent"&&I(this.managedAgentPolicy),r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(this.configurationRestartRequired&&(this.mode==="stdio"?await this.stopStdioProcess():await this.killSpawnProcess(),this.configurationRestartRequired=!1),this.runId=a(),this.seq=0,this.mode==="stdio")if(this.usesNodeStdioV2)await this.sendStdioV2(e,D(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,i),t,s,n);else{const o=`${u(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,i)}${e}`;await this.sendStdio(o,t)}else{const o=`${u(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,i)}${e}`;await this.runSpawn(o,t)}}async resume(e){if(this.mode==="stdio"){if(this.usesNodeStdioV2){const s=await this.sendProtocolRequest("resume",{sessionId:this.sessionId,nativeSessionId:e});this.agentSessionId=s?.nativeSessionId??e;return}const t=JSON.stringify({method:"resume",id:a(),params:{sessionId:this.sessionId,agentSessionId:e}});this.stdioProcess?.stdin?.write(t+`
|
|
2
|
+
`)}}async stop(){this.mode==="stdio"?await this.stopStdioProcess():await this.killSpawnProcess()}async runSpawn(e,t){await this.killSpawnProcess();const s=["/run","--workdir",this.workDir??process.cwd()];this.sessionId&&s.push("--session",this.sessionId),this.agentSessionId&&s.push("--resume",this.agentSessionId),t&&s.push("--model",t);const n=await this.prepareManagedLaunch();let i;try{i=l(this.command,s,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:n.env})}catch(o){throw await this.disposeManagedConfig(n.configDir),o}this.spawnProcess=i,this.managedConfigDir=n.configDir;const r=this.startDispatchGuard();this.dispatchObservedEvent=!1,this.attachOutputHandlers(i,()=>{this.spawnProcess===i&&(this.spawnProcess=null),this.disposeManagedConfig(n.configDir)}),i.stdin?.once("error",o=>this.rejectDispatch(o)),i.stdin?.write(e),i.stdin?.end(),await r.promise}async killSpawnProcess(){const e=this.spawnProcess;if(!e){await this.disposeManagedConfig(this.managedConfigDir);return}this.spawnProcess=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}async startStdioProcess(){const e=await this.prepareManagedLaunch();let t;try{t=l(this.command,["/start","--workdir",this.workDir??process.cwd()],{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:e.env})}catch(s){throw await this.disposeManagedConfig(e.configDir),s}this.stdioProcess=t,this.managedConfigDir=e.configDir,this.attachOutputHandlers(t,()=>{this.stdioProcess===t&&(this.stdioProcess=null,this.disposeManagedConfig(e.configDir),this.stoppingStdioProcess||this.emit("error",new Error("Custom agent process exited unexpectedly")))})}async sendStdio(e,t){this.stdioProcess||await this.startStdioProcess();const s=this.startDispatchGuard();this.dispatchObservedEvent=!1;const n=JSON.stringify({method:"send",id:a(),params:{sessionId:this.sessionId,text:e,modelId:t}});this.stdioProcess?.stdin?.once("error",i=>this.rejectDispatch(i)),this.stdioProcess?.stdin?.write(n+`
|
|
3
|
+
`),await s.promise}async sendStdioV2(e,t,s,n,i){this.stdioProcess||(await this.startStdioProcess(),await this.sendProtocolRequest("start",{sessionId:this.sessionId,workDir:this.workDir})),this.dispatchObservedEvent=!1,await this.sendProtocolRequest("send",{sessionId:this.sessionId,text:e,systemPrompt:t,modelId:s,reasoningEffort:n,attachments:i?.map(r=>({path:r.path,name:r.name,mime:r.mimeType}))??[]})}async stopStdioProcess(){const e=this.stdioProcess;if(!e){await this.disposeManagedConfig(this.managedConfigDir);return}this.stoppingStdioProcess=!0;const t=new Promise(s=>{const n=setTimeout(()=>{e.kill("SIGTERM"),setTimeout(()=>{e.kill("SIGKILL"),s()},3e3)},5e3);e.on("close",()=>{clearTimeout(n),s()})});if(this.usesNodeStdioV2)await this.sendProtocolRequest("stop",{}).catch(()=>{});else{const s=JSON.stringify({method:"stop",id:a()});e.stdin?.write(s+`
|
|
4
|
+
`)}await t,this.stdioProcess=null,await this.disposeManagedConfig(this.managedConfigDir),this.stoppingStdioProcess=!1}async prepareManagedLaunch(){const e=this.managedAgentPolicy;if(!e)return{env:v(this.extraEnv),configDir:null};if(C(e))return{env:y(this.extraEnv),configDir:null};const t=p(this.entry);if(!e.enforcement.executableFingerprint||t!==e.enforcement.executableFingerprint)throw new Error("custom_managed_runtime_executable_changed");if(e.enforcement.level!=="unverified")throw new Error("custom_managed_runtime_protection_must_be_unverified");const s=R(this.entry);if(s.state==="declared"&&e.enforcement.runtimeVersion!==this.entry.caps.version)throw new Error("custom_managed_runtime_version_changed");if(s.state==="declared"){const r=s.declaration.platforms[e.enforcement.platform],o=E(e.requestedPolicy,r??null);if(o.unavailableCapabilities.length>0)throw new Error(`custom_managed_runtime_capability_unavailable:${o.unavailableCapabilities.join(",")}`)}const n=S({agentType:this.type,providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});if(s.state==="unverified")return{env:n,configDir:null};const i=await b(e);return n[x]=i.policyPath,{env:n,configDir:i.directory}}async disposeManagedConfig(e){e&&(this.managedConfigDir===e&&(this.managedConfigDir=null),await k(e).catch(()=>{}))}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(t=>[t,this.extraEnv[t]??null]);return f("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}attachOutputHandlers(e,t){g({input:e.stdout}).on("line",i=>{if(i.trim())try{const r=JSON.parse(i);"type"in r&&r.type==="response"?this.handleProtocolResponse(r):"type"in r&&r.type==="event"?this.handleProtocolEvent({...r.event,agentSessionId:r.event.nativeSessionId}):this.handleProtocolEvent(r)}catch{}});let n="";e.stderr?.on("data",i=>{n+=i.toString()}),e.on("close",i=>{if(t(),this.rejectPendingProtocolRequests(new Error(`Custom agent process exited with code ${i??"unknown"}`)),i!==0&&i!==null){const r=n.trim()||`Agent exited with code ${i}`;this.rejectDispatch(new Error(r)),this.emitEvent({state:"error",message:r})}else this.dispatchObservedEvent?this.acceptDispatch():this.rejectDispatch(new Error("Custom agent exited without protocol events"))}),e.on("error",i=>{t(),this.rejectDispatch(i),this.emit("error",i)})}handleProtocolResponse(e){if(!e.id)return;const t=this.pendingProtocolRequests.get(e.id);if(t){if(clearTimeout(t.timer),this.pendingProtocolRequests.delete(e.id),e.ok){t.resolve(e.result);return}t.reject(new Error(e.error?.message??e.error?.code??"Adapter request failed"))}}sendProtocolRequest(e,t){const s=this.stdioProcess?.stdin;if(!s?.writable)return Promise.reject(new Error("Custom adapter stdio is not writable"));const n=a();return new Promise((i,r)=>{const o=setTimeout(()=>{this.pendingProtocolRequests.delete(n),r(new Error(`Timed out waiting for custom adapter ${e} response`))},e==="send"?m:5e3);this.pendingProtocolRequests.set(n,{resolve:i,reject:r,timer:o}),s.write(`${JSON.stringify({protocolVersion:2,id:n,method:e,params:t})}
|
|
5
5
|
`,h=>{if(!h)return;const d=this.pendingProtocolRequests.get(n);d&&(clearTimeout(d.timer),this.pendingProtocolRequests.delete(n),d.reject(h))})})}rejectPendingProtocolRequests(e){for(const t of this.pendingProtocolRequests.values())clearTimeout(t.timer),t.reject(e);this.pendingProtocolRequests.clear()}handleProtocolEvent(e){const{state:t}=e;if(t)switch(this.dispatchObservedEvent=!0,t){case"delta":this.acceptDispatch(),this.emitEvent({state:"delta",text:e.text??"",thinking:e.thinking});break;case"final":this.acceptDispatch(),this.expectedResumedSessionId&&e.agentSessionId===this.expectedResumedSessionId&&this.executableFingerprint&&(A(this.type,this.executableFingerprint,this.entry.caps.version),this.resumeConformant=!0,this.expectedResumedSessionId=null),e.agentSessionId&&(this.agentSessionId=e.agentSessionId),this.emitEvent({state:"final",usage:e.usage,agentSessionId:this.agentSessionId??void 0});break;case"error":this.rejectDispatch(new Error(e.message??"unknown error")),this.emitEvent({state:"error",message:e.message??"unknown error"});break;case"tool-call":this.acceptDispatch(),this.emitEvent({state:"tool-call",name:e.name??"",args:e.args});break;case"tool-result":this.acceptDispatch(),this.emitEvent({state:"tool-result",name:e.name??"",result:e.result??""});break;case"notify":this.acceptDispatch(),this.emitEvent({state:"notify",text:e.text??"",title:e.title,source:e.source});break}}startDispatchGuard(){this.acceptDispatch();let e;const t=new Promise((s,n)=>{e={settled:!1,timer:setTimeout(()=>this.acceptDispatch(e),m),resolve:s,reject:n,promise:Promise.resolve()}});return e.promise=t,this.dispatchGuard=e,e}acceptDispatch(e=this.dispatchGuard){!e||e.settled||(e.settled=!0,clearTimeout(e.timer),this.dispatchGuard===e&&(this.dispatchGuard=null),e.resolve())}rejectDispatch(e,t=this.dispatchGuard){!t||t.settled||(t.settled=!0,clearTimeout(t.timer),this.dispatchGuard===t&&(this.dispatchGuard=null),t.reject(e))}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}}function U(c,e){const t=`custom:${c}`;_(t,e),P(t,()=>new M(c,e))}export{M as CustomAgentAdapter,U as registerCustomAgent};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sweepAttachmentTransfersCooperatively as f}from"./attachment-transfer-store.js";function u(t){let r=!1,n=!1;const s=()=>!r,c=t.sweep??((o,e)=>f(o,Date.now(),e)),l=async()=>{for(const o of new Set(t.getRoots())){if(r)return;try{await c(o,s)}catch(e){t.onError(e)}await new Promise(e=>setImmediate(e))}},a=setInterval(()=>{r||n||(n=!0,l().catch(t.onError).finally(()=>{n=!1}))},6e4);return a.unref?.(),()=>{r=!0,clearInterval(a)}}export{u as startAttachmentCleanupLoop};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import M from"node:crypto";import s from"node:fs";import{renameSyncWithRetry as D}from"../fs/atomic-rename.js";import o from"node:path";import{serializeFsTransferManifest as
|
|
2
|
-
`,{mode:384}),D(t,e)}function u(e){try{return JSON.parse(s.readFileSync(e,"utf8"))}catch{return null}}function P(e){const r=M.createHash("sha256"),t=s.openSync(e,"r"),n=Buffer.allocUnsafe(256*1024);try{let i=0;do i=s.readSync(t,n,0,n.length,null),i>0&&r.update(n.subarray(0,i));while(i>0)}finally{s.closeSync(t)}return r.digest("hex")}function x(e){return M.createHash("sha256").update(
|
|
1
|
+
import M from"node:crypto";import s from"node:fs";import{renameSyncWithRetry as D}from"../fs/atomic-rename.js";import o from"node:path";import{serializeFsTransferManifest as K}from"@shennian/wire";const U=600*1e3,q=1440*60*1e3,V=1024*1024,C=1024*1024*1024,Z=2e3,H=1024*1024*1024,w=1,$="__file__",O=/^[a-f0-9]{64}$/i,L=/^[A-Za-z0-9_-]{8,128}$/;function l(e){return o.join(e,".uploads")}function S(e){return o.join(l(e),".staging")}function E(e){return o.join(l(e),".metadata")}function m(e,r){return o.join(S(e),r)}function T(e,r){return o.join(m(e,r),"manifest.json")}function A(e,r){return o.join(E(e),`${r.toLowerCase()}.json`)}function d(e,r){const t=o.relative(o.resolve(e),o.resolve(r));if(!(t===""||!t.startsWith("..")&&!o.isAbsolute(t)))throw new Error("attachment_path_outside_uploads")}function z(e){if(!L.test(e))throw new Error("invalid_transfer_id")}function p(e){if(!O.test(e))throw new Error("invalid_attachment_sha256");return e.toLowerCase()}function G(e){if(!e||e.trim()!==e||o.basename(e)!==e||e==="."||e==="..")throw new Error("invalid_attachment_name");if(Array.from(e).some(r=>r.charCodeAt(0)<=31))throw new Error("invalid_attachment_name");return e}function g(e){if(!e||e.trim()!==e||e.includes("\\"))throw new Error("invalid_attachment_relative_path");if(o.posix.isAbsolute(e)||o.win32.isAbsolute(e))throw new Error("invalid_attachment_relative_path");if(e.split("/").some(t=>!t||t==="."||t===".."))throw new Error("invalid_attachment_relative_path");return e}function B(e,r,t){if(!Number.isSafeInteger(e)||e<0||e>r)throw new Error(`invalid_${t}`);return e}function k(e,r){s.mkdirSync(o.dirname(e),{recursive:!0});const t=`${e}.${process.pid}.tmp`;s.writeFileSync(t,`${JSON.stringify(r)}
|
|
2
|
+
`,{mode:384}),D(t,e)}function u(e){try{return JSON.parse(s.readFileSync(e,"utf8"))}catch{return null}}function P(e){const r=M.createHash("sha256"),t=s.openSync(e,"r"),n=Buffer.allocUnsafe(256*1024);try{let i=0;do i=s.readSync(t,n,0,n.length,null),i>0&&r.update(n.subarray(0,i));while(i>0)}finally{s.closeSync(t)}return r.digest("hex")}function x(e){return M.createHash("sha256").update(K(e)).digest("hex")}function y(e,r,t){const n=o.join(m(e,r),"payload"),i=t?o.join(n,...t.split("/")):n;return d(m(e,r),i),i}function W(e,r){z(r);const t=u(T(e,r));if(!t||t.version!==w||t.transferId!==r||o.resolve(t.rootPath)!==o.resolve(e))throw new Error("invalid_transfer_id");return d(l(e),t.targetPath),t}function F(e){k(T(e.rootPath,e.transferId),e)}function Q(e,r){if(!s.existsSync(e))return e;const t=o.parse(e);for(let n=0;n<1e3;n+=1){const i=n===0?r.slice(0,10):`${r.slice(0,10)}-${n+1}`,a=o.join(t.dir,`${t.name}-${i}${t.ext}`);if(!s.existsSync(a))return a}throw new Error("attachment_name_conflict")}function R(e,r){const t=u(A(e,r));if(!t||t.version!==w||t.sha256!==r)return null;try{d(l(e),t.path);const n=s.statSync(t.path);if(t.kind==="file"&&(!n.isFile()||n.size!==t.byteSize||P(t.path)!==t.sha256))return null;if(t.kind==="folder"){if(!n.isDirectory()||!t.files?.length)return null;for(const i of t.files){const a=o.join(t.path,...g(i.relativePath).split("/"));if(d(t.path,a),!s.statSync(a).isFile()||s.statSync(a).size!==i.size||P(a)!==i.sha256)return null}if(x(t.files)!==t.sha256)return null}return t}catch{return null}}function b(e,r){return{transferId:e.transferId,path:e.path,name:e.name,mimeType:e.mimeType,kind:e.kind,byteSize:e.byteSize,sha256:e.sha256,reused:r}}function ee(e){if(e.kind==="file")return[{relativePath:$,size:e.totalSize,sha256:e.sha256,receivedSize:0}];if(!e.manifest?.length||e.manifest.length>Z)throw new Error("invalid_attachment_manifest");const r=new Set;let t=0;const n=e.manifest.map(i=>{const a=g(i.relativePath);if(r.has(a))throw new Error("duplicate_attachment_relative_path");r.add(a);const f=B(i.size,C,"attachment_size");if(t+=f,t>H)throw new Error("attachment_folder_too_large");return{...i,relativePath:a,size:f,sha256:p(i.sha256),receivedSize:0}});if(t!==e.totalSize)throw new Error("attachment_total_size_mismatch");if(x(n)!==e.sha256)throw new Error("attachment_manifest_hash_mismatch");return n}function se(e,r=Date.now()){z(e.transferId);const t=G(e.name),n=p(e.sha256),i=e.kind==="folder"?H:C,a=B(e.totalSize,i,"attachment_total_size");if(!e.rootPath||!o.isAbsolute(e.rootPath))throw new Error("invalid_attachment_root");if(!e.mimeType||e.mimeType.length>255)throw new Error("invalid_attachment_mime_type");te(e.rootPath,r);const f=R(e.rootPath,n);if(f&&f.kind===e.kind&&f.byteSize===a)return{transferId:e.transferId,path:f.path,reused:!0,offsets:{},attachment:{...b(f,!0),transferId:e.transferId}};const c=u(T(e.rootPath,e.transferId));if(c){if(c.sha256!==n||c.totalSize!==a||c.name!==t||c.kind!==e.kind||c.mimeType!==e.mimeType)throw new Error("transfer_identity_conflict");return c.lastActivityAt=r,F(c),{transferId:e.transferId,path:c.targetPath,reused:!1,offsets:Object.fromEntries(c.files.map(_=>[_.relativePath,_.receivedSize]))}}const h=ee({...e,name:t,sha256:n,totalSize:a}),v=l(e.rootPath);s.mkdirSync(S(e.rootPath),{recursive:!0,mode:448}),s.mkdirSync(E(e.rootPath),{recursive:!0,mode:448});const X=m(e.rootPath,e.transferId);s.mkdirSync(X,{recursive:!1,mode:448});const I=o.join(v,t);d(v,I);const N=Q(I,n);if(e.kind==="folder"){s.mkdirSync(y(e.rootPath,e.transferId),{recursive:!0,mode:448});for(const _ of h){const j=y(e.rootPath,e.transferId,_.relativePath);s.mkdirSync(o.dirname(j),{recursive:!0,mode:448}),s.writeFileSync(j,Buffer.alloc(0),{mode:384})}}else s.writeFileSync(y(e.rootPath,e.transferId),Buffer.alloc(0),{mode:384});const Y={version:w,transferId:e.transferId,rootPath:o.resolve(e.rootPath),uploadsRoot:v,kind:e.kind,name:t,mimeType:e.mimeType,totalSize:a,sha256:n,targetPath:N,createdAt:r,lastActivityAt:r,files:h};return F(Y),{transferId:e.transferId,path:N,reused:!1,offsets:Object.fromEntries(h.map(_=>[_.relativePath,0]))}}function ce(e){const r=W(e.rootPath,e.transferId),t=r.kind==="file"?$:g(e.relativePath??""),n=r.files.find(a=>a.relativePath===t);if(!n)throw new Error("invalid_attachment_relative_path");if(!Number.isSafeInteger(e.offset)||e.offset!==n.receivedSize)throw new Error(e.offset<n.receivedSize?"duplicate_attachment_chunk":"out_of_order_attachment_chunk");if(e.data.length<=0||e.data.length>V)throw new Error("invalid_attachment_chunk_size");if(e.offset+e.data.length>n.size)throw new Error("attachment_chunk_exceeds_size");const i=y(e.rootPath,e.transferId,r.kind==="folder"?n.relativePath:void 0);return s.appendFileSync(i,e.data),n.receivedSize+=e.data.length,r.lastActivityAt=e.now??Date.now(),F(r),{written:e.data.length,nextOffset:n.receivedSize}}function fe(e,r,t=Date.now()){const n=W(e,r);for(const c of n.files){if(c.receivedSize!==c.size)throw new Error("attachment_transfer_incomplete");const h=y(e,r,n.kind==="folder"?c.relativePath:void 0);if(s.statSync(h).size!==c.size)throw new Error("attachment_size_mismatch");if(P(h)!==c.sha256)throw new Error("attachment_hash_mismatch")}if(n.kind==="folder"&&x(n.files)!==n.sha256)throw new Error("attachment_manifest_hash_mismatch");const i=R(e,n.sha256);if(i&&i.kind===n.kind&&i.byteSize===n.totalSize)return s.rmSync(m(e,r),{recursive:!0,force:!0}),{...b(i,!0),transferId:r};s.mkdirSync(o.dirname(n.targetPath),{recursive:!0,mode:448});const a=y(e,r);D(a,n.targetPath);const f={version:w,transferId:r,path:n.targetPath,name:n.name,mimeType:n.mimeType,kind:n.kind,byteSize:n.totalSize,sha256:n.sha256,finishedAt:t,referencedAt:null,...n.kind==="folder"?{files:n.files.map(({receivedSize:c,...h})=>h)}:{}};return k(A(e,n.sha256),f),s.rmSync(m(e,r),{recursive:!0,force:!0}),b(f,!1)}function he(e,r){z(r);const t=m(e,r);d(S(e),t);const n=s.existsSync(t);return s.rmSync(t,{recursive:!0,force:!0}),n}function de(e,r,t=Date.now()){for(const n of r){if(!O.test(n.sha256))continue;const i=A(e,n.sha256),a=u(i);!a||o.resolve(a.path)!==o.resolve(n.path)||(d(l(e),a.path),a.referencedAt=a.referencedAt??t,k(i,a))}}function le(e,r){for(const t of r){const n=p(t.sha256),i=R(e,n);if(!i)throw new Error("attachment_not_finished");const a=i.kind==="folder"?"folder":i.mimeType.startsWith("image/")?"image":"file";if(o.resolve(i.path)!==o.resolve(t.path)||i.name!==t.name||i.mimeType!==t.mimeType||i.byteSize!==t.byteSize||a!==t.kind)throw new Error("attachment_reference_mismatch")}}function te(e,r=Date.now()){const t={stagingRemoved:0,orphanRemoved:0};for(const n of J(e,r,t));return t}async function me(e,r=Date.now(),t=()=>!0){const n={stagingRemoved:0,orphanRemoved:0};let i=0;for(const a of J(e,r,n))if(++i%16===0&&await new Promise(f=>setImmediate(f)),!t())break;return n}function*J(e,r,t){const n=S(e);try{for(const a of s.readdirSync(n,{withFileTypes:!0})){if(yield,!a.isDirectory()||!L.test(a.name))continue;const f=o.join(n,a.name),h=u(o.join(f,"manifest.json"))?.lastActivityAt??s.statSync(f).mtimeMs;r-h<U||(d(n,f),s.rmSync(f,{recursive:!0,force:!0}),t.stagingRemoved+=1)}}catch(a){if(a.code!=="ENOENT")throw a}const i=E(e);try{for(const a of s.readdirSync(i,{withFileTypes:!0})){if(yield,!a.isFile()||!a.name.endsWith(".json"))continue;const f=o.join(i,a.name),c=u(f);!c||c.referencedAt!==null||r-c.finishedAt<q||(d(l(e),c.path),s.rmSync(c.path,{recursive:c.kind==="folder",force:!0}),s.rmSync(f,{force:!0}),t.orphanRemoved+=1)}}catch(a){if(a.code!=="ENOENT")throw a}}export{V as ATTACHMENT_MAX_CHUNK_BYTES,C as ATTACHMENT_MAX_FILE_BYTES,H as ATTACHMENT_MAX_FOLDER_BYTES,Z as ATTACHMENT_MAX_FOLDER_FILES,q as ATTACHMENT_ORPHAN_TTL_MS,U as ATTACHMENT_TRANSFER_IDLE_MS,he as abortAttachmentTransfer,ce as appendAttachmentTransferChunk,le as assertFinishedAttachmentReferences,fe as finishAttachmentTransfer,de as markAttachmentReferences,se as startAttachmentTransfer,te as sweepAttachmentTransfers,me as sweepAttachmentTransfersCooperatively};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{personalWorkspace as
|
|
1
|
+
import{personalWorkspace as r}from"../../personal-workspace/service.js";async function t(s,e){try{const a=e.params.action==="worker_info"?s.getAgentSnapshot?.()??[]:[];s.client.sendRes({type:"res",id:e.id,ok:!0,payload:await r(e.params,a)})}catch(a){const o=a instanceof Error?a.message:"";s.client.sendRes({type:"res",id:e.id,ok:!1,error:/^personal_[a-z_]+$/.test(o)?o:"personal_directory_unavailable"})}}export{t as handlePersonalWorkspace};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import b from"node:crypto";import{getRegisteredAgents as S,unregisterAgent as k}from"../agents/adapter.js";import{resetCommandSpecCache as w}from"../agents/command-spec.js";import{loadConfig as I}from"../config/index.js";import{handleUpgradeStart as A,handleUpgradeStatus as T}from"../commands/upgrade.js";import{handleAgentsRefresh as P,handleModelsRefresh as C,refreshMachineAgents as M}from"./handlers/agents.js";import{AcpDiscoveryWatcher as x}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as D}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as F,handleAgentConfigGet as E,handleAgentConfigTest as Q,handleAgentConfigUpsert as j}from"./handlers/agent-config.js";import{handleCodexSettings as z}from"./handlers/codex-settings.js";import{handleChatAbort as O,handleChatSend as B}from"./handlers/chat.js";import{recoverJournaledRun as H}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 U}from"./handlers/title.js";import{handleSessionMessageStatus as J}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as $}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as V}from"./handlers/voice-window.js";import{commitStewardSay as L,commitTerminalStewardSay as N}from"./handlers/steward.js";import{handlePersonalRequest as G}from"./handlers/personal.js";import{handleRemoteAccessPause as K}from"./handlers/remote-access.js";import{cleanupPendingTransfers as X,handleFsLs as Z,handleFsRead as Y,handleFsRename as q,handleFsWrite as ee,handleFsTransferAbort as se,handleFsTransferChunk as te,handleFsTransferFinish as ae,handleFsTransferStart as re,handleFsExportMarkdownPdf as ne,handleFsExportMarkdownPdfSetup as ie,handleFsArchiveZip as oe}from"./handlers/fs.js";import{handleRegionProbe as ce,handleRegionSwitch as le,handleUpgradeSetPolicy as ue}from"./handlers/control.js";import{ManagerRuntimeService as he,setManagerRuntimeService as d}from"../manager/runtime.js";import{ChatQueueManager as de}from"./queue.js";import{createAuthorizedFsRoot as me,createAuthorizedFsRootAsync as pe,resolveAuthorizedPath as ge,resolveAuthorizedPathAsync as fe,resolveSessionWorkDir as ve}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/shennian.js";import"../agents/manager.js";import{registerCustomAgent as ye}from"../agents/custom.js";import{listNodeAdapters as Re}from"../adapter-kit/registry.js";import{syncNodeAdapterAgents as be}from"../agents/node-adapter.js";import{bindManagedRoom as Se,handleManagedRoomBind as ke,handleManagedRoomRestart as we,discardPreBindingSession as Ie}from"./handlers/room-managed.js";import{getDaemonInstallationId as m,listSessionRecords as u,purgeCanonicalSession as Ae,purgeSessionRecord as Te,recordSession as Pe,upsertMessage as Ce}from"./store.js";import{requestSessionIndexPublish as p}from"./index-publisher.js";import{checkRunStalls as Me}from"./run-stall.js";import{reportUpgradeAggregateMetric as xe}from"../log-reporter.js";import{PersonalHistorySubscriptions as De}from"./history-subscriptions.js";import{sweepAttachmentTransfers as Fe}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Ee}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Qe}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as je}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as ze}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as c}from"../personal-sync/epoch.js";import{ActiveRunJournal as Oe}from"./run-recovery/journal.js";import{RunRecoveryBarrier as Be}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as He}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as We}from"./project-fs-store.js";import{handleProjectFsRequest as _e}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as Ue,handleAcpAgentRequest as Je}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as $e}from"./deletion-synchronizer.js";import{dispatchManagedChat as Ve,dispatchQueuedChat as Le,interruptQueuedChat as Ne}from"./queued-chat-dispatch.js";const Ge=50;import{resolveSessionWorkDir as rt}from"../fs/boundary.js";function Ke(){return"\u795E\u5FF5\u5347\u7EA7\u4E2D\u65AD\u4E86\u672C\u6B21\u8FD0\u884C\u3002\u5DF2\u5B8C\u6210\u7684\u56DE\u590D\u6216\u64CD\u4F5C\u4ECD\u7136\u6709\u6548\uFF0C\u672A\u5B8C\u6210\u90E8\u5206\u53EF\u91CD\u8BD5\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\u3002"}class st{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;getAgentSnapshot;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 Be;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new We;deletionSynchronizer;constructor(e,t=null,s,r=null,n=null,o=null,h=null,g=null,f=null,v=null,y=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=r,this.managedRoomBinder=n,this.remoteAccessPauseController=o,this.managedRoomContextRevoker=h,this.managedRoomExecutor=g,this.trustedProjectFsRequestResolver=v,this.getAgentSnapshot=y,this.runJournal=f??new Oe(m());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new He({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>H(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=u().find(R=>R.sessionId===a.sessionId),l=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===l},onOutcome:a=>xe({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 he({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new de({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Ve(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>Le(this.getRuntime(),a,i),interruptQueuedSession:a=>Ne(this.getRuntime(),a)}),this.deletionSynchronizer=new $e(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new De(this.client),this.nativeCleanupOutbox=new ze({logger:console.info}),this.acpDiscoveryWatcher=new x(async()=>{w(),await M(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeFusion?.setExternalClaimHandler?.((a,i)=>{this.chatQueue.noteExternalClaim(a,i)}),this.nativeCleanupOutbox.start(),d(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(()=>{Me(this.sessions.entries(),()=>p(this.client)),this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.attachmentCleanupTimer=setInterval(()=>{const a=new Set([...u().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{Fe(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,e.roomOrigin)}noteManagedRoomSendOutcome(e){for(const t of this.sessions.values()){if(t.managedRoomContextToken!==e.token)continue;const s=t.roomSendOutcome??(t.roomSendOutcome={successes:0,failureCodes:[]});e.ok?s.successes+=1:s.failureCodes.length<20&&s.failureCodes.push(e.errorCode??"managed_room_action_failed");return}}getManagedRoomActiveRunId(e,t){const s=this.sessions.get(t);if(s?.currentRunId)return s.currentRunId;for(const r of this.sessions.values())if(r.managedRoomContextToken===e)return r.currentRunId??null;return null}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),getAgentSnapshot:this.getAgentSnapshot??void 0,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}}bindManagedRoomFromLocal(e){return Se(this.getRuntime(),this.managedRoomBinder,e)}stewardSayFromLocal(e){const t=typeof e.sessionId=="string"?e.sessionId:"",s=typeof e.text=="string"?e.text:"";return t?L(this.getRuntime(),t,s):N(this.getRuntime(),s)}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=Ke();Ce(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})}),Pe({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}),p(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=u().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 Ie(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new Ee({daemonInstallationId:m()}),s=u().find(o=>o.sessionId===e.sessionId)?.codexSettings?.codexHome;let r=[];try{r=Qe(e.sessionId,{records:u()})}catch(o){console.warn("[session.deletions] local native source lookup failed",{error:o instanceof Error?o.message:String(o)})}t.recordSession(e);for(const o of[...e.sources,...r]){const h=t.find(o.agentType,o.sourceSessionKey);h&&h.sessionId!==e.sessionId||t.record({...e,...o})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const n=this.sessions.get(e.sessionId);if(n){this.revokeManagedRoomToken(n);try{await n.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),je(e.sessionId),Ae(e.sessionId),Te(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e,s),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 S())t.startsWith("custom:")&&k(t);const e=I();for(const[t,s]of Object.entries(e.customAgents??{}))ye(t,s);be(Re(),new Set(Object.keys(e.customAgents??{})))}async handleReq(e,t={}){const s=this.getRuntime();let r;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??""))?r={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await B(s,e);break;case"chat.enqueue":c(e.params),r={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.codex.settings.get":case"chat.codex.settings.set":z(s,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 O(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 U(s,e);break;case"room.agent.bind-managed":await ke(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await we(s,this.managedRoomBinder,e);break;case"personal.recording":case"personal.workspace":case"project.taskEvent":case"personal.apps.list":case"personal.apps.register":case"personal.apps.remove":case"personal.service":await G(s,e);break;case"fs.ls":await Z(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await _e(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await Y(s,e);break;case"fs.write":await ee(s,e);break;case"fs.export.markdown-pdf":await ne(s,e);break;case"fs.export.markdown-pdf.setup":await ie(s,e);break;case"fs.archive.zip":await oe(s,e);break;case"fs.rename":await q(s,e);break;case"fs.transfer.start":await re(s,e);break;case"fs.transfer.chunk":await te(s,e);break;case"fs.transfer.finish":await ae(s,e);break;case"fs.transfer.abort":await se(s,e);break;case"region.probe":await ce(s,e);break;case"region.switch":await le(s,e);break;case"upgrade.start":await A(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 T(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await ue(s,e);break;case"machine.remote-access.pause":await K(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await Ue(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 Je(s,e);break;case"models.refresh":await C(s,e);break;case"agent.config.get":await E(s,e);break;case"agent.config.upsert":await j(s,e);break;case"agent.config.clear":await F(s,e);break;case"agent.config.test":await Q(s,e);break;case"agent.workspace.validate":await $(s,e);break;case"agent.capabilities.list":await D(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<Ge)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 ve(e)}resolveAuthorizedPath(e,t){return ge(e,me(t))}async resolveAuthorizedPathAsync(e,t){return fe(e,await pe(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(),X(this.getRuntime()),await this.managerRuntime.stop(),d(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{st as SessionManager,rt as resolveSessionWorkDir,Ke as upgradeRecoveryVisibleMessage};
|
|
1
|
+
import b from"node:crypto";import{getRegisteredAgents as S,unregisterAgent as k}from"../agents/adapter.js";import{resetCommandSpecCache as A}from"../agents/command-spec.js";import{loadConfig as w}from"../config/index.js";import{handleUpgradeStart as I,handleUpgradeStatus as T}from"../commands/upgrade.js";import{handleAgentsRefresh as P,handleModelsRefresh as C,refreshMachineAgents as M}from"./handlers/agents.js";import{AcpDiscoveryWatcher as x}from"../agents/acp/watcher.js";import{handleAgentCapabilitiesList as F}from"./handlers/agent-capabilities.js";import{handleAgentConfigClear as D,handleAgentConfigGet as E,handleAgentConfigTest as Q,handleAgentConfigUpsert as j}from"./handlers/agent-config.js";import{handleCodexSettings as z}from"./handlers/codex-settings.js";import{handleChatAbort as O,handleChatSend as B}from"./handlers/chat.js";import{recoverJournaledRun as H}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 U}from"./handlers/title.js";import{handleSessionMessageStatus as J}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as $}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as L}from"./handlers/voice-window.js";import{commitStewardSay as V,commitTerminalStewardSay as N}from"./handlers/steward.js";import{handlePersonalRequest as G}from"./handlers/personal.js";import{handleRemoteAccessPause as K}from"./handlers/remote-access.js";import{cleanupPendingTransfers as X,handleFsLs as Z,handleFsRead as Y,handleFsRename as q,handleFsWrite as ee,handleFsTransferAbort as se,handleFsTransferChunk as te,handleFsTransferFinish as ae,handleFsTransferStart as ne,handleFsExportMarkdownPdf as re,handleFsExportMarkdownPdfSetup as ie,handleFsArchiveZip as oe}from"./handlers/fs.js";import{handleRegionProbe as ce,handleRegionSwitch as le,handleUpgradeSetPolicy as ue}from"./handlers/control.js";import{ManagerRuntimeService as he,setManagerRuntimeService as h}from"../manager/runtime.js";import{ChatQueueManager as de}from"./queue.js";import{createAuthorizedFsRoot as me,createAuthorizedFsRootAsync as pe,resolveAuthorizedPath as ge,resolveAuthorizedPathAsync as fe,resolveSessionWorkDir as ve}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/shennian.js";import"../agents/manager.js";import{registerCustomAgent as ye}from"../agents/custom.js";import{listNodeAdapters as Re}from"../adapter-kit/registry.js";import{syncNodeAdapterAgents as be}from"../agents/node-adapter.js";import{bindManagedRoom as Se,handleManagedRoomBind as ke,handleManagedRoomRestart as Ae,discardPreBindingSession as we}from"./handlers/room-managed.js";import{getDaemonInstallationId as d,listSessionRecords as l,purgeCanonicalSession as Ie,purgeSessionRecord as Te,recordSession as Pe,upsertMessage as Ce}from"./store.js";import{requestSessionIndexPublish as m}from"./index-publisher.js";import{checkRunStalls as Me}from"./run-stall.js";import{reportUpgradeAggregateMetric as xe}from"../log-reporter.js";import{PersonalHistorySubscriptions as Fe}from"./history-subscriptions.js";import{startAttachmentCleanupLoop as De}from"./attachment-cleanup-loop.js";import{NativeSourceDeletionStore as Ee}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Qe}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as je}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as ze}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as c}from"../personal-sync/epoch.js";import{ActiveRunJournal as Oe}from"./run-recovery/journal.js";import{RunRecoveryBarrier as Be}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as He}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as We}from"./project-fs-store.js";import{handleProjectFsRequest as _e}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as Ue,handleAcpAgentRequest as Je}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as $e}from"./deletion-synchronizer.js";import{dispatchManagedChat as Le,dispatchQueuedChat as Ve,interruptQueuedChat as Ne}from"./queued-chat-dispatch.js";const Ge=50;import{resolveSessionWorkDir as nt}from"../fs/boundary.js";function Ke(){return"\u795E\u5FF5\u5347\u7EA7\u4E2D\u65AD\u4E86\u672C\u6B21\u8FD0\u884C\u3002\u5DF2\u5B8C\u6210\u7684\u56DE\u590D\u6216\u64CD\u4F5C\u4ECD\u7136\u6709\u6548\uFF0C\u672A\u5B8C\u6210\u90E8\u5206\u53EF\u91CD\u8BD5\u3002\u539F\u4F1A\u8BDD\u5DF2\u4FDD\u7559\u3002"}class st{client;nativeFusion;cliVersion;upgradePolicyController;managedRoomBinder;remoteAccessPauseController;managedRoomContextRevoker;managedRoomExecutor;trustedProjectFsRequestResolver;getAgentSnapshot;scheduleHandler;getScheduleQueue(){return this.chatQueue}sessions=new Map;processedReqIds=new Set;runTextAcc=new Map;pendingTransfers=new Map;managerRuntime;chatQueue;historySubscriptions;nativeCleanupOutbox;activityProbeTimer=null;stopAttachmentCleanup=null;activeRequests=0;acpDiscoveryWatcher;runJournal;recoveryBarrier=new Be;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new We;deletionSynchronizer;constructor(e,t=null,s,n=null,r=null,i=null,u=null,p=null,g=null,f=null,v=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=i,this.managedRoomContextRevoker=u,this.managedRoomExecutor=p,this.trustedProjectFsRequestResolver=f,this.getAgentSnapshot=v,this.runJournal=g??new Oe(d());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new He({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,o)=>H(this.getRuntime(),a,o),commitTerminal:(a,o)=>this.commitRecoveryTerminal(a,o),isCanonicalTerminal:a=>{const o=l().find(R=>R.sessionId===a.sessionId),y=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return o?.lastAttentionId===y},onOutcome:a=>xe({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 he({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new de({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,o)=>Le(this.getRuntime(),a,o),dispatchQueuedReq:(a,o)=>Ve(this.getRuntime(),a,o),interruptQueuedSession:a=>Ne(this.getRuntime(),a)}),this.deletionSynchronizer=new $e(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new Fe(this.client),this.nativeCleanupOutbox=new ze({logger:console.info}),this.acpDiscoveryWatcher=new x(async()=>{A(),await M(this.getRuntime())}),this.nativeFusion?.setExternalTerminalHandler?.(a=>{this.handleExternalTerminal(a)}),this.nativeFusion?.setExternalClaimHandler?.((a,o)=>{this.chatQueue.noteExternalClaim(a,o)}),this.nativeCleanupOutbox.start(),h(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(()=>{Me(this.sessions.entries(),()=>m(this.client)),this.publishManagedActivitySnapshots().catch(a=>{console.error("[session.activity] managed probe failed",a)})},15e3),this.activityProbeTimer.unref?.(),this.stopAttachmentCleanup=De({getRoots:()=>[...l().map(a=>this.resolvePath(a.workDir)),...Array.from(this.pendingTransfers.values()).map(a=>this.resolvePath(a.rootPath))],onError:a=>console.error("[attachment.cleanup] failed",a instanceof Error?a.message:String(a))})}executeManagedManagerAction(e){return this.managerRuntime.executeScopedWorkerAction(e.managerSessionId,e.action,e.params,e.roomOrigin)}noteManagedRoomSendOutcome(e){for(const t of this.sessions.values()){if(t.managedRoomContextToken!==e.token)continue;const s=t.roomSendOutcome??(t.roomSendOutcome={successes:0,failureCodes:[]});e.ok?s.successes+=1:s.failureCodes.length<20&&s.failureCodes.push(e.errorCode??"managed_room_action_failed");return}}getManagedRoomActiveRunId(e,t){const s=this.sessions.get(t);if(s?.currentRunId)return s.currentRunId;for(const n of this.sessions.values())if(n.managedRoomContextToken===e)return n.currentRunId??null;return null}getRuntime(){return{client:this.client,pendingTransfers:this.pendingTransfers,processedReqIds:this.processedReqIds,reloadCustomAgents:()=>this.reloadCustomAgents(),getAgentSnapshot:this.getAgentSnapshot??void 0,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}}bindManagedRoomFromLocal(e){return Se(this.getRuntime(),this.managedRoomBinder,e)}stewardSayFromLocal(e){const t=typeof e.sessionId=="string"?e.sessionId:"",s=typeof e.text=="string"?e.text:"";return t?V(this.getRuntime(),t,s):N(this.getRuntime(),s)}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=Ke();Ce(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})}),Pe({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}),m(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=l().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 we(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new Ee({daemonInstallationId:d()}),s=l().find(i=>i.sessionId===e.sessionId)?.codexSettings?.codexHome;let n=[];try{n=Qe(e.sessionId,{records:l()})}catch(i){console.warn("[session.deletions] local native source lookup failed",{error:i instanceof Error?i.message:String(i)})}t.recordSession(e);for(const i of[...e.sources,...n]){const u=t.find(i.agentType,i.sourceSessionKey);u&&u.sessionId!==e.sessionId||t.record({...e,...i})}this.runJournal.markSessionAborted(e.sessionId),this.recoveryBarrier.end(e.sessionId);const r=this.sessions.get(e.sessionId);if(r){this.revokeManagedRoomToken(r);try{await r.adapter.stop()}catch{}this.sessions.delete(e.sessionId)}this.historySubscriptions.closeSession(e.sessionId),this.nativeFusion?.handleSessionDeleted(e.sessionId),this.chatQueue.purgeSession(e.sessionId),je(e.sessionId),Ie(e.sessionId),Te(e.sessionId),this.runTextAcc.delete(e.sessionId),this.publishSessionActivity(e.sessionId,null),this.nativeCleanupOutbox.enqueue(e,s),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 S())t.startsWith("custom:")&&k(t);const e=w();for(const[t,s]of Object.entries(e.customAgents??{}))ye(t,s);be(Re(),new Set(Object.keys(e.customAgents??{})))}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 B(s,e);break;case"chat.enqueue":c(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.codex.settings.get":case"chat.codex.settings.set":z(s,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 O(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":L(s,e);break;case"session.title.set":await U(s,e);break;case"room.agent.bind-managed":await ke(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await Ae(s,this.managedRoomBinder,e);break;case"personal.recording":case"personal.workspace":case"project.taskEvent":case"personal.apps.list":case"personal.apps.register":case"personal.apps.remove":case"personal.service":await G(s,e);break;case"fs.ls":await Z(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await _e(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await Y(s,e);break;case"fs.write":await ee(s,e);break;case"fs.export.markdown-pdf":await re(s,e);break;case"fs.export.markdown-pdf.setup":await ie(s,e);break;case"fs.archive.zip":await oe(s,e);break;case"fs.rename":await q(s,e);break;case"fs.transfer.start":await ne(s,e);break;case"fs.transfer.chunk":await te(s,e);break;case"fs.transfer.finish":await ae(s,e);break;case"fs.transfer.abort":await se(s,e);break;case"region.probe":await ce(s,e);break;case"region.switch":await le(s,e);break;case"upgrade.start":await I(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 T(this.client,e.id,{currentVersion:this.cliVersion});break;case"upgrade.set-policy":await ue(s,e);break;case"machine.remote-access.pause":await K(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await Ue(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 Je(s,e);break;case"models.refresh":await C(s,e);break;case"agent.config.get":await E(s,e);break;case"agent.config.upsert":await j(s,e);break;case"agent.config.clear":await D(s,e);break;case"agent.config.test":await Q(s,e);break;case"agent.workspace.validate":await $(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<Ge)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 ve(e)}resolveAuthorizedPath(e,t){return ge(e,me(t))}async resolveAuthorizedPathAsync(e,t){return fe(e,await pe(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.stopAttachmentCleanup?.(),this.stopAttachmentCleanup=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(),X(this.getRuntime()),await this.managerRuntime.stop(),h(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{st as SessionManager,nt as resolveSessionWorkDir,Ke as upgradeRecoveryVisibleMessage};
|