shennian 0.5.1 → 0.5.2
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 +17 -27
- package/dist/src/agents/acp/adapter.js +2 -2
- package/dist/src/agents/model-registry/discovery.js +3 -3
- package/dist/src/agents/model-registry/service.js +1 -1
- package/dist/src/agents/model-registry.js +1 -1
- package/dist/src/agents/pi-coding-agent.js +3 -4
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
- package/dist/src/session/handlers/chat-events.js +2 -2
- package/dist/src/session/manager.js +1 -1
- package/package.json +1 -1
- package/dist/src/agents/pi-managed-model-broker.js +0 -1
- package/dist/src/session/handlers/pi-validation-session.js +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 234,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian.js",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"file": "src/agents/acp/adapter.js",
|
|
19
|
-
"beforeBytes":
|
|
20
|
-
"afterBytes":
|
|
19
|
+
"beforeBytes": 26392,
|
|
20
|
+
"afterBytes": 13813
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"file": "src/agents/acp/auth-state.js",
|
|
@@ -206,8 +206,8 @@
|
|
|
206
206
|
},
|
|
207
207
|
{
|
|
208
208
|
"file": "src/agents/model-registry/discovery.js",
|
|
209
|
-
"beforeBytes":
|
|
210
|
-
"afterBytes":
|
|
209
|
+
"beforeBytes": 11107,
|
|
210
|
+
"afterBytes": 5219
|
|
211
211
|
},
|
|
212
212
|
{
|
|
213
213
|
"file": "src/agents/model-registry/opencode-api.js",
|
|
@@ -226,8 +226,8 @@
|
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
"file": "src/agents/model-registry/service.js",
|
|
229
|
-
"beforeBytes":
|
|
230
|
-
"afterBytes":
|
|
229
|
+
"beforeBytes": 8864,
|
|
230
|
+
"afterBytes": 3358
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
233
|
"file": "src/agents/model-registry/types.js",
|
|
@@ -236,8 +236,8 @@
|
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
"file": "src/agents/model-registry.js",
|
|
239
|
-
"beforeBytes":
|
|
240
|
-
"afterBytes":
|
|
239
|
+
"beforeBytes": 986,
|
|
240
|
+
"afterBytes": 928
|
|
241
241
|
},
|
|
242
242
|
{
|
|
243
243
|
"file": "src/agents/native-capabilities.js",
|
|
@@ -266,19 +266,14 @@
|
|
|
266
266
|
},
|
|
267
267
|
{
|
|
268
268
|
"file": "src/agents/pi-coding-agent.js",
|
|
269
|
-
"beforeBytes":
|
|
270
|
-
"afterBytes":
|
|
269
|
+
"beforeBytes": 22758,
|
|
270
|
+
"afterBytes": 12494
|
|
271
271
|
},
|
|
272
272
|
{
|
|
273
273
|
"file": "src/agents/pi-managed-extension.js",
|
|
274
274
|
"beforeBytes": 10227,
|
|
275
275
|
"afterBytes": 9273
|
|
276
276
|
},
|
|
277
|
-
{
|
|
278
|
-
"file": "src/agents/pi-managed-model-broker.js",
|
|
279
|
-
"beforeBytes": 8635,
|
|
280
|
-
"afterBytes": 4663
|
|
281
|
-
},
|
|
282
277
|
{
|
|
283
278
|
"file": "src/agents/pi-rpc-client.js",
|
|
284
279
|
"beforeBytes": 5326,
|
|
@@ -896,8 +891,8 @@
|
|
|
896
891
|
},
|
|
897
892
|
{
|
|
898
893
|
"file": "src/session/handlers/agent-workspace-validation.js",
|
|
899
|
-
"beforeBytes":
|
|
900
|
-
"afterBytes":
|
|
894
|
+
"beforeBytes": 9136,
|
|
895
|
+
"afterBytes": 4977
|
|
901
896
|
},
|
|
902
897
|
{
|
|
903
898
|
"file": "src/session/handlers/agents.js",
|
|
@@ -916,8 +911,8 @@
|
|
|
916
911
|
},
|
|
917
912
|
{
|
|
918
913
|
"file": "src/session/handlers/chat-events.js",
|
|
919
|
-
"beforeBytes":
|
|
920
|
-
"afterBytes":
|
|
914
|
+
"beforeBytes": 18625,
|
|
915
|
+
"afterBytes": 7583
|
|
921
916
|
},
|
|
922
917
|
{
|
|
923
918
|
"file": "src/session/handlers/chat-recovery.js",
|
|
@@ -949,11 +944,6 @@
|
|
|
949
944
|
"beforeBytes": 676,
|
|
950
945
|
"afterBytes": 392
|
|
951
946
|
},
|
|
952
|
-
{
|
|
953
|
-
"file": "src/session/handlers/pi-validation-session.js",
|
|
954
|
-
"beforeBytes": 2016,
|
|
955
|
-
"afterBytes": 1147
|
|
956
|
-
},
|
|
957
947
|
{
|
|
958
948
|
"file": "src/session/handlers/project-fs.js",
|
|
959
949
|
"beforeBytes": 3778,
|
|
@@ -1006,8 +996,8 @@
|
|
|
1006
996
|
},
|
|
1007
997
|
{
|
|
1008
998
|
"file": "src/session/manager.js",
|
|
1009
|
-
"beforeBytes":
|
|
1010
|
-
"afterBytes":
|
|
999
|
+
"beforeBytes": 40313,
|
|
1000
|
+
"afterBytes": 21179
|
|
1011
1001
|
},
|
|
1012
1002
|
{
|
|
1013
1003
|
"file": "src/session/native-cleanup-outbox.js",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{randomUUID as
|
|
1
|
+
import{randomUUID as g}from"node:crypto";import{createHash as f}from"node:crypto";import{realpathSync as y}from"node:fs";import{pathToFileURL as v}from"node:url";import*as l from"@agentclientprotocol/sdk";import{RequestError as C}from"@agentclientprotocol/sdk";import{AgentAdapter as A,registerAgent as P}from"../adapter.js";import{mapAcpSessionUpdate as q}from"./events.js";import{AcpProcessClient as E}from"./process-client.js";import{acpAgentType as S}from"./types.js";import{runAcpTerminalAuthentication as b}from"./auth.js";import{setAcpRuntimeAuthState as d}from"./auth-state.js";import{recordAcpAuthFailure as x,recordAcpImportResult as I}from"./metrics.js";import{isManagedAgentNativeFull as w}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as O}from"../../agent-env.js";function p(c,e){return c.find(t=>t.category===e&&t.type==="select")}function m(c){return(c?.options??[]).flatMap(e=>"options"in e?e.options:[e])}class T extends A{manifest;options;type;get recoveryCapabilities(){const e=this.client?.capabilities;return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!!(e?.sessionCapabilities?.resume||e?.loadSession)}}client=null;workDir="";shennianSessionId="";requestedSessionId=null;agentSessionId=null;runId="";seq=0;active=!1;extraEnv={};pendingPermissions=new Map;configOptions=[];modes=null;importCapture=null;emittedToolStates=new Map;pendingAuthRetry=null;retryingAfterAuth=!1;managedAgentPolicy=null;configurationSignature="";startedConfigurationSignature="";constructor(e,t={}){super(),this.manifest=e,this.options=t,this.type=S(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.configurationSignature=f("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[n])=>t.localeCompare(n)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}async start(e,t,n){this.shennianSessionId=e;try{this.workDir=y.native(t)}catch{this.workDir=t}this.requestedSessionId=n??null,this.agentSessionId=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}async send(e,t,n,i,s){await this.refreshProcessConfiguration();const a=this.requireClient();this.runId=g(),this.seq=0,this.emittedToolStates.clear();try{await this.ensureSession(),await this.applyDynamicConfig(t,n),this.active=!0,this.emitEvent({state:"start",runPhase:"thinking",agentSessionId:this.agentSessionId??void 0});const o=[],r=[];s?.trim()&&r.push(s.trim()),r.push(e),o.push({type:"text",text:r.join(`
|
|
2
2
|
|
|
3
|
-
`)});for(const h of i??[])r.push({type:"resource_link",uri:I(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const c=await this.promptWithTimeout(o,r);this.active=!1,c.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(r){this.active=!1,this.cancelPendingPermissions();const a=r instanceof Error?r.message:String(r),c=r instanceof w&&r.code===-32e3;throw c&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...s?{reasoningEffort:s}:{},...i?{attachments:[...i]}:{},...n!==void 0?{systemPrompt:n}:{}})),this.emitEvent({state:"error",message:a,...c?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),r}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const s=this.pendingPermissions.get(e);if(!s)throw new Error("ACP permission request is no longer pending");if(!s.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(s.timer),s.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=this.configOptions.find(o=>o.category==="model"&&o.type==="select"),t=this.configOptions.find(o=>o.category==="thought_level"&&o.type==="select"),s=this.modes?.availableModes.map(o=>({id:o.id,name:o.name,...o.description?{description:o.description}:{}}))??[],i=o=>(o?.options??[]).flatMap(r=>"options"in r?r.options:[r]),n=(t?i(t):s).map(o=>({id:"value"in o?o.value:o.id,name:o.name,...o.description?{description:o.description}:{}}));return{models:i(e).map(o=>({id:o.value,name:o.name,...o.description?{description:o.description}:{},...o.value===e?.currentValue?{isDefault:!0}:{},...n.length?{supportedReasoningEfforts:n}:{}})),modes:s}}async authenticate(e,t={}){const s=this.requireClient(),i=s.initializeResponse?.authMethods?.find(n=>n.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await s.close(),await q({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(n=>typeof n[1]=="string"))},i,this.workDir)}else await s.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(n){throw E(),n}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const s=[];let i;for(let n=0;n<10&&s.length<500;n+=1){let o=e.cwd;if(o)try{o=g.native(o)}catch{}const r=await t.listSessions(o,i);if(s.push(...r.sessions.slice(0,500-s.length).map(a=>({agentSessionId:a.sessionId,cwd:a.cwd,...a.title?{title:a.title.slice(0,200)}:{},...a.updatedAt?{updatedAt:a.updatedAt}:{}}))),i=r.nextCursor,!i)break}return s}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const s=[];this.importCapture=s;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,y(!0)}catch(i){throw y(!1),i}finally{this.importCapture=null}return s.map((i,n)=>({sourceId:i.sourceHint??m("sha256").update(`${e}\0${n}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const s=e.capabilities;if(s.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(s.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId;return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const s=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of s){if(!i.value)continue;const n=this.configOptions.find(o=>o.category===i.category&&o.type==="select");!n||n.currentValue===i.value||(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:n.id,value:i.value}),n.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of A(e.update,s=>this.makeEvent(s)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,s=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,n=i?this.importCapture.find(o=>o.sourceHint===i):this.importCapture.at(-1);n?.role===s&&n.sourceHint===i?n.payload+=t:this.importCapture.push({role:s,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,s=this.importCapture.find(n=>n.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};s?s.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),s=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=s:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:s})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=p();return new Promise(s=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),s({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(n=>n.optionId)),resolve:s,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(n=>({id:n.optionId,name:n.name,kind:n.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new P(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?S(this.managedAgentPolicy)?b(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?S(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let s;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,n)=>{s=setTimeout(()=>n(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),s.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{s&&clearTimeout(s)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function J(u){v(f(u.id),()=>new x(u))}export{x as AcpAgentAdapter,J as registerAcpAgent};
|
|
3
|
+
`)});for(const h of i??[])o.push({type:"resource_link",uri:v(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const u=await this.promptWithTimeout(a,o);this.active=!1,u.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(o){this.active=!1,this.cancelPendingPermissions();const r=o instanceof Error?o.message:String(o),u=o instanceof C&&o.code===-32e3;throw u&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...n?{reasoningEffort:n}:{},...i?{attachments:[...i]}:{},...s!==void 0?{systemPrompt:s}:{}})),this.emitEvent({state:"error",message:r,...u?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),o}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const n=this.pendingPermissions.get(e);if(!n)throw new Error("ACP permission request is no longer pending");if(!n.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(n.timer),n.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=p(this.configOptions,"model"),t=p(this.configOptions,"thought_level"),n=this.modes?.availableModes.map(s=>({id:s.id,name:s.name,...s.description?{description:s.description}:{}}))??[],i=(t?m(t):n).map(s=>({id:"value"in s?s.value:s.id,name:s.name,...s.description?{description:s.description}:{}}));return{models:m(e).map(s=>({id:s.value,name:s.name,...s.description?{description:s.description}:{},...s.value===e?.currentValue?{isDefault:!0}:{},...i.length?{supportedReasoningEfforts:i}:{}})),modes:n}}async authenticate(e,t={}){const n=this.requireClient(),i=n.initializeResponse?.authMethods?.find(s=>s.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await n.close(),await b({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(s=>typeof s[1]=="string"))},i,this.workDir)}else await n.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(s){throw x(),s}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const n=[];let i;for(let s=0;s<10&&n.length<500;s+=1){let a=e.cwd;if(a)try{a=y.native(a)}catch{}const o=await t.listSessions(a,i);if(n.push(...o.sessions.slice(0,500-n.length).map(r=>({agentSessionId:r.sessionId,cwd:r.cwd,...r.title?{title:r.title.slice(0,200)}:{},...r.updatedAt?{updatedAt:r.updatedAt}:{}}))),i=o.nextCursor,!i)break}return n}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const n=[];this.importCapture=n;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,I(!0)}catch(i){throw I(!1),i}finally{this.importCapture=null}return n.map((i,s)=>({sourceId:i.sourceHint??f("sha256").update(`${e}\0${s}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const n=e.capabilities;if(n.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(n.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId,this.emit("sessionOptions");return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null,this.emit("sessionOptions")}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const n=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of n){if(!i.value)continue;const s=p(this.configOptions,i.category);!s||s.currentValue===i.value||m(s).some(a=>a.value===i.value)&&(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:s.id,value:i.value}),s.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of q(e.update,n=>this.makeEvent(n)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,n=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,s=i?this.importCapture.find(a=>a.sourceHint===i):this.importCapture.at(-1);s?.role===n&&s.sourceHint===i?s.payload+=t:this.importCapture.push({role:n,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,n=this.importCapture.find(s=>s.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};n?n.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),n=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=n:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:n})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=g();return new Promise(n=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),n({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(s=>s.optionId)),resolve:n,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(s=>({id:s.optionId,name:s.name,kind:s.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new E(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?w(this.managedAgentPolicy)?O(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?w(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let n;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,s)=>{n=setTimeout(()=>s(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),n.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{n&&clearTimeout(n)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function L(c){P(S(c.id),()=>new T(c))}export{T as AcpAgentAdapter,L as registerAcpAgent};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createInterface as
|
|
2
|
-
`,
|
|
3
|
-
${
|
|
1
|
+
import{createInterface as _}from"node:readline";import{resolveBuiltinCommand as l,spawnResolvedCommand as w}from"../command-spec.js";import{fallbackClaudeAliasModels as E,discoverClaudeAliasModelsFromEnv as k,fallbackCodexModels as h,fallbackWorkBuddyModels as x,fallbackGeminiModels as R,parseCodexAppServerModels as O,parseCursorModels as A,parseOpenCodeModels as I}from"./parsers.js";import{runResolvedCommand as f}from"./runner.js";import{DISCOVERY_WORKDIR as M,ModelDiscoveryFallbackError as b}from"./types.js";import{buildAgentProcessEnv as C,readLatestUserEnv as P}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as S}from"../codex-utils.js";import{PiRpcClient as T}from"../pi-rpc-client.js";import{discoverOpenCodeModelsViaApi as $}from"./opencode-api.js";function D(r){const e=r instanceof Error?r.message:"";return/timed out/i.test(e)?"app_server_timeout":/\berror\b|invalid|unsupported|unknown (?:method|field)/i.test(e)?"app_server_rpc_error":"app_server_unavailable"}function m(r,e,t,n,s,i){return r.stdin?new Promise((o,a)=>{const p=setTimeout(()=>{e.delete(t),a(new Error(`codex app-server request timed out: ${n}`))},i);e.set(t,{resolve:o,reject:a,timer:p}),r.stdin.write(`${JSON.stringify({id:t,method:n,params:s})}
|
|
2
|
+
`,c=>{c&&(clearTimeout(p),e.delete(t),a(c))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function L(r){const e=w(r,["app-server","--listen","stdio://"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new Map;let n=1;_({input:e.stdout}).on("line",i=>{if(!i.trim())return;let o;try{o=JSON.parse(i)}catch{return}if(o.id==null)return;const a=t.get(o.id);a&&(clearTimeout(a.timer),t.delete(o.id),o.error?a.reject(new Error(o.error.message||`codex app-server error ${o.error.code??""}`.trim())):a.resolve(o.result))});try{await m(e,t,n++,"initialize",{clientInfo:S,capabilities:{experimentalApi:!0}},1e4);const[i,o]=await Promise.all([m(e,t,n++,"model/list",{},15e3),m(e,t,n++,"config/read",{},15e3).catch(()=>null)]),a=typeof o=="object"&&o!==null&&"config"in o?o.config:void 0;return O({...typeof i=="object"&&i!==null?i:{},config:a})}finally{for(const[i,o]of t)clearTimeout(o.timer),o.reject(new Error("codex app-server stopped")),t.delete(i);e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function q(){const r=l("cursor");if(!r)return[];const e=await f(r,["--list-models"]);return A(e.stdout)}async function j(){const r=l("opencode");if(!r)return[];const e=await $().catch(()=>[]);if(e.length>0)return e;const t=await f(r,["models"]);return I(t.stdout)}async function G(){const r=l("pi-coding-agent");if(!r)return[];const e=w(r,["--mode","rpc","--no-session","--offline","--no-extensions","--no-skills","--no-prompt-templates","--no-context-files","--no-tools"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new T(e,{requestTimeoutMs:1e4});try{const[n,s]=await Promise.all([t.request("get_available_models"),t.request("get_state")]),i=n.data&&typeof n.data=="object"?n.data:{},o=s.data&&typeof s.data=="object"?s.data:{},a=typeof o.model?.id=="string"&&typeof o.model.provider=="string"?`${o.model.provider}/${o.model.id}`:null;return Array.isArray(i.models)?i.models.flatMap(c=>{if(!c||typeof c!="object")return[];const d=c;if(typeof d.id!="string"||typeof d.provider!="string")return[];const v=`${d.provider}/${d.id}`,y=d.reasoning===!0?["off","minimal","low","medium","high","xhigh","max"].map(g=>({id:g,name:g})):void 0;return[{id:v,name:typeof d.name=="string"&&d.name.trim()?d.name:d.id,provider:d.provider,isDefault:v===a,...y?{supportedReasoningEfforts:y,defaultReasoningEffort:"medium"}:{}}]}):[]}catch{return[]}finally{t.close(),e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function N(){const r=l("claude");if(!r)return[];const e=P(),t=k(e);if(t.length>0)return t;const n=E(e),s=await f(r,["--help"],3e3).catch(()=>null);return!s||/\bfable\b/i.test(`${s.stdout}
|
|
3
|
+
${s.stderr}`)?n:n.filter(i=>i.id!=="fable")}async function F(){const r=l("codex");if(!r)return[];let e;try{e=await L(r)}catch(t){throw new b("codex",D(t),h())}if(e.length===0)throw new b("codex","empty_model_list",h());return e}async function B(){return l("gemini")?R():[]}const u=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0}],V=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function W(r){if(!r.serverUrl||!r.authToken)return u;try{const e=await fetch(`${r.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${r.authToken}`}});if(!e.ok)return u;const t=await e.json(),n=(t.models??[]).map(s=>({id:s.id,name:s.name?.trim()||s.id,provider:s.provider,isDefault:s.id===t.default}));return n.length>0?n:u}catch{return u}}async function K(r,e){switch(r){case"claude":return N();case"codex":return F();case"workbuddy":return l("workbuddy")?x():[];case"gemini":return B();case"cursor":return q();case"openclaw":return[];case"opencode":return j();case"pi":return W(e);case"pi-coding-agent":return G();case"manager":return V}}async function re(r,e){return r.type.startsWith("custom:")?r.models??[]:r.type.startsWith("acp:")?[]:K(r.type,e)}export{re as discoverModelsForAgent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAgentConfigSummary as
|
|
1
|
+
import{getAgentConfigSummary as v}from"../config-status.js";import{isCacheFresh as M,readCache as f,writeCache as g}from"./cache.js";import{discoverModelsForAgent as b}from"./discovery.js";import{ModelDiscoveryFallbackError as x}from"./types.js";import{getAgentRuntimeSummary as C}from"../runtime-compatibility.js";import{isRestrictedRoomChatUnsupported as F,resolveManagedAgentRuntimeProtection as w}from"../../security/managed-agent-runtime.js";const E={claude:"claude-alias-v2",codex:"codex-app-server-v2",opencode:"opencode-connected-v1"};function O(t,s,e){console.warn(`[model-discovery] agent=${t} source=fallback reason=${s} usedCache=${e}`)}function A(t){const s=new Set,e=[];for(const r of t)!r.id||s.has(r.id)||(s.add(r.id),e.push(r));return e}function S(t){const s=t.type!=="manager"&&t.type!=="pi"&&t.type!=="openclaw",e=s,r=e&&!t.type.startsWith("acp:"),i=e?w({agentType:t.type,runtimeVersion:t.version,platform:t.runtimePlatform,isWsl:t.runtimeIsWsl,executableFingerprint:t.executableFingerprint,requireExecutableFingerprint:!0}):null,p=r&&!F(t.type)&&(i?.level==="hard"||i?.level==="partial"),o=e,n=p||o,a=s;return{supportsStandardSession:s,supportsManagedAgent:p,supportsManagedNativeFull:o,supportsRoomTools:n,supportsWorker:a,supportsManagerMode:n&&a,supportsExternalWorkerTarget:a,...i?{managedAgentProtection:i}:{}}}function R(t,s){return t.type==="opencode"&&(!t.authState||t.authState==="unknown")&&s.length>0?{authState:"ready"}:t.authState?{authState:t.authState}:{}}function P(t,s){if(!t.startsWith("acp:"))return!1;const e=A(s);if(e.length===0)return!1;const r=f(),i=r.agents[t];return JSON.stringify(i?.models)===JSON.stringify(e)?!1:(r.agents[t]={refreshedAt:Date.now(),models:e},g(r),!0)}function V(t){const s=f();return t.map(e=>{const r=v(e.type),i=C(e);return{type:e.type,models:s.agents[e.type]?.models??e.models??[],...e.integration?{integration:e.integration}:{},...e.display?{display:e.display}:{},...e.acpCapabilities?{acpCapabilities:e.acpCapabilities}:{},...R(e,s.agents[e.type]?.models??e.models??[]),...e.acpAuthMethods?{acpAuthMethods:e.acpAuthMethods}:{},...e.catalogRevision?{catalogRevision:e.catalogRevision}:{},...S(e),...r?{config:r}:{},...i?{runtime:i}:{}}})}async function _(t,s){return k(t,s,{forceRefresh:!0})}async function k(t,s,e={}){const r=f();let i=!1;const p=[];for(const o of t){const n=r.agents[o.type],a=E[o.type],u=n&&(!a||n.sourceRevision===a)?n:void 0;let c;if(!e.forceRefresh&&M(n,o.version,a))c=n.models;else{let d=null;try{d=A(await b(o,s)),c=d.length>0?d:u?.models??o.models??[]}catch(l){if(l instanceof x){const y=!!u?.models.length;c=y?u.models:l.fallbackModels,O(o.type,l.failureCode,y)}else c=u?.models??o.models??[]}if(d&&d.length>0){const l={version:o.version,...a?{sourceRevision:a}:{},refreshedAt:Date.now(),models:c};JSON.stringify(n)!==JSON.stringify(l)&&(r.agents[o.type]=l,i=!0)}}const h=v(o.type),m=C(o);p.push({type:o.type,models:c,...o.integration?{integration:o.integration}:{},...o.display?{display:o.display}:{},...o.acpCapabilities?{acpCapabilities:o.acpCapabilities}:{},...R(o,c),...o.acpAuthMethods?{acpAuthMethods:o.acpAuthMethods}:{},...o.catalogRevision?{catalogRevision:o.catalogRevision}:{},...S(o),...h?{config:h}:{},...m?{runtime:m}:{}})}return i&&g(r),p}export{V as getCachedAgentInfos,P as recordAcpAgentModels,_ as refreshAgentInfos,k as resolveAgentInfos};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCachedAgentInfos as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as
|
|
1
|
+
import{getCachedAgentInfos as g,recordAcpAgentModels as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as r,parseClaudeBinaryModels as l,parseClaudeModels as d,parseCodexModels as a,parseCodexAppServerModels as p,parseCursorModels as n,parseGeminiModels as t,parseOpenClawModels as i,stripAnsi as M}from"./model-registry/parsers.js";const A={applyClaudeModelEnvOverrides:e,discoverClaudeAliasModelsFromEnv:s,fallbackCodexModels:o,fallbackClaudeAliasModels:r,parseClaudeBinaryModels:l,parseClaudeModels:d,parseCodexModels:a,parseCodexAppServerModels:p,parseCursorModels:n,parseOpenClawModels:i,parseGeminiModels:t,stripAnsi:M};export{g as getCachedAgentInfos,A as modelSwitchingTestExports,m as recordAcpAgentModels,u as refreshAgentInfos,v as resolveAgentInfos};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
[truncated]`}function
|
|
3
|
-
`)}`}function E(n,t){const s=[];for(const e of n??[]){if(e.kind!=="image"||!e.mimeType.startsWith("image/"))continue;let i=e.previewData?.trim()??"";const a=i.indexOf(",");if(i.startsWith("data:")&&a>=0&&(i=i.slice(a+1)),!i&&t&&e.path&&!/^https?:\/\//i.test(e.path))try{const l=h.statSync(e.path);l.isFile()&&l.size<=10*1024*1024&&(i=h.readFileSync(e.path).toString("base64"))}catch{i=""}i&&s.push({type:"image",data:i,mimeType:e.mimeType})}return s}class W extends v{type="pi-coding-agent";get supportsActiveInput(){return!0}async injectActiveInput(t){const s=await this.readState();if(!this.rpc||!this.runId||!s.isStreaming&&!s.isCompacting)throw new Error("pi_active_turn_unavailable");const e={message:I(t.text,t.attachments,this.workDir,this.externalChannel,this.shennianSessionId,null)},i=E(t.attachments,!this.managedAgentPolicy);i.length&&!this.modelBroker&&(e.images=i),await this.rpc.request("steer",e)}get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;rpc=null;shennianSessionId="";workDir="";sessionDir="";agentSessionId=null;externalChannel=null;extraEnv={};spawnedRoomContext=null;managedAgentPolicy=null;runId="";seq=0;active=!1;terminal=!0;stderr="";lastUsage;promptFile=null;modelBroker=null;persistNativeSession=!0;validationRoot=null;runPhase=null;configure(t){t.sessionId&&(this.shennianSessionId=t.sessionId),this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null)}async start(t,s,e,i){await this.stopProcess(),this.shennianSessionId=t,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.agentSessionId=e??null;const a=f("runtime","pi-coding-agent",g(t));this.persistNativeSession=i?.persistNativeSession!==!1,this.validationRoot=this.persistNativeSession?null:u.join(a,`validation-${w()}`),this.sessionDir=this.validationRoot?u.join(this.validationRoot,"sessions"):u.join(a,"sessions"),h.mkdirSync(this.sessionDir,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(this.sessionDir,448),this.active=!1,this.terminal=!0}async send(t,s,e,i,a,l){await this.ensureProcess(a);const c=this.requireRpc(),p=await this.readState(),o=!!(p.isStreaming||p.isCompacting);(!o||!this.runId)&&(this.runId=w(),this.seq=0,this.terminal=!1,this.lastUsage=void 0,this.runPhase="thinking");const d=K(s);if(d.modelId&&!o&&(p.model?.id!==d.modelId||d.provider&&p.model?.provider!==d.provider)){if(!d.provider)throw new Error("Pi model selection must include provider/modelId");await c.request("set_model",{provider:d.provider,modelId:d.modelId})}e&&!o&&await c.request("set_thinking_level",{level:e});const r=o?l?.source==="room_activation"?"follow_up":"steer":"prompt",m={message:I(t,i,this.workDir,this.externalChannel,this.shennianSessionId,null)},S=E(i,!this.managedAgentPolicy);S.length&&!this.modelBroker&&(m.images=S),this.modelBroker?.setTurnActive(!0);try{await c.request(r,m)}catch(A){throw this.modelBroker?.setTurnActive(!1),A}}async resume(t){await this.stopProcess(),this.agentSessionId=t}async stop(){const t=this.rpc;t&&(await t.request("clear_queue").catch(()=>{}),await t.request("abort").catch(()=>{})),!this.terminal&&this.runId&&this.emitTerminal({state:"aborted"}),await this.stopProcess()}async getStatus(){if(!this.rpc||!this.process)return{active:!1,runId:null,canStop:!1};const t=await this.readState().catch(()=>null),s=!!(t?.isStreaming||t?.isCompacting||this.active);return{active:s,runId:s?this.runId:null,runPhase:s?this.runPhase??"thinking":null,canStop:s}}async setTitle(t,s){this.rpc&&await this.rpc.request("set_session_name",{name:s.slice(0,200)})}async ensureProcess(t){if(this.process&&this.rpc){if(!await this.roomContextStale())return;await this.stopProcess()}const s=k("pi-coding-agent");if(!s)throw new Error('Command "pi" not found. Install @earendil-works/pi-coding-agent from the official package.');const e=["--mode","rpc","--session-dir",this.sessionDir,"--offline"];this.agentSessionId&&e.push("--session",this.agentSessionId);const i=await this.prepareHostedModel();if(i&&e.push("--provider","shennian-dashscope","--model","deepseek-v4-flash-0731"),this.managedAgentPolicy&&!P(this.managedAgentPolicy)){e.push("--no-extensions","--no-skills","--no-prompt-templates","--no-context-files");const r=this.managedTools(),m=F({outputPath:u.join(f("runtime","pi-coding-agent",g(this.shennianSessionId)),"managed-extension.ts"),policy:this.managedAgentPolicy,allowRoomControl:!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT,allowManagerControl:!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,allowHostShell:this.managedAgentPolicy.adapterPolicy.fileAccess==="host-full"});e.push("--no-builtin-tools","--extension",m),r.length?e.push("--tools",r.join(",")):e.push("--no-tools")}const a=D(this.workDir,this.externalChannel,this.shennianSessionId,t),l=this.validationRoot??f("runtime","pi-coding-agent",g(this.shennianSessionId));h.mkdirSync(l,{recursive:!0,mode:448}),this.promptFile=u.join(l,"instructions.md"),h.writeFileSync(this.promptFile,a,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(this.promptFile,384),e.push("--append-system-prompt",this.promptFile);const c={NO_COLOR:"1",...i?{PI_CODING_AGENT_DIR:i.configDir}:{}},p=this.managedAgentPolicy&&!P(this.managedAgentPolicy)?T({agentType:this.type,providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:c}):this.managedAgentPolicy?C({...c,...this.extraEnv}):N({...c,...this.extraEnv});let o;try{o=R(s,e,{cwd:this.workDir,stdio:["pipe","pipe","pipe"],env:p})}catch(r){throw await this.stopModelBroker(),r}this.process=o,this.spawnedRoomContext=this.currentRoomContext(),this.stderr="",o.stderr?.on("data",r=>{const m=typeof r=="string"?r:r.toString("utf8");this.stderr=y(`${this.stderr}${m}`,$)});const d=new B(o);this.rpc=d,d.on("event",r=>this.handleRpcEvent(r)),d.on("protocolError",r=>this.emitError(r.message)),o.once("close",r=>{this.process===o&&(this.process=null,this.rpc=null,this.terminal||this.emitError(r===0?"Pi RPC process closed before agent_settled":`Pi RPC process exited with code ${r??"unknown"}${this.stderr?`: ${this.stderr}`:""}`),this.stopModelBroker())}),o.once("error",r=>{this.process===o&&this.emitError(r.message)});try{const r=await this.readState();if(!r.sessionId)throw new Error("Pi RPC did not return a session ID");if(r.isStreaming||r.isCompacting)throw new Error("Pi RPC session is not idle after startup");if(this.agentSessionId&&r.sessionId!==this.agentSessionId)throw new Error("Pi RPC resumed a different session");if(!r.sessionFile||!this.ownsSessionFile(r.sessionFile))throw new Error("Pi RPC returned a session file outside the Shennian-owned directory");this.agentSessionId=r.sessionId,this.persistNativeSession&&U(r.sessionId,this.sessionDir)}catch(r){throw await this.stopProcess(),r}}currentRoomContext(){return this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT??null}async roomContextStale(){if(this.currentRoomContext()===this.spawnedRoomContext)return!1;const t=await this.readState().catch(()=>null);return!t?.isStreaming&&!t?.isCompacting}managedTools(){const t=this.managedAgentPolicy?.adapterPolicy;if(!t)return[];const s=["read","grep","find","ls"];(t.fileAccess==="workspace-write"||t.fileAccess==="host-full")&&s.push("edit","write");const e=!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,i=!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT;return(e||i||t.fileAccess==="host-full")&&s.push("bash"),s}ownsSessionFile(t){const s=u.resolve(this.sessionDir),e=u.resolve(t),i=u.relative(s,e);return i!==""&&!i.startsWith("..")&&!u.isAbsolute(i)}async readState(){const t=await this.requireRpc().request("get_state");return z(t)}requireRpc(){if(!this.rpc)throw new Error("Pi RPC process is not running");return this.rpc}handleRpcEvent(t){if(t.type==="agent_start"){this.active=!0,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:this.agentSessionId??void 0});return}if(t.type==="message_update"){this.lastUsage=_(t.usage)??this.lastUsage;const s=t.assistantMessageEvent;if(!s||typeof s!="object")return;const e=s;e.type==="text_delta"&&typeof e.delta=="string"?(this.runPhase="streaming_text",this.emitEvent({state:"delta",text:e.delta})):e.type==="thinking_delta"&&typeof e.delta=="string"&&(this.runPhase="thinking",this.emitEvent({state:"delta",text:e.delta,thinking:!0}));return}if(t.type==="tool_execution_start"){this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:typeof t.toolName=="string"?t.toolName:"tool",args:t.args&&typeof t.args=="object"&&!Array.isArray(t.args)?t.args:{}});return}if(t.type==="tool_execution_end"){this.runPhase="thinking",this.emitEvent({state:"tool-result",name:typeof t.toolName=="string"?t.toolName:"tool",result:X(t.result)||Z(t.result)});return}if(t.type==="tool_execution_update"){this.emitEvent({state:"notify",runPhase:"tool_running",message:"Pi tool is running"});return}if(t.type==="message_end"){const s=t.message;if(s&&typeof s=="object"){const e=s;this.lastUsage=_(e.usage)??this.lastUsage,e.stopReason==="error"&&(this.modelBroker?.setTurnActive(!1),this.emitError(typeof e.errorMessage=="string"?e.errorMessage:"Pi model request failed"))}return}if(t.type==="compaction_start"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is compacting context"});return}if(t.type==="auto_retry_start"||t.type==="summarization_retry_scheduled"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is retrying"});return}if(t.type==="extension_ui_request"){typeof t.id=="string"&&this.rpc?.notify("extension_ui_response",{id:t.id,cancelled:!0});return}if(t.type==="extension_error"){this.modelBroker?.setTurnActive(!1),this.emitError(typeof t.error=="string"?t.error:"Pi extension failed");return}t.type==="agent_settled"&&(this.active=!1,this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.lastUsage}))}emitEvent(t){this.runId&&this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}emitTerminal(t){this.terminal||(this.terminal=!0,this.active=!1,this.runPhase=null,this.emitEvent(t))}emitError(t){this.modelBroker?.setTurnActive(!1),this.emitTerminal({state:"error",message:L(t)})}async prepareHostedModel(){const t=b(),s=t.machineToken?.trim();if(!s)return null;const e=new q({serverUrl:t.serverUrl?.trim()||"https://shennian.net",machineToken:s,sessionId:this.shennianSessionId}),i=await e.start(),a=this.validationRoot?u.join(this.validationRoot,"agent-config"):f("runtime","pi-coding-agent",g(this.shennianSessionId),"agent-config");h.mkdirSync(a,{recursive:!0,mode:448}),process.platform!=="win32"&&h.chmodSync(a,448);const l=u.join(a,"models.json"),c={providers:{"shennian-dashscope":{baseUrl:i.baseUrl,api:"openai-completions",apiKey:i.apiKey,authHeader:!0,compat:{supportsDeveloperRole:!1,supportsReasoningEffort:!0},models:[{id:"deepseek-v4-flash-0731",name:"DeepSeek V4 Flash",reasoning:!0,input:["text"],thinkingLevelMap:{off:null,minimal:null,low:"low",medium:null,high:"high",xhigh:null,max:"max"}}]}}};return h.writeFileSync(l,`${JSON.stringify(c,null,2)}
|
|
4
|
-
`,{encoding:"utf8",mode:384}),process.platform!=="win32"&&h.chmodSync(l,384),this.modelBroker=e,{configDir:a}}async stopModelBroker(){const t=this.modelBroker;this.modelBroker=null,await t?.stop().catch(()=>{})}async stopProcess(){const t=this.process;this.process=null,this.rpc?.close(),this.rpc=null,t?(t.kill("SIGTERM"),await new Promise(s=>{let e=!1;const i=()=>{e||(e=!0,s())};t.once("close",i),setTimeout(()=>{t.kill("SIGKILL"),i()},H).unref()}),await this.stopModelBroker()):await this.stopModelBroker(),this.validationRoot&&(h.rmSync(this.validationRoot,{recursive:!0,force:!0}),this.validationRoot=null)}}x("pi-coding-agent",()=>new W);export{W as PiCodingAgentAdapter};
|
|
1
|
+
import d from"node:fs";import h from"node:path";import{randomUUID as P}from"node:crypto";import{AgentAdapter as A,registerAgent as x}from"./adapter.js";import{resolveBuiltinCommand as v,spawnAgentCommand as R}from"./command-spec.js";import{buildAgentProcessEnv as N,buildManagedAgentProcessEnv as C,buildManagedNativeFullProcessEnv as T}from"../agent-env.js";import{resolveShennianPath as m}from"../config/index.js";import{buildInlineChannelPreamble as b,buildPlatformInstructions as k}from"./platform-instructions.js";import{isManagedAgentNativeFull as _}from"../security/managed-agent-policy.js";import{PiRpcClient as D}from"./pi-rpc-client.js";import{registerManagedAgentRuntimeSecurity as M}from"../security/managed-agent-runtime.js";import{PI_CODING_AGENT_MANAGED_RUNTIME_SECURITY as O}from"./pi-coding-agent-managed-permissions.js";import{writePiManagedExtension as q}from"./pi-managed-extension.js";import{recordPiSessionOwnership as j}from"./pi-session-ownership.js";M("pi-coding-agent",O);const F=32*1024,$=256*1024,U=3e3;function g(n){return n.replace(/[^a-zA-Z0-9_.-]/g,"_").slice(0,180)||"session"}function B(n){return n.data&&typeof n.data=="object"&&!Array.isArray(n.data)?n.data:{}}function G(n){if(typeof n=="string")return n;if(!n||typeof n!="object")return"";const t=n.content;return Array.isArray(t)?t.map(s=>{if(!s||typeof s!="object")return"";const e=s;return e.type==="text"&&typeof e.text=="string"?e.text:""}).join(""):""}function f(n,t=$){return n.length<=t?n:`${n.slice(0,t)}
|
|
2
|
+
[truncated]`}function z(n){return f(n,2e3).replace(/Bearer\s+[A-Za-z0-9._~-]+/gi,"Bearer [redacted]").replace(/\b(?:pimc|mrc)_[A-Za-z0-9_-]{20,}\b/g,"[redacted-capability]").replace(/\bsk-[A-Za-z0-9_-]{12,}\b/g,"[redacted-key]")}function H(n){try{return f(JSON.stringify(n))}catch{return"[unserializable]"}}function E(n){if(!n||typeof n!="object")return;const t=n;if(!(typeof t.input!="number"&&typeof t.output!="number"))return{inputTokens:typeof t.input=="number"?t.input:0,outputTokens:typeof t.output=="number"?t.output:0}}function X(n){const t=n?.trim();if(!t)return{};const s=t.indexOf("/");return s<=0||s===t.length-1?{modelId:t}:{provider:t.slice(0,s),modelId:t.slice(s+1)}}function w(n,t,s,e,r,l){const c=b(s,e,r,l),u=t?.filter(a=>a.kind!=="image")??[];if(!u.length)return`${c}${n}`;const o=u.map(a=>`[${a.name}](<${a.path}>)`);return`${c}${[n,"",...o].join(`
|
|
3
|
+
`)}`}function I(n,t){const s=[];for(const e of n??[]){if(e.kind!=="image"||!e.mimeType.startsWith("image/"))continue;let r=e.previewData?.trim()??"";const l=r.indexOf(",");if(r.startsWith("data:")&&l>=0&&(r=r.slice(l+1)),!r&&t&&e.path&&!/^https?:\/\//i.test(e.path))try{const c=d.statSync(e.path);c.isFile()&&c.size<=10*1024*1024&&(r=d.readFileSync(e.path).toString("base64"))}catch{r=""}r&&s.push({type:"image",data:r,mimeType:e.mimeType})}return s}class Z extends A{type="pi-coding-agent";get supportsActiveInput(){return!0}async injectActiveInput(t){const s=await this.readState();if(!this.rpc||!this.runId||!s.isStreaming&&!s.isCompacting)throw new Error("pi_active_turn_unavailable");const e={message:w(t.text,t.attachments,this.workDir,this.externalChannel,this.shennianSessionId,null)},r=I(t.attachments,!this.managedAgentPolicy);r.length&&(e.images=r),await this.rpc.request("steer",e)}get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;rpc=null;shennianSessionId="";workDir="";sessionDir="";agentSessionId=null;externalChannel=null;extraEnv={};spawnedRoomContext=null;managedAgentPolicy=null;runId="";seq=0;active=!1;terminal=!0;stderr="";lastUsage;promptFile=null;persistNativeSession=!0;validationRoot=null;runPhase=null;configure(t){t.sessionId&&(this.shennianSessionId=t.sessionId),this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null)}async start(t,s,e,r){await this.stopProcess(),this.shennianSessionId=t,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.agentSessionId=e??null;const l=m("runtime","pi-coding-agent",g(t));this.persistNativeSession=r?.persistNativeSession!==!1,this.validationRoot=this.persistNativeSession?null:h.join(l,`validation-${P()}`),this.sessionDir=this.validationRoot?h.join(this.validationRoot,"sessions"):h.join(l,"sessions"),d.mkdirSync(this.sessionDir,{recursive:!0,mode:448}),process.platform!=="win32"&&d.chmodSync(this.sessionDir,448),this.active=!1,this.terminal=!0}async send(t,s,e,r,l,c){await this.ensureProcess(l);const u=this.requireRpc(),o=await this.readState(),a=!!(o.isStreaming||o.isCompacting);(!a||!this.runId)&&(this.runId=P(),this.seq=0,this.terminal=!1,this.lastUsage=void 0,this.runPhase="thinking");const i=X(s);if(i.modelId&&!a&&(o.model?.id!==i.modelId||i.provider&&o.model?.provider!==i.provider)){if(!i.provider)throw new Error("Pi model selection must include provider/modelId");await u.request("set_model",{provider:i.provider,modelId:i.modelId})}e&&!a&&await u.request("set_thinking_level",{level:e});const p=a?c?.source==="room_activation"?"follow_up":"steer":"prompt",y={message:w(t,r,this.workDir,this.externalChannel,this.shennianSessionId,null)},S=I(r,!this.managedAgentPolicy);S.length&&(y.images=S),await u.request(p,y)}async resume(t){await this.stopProcess(),this.agentSessionId=t}async stop(){const t=this.rpc;t&&(await t.request("clear_queue").catch(()=>{}),await t.request("abort").catch(()=>{})),!this.terminal&&this.runId&&this.emitTerminal({state:"aborted"}),await this.stopProcess()}async getStatus(){if(!this.rpc||!this.process)return{active:!1,runId:null,canStop:!1};const t=await this.readState().catch(()=>null),s=!!(t?.isStreaming||t?.isCompacting||this.active);return{active:s,runId:s?this.runId:null,runPhase:s?this.runPhase??"thinking":null,canStop:s}}async setTitle(t,s){this.rpc&&await this.rpc.request("set_session_name",{name:s.slice(0,200)})}async ensureProcess(t){if(this.process&&this.rpc){if(!await this.roomContextStale())return;await this.stopProcess()}const s=v("pi-coding-agent");if(!s)throw new Error('Command "pi" not found. Install @earendil-works/pi-coding-agent from the official package.');const e=["--mode","rpc","--session-dir",this.sessionDir,"--offline"];if(this.agentSessionId&&e.push("--session",this.agentSessionId),this.managedAgentPolicy&&!_(this.managedAgentPolicy)){e.push("--no-extensions","--no-skills","--no-prompt-templates","--no-context-files");const i=this.managedTools(),p=q({outputPath:h.join(m("runtime","pi-coding-agent",g(this.shennianSessionId)),"managed-extension.ts"),policy:this.managedAgentPolicy,allowRoomControl:!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT,allowManagerControl:!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,allowHostShell:this.managedAgentPolicy.adapterPolicy.fileAccess==="host-full"});e.push("--no-builtin-tools","--extension",p),i.length?e.push("--tools",i.join(",")):e.push("--no-tools")}const r=k(this.workDir,this.externalChannel,this.shennianSessionId,t),l=this.validationRoot??m("runtime","pi-coding-agent",g(this.shennianSessionId));d.mkdirSync(l,{recursive:!0,mode:448}),this.promptFile=h.join(l,"instructions.md"),d.writeFileSync(this.promptFile,r,{encoding:"utf8",mode:384}),process.platform!=="win32"&&d.chmodSync(this.promptFile,384),e.push("--append-system-prompt",this.promptFile);const c={NO_COLOR:"1"},u=this.managedAgentPolicy&&!_(this.managedAgentPolicy)?C({agentType:this.type,providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:c}):this.managedAgentPolicy?T({...c,...this.extraEnv}):N({...c,...this.extraEnv}),o=R(s,e,{cwd:this.workDir,stdio:["pipe","pipe","pipe"],env:u});this.process=o,this.spawnedRoomContext=this.currentRoomContext(),this.stderr="",o.stderr?.on("data",i=>{const p=typeof i=="string"?i:i.toString("utf8");this.stderr=f(`${this.stderr}${p}`,F)});const a=new D(o);this.rpc=a,a.on("event",i=>this.handleRpcEvent(i)),a.on("protocolError",i=>this.emitError(i.message)),o.once("close",i=>{this.process===o&&(this.process=null,this.rpc=null,this.terminal||this.emitError(i===0?"Pi RPC process closed before agent_settled":`Pi RPC process exited with code ${i??"unknown"}${this.stderr?`: ${this.stderr}`:""}`))}),o.once("error",i=>{this.process===o&&this.emitError(i.message)});try{const i=await this.readState();if(!i.sessionId)throw new Error("Pi RPC did not return a session ID");if(i.isStreaming||i.isCompacting)throw new Error("Pi RPC session is not idle after startup");if(this.agentSessionId&&i.sessionId!==this.agentSessionId)throw new Error("Pi RPC resumed a different session");if(!i.sessionFile||!this.ownsSessionFile(i.sessionFile))throw new Error("Pi RPC returned a session file outside the Shennian-owned directory");this.agentSessionId=i.sessionId,this.persistNativeSession&&j(i.sessionId,this.sessionDir)}catch(i){throw await this.stopProcess(),i}}currentRoomContext(){return this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT??null}async roomContextStale(){if(this.currentRoomContext()===this.spawnedRoomContext)return!1;const t=await this.readState().catch(()=>null);return!t?.isStreaming&&!t?.isCompacting}managedTools(){const t=this.managedAgentPolicy?.adapterPolicy;if(!t)return[];const s=["read","grep","find","ls"];(t.fileAccess==="workspace-write"||t.fileAccess==="host-full")&&s.push("edit","write");const e=!!this.extraEnv.SHENNIAN_MANAGER_SESSION_ID,r=!!this.extraEnv.SHENNIAN_MANAGED_ROOM_CONTEXT;return(e||r||t.fileAccess==="host-full")&&s.push("bash"),s}ownsSessionFile(t){const s=h.resolve(this.sessionDir),e=h.resolve(t),r=h.relative(s,e);return r!==""&&!r.startsWith("..")&&!h.isAbsolute(r)}async readState(){const t=await this.requireRpc().request("get_state");return B(t)}requireRpc(){if(!this.rpc)throw new Error("Pi RPC process is not running");return this.rpc}handleRpcEvent(t){if(t.type==="agent_start"){this.active=!0,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:this.agentSessionId??void 0});return}if(t.type==="message_update"){this.lastUsage=E(t.usage)??this.lastUsage;const s=t.assistantMessageEvent;if(!s||typeof s!="object")return;const e=s;e.type==="text_delta"&&typeof e.delta=="string"?(this.runPhase="streaming_text",this.emitEvent({state:"delta",text:e.delta})):e.type==="thinking_delta"&&typeof e.delta=="string"&&(this.runPhase="thinking",this.emitEvent({state:"delta",text:e.delta,thinking:!0}));return}if(t.type==="tool_execution_start"){this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:typeof t.toolName=="string"?t.toolName:"tool",args:t.args&&typeof t.args=="object"&&!Array.isArray(t.args)?t.args:{}});return}if(t.type==="tool_execution_end"){this.runPhase="thinking",this.emitEvent({state:"tool-result",name:typeof t.toolName=="string"?t.toolName:"tool",result:G(t.result)||H(t.result)});return}if(t.type==="tool_execution_update"){this.emitEvent({state:"notify",runPhase:"tool_running",message:"Pi tool is running"});return}if(t.type==="message_end"){const s=t.message;if(s&&typeof s=="object"){const e=s;this.lastUsage=E(e.usage)??this.lastUsage,e.stopReason==="error"&&this.emitError(typeof e.errorMessage=="string"?e.errorMessage:"Pi model request failed")}return}if(t.type==="compaction_start"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is compacting context"});return}if(t.type==="auto_retry_start"||t.type==="summarization_retry_scheduled"){this.runPhase="thinking",this.emitEvent({state:"notify",runPhase:"thinking",message:"Pi is retrying"});return}if(t.type==="extension_ui_request"){typeof t.id=="string"&&this.rpc?.notify("extension_ui_response",{id:t.id,cancelled:!0});return}if(t.type==="extension_error"){this.emitError(typeof t.error=="string"?t.error:"Pi extension failed");return}t.type==="agent_settled"&&(this.active=!1,this.emitTerminal({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.lastUsage}))}emitEvent(t){this.runId&&this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}emitTerminal(t){this.terminal||(this.terminal=!0,this.active=!1,this.runPhase=null,this.emitEvent(t))}emitError(t){this.emitTerminal({state:"error",message:z(t)})}async stopProcess(){const t=this.process;this.process=null,this.rpc?.close(),this.rpc=null,t&&(t.kill("SIGTERM"),await new Promise(s=>{let e=!1;const r=()=>{e||(e=!0,s())};t.once("close",r),setTimeout(()=>{t.kill("SIGKILL"),r()},U).unref()})),this.validationRoot&&(d.rmSync(this.validationRoot,{recursive:!0,force:!0}),this.validationRoot=null)}}x("pi-coding-agent",()=>new Z);export{Z as PiCodingAgentAdapter};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import p from"node:fs/promises";import D from"node:path";import{randomUUID as h}from"node:crypto";import{isAvailableAgentType as A}from"@shennian/wire";import{createAgent as I}from"../../agents/adapter.js";import{buildManagedAgentEnv as b}from"../../agents/config-status.js";import{ManagerModeAdapter as N}from"../../agents/manager.js";import{NativeSessionLifecycleRegistry as C}from"../native-session-lifecycle.js";import{validateManagedAgentWorkDir as S}from"../../security/managed-agent-policy.js";const T="\u8BF7\u56DE\u590D hello\uFF0C\u7528\u4E8E\u786E\u8BA4\u4F60\u5DF2\u51C6\u5907\u597D\u3002",O=6e4,M=new C;async function x(e,r={}){try{return await R(e,r)}catch(t){const n=t instanceof Error?t.message:"";return{ok:!1,errorCode:n==="agent_validation_cleanup_failed"?n:_(t,"start")}}}async function R(e,r){if(!A(e.runtimeAdapter)||e.runtimeAdapter==="manager"||e.runtimeAdapter==="pi"||e.runtimeAdapter==="openclaw")return{ok:!1,errorCode:"agent_validation_runtime_unavailable"};if(!D.isAbsolute(e.workDir.trim()))return{ok:!1,errorCode:"agent_validation_workdir_invalid"};let t;try{t=await(r.resolveWorkDir??W)(e.workDir)}catch(i){return{ok:!1,errorCode:L(i)}}if(!(r.validateWorkDir?await r.validateWorkDir(t):(await S(t,async()=>t)).ok))return{ok:!1,errorCode:"agent_validation_workdir_invalid"};const s=(r.createAdapter??I)(e.runtimeAdapter);if(!s)return{ok:!1,errorCode:"agent_validation_runtime_unavailable"};const o=e.sessionMode==="manager"?new N(s,e.runtimeAdapter):s,g=`agent-validation-${h()}`;let l="",u="",f=null,c=null;const y=new Promise(i=>{c=i}),k=i=>{i.agentSessionId&&(l=i.agentSessionId,r.ignoreNativeSession?.(e.runtimeAdapter,l)),i.state==="delta"&&!i.thinking&&i.text&&(u+=i.text),i.state==="final"?(i.text&&(u+=i.text),c?.({kind:"final"})):(i.state==="error"||i.state==="aborted")&&c?.({kind:"error",error:i.message??i.state})},v=i=>c?.({kind:"error",error:i});o.on("agentEvent",k),o.on("error",v);const E=async()=>{o.configure?.({sessionId:g,env:b(e.runtimeAdapter)});try{await o.start(g,t,null,{persistNativeSession:!1})}catch(a){return{ok:!1,errorCode:_(a,"start")}}const i=new Promise(a=>{f=setTimeout(()=>a({kind:"timeout"}),r.timeoutMs??O)}),m=o.send(T,e.modelId??void 0).then(()=>y).catch(a=>({kind:"error",error:a})),d=await Promise.race([m,i]);return d.kind==="timeout"?{ok:!1,errorCode:"agent_validation_response_timeout"}:d.kind==="error"?{ok:!1,errorCode:_(d.error,"response")}:u.toLowerCase().includes("hello")?{ok:!0}:{ok:!1,errorCode:"agent_validation_response_mismatch"}};let w;try{w=await E()}finally{f&&clearTimeout(f),o.removeListener("agentEvent",k),o.removeListener("error",v),await o.stop().catch(()=>{}),l&&(r.cleanupNativeSession??((m,d,a)=>{M.execute(m,d,{workDir:a}).catch(()=>{})}))(e.runtimeAdapter,l,t)}return w}async function J(e,r){const t=U(r.params);if(!t){e.client.sendRes({type:"res",id:r.id,ok:!1,error:"agent_validation_invalid_configuration"});return}const n=await x(t,{ignoreNativeSession:(s,o)=>{e.nativeFusion?.ignoreNativeSource(s,o)}});e.client.sendRes(n.ok?{type:"res",id:r.id,ok:!0,payload:{ready:!0}}:{type:"res",id:r.id,ok:!1,error:n.errorCode})}async function W(e){const r=e.trim();if(!r)throw Object.assign(new Error("workdir_required"),{code:"EINVAL"});const t=await p.realpath(r);if(!(await p.stat(t)).isDirectory())throw Object.assign(new Error("workdir_not_directory"),{code:"ENOTDIR"});return t}function L(e){const r=P(e);return r==="ENOENT"?"agent_validation_workdir_not_found":r==="ENOTDIR"?"agent_validation_workdir_not_directory":r==="EACCES"||r==="EPERM"?"agent_validation_workdir_unavailable":"agent_validation_workdir_invalid"}function _(e,r){const t=e instanceof Error?e.message:String(e);return t==="agent_validation_server_upgrade_required"?t:/model.*(?:not found|unavailable|unsupported|invalid|access denied|permission denied|not (?:allowed|authorized))|(?:access|permission) denied.*model|unknown model/i.test(t)?"agent_validation_model_unavailable":/quota|insufficient.*(?:credit|balance)|billing|rate.?limit|\b429\b/i.test(t)?"agent_validation_quota_exceeded":/not found|enoent|command .* missing|is .* installed/i.test(t)?"agent_validation_runtime_unavailable":/unauth|authentication|not logged|login required|api key|token.*missing|forbidden|401|403/i.test(t)?"agent_validation_runtime_auth_required":/ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT|network|fetch failed|connection.*(?:failed|closed|refused)/i.test(t)?"agent_validation_network_failed":r==="start"?"agent_validation_start_failed":"agent_validation_response_failed"}function P(e){return typeof e=="object"&&e&&"code"in e?String(e.code):""}function U(e){const r=typeof e.runtimeAdapter=="string"?e.runtimeAdapter:"",t=typeof e.workDir=="string"?e.workDir:"",n=e.sessionMode==="manager"?"manager":"standard";return!A(r)||!t.trim()?null:{runtimeAdapter:r,workDir:t,sessionMode:n,modelId:typeof e.modelId=="string"?e.modelId:null}}export{J as handleAgentWorkspaceValidation,x as validateAgentWorkspaceConfiguration};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{buildApprovalPendingPayload as
|
|
2
|
-
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function
|
|
1
|
+
import{buildApprovalPendingPayload as w}from"@shennian/wire";import{createHash as x}from"node:crypto";import{AgentEventTerminalGate as T}from"../../agents/event-terminal-gate.js";import{recordAcpAgentModels as M}from"../../agents/model-registry.js";import{reportLog as D}from"../../log-reporter.js";import{registerInternalNativeSource as k}from"../../native-fusion/source-visibility.js";import{requestSessionIndexPublish as c}from"../index-publisher.js";import{noteRunActivity as _}from"../run-stall.js";import{appendMessage as u,recordSession as m,upsertMessage as P}from"../store.js";import{writeToolDetail as j}from"../tool-detail-store.js";import{refreshMachineAgents as O}from"./agents.js";import{roomReplyFailureNotice as C}from"../room-reply-notice.js";function N(a){const r=a.indexOf(`
|
|
2
|
+
`),o=r>0?Math.min(r,80):Math.min(a.length,80);return a.slice(0,o)}function A(a,r,o){return`${a}:${x("sha256").update(`${r}\0${o??""}`).digest("hex")}`}function B(a,r,o={}){if(a.state==="tool-call"||a.state==="tool-result"){const i={runId:a.runId,sourceSeq:a.seq};return{state:a.state,runId:a.runId,seq:a.seq,sessionId:r,detailRef:i,status:a.state==="tool-call"?"running":"completed",detailAvailable:!0,...a.durationMs!==void 0?{durationMs:a.durationMs}:{},...a.name?{name:a.name}:{},...a.source?{source:a.source}:{},...a.agentSessionId?{agentSessionId:a.agentSessionId}:{},...o}}return{...a,sessionId:r,...o}}const H=3e4;function J(a){return a.state==="heartbeat"?a.runPhase??null:a.state==="tool-call"||a.state==="tool-result"?"tool_running":a.state==="approval-pending"?"waiting_approval":a.state==="delta"?a.thinking?"thinking":"streaming_text":a.state==="init"||a.state==="start"?"thinking":null}function R(a,r){return a!=="manager"?a:r==="claude"?"claude":"codex"}function v(a,r,o,i){let I=null;const E=new T;function S(t,n={}){a.client.sendAgentEvent({type:"event",event:"agent",payload:B(t,r,n),seq:t.seq,id:`agent-evt-${t.runId}-${t.seq}`})}o.startsWith("acp:")&&i.on("sessionOptions",()=>{try{const t=i.getSessionOptions?.().models??[];if(!M(o,t))return;const n=a.getAgentSnapshot?.();if(!n)return;a.client.sendEvent({type:"event",event:"machine.agents",payload:{agentList:n.map(e=>e.type),agents:n}})}catch{}});function $(t){t?.heartbeatTimer&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=null)}function y(t){if(!t.currentRunId||!t.currentRunPhase)return;const n=t.heartbeatSeq++;a.client.sendAgentEvent({type:"event",event:"agent",payload:{state:"heartbeat",sessionId:r,runId:t.currentRunId,seq:n,runPhase:t.currentRunPhase},seq:n,id:`agent-heartbeat-${t.currentRunId}-${n}-${Date.now()}`})}function b(t){!t||t.heartbeatTimer||(t.heartbeatTimer=setInterval(()=>{y(t)},H),t.heartbeatTimer.unref?.())}function g(t){const n=t?.pendingTextEvent;!t||!n||!n.text||(u(r,{id:`agent-${n.runId}-${n.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:n.text}),c(a.client),S({state:"delta",runId:n.runId,seq:n.seq,text:n.text,thinking:n.thinking||void 0}),t.pendingTextEvent=null)}i.on("agentEvent",t=>{if(!E.accept(t))return;let n=!1;t.errorCode==="acp_auth_required"&&O(a).catch(()=>{});const e=a.sessions.get(r),p=J(t),s=t.state==="final"||t.state==="error"||t.state==="aborted";if(e&&_(r,e,s),e&&(e.nextEventSeq=t.seq+1,s||(e.currentRunId=t.runId),!s&&p&&(e.currentRunPhase=p,b(e)),t.agentSessionId&&(e.agentSessionId=t.agentSessionId),e.journalRunId)){const l={agentSessionId:t.agentSessionId??e.agentSessionId,providerRunId:t.runId||null,lastObservedEventSeq:t.seq,...s?{}:{phase:p==="waiting_approval"?"waiting_approval":"running"}};a.runJournal?.update(r,e.journalRunId,l)}if(a.managerRuntime?.noteAgentEvent(r,t),t.state==="delta"&&t.thinking)return;t.state!=="delta"&&D({level:"info",sessionId:r,wsEvent:`agent.${t.state}`,wsDirection:"out",metadata:{runId:t.runId,seq:t.seq,agentType:o}});let f=!1;if(t.state==="tool-call"||t.state==="tool-result"){const l=t.toolCallId?`agent-tool-${x("sha256").update(`${t.runId}\0${t.toolCallId}`).digest("hex")}`:`agent-${t.runId}-${t.seq}`;j({sessionId:r,toolCallId:l,detailRevision:t.seq,ts:Date.now(),name:t.name??"tool",...t.args!==void 0?{args:t.args}:{},...t.result!==void 0?{result:t.result}:{},status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq}}),(t.toolCallId?P:u)(r,{id:l,sessionId:r,role:"agent",ts:Date.now(),payload:JSON.stringify({v:1,type:t.state==="tool-call"?"tool_use":"tool_result",name:t.name,toolCallId:l,status:t.toolStatus??(t.state==="tool-call"?"running":"completed"),...t.durationMs!==void 0?{durationMs:t.durationMs}:{},detailRef:{runId:t.runId,sourceSeq:t.seq},detailRevision:t.seq,detailAvailable:!0,resultOmitted:t.state==="tool-result"})}),f=!0}else t.state==="approval-pending"?(u(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:w({...t.approval,permission:t.permission})}),f=!0,e&&m({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,attentionId:A("approval",t.runId,t.seq)})):(t.state==="error"||t.state==="aborted")&&t.message&&(u(r,{id:`agent-${t.runId||"run"}-${t.seq}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),f=!0);f&&c(a.client);const d=`${r}:${t.runId}`;if(t.state==="delta"&&!t.thinking&&t.text&&a.runTextAcc.set(d,(a.runTextAcc.get(d)??"")+t.text),t.agentSessionId&&t.agentSessionId!==I&&(e?.nativeSessionVisibility==="internal"&&k(r,R(o,t.source)??o,t.agentSessionId),I=t.agentSessionId,a.nativeFusion?.noteManagedSourceSession(r,R(o,t.source),t.agentSessionId),e&&m({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:t.agentSessionId}),a.client.sendEvent({type:"event",event:"session.update",payload:{session:{id:r,agentType:o,agentSessionId:t.agentSessionId}}})),t.state==="delta"){const l=t.text??"";if(!l)return;e?.pendingTextEvent&&e.pendingTextEvent.runId!==t.runId&&g(e),e&&!e.pendingTextEvent&&(e.pendingTextEvent={runId:t.runId,seq:t.seq,text:"",thinking:!1}),e?.pendingTextEvent&&(e.pendingTextEvent.text+=l,e.pendingTextEvent.seq=t.seq);return}let q={};if(t.state==="final"){g(e);const l=e?C(e):null;l&&(n=!0,u(r,{id:`room-reply-notice-${t.runId}`,sessionId:r,role:"agent",ts:Date.now(),payload:l}),c(a.client));const h=a.runTextAcc.get(d)??"";h&&(q={messageSummary:N(h)}),a.runTextAcc.delete(d)}else t.state==="error"||t.state==="aborted"?(g(e),a.runTextAcc.delete(d)):(t.state==="tool-call"||t.state==="tool-result"||t.state==="approval-pending")&&g(e);s&&e?.currentRunId===t.runId&&(e.currentRunId=null,e.currentRunPhase=null,e.nextEventSeq=0,$(e),a.chatQueue?.noteTerminal(r),m({sessionId:r,agentType:o,workDir:e.workDir,agentSessionId:e.agentSessionId,status:t.state==="final"&&!n?"completed":"failed",attentionId:A("terminal",t.runId),lastActivityAt:new Date().toISOString()}),c(a.client),e.journalRunId&&(a.runJournal?.remove(r,e.journalRunId),a.recoveryBarrier?.end(r),e.journalRunId=null)),S(t,q)}),i.on("error",t=>{console.error(`[chat.send] adapter error sessionId=${r} agentType=${o}: ${t.message}`);const n=a.sessions.get(r);n?.journalRunId&&(a.runJournal?.update(r,n.journalRunId,{phase:"terminal"}),a.runJournal?.remove(r,n.journalRunId),a.recoveryBarrier?.end(r),n.journalRunId=null),a.sessions.delete(r),a.chatQueue?.noteTerminal(r),a.chatQueue?.isDispatching?.(r)||(u(r,{id:`agent-error-${r}-${Date.now()}`,sessionId:r,role:"agent",ts:Date.now(),payload:t.message}),c(a.client)),a.client.sendEvent({type:"event",event:"agent",payload:{state:"error",sessionId:r,message:t.message,runId:"",seq:0}})})}export{v as bindAdapterEvents,R as getNativeSourceAgentType};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import b from"node:crypto";import{getRegisteredAgents as k,unregisterAgent as S}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{handleChatAbort as z,handleChatSend as O}from"./handlers/chat.js";import{recoverJournaledRun as B}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 U}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as J}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as $}from"./handlers/voice-window.js";import{handleRemoteAccessPause as V}from"./handlers/remote-access.js";import{cleanupPendingTransfers as L,handleFsLs as N,handleFsRead as G,handleFsRename as K,handleFsWrite as X,handleFsTransferAbort as Z,handleFsTransferChunk as Y,handleFsTransferFinish as q,handleFsTransferStart as ee,handleFsExportMarkdownPdf as se,handleFsExportMarkdownPdfSetup as te,handleFsArchiveZip as ae}from"./handlers/fs.js";import{handleRegionProbe as re,handleRegionSwitch as ne,handleUpgradeSetPolicy as ie}from"./handlers/control.js";import{ManagerRuntimeService as oe,setManagerRuntimeService as u}from"../manager/runtime.js";import{ChatQueueManager as ce}from"./queue.js";import{createAuthorizedFsRoot as le,createAuthorizedFsRootAsync as he,resolveAuthorizedPath as ue,resolveAuthorizedPathAsync as de,resolveSessionWorkDir as me}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 pe}from"../agents/custom.js";import{handleManagedRoomBind as ge,handleManagedRoomRestart as fe,discardPreBindingSession as ve}from"./handlers/room-managed.js";import{getDaemonInstallationId as d,listSessionRecords as h,purgeCanonicalSession as ye,purgeSessionRecord as Re,recordSession as be,upsertMessage as ke}from"./store.js";import{requestSessionIndexPublish as m}from"./index-publisher.js";import{checkRunStalls as Se}from"./run-stall.js";import{reportUpgradeAggregateMetric as we}from"../log-reporter.js";import{PersonalHistorySubscriptions as Ie}from"./history-subscriptions.js";import{sweepAttachmentTransfers as Ae}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Te}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Pe}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as Ce}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as Me}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as o}from"../personal-sync/epoch.js";import{ActiveRunJournal as xe}from"./run-recovery/journal.js";import{RunRecoveryBarrier as De}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Fe}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as Ee}from"./project-fs-store.js";import{handleProjectFsRequest as Qe}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as je,handleAcpAgentRequest as ze}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as Oe}from"./deletion-synchronizer.js";import{dispatchManagedChat as Be,dispatchQueuedChat as We,interruptQueuedChat as _e}from"./queued-chat-dispatch.js";const He=50;import{resolveSessionWorkDir as Vs}from"../fs/boundary.js";function Ue(){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 Us{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 De;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new Ee;deletionSynchronizer;constructor(e,t=null,s,n=null,r=null,l=null,p=null,g=null,f=null,v=null,y=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=l,this.managedRoomContextRevoker=p,this.managedRoomExecutor=g,this.trustedProjectFsRequestResolver=v,this.getAgentSnapshot=y,this.runJournal=f??new xe(d());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Fe({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>B(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=h().find(R=>R.sessionId===a.sessionId),c=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===c},onOutcome:a=>we({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 oe({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new ce({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Be(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>We(this.getRuntime(),a,i),interruptQueuedSession:a=>_e(this.getRuntime(),a)}),this.deletionSynchronizer=new Oe(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new Ie(this.client),this.nativeCleanupOutbox=new Me({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(),u(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(()=>{Se(this.sessions.entries(),()=>m(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([...h().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{Ae(this.resolvePath(i))}catch(c){console.error("[attachment.cleanup] failed",c instanceof Error?c.message:String(c))}},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}}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=Ue();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})}),be({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=h().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 ve(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new Te({daemonInstallationId:d()});let s=[];try{s=Pe(e.sessionId,{records:h()})}catch(r){console.warn("[session.deletions] local native source lookup failed",{error:r instanceof Error?r.message:String(r)})}t.recordSession(e);for(const r of[...e.sources,...s]){const l=t.find(r.agentType,r.sourceSessionKey);l&&l.sessionId!==e.sessionId||t.record({...e,...r})}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),Ce(e.sessionId),ye(e.sessionId),Re(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:")&&S(t);const e=I();for(const[t,s]of Object.entries(e.customAgents??{}))pe(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");o(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?n={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await O(s,e);break;case"chat.enqueue":o(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.queue.get":o(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":o(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":o(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":o(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":o(e.params),await z(s,e);break;case"session.refresh":o(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":U(s,e);break;case"session.tool.detail":await _(s,e);break;case"voice.session.body.window":$(s,e);break;case"session.title.set":await H(s,e);break;case"room.agent.bind-managed":await ge(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await fe(s,this.managedRoomBinder,e);break;case"fs.ls":await N(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await Qe(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await G(s,e);break;case"fs.write":await X(s,e);break;case"fs.export.markdown-pdf":await se(s,e);break;case"fs.export.markdown-pdf.setup":await te(s,e);break;case"fs.archive.zip":await ae(s,e);break;case"fs.rename":await K(s,e);break;case"fs.transfer.start":await ee(s,e);break;case"fs.transfer.chunk":await Y(s,e);break;case"fs.transfer.finish":await q(s,e);break;case"fs.transfer.abort":await Z(s,e);break;case"region.probe":await re(s,e);break;case"region.switch":await ne(s,e);break;case"upgrade.start":await A(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 ie(s,e);break;case"machine.remote-access.pause":await V(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await je(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 ze(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 J(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(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<He)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 me(e)}resolveAuthorizedPath(e,t){return ue(e,le(t))}async resolveAuthorizedPathAsync(e,t){return de(e,await he(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(),L(this.getRuntime()),await this.managerRuntime.stop(),u(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Us as SessionManager,Vs as resolveSessionWorkDir,Ue as upgradeRecoveryVisibleMessage};
|
|
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 A}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 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{handleChatAbort as z,handleChatSend as O}from"./handlers/chat.js";import{recoverJournaledRun as B}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 U}from"./handlers/message-status.js";import{handleAgentWorkspaceValidation as J}from"./handlers/agent-workspace-validation.js";import{handleVoiceSessionBodyWindow as $}from"./handlers/voice-window.js";import{handleRemoteAccessPause as V}from"./handlers/remote-access.js";import{cleanupPendingTransfers as L,handleFsLs as N,handleFsRead as G,handleFsRename as K,handleFsWrite as X,handleFsTransferAbort as Z,handleFsTransferChunk as Y,handleFsTransferFinish as q,handleFsTransferStart as ee,handleFsExportMarkdownPdf as se,handleFsExportMarkdownPdfSetup as te,handleFsArchiveZip as ae}from"./handlers/fs.js";import{handleRegionProbe as re,handleRegionSwitch as ne,handleUpgradeSetPolicy as ie}from"./handlers/control.js";import{ManagerRuntimeService as oe,setManagerRuntimeService as u}from"../manager/runtime.js";import{ChatQueueManager as ce}from"./queue.js";import{createAuthorizedFsRoot as le,createAuthorizedFsRootAsync as he,resolveAuthorizedPath as ue,resolveAuthorizedPathAsync as de,resolveSessionWorkDir as me}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 pe}from"../agents/custom.js";import{handleManagedRoomBind as ge,handleManagedRoomRestart as fe,discardPreBindingSession as ve}from"./handlers/room-managed.js";import{getDaemonInstallationId as d,listSessionRecords as h,purgeCanonicalSession as ye,purgeSessionRecord as Re,recordSession as be,upsertMessage as Se}from"./store.js";import{requestSessionIndexPublish as m}from"./index-publisher.js";import{checkRunStalls as ke}from"./run-stall.js";import{reportUpgradeAggregateMetric as we}from"../log-reporter.js";import{PersonalHistorySubscriptions as Ae}from"./history-subscriptions.js";import{sweepAttachmentTransfers as Ie}from"./attachment-transfer-store.js";import{NativeSourceDeletionStore as Te}from"../native-fusion/native-source-deletions.js";import{collectLocalNativeSources as Pe}from"../native-fusion/session-native-sources.js";import{purgeToolDetails as Ce}from"./tool-detail-store.js";import{NativeSessionCleanupOutbox as Me}from"./native-cleanup-outbox.js";import{assertPersonalSyncIdentity as o}from"../personal-sync/epoch.js";import{ActiveRunJournal as xe}from"./run-recovery/journal.js";import{RunRecoveryBarrier as De}from"./run-recovery/barrier.js";import{RunRecoveryCoordinator as Fe}from"./run-recovery/coordinator.js";import{ProjectFsHandleStore as Ee}from"./project-fs-store.js";import{handleProjectFsRequest as Qe}from"./handlers/project-fs.js";import{handleAgentPermissionResponse as je,handleAcpAgentRequest as ze}from"./handlers/agent-control.js";import{SessionDeletionSynchronizer as Oe}from"./deletion-synchronizer.js";import{dispatchManagedChat as Be,dispatchQueuedChat as We,interruptQueuedChat as _e}from"./queued-chat-dispatch.js";const He=50;import{resolveSessionWorkDir as Vs}from"../fs/boundary.js";function Ue(){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 Us{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 De;recoveryCoordinator;recoveryPass=null;prepareManagedRecovery;projectFsHandleStore=new Ee;deletionSynchronizer;constructor(e,t=null,s,n=null,r=null,l=null,p=null,g=null,f=null,v=null,y=null){this.client=e,this.nativeFusion=t,this.cliVersion=s,this.upgradePolicyController=n,this.managedRoomBinder=r,this.remoteAccessPauseController=l,this.managedRoomContextRevoker=p,this.managedRoomExecutor=g,this.trustedProjectFsRequestResolver=v,this.getAgentSnapshot=y,this.runJournal=f??new xe(d());for(const a of this.runJournal.loadPendingReconciliation().records)this.recoveryBarrier.begin(a.sessionId);this.recoveryCoordinator=new Fe({journal:this.runJournal,barrier:this.recoveryBarrier,recover:(a,i)=>B(this.getRuntime(),a,i),commitTerminal:(a,i)=>this.commitRecoveryTerminal(a,i),isCanonicalTerminal:a=>{const i=h().find(R=>R.sessionId===a.sessionId),c=`terminal:${b.createHash("sha256").update(`${a.runId}\0`).digest("hex")}`;return i?.lastAttentionId===c},onOutcome:a=>we({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 oe({getRuntime:()=>this.getRuntime(),getAgentSnapshot:this.getAgentSnapshot??void 0,dispatchReq:a=>this.handleReq(a,{propagateErrors:!0})}),this.chatQueue=new ce({getRuntime:()=>this.getRuntime(),dispatchReq:a=>this.handleReq(a),dispatchManagedReq:(a,i)=>Be(this.getRuntime(),a,i),dispatchQueuedReq:(a,i)=>We(this.getRuntime(),a,i),interruptQueuedSession:a=>_e(this.getRuntime(),a)}),this.deletionSynchronizer=new Oe(e,a=>this.applySessionDeletion(a)),this.historySubscriptions=new Ae(this.client),this.nativeCleanupOutbox=new Me({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(),u(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(()=>{ke(this.sessions.entries(),()=>m(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([...h().map(i=>i.workDir),...Array.from(this.pendingTransfers.values()).map(i=>i.rootPath)]);for(const i of a)try{Ie(this.resolvePath(i))}catch(c){console.error("[attachment.cleanup] failed",c instanceof Error?c.message:String(c))}},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}}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}}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=Ue();Se(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})}),be({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=h().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 ve(this.getRuntime(),e)}discardPendingManagedRoomMessages(e){return this.chatQueue.discardPendingManagedRoomMessages(e)}async synchronizeSessionDeletions(){await this.deletionSynchronizer.synchronize()}async applySessionDeletion(e){const t=new Te({daemonInstallationId:d()});let s=[];try{s=Pe(e.sessionId,{records:h()})}catch(r){console.warn("[session.deletions] local native source lookup failed",{error:r instanceof Error?r.message:String(r)})}t.recordSession(e);for(const r of[...e.sources,...s]){const l=t.find(r.agentType,r.sourceSessionKey);l&&l.sessionId!==e.sessionId||t.record({...e,...r})}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),Ce(e.sessionId),ye(e.sessionId),Re(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 S())t.startsWith("custom:")&&k(t);const e=A();for(const[t,s]of Object.entries(e.customAgents??{}))pe(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");o(e.params),this.recoveryBarrier.isDispatchFrozen()||this.recoveryBarrier.isRecovering(String(e.params.sessionId??""))?n={durableQueueHandoff:await this.chatQueue.handleEnqueue({...e,method:"chat.enqueue"})}:await O(s,e);break;case"chat.enqueue":o(e.params),n={durableQueueHandoff:await this.chatQueue.handleEnqueue(e)};break;case"chat.queue.get":o(e.params),await this.chatQueue.handleGet(e);break;case"chat.queue.edit":o(e.params),await this.chatQueue.handleEdit(e);break;case"chat.queue.delete":o(e.params),await this.chatQueue.handleDelete(e);break;case"chat.queue.promote":o(e.params),await this.chatQueue.handlePromote(e);break;case"chat.abort":o(e.params),await z(s,e);break;case"session.refresh":o(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":U(s,e);break;case"session.tool.detail":await _(s,e);break;case"voice.session.body.window":$(s,e);break;case"session.title.set":await H(s,e);break;case"room.agent.bind-managed":await ge(s,this.managedRoomBinder,e);break;case"room.agent.restart-managed":await fe(s,this.managedRoomBinder,e);break;case"fs.ls":await N(s,e);break;case"project.fs.open":case"project.fs.list":case"project.fs.read":case"project.fs.close":await Qe(this.client,this.projectFsHandleStore,e,this.trustedProjectFsRequestResolver);break;case"fs.read":await G(s,e);break;case"fs.write":await X(s,e);break;case"fs.export.markdown-pdf":await se(s,e);break;case"fs.export.markdown-pdf.setup":await te(s,e);break;case"fs.archive.zip":await ae(s,e);break;case"fs.rename":await K(s,e);break;case"fs.transfer.start":await ee(s,e);break;case"fs.transfer.chunk":await Y(s,e);break;case"fs.transfer.finish":await q(s,e);break;case"fs.transfer.abort":await Z(s,e);break;case"region.probe":await re(s,e);break;case"region.switch":await ne(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 ie(s,e);break;case"machine.remote-access.pause":await V(this.client,this.remoteAccessPauseController,e);break;case"agents.refresh":await P(s,e);break;case"agent.permission.respond":await je(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 ze(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 J(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(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<He)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 me(e)}resolveAuthorizedPath(e,t){return ue(e,le(t))}async resolveAuthorizedPathAsync(e,t){return de(e,await he(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(),L(this.getRuntime()),await this.managerRuntime.stop(),u(null)}revokeManagedRoomToken(e){const t=e.managedRoomContextToken;e.managedRoomContextToken=null,t&&this.managedRoomContextRevoker?.(t)}}export{Us as SessionManager,Vs as resolveSessionWorkDir,Ue as upgradeRecoveryVisibleMessage};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import f from"node:http";import{randomBytes as c,timingSafeEqual as y}from"node:crypto";const b=20*1024*1024,p=18e4;function g(a){return a?.startsWith("Bearer ")?a.slice(7):""}function _(a,t){const e=Buffer.from(a),r=Buffer.from(t);return e.length===r.length&&y(e,r)}async function v(a){const t=[];let e=0;for await(const r of a){const i=Buffer.isBuffer(r)?r:Buffer.from(r);if(e+=i.length,e>b)throw new Error("request_too_large");t.push(i)}return Buffer.concat(t)}class C{options;server=null;capability=c(32).toString("base64url");turnActive=!1;port=0;upstreamCapability=null;upstreamCapabilityExpiresAt=0;constructor(t){this.options=t}async start(){if(this.server)return this.connection();const t=f.createServer((r,i)=>{this.handle(r,i)});t.requestTimeout=p,t.headersTimeout=1e4,await new Promise((r,i)=>{t.once("error",i),t.listen(0,"127.0.0.1",()=>{t.removeListener("error",i),r()})});const e=t.address();if(!e||typeof e=="string")throw t.close(),new Error("pi_model_broker_address_unavailable");return this.server=t,this.port=e.port,this.connection()}setTurnActive(t){this.turnActive=t,t||this.revokeUpstreamCapability()}async stop(){this.turnActive=!1,await this.revokeUpstreamCapability(),this.capability=c(32).toString("base64url");const t=this.server;this.server=null,this.port=0,t&&await new Promise(e=>t.close(()=>e()))}connection(){if(!this.port)throw new Error("pi_model_broker_not_started");return{baseUrl:`http://127.0.0.1:${this.port}/v1`,apiKey:this.capability}}async handle(t,e){e.setHeader("Cache-Control","no-store");const r=g(t.headers.authorization);if(!r||!_(r,this.capability)){this.json(e,401,{error:{message:"Unauthorized",type:"authentication_error"}});return}if(t.method==="GET"&&t.url==="/v1/models"){this.json(e,200,{object:"list",data:[{id:"deepseek-v4-flash-0731",object:"model",owned_by:"shennian"}]});return}if(t.method!=="POST"||t.url!=="/v1/chat/completions"){this.json(e,404,{error:{message:"Not found",type:"invalid_request_error"}});return}if(!this.turnActive){this.json(e,403,{error:{message:"Managed model capability is not active",type:"permission_error"}});return}try{const i=await v(t),o=await this.ensureUpstreamCapability();if(e.destroyed||!this.turnActive){await this.revokeUpstreamCapability();return}const n=new AbortController;t.once("aborted",()=>n.abort()),e.once("close",()=>n.abort());const h=setTimeout(()=>n.abort(),p);let s;try{s=await(this.options.fetchImpl??fetch)(`${this.options.serverUrl.replace(/\/$/,"")}/api/managed-model/v1/chat/completions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${o}`},body:i.toString("utf8"),signal:n.signal})}finally{clearTimeout(h)}if(e.statusCode=s.status,e.setHeader("content-type",s.headers.get("content-type")||"application/json; charset=utf-8"),!s.body){e.end();return}const l=s.body.getReader();try{for(;;){const{done:u,value:d}=await l.read();if(u)break;e.write(Buffer.from(d))||await new Promise(m=>e.once("drain",m))}}finally{l.releaseLock()}e.end()}catch(i){if(e.headersSent){e.destroy();return}const o=i instanceof Error&&i.message==="request_too_large"?413:502;this.json(e,o,{error:{message:o===413?"Request too large":"Managed model request failed",type:o===413?"invalid_request_error":"upstream_error"}})}}json(t,e,r){t.statusCode=e,t.setHeader("content-type","application/json; charset=utf-8"),t.end(JSON.stringify(r))}async ensureUpstreamCapability(){if(this.upstreamCapability&&this.upstreamCapabilityExpiresAt>Date.now()+1e4)return this.upstreamCapability;const t=await(this.options.fetchImpl??fetch)(`${this.options.serverUrl.replace(/\/$/,"")}/api/managed-model/v1/capabilities`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${this.options.machineToken}`},signal:AbortSignal.timeout(5e3),body:JSON.stringify({sessionId:this.options.sessionId,agentType:"pi-coding-agent"})});if(!t.ok)throw new Error("managed_model_capability_issue_failed");const e=await t.json(),r=typeof e.expiresAt=="string"?Date.parse(e.expiresAt):NaN;if(typeof e.token!="string"||!/^pimc_[A-Za-z0-9_-]{43}$/.test(e.token)||e.model!=="deepseek-v4-flash-0731"||!Number.isFinite(r))throw new Error("managed_model_capability_response_invalid");return this.upstreamCapability=e.token,this.upstreamCapabilityExpiresAt=r,e.token}async revokeUpstreamCapability(){const t=this.upstreamCapability;this.upstreamCapability=null,this.upstreamCapabilityExpiresAt=0,t&&await(this.options.fetchImpl??fetch)(`${this.options.serverUrl.replace(/\/$/,"")}/api/managed-model/v1/capabilities`,{method:"DELETE",headers:{authorization:`Bearer ${t}`},signal:AbortSignal.timeout(5e3)}).catch(()=>{})}}export{C as PiManagedModelBroker};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{loadConfig as s}from"../../config/index.js";import{regionToUrl as d}from"../../region.js";async function h(){const i=s();if(!i.machineToken)throw new Error("401 machine authentication required");return l(i.serverUrl||d("cn"),i.machineToken)}async function l(i,o,t=fetch){const n=`${i.replace(/\/$/,"")}/api/managed-model/v1/validation-sessions`,r=await t(n,{method:"POST",headers:{authorization:`Bearer ${o}`},signal:AbortSignal.timeout(5e3)});if(r.status===404)throw new Error("agent_validation_server_upgrade_required");if(!r.ok)throw new Error(`Pi validation registration failed (${r.status})`);const e=await r.json();if(typeof e.sessionId!="string"||!/^pi-validation-[0-9a-f-]{36}$/.test(e.sessionId))throw new Error("Pi validation registration returned an invalid session");const a=e.sessionId;return{sessionId:a,async dispose(){try{if(!(await t(`${n}/${a}`,{method:"DELETE",headers:{authorization:`Bearer ${o}`},signal:AbortSignal.timeout(5e3)})).ok)throw new Error("agent_validation_cleanup_failed")}catch{throw new Error("agent_validation_cleanup_failed")}}}}export{l as createPiValidationSession,h as registerPiValidationSession};
|