shennian 0.4.31 → 0.4.33
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 +59 -39
- package/dist/src/agents/acp/adapter.d.ts +4 -0
- package/dist/src/agents/acp/adapter.js +2 -2
- package/dist/src/agents/acp/client-services.d.ts +2 -1
- package/dist/src/agents/acp/client-services.js +2 -2
- package/dist/src/agents/acp/discovery.js +1 -1
- package/dist/src/agents/acp/process-client.js +1 -1
- package/dist/src/agents/claude.d.ts +1 -0
- package/dist/src/agents/claude.js +5 -5
- package/dist/src/agents/codex.js +3 -3
- package/dist/src/agents/command-spec.d.ts +1 -0
- package/dist/src/agents/command-spec.js +3 -3
- package/dist/src/commands/daemon-instance-lock.d.ts +21 -0
- package/dist/src/commands/daemon-instance-lock.js +1 -0
- package/dist/src/commands/daemon.d.ts +2 -2
- package/dist/src/commands/daemon.js +6 -6
- package/dist/src/commands/upgrade.js +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/relay/client.d.ts +4 -0
- package/dist/src/relay/client.js +1 -1
- package/dist/src/room/activation-service.d.ts +2 -0
- package/dist/src/room/activation-service.js +4 -4
- package/dist/src/room/managed-room-binding.d.ts +2 -1
- package/dist/src/room/managed-room-binding.js +1 -1
- package/dist/src/room/room-binding-client.js +1 -1
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/handlers/project-fs.d.ts +11 -0
- package/dist/src/session/handlers/project-fs.js +1 -0
- package/dist/src/session/handlers/room-managed.js +1 -1
- package/dist/src/session/manager.d.ts +6 -1
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/project-fs-store.d.ts +43 -0
- package/dist/src/session/project-fs-store.js +1 -0
- package/dist/src/session/queue.js +4 -4
- package/dist/src/upgrade/channel.d.ts +5 -0
- package/dist/src/upgrade/channel.js +2 -0
- package/dist/src/upgrade/engine.js +2 -2
- package/node_modules/@shennian/wire/dist/index.d.ts +1 -0
- package/node_modules/@shennian/wire/dist/index.js +1 -0
- package/node_modules/@shennian/wire/dist/methods.d.ts +3 -1
- package/node_modules/@shennian/wire/dist/methods.js +2 -0
- package/node_modules/@shennian/wire/dist/project-fs.d.ts +146 -0
- package/node_modules/@shennian/wire/dist/project-fs.js +462 -0
- package/node_modules/@shennian/wire/dist/project.d.ts +2 -0
- package/node_modules/@shennian/wire/dist/project.js +2 -0
- package/node_modules/@shennian/wire/dist/session-sync.d.ts +8 -1
- package/node_modules/@shennian/wire/dist/session-sync.js +1 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 182,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian.js",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"file": "src/agents/acp/adapter.js",
|
|
19
|
-
"beforeBytes":
|
|
20
|
-
"afterBytes":
|
|
19
|
+
"beforeBytes": 25702,
|
|
20
|
+
"afterBytes": 13667
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"file": "src/agents/acp/auth-state.js",
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"file": "src/agents/acp/client-services.js",
|
|
44
|
-
"beforeBytes":
|
|
45
|
-
"afterBytes":
|
|
44
|
+
"beforeBytes": 5184,
|
|
45
|
+
"afterBytes": 2824
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"file": "src/agents/acp/discovery.js",
|
|
49
|
-
"beforeBytes":
|
|
50
|
-
"afterBytes":
|
|
49
|
+
"beforeBytes": 9943,
|
|
50
|
+
"afterBytes": 4539
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"file": "src/agents/acp/events.js",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"file": "src/agents/acp/process-client.js",
|
|
74
|
-
"beforeBytes":
|
|
75
|
-
"afterBytes":
|
|
74
|
+
"beforeBytes": 7304,
|
|
75
|
+
"afterBytes": 4420
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"file": "src/agents/acp/process-tree.js",
|
|
@@ -101,8 +101,8 @@
|
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"file": "src/agents/claude.js",
|
|
104
|
-
"beforeBytes":
|
|
105
|
-
"afterBytes":
|
|
104
|
+
"beforeBytes": 18877,
|
|
105
|
+
"afterBytes": 9108
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"file": "src/agents/codex-managed-permissions.js",
|
|
@@ -121,13 +121,13 @@
|
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"file": "src/agents/codex.js",
|
|
124
|
-
"beforeBytes":
|
|
125
|
-
"afterBytes":
|
|
124
|
+
"beforeBytes": 66408,
|
|
125
|
+
"afterBytes": 34028
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
"file": "src/agents/command-spec.js",
|
|
129
|
-
"beforeBytes":
|
|
130
|
-
"afterBytes":
|
|
129
|
+
"beforeBytes": 18342,
|
|
130
|
+
"afterBytes": 8290
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
"file": "src/agents/config-status.js",
|
|
@@ -289,6 +289,11 @@
|
|
|
289
289
|
"beforeBytes": 5136,
|
|
290
290
|
"afterBytes": 2826
|
|
291
291
|
},
|
|
292
|
+
{
|
|
293
|
+
"file": "src/commands/daemon-instance-lock.js",
|
|
294
|
+
"beforeBytes": 3665,
|
|
295
|
+
"afterBytes": 1250
|
|
296
|
+
},
|
|
292
297
|
{
|
|
293
298
|
"file": "src/commands/daemon-process.js",
|
|
294
299
|
"beforeBytes": 3288,
|
|
@@ -306,8 +311,8 @@
|
|
|
306
311
|
},
|
|
307
312
|
{
|
|
308
313
|
"file": "src/commands/daemon.js",
|
|
309
|
-
"beforeBytes":
|
|
310
|
-
"afterBytes":
|
|
314
|
+
"beforeBytes": 46021,
|
|
315
|
+
"afterBytes": 22106
|
|
311
316
|
},
|
|
312
317
|
{
|
|
313
318
|
"file": "src/commands/integration.js",
|
|
@@ -361,8 +366,8 @@
|
|
|
361
366
|
},
|
|
362
367
|
{
|
|
363
368
|
"file": "src/commands/upgrade.js",
|
|
364
|
-
"beforeBytes":
|
|
365
|
-
"afterBytes":
|
|
369
|
+
"beforeBytes": 10405,
|
|
370
|
+
"afterBytes": 5597
|
|
366
371
|
},
|
|
367
372
|
{
|
|
368
373
|
"file": "src/config/index.js",
|
|
@@ -436,8 +441,8 @@
|
|
|
436
441
|
},
|
|
437
442
|
{
|
|
438
443
|
"file": "src/index.js",
|
|
439
|
-
"beforeBytes":
|
|
440
|
-
"afterBytes":
|
|
444
|
+
"beforeBytes": 35741,
|
|
445
|
+
"afterBytes": 17740
|
|
441
446
|
},
|
|
442
447
|
{
|
|
443
448
|
"file": "src/log-redaction.js",
|
|
@@ -571,8 +576,8 @@
|
|
|
571
576
|
},
|
|
572
577
|
{
|
|
573
578
|
"file": "src/relay/client.js",
|
|
574
|
-
"beforeBytes":
|
|
575
|
-
"afterBytes":
|
|
579
|
+
"beforeBytes": 18081,
|
|
580
|
+
"afterBytes": 8805
|
|
576
581
|
},
|
|
577
582
|
{
|
|
578
583
|
"file": "src/room/activation-audit.js",
|
|
@@ -586,8 +591,8 @@
|
|
|
586
591
|
},
|
|
587
592
|
{
|
|
588
593
|
"file": "src/room/activation-service.js",
|
|
589
|
-
"beforeBytes":
|
|
590
|
-
"afterBytes":
|
|
594
|
+
"beforeBytes": 24183,
|
|
595
|
+
"afterBytes": 12030
|
|
591
596
|
},
|
|
592
597
|
{
|
|
593
598
|
"file": "src/room/attachment-cache.js",
|
|
@@ -631,8 +636,8 @@
|
|
|
631
636
|
},
|
|
632
637
|
{
|
|
633
638
|
"file": "src/room/managed-room-binding.js",
|
|
634
|
-
"beforeBytes":
|
|
635
|
-
"afterBytes":
|
|
639
|
+
"beforeBytes": 7191,
|
|
640
|
+
"afterBytes": 3831
|
|
636
641
|
},
|
|
637
642
|
{
|
|
638
643
|
"file": "src/room/managed-room-ipc.js",
|
|
@@ -661,8 +666,8 @@
|
|
|
661
666
|
},
|
|
662
667
|
{
|
|
663
668
|
"file": "src/room/room-binding-client.js",
|
|
664
|
-
"beforeBytes":
|
|
665
|
-
"afterBytes":
|
|
669
|
+
"beforeBytes": 6903,
|
|
670
|
+
"afterBytes": 3961
|
|
666
671
|
},
|
|
667
672
|
{
|
|
668
673
|
"file": "src/room/session-registry.js",
|
|
@@ -736,8 +741,8 @@
|
|
|
736
741
|
},
|
|
737
742
|
{
|
|
738
743
|
"file": "src/session/handlers/chat.js",
|
|
739
|
-
"beforeBytes":
|
|
740
|
-
"afterBytes":
|
|
744
|
+
"beforeBytes": 58009,
|
|
745
|
+
"afterBytes": 24871
|
|
741
746
|
},
|
|
742
747
|
{
|
|
743
748
|
"file": "src/session/handlers/control.js",
|
|
@@ -754,6 +759,11 @@
|
|
|
754
759
|
"beforeBytes": 676,
|
|
755
760
|
"afterBytes": 392
|
|
756
761
|
},
|
|
762
|
+
{
|
|
763
|
+
"file": "src/session/handlers/project-fs.js",
|
|
764
|
+
"beforeBytes": 3778,
|
|
765
|
+
"afterBytes": 1762
|
|
766
|
+
},
|
|
757
767
|
{
|
|
758
768
|
"file": "src/session/handlers/remote-access.js",
|
|
759
769
|
"beforeBytes": 1644,
|
|
@@ -761,8 +771,8 @@
|
|
|
761
771
|
},
|
|
762
772
|
{
|
|
763
773
|
"file": "src/session/handlers/room-managed.js",
|
|
764
|
-
"beforeBytes":
|
|
765
|
-
"afterBytes":
|
|
774
|
+
"beforeBytes": 4813,
|
|
775
|
+
"afterBytes": 2536
|
|
766
776
|
},
|
|
767
777
|
{
|
|
768
778
|
"file": "src/session/handlers/session-refresh.js",
|
|
@@ -796,8 +806,8 @@
|
|
|
796
806
|
},
|
|
797
807
|
{
|
|
798
808
|
"file": "src/session/manager.js",
|
|
799
|
-
"beforeBytes":
|
|
800
|
-
"afterBytes":
|
|
809
|
+
"beforeBytes": 50398,
|
|
810
|
+
"afterBytes": 26589
|
|
801
811
|
},
|
|
802
812
|
{
|
|
803
813
|
"file": "src/session/native-cleanup-outbox.js",
|
|
@@ -809,6 +819,11 @@
|
|
|
809
819
|
"beforeBytes": 14829,
|
|
810
820
|
"afterBytes": 6738
|
|
811
821
|
},
|
|
822
|
+
{
|
|
823
|
+
"file": "src/session/project-fs-store.js",
|
|
824
|
+
"beforeBytes": 19274,
|
|
825
|
+
"afterBytes": 9362
|
|
826
|
+
},
|
|
812
827
|
{
|
|
813
828
|
"file": "src/session/projection.js",
|
|
814
829
|
"beforeBytes": 1991,
|
|
@@ -816,8 +831,8 @@
|
|
|
816
831
|
},
|
|
817
832
|
{
|
|
818
833
|
"file": "src/session/queue.js",
|
|
819
|
-
"beforeBytes":
|
|
820
|
-
"afterBytes":
|
|
834
|
+
"beforeBytes": 36820,
|
|
835
|
+
"afterBytes": 16528
|
|
821
836
|
},
|
|
822
837
|
{
|
|
823
838
|
"file": "src/session/run-recovery/barrier.js",
|
|
@@ -859,10 +874,15 @@
|
|
|
859
874
|
"beforeBytes": 15004,
|
|
860
875
|
"afterBytes": 8684
|
|
861
876
|
},
|
|
877
|
+
{
|
|
878
|
+
"file": "src/upgrade/channel.js",
|
|
879
|
+
"beforeBytes": 2185,
|
|
880
|
+
"afterBytes": 1207
|
|
881
|
+
},
|
|
862
882
|
{
|
|
863
883
|
"file": "src/upgrade/engine.js",
|
|
864
|
-
"beforeBytes":
|
|
865
|
-
"afterBytes":
|
|
884
|
+
"beforeBytes": 16155,
|
|
885
|
+
"afterBytes": 6796
|
|
866
886
|
},
|
|
867
887
|
{
|
|
868
888
|
"file": "src/upgrade/scheduler.js",
|
|
@@ -29,6 +29,8 @@ export declare class AcpAgentAdapter extends AgentAdapter {
|
|
|
29
29
|
private pendingAuthRetry;
|
|
30
30
|
private retryingAfterAuth;
|
|
31
31
|
private managedAgentPolicy;
|
|
32
|
+
private configurationSignature;
|
|
33
|
+
private startedConfigurationSignature;
|
|
32
34
|
constructor(manifest: AcpAgentManifest, options?: {
|
|
33
35
|
permissionTimeoutMs?: number;
|
|
34
36
|
promptTimeoutMs?: number;
|
|
@@ -67,6 +69,8 @@ export declare class AcpAgentAdapter extends AgentAdapter {
|
|
|
67
69
|
private captureImportedUpdate;
|
|
68
70
|
private handlePermission;
|
|
69
71
|
private requireClient;
|
|
72
|
+
private createProcessClient;
|
|
73
|
+
private refreshProcessConfiguration;
|
|
70
74
|
private buildEnvironment;
|
|
71
75
|
private buildClientCapabilities;
|
|
72
76
|
private retryAfterAuthentication;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{randomUUID as p}from"node:crypto";import{createHash as
|
|
1
|
+
import{randomUUID as p}from"node:crypto";import{createHash as m}from"node:crypto";import{realpathSync as g}from"node:fs";import{pathToFileURL as I}from"node:url";import*as l from"@agentclientprotocol/sdk";import{RequestError as w}from"@agentclientprotocol/sdk";import{AgentAdapter as C,registerAgent as v}from"../adapter.js";import{mapAcpSessionUpdate as A}from"./events.js";import{AcpProcessClient as P}from"./process-client.js";import{acpAgentType as f}from"./types.js";import{runAcpTerminalAuthentication as q}from"./auth.js";import{setAcpRuntimeAuthState as d}from"./auth-state.js";import{recordAcpAuthFailure as E,recordAcpImportResult as y}from"./metrics.js";import{isManagedAgentNativeFull as S}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as b}from"../../agent-env.js";class x extends C{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=f(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.configurationSignature=m("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[s])=>t.localeCompare(s)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}async start(e,t,s){this.shennianSessionId=e;try{this.workDir=g.native(t)}catch{this.workDir=t}this.requestedSessionId=s??null,this.agentSessionId=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}async send(e,t,s,i,n){await this.refreshProcessConfiguration();const o=this.requireClient();this.runId=p(),this.seq=0,this.emittedToolStates.clear();try{await this.ensureSession(),await this.applyDynamicConfig(t,s),this.active=!0,this.emitEvent({state:"start",runPhase:"thinking",agentSessionId:this.agentSessionId??void 0});const r=[],a=[];n?.trim()&&a.push(n.trim()),a.push(e),r.push({type:"text",text:a.join(`
|
|
2
2
|
|
|
3
|
-
`)});for(const h of t??[])r.push({type:"resource_link",uri:v(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const c=await this.promptWithTimeout(o,r);this.active=!1,c.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(r){this.active=!1,this.cancelPendingPermissions();const a=r instanceof Error?r.message:String(r),c=r instanceof S&&r.code===-32e3;throw c&&(u(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...i?{modelId:i}:{},...s?{reasoningEffort:s}:{},...t?{attachments:[...t]}:{},...n!==void 0?{systemPrompt:n}:{}})),this.emitEvent({state:"error",message:a,...c?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),r}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,i){const s=this.pendingPermissions.get(e);if(!s)throw new Error("ACP permission request is no longer pending");if(!s.optionIds.has(i))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(s.timer),s.resolve({outcome:{outcome:"selected",optionId:i}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=this.configOptions.find(o=>o.category==="model"&&o.type==="select"),i=this.configOptions.find(o=>o.category==="thought_level"&&o.type==="select"),s=this.modes?.availableModes.map(o=>({id:o.id,name:o.name,...o.description?{description:o.description}:{}}))??[],t=o=>(o?.options??[]).flatMap(r=>"options"in r?r.options:[r]),n=(i?t(i):s).map(o=>({id:"value"in o?o.value:o.id,name:o.name,...o.description?{description:o.description}:{}}));return{models:t(e).map(o=>({id:o.value,name:o.name,...o.description?{description:o.description}:{},...o.value===e?.currentValue?{isDefault:!0}:{},...n.length?{supportedReasoningEfforts:n}:{}})),modes:s}}async authenticate(e,i={}){const s=this.requireClient(),t=s.initializeResponse?.authMethods?.find(n=>n.id===e);if(!t)throw new Error("ACP authentication method is unavailable");try{if("type"in t&&t.type==="terminal"){if(!i.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await s.close(),await q({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(n=>typeof n[1]=="string"))},t,this.workDir)}else await s.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(n){throw E(),n}}async logout(){await this.requireClient().logout(),u(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=new g(this.manifest.launch,{onSessionUpdate:i=>this.handleSessionUpdate(i),onPermission:i=>this.handlePermission(i)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0}),await this.client.start(this.workDir),u(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const i=this.requireClient();if(!i.capabilities.sessionCapabilities?.list)return[];const s=[];let t;for(let n=0;n<10&&s.length<500;n+=1){let o=e.cwd;if(o)try{o=m.native(o)}catch{}const r=await i.listSessions(o,t);if(s.push(...r.sessions.slice(0,500-s.length).map(a=>({agentSessionId:a.sessionId,cwd:a.cwd,...a.title?{title:a.title.slice(0,200)}:{},...a.updatedAt?{updatedAt:a.updatedAt}:{}}))),t=r.nextCursor,!t)break}return s}async loadExternalSession(e){const i=this.requireClient();if(!i.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const s=[];this.importCapture=s;try{const t=await i.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=t.configOptions??[],this.modes=t.modes??null,y(!0)}catch(t){throw y(!1),t}finally{this.importCapture=null}return s.map((t,n)=>({sourceId:t.sourceHint??I("sha256").update(`${e}\0${n}\0${t.role}\0${t.payload}`).digest("hex"),role:t.role,payload:t.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const s=e.capabilities;if(s.sessionCapabilities?.resume){const t=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=t.configOptions??[],this.modes=t.modes??null}else if(s.loadSession){this.agentSessionId=this.requestedSessionId;const t=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=t.configOptions??[],this.modes=t.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId;return}const i=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=i.sessionId,this.configOptions=i.configOptions??[],this.modes=i.modes??null}async applyDynamicConfig(e,i){if(!this.agentSessionId)return;i&&this.modes?.availableModes.some(t=>t.id===i)&&(this.modes.currentModeId!==i&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:i}),this.modes.currentModeId=i),i=void 0);const s=[{category:"model",value:e},{category:"thought_level",value:i}];for(const t of s){if(!t.value)continue;const n=this.configOptions.find(o=>o.category===t.category&&o.type==="select");!n||n.currentValue===t.value||(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:n.id,value:t.value}),n.currentValue=t.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 i=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===i)return;this.emittedToolStates.set(e.update.toolCallId,i)}for(const i of P(e.update,s=>this.makeEvent(s)))this.emit("agentEvent",i)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const i=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,s=e.sessionUpdate==="user_message_chunk"?"user":"agent",t=e.messageId?`message:${e.messageId}`:void 0,n=t?this.importCapture.find(o=>o.sourceHint===t):this.importCapture.at(-1);n?.role===s&&n.sourceHint===t?n.payload+=i:this.importCapture.push({role:s,payload:i,...t?{sourceHint:t}:{}});return}if(e.sessionUpdate==="tool_call"){const i=`tool:${e.toolCallId}`,s=this.importCapture.find(n=>n.sourceHint===i),t={role:"agent",sourceHint:i,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};s?s.payload=t.payload:this.importCapture.push(t);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const i=this.importCapture.find(t=>t.sourceHint===`tool:${e.toolCallId}`),s=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});i?i.payload=s:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:s})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const i=p();return new Promise(s=>{const t=setTimeout(()=>{this.pendingPermissions.delete(i),s({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);t.unref?.(),this.pendingPermissions.set(i,{optionIds:new Set(e.options.map(n=>n.optionId)),resolve:s,timer:t}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:i,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(n=>({id:n.optionId,name:n.name,kind:n.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}buildEnvironment(){return this.managedAgentPolicy?w(this.managedAgentPolicy)?b(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},i=this.managedAgentPolicy?.adapterPolicy;return!i||w(this.managedAgentPolicy)?e:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&i.fileAccess!=="workspace-read"),terminal:!1}}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,i){let s;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:i}),new Promise((t,n)=>{s=setTimeout(()=>n(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),s.unref?.()})])}catch(t){throw t instanceof Error&&t.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),t}finally{s&&clearTimeout(s)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function B(d){A(f(d.id),()=>new x(d))}export{x as AcpAgentAdapter,B as registerAcpAgent};
|
|
3
|
+
`)});for(const h of i??[])r.push({type:"resource_link",uri:I(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const c=await this.promptWithTimeout(o,r);this.active=!1,c.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(r){this.active=!1,this.cancelPendingPermissions();const a=r instanceof Error?r.message:String(r),c=r instanceof w&&r.code===-32e3;throw c&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...s?{reasoningEffort:s}:{},...i?{attachments:[...i]}:{},...n!==void 0?{systemPrompt:n}:{}})),this.emitEvent({state:"error",message:a,...c?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),r}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const s=this.pendingPermissions.get(e);if(!s)throw new Error("ACP permission request is no longer pending");if(!s.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(s.timer),s.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=this.configOptions.find(o=>o.category==="model"&&o.type==="select"),t=this.configOptions.find(o=>o.category==="thought_level"&&o.type==="select"),s=this.modes?.availableModes.map(o=>({id:o.id,name:o.name,...o.description?{description:o.description}:{}}))??[],i=o=>(o?.options??[]).flatMap(r=>"options"in r?r.options:[r]),n=(t?i(t):s).map(o=>({id:"value"in o?o.value:o.id,name:o.name,...o.description?{description:o.description}:{}}));return{models:i(e).map(o=>({id:o.value,name:o.name,...o.description?{description:o.description}:{},...o.value===e?.currentValue?{isDefault:!0}:{},...n.length?{supportedReasoningEfforts:n}:{}})),modes:s}}async authenticate(e,t={}){const s=this.requireClient(),i=s.initializeResponse?.authMethods?.find(n=>n.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await s.close(),await q({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(n=>typeof n[1]=="string"))},i,this.workDir)}else await s.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(n){throw E(),n}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const s=[];let i;for(let n=0;n<10&&s.length<500;n+=1){let o=e.cwd;if(o)try{o=g.native(o)}catch{}const r=await t.listSessions(o,i);if(s.push(...r.sessions.slice(0,500-s.length).map(a=>({agentSessionId:a.sessionId,cwd:a.cwd,...a.title?{title:a.title.slice(0,200)}:{},...a.updatedAt?{updatedAt:a.updatedAt}:{}}))),i=r.nextCursor,!i)break}return s}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const s=[];this.importCapture=s;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,y(!0)}catch(i){throw y(!1),i}finally{this.importCapture=null}return s.map((i,n)=>({sourceId:i.sourceHint??m("sha256").update(`${e}\0${n}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const s=e.capabilities;if(s.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(s.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId;return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const s=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of s){if(!i.value)continue;const n=this.configOptions.find(o=>o.category===i.category&&o.type==="select");!n||n.currentValue===i.value||(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:n.id,value:i.value}),n.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of A(e.update,s=>this.makeEvent(s)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,s=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,n=i?this.importCapture.find(o=>o.sourceHint===i):this.importCapture.at(-1);n?.role===s&&n.sourceHint===i?n.payload+=t:this.importCapture.push({role:s,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,s=this.importCapture.find(n=>n.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};s?s.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),s=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=s:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:s})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=p();return new Promise(s=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),s({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(n=>n.optionId)),resolve:s,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(n=>({id:n.optionId,name:n.name,kind:n.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new P(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?S(this.managedAgentPolicy)?b(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return!t||S(this.managedAgentPolicy)?e:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!1}}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let s;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,n)=>{s=setTimeout(()=>n(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),s.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{s&&clearTimeout(s)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function J(u){v(f(u.id),()=>new x(u))}export{x as AcpAgentAdapter,J as registerAcpAgent};
|
|
@@ -6,12 +6,13 @@ export declare class AcpClientServices {
|
|
|
6
6
|
terminal?: boolean;
|
|
7
7
|
};
|
|
8
8
|
private readonly root;
|
|
9
|
+
private readonly environment;
|
|
9
10
|
private readonly terminals;
|
|
10
11
|
constructor(workDir: string, enabled: {
|
|
11
12
|
readTextFile?: boolean;
|
|
12
13
|
writeTextFile?: boolean;
|
|
13
14
|
terminal?: boolean;
|
|
14
|
-
});
|
|
15
|
+
}, environment?: NodeJS.ProcessEnv);
|
|
15
16
|
get capabilities(): {
|
|
16
17
|
fs: {
|
|
17
18
|
readTextFile: boolean;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import c from"node:fs";import n from"node:path";import{randomUUID as p}from"node:crypto";import{spawn as w}from"node:child_process";import{terminateProcessTree as m}from"./process-tree.js";class F{enabled;root;terminals=new Map;constructor(t,e){this.enabled=e,this.root=c.realpathSync(t)}get capabilities(){return{fs:{readTextFile:!!this.enabled.readTextFile,writeTextFile:!!this.enabled.writeTextFile},terminal:!!this.enabled.terminal}}async readTextFile(t){if(!this.enabled.readTextFile)throw new Error("ACP file reads are disabled");const r=(await c.promises.readFile(await this.resolve(t.path,!1),"utf8")).split(`
|
|
1
|
+
import c from"node:fs";import n from"node:path";import{randomUUID as p}from"node:crypto";import{spawn as w}from"node:child_process";import{terminateProcessTree as m}from"./process-tree.js";class F{enabled;root;environment;terminals=new Map;constructor(t,e,r=process.env){this.enabled=e,this.root=c.realpathSync(t),this.environment={...r}}get capabilities(){return{fs:{readTextFile:!!this.enabled.readTextFile,writeTextFile:!!this.enabled.writeTextFile},terminal:!!this.enabled.terminal}}async readTextFile(t){if(!this.enabled.readTextFile)throw new Error("ACP file reads are disabled");const r=(await c.promises.readFile(await this.resolve(t.path,!1),"utf8")).split(`
|
|
2
2
|
`),a=Math.max(0,(t.line??1)-1),i=Math.min(Math.max(0,t.limit??r.length),1e5);return{content:r.slice(a,a+i).join(`
|
|
3
|
-
`)}}async writeTextFile(t){if(!this.enabled.writeTextFile)throw new Error("ACP file writes are disabled");const e=await this.resolve(t.path,!0);await c.promises.writeFile(e,t.content,"utf8")}async createTerminal(t){if(!this.enabled.terminal)throw new Error("ACP terminals are disabled");const e=await this.resolve(t.cwd??this.root,!1),r=w(t.command,t.args??[],{cwd:e,env:{...
|
|
3
|
+
`)}}async writeTextFile(t){if(!this.enabled.writeTextFile)throw new Error("ACP file writes are disabled");const e=await this.resolve(t.path,!0);await c.promises.writeFile(e,t.content,"utf8")}async createTerminal(t){if(!this.enabled.terminal)throw new Error("ACP terminals are disabled");const e=await this.resolve(t.cwd??this.root,!1),r=w(t.command,t.args??[],{cwd:e,env:{...this.environment,...Object.fromEntries((t.env??[]).map(s=>[s.name,s.value]))},stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0}),a=Math.min(Number(t.outputByteLimit??1024*1024),4*1024*1024),i={child:r,output:Buffer.alloc(0),limit:a,truncated:!1,exitStatus:null,exited:new Promise(s=>r.once("exit",(o,h)=>{const d={exitCode:o,signal:h};i.exitStatus=d,s(d)}))},l=s=>{if(i.output=Buffer.concat([i.output,s]),i.output.byteLength>i.limit){let o=i.output.byteLength-i.limit;for(;o<i.output.byteLength&&(i.output[o]&192)===128;)o+=1;i.output=i.output.subarray(o),i.truncated=!0}};r.stdout.on("data",l),r.stderr.on("data",l);const u=p();return this.terminals.set(u,i),{terminalId:u}}terminalOutput(t){const e=this.requireTerminal(t.terminalId);return{output:e.output.toString("utf8"),truncated:e.truncated,exitStatus:e.exitStatus}}async waitForTerminalExit(t){return this.requireTerminal(t.terminalId).exited}killTerminal(t){m(this.requireTerminal(t.terminalId).child)}releaseTerminal(t){const e=this.requireTerminal(t.terminalId);e.exitStatus||m(e.child),this.terminals.delete(t.terminalId)}close(){for(const t of this.terminals.values())t.exitStatus||m(t.child);this.terminals.clear()}requireTerminal(t){const e=this.terminals.get(t);if(!e)throw new Error("Unknown ACP terminal");return e}async resolve(t,e){if(!n.isAbsolute(t))throw new Error("ACP path must be absolute");const r=n.resolve(t),a=e?n.dirname(r):r,i=await c.promises.realpath(a),l=e?n.join(i,n.basename(r)):i,u=n.relative(this.root,l);if(u.startsWith("..")||n.isAbsolute(u))throw new Error("ACP path is outside the session workspace");return l}}export{F as AcpClientServices};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{RequestError as
|
|
1
|
+
import{RequestError as R}from"@agentclientprotocol/sdk";import{buildCommandStringLaunchSpec as T,commandExists as E,resolveCommandFileIdentity as F,resolveCommandFilePath as P}from"../command-spec.js";import{registerAcpAgent as x}from"./adapter.js";import{getRegisteredAgents as L,unregisterAgent as N}from"../adapter.js";import{readAcpManifests as D}from"./manifests.js";import{AcpProcessClient as _}from"./process-client.js";import{acpAgentType as h}from"./types.js";import{loadAcpCatalog as q}from"./catalog.js";import{buildAcpCapabilityCacheKey as K,readAcpCapabilityCache as O,writeAcpCapabilityCache as W}from"./capability-cache.js";import{getAcpRuntimeAuthState as I,setAcpRuntimeAuthState as $}from"./auth-state.js";import{recordAcpScan as H}from"./metrics.js";import{fingerprintNativeExecutable as U}from"../../security/managed-agent-executable.js";const V=[{id:"qwen-code",name:"Qwen Code",source:"registry",launch:{command:"qwen",args:["--acp"]}},{id:"kimi",name:"Kimi CLI",source:"registry",launch:{command:"kimi",args:["acp"]}}],j=new Set(["claude","codex","codebuddy","cursor","opencode","pi"]);async function le(t={}){const i=Date.now();let o=0,n=0;const a={},f=new Set(L().filter(e=>e.startsWith("acp:"))),c=t.candidates?{candidates:t.candidates,revision:void 0}:await q(t),A=G([...c.candidates.length?c.candidates:V,...D()]),B=A.filter(e=>{const l=e.launch.command;return j.has(l)?!1:E(l)}).filter((e,l,g)=>g.findIndex(v=>v.id===e.id)===l),C=(await J(B,3,async e=>{const l=P(e.launch.command),g=l?U(l):void 0,u={...T(e.launch.command,e.launch.args??[],t.cwd??process.cwd()),...e.launch.env?{env:e.launch.env}:{}},y=K({manifest:e,platform:process.platform,catalogRevision:c.revision,executableIdentity:F(e.launch.command)}),d=y?O(y):null;if(d?.type===h(e.id)&&d.integration==="acp"&&d.acpCapabilities?.protocolVersion===1)return o+=1,x({...e,launch:u,authLaunch:e.launch}),{...d,authState:I(h(e.id))??d.authState,command:u.command,args:u.args??[],executableFingerprint:g,display:{...d.display,name:e.name},...c.revision?{catalogRevision:c.revision}:{}};const w=new _(u,{onSessionUpdate:()=>{},onPermission:async()=>({outcome:{outcome:"cancelled"}})},process.env,{terminalAuth:!0});try{const r=await w.start(t.cwd??process.cwd()),s=r.agentCapabilities??{},M={protocolVersion:1,listSessions:!!s.sessionCapabilities?.list,loadSession:!!s.loadSession,resumeSession:!!s.sessionCapabilities?.resume,closeSession:!!s.sessionCapabilities?.close,deleteSession:!!s.sessionCapabilities?.delete,terminal:!!e.clientCapabilities?.terminal,fileRead:!!e.clientCapabilities?.readTextFile,fileWrite:!!e.clientCapabilities?.writeTextFile,permission:!0,modelConfig:!1};let p=r.authMethods?.length?"unknown":"ready";if(s.sessionCapabilities?.list)try{await w.listSessions(t.cwd??process.cwd()),p=r.authMethods?.length?"unknown":"ready"}catch(m){p=m instanceof R&&m.code===-32e3?"required":"unknown"}const S=I(h(e.id));S?p=S:p==="required"&&$(h(e.id),p),x({...e,launch:u,authLaunch:e.launch});const b={type:h(e.id),command:u.command,args:u.args??[],version:r.agentInfo?.version??void 0,runtimePlatform:process.platform,executableFingerprint:g,integration:"acp",display:{name:e.name,version:r.agentInfo?.version??void 0},acpCapabilities:M,authState:p,acpAuthMethods:(r.authMethods??[]).slice(0,8).map(m=>({id:m.id.slice(0,128),name:m.name.slice(0,80),type:"type"in m&&m.type==="terminal"?"terminal":"agent"})),...c.revision?{catalogRevision:c.revision}:{}};return y&&W(y,b),b}catch(r){n+=1;const s=z(r);return a[s]=(a[s]??0)+1,null}finally{await w.close()}})).filter(e=>!!e),k=new Set(C.map(e=>e.type));for(const e of f)k.has(e)||N(e);return H({durationMs:Date.now()-i,candidateCount:A.length,installedCount:C.length,cacheHits:o,handshakeFailures:n,handshakeFailuresByKind:a}),C}function z(t){const i=t instanceof Error?t.message:"";return/timed out/i.test(i)?"timeout":/protocol version/i.test(i)?"version":/safety limit|exceeded/i.test(i)?"output_limit":/json|parse/i.test(i)?"invalid_protocol":/enoent|not found/i.test(i)?"launch":"other"}function G(t){const i=new Set(t.filter(n=>n.source==="local").map(n=>n.id)),o=new Map;for(const n of t){if(n.source!=="local"&&i.has(n.id))continue;const a=`${n.id}\0${n.launch.command}\0${JSON.stringify(n.launch.args??[])}`;o.has(a)||o.set(a,n)}return[...o.values()]}async function J(t,i,o){const n=new Array(t.length);let a=0;return await Promise.all(Array.from({length:Math.min(i,t.length)},async()=>{for(;;){const f=a++;if(f>=t.length)return;n[f]=await o(t[f])}})),n}export{le as discoverAcpAgents};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as m}from"node:child_process";import{Readable as d,Transform as p,Writable as S}from"node:stream";import*as n from"@agentclientprotocol/sdk";import{AcpClientServices as f}from"./client-services.js";import{terminateProcessTree as h}from"./process-tree.js";class _{launch;handlers;environment;clientCapabilities;timeouts;process=null;connection=null;initialization=null;stderr="";clientServices=null;constructor(i,t,s=process.env,r={},o={}){this.launch=i,this.handlers=t,this.environment=s,this.clientCapabilities=r,this.timeouts=o}get capabilities(){return this.initialization?.agentCapabilities??{}}get initializeResponse(){return this.initialization}async listSessions(i,t){return a(this.agent.request(n.methods.agent.session.list,{cwd:i,cursor:t}),this.timeouts.sessionMs??8e3,"ACP session list timed out")}async authenticate(i){await a(this.agent.request(n.methods.agent.authenticate,{methodId:i}),this.timeouts.authMs??12e4,"ACP authentication timed out")}async logout(){await a(this.agent.request(n.methods.agent.logout,{}),8e3,"ACP logout timed out")}async closeSession(i){await a(this.agent.request(n.methods.agent.session.close,{sessionId:i}),8e3,"ACP session close timed out")}async deleteSession(i){await a(this.agent.request(n.methods.agent.session.delete,{sessionId:i}),8e3,"ACP session delete timed out")}get agent(){if(!this.connection)throw new Error("ACP process is not connected");return this.connection.agent}async start(i){if(this.connection)return this.initialization;const t=m(this.launch.command,this.launch.args??[],{cwd:i,env:{...this.environment,...this.launch.env},stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0});this.process=t,t.stderr.on("data",e=>{this.stderr.length<16384&&(this.stderr+=e.toString())}),this.clientServices=Object.values(this.clientCapabilities).some(Boolean)?new f(i,this.clientCapabilities):null;let s=n.client({name:"Shennian"}).onRequest(n.methods.client.session.requestPermission,({params:e})=>this.handlers.onPermission(e)).onNotification(n.methods.client.session.update,({params:e})=>this.handlers.onSessionUpdate(e));this.clientServices?.enabled.readTextFile&&(s=s.onRequest(n.methods.client.fs.readTextFile,({params:e})=>this.clientServices.readTextFile(e))),this.clientServices?.enabled.writeTextFile&&(s=s.onRequest(n.methods.client.fs.writeTextFile,({params:e})=>this.clientServices.writeTextFile(e))),this.clientServices?.enabled.terminal&&(s=s.onRequest(n.methods.client.terminal.create,({params:e})=>this.clientServices.createTerminal(e)).onRequest(n.methods.client.terminal.output,({params:e})=>this.clientServices.terminalOutput(e)).onRequest(n.methods.client.terminal.waitForExit,({params:e})=>this.clientServices.waitForTerminalExit(e)).onRequest(n.methods.client.terminal.kill,({params:e})=>this.clientServices.killTerminal(e)).onRequest(n.methods.client.terminal.release,({params:e})=>this.clientServices.releaseTerminal(e)));const r=new p({transform:
|
|
1
|
+
import{spawn as m}from"node:child_process";import{Readable as d,Transform as p,Writable as S}from"node:stream";import*as n from"@agentclientprotocol/sdk";import{AcpClientServices as f}from"./client-services.js";import{terminateProcessTree as h}from"./process-tree.js";class _{launch;handlers;environment;clientCapabilities;timeouts;process=null;connection=null;initialization=null;stderr="";clientServices=null;constructor(i,t,s=process.env,r={},o={}){this.launch=i,this.handlers=t,this.environment=s,this.clientCapabilities=r,this.timeouts=o}get capabilities(){return this.initialization?.agentCapabilities??{}}get initializeResponse(){return this.initialization}async listSessions(i,t){return a(this.agent.request(n.methods.agent.session.list,{cwd:i,cursor:t}),this.timeouts.sessionMs??8e3,"ACP session list timed out")}async authenticate(i){await a(this.agent.request(n.methods.agent.authenticate,{methodId:i}),this.timeouts.authMs??12e4,"ACP authentication timed out")}async logout(){await a(this.agent.request(n.methods.agent.logout,{}),8e3,"ACP logout timed out")}async closeSession(i){await a(this.agent.request(n.methods.agent.session.close,{sessionId:i}),8e3,"ACP session close timed out")}async deleteSession(i){await a(this.agent.request(n.methods.agent.session.delete,{sessionId:i}),8e3,"ACP session delete timed out")}get agent(){if(!this.connection)throw new Error("ACP process is not connected");return this.connection.agent}async start(i){if(this.connection)return this.initialization;const t=m(this.launch.command,this.launch.args??[],{cwd:i,env:{...this.environment,...this.launch.env},stdio:["pipe","pipe","pipe"],detached:process.platform!=="win32",windowsHide:!0});this.process=t,t.stderr.on("data",e=>{this.stderr.length<16384&&(this.stderr+=e.toString())}),this.clientServices=Object.values(this.clientCapabilities).some(Boolean)?new f(i,this.clientCapabilities,{...this.environment,...this.launch.env}):null;let s=n.client({name:"Shennian"}).onRequest(n.methods.client.session.requestPermission,({params:e})=>this.handlers.onPermission(e)).onNotification(n.methods.client.session.update,({params:e})=>this.handlers.onSessionUpdate(e));this.clientServices?.enabled.readTextFile&&(s=s.onRequest(n.methods.client.fs.readTextFile,({params:e})=>this.clientServices.readTextFile(e))),this.clientServices?.enabled.writeTextFile&&(s=s.onRequest(n.methods.client.fs.writeTextFile,({params:e})=>this.clientServices.writeTextFile(e))),this.clientServices?.enabled.terminal&&(s=s.onRequest(n.methods.client.terminal.create,({params:e})=>this.clientServices.createTerminal(e)).onRequest(n.methods.client.terminal.output,({params:e})=>this.clientServices.terminalOutput(e)).onRequest(n.methods.client.terminal.waitForExit,({params:e})=>this.clientServices.waitForTerminalExit(e)).onRequest(n.methods.client.terminal.kill,({params:e})=>this.clientServices.killTerminal(e)).onRequest(n.methods.client.terminal.release,({params:e})=>this.clientServices.releaseTerminal(e)));const r=new p({transform:v(()=>h(t,!0))});t.stdout.pipe(r);const o=n.ndJsonStream(S.toWeb(t.stdin),d.toWeb(r)),l=s.connect(o);this.connection=l,t.once("error",e=>l.close(e)),t.once("exit",(e,u)=>{l.close(new Error(`ACP agent exited (${e??u??"unknown"})`))});try{const e=await a(l.agent.request(n.methods.agent.initialize,{protocolVersion:n.PROTOCOL_VERSION,clientCapabilities:{...this.clientServices?.capabilities??{},...this.clientCapabilities.terminalAuth?{auth:{terminal:!0}}:{}},clientInfo:{name:"Shennian",version:"0.4.13"}}),this.timeouts.initializeMs??8e3,"ACP initialize timed out");if(e.protocolVersion!==n.PROTOCOL_VERSION)throw new Error(`Unsupported ACP protocol version ${e.protocolVersion}`);return this.initialization=e,e}catch(e){throw await this.close(),e}}async close(){const i=this.connection,t=this.process;this.connection=null,this.process=null,this.initialization=null,this.clientServices?.close(),this.clientServices=null,i?.close(),t&&t.exitCode===null&&t.signalCode===null&&(h(t),setTimeout(()=>h(t,!0),2e3).unref?.())}}const g=4*1024*1024,w=64*1024*1024;function v(c){let i=0,t=0;return function(s,r,o){i+=s.length;for(const l of s)t=l===10?0:t+1;if(i>w||t>g){c(),o(new Error("ACP output exceeded safety limit"));return}o(null,s)}}async function a(c,i,t){let s;try{return await Promise.race([c,new Promise((r,o)=>{s=setTimeout(()=>o(new Error(t)),i)})])}finally{s&&clearTimeout(s)}}export{_ as AcpProcessClient};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import p from"node:fs";import o from"node:path";import{createInterface as y}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as S,registerAgent as E}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}}class F extends S{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;terminalState="open";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",
|
|
3
|
-
`)){const d=u.trim();
|
|
4
|
-
`})}}),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=L();return
|
|
1
|
+
import p from"node:fs";import o from"node:path";import{createInterface as y}from"node:readline";import{randomUUID as f}from"node:crypto";import{AgentAdapter as S,registerAgent as E}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as x,spawnResolvedCommandSync as v}from"./command-spec.js";import{buildAgentProcessEnv as P,buildManagedAgentProcessEnv as I,buildManagedNativeFullProcessEnv as C}from"../agent-env.js";import{buildPlatformInstructions as g}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as k,isManagedAgentNativeFull as c}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as w}from"../security/managed-agent-runtime.js";import{resolveManagedRoomIpcPaths as A}from"../daemon-ipc/paths.js";import{CLAUDE_MANAGED_RUNTIME_SECURITY as _,compileClaudeManagedPermissions as T}from"./claude-managed-permissions.js";w("claude",_);function R(n){return n?.trim()||"default"}const O=new Set(["low","medium","high","xhigh","max"]),h=new Map;function M(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 X(){h.clear()}function N(n){const e=n.trim();return e?!e.includes("claude.ai connectors are disabled because"):!1}function D(){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}}class F extends S{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;terminalState="open";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",R(t));const d=M(s);d&&D()&&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",new Error('Command "claude" not found. Is Claude Code CLI installed?'));return}const s=x(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=s,y({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(`
|
|
3
|
+
`)){const d=u.trim();N(d)&&this.emitEvent({state:"delta",text:d+`
|
|
4
|
+
`})}}),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=L();return T(k(e),e.adapterPolicy.workDir,{internalReadPaths:t.readPaths,internalUnixSockets:t.unixSockets,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}buildProcessEnv(){return this.managedAgentPolicy?c(this.managedAgentPolicy)?C({NO_COLOR:"1",...this.extraEnv}):I({agentType:"claude",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}}):P(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.emitErrorIfOpen({state:"error",message:'Claude authentication failed. Run "claude auth login" and retry.'});return}if(e.type==="assistant"){if(e.message?.content){for(const t of e.message.content)if(t.type==="text"&&t.text){const s=this.hasEmittedText?`
|
|
5
5
|
|
|
6
6
|
`:"";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"&&this.emitEvent({state:"tool-call",name:t.name,args:t.input});return}if(e.subtype==="text"&&e.text){const t=this.hasEmittedText?`
|
|
7
7
|
|
|
8
|
-
`:"";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==="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=e.usage??e.message?.usage;this.
|
|
8
|
+
`:"";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==="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"})}handleProcessClose(e,t){if(e!==0&&e!==null){const s=t.trim()||`claude exited with code ${e}`;this.emitErrorIfOpen({state:"error",message:s});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.terminalState="open",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 L(){const n=A(),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(...U(s.path)),{readPaths:[...new Set(e)].sort(),unixSockets:[...new Set(t)].sort()}}function U(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()}E("claude",()=>new F);export{F as ClaudeAdapter,R as normalizeClaudeModelId,M as normalizeClaudeReasoningEffort,X as resetClaudeCapabilityCacheForTests,L as resolveClaudeManagedInternalAccess,U as resolveClaudeShennianCliReadPaths,N as shouldForwardClaudeStderrLine,D as supportsClaudeReasoningEffort};
|