shennian 0.5.1 → 0.5.3
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 +65 -70
- package/dist/src/agents/acp/adapter.js +2 -2
- package/dist/src/agents/acp/client-services.js +1 -1
- package/dist/src/agents/acp/process-client.js +1 -1
- package/dist/src/agents/config-status.js +1 -1
- package/dist/src/agents/model-registry/cache.js +1 -1
- package/dist/src/agents/model-registry/discovery.js +3 -3
- package/dist/src/agents/model-registry/opencode-api.js +1 -1
- package/dist/src/agents/model-registry/service.js +1 -1
- package/dist/src/agents/model-registry.js +1 -1
- package/dist/src/agents/opencode.js +1 -1
- package/dist/src/agents/pi-coding-agent.js +3 -4
- package/dist/src/agents/pi-turn-diagnostics.js +1 -0
- package/dist/src/agents/process-tree.js +1 -0
- package/dist/src/commands/agent-readiness.js +2 -2
- package/dist/src/commands/room.js +3 -3
- package/dist/src/daemon-ipc/agent-readiness.js +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/manager/runtime.js +4 -4
- package/dist/src/room/activation-service.js +1 -1
- package/dist/src/room/attachment-upload.js +1 -1
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/room/mirror-sync-service.js +1 -1
- package/dist/src/room/room-action-client.js +1 -1
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
- package/dist/src/session/handlers/chat-events.js +2 -2
- package/dist/src/session/handlers/chat-recovery.js +1 -1
- package/dist/src/session/handlers/chat.js +1 -1
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/queue.js +1 -1
- package/node_modules/@shennian/wire/dist/session.js +1 -1
- package/package.json +1 -1
- package/dist/src/agents/acp/process-tree.js +0 -1
- package/dist/src/agents/pi-managed-model-broker.js +0 -1
- package/dist/src/session/handlers/pi-validation-session.js +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 235,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian.js",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"file": "src/agents/acp/adapter.js",
|
|
19
|
-
"beforeBytes":
|
|
20
|
-
"afterBytes":
|
|
19
|
+
"beforeBytes": 26392,
|
|
20
|
+
"afterBytes": 13813
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"file": "src/agents/acp/auth-state.js",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"file": "src/agents/acp/client-services.js",
|
|
44
|
-
"beforeBytes":
|
|
45
|
-
"afterBytes":
|
|
44
|
+
"beforeBytes": 6337,
|
|
45
|
+
"afterBytes": 3536
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"file": "src/agents/acp/discovery.js",
|
|
@@ -71,13 +71,8 @@
|
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"file": "src/agents/acp/process-client.js",
|
|
74
|
-
"beforeBytes":
|
|
75
|
-
"afterBytes":
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"file": "src/agents/acp/process-tree.js",
|
|
79
|
-
"beforeBytes": 698,
|
|
80
|
-
"afterBytes": 371
|
|
74
|
+
"beforeBytes": 7305,
|
|
75
|
+
"afterBytes": 4421
|
|
81
76
|
},
|
|
82
77
|
{
|
|
83
78
|
"file": "src/agents/acp/types.js",
|
|
@@ -146,8 +141,8 @@
|
|
|
146
141
|
},
|
|
147
142
|
{
|
|
148
143
|
"file": "src/agents/config-status.js",
|
|
149
|
-
"beforeBytes":
|
|
150
|
-
"afterBytes":
|
|
144
|
+
"beforeBytes": 7855,
|
|
145
|
+
"afterBytes": 3923
|
|
151
146
|
},
|
|
152
147
|
{
|
|
153
148
|
"file": "src/agents/cursor-managed-permissions.js",
|
|
@@ -201,18 +196,18 @@
|
|
|
201
196
|
},
|
|
202
197
|
{
|
|
203
198
|
"file": "src/agents/model-registry/cache.js",
|
|
204
|
-
"beforeBytes":
|
|
205
|
-
"afterBytes":
|
|
199
|
+
"beforeBytes": 1745,
|
|
200
|
+
"afterBytes": 673
|
|
206
201
|
},
|
|
207
202
|
{
|
|
208
203
|
"file": "src/agents/model-registry/discovery.js",
|
|
209
|
-
"beforeBytes":
|
|
210
|
-
"afterBytes":
|
|
204
|
+
"beforeBytes": 11107,
|
|
205
|
+
"afterBytes": 5219
|
|
211
206
|
},
|
|
212
207
|
{
|
|
213
208
|
"file": "src/agents/model-registry/opencode-api.js",
|
|
214
|
-
"beforeBytes":
|
|
215
|
-
"afterBytes":
|
|
209
|
+
"beforeBytes": 3259,
|
|
210
|
+
"afterBytes": 1580
|
|
216
211
|
},
|
|
217
212
|
{
|
|
218
213
|
"file": "src/agents/model-registry/parsers.js",
|
|
@@ -226,8 +221,8 @@
|
|
|
226
221
|
},
|
|
227
222
|
{
|
|
228
223
|
"file": "src/agents/model-registry/service.js",
|
|
229
|
-
"beforeBytes":
|
|
230
|
-
"afterBytes":
|
|
224
|
+
"beforeBytes": 9489,
|
|
225
|
+
"afterBytes": 3505
|
|
231
226
|
},
|
|
232
227
|
{
|
|
233
228
|
"file": "src/agents/model-registry/types.js",
|
|
@@ -236,8 +231,8 @@
|
|
|
236
231
|
},
|
|
237
232
|
{
|
|
238
233
|
"file": "src/agents/model-registry.js",
|
|
239
|
-
"beforeBytes":
|
|
240
|
-
"afterBytes":
|
|
234
|
+
"beforeBytes": 986,
|
|
235
|
+
"afterBytes": 928
|
|
241
236
|
},
|
|
242
237
|
{
|
|
243
238
|
"file": "src/agents/native-capabilities.js",
|
|
@@ -256,8 +251,8 @@
|
|
|
256
251
|
},
|
|
257
252
|
{
|
|
258
253
|
"file": "src/agents/opencode.js",
|
|
259
|
-
"beforeBytes":
|
|
260
|
-
"afterBytes":
|
|
254
|
+
"beforeBytes": 13890,
|
|
255
|
+
"afterBytes": 7062
|
|
261
256
|
},
|
|
262
257
|
{
|
|
263
258
|
"file": "src/agents/pi-coding-agent-managed-permissions.js",
|
|
@@ -266,19 +261,14 @@
|
|
|
266
261
|
},
|
|
267
262
|
{
|
|
268
263
|
"file": "src/agents/pi-coding-agent.js",
|
|
269
|
-
"beforeBytes":
|
|
270
|
-
"afterBytes":
|
|
264
|
+
"beforeBytes": 28451,
|
|
265
|
+
"afterBytes": 15071
|
|
271
266
|
},
|
|
272
267
|
{
|
|
273
268
|
"file": "src/agents/pi-managed-extension.js",
|
|
274
269
|
"beforeBytes": 10227,
|
|
275
270
|
"afterBytes": 9273
|
|
276
271
|
},
|
|
277
|
-
{
|
|
278
|
-
"file": "src/agents/pi-managed-model-broker.js",
|
|
279
|
-
"beforeBytes": 8635,
|
|
280
|
-
"afterBytes": 4663
|
|
281
|
-
},
|
|
282
272
|
{
|
|
283
273
|
"file": "src/agents/pi-rpc-client.js",
|
|
284
274
|
"beforeBytes": 5326,
|
|
@@ -289,11 +279,21 @@
|
|
|
289
279
|
"beforeBytes": 2397,
|
|
290
280
|
"afterBytes": 1328
|
|
291
281
|
},
|
|
282
|
+
{
|
|
283
|
+
"file": "src/agents/pi-turn-diagnostics.js",
|
|
284
|
+
"beforeBytes": 7200,
|
|
285
|
+
"afterBytes": 3920
|
|
286
|
+
},
|
|
292
287
|
{
|
|
293
288
|
"file": "src/agents/platform-instructions.js",
|
|
294
289
|
"beforeBytes": 2829,
|
|
295
290
|
"afterBytes": 1705
|
|
296
291
|
},
|
|
292
|
+
{
|
|
293
|
+
"file": "src/agents/process-tree.js",
|
|
294
|
+
"beforeBytes": 2647,
|
|
295
|
+
"afterBytes": 856
|
|
296
|
+
},
|
|
297
297
|
{
|
|
298
298
|
"file": "src/agents/runtime-compatibility.js",
|
|
299
299
|
"beforeBytes": 1587,
|
|
@@ -321,8 +321,8 @@
|
|
|
321
321
|
},
|
|
322
322
|
{
|
|
323
323
|
"file": "src/commands/agent-readiness.js",
|
|
324
|
-
"beforeBytes":
|
|
325
|
-
"afterBytes":
|
|
324
|
+
"beforeBytes": 7770,
|
|
325
|
+
"afterBytes": 6041
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
"file": "src/commands/agent.js",
|
|
@@ -406,8 +406,8 @@
|
|
|
406
406
|
},
|
|
407
407
|
{
|
|
408
408
|
"file": "src/commands/room.js",
|
|
409
|
-
"beforeBytes":
|
|
410
|
-
"afterBytes":
|
|
409
|
+
"beforeBytes": 18609,
|
|
410
|
+
"afterBytes": 10774
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
413
|
"file": "src/commands/runtime.js",
|
|
@@ -441,8 +441,8 @@
|
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
443
|
"file": "src/daemon-ipc/agent-readiness.js",
|
|
444
|
-
"beforeBytes":
|
|
445
|
-
"afterBytes":
|
|
444
|
+
"beforeBytes": 5145,
|
|
445
|
+
"afterBytes": 2587
|
|
446
446
|
},
|
|
447
447
|
{
|
|
448
448
|
"file": "src/daemon-ipc/client.js",
|
|
@@ -516,8 +516,8 @@
|
|
|
516
516
|
},
|
|
517
517
|
{
|
|
518
518
|
"file": "src/index.js",
|
|
519
|
-
"beforeBytes":
|
|
520
|
-
"afterBytes":
|
|
519
|
+
"beforeBytes": 42698,
|
|
520
|
+
"afterBytes": 21157
|
|
521
521
|
},
|
|
522
522
|
{
|
|
523
523
|
"file": "src/log-redaction.js",
|
|
@@ -546,8 +546,8 @@
|
|
|
546
546
|
},
|
|
547
547
|
{
|
|
548
548
|
"file": "src/manager/runtime.js",
|
|
549
|
-
"beforeBytes":
|
|
550
|
-
"afterBytes":
|
|
549
|
+
"beforeBytes": 35692,
|
|
550
|
+
"afterBytes": 17388
|
|
551
551
|
},
|
|
552
552
|
{
|
|
553
553
|
"file": "src/manager/worker-ipc.js",
|
|
@@ -706,8 +706,8 @@
|
|
|
706
706
|
},
|
|
707
707
|
{
|
|
708
708
|
"file": "src/room/activation-service.js",
|
|
709
|
-
"beforeBytes":
|
|
710
|
-
"afterBytes":
|
|
709
|
+
"beforeBytes": 28666,
|
|
710
|
+
"afterBytes": 15706
|
|
711
711
|
},
|
|
712
712
|
{
|
|
713
713
|
"file": "src/room/attachment-cache.js",
|
|
@@ -716,8 +716,8 @@
|
|
|
716
716
|
},
|
|
717
717
|
{
|
|
718
718
|
"file": "src/room/attachment-upload.js",
|
|
719
|
-
"beforeBytes":
|
|
720
|
-
"afterBytes":
|
|
719
|
+
"beforeBytes": 7283,
|
|
720
|
+
"afterBytes": 3698
|
|
721
721
|
},
|
|
722
722
|
{
|
|
723
723
|
"file": "src/room/device-authorization-client.js",
|
|
@@ -761,13 +761,13 @@
|
|
|
761
761
|
},
|
|
762
762
|
{
|
|
763
763
|
"file": "src/room/managed-room-ipc.js",
|
|
764
|
-
"beforeBytes":
|
|
765
|
-
"afterBytes":
|
|
764
|
+
"beforeBytes": 15570,
|
|
765
|
+
"afterBytes": 7327
|
|
766
766
|
},
|
|
767
767
|
{
|
|
768
768
|
"file": "src/room/mirror-sync-service.js",
|
|
769
|
-
"beforeBytes":
|
|
770
|
-
"afterBytes":
|
|
769
|
+
"beforeBytes": 12375,
|
|
770
|
+
"afterBytes": 5688
|
|
771
771
|
},
|
|
772
772
|
{
|
|
773
773
|
"file": "src/room/public-attachment-cache.js",
|
|
@@ -791,8 +791,8 @@
|
|
|
791
791
|
},
|
|
792
792
|
{
|
|
793
793
|
"file": "src/room/room-action-client.js",
|
|
794
|
-
"beforeBytes":
|
|
795
|
-
"afterBytes":
|
|
794
|
+
"beforeBytes": 29246,
|
|
795
|
+
"afterBytes": 14863
|
|
796
796
|
},
|
|
797
797
|
{
|
|
798
798
|
"file": "src/room/room-binding-client.js",
|
|
@@ -896,8 +896,8 @@
|
|
|
896
896
|
},
|
|
897
897
|
{
|
|
898
898
|
"file": "src/session/handlers/agent-workspace-validation.js",
|
|
899
|
-
"beforeBytes":
|
|
900
|
-
"afterBytes":
|
|
899
|
+
"beforeBytes": 10525,
|
|
900
|
+
"afterBytes": 5385
|
|
901
901
|
},
|
|
902
902
|
{
|
|
903
903
|
"file": "src/session/handlers/agents.js",
|
|
@@ -916,13 +916,13 @@
|
|
|
916
916
|
},
|
|
917
917
|
{
|
|
918
918
|
"file": "src/session/handlers/chat-events.js",
|
|
919
|
-
"beforeBytes":
|
|
920
|
-
"afterBytes":
|
|
919
|
+
"beforeBytes": 18625,
|
|
920
|
+
"afterBytes": 7583
|
|
921
921
|
},
|
|
922
922
|
{
|
|
923
923
|
"file": "src/session/handlers/chat-recovery.js",
|
|
924
|
-
"beforeBytes":
|
|
925
|
-
"afterBytes":
|
|
924
|
+
"beforeBytes": 6918,
|
|
925
|
+
"afterBytes": 3623
|
|
926
926
|
},
|
|
927
927
|
{
|
|
928
928
|
"file": "src/session/handlers/chat-session-lifecycle.js",
|
|
@@ -931,8 +931,8 @@
|
|
|
931
931
|
},
|
|
932
932
|
{
|
|
933
933
|
"file": "src/session/handlers/chat.js",
|
|
934
|
-
"beforeBytes":
|
|
935
|
-
"afterBytes":
|
|
934
|
+
"beforeBytes": 35377,
|
|
935
|
+
"afterBytes": 15049
|
|
936
936
|
},
|
|
937
937
|
{
|
|
938
938
|
"file": "src/session/handlers/control.js",
|
|
@@ -949,11 +949,6 @@
|
|
|
949
949
|
"beforeBytes": 676,
|
|
950
950
|
"afterBytes": 392
|
|
951
951
|
},
|
|
952
|
-
{
|
|
953
|
-
"file": "src/session/handlers/pi-validation-session.js",
|
|
954
|
-
"beforeBytes": 2016,
|
|
955
|
-
"afterBytes": 1147
|
|
956
|
-
},
|
|
957
952
|
{
|
|
958
953
|
"file": "src/session/handlers/project-fs.js",
|
|
959
954
|
"beforeBytes": 3778,
|
|
@@ -1006,8 +1001,8 @@
|
|
|
1006
1001
|
},
|
|
1007
1002
|
{
|
|
1008
1003
|
"file": "src/session/manager.js",
|
|
1009
|
-
"beforeBytes":
|
|
1010
|
-
"afterBytes":
|
|
1004
|
+
"beforeBytes": 40733,
|
|
1005
|
+
"afterBytes": 21391
|
|
1011
1006
|
},
|
|
1012
1007
|
{
|
|
1013
1008
|
"file": "src/session/native-cleanup-outbox.js",
|
|
@@ -1071,8 +1066,8 @@
|
|
|
1071
1066
|
},
|
|
1072
1067
|
{
|
|
1073
1068
|
"file": "src/session/queue.js",
|
|
1074
|
-
"beforeBytes":
|
|
1075
|
-
"afterBytes":
|
|
1069
|
+
"beforeBytes": 41453,
|
|
1070
|
+
"afterBytes": 18387
|
|
1076
1071
|
},
|
|
1077
1072
|
{
|
|
1078
1073
|
"file": "src/session/queued-chat-dispatch.js",
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{randomUUID as
|
|
1
|
+
import{randomUUID as g}from"node:crypto";import{createHash as f}from"node:crypto";import{realpathSync as y}from"node:fs";import{pathToFileURL as v}from"node:url";import*as l from"@agentclientprotocol/sdk";import{RequestError as C}from"@agentclientprotocol/sdk";import{AgentAdapter as A,registerAgent as P}from"../adapter.js";import{mapAcpSessionUpdate as q}from"./events.js";import{AcpProcessClient as E}from"./process-client.js";import{acpAgentType as S}from"./types.js";import{runAcpTerminalAuthentication as b}from"./auth.js";import{setAcpRuntimeAuthState as d}from"./auth-state.js";import{recordAcpAuthFailure as x,recordAcpImportResult as I}from"./metrics.js";import{isManagedAgentNativeFull as w}from"../../security/managed-agent-policy.js";import{buildManagedNativeFullProcessEnv as O}from"../../agent-env.js";function p(c,e){return c.find(t=>t.category===e&&t.type==="select")}function m(c){return(c?.options??[]).flatMap(e=>"options"in e?e.options:[e])}class T extends A{manifest;options;type;get recoveryCapabilities(){const e=this.client?.capabilities;return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!!(e?.sessionCapabilities?.resume||e?.loadSession)}}client=null;workDir="";shennianSessionId="";requestedSessionId=null;agentSessionId=null;runId="";seq=0;active=!1;extraEnv={};pendingPermissions=new Map;configOptions=[];modes=null;importCapture=null;emittedToolStates=new Map;pendingAuthRetry=null;retryingAfterAuth=!1;managedAgentPolicy=null;configurationSignature="";startedConfigurationSignature="";constructor(e,t={}){super(),this.manifest=e,this.options=t,this.type=S(e.id)}configure(e){this.extraEnv=e.env??{},this.managedAgentPolicy=e.managedAgentPolicy??null,this.configurationSignature=f("sha256").update(JSON.stringify({env:Object.entries(this.extraEnv).sort(([t],[n])=>t.localeCompare(n)),managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}async start(e,t,n){this.shennianSessionId=e;try{this.workDir=y.native(t)}catch{this.workDir=t}this.requestedSessionId=n??null,this.agentSessionId=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}async send(e,t,n,i,s){await this.refreshProcessConfiguration();const a=this.requireClient();this.runId=g(),this.seq=0,this.emittedToolStates.clear();try{await this.ensureSession(),await this.applyDynamicConfig(t,n),this.active=!0,this.emitEvent({state:"start",runPhase:"thinking",agentSessionId:this.agentSessionId??void 0});const o=[],r=[];s?.trim()&&r.push(s.trim()),r.push(e),o.push({type:"text",text:r.join(`
|
|
2
2
|
|
|
3
|
-
`)});for(const h of i??[])r.push({type:"resource_link",uri:I(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const c=await this.promptWithTimeout(o,r);this.active=!1,c.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(r){this.active=!1,this.cancelPendingPermissions();const a=r instanceof Error?r.message:String(r),c=r instanceof w&&r.code===-32e3;throw c&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...s?{reasoningEffort:s}:{},...i?{attachments:[...i]}:{},...n!==void 0?{systemPrompt:n}:{}})),this.emitEvent({state:"error",message:a,...c?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),r}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const s=this.pendingPermissions.get(e);if(!s)throw new Error("ACP permission request is no longer pending");if(!s.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(s.timer),s.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=this.configOptions.find(o=>o.category==="model"&&o.type==="select"),t=this.configOptions.find(o=>o.category==="thought_level"&&o.type==="select"),s=this.modes?.availableModes.map(o=>({id:o.id,name:o.name,...o.description?{description:o.description}:{}}))??[],i=o=>(o?.options??[]).flatMap(r=>"options"in r?r.options:[r]),n=(t?i(t):s).map(o=>({id:"value"in o?o.value:o.id,name:o.name,...o.description?{description:o.description}:{}}));return{models:i(e).map(o=>({id:o.value,name:o.name,...o.description?{description:o.description}:{},...o.value===e?.currentValue?{isDefault:!0}:{},...n.length?{supportedReasoningEfforts:n}:{}})),modes:s}}async authenticate(e,t={}){const s=this.requireClient(),i=s.initializeResponse?.authMethods?.find(n=>n.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await s.close(),await q({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(n=>typeof n[1]=="string"))},i,this.workDir)}else await s.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(n){throw E(),n}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const s=[];let i;for(let n=0;n<10&&s.length<500;n+=1){let o=e.cwd;if(o)try{o=g.native(o)}catch{}const r=await t.listSessions(o,i);if(s.push(...r.sessions.slice(0,500-s.length).map(a=>({agentSessionId:a.sessionId,cwd:a.cwd,...a.title?{title:a.title.slice(0,200)}:{},...a.updatedAt?{updatedAt:a.updatedAt}:{}}))),i=r.nextCursor,!i)break}return s}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const s=[];this.importCapture=s;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,y(!0)}catch(i){throw y(!1),i}finally{this.importCapture=null}return s.map((i,n)=>({sourceId:i.sourceHint??m("sha256").update(`${e}\0${n}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const s=e.capabilities;if(s.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(s.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId;return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const s=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of s){if(!i.value)continue;const n=this.configOptions.find(o=>o.category===i.category&&o.type==="select");!n||n.currentValue===i.value||(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:n.id,value:i.value}),n.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of A(e.update,s=>this.makeEvent(s)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,s=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,n=i?this.importCapture.find(o=>o.sourceHint===i):this.importCapture.at(-1);n?.role===s&&n.sourceHint===i?n.payload+=t:this.importCapture.push({role:s,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,s=this.importCapture.find(n=>n.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};s?s.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),s=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=s:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:s})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=p();return new Promise(s=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),s({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(n=>n.optionId)),resolve:s,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(n=>({id:n.optionId,name:n.name,kind:n.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new P(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?S(this.managedAgentPolicy)?b(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?S(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let s;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,n)=>{s=setTimeout(()=>n(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),s.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{s&&clearTimeout(s)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function J(u){v(f(u.id),()=>new x(u))}export{x as AcpAgentAdapter,J as registerAcpAgent};
|
|
3
|
+
`)});for(const h of i??[])o.push({type:"resource_link",uri:v(h.path).href,name:h.name,mimeType:h.mimeType,size:h.byteSize});const u=await this.promptWithTimeout(a,o);this.active=!1,u.stopReason==="cancelled"?this.emitEvent({state:"aborted",agentSessionId:this.agentSessionId??void 0}):this.emitEvent({state:"final",agentSessionId:this.agentSessionId??void 0})}catch(o){this.active=!1,this.cancelPendingPermissions();const r=o instanceof Error?o.message:String(o),u=o instanceof C&&o.code===-32e3;throw u&&(d(this.type,"required"),this.retryingAfterAuth||(this.pendingAuthRetry={text:e,...t?{modelId:t}:{},...n?{reasoningEffort:n}:{},...i?{attachments:[...i]}:{},...s!==void 0?{systemPrompt:s}:{}})),this.emitEvent({state:"error",message:r,...u?{errorCode:"acp_auth_required"}:{},agentSessionId:this.agentSessionId??void 0}),o}}async resume(e){this.requestedSessionId=e,this.agentSessionId=null,await this.ensureSession()}async stop(){this.active&&this.agentSessionId&&this.client&&await this.client.agent.notify(l.methods.agent.session.cancel,{sessionId:this.agentSessionId}),this.cancelPendingPermissions(),this.active=!1,await this.client?.close(),this.client=null,this.startedConfigurationSignature=""}async getStatus(){return{active:this.active,runId:this.active?this.runId:null,canStop:this.active}}async respondToPermission(e,t){const n=this.pendingPermissions.get(e);if(!n)throw new Error("ACP permission request is no longer pending");if(!n.optionIds.has(t))throw new Error("Invalid ACP permission option");this.pendingPermissions.delete(e),clearTimeout(n.timer),n.resolve({outcome:{outcome:"selected",optionId:t}})}getAuthMethods(){return[...this.requireClient().initializeResponse?.authMethods??[]]}hasPendingAuthenticationRetry(){return this.pendingAuthRetry!==null}getSessionOptions(){const e=p(this.configOptions,"model"),t=p(this.configOptions,"thought_level"),n=this.modes?.availableModes.map(s=>({id:s.id,name:s.name,...s.description?{description:s.description}:{}}))??[],i=(t?m(t):n).map(s=>({id:"value"in s?s.value:s.id,name:s.name,...s.description?{description:s.description}:{}}));return{models:m(e).map(s=>({id:s.value,name:s.name,...s.description?{description:s.description}:{},...s.value===e?.currentValue?{isDefault:!0}:{},...i.length?{supportedReasoningEfforts:i}:{}})),modes:n}}async authenticate(e,t={}){const n=this.requireClient(),i=n.initializeResponse?.authMethods?.find(s=>s.id===e);if(!i)throw new Error("ACP authentication method is unavailable");try{if("type"in i&&i.type==="terminal"){if(!t.interactiveTerminal)throw new Error("ACP terminal authentication must be completed on the target machine with `shennian agent auth`");await n.close(),await b({...this.manifest.authLaunch??this.manifest.launch,env:Object.fromEntries(Object.entries({...this.extraEnv,...this.manifest.authLaunch?.env??this.manifest.launch.env}).filter(s=>typeof s[1]=="string"))},i,this.workDir)}else await n.authenticate(e);await this.resumeAfterExternalAuthentication()}catch(s){throw x(),s}}async logout(){await this.requireClient().logout(),d(this.type,"required")}async resumeAfterExternalAuthentication(){await this.client?.close(),this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature,d(this.type,"ready");const e=this.pendingAuthRetry;this.pendingAuthRetry=null,e&&this.retryAfterAuthentication(e)}async listExternalSessions(e={}){const t=this.requireClient();if(!t.capabilities.sessionCapabilities?.list)return[];const n=[];let i;for(let s=0;s<10&&n.length<500;s+=1){let a=e.cwd;if(a)try{a=y.native(a)}catch{}const o=await t.listSessions(a,i);if(n.push(...o.sessions.slice(0,500-n.length).map(r=>({agentSessionId:r.sessionId,cwd:r.cwd,...r.title?{title:r.title.slice(0,200)}:{},...r.updatedAt?{updatedAt:r.updatedAt}:{}}))),i=o.nextCursor,!i)break}return n}async loadExternalSession(e){const t=this.requireClient();if(!t.capabilities.loadSession)throw new Error("ACP session history import is unsupported");this.requestedSessionId=e,this.agentSessionId=e;const n=[];this.importCapture=n;try{const i=await t.agent.request(l.methods.agent.session.load,{sessionId:e,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null,I(!0)}catch(i){throw I(!1),i}finally{this.importCapture=null}return n.map((i,s)=>({sourceId:i.sourceHint??f("sha256").update(`${e}\0${s}\0${i.role}\0${i.payload}`).digest("hex"),role:i.role,payload:i.payload}))}async closeExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.close)throw new Error("ACP session close is unsupported");await this.requireClient().closeSession(e)}async deleteExternalSession(e){if(!this.requireClient().capabilities.sessionCapabilities?.delete)throw new Error("ACP session delete is unsupported");await this.requireClient().deleteSession(e)}async ensureSession(){if(this.agentSessionId)return;const e=this.requireClient();if(this.requestedSessionId){const n=e.capabilities;if(n.sessionCapabilities?.resume){const i=await e.agent.request(l.methods.agent.session.resume,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else if(n.loadSession){this.agentSessionId=this.requestedSessionId;const i=await e.agent.request(l.methods.agent.session.load,{sessionId:this.requestedSessionId,cwd:this.workDir,mcpServers:[]});this.configOptions=i.configOptions??[],this.modes=i.modes??null}else throw new Error(`${this.manifest.name} cannot resume ACP sessions`);this.agentSessionId=this.requestedSessionId,this.emit("sessionOptions");return}const t=await e.agent.request(l.methods.agent.session.new,{cwd:this.workDir,mcpServers:[]});this.agentSessionId=t.sessionId,this.configOptions=t.configOptions??[],this.modes=t.modes??null,this.emit("sessionOptions")}async applyDynamicConfig(e,t){if(!this.agentSessionId)return;t&&this.modes?.availableModes.some(i=>i.id===t)&&(this.modes.currentModeId!==t&&(await this.requireClient().agent.request(l.methods.agent.session.setMode,{sessionId:this.agentSessionId,modeId:t}),this.modes.currentModeId=t),t=void 0);const n=[{category:"model",value:e},{category:"thought_level",value:t}];for(const i of n){if(!i.value)continue;const s=p(this.configOptions,i.category);!s||s.currentValue===i.value||m(s).some(a=>a.value===i.value)&&(await this.requireClient().agent.request(l.methods.agent.session.setConfigOption,{sessionId:this.agentSessionId,configId:s.id,value:i.value}),s.currentValue=i.value)}}handleSessionUpdate(e){if(e.sessionId===this.agentSessionId){if(this.importCapture){this.captureImportedUpdate(e.update);return}if(this.active){if(e.update.sessionUpdate==="tool_call"||e.update.sessionUpdate==="tool_call_update"){const t=JSON.stringify(e.update);if(this.emittedToolStates.get(e.update.toolCallId)===t)return;this.emittedToolStates.set(e.update.toolCallId,t)}for(const t of q(e.update,n=>this.makeEvent(n)))this.emit("agentEvent",t)}}}captureImportedUpdate(e){if(this.importCapture){if(e.sessionUpdate==="user_message_chunk"||e.sessionUpdate==="agent_message_chunk"){const t=e.content.type==="text"?e.content.text:e.content.type==="resource_link"?e.content.name||e.content.uri:`[${e.content.type}]`,n=e.sessionUpdate==="user_message_chunk"?"user":"agent",i=e.messageId?`message:${e.messageId}`:void 0,s=i?this.importCapture.find(a=>a.sourceHint===i):this.importCapture.at(-1);s?.role===n&&s.sourceHint===i?s.payload+=t:this.importCapture.push({role:n,payload:t,...i?{sourceHint:i}:{}});return}if(e.sessionUpdate==="tool_call"){const t=`tool:${e.toolCallId}`,n=this.importCapture.find(s=>s.sourceHint===t),i={role:"agent",sourceHint:t,payload:JSON.stringify({v:1,type:"tool_use",name:e.title,toolCallId:e.toolCallId,status:e.status??"running"})};n?n.payload=i.payload:this.importCapture.push(i);return}if(e.sessionUpdate==="tool_call_update"&&(e.status==="completed"||e.status==="failed")){const t=this.importCapture.find(i=>i.sourceHint===`tool:${e.toolCallId}`),n=JSON.stringify({v:1,type:"tool_result",name:e.title??"tool",toolCallId:e.toolCallId,status:e.status});t?t.payload=n:this.importCapture.push({role:"agent",sourceHint:`tool:${e.toolCallId}`,payload:n})}}}handlePermission(e){if(!this.active||e.sessionId!==this.agentSessionId)return Promise.resolve({outcome:{outcome:"cancelled"}});const t=g();return new Promise(n=>{const i=setTimeout(()=>{this.pendingPermissions.delete(t),n({outcome:{outcome:"cancelled"}})},this.options.permissionTimeoutMs??3e5);i.unref?.(),this.pendingPermissions.set(t,{optionIds:new Set(e.options.map(s=>s.optionId)),resolve:n,timer:i}),this.emitEvent({state:"approval-pending",runPhase:"waiting_approval",approval:{title:e.toolCall.title??void 0,source:this.manifest.name},permission:{id:t,sessionId:this.shennianSessionId,agentSessionId:this.agentSessionId??void 0,runId:this.runId,toolCallId:e.toolCall.toolCallId,options:e.options.map(s=>({id:s.optionId,name:s.name,kind:s.kind}))}})})}requireClient(){if(!this.client)throw new Error("ACP adapter has not started");return this.client}createProcessClient(){return new E(this.manifest.launch,{onSessionUpdate:e=>this.handleSessionUpdate(e),onPermission:e=>this.handlePermission(e)},this.buildEnvironment(),{...this.buildClientCapabilities(),terminalAuth:!0})}async refreshProcessConfiguration(){if(!this.client||this.startedConfigurationSignature===this.configurationSignature)return;const e=this.agentSessionId??this.requestedSessionId;await this.client.close(),this.requestedSessionId=e,this.agentSessionId=null,this.configOptions=[],this.modes=null,this.client=this.createProcessClient(),await this.client.start(this.workDir),this.startedConfigurationSignature=this.configurationSignature}buildEnvironment(){return this.managedAgentPolicy?w(this.managedAgentPolicy)?O(this.extraEnv):{...this.extraEnv}:{...process.env,...this.extraEnv}}buildClientCapabilities(){const e=this.manifest.clientCapabilities??{},t=this.managedAgentPolicy?.adapterPolicy;return t?w(this.managedAgentPolicy)?{...e,terminal:!0,terminalPolicy:"managed-room-only"}:{readTextFile:!!e.readTextFile,writeTextFile:!!(e.writeTextFile&&t.fileAccess!=="workspace-read"),terminal:!0,terminalPolicy:"managed-room-only"}:e}async retryAfterAuthentication(e){this.retryingAfterAuth=!0;try{await this.send(e.text,e.modelId,e.reasoningEffort,e.attachments,e.systemPrompt)}catch{}finally{this.retryingAfterAuth=!1}}async promptWithTimeout(e,t){let n;try{return await Promise.race([e.agent.request(l.methods.agent.session.prompt,{sessionId:this.agentSessionId,prompt:t}),new Promise((i,s)=>{n=setTimeout(()=>s(new Error("ACP prompt timed out")),this.options.promptTimeoutMs??720*6e4),n.unref?.()})])}catch(i){throw i instanceof Error&&i.message==="ACP prompt timed out"&&(await e.close(),this.client===e&&(this.client=null)),i}finally{n&&clearTimeout(n)}}cancelPendingPermissions(){for(const e of this.pendingPermissions.values())clearTimeout(e.timer),e.resolve({outcome:{outcome:"cancelled"}});this.pendingPermissions.clear()}makeEvent(e){return{...e,runId:this.runId,seq:this.seq++}}emitEvent(e){this.emit("agentEvent",this.makeEvent(e))}}function L(c){P(S(c.id),()=>new T(c))}export{T as AcpAgentAdapter,L as registerAcpAgent};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import c from"node:fs";import o from"node:path";import{randomUUID as w}from"node:crypto";import{spawn as f}from"node:child_process";import{terminateProcessTree as u}from"
|
|
1
|
+
import c from"node:fs";import o from"node:path";import{randomUUID as w}from"node:crypto";import{spawn as f}from"node:child_process";import{terminateProcessTree as u}from"../process-tree.js";import{resolveBuiltinCommand as b}from"../command-spec.js";class A{enabled;root;environment;terminals=new Map;constructor(t,e,n=process.env){this.enabled=e,this.root=c.realpathSync(t),this.environment={...n}}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 n=(await c.promises.readFile(await this.resolve(t.path,!1),"utf8")).split(`
|
|
2
2
|
`),r=Math.max(0,(t.line??1)-1),a=Math.min(Math.max(0,t.limit??n.length),1e5);return{content:n.slice(r,r+a).join(`
|
|
3
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),n=this.resolveTerminalInvocation(t.command,t.args??[]),r=f(n.command,n.args,{cwd:e,env:this.enabled.terminalPolicy==="managed-room-only"?{...this.environment}:{...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",(l,p)=>{const h={exitCode:l,signal:p};i.exitStatus=h,s(h)}))},m=s=>{if(i.output=Buffer.concat([i.output,s]),i.output.byteLength>i.limit){let l=i.output.byteLength-i.limit;for(;l<i.output.byteLength&&(i.output[l]&192)===128;)l+=1;i.output=i.output.subarray(l),i.truncated=!0}};r.stdout.on("data",m),r.stderr.on("data",m);const d=w();return this.terminals.set(d,i),{terminalId:d}}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){u(this.requireTerminal(t.terminalId).child)}releaseTerminal(t){const e=this.requireTerminal(t.terminalId);e.exitStatus||u(e.child),this.terminals.delete(t.terminalId)}close(){for(const t of this.terminals.values())t.exitStatus||u(t.child);this.terminals.clear()}requireTerminal(t){const e=this.terminals.get(t);if(!e)throw new Error("Unknown ACP terminal");return e}resolveTerminalInvocation(t,e){if(this.enabled.terminalPolicy!=="managed-room-only")return{command:t,args:e};const n=e[1],r=n!=="attachment"||e[2]==="get";if(o.basename(t).replace(/\.(?:cmd|exe)$/i,"")!=="shennian"||e[0]!=="room"||!["status","read","send","attachment","pause","schedule"].includes(n??"")||!r)throw new Error("ACP managed terminal only permits Shennian Room commands");const a=b("pi");if(!a)throw new Error("Shennian CLI is unavailable for ACP managed Room tools");return{command:a.command,args:[...a.args,...e]}}async resolve(t,e){if(!o.isAbsolute(t))throw new Error("ACP path must be absolute");const n=o.resolve(t),r=e?o.dirname(n):n,a=await c.promises.realpath(r),i=e?o.join(a,o.basename(n)):a,m=o.relative(this.root,i);if(m.startsWith("..")||o.isAbsolute(m))throw new Error("ACP path is outside the session workspace");return i}}export{A as AcpClientServices};
|
|
@@ -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"
|
|
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 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import s from"node:fs";import m from"node:os";import i from"node:path";import{readLatestUserEnv as E}from"../agent-env.js";import{loadConfig as S,resolveShennianPath as g}from"../config/index.js";const c=g("agent-provider-config.json"),U=4;function A(e){return e==="codex"||e==="claude"||e==="pi"}const O={codex:{baseUrl:["OPENAI_BASE_URL","OPENAI_API_BASE","OPENAI_API_URL"],token:["OPENAI_API_KEY","OPENAI_TOKEN"]},claude:{baseUrl:["ANTHROPIC_BASE_URL","ANTHROPIC_API_URL"],token:["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN"]},pi:{baseUrl:["DASHSCOPE_BASE_URL","DASHSCOPE_API_BASE","DASHSCOPE_API_URL"],token:["DASHSCOPE_API_KEY","DASHSCOPE_TOKEN"]}};function k(e){return u().configs[e]}function v(e){const n=u(),o=n.configs[e.agent],t={agent:e.agent,baseUrl:e.baseUrl?.trim()||o?.baseUrl,token:e.token?.trim()||o?.token,updatedAt:new Date().toISOString()};return n.configs[e.agent]=t,_(n),t}function B(e){const n=u();delete n.configs[e],_(n)}function K(e){if(!A(e))return{};const n=k(e);return n?l(e==="codex"?{OPENAI_BASE_URL:n.baseUrl,OPENAI_API_KEY:n.token}:e==="claude"?{ANTHROPIC_BASE_URL:n.baseUrl,ANTHROPIC_API_KEY:n.token}:{DASHSCOPE_BASE_URL:n.baseUrl,DASHSCOPE_API_KEY:n.token}):{}}function j(e,n=E()){if(e==="pi-coding-agent"||!A(e))return;const o=k(e);if(o?.token||o?.baseUrl)return a({agent:e,source:"shennian",status:o.token?"managed":"missing",baseUrl:o.baseUrl,token:o.token,tokenPresent:!!o.token});const t=I(e,n);if(t.tokenPresent||t.baseUrl)return a({agent:e,source:"env",status:t.tokenPresent?"detected":"missing",baseUrl:t.baseUrl,token:t.token,tokenPresent:t.tokenPresent});const r=p(e);return r.tokenPresent||r.baseUrl?a({agent:e,source:"config-file",status:r.tokenPresent?"detected":"missing",baseUrl:r.baseUrl,token:r.token,tokenPresent:r.tokenPresent}):a({agent:e,source:"unknown",status:"missing",tokenPresent:!1})}function u(){try{return{configs:JSON.parse(s.readFileSync(c,"utf-8")).configs??{}}}catch{return{configs:{}}}}function _(e){s.mkdirSync(i.dirname(c),{recursive:!0}),s.writeFileSync(c,JSON.stringify(e,null,2),{mode:384});try{s.chmodSync(c,384)}catch{}}function l(e){const n={};for(const[o,t]of Object.entries(e))t&&(n[o]=t);return n}function I(e,n){const o=O[e],t=P(n,o.baseUrl),r=P(n,o.token);return{baseUrl:t,token:r,tokenPresent:!!r}}function P(e,n){for(const o of n){const t=e[o]?.trim();if(t)return t}}function p(e){const n=m.homedir();if(e==="pi"){const r=S().apiKeys?.dashscope?.trim();if(r)return{token:r,tokenPresent:!0}}const o=e==="codex"?[i.join(n,".codex","config.toml"),i.join(n,".codex","auth.json")]:e==="claude"?[i.join(n,".claude","settings.json"),i.join(n,".claude.json")]:[i.join(n,".dashscope","config.json")];for(const t of o){const r=C(t);if(!r)continue;const f=N(r,e),d=b(r);if(f||d)return{token:f,baseUrl:d,tokenPresent:!!f}}return{tokenPresent:!1}}function C(e){try{const n=s.statSync(e);return!n.isFile()||n.size>1024*1024?null:s.readFileSync(e,"utf-8")}catch{return null}}function b(e){return e.match(/(?:base_url|baseURL|api_url|apiUrl|ANTHROPIC_BASE_URL|OPENAI_BASE_URL|DASHSCOPE_BASE_URL)["'\s:=]+([^"'\s,}]+)/i)?.[1]?.trim()}function N(e,n){const o=n==="claude"?"sk-ant-":"sk-",t=e.match(new RegExp(`${o.replace(/-/g,"\\-")}[A-Za-z0-9_\\-]{8,}`));return t?.[0]?t[0]:e.match(/(?:api[_-]?key|auth[_-]?token|token|dashscope)["'\s:=]+([A-Za-z0-9_\-.]{12,})/i)?.[1]?.trim()}function a(e){return{status:e.status,source:e.source,tokenPresent:e.tokenPresent,...e.baseUrl?{baseUrlHost:R(e.baseUrl)}:{},...e.token?{tokenHint:h(e.token)}:{},updatedAt:new Date().toISOString()}}function h(e){const n=e.trim();return n?`\u2022\u2022\u2022\u2022${n.slice(-U)}`:""}function R(e){try{return new URL(e).host||e}catch{return e.replace(/^https?:\/\//i,"").replace(/\/.*$/,"")||e}}export{K as buildManagedAgentEnv,B as deleteManagedAgentProviderConfig,j as getAgentConfigSummary,k as getManagedAgentProviderConfig,h as maskToken,v as upsertManagedAgentProviderConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"node:fs";import s from"node:path";import{CACHE_TTL_MS as a,CACHE_VERSION as i,MODEL_CACHE_PATH as n}from"./types.js";function f(){e.mkdirSync(s.dirname(n),{recursive:!0})}function h(){try{const r=JSON.parse(e.readFileSync(n,"utf-8"));if(r.version===i&&r.agents&&typeof r.agents=="object")return r}catch{}return{version:i,agents:{}}}function m(r){try{f(),e.writeFileSync(n,JSON.stringify(r,null,2))}catch{}}function l(r,o,t){if(!r||r.version!==o||t&&r.sourceRevision!==t)return!1;const c=t?.startsWith("opencode-connected-")||t?.startsWith("pi-configured-")?900*1e3:a;return Date.now()-r.refreshedAt<c}export{l as isCacheFresh,h as readCache,m as writeCache};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createInterface as
|
|
2
|
-
`,
|
|
3
|
-
${
|
|
1
|
+
import{createInterface as _}from"node:readline";import{resolveBuiltinCommand as l,spawnResolvedCommand as w}from"../command-spec.js";import{fallbackClaudeAliasModels as E,discoverClaudeAliasModelsFromEnv as k,fallbackCodexModels as h,fallbackWorkBuddyModels as x,fallbackGeminiModels as R,parseCodexAppServerModels as O,parseCursorModels as A,parseOpenCodeModels as I}from"./parsers.js";import{runResolvedCommand as f}from"./runner.js";import{DISCOVERY_WORKDIR as M,ModelDiscoveryFallbackError as b}from"./types.js";import{buildAgentProcessEnv as C,readLatestUserEnv as P}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as S}from"../codex-utils.js";import{PiRpcClient as T}from"../pi-rpc-client.js";import{discoverOpenCodeModelsViaApi as $}from"./opencode-api.js";function D(r){const e=r instanceof Error?r.message:"";return/timed out/i.test(e)?"app_server_timeout":/\berror\b|invalid|unsupported|unknown (?:method|field)/i.test(e)?"app_server_rpc_error":"app_server_unavailable"}function m(r,e,t,n,s,i){return r.stdin?new Promise((o,a)=>{const p=setTimeout(()=>{e.delete(t),a(new Error(`codex app-server request timed out: ${n}`))},i);e.set(t,{resolve:o,reject:a,timer:p}),r.stdin.write(`${JSON.stringify({id:t,method:n,params:s})}
|
|
2
|
+
`,c=>{c&&(clearTimeout(p),e.delete(t),a(c))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function L(r){const e=w(r,["app-server","--listen","stdio://"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new Map;let n=1;_({input:e.stdout}).on("line",i=>{if(!i.trim())return;let o;try{o=JSON.parse(i)}catch{return}if(o.id==null)return;const a=t.get(o.id);a&&(clearTimeout(a.timer),t.delete(o.id),o.error?a.reject(new Error(o.error.message||`codex app-server error ${o.error.code??""}`.trim())):a.resolve(o.result))});try{await m(e,t,n++,"initialize",{clientInfo:S,capabilities:{experimentalApi:!0}},1e4);const[i,o]=await Promise.all([m(e,t,n++,"model/list",{},15e3),m(e,t,n++,"config/read",{},15e3).catch(()=>null)]),a=typeof o=="object"&&o!==null&&"config"in o?o.config:void 0;return O({...typeof i=="object"&&i!==null?i:{},config:a})}finally{for(const[i,o]of t)clearTimeout(o.timer),o.reject(new Error("codex app-server stopped")),t.delete(i);e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function q(){const r=l("cursor");if(!r)return[];const e=await f(r,["--list-models"]);return A(e.stdout)}async function j(){const r=l("opencode");if(!r)return[];const e=await $().catch(()=>[]);if(e.length>0)return e;const t=await f(r,["models"]);return I(t.stdout)}async function G(){const r=l("pi-coding-agent");if(!r)return[];const e=w(r,["--mode","rpc","--no-session","--offline","--no-extensions","--no-skills","--no-prompt-templates","--no-context-files","--no-tools"],{cwd:M,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new T(e,{requestTimeoutMs:1e4});try{const[n,s]=await Promise.all([t.request("get_available_models"),t.request("get_state")]),i=n.data&&typeof n.data=="object"?n.data:{},o=s.data&&typeof s.data=="object"?s.data:{},a=typeof o.model?.id=="string"&&typeof o.model.provider=="string"?`${o.model.provider}/${o.model.id}`:null;return Array.isArray(i.models)?i.models.flatMap(c=>{if(!c||typeof c!="object")return[];const d=c;if(typeof d.id!="string"||typeof d.provider!="string")return[];const v=`${d.provider}/${d.id}`,y=d.reasoning===!0?["off","minimal","low","medium","high","xhigh","max"].map(g=>({id:g,name:g})):void 0;return[{id:v,name:typeof d.name=="string"&&d.name.trim()?d.name:d.id,provider:d.provider,isDefault:v===a,...y?{supportedReasoningEfforts:y,defaultReasoningEffort:"medium"}:{}}]}):[]}catch{return[]}finally{t.close(),e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function N(){const r=l("claude");if(!r)return[];const e=P(),t=k(e);if(t.length>0)return t;const n=E(e),s=await f(r,["--help"],3e3).catch(()=>null);return!s||/\bfable\b/i.test(`${s.stdout}
|
|
3
|
+
${s.stderr}`)?n:n.filter(i=>i.id!=="fable")}async function F(){const r=l("codex");if(!r)return[];let e;try{e=await L(r)}catch(t){throw new b("codex",D(t),h())}if(e.length===0)throw new b("codex","empty_model_list",h());return e}async function B(){return l("gemini")?R():[]}const u=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0}],V=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function W(r){if(!r.serverUrl||!r.authToken)return u;try{const e=await fetch(`${r.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${r.authToken}`}});if(!e.ok)return u;const t=await e.json(),n=(t.models??[]).map(s=>({id:s.id,name:s.name?.trim()||s.id,provider:s.provider,isDefault:s.id===t.default}));return n.length>0?n:u}catch{return u}}async function K(r,e){switch(r){case"claude":return N();case"codex":return F();case"workbuddy":return l("workbuddy")?x():[];case"gemini":return B();case"cursor":return q();case"openclaw":return[];case"opencode":return j();case"pi":return W(e);case"pi-coding-agent":return G();case"manager":return V}}async function re(r,e){return r.type.startsWith("custom:")?r.models??[]:r.type.startsWith("acp:")?[]:K(r.type,e)}export{re as discoverModelsForAgent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomBytes as m}from"node:crypto";import{createServer as
|
|
1
|
+
import{randomBytes as m}from"node:crypto";import{createServer as f}from"node:net";import{resolveBuiltinCommand as u,spawnResolvedCommand as w}from"../command-spec.js";import{DETACH_PROCESS_GROUP as v,stopProcessTree as h}from"../process-tree.js";import{buildAgentProcessEnv as O}from"../../agent-env.js";import{DISCOVERY_WORKDIR as g}from"./types.js";import{parseOpenCodeProviderModels as C}from"./parsers.js";async function P(){return new Promise((s,r)=>{const e=f();e.once("error",r),e.listen(0,"127.0.0.1",()=>{const o=e.address(),t=o&&typeof o!="string"?o.port:0;e.close(()=>t?s(t):r(new Error("OpenCode discovery port unavailable")))})})}async function b(){const s=u("opencode");if(!s)return[];const r=await P(),e=m(24).toString("hex"),o=w(s,["serve","--hostname","127.0.0.1","--port",String(r)],{cwd:g,stdio:["ignore","pipe","pipe"],env:O({NO_COLOR:"1",OPENCODE_SERVER_PASSWORD:e}),detached:v});o.stdout?.resume(),o.stderr?.resume();const t=`Basic ${Buffer.from(`opencode:${e}`).toString("base64")}`,a=`http://127.0.0.1:${r}`;let i=!1;o.once("close",()=>{i=!0}),o.once("error",()=>{i=!0});try{const p=Date.now()+1e4;for(;Date.now()<p&&!i;){try{const n=new AbortController,l=setTimeout(()=>n.abort(),2e3);try{const[c,d]=await Promise.all([fetch(`${a}/provider`,{headers:{Authorization:t},signal:n.signal}),fetch(`${a}/config`,{headers:{Authorization:t},signal:n.signal})]);if(c.ok&&d.ok)return C(await c.json(),await d.json())}finally{clearTimeout(l)}}catch{}await new Promise(n=>setTimeout(n,200))}return[]}finally{await h(o,1e3)}}export{b as discoverOpenCodeModelsViaApi};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAgentConfigSummary as
|
|
1
|
+
import{getAgentConfigSummary as v}from"../config-status.js";import{isCacheFresh as b,readCache as f,writeCache as g}from"./cache.js";import{discoverModelsForAgent as x}from"./discovery.js";import{ModelDiscoveryFallbackError as F}from"./types.js";import{getAgentRuntimeSummary as A}from"../runtime-compatibility.js";import{isRestrictedRoomChatUnsupported as E,resolveManagedAgentRuntimeProtection as w}from"../../security/managed-agent-runtime.js";const C={claude:"claude-alias-v2",codex:"codex-app-server-v2",opencode:"opencode-connected-v1","pi-coding-agent":"pi-configured-v1"};function O(t,s,e){console.warn(`[model-discovery] agent=${t} source=fallback reason=${s} usedCache=${e}`)}function R(t){const s=new Set,e=[];for(const n of t)!n.id||s.has(n.id)||(s.add(n.id),e.push(n));return e}function S(t){const s=t.type!=="manager"&&t.type!=="pi"&&t.type!=="openclaw",e=s,n=e&&!t.type.startsWith("acp:"),r=e?w({agentType:t.type,runtimeVersion:t.version,platform:t.runtimePlatform,isWsl:t.runtimeIsWsl,executableFingerprint:t.executableFingerprint,requireExecutableFingerprint:!0}):null,c=n&&!E(t.type)&&(r?.level==="hard"||r?.level==="partial"),o=e,i=e,p=[...o?["native-full"]:[],...c?["restricted"]:[]],l=i,a=s;return{supportsStandardSession:s,supportsAgent:i,supportedAgentExecutionModes:p,supportsManagedAgent:c,supportsManagedNativeFull:o,supportsRoomTools:l,supportsWorker:a,supportsManagerMode:l&&a,supportsExternalWorkerTarget:a,...r?{managedAgentProtection:r}:{}}}function M(t,s){return t.type==="opencode"&&(!t.authState||t.authState==="unknown")&&s.length>0?{authState:"ready"}:t.authState?{authState:t.authState}:{}}function P(t,s){if(!t.startsWith("acp:"))return!1;const e=R(s);if(e.length===0)return!1;const n=f(),r=n.agents[t];return JSON.stringify(r?.models)===JSON.stringify(e)?!1:(n.agents[t]={refreshedAt:Date.now(),models:e},g(n),!0)}function V(t){const s=f();return t.map(e=>{const n=s.agents[e.type],r=C[e.type],c=n&&(!r||n.sourceRevision===r)?n.models:e.models??[],o=v(e.type),i=A(e);return{type:e.type,models:c,...e.integration?{integration:e.integration}:{},...e.display?{display:e.display}:{},...e.acpCapabilities?{acpCapabilities:e.acpCapabilities}:{},...M(e,c),...e.acpAuthMethods?{acpAuthMethods:e.acpAuthMethods}:{},...e.catalogRevision?{catalogRevision:e.catalogRevision}:{},...S(e),...o?{config:o}:{},...i?{runtime:i}:{}}})}async function _(t,s){return k(t,s,{forceRefresh:!0})}async function k(t,s,e={}){const n=f();let r=!1;const c=[];for(const o of t){const i=n.agents[o.type],p=C[o.type],l=i&&(!p||i.sourceRevision===p)?i:void 0;let a;if(!e.forceRefresh&&b(i,o.version,p))a=i.models;else{let d=null;try{d=R(await x(o,s)),a=d.length>0?d:l?.models??o.models??[]}catch(u){if(u instanceof F){const y=!!l?.models.length;a=y?l.models:u.fallbackModels,O(o.type,u.failureCode,y)}else a=l?.models??o.models??[]}if(d&&d.length>0){const u={version:o.version,...p?{sourceRevision:p}:{},refreshedAt:Date.now(),models:a};JSON.stringify(i)!==JSON.stringify(u)&&(n.agents[o.type]=u,r=!0)}}const h=v(o.type),m=A(o);c.push({type:o.type,models:a,...o.integration?{integration:o.integration}:{},...o.display?{display:o.display}:{},...o.acpCapabilities?{acpCapabilities:o.acpCapabilities}:{},...M(o,a),...o.acpAuthMethods?{acpAuthMethods:o.acpAuthMethods}:{},...o.catalogRevision?{catalogRevision:o.catalogRevision}:{},...S(o),...h?{config:h}:{},...m?{runtime:m}:{}})}return r&&g(n),c}export{V as getCachedAgentInfos,P as recordAcpAgentModels,_ as refreshAgentInfos,k as resolveAgentInfos};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCachedAgentInfos as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as
|
|
1
|
+
import{getCachedAgentInfos as g,recordAcpAgentModels as m,refreshAgentInfos as u,resolveAgentInfos as v}from"./model-registry/service.js";import{applyClaudeModelEnvOverrides as e,discoverClaudeAliasModelsFromEnv as s,fallbackCodexModels as o,fallbackClaudeAliasModels as r,parseClaudeBinaryModels as l,parseClaudeModels as d,parseCodexModels as a,parseCodexAppServerModels as p,parseCursorModels as n,parseGeminiModels as t,parseOpenClawModels as i,stripAnsi as M}from"./model-registry/parsers.js";const A={applyClaudeModelEnvOverrides:e,discoverClaudeAliasModelsFromEnv:s,fallbackCodexModels:o,fallbackClaudeAliasModels:r,parseClaudeBinaryModels:l,parseClaudeModels:d,parseCodexModels:a,parseCodexAppServerModels:p,parseCursorModels:n,parseOpenClawModels:i,parseGeminiModels:t,stripAnsi:M};export{g as getCachedAgentInfos,A as modelSwitchingTestExports,m as recordAcpAgentModels,u as refreshAgentInfos,v as resolveAgentInfos};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createInterface as g}from"node:readline";import{randomUUID as
|
|
1
|
+
import{createInterface as g}from"node:readline";import{randomUUID as u}from"node:crypto";import{AgentAdapter as f,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as m,spawnAgentCommand as E}from"./command-spec.js";import{spawnEnoentError as C}from"./spawn-errors.js";import{DETACH_PROCESS_GROUP as y,stopProcessTree as O}from"./process-tree.js";import{buildAgentProcessEnv as D,buildManagedAgentProcessEnv as I,buildManagedNativeFullProcessEnv as S}from"../agent-env.js";import{buildInlineChannelPreamble as P}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as _,isManagedAgentNativeFull as w}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as A}from"../security/managed-agent-runtime.js";import{compileOpenCodeManagedPermissions as v,createOpenCodeManagedConfigDirectory as N,disposeOpenCodeManagedConfigDirectory as x,OPENCODE_MANAGED_RUNTIME_SECURITY as k}from"./opencode-managed-permissions.js";A("opencode",k);const T=64*1024;function R(n){if(!n)return;const e=n.input,t=n.output;if(!(typeof e!="number"&&typeof t!="number"))return{inputTokens:typeof e=="number"?e:0,outputTokens:typeof t=="number"?t:0}}function l(n){if(n==null)return"";if(typeof n=="string")return n;try{return JSON.stringify(n)}catch{return String(n)}}function p(n){if(!n)return"opencode request failed";if(typeof n=="string")return n;if(typeof n!="object")return String(n);const e=n;return typeof e.message=="string"?e.message:typeof e.name=="string"?e.name:"data"in e?p(e.data):l(n)||"opencode request failed"}class M extends f{type="opencode";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;agentSessionId=null;workDir=null;seq=0;runId="";terminalState="closed";runUsage;externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;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,o){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,o&&(this.agentSessionId=o),this.resetRunState()}async send(e,t,o,i,s,c){if(c?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=u(),this.resetRunState();const a=["run","--format","json","--dir",this.workDir??process.cwd()];this.agentSessionId&&a.push("--session",this.agentSessionId),t&&a.push("--model",t);const r=`${P(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,s)}${e}`;await this.spawnAndParse(a,r)}async resume(e){await this.killProcess(),this.agentSessionId=e,this.runId=u(),this.resetRunState(),this.emitEvent({state:"start",agentSessionId:e}),this.emitFinalIfOpen({state:"final",agentSessionId:e})}async stop(){await this.killProcess()}resetRunState(){this.seq=0,this.terminalState="open",this.runUsage=void 0}async spawnAndParse(e,t){const o=m("opencode");if(!o){this.emit("error",new Error('Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".'));return}const i=await this.prepareManagedLaunch();let s;try{s=E(o,[e[0],...i.args,...e.slice(1)],{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:i.env,detached:y})}catch(r){throw await this.disposeManagedConfig(i.configDir),r}this.process=s,this.managedConfigDir=i.configDir,g({input:s.stdout}).on("line",r=>{this.handleProcessLine(s,r)});let a=Buffer.alloc(0);s.stderr?.on("data",r=>{const d=T-a.byteLength;d>0&&(a=Buffer.concat([a,r.subarray(0,d)]))}),s.on("close",(r,d)=>{this.process===s&&(this.disposeManagedConfig(i.configDir),this.terminalState==="open"&&this.completeRunAfterProcessExit(r,d,a.toString("utf8").trim()))}),s.on("error",r=>{this.process===s&&(this.process=null,this.disposeManagedConfig(i.configDir),r.code==="ENOENT"?this.emit("error",C(this.workDir,'Command "opencode" not found. Install it with "npm i -g opencode-ai@latest".')):this.emit("error",r))}),s.stdin.on("error",r=>{this.process===s&&this.emitErrorIfOpen({state:"error",message:r.message})}),s.stdin.end(t)}async prepareManagedLaunch(){const e=this.managedAgentPolicy;if(!e)return{args:["--auto"],env:D({NO_COLOR:"1",...this.extraEnv}),configDir:null};if(w(e))return{args:["--auto"],env:S({NO_COLOR:"1",...this.extraEnv}),configDir:null};const t=v(_(e),e.adapterPolicy.workDir),o=await N(t),i=I({agentType:"opencode",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return i.OPENCODE_CONFIG=o.configPath,i.OPENCODE_CONFIG_DIR=o.directory,i.OPENCODE_CONFIG_CONTENT=JSON.stringify(t.config),i.OPENCODE_DISABLE_PROJECT_CONFIG="true",i.OPENCODE_DISABLE_CLAUDE_CODE="1",i.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT="1",i.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS="1",{args:t.args,env:i,configDir:o.directory}}async disposeManagedConfig(e){e&&(this.managedConfigDir===e&&(this.managedConfigDir=null),await x(e).catch(()=>{}))}handleStreamEvent(e){e.sessionID&&e.sessionID!==this.agentSessionId&&(this.agentSessionId=e.sessionID,this.emitEvent({state:"start",agentSessionId:e.sessionID}));const t=e.part;if(e.type==="text"&&t?.text){this.emitEvent({state:"delta",text:t.text});return}if(e.type==="reasoning"&&t?.text){this.emitEvent({state:"delta",text:t.text,thinking:!0});return}if(e.type==="tool_use"&&t?.type==="tool"){t.state?.status==="completed"||t.state?.status==="error"?this.emitEvent({state:"tool-result",name:t.tool??"tool",result:t.state.status==="error"?t.state.error??"tool failed":l(t.state?.output)}):this.emitEvent({state:"tool-call",name:t.tool??"tool",args:t.state?.input??{}});return}if(e.type==="error"){this.emitErrorIfOpen({state:"error",message:p(e.error)});return}e.type==="step_finish"&&this.recordStepUsage(R(t?.tokens))}handleProcessLine(e,t){if(!(this.process!==e||!t.trim()))try{this.handleStreamEvent(JSON.parse(t))}catch{this.emitEvent({state:"delta",text:t})}}recordStepUsage(e){e&&(this.runUsage={inputTokens:(this.runUsage?.inputTokens??0)+e.inputTokens,outputTokens:(this.runUsage?.outputTokens??0)+e.outputTokens})}completeRunAfterProcessExit(e=0,t=null,o=""){if(e!==0||t!==null){this.emitErrorIfOpen({state:"error",message:o||(t?`opencode exited with signal ${t}`:`opencode exited with code ${String(e)}`)});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:this.runUsage})}emitEvent(e){const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}emitFinalIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="closed",this.emitEvent(e))}async killProcess(){const e=this.process;if(!e){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,await O(e),await this.disposeManagedConfig(this.managedConfigDir)}}h("opencode",()=>new M);export{M as OpenCodeAdapter};
|