shennian 0.5.12 → 0.5.13

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.
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "jsMinified": true,
4
4
  "minifier": "esbuild",
5
- "fileCount": 256,
5
+ "fileCount": 264,
6
6
  "files": [
7
7
  {
8
8
  "file": "bin/shennian-adapter-host.js",
@@ -51,8 +51,8 @@
51
51
  },
52
52
  {
53
53
  "file": "src/agents/acp/adapter.js",
54
- "beforeBytes": 26392,
55
- "afterBytes": 13813
54
+ "beforeBytes": 27928,
55
+ "afterBytes": 14294
56
56
  },
57
57
  {
58
58
  "file": "src/agents/acp/auth-state.js",
@@ -136,8 +136,8 @@
136
136
  },
137
137
  {
138
138
  "file": "src/agents/claude.js",
139
- "beforeBytes": 21692,
140
- "afterBytes": 10167
139
+ "beforeBytes": 22170,
140
+ "afterBytes": 10367
141
141
  },
142
142
  {
143
143
  "file": "src/agents/codex-managed-permissions.js",
@@ -166,13 +166,13 @@
166
166
  },
167
167
  {
168
168
  "file": "src/agents/codex.js",
169
- "beforeBytes": 36353,
170
- "afterBytes": 19396
169
+ "beforeBytes": 36771,
170
+ "afterBytes": 19653
171
171
  },
172
172
  {
173
173
  "file": "src/agents/command-spec.js",
174
- "beforeBytes": 21138,
175
- "afterBytes": 9486
174
+ "beforeBytes": 21633,
175
+ "afterBytes": 9644
176
176
  },
177
177
  {
178
178
  "file": "src/agents/config-status.js",
@@ -181,13 +181,13 @@
181
181
  },
182
182
  {
183
183
  "file": "src/agents/cursor-managed-permissions.js",
184
- "beforeBytes": 12138,
185
- "afterBytes": 5991
184
+ "beforeBytes": 13555,
185
+ "afterBytes": 6231
186
186
  },
187
187
  {
188
188
  "file": "src/agents/cursor.js",
189
- "beforeBytes": 12806,
190
- "afterBytes": 6155
189
+ "beforeBytes": 13229,
190
+ "afterBytes": 6440
191
191
  },
192
192
  {
193
193
  "file": "src/agents/custom-managed-runtime.js",
@@ -201,8 +201,8 @@
201
201
  },
202
202
  {
203
203
  "file": "src/agents/custom.js",
204
- "beforeBytes": 22815,
205
- "afterBytes": 12166
204
+ "beforeBytes": 23006,
205
+ "afterBytes": 12301
206
206
  },
207
207
  {
208
208
  "file": "src/agents/detect.js",
@@ -286,13 +286,13 @@
286
286
  },
287
287
  {
288
288
  "file": "src/agents/opencode-managed-permissions.js",
289
- "beforeBytes": 7040,
290
- "afterBytes": 3492
289
+ "beforeBytes": 9194,
290
+ "afterBytes": 3781
291
291
  },
292
292
  {
293
293
  "file": "src/agents/opencode.js",
294
- "beforeBytes": 14292,
295
- "afterBytes": 7094
294
+ "beforeBytes": 17506,
295
+ "afterBytes": 8068
296
296
  },
297
297
  {
298
298
  "file": "src/agents/pi-coding-agent-managed-permissions.js",
@@ -301,8 +301,8 @@
301
301
  },
302
302
  {
303
303
  "file": "src/agents/pi-coding-agent.js",
304
- "beforeBytes": 28446,
305
- "afterBytes": 15071
304
+ "beforeBytes": 29371,
305
+ "afterBytes": 15448
306
306
  },
307
307
  {
308
308
  "file": "src/agents/pi-managed-extension.js",
@@ -336,8 +336,33 @@
336
336
  },
337
337
  {
338
338
  "file": "src/agents/public-agent-client.js",
339
- "beforeBytes": 3499,
340
- "afterBytes": 2070
339
+ "beforeBytes": 8149,
340
+ "afterBytes": 4865
341
+ },
342
+ {
343
+ "file": "src/agents/public-delivery-client.js",
344
+ "beforeBytes": 8361,
345
+ "afterBytes": 5063
346
+ },
347
+ {
348
+ "file": "src/agents/public-delivery-worker.js",
349
+ "beforeBytes": 7496,
350
+ "afterBytes": 3715
351
+ },
352
+ {
353
+ "file": "src/agents/public-reply-collector.js",
354
+ "beforeBytes": 4534,
355
+ "afterBytes": 1776
356
+ },
357
+ {
358
+ "file": "src/agents/public-turn-runner.js",
359
+ "beforeBytes": 6301,
360
+ "afterBytes": 3920
361
+ },
362
+ {
363
+ "file": "src/agents/public-workdir.js",
364
+ "beforeBytes": 2236,
365
+ "afterBytes": 1227
341
366
  },
342
367
  {
343
368
  "file": "src/agents/runtime-compatibility.js",
@@ -356,13 +381,13 @@
356
381
  },
357
382
  {
358
383
  "file": "src/agents/workbuddy-managed-permissions.js",
359
- "beforeBytes": 13486,
360
- "afterBytes": 6431
384
+ "beforeBytes": 15241,
385
+ "afterBytes": 6763
361
386
  },
362
387
  {
363
388
  "file": "src/agents/workbuddy.js",
364
- "beforeBytes": 18443,
365
- "afterBytes": 9602
389
+ "beforeBytes": 18932,
390
+ "afterBytes": 9931
366
391
  },
367
392
  {
368
393
  "file": "src/commands/adapter.js",
@@ -376,8 +401,8 @@
376
401
  },
377
402
  {
378
403
  "file": "src/commands/agent-workspace.js",
379
- "beforeBytes": 10802,
380
- "afterBytes": 6752
404
+ "beforeBytes": 18502,
405
+ "afterBytes": 12357
381
406
  },
382
407
  {
383
408
  "file": "src/commands/agent.js",
@@ -601,8 +626,8 @@
601
626
  },
602
627
  {
603
628
  "file": "src/index.js",
604
- "beforeBytes": 43613,
605
- "afterBytes": 21576
629
+ "beforeBytes": 45207,
630
+ "afterBytes": 22296
606
631
  },
607
632
  {
608
633
  "file": "src/log-redaction.js",
@@ -686,8 +711,8 @@
686
711
  },
687
712
  {
688
713
  "file": "src/native-fusion/local-repository.js",
689
- "beforeBytes": 28392,
690
- "afterBytes": 13832
714
+ "beforeBytes": 28619,
715
+ "afterBytes": 13945
691
716
  },
692
717
  {
693
718
  "file": "src/native-fusion/native-source-deletions.js",
@@ -739,6 +764,11 @@
739
764
  "beforeBytes": 5783,
740
765
  "afterBytes": 3130
741
766
  },
767
+ {
768
+ "file": "src/native-fusion/test-workspace.js",
769
+ "beforeBytes": 977,
770
+ "afterBytes": 429
771
+ },
742
772
  {
743
773
  "file": "src/native-fusion/types.js",
744
774
  "beforeBytes": 54,
@@ -919,6 +949,11 @@
919
949
  "beforeBytes": 2475,
920
950
  "afterBytes": 1710
921
951
  },
952
+ {
953
+ "file": "src/security/macos-file-sandbox.js",
954
+ "beforeBytes": 3767,
955
+ "afterBytes": 1123
956
+ },
922
957
  {
923
958
  "file": "src/security/managed-agent-credential-paths.js",
924
959
  "beforeBytes": 1853,
@@ -931,14 +966,19 @@
931
966
  },
932
967
  {
933
968
  "file": "src/security/managed-agent-policy.js",
934
- "beforeBytes": 7684,
935
- "afterBytes": 3719
969
+ "beforeBytes": 8094,
970
+ "afterBytes": 3763
936
971
  },
937
972
  {
938
973
  "file": "src/security/managed-agent-runtime.js",
939
974
  "beforeBytes": 7393,
940
975
  "afterBytes": 3348
941
976
  },
977
+ {
978
+ "file": "src/security/public-agent-policy.js",
979
+ "beforeBytes": 2554,
980
+ "afterBytes": 1144
981
+ },
942
982
  {
943
983
  "file": "src/session/archive-zip.js",
944
984
  "beforeBytes": 8037,
@@ -1,3 +1,3 @@
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(`
1
+ import{randomUUID as y}from"node:crypto";import{createHash as S}from"node:crypto";import{realpathSync as w}from"node:fs";import{pathToFileURL as v}from"node:url";import*as a from"@agentclientprotocol/sdk";import{RequestError as A}from"@agentclientprotocol/sdk";import{AgentAdapter as P,registerAgent as b}from"../adapter.js";import{mapAcpSessionUpdate as q}from"./events.js";import{AcpProcessClient as E}from"./process-client.js";import{acpAgentType as I}from"./types.js";import{runAcpTerminalAuthentication as T}from"./auth.js";import{setAcpRuntimeAuthState as p}from"./auth-state.js";import{recordAcpAuthFailure as x,recordAcpImportResult as C}from"./metrics.js";import{isManagedAgentNativeFull as m}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as O}from"../../agent-env.js";import{assertPublicAgentPolicy as _}from"../../security/public-agent-policy.js";function g(l,e){return l.find(t=>t.category===e&&t.type==="select")}function f(l){return(l?.options??[]).flatMap(e=>"options"in e?e.options:[e])}class k extends P{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;publicTurn=!1;baseConfigurationSignature="";startedConfigurationSignature="";constructor(e,t={}){super(),this.manifest=e,this.options=t,this.type=I(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.baseConfigurationSignature=S("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[n])=>t.localeCompare(n)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}get configurationSignature(){return`${this.baseConfigurationSignature}:${this.publicTurn?"public":"room"}`}async start(e,t,n){this.shennianSessionId=e;try{this.workDir=w.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,r){r?.source==="published_agent"&&_(this.managedAgentPolicy),this.publicTurn=r?.source==="published_agent",await this.refreshProcessConfiguration();const u=this.requireClient();this.runId=y(),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=[],c=[];s?.trim()&&c.push(s.trim()),c.push(e),o.push({type:"text",text:c.join(`
2
2
 
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};
3
+ `)});for(const d of i??[])o.push({type:"resource_link",uri:v(d.path).href,name:d.name,mimeType:d.mimeType,size:d.byteSize});const h=await this.promptWithTimeout(u,o);this.active=!1,h.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 c=o instanceof Error?o.message:String(o),h=o instanceof A&&o.code===-32e3;throw h&&(p(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:c,...h?{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(a.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=g(this.configOptions,"model"),t=g(this.configOptions,"thought_level"),n=this.modes?.availableModes.map(s=>({id:s.id,name:s.name,...s.description?{description:s.description}:{}}))??[],i=(t?f(t):n).map(s=>({id:"value"in s?s.value:s.id,name:s.name,...s.description?{description:s.description}:{}}));return{models:f(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 T({...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(),p(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,p(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 r=e.cwd;if(r)try{r=w.native(r)}catch{}const u=await t.listSessions(r,i);if(n.push(...u.sessions.slice(0,500-n.length).map(o=>({agentSessionId:o.sessionId,cwd:o.cwd,...o.title?{title:o.title.slice(0,200)}:{},...o.updatedAt?{updatedAt:o.updatedAt}:{}}))),i=u.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(a.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,C(!0)}catch(i){throw C(!1),i}finally{this.importCapture=null}return n.map((i,s)=>({sourceId:i.sourceHint??S("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(a.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(a.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(a.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(a.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=g(this.configOptions,i.category);!s||s.currentValue===i.value||f(s).some(r=>r.value===i.value)&&(await this.requireClient().agent.request(a.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(r=>r.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=y();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?m(this.managedAgentPolicy)?O(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?this.publicTurn?m(this.managedAgentPolicy)?{readTextFile:!!e.readTextFile,writeTextFile:!!e.writeTextFile,terminal:!1}:{readTextFile:!1,writeTextFile:!1,terminal:!1}:m(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(a.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 G(l){b(I(l.id),()=>new k(l))}export{k as AcpAgentAdapter,G as registerAcpAgent};
@@ -1,10 +1,10 @@
1
- import p from"node:fs";import o from"node:path";import{createInterface as S}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as E,registerAgent as x}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as v,spawnResolvedCommandSync as P}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";import{buildAgentProcessEnv as I,buildManagedAgentProcessEnv as k,buildManagedNativeFullProcessEnv as w}from"../agent-env.js";import{buildPlatformInstructions as g}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as A,isManagedAgentNativeFull as c}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as _}from"../security/managed-agent-runtime.js";import{resolveManagedRoomIpcPaths as R}from"../daemon-ipc/paths.js";import{CLAUDE_MANAGED_RUNTIME_SECURITY as T,compileClaudeManagedPermissions as N}from"./claude-managed-permissions.js";_("claude",T);function M(n){return n?.trim()||"default"}const O=new Set(["low","medium","high","xhigh","max"]),h=new Map;function D(n){const e=n?.trim();if(e){if(O.has(e))return e;throw new Error(`Unsupported Claude reasoning effort "${e}". Supported values: low, medium, high, xhigh, max.`)}}function te(){h.clear()}function L(n){const e=n.trim();return e?!e.includes("claude.ai connectors are disabled because"):!1}function F(){const n=m("claude");if(!n)return!1;const e=`${n.kind}:${n.path}:${n.command}:${n.args.join("\0")}`;if(h.has(e))return h.get(e)??!1;try{const t=P(n,["--help"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,env:process.env}),s=`${t.stdout??""}
2
- ${t.stderr??""}`,a=/(?:^|\s)--effort(?:\s|,|<)/.test(s);return h.set(e,a),a}catch{return h.set(e,!1),!1}}const y=64*1024;function U(n){const e=$(n);return e.length>y?`${e.slice(0,y)}
3
- \u2026[truncated]`:e}function $(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>{if(typeof e=="string")return e;if(typeof e!="object"||e===null)return"";const t=e;return typeof t.text=="string"?t.text:t.type==="image"?"[image]":""}).filter(Boolean).join(`
4
- `):""}class q extends E{options;type="claude";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;sessionId=null;workDir=null;seq=0;runId="";hasEmittedText=!1;toolNames=new Map;terminalState="open";authenticationRetrying=!1;pendingSuccess=null;persistNativeSession=!0;managedAgentPolicy=null;constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(e,t,s,a){this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=a?.persistNativeSession!==!1,s&&(this.agentSessionId=s)}async send(e,t,s,a,l,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=f(),this.resetRunState();const i=["-p",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]];this.persistNativeSession||i.push("--no-session-persistence");const u=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,l);u&&i.push("--append-system-prompt",u),this.options.hidden&&i.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&i.push("--dangerously-skip-permissions"),i.push("--model",M(t));const d=D(s);d&&F()&&i.push("--effort",d),this.agentSessionId&&i.push("--resume",this.agentSessionId),this.spawnAndParse(i)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=f(),this.resetRunState();const t=["--resume",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]],s=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);s&&t.push("--append-system-prompt",s),this.options.hidden&&t.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&t.push("--dangerously-skip-permissions"),this.spawnAndParse(t)}async stop(){await this.killProcess()}spawnAndParse(e){const t=m("claude");if(!t){this.emit("error",C(this.workDir,'Command "claude" not found. Is Claude Code CLI installed?'));return}const s=v(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=s,S({input:s.stdout}).on("line",r=>{if(r.trim())try{const i=JSON.parse(r);this.handleStreamEvent(i)}catch{}});let l="";s.stderr?.on("data",r=>{const i=r.toString();if(l+=i,this.terminalState==="open")for(const u of i.split(`
5
- `)){const d=u.trim();L(d)&&this.emitEvent({state:"delta",text:d+`
6
- `})}}),s.on("close",r=>{this.process===s&&(this.process=null,this.handleProcessClose(r,l))}),s.on("error",r=>{this.process===s&&(this.process=null,r.code==="ENOENT"?this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?')):this.emit("error",r))})}buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e||c(e))return null;const t=z();return N(A(e),e.adapterPolicy.workDir,{internalReadPaths:t.readPaths,internalUnixSockets:t.unixSockets,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}buildProcessEnv(){return this.managedAgentPolicy?c(this.managedAgentPolicy)?w({NO_COLOR:"1",...this.extraEnv}):k({agentType:"claude",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}}):I(this.extraEnv)}handleStreamEvent(e){if(e.type==="system"&&e.subtype==="init"&&e.session_id){this.agentSessionId=e.session_id,this.emitEvent({state:"start",agentSessionId:this.agentSessionId});return}if(e.type==="system"&&e.subtype==="api_retry"&&e.error==="authentication_failed"){this.authenticationRetrying=!0,this.emitEvent({state:"heartbeat",runPhase:"thinking",errorCode:"auth_retrying",message:"Claude authentication is retrying."});return}if(e.type==="assistant"){if(this.authenticationRetrying=!1,e.message?.content){for(const t of e.message.content)if(t.type==="text"&&t.text){const s=this.hasEmittedText?`
1
+ import p from"node:fs";import o from"node:path";import{createInterface as S}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as E,registerAgent as x}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as P,spawnResolvedCommandSync as v}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";import{buildAgentProcessEnv as I,buildManagedAgentProcessEnv as k,buildManagedNativeFullProcessEnv as A}from"../agent-env.js";import{buildPlatformInstructions as g}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as w,isManagedAgentNativeFull as c}from"../security/managed-agent-policy.js";import{assertPublicAgentPolicy as _}from"../security/public-agent-policy.js";import{registerManagedAgentRuntimeSecurity as R}from"../security/managed-agent-runtime.js";import{resolveManagedRoomIpcPaths as T}from"../daemon-ipc/paths.js";import{CLAUDE_MANAGED_RUNTIME_SECURITY as N,compileClaudeManagedPermissions as M}from"./claude-managed-permissions.js";R("claude",N);function O(n){return n?.trim()||"default"}const D=new Set(["low","medium","high","xhigh","max"]),h=new Map;function L(n){const e=n?.trim();if(e){if(D.has(e))return e;throw new Error(`Unsupported Claude reasoning effort "${e}". Supported values: low, medium, high, xhigh, max.`)}}function ne(){h.clear()}function F(n){const e=n.trim();return e?!e.includes("claude.ai connectors are disabled because"):!1}function U(){const n=m("claude");if(!n)return!1;const e=`${n.kind}:${n.path}:${n.command}:${n.args.join("\0")}`;if(h.has(e))return h.get(e)??!1;try{const t=v(n,["--help"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,env:process.env}),s=`${t.stdout??""}
2
+ ${t.stderr??""}`,a=/(?:^|\s)--effort(?:\s|,|<)/.test(s);return h.set(e,a),a}catch{return h.set(e,!1),!1}}const y=64*1024;function $(n){const e=q(n);return e.length>y?`${e.slice(0,y)}
3
+ \u2026[truncated]`:e}function q(n){return typeof n=="string"?n:Array.isArray(n)?n.map(e=>{if(typeof e=="string")return e;if(typeof e!="object"||e===null)return"";const t=e;return typeof t.text=="string"?t.text:t.type==="image"?"[image]":""}).filter(Boolean).join(`
4
+ `):""}class z extends E{options;type="claude";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;sessionId=null;workDir=null;seq=0;runId="";hasEmittedText=!1;toolNames=new Map;terminalState="open";authenticationRetrying=!1;pendingSuccess=null;persistNativeSession=!0;managedAgentPolicy=null;constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(e,t,s,a){this.sessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=a?.persistNativeSession!==!1,s&&(this.agentSessionId=s)}async send(e,t,s,a,l,r){if(r?.source==="published_agent"&&_(this.managedAgentPolicy),r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=f(),this.resetRunState();const i=["-p",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig(r?.source==="published_agent")?.args??[]];this.persistNativeSession||i.push("--no-session-persistence");const u=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,l);u&&i.push("--append-system-prompt",u),this.options.hidden&&i.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&i.push("--dangerously-skip-permissions"),i.push("--model",O(t));const d=L(s);d&&U()&&i.push("--effort",d),this.agentSessionId&&i.push("--resume",this.agentSessionId),this.spawnAndParse(i)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=f(),this.resetRunState();const t=["--resume",e,"--output-format","stream-json","--verbose",...this.buildManagedPermissionConfig()?.args??[]],s=this.options.systemPrompt??g(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);s&&t.push("--append-system-prompt",s),this.options.hidden&&t.push("--name","Shennian Manager Substrate"),(!this.managedAgentPolicy||c(this.managedAgentPolicy))&&process.getuid?.()!==0&&t.push("--dangerously-skip-permissions"),this.spawnAndParse(t)}async stop(){await this.killProcess()}spawnAndParse(e){const t=m("claude");if(!t){this.emit("error",C(this.workDir,'Command "claude" not found. Is Claude Code CLI installed?'));return}const s=P(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=s,S({input:s.stdout}).on("line",r=>{if(r.trim())try{const i=JSON.parse(r);this.handleStreamEvent(i)}catch{}});let l="";s.stderr?.on("data",r=>{const i=r.toString();if(l+=i,this.terminalState==="open")for(const u of i.split(`
5
+ `)){const d=u.trim();F(d)&&this.emitEvent({state:"delta",text:d+`
6
+ `})}}),s.on("close",r=>{this.process===s&&(this.process=null,this.handleProcessClose(r,l))}),s.on("error",r=>{this.process===s&&(this.process=null,r.code==="ENOENT"?this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?')):this.emit("error",r))})}buildManagedPermissionConfig(e=!1){const t=this.managedAgentPolicy;if(!t||c(t))return null;const s=e?{readPaths:[],unixSockets:[]}:G();return M(w(t),t.adapterPolicy.workDir,{internalReadPaths:s.readPaths,internalUnixSockets:s.unixSockets,shellSubprocessPolicy:t.environmentPolicy.shellSubprocess})}buildProcessEnv(){return this.managedAgentPolicy?c(this.managedAgentPolicy)?A({NO_COLOR:"1",...this.extraEnv}):k({agentType:"claude",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}}):I(this.extraEnv)}handleStreamEvent(e){if(e.type==="system"&&e.subtype==="init"&&e.session_id){this.agentSessionId=e.session_id,this.emitEvent({state:"start",agentSessionId:this.agentSessionId});return}if(e.type==="system"&&e.subtype==="api_retry"&&e.error==="authentication_failed"){this.authenticationRetrying=!0,this.emitEvent({state:"heartbeat",runPhase:"thinking",errorCode:"auth_retrying",message:"Claude authentication is retrying."});return}if(e.type==="assistant"){if(this.authenticationRetrying=!1,e.message?.content){for(const t of e.message.content)if(t.type==="text"&&t.text){const s=this.hasEmittedText?`
7
7
 
