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.
- package/dist/publish-build-manifest.json +75 -35
- package/dist/src/agents/acp/adapter.js +2 -2
- package/dist/src/agents/claude.js +7 -7
- package/dist/src/agents/codex.js +3 -3
- package/dist/src/agents/command-spec.js +3 -3
- package/dist/src/agents/cursor-managed-permissions.js +2 -2
- package/dist/src/agents/cursor.js +1 -1
- package/dist/src/agents/custom.js +5 -5
- package/dist/src/agents/opencode-managed-permissions.js +2 -2
- package/dist/src/agents/opencode.js +1 -1
- package/dist/src/agents/pi-coding-agent.js +3 -3
- package/dist/src/agents/public-agent-client.js +1 -1
- package/dist/src/agents/public-delivery-client.js +1 -0
- package/dist/src/agents/public-delivery-worker.js +1 -0
- package/dist/src/agents/public-reply-collector.js +1 -0
- package/dist/src/agents/public-turn-runner.js +3 -0
- package/dist/src/agents/public-workdir.js +1 -0
- package/dist/src/agents/workbuddy-managed-permissions.js +2 -2
- package/dist/src/agents/workbuddy.js +2 -2
- package/dist/src/commands/agent-workspace.js +3 -3
- package/dist/src/index.js +3 -3
- package/dist/src/native-fusion/local-repository.js +2 -2
- package/dist/src/native-fusion/test-workspace.js +1 -0
- package/dist/src/security/macos-file-sandbox.js +3 -0
- package/dist/src/security/managed-agent-policy.js +1 -1
- package/dist/src/security/public-agent-policy.js +1 -0
- package/node_modules/@shennian/wire/dist/agent-workspace.js +1 -1
- package/package.json +8 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
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":
|
|
55
|
-
"afterBytes":
|
|
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":
|
|
140
|
-
"afterBytes":
|
|
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":
|
|
170
|
-
"afterBytes":
|
|
169
|
+
"beforeBytes": 36771,
|
|
170
|
+
"afterBytes": 19653
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
"file": "src/agents/command-spec.js",
|
|
174
|
-
"beforeBytes":
|
|
175
|
-
"afterBytes":
|
|
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":
|
|
185
|
-
"afterBytes":
|
|
184
|
+
"beforeBytes": 13555,
|
|
185
|
+
"afterBytes": 6231
|
|
186
186
|
},
|
|
187
187
|
{
|
|
188
188
|
"file": "src/agents/cursor.js",
|
|
189
|
-
"beforeBytes":
|
|
190
|
-
"afterBytes":
|
|
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":
|
|
205
|
-
"afterBytes":
|
|
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":
|
|
290
|
-
"afterBytes":
|
|
289
|
+
"beforeBytes": 9194,
|
|
290
|
+
"afterBytes": 3781
|
|
291
291
|
},
|
|
292
292
|
{
|
|
293
293
|
"file": "src/agents/opencode.js",
|
|
294
|
-
"beforeBytes":
|
|
295
|
-
"afterBytes":
|
|
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":
|
|
305
|
-
"afterBytes":
|
|
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":
|
|
340
|
-
"afterBytes":
|
|
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":
|
|
360
|
-
"afterBytes":
|
|
384
|
+
"beforeBytes": 15241,
|
|
385
|
+
"afterBytes": 6763
|
|
361
386
|
},
|
|
362
387
|
{
|
|
363
388
|
"file": "src/agents/workbuddy.js",
|
|
364
|
-
"beforeBytes":
|
|
365
|
-
"afterBytes":
|
|
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":
|
|
380
|
-
"afterBytes":
|
|
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":
|
|
605
|
-
"afterBytes":
|
|
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":
|
|
690
|
-
"afterBytes":
|
|
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":
|
|
935
|
-
"afterBytes":
|
|
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
|
|
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
|
|
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
|
|
3
|
-
\u2026[truncated]`:e}function
|
|
4
|
-
`):""}class
|
|
5
|
-
`)){const d=u.trim();
|
|
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
|
|
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
|
|
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};
|
package/dist/src/agents/codex.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{CODEX_DESKTOP_SEND_UNAVAILABLE as v}from"@shennian/wire";import{createHash as y,randomUUID as
|
|
2
|
-
${d}`.trim();if(c!==0){u(new Error(g||`codex queue exited with code ${c??"unknown"}`));return}const
|
|
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(!
|
|
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
|
|
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
|
|
4
|
-
${e.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{
|
|
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
|
|
2
|
-
`,{encoding:"utf8",mode:384,flag:"wx"})}export{
|
|
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};
|