8
8
  `:"";this.emitEvent({state:"delta",text:s+t.text}),this.hasEmittedText=!0}else t.type==="thinking"&&t.thinking?this.emitEvent({state:"delta",text:t.thinking,thinking:!0}):t.type==="tool_use"&&(t.id&&t.name&&this.toolNames.set(t.id,t.name),this.emitEvent({state:"tool-call",name:t.name,args:t.input,...t.id?{toolCallId:t.id}:{}}));return}if(e.subtype==="text"&&e.text){const t=this.hasEmittedText?`
9
9
 
10
- `:"";this.emitEvent({state:"delta",text:t+e.text}),this.hasEmittedText=!0}else e.subtype==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.subtype==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});return}if(e.type==="user"){for(const t of e.message?.content??[])t.type!=="tool_result"||!t.tool_use_id||this.emitEvent({state:"tool-result",name:this.toolNames.get(t.tool_use_id),toolCallId:t.tool_use_id,toolStatus:t.is_error===!0?"failed":"completed",result:U(t.content)});return}if(e.type==="result")if(e.subtype==="tool_result"){const t=typeof e.content=="string"?e.content:JSON.stringify(e.content);this.emitEvent({state:"tool-result",name:e.name,result:t})}else if(e.subtype==="success"){e.session_id&&(this.agentSessionId=e.session_id);const t=typeof e.result=="string"?e.result:"";!this.hasEmittedText&&t.trim()&&(this.emitEvent({state:"delta",text:t}),this.hasEmittedText=!0);const s=e.usage??e.message?.usage;this.pendingSuccess={agentSessionId:this.agentSessionId??void 0,usage:s?{inputTokens:s.input_tokens,outputTokens:s.output_tokens}:void 0}}else e.subtype==="error"&&this.emitErrorIfOpen({state:"error",message:e.error??e.result??"unknown error",...this.authenticationRetrying?{errorCode:"auth_required"}:{}})}handleProcessClose(e,t){if(e!==0&&e!==null){const s=t.trim()||`claude exited with code ${e}`;this.emitErrorIfOpen({state:"error",message:s,...this.authenticationRetrying?{errorCode:"auth_required"}:{}});return}if(!this.hasEmittedText){this.emitErrorIfOpen({state:"error",message:"Claude completed without response text"});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.pendingSuccess?.agentSessionId??this.agentSessionId??void 0,usage:this.pendingSuccess?.usage})}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="final",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.emitEvent(e))}resetRunState(){this.seq=0,this.hasEmittedText=!1,this.toolNames.clear(),this.terminalState="open",this.authenticationRetrying=!1,this.pendingSuccess=null}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}))}}function z(){const n=R(),e=[n.secretFile],t=n.transport==="unix_socket"?[n.endpoint]:[];n.transport==="unix_socket"&&e.push(n.endpoint);const s=m("pi");return s?.path&&e.push(...G(s.path)),{readPaths:[...new Set(e)].sort(),unixSockets:[...new Set(t)].sort()}}function G(n){const e=o.normalize(n.trim());if(!e||!o.isAbsolute(e))return[];const t=[e];try{const s=p.realpathSync(e);t.push(s,o.dirname(s),o.dirname(o.dirname(s)));let a=o.dirname(s);for(let l=0;l<8;l+=1){const r=o.join(a,"package.json");try{if(JSON.parse(p.readFileSync(r,"utf8")).name==="shennian"){t.push(a);break}}catch{}const i=o.dirname(a);if(i===a)break;a=i}}catch{}return[...new Set(t)].sort()}x("claude",()=>new q);export{q as ClaudeAdapter,M as normalizeClaudeModelId,D as normalizeClaudeReasoningEffort,te as resetClaudeCapabilityCacheForTests,z as resolveClaudeManagedInternalAccess,G as resolveClaudeShennianCliReadPaths,L as shouldForwardClaudeStderrLine,F as supportsClaudeReasoningEffort};
10
+ `:"";this.emitEvent({state:"delta",text:t+e.text}),this.hasEmittedText=!0}else e.subtype==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.subtype==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});return}if(e.type==="user"){for(const t of e.message?.content??[])t.type!=="tool_result"||!t.tool_use_id||this.emitEvent({state:"tool-result",name:this.toolNames.get(t.tool_use_id),toolCallId:t.tool_use_id,toolStatus:t.is_error===!0?"failed":"completed",result:$(t.content)});return}if(e.type==="result")if(e.subtype==="tool_result"){const t=typeof e.content=="string"?e.content:JSON.stringify(e.content);this.emitEvent({state:"tool-result",name:e.name,result:t})}else if(e.subtype==="success"){e.session_id&&(this.agentSessionId=e.session_id);const t=typeof e.result=="string"?e.result:"";!this.hasEmittedText&&t.trim()&&(this.emitEvent({state:"delta",text:t}),this.hasEmittedText=!0);const s=e.usage??e.message?.usage;this.pendingSuccess={agentSessionId:this.agentSessionId??void 0,usage:s?{inputTokens:s.input_tokens,outputTokens:s.output_tokens}:void 0}}else e.subtype==="error"&&this.emitErrorIfOpen({state:"error",message:e.error??e.result??"unknown error",...this.authenticationRetrying?{errorCode:"auth_required"}:{}})}handleProcessClose(e,t){if(e!==0&&e!==null){const s=t.trim()||`claude exited with code ${e}`;this.emitErrorIfOpen({state:"error",message:s,...this.authenticationRetrying?{errorCode:"auth_required"}:{}});return}if(!this.hasEmittedText){this.emitErrorIfOpen({state:"error",message:"Claude completed without response text"});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.pendingSuccess?.agentSessionId??this.agentSessionId??void 0,usage:this.pendingSuccess?.usage})}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="final",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.emitEvent(e))}resetRunState(){this.seq=0,this.hasEmittedText=!1,this.toolNames.clear(),this.terminalState="open",this.authenticationRetrying=!1,this.pendingSuccess=null}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}async killProcess(){const e=this.process;e&&(this.process=null,e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},3e3)}))}}function G(){const n=T(),e=[n.secretFile],t=n.transport==="unix_socket"?[n.endpoint]:[];n.transport==="unix_socket"&&e.push(n.endpoint);const s=m("pi");return s?.path&&e.push(...b(s.path)),{readPaths:[...new Set(e)].sort(),unixSockets:[...new Set(t)].sort()}}function b(n){const e=o.normalize(n.trim());if(!e||!o.isAbsolute(e))return[];const t=[e];try{const s=p.realpathSync(e);t.push(s,o.dirname(s),o.dirname(o.dirname(s)));let a=o.dirname(s);for(let l=0;l<8;l+=1){const r=o.join(a,"package.json");try{if(JSON.parse(p.readFileSync(r,"utf8")).name==="shennian"){t.push(a);break}}catch{}const i=o.dirname(a);if(i===a)break;a=i}}catch{}return[...new Set(t)].sort()}x("claude",()=>new z);export{z as ClaudeAdapter,O as normalizeClaudeModelId,L as normalizeClaudeReasoningEffort,ne as resetClaudeCapabilityCacheForTests,G as resolveClaudeManagedInternalAccess,b as resolveClaudeShennianCliReadPaths,F as shouldForwardClaudeStderrLine,U as supportsClaudeReasoningEffort};
@@ -1,3 +1,3 @@
1
- import{CODEX_DESKTOP_SEND_UNAVAILABLE as v}from"@shennian/wire";import{createHash as y,randomUUID as A}from"node:crypto";import S from"node:path";import{createInterface as x}from"node:readline";import{buildAgentProcessEnv as M,buildManagedAgentProcessEnv as N,buildManagedNativeFullProcessEnv as b}from"../agent-env.js";import{isCodexThreadTailInterrupted as O}from"../native-fusion/codex-files.js";import{isManagedAgentNativeFull as I,resolveManagedAgentAdapterEnforcement as k}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as D}from"../security/managed-agent-runtime.js";import{registerAgent as L}from"./adapter.js";import{CODEX_MANAGED_RUNTIME_SECURITY as j,assertCodexManagedPermissionProfile as T,compileCodexManagedPermissions as F,extractCodexMcpServerNames as q}from"./codex-managed-permissions.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as U,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as B}from"./codex-managed-room-tools.js";import{CODEX_APP_SERVER_CLIENT_INFO as W,isCodexUnsupportedEffortError as z,isMissingCodexRolloutError as _,normalizeCodexModelId as p,normalizeCodexReasoningEffort as G,normalizeCodexStderr as H}from"./codex-utils.js";import{resolveBuiltinCommand as K,spawnAgentCommand as f}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";const w="codex_command_unavailable: \u8BF7\u786E\u8BA4 Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\u3002";import{ensurePlatformInstructionsFile as $}from"./platform-instructions.js";import{buildCodexQueueArgs as xe,buildCodexQueuedText as Ie,isCodexActiveWriterError as Te,isCodexExcludeTurnsUnsupportedError as _e,isCodexPaginatedHistoryUnsupportedError as Ce,isCodexProjectApiUnsupportedError as Ee,selectCodexProjectIdForWorkDir as Re}from"./codex-protocol.js";import{isCodexUnsupportedEffortError as Ae,isMissingCodexRolloutError as Me,normalizeCodexModelId as Ne,normalizeCodexReasoningEffort as be}from"./codex-utils.js";import{buildCodexQueueArgs as V,buildCodexTextInput as E,isCodexActiveWriterError as R,isCodexExcludeTurnsUnsupportedError as X,isCodexPaginatedHistoryUnsupportedError as J,isCodexProjectApiUnsupportedError as Q,selectCodexProjectIdForWorkDir as Y}from"./codex-protocol.js";import{CodexRuntime as Z}from"./codex-runtime.js";D("codex",j);class ee extends Z{get supportsActiveInput(){return!0}async injectActiveInput(e){const i=this.agentSessionId,r=this.activeTurnId;if(!i||!r||!this.process)throw new Error("codex_active_turn_unavailable");const s=await this.sendRpc("turn/steer",{threadId:i,expectedTurnId:r,input:[E(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(s.turnId&&s.turnId!==r)throw new Error("codex_active_turn_changed")}launchCommand=null;resolveLaunchCommand(){if(this.process&&this.launchCommand)return this.launchCommand;const e=K("codex");if(!e||process.platform==="win32"&&e.kind==="wsl-bridge")throw new Error(process.platform==="win32"?"codex_windows_runtime_unavailable: \u8BF7\u786E\u8BA4 Windows Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5230 WSL\uFF0C\u5F85\u53D1\u9001\u6D88\u606F\u4FDD\u7559\u3002":w);return this.launchCommand=e,e}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}configure(e){const i=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const r=this.configurationFingerprint();i!==r&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(i=>[i,this.extraEnv[i]??null]);return y("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return M({...e,...this.extraEnv});if(I(this.managedAgentPolicy))return b({...e,...this.extraEnv});const i=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return N({agentType:"codex",providerEnv:i,sessionEnv:i,runtimeEnv:e})}async start(e,i,r,s){this.shennianSessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??i,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,this.nativeSessionVisibility=s?.nativeSessionVisibility??"user",r&&(this.agentSessionId=r),this.notifyNativeSession()}async prepareSend(e,i,r,s,o,t){const n=o?.trim()??"";if(n!==this.agentSystemPrompt&&(this.agentSystemPrompt=n,this.process&&await this.killProcess(!0)),!this.activeTurnId){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(p(i))}catch(a){if(!R(a)||!this.agentSessionId)throw a;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:a});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:a});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,i,r,s,o,t){if((t?.source==="room_activation"||t?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((t?.source==="room_activation"||t?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const n=t?.source==="room_activation"||t?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=p(i),h=G(r),d=o?.trim()??"";if(d!==this.agentSystemPrompt&&(this.agentSystemPrompt=d,this.process&&await this.killProcess(!0)),(t?.source==="room_activation"||t?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=A(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)};this.managedRoomCapabilityExpectedForTurn=n;try{await this.ensureAppServer(a)}catch(c){if(!this.agentSessionId||!R(c))throw c;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:c});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:c});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:h,attachments:s,recoveryCount:0}:null;const u=await this.startTurnWithRecovery(l,e,a,h,s),m=this.agentSessionId??l;if(this.activeTurnId=u.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===m&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??O(e)}async enqueueForExternalOwner(e,i,r){if(this.options.hidden||this.nativeSessionVisibility==="internal")throw new Error("codex_managed_thread_owned_externally");const s=this.resolveLaunchCommand(),o=V(e,i,r),t=f(s,o,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((n,a)=>{let h="",d="",l=!1;const u=(c,g)=>{l||(l=!0,clearTimeout(m),c?a(c):n(g))},m=setTimeout(()=>{t.kill("SIGTERM"),u(new Error("Codex Desktop message queue timed out"))},6e4);m.unref?.(),t.stdout?.on("data",c=>{h+=c.toString()}),t.stderr?.on("data",c=>{d+=c.toString()}),t.once("error",c=>u(c)),t.once("close",c=>{const g=`${h}
2
- ${d}`.trim();if(c!==0){u(new Error(g||`codex queue exited with code ${c??"unknown"}`));return}const P=g.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];u(void 0,P)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,i,r){const s=e.trim(),o=i.replace(/\s+/g," ").trim();!s||!o||(this.agentSessionId=s,this.notifyNativeSession(),r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,name:o}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,i=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:i,runPhase:null,canStop:!1};let r=null;try{r=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const s=r?.type==="active"||!!i;return{active:s,runId:i,runPhase:s?this.mapThreadStatusToRunPhase(r):null,canStop:!!(s&&i&&this.process)}}spawnCodex(e){const i=this.resolveLaunchCommand(),r=f(i,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=r,x({input:r.stdout}).on("line",t=>{if(t.trim())try{const n=JSON.parse(t);this.handleStreamEvent(n)}catch{this.emitEvent({state:"delta",text:t})}});let o="";r.stderr?.on("data",t=>{o+=t.toString()}),r.on("close",t=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(t,o))}),r.on("error",t=>{this.process===r&&(this.process=null,t.code==="ENOENT"?this.emit("error",C(this.workDir,w)):this.emit("error",t))})}spawnAppServer(){const e=this.resolveLaunchCommand(),i=["app-server","--listen","stdio://"],r=this.options.modelInstructionsFile??$(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&i.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const s=f(e,i,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,x({input:s.stdout}).on("line",t=>{if(!t.trim())return;let n;try{n=JSON.parse(t)}catch{this.handleAppServerNonJsonStdout(t);return}this.handleAppServerMessage(n)}),s.stderr?.on("data",t=>{this.stderrBuf+=t.toString()}),s.on("close",t=>{if(this.process!==s)return;const n=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(H(this.stderrBuf)||`codex app-server exited with code ${t}`)),this.terminalState==="open"&&n&&this.handleProcessClose(t,this.stderrBuf)}),s.on("error",t=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(t),t.code==="ENOENT"?this.emit("error",C(this.workDir,w)):this.emit("error",t))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async i=>{throw this.appServerReady=null,await this.killProcess(),i}),this.appServerReady)}async initializeAppServer(e){const i=p(e);await this.sendRpc("initialize",{clientInfo:W,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!I(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const r=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor),s=this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?U:B,o=r?s.map(l=>l.name).join(`
3
- `):null;if(this.managedAgentPolicy&&r){if(this.managedRoomTools.isConfigured()||this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");await this.managedRoomTools.assertReady(this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?"manager.sessions.list":"status")}if(this.agentSessionId&&this.managedAgentPolicy&&r&&(this.agentSessionId!==this.managedRoomToolThreadId||this.managedRoomToolSurfaceKey!==o)){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null,this.managedRoomToolThreadId=null,this.managedRoomToolSurfaceKey=null}if(this.agentSessionId){const l={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...i?{model:i}:{}};let u;try{u=await this.sendRpc("thread/resume",{...l,excludeTurns:!0})}catch(m){if(!X(m))throw m;u=await this.sendRpc("thread/resume",l)}this.agentSessionId=u.thread?.id??this.agentSessionId,this.notifyNativeSession(),this.managedPermissionConfig&&T(u,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId,this.managedRoomToolSurfaceKey=o);return}const t=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,n=t?void 0:await this.resolveCodexProjectId(),a={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:t?"shennian_internal":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&r?{dynamicTools:s}:{},...n?{projectId:n}:{},...i?{model:i}:{}};let h;if(t&&!this.managedPermissionConfig)h=await this.sendRpc("thread/start",a);else try{h=await this.sendRpc("thread/start",{...a,historyMode:"paginated"})}catch(l){throw J(l)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:l}):l}const d=h.thread?.id;if(!d)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&T(h,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(d),this.managedRoomToolThreadId=d,this.managedRoomToolSurfaceKey=o),this.agentSessionId=d,this.notifyNativeSession()}notifyNativeSession(){this.agentSessionId&&this.emit("nativeSession","codex",this.agentSessionId)}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");if(!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor)&&!this.shennianSessionId)throw new Error("codex_managed_room_session_missing");const r=e.adapterPolicy.externalCapabilities.mcp?[]:q(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return F(k(e),e.adapterPolicy.workDir,{configuredMcpServerNames:r,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess,...this.shennianSessionId?{roomAttachmentSessionId:this.shennianSessionId}:{}})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const i=[];let r;do{const h=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});i.push(...h.data??[]),r=h.nextCursor}while(r);const s=Y(i,e);if(s)return s;const o=S.resolve(e),t=`shennian-project-${y("sha256").update(o).digest("hex")}`,a=(await this.sendRpc("project/create",{idempotencyKey:t,name:S.basename(o)||o,roots:[{path:o}],metadata:{createdBy:"Shennian"}})).project?.id;if(!a)throw new Error("codex app-server project/create returned no project id");return a}catch(i){throw Q(i)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:i}):i}}async startTurnWithRecovery(e,i,r,s,o){try{return await this.startTurn(e,i,r,s,o)}catch(t){if(!_(t))throw t;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,this.managedRoomToolSurfaceKey=null,await this.ensureAppServer(r);const n=this.agentSessionId;if(!n)throw new Error("codex app-server did not recreate the managed thread",{cause:t});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:n}),this.emitEvent({state:"start",agentSessionId:n}),await this.startFreshManagedTurnWithReadinessRetry(n,i,r,s,o)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,i,r,s,o)}}async startFreshManagedTurnWithReadinessRetry(e,i,r,s,o){const t=[0,100,300,1e3];let n;for(let a=0;a<t.length;a+=1){const h=t[a];h>0&&await new Promise(d=>setTimeout(d,h));try{const d=await this.startTurn(e,i,r,s,o);return a>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:a+1}),d}catch(d){if(n=d,!_(d)||a===t.length-1)throw d;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:a+2,delayMs:t[a+1]})}}throw n}logManagedThreadLifecycle(e,i){console.error(`[codex.managed] ${JSON.stringify({event:e,...i})}`)}async startTurn(e,i,r,s,o){try{return await this.sendRpc("turn/start",{threadId:e,input:[E(i,o)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...s?{effort:s}:{}})}catch(t){throw s&&z(t)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:t}):t}}async interruptActiveTurn(){const e=this.agentSessionId,i=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!i||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:i},5e3)}}L("codex",()=>new ee);export{ee as CodexAdapter,xe as buildCodexQueueArgs,Ie as buildCodexQueuedText,Te as isCodexActiveWriterError,_e as isCodexExcludeTurnsUnsupportedError,Ce as isCodexPaginatedHistoryUnsupportedError,Ee as isCodexProjectApiUnsupportedError,Ae as isCodexUnsupportedEffortError,Me as isMissingCodexRolloutError,Ne as normalizeCodexModelId,be as normalizeCodexReasoningEffort,Re as selectCodexProjectIdForWorkDir};
1
+ import{CODEX_DESKTOP_SEND_UNAVAILABLE as v}from"@shennian/wire";import{createHash as y,randomUUID as M}from"node:crypto";import S from"node:path";import{createInterface as I}from"node:readline";import{buildAgentProcessEnv as b,buildManagedAgentProcessEnv as N,buildManagedNativeFullProcessEnv as O}from"../agent-env.js";import{isCodexThreadTailInterrupted as k}from"../native-fusion/codex-files.js";import{isManagedAgentNativeFull as x,resolveManagedAgentAdapterEnforcement as D}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as L}from"../security/managed-agent-runtime.js";import{assertPublicAgentPolicy as T}from"../security/public-agent-policy.js";import{registerAgent as j}from"./adapter.js";import{CODEX_MANAGED_RUNTIME_SECURITY as F,assertCodexManagedPermissionProfile as _,compileCodexManagedPermissions as q,extractCodexMcpServerNames as U}from"./codex-managed-permissions.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as B,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as W}from"./codex-managed-room-tools.js";import{CODEX_APP_SERVER_CLIENT_INFO as z,isCodexUnsupportedEffortError as G,isMissingCodexRolloutError as C,normalizeCodexModelId as p,normalizeCodexReasoningEffort as H,normalizeCodexStderr as K}from"./codex-utils.js";import{resolveBuiltinCommand as $,spawnAgentCommand as f}from"./command-spec.js";import{spawnEnoentError as E}from"./spawn-errors.js";const w="codex_command_unavailable: \u8BF7\u786E\u8BA4 Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\u3002";import{ensurePlatformInstructionsFile as V}from"./platform-instructions.js";import{buildCodexQueueArgs as Te,buildCodexQueuedText as _e,isCodexActiveWriterError as Ce,isCodexExcludeTurnsUnsupportedError as Ee,isCodexPaginatedHistoryUnsupportedError as Re,isCodexProjectApiUnsupportedError as Pe,selectCodexProjectIdForWorkDir as Ae}from"./codex-protocol.js";import{isCodexUnsupportedEffortError as be,isMissingCodexRolloutError as Ne,normalizeCodexModelId as Oe,normalizeCodexReasoningEffort as ke}from"./codex-utils.js";import{buildCodexQueueArgs as X,buildCodexTextInput as R,isCodexActiveWriterError as P,isCodexExcludeTurnsUnsupportedError as J,isCodexPaginatedHistoryUnsupportedError as Q,isCodexProjectApiUnsupportedError as Y,selectCodexProjectIdForWorkDir as Z}from"./codex-protocol.js";import{CodexRuntime as ee}from"./codex-runtime.js";L("codex",F);class te extends ee{get supportsActiveInput(){return!0}async injectActiveInput(e){const i=this.agentSessionId,r=this.activeTurnId;if(!i||!r||!this.process)throw new Error("codex_active_turn_unavailable");const s=await this.sendRpc("turn/steer",{threadId:i,expectedTurnId:r,input:[R(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(s.turnId&&s.turnId!==r)throw new Error("codex_active_turn_changed")}launchCommand=null;resolveLaunchCommand(){if(this.process&&this.launchCommand)return this.launchCommand;const e=$("codex");if(!e||process.platform==="win32"&&e.kind==="wsl-bridge")throw new Error(process.platform==="win32"?"codex_windows_runtime_unavailable: \u8BF7\u786E\u8BA4 Windows Codex CLI \u8DEF\u5F84\u5E76\u5237\u65B0 AI \u5217\u8868\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5230 WSL\uFF0C\u5F85\u53D1\u9001\u6D88\u606F\u4FDD\u7559\u3002":w);return this.launchCommand=e,e}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}configure(e){const i=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const r=this.configurationFingerprint();i!==r&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(i=>[i,this.extraEnv[i]??null]);return y("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return b({...e,...this.extraEnv});if(x(this.managedAgentPolicy))return O({...e,...this.extraEnv});const i=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return N({agentType:"codex",providerEnv:i,sessionEnv:i,runtimeEnv:e})}async start(e,i,r,s){this.shennianSessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??i,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,this.nativeSessionVisibility=s?.nativeSessionVisibility??"user",r&&(this.agentSessionId=r),this.notifyNativeSession()}async prepareSend(e,i,r,s,o,t){t?.source==="published_agent"&&T(this.managedAgentPolicy);const n=o?.trim()??"";if(n!==this.agentSystemPrompt&&(this.agentSystemPrompt=n,this.process&&await this.killProcess(!0)),!this.activeTurnId){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(p(i))}catch(a){if(!P(a)||!this.agentSessionId)throw a;if(t?.source==="room_activation"||t?.source==="managed_private"||t?.source==="published_agent")throw new Error("codex_managed_thread_owned_externally",{cause:a});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:a});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,i,r,s,o,t){if(t?.source==="published_agent"&&T(this.managedAgentPolicy),(t?.source==="room_activation"||t?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((t?.source==="room_activation"||t?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const n=t?.source==="room_activation"||t?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=p(i),h=H(r),d=o?.trim()??"";if(d!==this.agentSystemPrompt&&(this.agentSystemPrompt=d,this.process&&await this.killProcess(!0)),(t?.source==="room_activation"||t?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=M(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)};this.managedRoomCapabilityExpectedForTurn=n;try{await this.ensureAppServer(a)}catch(c){if(!this.agentSessionId||!P(c))throw c;if(t?.source==="room_activation"||t?.source==="managed_private"||t?.source==="published_agent")throw new Error("codex_managed_thread_owned_externally",{cause:c});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(v,{cause:c});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:h,attachments:s,recoveryCount:0}:null;const u=await this.startTurnWithRecovery(l,e,a,h,s),m=this.agentSessionId??l;if(this.activeTurnId=u.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===m&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??k(e)}async enqueueForExternalOwner(e,i,r){if(this.options.hidden||this.nativeSessionVisibility==="internal")throw new Error("codex_managed_thread_owned_externally");const s=this.resolveLaunchCommand(),o=X(e,i,r),t=f(s,o,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((n,a)=>{let h="",d="",l=!1;const u=(c,g)=>{l||(l=!0,clearTimeout(m),c?a(c):n(g))},m=setTimeout(()=>{t.kill("SIGTERM"),u(new Error("Codex Desktop message queue timed out"))},6e4);m.unref?.(),t.stdout?.on("data",c=>{h+=c.toString()}),t.stderr?.on("data",c=>{d+=c.toString()}),t.once("error",c=>u(c)),t.once("close",c=>{const g=`${h}
2
+ ${d}`.trim();if(c!==0){u(new Error(g||`codex queue exited with code ${c??"unknown"}`));return}const A=g.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];u(void 0,A)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,i,r){const s=e.trim(),o=i.replace(/\s+/g," ").trim();!s||!o||(this.agentSessionId=s,this.notifyNativeSession(),r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,name:o}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,i=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:i,runPhase:null,canStop:!1};let r=null;try{r=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const s=r?.type==="active"||!!i;return{active:s,runId:i,runPhase:s?this.mapThreadStatusToRunPhase(r):null,canStop:!!(s&&i&&this.process)}}spawnCodex(e){const i=this.resolveLaunchCommand(),r=f(i,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=r,I({input:r.stdout}).on("line",t=>{if(t.trim())try{const n=JSON.parse(t);this.handleStreamEvent(n)}catch{this.emitEvent({state:"delta",text:t})}});let o="";r.stderr?.on("data",t=>{o+=t.toString()}),r.on("close",t=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(t,o))}),r.on("error",t=>{this.process===r&&(this.process=null,t.code==="ENOENT"?this.emit("error",E(this.workDir,w)):this.emit("error",t))})}spawnAppServer(){const e=this.resolveLaunchCommand(),i=["app-server","--listen","stdio://"],r=this.options.modelInstructionsFile??V(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&i.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const s=f(e,i,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,I({input:s.stdout}).on("line",t=>{if(!t.trim())return;let n;try{n=JSON.parse(t)}catch{this.handleAppServerNonJsonStdout(t);return}this.handleAppServerMessage(n)}),s.stderr?.on("data",t=>{this.stderrBuf+=t.toString()}),s.on("close",t=>{if(this.process!==s)return;const n=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(K(this.stderrBuf)||`codex app-server exited with code ${t}`)),this.terminalState==="open"&&n&&this.handleProcessClose(t,this.stderrBuf)}),s.on("error",t=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(t),t.code==="ENOENT"?this.emit("error",E(this.workDir,w)):this.emit("error",t))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async i=>{throw this.appServerReady=null,await this.killProcess(),i}),this.appServerReady)}async initializeAppServer(e){const i=p(e);await this.sendRpc("initialize",{clientInfo:z,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!x(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const r=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor),s=this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?B:W,o=r?s.map(l=>l.name).join(`
3
+ `):null;if(this.managedAgentPolicy&&r){if(this.managedRoomTools.isConfigured()||this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");await this.managedRoomTools.assertReady(this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?"manager.sessions.list":"status")}if(this.agentSessionId&&this.managedAgentPolicy&&r&&(this.agentSessionId!==this.managedRoomToolThreadId||this.managedRoomToolSurfaceKey!==o)){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null,this.managedRoomToolThreadId=null,this.managedRoomToolSurfaceKey=null}if(this.agentSessionId){const l={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...i?{model:i}:{}};let u;try{u=await this.sendRpc("thread/resume",{...l,excludeTurns:!0})}catch(m){if(!J(m))throw m;u=await this.sendRpc("thread/resume",l)}this.agentSessionId=u.thread?.id??this.agentSessionId,this.notifyNativeSession(),this.managedPermissionConfig&&_(u,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId,this.managedRoomToolSurfaceKey=o);return}const t=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,n=t?void 0:await this.resolveCodexProjectId(),a={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:t?"shennian_internal":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&r?{dynamicTools:s}:{},...n?{projectId:n}:{},...i?{model:i}:{}};let h;if(t&&!this.managedPermissionConfig)h=await this.sendRpc("thread/start",a);else try{h=await this.sendRpc("thread/start",{...a,historyMode:"paginated"})}catch(l){throw Q(l)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:l}):l}const d=h.thread?.id;if(!d)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&_(h,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(d),this.managedRoomToolThreadId=d,this.managedRoomToolSurfaceKey=o),this.agentSessionId=d,this.notifyNativeSession()}notifyNativeSession(){this.agentSessionId&&this.emit("nativeSession","codex",this.agentSessionId)}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");if(!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor)&&!this.shennianSessionId)throw new Error("codex_managed_room_session_missing");const r=e.adapterPolicy.externalCapabilities.mcp?[]:U(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return q(D(e),e.adapterPolicy.workDir,{configuredMcpServerNames:r,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess,...this.shennianSessionId?{roomAttachmentSessionId:this.shennianSessionId}:{}})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const i=[];let r;do{const h=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});i.push(...h.data??[]),r=h.nextCursor}while(r);const s=Z(i,e);if(s)return s;const o=S.resolve(e),t=`shennian-project-${y("sha256").update(o).digest("hex")}`,a=(await this.sendRpc("project/create",{idempotencyKey:t,name:S.basename(o)||o,roots:[{path:o}],metadata:{createdBy:"Shennian"}})).project?.id;if(!a)throw new Error("codex app-server project/create returned no project id");return a}catch(i){throw Y(i)?new Error("codex_session_capability_unavailable: \u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:i}):i}}async startTurnWithRecovery(e,i,r,s,o){try{return await this.startTurn(e,i,r,s,o)}catch(t){if(!C(t))throw t;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,this.managedRoomToolSurfaceKey=null,await this.ensureAppServer(r);const n=this.agentSessionId;if(!n)throw new Error("codex app-server did not recreate the managed thread",{cause:t});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:n}),this.emitEvent({state:"start",agentSessionId:n}),await this.startFreshManagedTurnWithReadinessRetry(n,i,r,s,o)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,i,r,s,o)}}async startFreshManagedTurnWithReadinessRetry(e,i,r,s,o){const t=[0,100,300,1e3];let n;for(let a=0;a<t.length;a+=1){const h=t[a];h>0&&await new Promise(d=>setTimeout(d,h));try{const d=await this.startTurn(e,i,r,s,o);return a>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:a+1}),d}catch(d){if(n=d,!C(d)||a===t.length-1)throw d;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:a+2,delayMs:t[a+1]})}}throw n}logManagedThreadLifecycle(e,i){console.error(`[codex.managed] ${JSON.stringify({event:e,...i})}`)}async startTurn(e,i,r,s,o){try{return await this.sendRpc("turn/start",{threadId:e,input:[R(i,o)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...s?{effort:s}:{}})}catch(t){throw s&&G(t)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:t}):t}}async interruptActiveTurn(){const e=this.agentSessionId,i=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!i||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:i},5e3)}}j("codex",()=>new te);export{te as CodexAdapter,Te as buildCodexQueueArgs,_e as buildCodexQueuedText,Ce as isCodexActiveWriterError,Ee as isCodexExcludeTurnsUnsupportedError,Re as isCodexPaginatedHistoryUnsupportedError,Pe as isCodexProjectApiUnsupportedError,be as isCodexUnsupportedEffortError,Ne as isMissingCodexRolloutError,Oe as normalizeCodexModelId,ke as normalizeCodexReasoningEffort,Ae as selectCodexProjectIdForWorkDir};
@@ -1,4 +1,4 @@
1
- import{spawn as A,spawnSync as b}from"node:child_process";import l from"node:fs";import $ from"node:crypto";import S from"node:os";import s from"node:path";import{resetWindowsInstallationPaths as z,windowsLookupPath as O,windowsCodexDesktopCandidates as _}from"./windows-agent-paths.js";const W={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,p=new Map;function rn(){z(),m.clear(),f.clear(),h.clear(),p.clear()}function d(){return process.platform}function q(n){return n.split(/\r?\n/).map(t=>t.trim()).filter(Boolean)}function v(n){if(s.basename(n)!==n)return[n];const t=S.homedir();if(d()==="win32"){const i=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],a=process.env.APPDATA||i.join(t,"AppData","Roaming"),u=process.env.LOCALAPPDATA||i.join(t,"AppData","Local"),P=[i.join(t,".shennian","node"),i.join("C:\\","nvm4w","nodejs"),i.join(u,"npm-global"),i.join(a,"npm"),i.join(u,"pnpm"),i.join(t,"scoop","shims"),i.join("C:\\","Program Files","nodejs")].flatMap(x=>r.map(C=>i.join(x,C)));if(n==="codebuddy"){const x=[i.join(u,"Programs","WorkBuddy"),i.join(u,"WorkBuddy"),i.join("C:\\","Program Files","WorkBuddy")];for(const C of x)for(const V of["codebuddy.exe","codebuddy.cmd","codebuddy"])P.push(i.join(C,"resources","app.asar.unpacked","cli","bin",V))}return P}const o=[s.join(t,".npm-global","bin"),s.join(t,".local","bin"),s.join(t,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(i=>s.join(i,n));return n==="claude"&&d()==="darwin"&&o.push(...U(t)),n==="codebuddy"&&d()==="darwin"&&o.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(t,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),o}function B(n=d(),t=S.homedir()){return n==="win32"?_(t):n!=="darwin"?[]:["/Applications",s.join(t,"Applications")].flatMap(e=>["ChatGPT.app","Codex.app"].map(o=>s.join(e,o,"Contents","Resources","codex")))}function U(n){const t=[s.join(n,"Library","Application Support","Claude","claude-code")],e=[];for(const o of t){let i;try{i=l.readdirSync(o,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,a)=>a.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of i)e.push(s.join(o,r,"claude.app","Contents","MacOS","claude"))}return e}function H(n,t){const e=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="win32"){if(t&&s.basename(t)!==t){const o=s.win32.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.win32.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}if(t&&s.basename(t)!==t){const o=s.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const t=d()==="win32",o=b(t?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:t?O():H(process.env.PATH,n)}}),r=[...o.status===0?q(o.stdout??""):[]];for(const a of v(n))l.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function D(){return process.env.ComSpec||"cmd.exe"}function k(n){const t=s.extname(n).toLowerCase();return t===".exe"||t===".com"}function w(n){const t=s.extname(n).toLowerCase();return t===".cmd"||t===".bat"}function L(n){const t=s.extname(n).toLowerCase();return t===".js"||t===".mjs"||t===".cjs"}function M(){return c("node.exe")[0]??c("node")[0]??"node"}function E(n){return`"${n.replace(/"/g,'""')}"`}function y(n){return`'${n.replace(/'/g,"'\\''")}'`}function Z(n){if(!n)return;const t=n.replace(/\//g,"\\"),e=t.match(/^([A-Za-z]):\\(.*)$/);if(e){const[,o,i]=e,r=i.replace(/\\/g,"/");return`/mnt/${o.toLowerCase()}/${r}`}if(t.startsWith("\\\\wsl$\\"))return`/${t.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function N(n){const t=n.trim();if(!t)throw new Error("Command string is empty");if(/[\\/]/.test(t)||/^[A-Za-z]:/.test(t))return w(t)?{kind:"cmd-shim",path:t}:{kind:"direct",path:t};const o=c(t),i=o.find(k);if(i)return{kind:"direct",path:i};const r=o.find(w);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:t}}function T(n){if(p.has(n))return p.get(n)??!1;const t=c("wsl.exe")[0]??c("wsl")[0];if(!t)return p.set(n,!1),!1;const o=b(t,["-e","sh","-lc",`command -v ${y(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return p.set(n,o),o}function sn(n){if(m.has(n))return m.get(n)??!1;const t=c(n).length>0||d()==="win32"&&T(n);return m.set(n,t),t}function an(n){const t=c(n)[0];if(!t)return null;try{const e=l.realpathSync(t),o=l.statSync(e,{bigint:!0}),i=$.createHash("sha256").update(e).digest("hex"),r=$.createHash("sha256").update(`${o.dev}:${o.ino}:${o.size}:${o.mtimeNs}`).digest("hex");return{pathHash:i,fingerprint:r}}catch{return null}}function dn(n){return c(n)[0]??null}function G(n){const t=c(n.command);if(n.command==="codex"){const i=process.env.SHENNIAN_CODEX_PATH?.trim(),r=i?[i]:[...t,...B()];for(const a of r){if(i&&!s.win32.isAbsolute(a))return null;const u=k(a)?"native":w(a)?"cmd-shim":null;if(!u)continue;const g={...n,kind:u,path:a};if(I("codex",g))return g}return null}const e=t.find(k);if(e)return{...n,kind:"native",path:e};const o=t.find(w);if(o)return{...n,kind:"cmd-shim",path:o};if(T(n.command)){const i=c("wsl.exe")[0]??c("wsl")[0];if(i)return{...n,kind:"wsl-bridge",path:i}}return null}function cn(n){if(f.has(n))return f.get(n)??null;const t=n==="codex"&&d()==="darwin"?B().find(o=>l.existsSync(o)?!!I("codex",{command:o,args:[],display:"Codex Desktop",kind:"native",path:o}):!1):void 0,e=t?{...W.codex[0],kind:"native",path:t}:W[n].map(o=>{if(d()==="win32")return G(o);const i=c(o.command)[0];return i?{...o,kind:"native",path:i}:null}).find(Boolean)??null;return f.set(n,e),e}function F(n,t,e){if(n.kind==="native")return d()==="win32"&&L(n.path)?{command:M(),args:[n.path,...n.args,...t],cwd:e}:{command:n.path,args:[...n.args,...t],cwd:e};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...t].map(E).join(" ");return{command:D(),args:["/d","/s","/c",`"${r}"`],cwd:e}}const o=e?Z(e):void 0;if(e&&!o)throw new Error(`Cannot map Windows path to WSL workDir: ${e}`);const i=[o?`cd ${y(o)}`:"",`exec ${[n.command,...n.args,...t].map(y).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",i],cwd:void 0}}function X(n,t,e={}){const o=F(n,t,e.cwd);return A(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function un(n,t,e={}){return X(n,t,e)}function j(n,t,e={}){const o=F(n,t,e.cwd);return b(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n){const t=[];let e="",o=!1,i=!1;for(const r of n){if(r==="'"&&!i){o=!o;continue}if(r==='"'&&!o){i=!i;continue}if(r===" "&&!o&&!i){e&&(t.push(e),e="");continue}e+=r}return e&&t.push(e),t}function J(n,t,e){const o=R(n),i=o[0];if(!i)throw new Error("Command string is empty");const r=o.slice(1);if(d()!=="win32")return{command:i,args:[...r,...t],cwd:e};const a=N(i);return a.kind==="cmd-shim"?{command:D(),args:["/d","/s","/c",`"${[a.path,...r,...t].map(E).join(" ")}"`],cwd:e}:L(a.path)?{command:M(),args:[a.path,...r,...t],cwd:e}:{command:a.path,args:[...r,...t],cwd:e}}function ln(n,t,e={}){const o=J(n,t,e.cwd),i=R(n),r=d()==="win32"&&i[0]?N(i[0]):null;return A(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,env:{...e.env,PATH:H(e.env?.PATH??process.env.PATH,i[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function K(n,t="--version"){const e=j(n,[t],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
1
+ import{spawn as A,spawnSync as b}from"node:child_process";import l from"node:fs";import $ from"node:crypto";import S from"node:os";import s from"node:path";import{resetWindowsInstallationPaths as z,windowsLookupPath as O,windowsCodexDesktopCandidates as _}from"./windows-agent-paths.js";import{wrapCommandWithMacosFileSandbox as q}from"../security/macos-file-sandbox.js";const W={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,p=new Map;function an(){z(),m.clear(),f.clear(),h.clear(),p.clear()}function d(){return process.platform}function U(n){return n.split(/\r?\n/).map(t=>t.trim()).filter(Boolean)}function v(n){if(s.basename(n)!==n)return[n];const t=S.homedir();if(d()==="win32"){const i=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],a=process.env.APPDATA||i.join(t,"AppData","Roaming"),u=process.env.LOCALAPPDATA||i.join(t,"AppData","Local"),P=[i.join(t,".shennian","node"),i.join("C:\\","nvm4w","nodejs"),i.join(u,"npm-global"),i.join(a,"npm"),i.join(u,"pnpm"),i.join(t,"scoop","shims"),i.join("C:\\","Program Files","nodejs")].flatMap(x=>r.map(C=>i.join(x,C)));if(n==="codebuddy"){const x=[i.join(u,"Programs","WorkBuddy"),i.join(u,"WorkBuddy"),i.join("C:\\","Program Files","WorkBuddy")];for(const C of x)for(const V of["codebuddy.exe","codebuddy.cmd","codebuddy"])P.push(i.join(C,"resources","app.asar.unpacked","cli","bin",V))}return P}const o=[s.join(t,".npm-global","bin"),s.join(t,".local","bin"),s.join(t,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(i=>s.join(i,n));return n==="claude"&&d()==="darwin"&&o.push(...Z(t)),n==="codebuddy"&&d()==="darwin"&&o.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(t,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),o}function B(n=d(),t=S.homedir()){return n==="win32"?_(t):n!=="darwin"?[]:["/Applications",s.join(t,"Applications")].flatMap(e=>["ChatGPT.app","Codex.app"].map(o=>s.join(e,o,"Contents","Resources","codex")))}function Z(n){const t=[s.join(n,"Library","Application Support","Claude","claude-code")],e=[];for(const o of t){let i;try{i=l.readdirSync(o,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,a)=>a.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of i)e.push(s.join(o,r,"claude.app","Contents","MacOS","claude"))}return e}function H(n,t){const e=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="win32"){if(t&&s.basename(t)!==t){const o=s.win32.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.win32.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}if(t&&s.basename(t)!==t){const o=s.dirname(t);e.includes(o)||e.unshift(o)}for(const o of v("shennian")){const i=s.dirname(o);e.includes(i)||e.push(i)}return e.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const t=d()==="win32",o=b(t?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:t?O():H(process.env.PATH,n)}}),r=[...o.status===0?U(o.stdout??""):[]];for(const a of v(n))l.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function D(){return process.env.ComSpec||"cmd.exe"}function k(n){const t=s.extname(n).toLowerCase();return t===".exe"||t===".com"}function w(n){const t=s.extname(n).toLowerCase();return t===".cmd"||t===".bat"}function L(n){const t=s.extname(n).toLowerCase();return t===".js"||t===".mjs"||t===".cjs"}function M(){return c("node.exe")[0]??c("node")[0]??"node"}function F(n){return`"${n.replace(/"/g,'""')}"`}function y(n){return`'${n.replace(/'/g,"'\\''")}'`}function G(n){if(!n)return;const t=n.replace(/\//g,"\\"),e=t.match(/^([A-Za-z]):\\(.*)$/);if(e){const[,o,i]=e,r=i.replace(/\\/g,"/");return`/mnt/${o.toLowerCase()}/${r}`}if(t.startsWith("\\\\wsl$\\"))return`/${t.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function E(n){const t=n.trim();if(!t)throw new Error("Command string is empty");if(/[\\/]/.test(t)||/^[A-Za-z]:/.test(t))return w(t)?{kind:"cmd-shim",path:t}:{kind:"direct",path:t};const o=c(t),i=o.find(k);if(i)return{kind:"direct",path:i};const r=o.find(w);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:t}}function N(n){if(p.has(n))return p.get(n)??!1;const t=c("wsl.exe")[0]??c("wsl")[0];if(!t)return p.set(n,!1),!1;const o=b(t,["-e","sh","-lc",`command -v ${y(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return p.set(n,o),o}function dn(n){if(m.has(n))return m.get(n)??!1;const t=c(n).length>0||d()==="win32"&&N(n);return m.set(n,t),t}function cn(n){const t=c(n)[0];if(!t)return null;try{const e=l.realpathSync(t),o=l.statSync(e,{bigint:!0}),i=$.createHash("sha256").update(e).digest("hex"),r=$.createHash("sha256").update(`${o.dev}:${o.ino}:${o.size}:${o.mtimeNs}`).digest("hex");return{pathHash:i,fingerprint:r}}catch{return null}}function un(n){return c(n)[0]??null}function X(n){const t=c(n.command);if(n.command==="codex"){const i=process.env.SHENNIAN_CODEX_PATH?.trim(),r=i?[i]:[...t,...B()];for(const a of r){if(i&&!s.win32.isAbsolute(a))return null;const u=k(a)?"native":w(a)?"cmd-shim":null;if(!u)continue;const g={...n,kind:u,path:a};if(I("codex",g))return g}return null}const e=t.find(k);if(e)return{...n,kind:"native",path:e};const o=t.find(w);if(o)return{...n,kind:"cmd-shim",path:o};if(N(n.command)){const i=c("wsl.exe")[0]??c("wsl")[0];if(i)return{...n,kind:"wsl-bridge",path:i}}return null}function ln(n){if(f.has(n))return f.get(n)??null;const t=n==="codex"&&d()==="darwin"?B().find(o=>l.existsSync(o)?!!I("codex",{command:o,args:[],display:"Codex Desktop",kind:"native",path:o}):!1):void 0,e=t?{...W.codex[0],kind:"native",path:t}:W[n].map(o=>{if(d()==="win32")return X(o);const i=c(o.command)[0];return i?{...o,kind:"native",path:i}:null}).find(Boolean)??null;return f.set(n,e),e}function T(n,t,e){if(n.kind==="native")return d()==="win32"&&L(n.path)?{command:M(),args:[n.path,...n.args,...t],cwd:e}:{command:n.path,args:[...n.args,...t],cwd:e};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...t].map(F).join(" ");return{command:D(),args:["/d","/s","/c",`"${r}"`],cwd:e}}const o=e?G(e):void 0;if(e&&!o)throw new Error(`Cannot map Windows path to WSL workDir: ${e}`);const i=[o?`cd ${y(o)}`:"",`exec ${[n.command,...n.args,...t].map(y).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",i],cwd:void 0}}function J(n,t,e={}){const{macosFileSandbox:o,...i}=e,r=T(n,t,i.cwd),a=o&&n.kind==="native"?q(r.command,r.args,o):r;return A(a.command,a.args,{...i,cwd:r.cwd,windowsHide:i.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function pn(n,t,e={}){return J(n,t,e)}function j(n,t,e={}){const o=T(n,t,e.cwd);return b(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n){const t=[];let e="",o=!1,i=!1;for(const r of n){if(r==="'"&&!i){o=!o;continue}if(r==='"'&&!o){i=!i;continue}if(r===" "&&!o&&!i){e&&(t.push(e),e="");continue}e+=r}return e&&t.push(e),t}function K(n,t,e){const o=R(n),i=o[0];if(!i)throw new Error("Command string is empty");const r=o.slice(1);if(d()!=="win32")return{command:i,args:[...r,...t],cwd:e};const a=E(i);return a.kind==="cmd-shim"?{command:D(),args:["/d","/s","/c",`"${[a.path,...r,...t].map(F).join(" ")}"`],cwd:e}:L(a.path)?{command:M(),args:[a.path,...r,...t],cwd:e}:{command:a.path,args:[...r,...t],cwd:e}}function mn(n,t,e={}){const o=K(n,t,e.cwd),i=R(n),r=d()==="win32"&&i[0]?E(i[0]):null;return A(o.command,o.args,{...e,cwd:o.cwd,windowsHide:e.windowsHide??!0,env:{...e.env,PATH:H(e.env?.PATH??process.env.PATH,i[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function Q(n,t="--version"){const e=j(n,[t],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
2
2
  ${e.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function I(n,t){if(n==="codex"||n==="claude"){const r=j(t,["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});if(r.status!==0)return;const a=`${r.stdout??""}
3
- ${r.stderr??""}`.replace(/\u001b\[[0-9;]*m/g,"");return(n==="codex"?a.match(/^\s*codex-cli\s+(\d+\.\d+\.\d+[\w.-]*)\s*$/im):a.match(/^\s*(\d+\.\d+\.\d+[\w.-]*)\s+\(Claude Code\)\s*$/im))?.[1]}if(n!=="cursor")return K(t);const e=j(t,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
4
- ${e.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{J as buildCommandStringLaunchSpec,F as buildLaunchSpec,sn as commandExists,I as getBuiltinAgentVersion,B as getCodexDesktopCommandCandidates,K as getCommandVersion,d as getProcessPlatform,R as parseCommandString,rn as resetCommandSpecCache,cn as resolveBuiltinCommand,an as resolveCommandFileIdentity,dn as resolveCommandFilePath,un as spawnAgentCommand,ln as spawnCommandString,X as spawnResolvedCommand,j as spawnResolvedCommandSync,Z as windowsPathToWsl};
3
+ ${r.stderr??""}`.replace(/\u001b\[[0-9;]*m/g,"");return(n==="codex"?a.match(/^\s*codex-cli\s+(\d+\.\d+\.\d+[\w.-]*)\s*$/im):a.match(/^\s*(\d+\.\d+\.\d+[\w.-]*)\s+\(Claude Code\)\s*$/im))?.[1]}if(n!=="cursor")return Q(t);const e=j(t,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return e.status!==0?void 0:`${e.stdout??""}
4
+ ${e.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{K as buildCommandStringLaunchSpec,T as buildLaunchSpec,dn as commandExists,I as getBuiltinAgentVersion,B as getCodexDesktopCommandCandidates,Q as getCommandVersion,d as getProcessPlatform,R as parseCommandString,an as resetCommandSpecCache,ln as resolveBuiltinCommand,cn as resolveCommandFileIdentity,un as resolveCommandFilePath,pn as spawnAgentCommand,mn as spawnCommandString,J as spawnResolvedCommand,j as spawnResolvedCommandSync,G as windowsPathToWsl};
@@ -1,2 +1,2 @@
1
- import l from"node:fs";import c from"node:fs/promises";import u from"node:os";import s from"node:path";import{resolveProtectedShennianDirectories as C}from"../security/managed-agent-credential-paths.js";const f="shennian-cursor-managed-",R=1024*1024,v=["Read(.env)","Read(.env.*)","Read(**/.env)","Read(**/.env.*)","Read(*.key)","Read(**/*.key)","Read(*.pem)","Read(**/*.pem)","Read(~/.shennian/**)","Read($HOME/.shennian/**)"],p={commandNetwork:{allow:!1,deny:!0},webSearch:{allow:!0,deny:!0},browser:{allow:!1,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!1,deny:!1}},U={minimumRuntimeVersion:"2026.08.31",maximumRuntimeVersionExclusive:"2026.09.01",platforms:{darwin:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:p,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},linux:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:p,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},wsl:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:p,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},win32:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:{commandNetwork:{allow:!0,deny:!1},webSearch:{allow:!0,deny:!0},browser:{allow:!1,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!0,deny:!0}},knownGaps:["sandbox.nativeWindowsUnverified","sandbox.shellDisabled","externalCapabilities.projectMcpStartup"]}}};function G(a,e){const n=j(e),o=a.effectivePolicy,t=o.fileAccess==="host-full",r=o.fileAccess==="workspace-read",w=E(),b=w.map(k=>k.replace(/^Read\(/,"Write("));if(o.externalCapabilities.commandNetwork)throw new Error("cursor_managed_command_network_unavailable");if(o.externalCapabilities.mcp)throw new Error("cursor_managed_mcp_isolation_unavailable");if(o.externalCapabilities.browser||o.externalCapabilities.computerUse)throw new Error("cursor_managed_native_interactive_tool_control_unavailable");if(a.platform==="win32"&&!t)throw new Error("cursor_managed_native_windows_sandbox_unavailable");t||S(n,r);const i=["Read(**)"];r||i.push("Write(**)"),o.externalCapabilities.webSearch&&i.push("WebFetch(*)"),o.externalCapabilities.mcp&&i.push("Mcp(*:*)");const h=[...w,...b,"Shell(*)",...r?["Write(**)"]:[],...o.externalCapabilities.webSearch?[]:["WebFetch(*)"],...o.externalCapabilities.mcp?[]:["Mcp(*:*)"]],d=o.externalCapabilities.commandNetwork,y={version:1,editor:{vimMode:!1},approvalMode:t?"unrestricted":"allowlist",sandbox:{mode:t?"disabled":"enabled",networkAccess:d?"allow_all":"user_config_only",readBoundary:t?"system":"workspace"},permissions:{allow:[...new Set(i)].sort(),deny:[...new Set(h)].sort()},notifications:!1,hints:!1,suggestNextPrompt:!1,attribution:{attributeCommitsToAgent:!1,attributePRsToAgent:!1}},x={type:t?"insecure_none":r?"workspace_readonly":"workspace_readwrite",additionalReadwritePaths:[],additionalReadonlyPaths:[],disableTmpWrite:!0,enableSharedBuildCache:!1,networkPolicy:d?{default:"allow",allow:[],deny:[]}:{default:"deny",allow:[],deny:["*"]},networkPolicyStrict:!d,readBoundary:t?"system":"workspace"};return{args:["--trust","--workspace",n,"--sandbox",t?"disabled":"enabled",...r?["--mode","ask"]:[],...o.externalCapabilities.mcp?["--approve-mcps"]:[],...t?["--force"]:[]],cliConfig:y,sandboxConfig:x}}async function T(a){const e=await c.mkdtemp(s.join(u.tmpdir(),f));try{return await c.chmod(e,448),await Promise.all([_(s.join(e,"cli-config.json"),a.cliConfig),_(s.join(e,"sandbox.json"),a.sandboxConfig)]),e}catch(n){throw await g(e).catch(()=>{}),new Error("cursor_managed_config_initialization_failed",{cause:n})}}async function g(a){const e=s.resolve(a),n=s.resolve(u.tmpdir());if(s.dirname(e)!==n||!s.basename(e).startsWith(f))throw new Error("cursor_managed_config_cleanup_refused");await c.rm(e,{recursive:!0,force:!0})}function S(a,e){const n=s.join(a,".cursor","sandbox.json");if(!l.existsSync(n))return;let o;try{const r=l.statSync(n);if(!r.isFile()||r.size>R)throw new Error("invalid_project_sandbox");o=l.readFileSync(n,"utf8")}catch(r){throw new Error("cursor_managed_project_sandbox_unverifiable",{cause:r})}let t;try{const r=JSON.parse(o);if(!r||typeof r!="object"||Array.isArray(r))throw new Error("invalid_project_sandbox");t=r}catch(r){throw new Error("cursor_managed_project_sandbox_unverifiable",{cause:r})}if(t.type==="insecure_none")throw new Error("cursor_managed_project_sandbox_broadens_access");if(e&&t.type==="workspace_readwrite")throw new Error("cursor_managed_project_sandbox_broadens_access");if(m(t.additionalReadwritePaths)||m(t.additionalReadonlyPaths))throw new Error("cursor_managed_project_sandbox_broadens_access")}function m(a){return a==null?!1:!Array.isArray(a)||a.length>0}function A(a){return a.replaceAll("\\","/")}function E(){const a=C().map(e=>A(s.normalize(e))).filter(e=>s.isAbsolute(e));return[...new Set([...v,...a.map(e=>`Read(${e}/**)`)])]}function j(a){const e=s.normalize(a.trim());if(!e||!s.isAbsolute(e))throw new Error("cursor_managed_workdir_invalid");let n;try{n=l.realpathSync(e)}catch{throw new Error("cursor_managed_workdir_unavailable")}if(s.normalize(n)!==e)throw new Error("cursor_managed_workdir_not_realpath");return e}async function _(a,e){await c.writeFile(a,`${JSON.stringify(e)}
2
- `,{encoding:"utf8",mode:384,flag:"wx"})}export{U as CURSOR_MANAGED_RUNTIME_SECURITY,G as compileCursorManagedPermissions,T as createCursorManagedConfigDirectory,g as disposeCursorManagedConfigDirectory};
1
+ import c from"node:fs";import d from"node:fs/promises";import m from"node:os";import t from"node:path";import{resolveProtectedShennianDirectories as R}from"../security/managed-agent-credential-paths.js";const b="shennian-cursor-managed-",v=1024*1024,A=["Read(.env)","Read(.env.*)","Read(**/.env)","Read(**/.env.*)","Read(*.key)","Read(**/*.key)","Read(*.pem)","Read(**/*.pem)","Read(~/.shennian/**)","Read($HOME/.shennian/**)"],w={commandNetwork:{allow:!1,deny:!0},webSearch:{allow:!0,deny:!0},browser:{allow:!1,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!1,deny:!1}},G={minimumRuntimeVersion:"2026.08.31",maximumRuntimeVersionExclusive:"2026.09.01",platforms:{darwin:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:w,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","fileAccess.globalProjectHistoryPersisted","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},linux:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:w,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","fileAccess.globalProjectHistoryPersisted","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},wsl:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:w,knownGaps:["fileAccess.workspaceBoundaryUnenforced","fileAccess.outsideWorkspaceRead","fileAccess.globalProjectHistoryPersisted","sandbox.shellDisabled","externalCapabilities.webSearchToolGranularity","externalCapabilities.projectMcpStartup"]},win32:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:{commandNetwork:{allow:!0,deny:!1},webSearch:{allow:!0,deny:!0},browser:{allow:!1,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!0,deny:!0}},knownGaps:["sandbox.nativeWindowsUnverified","fileAccess.globalProjectHistoryPersisted","sandbox.shellDisabled","externalCapabilities.projectMcpStartup"]}}};function B(r,e,s={}){const i=M(e),o=r.effectivePolicy,a=o.fileAccess==="host-full",n=o.fileAccess==="workspace-read",p=s.publicTurn===!0,f=j(),y=f.map(C=>C.replace(/^Read\(/,"Write("));if(o.externalCapabilities.commandNetwork)throw new Error("cursor_managed_command_network_unavailable");if(o.externalCapabilities.mcp)throw new Error("cursor_managed_mcp_isolation_unavailable");if(o.externalCapabilities.browser||o.externalCapabilities.computerUse)throw new Error("cursor_managed_native_interactive_tool_control_unavailable");if(r.platform==="win32"&&!a)throw new Error("cursor_managed_native_windows_sandbox_unavailable");a||E(i,n);const l=p?[]:["Read(**)"];!p&&!n&&l.push("Write(**)"),o.externalCapabilities.webSearch&&l.push("WebFetch(*)"),o.externalCapabilities.mcp&&l.push("Mcp(*:*)");const x=[...f,...y,...p?["Read(**)","Write(**)"]:[],"Shell(*)",...n?["Write(**)"]:[],...o.externalCapabilities.webSearch?[]:["WebFetch(*)"],...o.externalCapabilities.mcp?[]:["Mcp(*:*)"]],u=o.externalCapabilities.commandNetwork,k={version:1,editor:{vimMode:!1},approvalMode:a?"unrestricted":"allowlist",sandbox:{mode:a?"disabled":"enabled",networkAccess:u?"allow_all":"user_config_only",readBoundary:a?"system":"workspace"},permissions:{allow:[...new Set(l)].sort(),deny:[...new Set(x)].sort()},notifications:!1,hints:!1,suggestNextPrompt:!1,attribution:{attributeCommitsToAgent:!1,attributePRsToAgent:!1}},g={type:a?"insecure_none":n?"workspace_readonly":"workspace_readwrite",additionalReadwritePaths:[],additionalReadonlyPaths:[],disableTmpWrite:!0,enableSharedBuildCache:!1,networkPolicy:u?{default:"allow",allow:[],deny:[]}:{default:"deny",allow:[],deny:["*"]},networkPolicyStrict:!u,readBoundary:a?"system":"workspace"};return{args:["--trust","--workspace",i,"--sandbox",a?"disabled":"enabled",...n?["--mode","ask"]:[],...o.externalCapabilities.mcp?["--approve-mcps"]:[],...a?["--force"]:[]],cliConfig:k,sandboxConfig:g}}async function F(r){const e=await d.mkdtemp(t.join(m.tmpdir(),b));try{return await d.chmod(e,448),await Promise.all([h(t.join(e,"cli-config.json"),r.cliConfig),h(t.join(e,"sandbox.json"),r.sandboxConfig)]),e}catch(s){throw await S(e).catch(()=>{}),new Error("cursor_managed_config_initialization_failed",{cause:s})}}async function S(r){const e=t.resolve(r),s=t.resolve(m.tmpdir());if(t.dirname(e)!==s||!t.basename(e).startsWith(b))throw new Error("cursor_managed_config_cleanup_refused");await d.rm(e,{recursive:!0,force:!0})}function E(r,e){const s=t.join(r,".cursor","sandbox.json");if(!c.existsSync(s))return;let i;try{const a=c.statSync(s);if(!a.isFile()||a.size>v)throw new Error("invalid_project_sandbox");i=c.readFileSync(s,"utf8")}catch(a){throw new Error("cursor_managed_project_sandbox_unverifiable",{cause:a})}let o;try{const a=JSON.parse(i);if(!a||typeof a!="object"||Array.isArray(a))throw new Error("invalid_project_sandbox");o=a}catch(a){throw new Error("cursor_managed_project_sandbox_unverifiable",{cause:a})}if(o.type==="insecure_none")throw new Error("cursor_managed_project_sandbox_broadens_access");if(e&&o.type==="workspace_readwrite")throw new Error("cursor_managed_project_sandbox_broadens_access");if(_(o.additionalReadwritePaths)||_(o.additionalReadonlyPaths))throw new Error("cursor_managed_project_sandbox_broadens_access")}function _(r){return r==null?!1:!Array.isArray(r)||r.length>0}function P(r){return r.replaceAll("\\","/")}function j(){const r=R().map(e=>P(t.normalize(e))).filter(e=>t.isAbsolute(e));return[...new Set([...A,...r.map(e=>`Read(${e}/**)`)])]}function M(r){const e=t.normalize(r.trim());if(!e||!t.isAbsolute(e))throw new Error("cursor_managed_workdir_invalid");let s;try{s=c.realpathSync(e)}catch{throw new Error("cursor_managed_workdir_unavailable")}if(t.normalize(s)!==e)throw new Error("cursor_managed_workdir_not_realpath");return e}async function h(r,e){await d.writeFile(r,`${JSON.stringify(e)}
2
+ `,{encoding:"utf8",mode:384,flag:"wx"})}export{G as CURSOR_MANAGED_RUNTIME_SECURITY,B as compileCursorManagedPermissions,F as createCursorManagedConfigDirectory,S as disposeCursorManagedConfigDirectory};