shennian 0.2.88 → 0.2.90
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/assets/wechat-channel/macos/manifest.json +22 -0
- package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +548 -0
- package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
- package/dist/src/agent-env.js +4 -105
- package/dist/src/agents/adapter.d.ts +6 -0
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude.js +8 -305
- package/dist/src/agents/codex-control.d.ts +35 -0
- package/dist/src/agents/codex-control.js +2 -0
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.d.ts +8 -0
- package/dist/src/agents/codex.js +15 -863
- package/dist/src/agents/command-spec.js +2 -413
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor.js +1 -249
- package/dist/src/agents/custom.js +4 -271
- package/dist/src/agents/detect.js +1 -56
- package/dist/src/agents/external-channel-instructions.js +10 -94
- package/dist/src/agents/gemini.js +1 -173
- package/dist/src/agents/manager.js +13 -157
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -187
- package/dist/src/agents/model-registry/parsers.js +4 -447
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -78
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -18
- package/dist/src/agents/openclaw.js +2 -275
- package/dist/src/agents/opencode.js +1 -231
- package/dist/src/agents/pi-context.js +12 -217
- package/dist/src/agents/pi.js +14 -723
- package/dist/src/agents/platform-instructions.js +9 -54
- package/dist/src/channels/base.d.ts +4 -1
- package/dist/src/channels/base.js +1 -3
- package/dist/src/channels/registry.js +1 -30
- package/dist/src/channels/reply-split.js +10 -89
- package/dist/src/channels/runtime.d.ts +1 -0
- package/dist/src/channels/runtime.js +5 -533
- package/dist/src/channels/secret-registry.d.ts +1 -0
- package/dist/src/channels/secret-registry.js +1 -46
- package/dist/src/channels/websocket.js +8 -378
- package/dist/src/channels/wechat-channel/anchor.d.ts +10 -0
- package/dist/src/channels/wechat-channel/anchor.js +1 -0
- package/dist/src/channels/wechat-channel/client.d.ts +74 -0
- package/dist/src/channels/wechat-channel/client.js +1 -0
- package/dist/src/channels/wechat-channel/cooldown.d.ts +15 -0
- package/dist/src/channels/wechat-channel/cooldown.js +1 -0
- package/dist/src/channels/wechat-channel/fingerprint.d.ts +28 -0
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -0
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +37 -0
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -0
- package/dist/src/channels/wechat-channel/helper-client.d.ts +25 -0
- package/dist/src/channels/wechat-channel/helper-client.js +3 -0
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +84 -0
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -0
- package/dist/src/channels/wechat-channel/index.d.ts +17 -0
- package/dist/src/channels/wechat-channel/index.js +1 -0
- package/dist/src/channels/wechat-channel/ledger.d.ts +33 -0
- package/dist/src/channels/wechat-channel/ledger.js +1 -0
- package/dist/src/channels/wechat-channel/media-resolver.d.ts +32 -0
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -0
- package/dist/src/channels/wechat-channel/message-key.d.ts +19 -0
- package/dist/src/channels/wechat-channel/message-key.js +1 -0
- package/dist/src/channels/wechat-channel/observer.d.ts +64 -0
- package/dist/src/channels/wechat-channel/observer.js +1 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +69 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -0
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
- package/dist/src/channels/wechat-channel/preflight.d.ts +37 -0
- package/dist/src/channels/wechat-channel/preflight.js +1 -0
- package/dist/src/channels/wechat-channel/runner.d.ts +34 -0
- package/dist/src/channels/wechat-channel/runner.js +1 -0
- package/dist/src/channels/wechat-channel/runtime.d.ts +45 -0
- package/dist/src/channels/wechat-channel/runtime.js +1 -0
- package/dist/src/channels/wechat-channel/scheduler.d.ts +35 -0
- package/dist/src/channels/wechat-channel/scheduler.js +1 -0
- package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
- package/dist/src/channels/wechat-rpa/macos.js +6 -48
- package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
- package/dist/src/channels/wechat-rpa.d.ts +21 -0
- package/dist/src/channels/wechat-rpa.js +6 -1022
- package/dist/src/channels/wecom.js +4 -357
- package/dist/src/commands/agent.js +6 -131
- package/dist/src/commands/daemon-windows.js +8 -48
- package/dist/src/commands/daemon.js +19 -1013
- package/dist/src/commands/external-attachments.js +1 -51
- package/dist/src/commands/external.js +1 -137
- package/dist/src/commands/manager.js +2 -389
- package/dist/src/commands/pair-qr.js +1 -6
- package/dist/src/commands/pair.js +9 -287
- package/dist/src/commands/tools.js +1 -34
- package/dist/src/commands/upgrade.js +1 -198
- package/dist/src/config/index.js +1 -35
- package/dist/src/daemon-log.js +6 -58
- package/dist/src/env-path.js +1 -64
- package/dist/src/fs/boundary.js +1 -126
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.d.ts +10 -0
- package/dist/src/fs/text-decoder.js +1 -0
- package/dist/src/index.js +2 -404
- package/dist/src/log-reporter.js +1 -16
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +2 -269
- package/dist/src/manager/runtime.js +19 -1003
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/opencode-parser.js +3 -123
- package/dist/src/native-fusion/parser-common.js +8 -264
- package/dist/src/native-fusion/parsers.js +8 -729
- package/dist/src/native-fusion/service.d.ts +10 -0
- package/dist/src/native-fusion/service.js +2 -198
- package/dist/src/native-fusion/state.js +1 -22
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/region.js +1 -88
- package/dist/src/relay/client.js +1 -343
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -733
- package/dist/src/session/handlers/control.js +1 -55
- package/dist/src/session/handlers/fs.js +1 -747
- package/dist/src/session/handlers/session-refresh.js +1 -35
- package/dist/src/session/handlers/skills.js +1 -121
- package/dist/src/session/handlers/title.js +1 -60
- package/dist/src/session/handlers/tool-detail.d.ts +3 -0
- package/dist/src/session/handlers/tool-detail.js +1 -0
- package/dist/src/session/manager.d.ts +3 -0
- package/dist/src/session/manager.js +1 -261
- package/dist/src/session/projection.js +1 -54
- package/dist/src/session/queue.js +4 -317
- package/dist/src/session/remote-attachments.js +1 -72
- package/dist/src/session/store.js +3 -109
- package/dist/src/session/types.d.ts +4 -0
- package/dist/src/session/types.js +1 -4
- package/dist/src/skills/registry.js +15 -148
- package/dist/src/skills/setup.js +1 -101
- package/dist/src/tools/markdown-to-pdf.js +10 -346
- package/dist/src/upgrade/engine.js +3 -347
- package/package.json +3 -2
- package/dist/scripts/wechat-rpa-download-candidates.mjs +0 -105
|
@@ -1,249 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/cursor-adapter.test.ts
|
|
3
|
-
import { createInterface } from 'node:readline';
|
|
4
|
-
import { randomUUID } from 'node:crypto';
|
|
5
|
-
import { AgentAdapter, registerAgent } from './adapter.js';
|
|
6
|
-
import { resolveBuiltinCommand, spawnResolvedCommand } from './command-spec.js';
|
|
7
|
-
import { buildAgentProcessEnv } from '../agent-env.js';
|
|
8
|
-
export class CursorAdapter extends AgentAdapter {
|
|
9
|
-
type = 'cursor';
|
|
10
|
-
process = null;
|
|
11
|
-
chatId = null;
|
|
12
|
-
workDir = null;
|
|
13
|
-
seq = 0;
|
|
14
|
-
runId = '';
|
|
15
|
-
emittedText = '';
|
|
16
|
-
async start(_sessionId, workDir, agentSessionId) {
|
|
17
|
-
this.workDir = workDir;
|
|
18
|
-
this.seq = 0;
|
|
19
|
-
if (agentSessionId)
|
|
20
|
-
this.chatId = agentSessionId;
|
|
21
|
-
}
|
|
22
|
-
async send(text, modelId) {
|
|
23
|
-
await this.killProcess();
|
|
24
|
-
this.runId = randomUUID();
|
|
25
|
-
this.resetRunState();
|
|
26
|
-
const args = [
|
|
27
|
-
'-p', text,
|
|
28
|
-
'--output-format', 'stream-json',
|
|
29
|
-
'--stream-partial-output',
|
|
30
|
-
'--trust',
|
|
31
|
-
];
|
|
32
|
-
if (modelId) {
|
|
33
|
-
args.push('--model', modelId);
|
|
34
|
-
}
|
|
35
|
-
if (this.chatId) {
|
|
36
|
-
args.push('--continue');
|
|
37
|
-
}
|
|
38
|
-
this.spawnAndParse(args);
|
|
39
|
-
}
|
|
40
|
-
async resume(agentSessionId) {
|
|
41
|
-
await this.killProcess();
|
|
42
|
-
this.chatId = agentSessionId;
|
|
43
|
-
this.runId = randomUUID();
|
|
44
|
-
this.resetRunState();
|
|
45
|
-
this.spawnAndParse([
|
|
46
|
-
'--resume', agentSessionId,
|
|
47
|
-
'--output-format', 'stream-json',
|
|
48
|
-
'--stream-partial-output',
|
|
49
|
-
'--trust',
|
|
50
|
-
]);
|
|
51
|
-
}
|
|
52
|
-
async stop() {
|
|
53
|
-
await this.killProcess();
|
|
54
|
-
}
|
|
55
|
-
spawnAndParse(args) {
|
|
56
|
-
const spec = resolveBuiltinCommand('cursor');
|
|
57
|
-
if (!spec) {
|
|
58
|
-
this.emit('error', new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const proc = spawnResolvedCommand(spec, args, {
|
|
62
|
-
cwd: this.workDir ?? undefined,
|
|
63
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
64
|
-
env: buildAgentProcessEnv(),
|
|
65
|
-
});
|
|
66
|
-
this.process = proc;
|
|
67
|
-
const rl = createInterface({ input: proc.stdout });
|
|
68
|
-
rl.on('line', (line) => {
|
|
69
|
-
if (!line.trim())
|
|
70
|
-
return;
|
|
71
|
-
try {
|
|
72
|
-
const obj = JSON.parse(line);
|
|
73
|
-
this.handleStreamEvent(obj);
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
// 非 JSON 行当作纯文本 delta
|
|
77
|
-
this.emitEvent({ state: 'delta', text: line });
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
let stderrBuf = '';
|
|
81
|
-
proc.stderr?.on('data', (chunk) => {
|
|
82
|
-
stderrBuf += chunk.toString();
|
|
83
|
-
});
|
|
84
|
-
proc.on('close', (code) => {
|
|
85
|
-
if (this.process !== proc)
|
|
86
|
-
return;
|
|
87
|
-
this.process = null;
|
|
88
|
-
if (code !== 0 && code !== null) {
|
|
89
|
-
const msg = stderrBuf.trim() || `cursor agent exited with code ${code}`;
|
|
90
|
-
this.emitEvent({ state: 'error', message: msg });
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
proc.on('error', (err) => {
|
|
94
|
-
if (this.process !== proc)
|
|
95
|
-
return;
|
|
96
|
-
this.process = null;
|
|
97
|
-
if (err.code === 'ENOENT') {
|
|
98
|
-
this.emit('error', new Error('Command "cursor" not found. Is Cursor CLI installed?'));
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
this.emit('error', err);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
handleStreamEvent(obj) {
|
|
106
|
-
if (obj.session_id && !this.chatId) {
|
|
107
|
-
this.chatId = obj.session_id;
|
|
108
|
-
}
|
|
109
|
-
if (obj.chat_id && !this.chatId) {
|
|
110
|
-
this.chatId = obj.chat_id;
|
|
111
|
-
}
|
|
112
|
-
const eventType = obj.type ?? obj.event;
|
|
113
|
-
switch (eventType) {
|
|
114
|
-
case 'system': {
|
|
115
|
-
// init event — session_id already captured above
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
case 'assistant': {
|
|
119
|
-
// Cursor's --stream-partial-output currently emits duplicate buffered
|
|
120
|
-
// flushes. Only timestamped assistant events without model_call_id are
|
|
121
|
-
// safe to treat as live deltas; use result.result as the terminal
|
|
122
|
-
// canonical text.
|
|
123
|
-
if (obj.message?.content) {
|
|
124
|
-
if (!this.isLiveAssistantDelta(obj))
|
|
125
|
-
break;
|
|
126
|
-
for (const block of obj.message.content) {
|
|
127
|
-
if (block.type === 'text' && block.text) {
|
|
128
|
-
this.emitTextDelta(block.text);
|
|
129
|
-
}
|
|
130
|
-
else if (block.type === 'thinking' && block.thinking) {
|
|
131
|
-
this.emitEvent({ state: 'delta', text: block.thinking, thinking: true });
|
|
132
|
-
}
|
|
133
|
-
else if (block.type === 'tool_use') {
|
|
134
|
-
this.emitEvent({ state: 'tool-call', name: block.name, args: block.input });
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
// Legacy flat
|
|
140
|
-
if (obj.delta ?? obj.text) {
|
|
141
|
-
this.emitEvent({ state: 'delta', text: (obj.delta ?? obj.text) });
|
|
142
|
-
}
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
case 'user': break; // echo of user message
|
|
146
|
-
case 'result': {
|
|
147
|
-
if (obj.subtype === 'success' || !obj.is_error) {
|
|
148
|
-
this.emitFinalResultDelta(obj.result);
|
|
149
|
-
const u = obj.usage;
|
|
150
|
-
this.emitEvent({
|
|
151
|
-
state: 'final',
|
|
152
|
-
agentSessionId: this.chatId ?? undefined,
|
|
153
|
-
usage: u
|
|
154
|
-
? {
|
|
155
|
-
inputTokens: u.inputTokens ?? u.input_tokens ?? 0,
|
|
156
|
-
outputTokens: u.outputTokens ?? u.output_tokens ?? 0,
|
|
157
|
-
}
|
|
158
|
-
: undefined,
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
this.emitEvent({
|
|
163
|
-
state: 'error',
|
|
164
|
-
message: obj.result ?? obj.error ?? 'unknown error',
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
break;
|
|
168
|
-
}
|
|
169
|
-
case 'error': {
|
|
170
|
-
this.emitEvent({
|
|
171
|
-
state: 'error',
|
|
172
|
-
message: obj.error ?? 'unknown error',
|
|
173
|
-
});
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
// Legacy event types
|
|
177
|
-
case 'text':
|
|
178
|
-
case 'delta':
|
|
179
|
-
case 'content': {
|
|
180
|
-
const text = obj.delta ?? obj.text;
|
|
181
|
-
if (text)
|
|
182
|
-
this.emitEvent({ state: 'delta', text });
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
case 'done': {
|
|
186
|
-
this.emitEvent({ state: 'final', agentSessionId: this.chatId ?? undefined });
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
default: {
|
|
190
|
-
if (obj.done) {
|
|
191
|
-
this.emitEvent({ state: 'final', agentSessionId: this.chatId ?? undefined });
|
|
192
|
-
}
|
|
193
|
-
else if (obj.delta ?? obj.text) {
|
|
194
|
-
this.emitEvent({ state: 'delta', text: (obj.delta ?? obj.text) });
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
emitEvent(partial) {
|
|
200
|
-
const event = {
|
|
201
|
-
...partial,
|
|
202
|
-
runId: this.runId,
|
|
203
|
-
seq: this.seq++,
|
|
204
|
-
};
|
|
205
|
-
this.emit('agentEvent', event);
|
|
206
|
-
}
|
|
207
|
-
async killProcess() {
|
|
208
|
-
const proc = this.process;
|
|
209
|
-
if (!proc)
|
|
210
|
-
return;
|
|
211
|
-
this.process = null;
|
|
212
|
-
proc.kill('SIGTERM');
|
|
213
|
-
await new Promise((resolve) => {
|
|
214
|
-
proc.on('close', resolve);
|
|
215
|
-
setTimeout(() => {
|
|
216
|
-
proc.kill('SIGKILL');
|
|
217
|
-
resolve();
|
|
218
|
-
}, 3000);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
resetRunState() {
|
|
222
|
-
this.seq = 0;
|
|
223
|
-
this.emittedText = '';
|
|
224
|
-
}
|
|
225
|
-
isLiveAssistantDelta(obj) {
|
|
226
|
-
return obj.timestamp_ms != null && !obj.model_call_id;
|
|
227
|
-
}
|
|
228
|
-
emitTextDelta(text) {
|
|
229
|
-
if (!text)
|
|
230
|
-
return;
|
|
231
|
-
this.emittedText += text;
|
|
232
|
-
this.emitEvent({ state: 'delta', text });
|
|
233
|
-
}
|
|
234
|
-
emitFinalResultDelta(result) {
|
|
235
|
-
if (!result)
|
|
236
|
-
return;
|
|
237
|
-
if (!this.emittedText) {
|
|
238
|
-
this.emitTextDelta(result);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
if (!result.startsWith(this.emittedText))
|
|
242
|
-
return;
|
|
243
|
-
const tail = result.slice(this.emittedText.length);
|
|
244
|
-
if (tail) {
|
|
245
|
-
this.emitTextDelta(tail);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
registerAgent('cursor', () => new CursorAdapter());
|
|
1
|
+
import{createInterface as o}from"node:readline";import{randomUUID as a}from"node:crypto";import{AgentAdapter as h,registerAgent as l}from"./adapter.js";import{resolveBuiltinCommand as u,spawnResolvedCommand as c}from"./command-spec.js";import{buildAgentProcessEnv as d}from"../agent-env.js";class m extends h{type="cursor";process=null;chatId=null;workDir=null;seq=0;runId="";emittedText="";async start(t,s,e){this.workDir=s,this.seq=0,e&&(this.chatId=e)}async send(t,s){await this.killProcess(),this.runId=a(),this.resetRunState();const e=["-p",t,"--output-format","stream-json","--stream-partial-output","--trust"];s&&e.push("--model",s),this.chatId&&e.push("--continue"),this.spawnAndParse(e)}async resume(t){await this.killProcess(),this.chatId=t,this.runId=a(),this.resetRunState(),this.spawnAndParse(["--resume",t,"--output-format","stream-json","--stream-partial-output","--trust"])}async stop(){await this.killProcess()}spawnAndParse(t){const s=u("cursor");if(!s){this.emit("error",new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));return}const e=c(s,t,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:d()});this.process=e,o({input:e.stdout}).on("line",i=>{if(i.trim())try{const r=JSON.parse(i);this.handleStreamEvent(r)}catch{this.emitEvent({state:"delta",text:i})}});let n="";e.stderr?.on("data",i=>{n+=i.toString()}),e.on("close",i=>{if(this.process===e&&(this.process=null,i!==0&&i!==null)){const r=n.trim()||`cursor agent exited with code ${i}`;this.emitEvent({state:"error",message:r})}}),e.on("error",i=>{this.process===e&&(this.process=null,i.code==="ENOENT"?this.emit("error",new Error('Command "cursor" not found. Is Cursor CLI installed?')):this.emit("error",i))})}handleStreamEvent(t){switch(t.session_id&&!this.chatId&&(this.chatId=t.session_id),t.chat_id&&!this.chatId&&(this.chatId=t.chat_id),t.type??t.event){case"system":break;case"assistant":{if(t.message?.content){if(!this.isLiveAssistantDelta(t))break;for(const e of t.message.content)e.type==="text"&&e.text?this.emitTextDelta(e.text):e.type==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.type==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});break}(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text});break}case"user":break;case"result":{if(t.subtype==="success"||!t.is_error){this.emitFinalResultDelta(t.result);const e=t.usage;this.emitEvent({state:"final",agentSessionId:this.chatId??void 0,usage:e?{inputTokens:e.inputTokens??e.input_tokens??0,outputTokens:e.outputTokens??e.output_tokens??0}:void 0})}else this.emitEvent({state:"error",message:t.result??t.error??"unknown error"});break}case"error":{this.emitEvent({state:"error",message:t.error??"unknown error"});break}case"text":case"delta":case"content":{const e=t.delta??t.text;e&&this.emitEvent({state:"delta",text:e});break}case"done":{this.emitEvent({state:"final",agentSessionId:this.chatId??void 0});break}default:t.done?this.emitEvent({state:"final",agentSessionId:this.chatId??void 0}):(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text})}}emitEvent(t){const s={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",s)}async killProcess(){const t=this.process;t&&(this.process=null,t.kill("SIGTERM"),await new Promise(s=>{t.on("close",s),setTimeout(()=>{t.kill("SIGKILL"),s()},3e3)}))}resetRunState(){this.seq=0,this.emittedText=""}isLiveAssistantDelta(t){return t.timestamp_ms!=null&&!t.model_call_id}emitTextDelta(t){t&&(this.emittedText+=t,this.emitEvent({state:"delta",text:t}))}emitFinalResultDelta(t){if(!t)return;if(!this.emittedText){this.emitTextDelta(t);return}if(!t.startsWith(this.emittedText))return;const s=t.slice(this.emittedText.length);s&&this.emitTextDelta(s)}}l("cursor",()=>new m);export{m as CursorAdapter};
|
|
@@ -1,271 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { spawnCommandString } from './command-spec.js';
|
|
6
|
-
import { buildAgentProcessEnv } from '../agent-env.js';
|
|
7
|
-
const DISPATCH_GUARD_MS = 3000;
|
|
8
|
-
export class CustomAgentAdapter extends AgentAdapter {
|
|
9
|
-
type;
|
|
10
|
-
command;
|
|
11
|
-
mode;
|
|
12
|
-
proactive;
|
|
13
|
-
sessionId = null;
|
|
14
|
-
agentSessionId = null;
|
|
15
|
-
workDir = null;
|
|
16
|
-
runId = '';
|
|
17
|
-
seq = 0;
|
|
18
|
-
// stdio mode: single long-lived process
|
|
19
|
-
stdioProcess = null;
|
|
20
|
-
// spawn mode: current single-turn process
|
|
21
|
-
spawnProcess = null;
|
|
22
|
-
dispatchGuard = null;
|
|
23
|
-
dispatchObservedEvent = false;
|
|
24
|
-
constructor(name, entry) {
|
|
25
|
-
super();
|
|
26
|
-
this.type = `custom:${name}`;
|
|
27
|
-
this.command = entry.command;
|
|
28
|
-
this.mode = entry.caps.mode;
|
|
29
|
-
this.proactive = entry.caps.proactive ?? false;
|
|
30
|
-
}
|
|
31
|
-
async start(sessionId, workDir, agentSessionId) {
|
|
32
|
-
this.sessionId = sessionId;
|
|
33
|
-
this.workDir = workDir;
|
|
34
|
-
this.seq = 0;
|
|
35
|
-
if (agentSessionId)
|
|
36
|
-
this.agentSessionId = agentSessionId;
|
|
37
|
-
if (this.mode === 'stdio') {
|
|
38
|
-
await this.startStdioProcess();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async send(text, modelId) {
|
|
42
|
-
this.runId = randomUUID();
|
|
43
|
-
this.seq = 0;
|
|
44
|
-
if (this.mode === 'stdio') {
|
|
45
|
-
await this.sendStdio(text, modelId);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
await this.runSpawn(text, modelId);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async resume(agentSessionId) {
|
|
52
|
-
if (this.mode === 'stdio') {
|
|
53
|
-
const msg = JSON.stringify({
|
|
54
|
-
method: 'resume',
|
|
55
|
-
id: randomUUID(),
|
|
56
|
-
params: { sessionId: this.sessionId, agentSessionId },
|
|
57
|
-
});
|
|
58
|
-
this.stdioProcess?.stdin?.write(msg + '\n');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async stop() {
|
|
62
|
-
if (this.mode === 'stdio') {
|
|
63
|
-
await this.stopStdioProcess();
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
await this.killSpawnProcess();
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// ─── Spawn mode ───────────────────────────────────────────────────────────
|
|
70
|
-
async runSpawn(text, modelId) {
|
|
71
|
-
await this.killSpawnProcess();
|
|
72
|
-
const guard = this.startDispatchGuard();
|
|
73
|
-
this.dispatchObservedEvent = false;
|
|
74
|
-
const args = ['/run', '--workdir', this.workDir ?? process.cwd()];
|
|
75
|
-
if (this.sessionId)
|
|
76
|
-
args.push('--session', this.sessionId);
|
|
77
|
-
if (this.agentSessionId)
|
|
78
|
-
args.push('--resume', this.agentSessionId);
|
|
79
|
-
if (modelId)
|
|
80
|
-
args.push('--model', modelId);
|
|
81
|
-
const proc = spawnCommandString(this.command, args, {
|
|
82
|
-
cwd: this.workDir ?? undefined,
|
|
83
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
84
|
-
env: buildAgentProcessEnv(),
|
|
85
|
-
});
|
|
86
|
-
this.spawnProcess = proc;
|
|
87
|
-
this.attachOutputHandlers(proc, () => {
|
|
88
|
-
if (this.spawnProcess === proc)
|
|
89
|
-
this.spawnProcess = null;
|
|
90
|
-
});
|
|
91
|
-
proc.stdin?.once('error', (error) => this.rejectDispatch(error));
|
|
92
|
-
proc.stdin?.write(text);
|
|
93
|
-
proc.stdin?.end();
|
|
94
|
-
await guard.promise;
|
|
95
|
-
}
|
|
96
|
-
async killSpawnProcess() {
|
|
97
|
-
const proc = this.spawnProcess;
|
|
98
|
-
if (!proc)
|
|
99
|
-
return;
|
|
100
|
-
this.spawnProcess = null;
|
|
101
|
-
proc.kill('SIGTERM');
|
|
102
|
-
await new Promise((resolve) => {
|
|
103
|
-
proc.on('close', resolve);
|
|
104
|
-
setTimeout(() => { proc.kill('SIGKILL'); resolve(); }, 3000);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
// ─── Stdio mode ───────────────────────────────────────────────────────────
|
|
108
|
-
async startStdioProcess() {
|
|
109
|
-
const proc = spawnCommandString(this.command, ['/start', '--workdir', this.workDir ?? process.cwd()], {
|
|
110
|
-
cwd: this.workDir ?? undefined,
|
|
111
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
112
|
-
env: buildAgentProcessEnv(),
|
|
113
|
-
});
|
|
114
|
-
this.stdioProcess = proc;
|
|
115
|
-
this.attachOutputHandlers(proc, () => {
|
|
116
|
-
if (this.stdioProcess === proc) {
|
|
117
|
-
this.stdioProcess = null;
|
|
118
|
-
this.emit('error', new Error('Custom agent process exited unexpectedly'));
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
async sendStdio(text, modelId) {
|
|
123
|
-
if (!this.stdioProcess) {
|
|
124
|
-
await this.startStdioProcess();
|
|
125
|
-
}
|
|
126
|
-
const guard = this.startDispatchGuard();
|
|
127
|
-
this.dispatchObservedEvent = false;
|
|
128
|
-
const msg = JSON.stringify({
|
|
129
|
-
method: 'send',
|
|
130
|
-
id: randomUUID(),
|
|
131
|
-
params: {
|
|
132
|
-
sessionId: this.sessionId,
|
|
133
|
-
text,
|
|
134
|
-
modelId,
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
this.stdioProcess?.stdin?.once('error', (error) => this.rejectDispatch(error));
|
|
138
|
-
this.stdioProcess?.stdin?.write(msg + '\n');
|
|
139
|
-
await guard.promise;
|
|
140
|
-
}
|
|
141
|
-
async stopStdioProcess() {
|
|
142
|
-
const proc = this.stdioProcess;
|
|
143
|
-
if (!proc)
|
|
144
|
-
return;
|
|
145
|
-
const stopMsg = JSON.stringify({ method: 'stop', id: randomUUID() });
|
|
146
|
-
proc.stdin?.write(stopMsg + '\n');
|
|
147
|
-
await new Promise((resolve) => {
|
|
148
|
-
const timer = setTimeout(() => {
|
|
149
|
-
proc.kill('SIGTERM');
|
|
150
|
-
setTimeout(() => { proc.kill('SIGKILL'); resolve(); }, 3000);
|
|
151
|
-
}, 5000);
|
|
152
|
-
proc.on('close', () => {
|
|
153
|
-
clearTimeout(timer);
|
|
154
|
-
resolve();
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
this.stdioProcess = null;
|
|
158
|
-
}
|
|
159
|
-
// ─── Shared output parsing ────────────────────────────────────────────────
|
|
160
|
-
attachOutputHandlers(proc, onClose) {
|
|
161
|
-
const rl = createInterface({ input: proc.stdout });
|
|
162
|
-
rl.on('line', (line) => {
|
|
163
|
-
if (!line.trim())
|
|
164
|
-
return;
|
|
165
|
-
try {
|
|
166
|
-
const event = JSON.parse(line);
|
|
167
|
-
this.handleProtocolEvent(event);
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
// ignore malformed lines
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
let stderrBuf = '';
|
|
174
|
-
proc.stderr?.on('data', (chunk) => { stderrBuf += chunk.toString(); });
|
|
175
|
-
proc.on('close', (code) => {
|
|
176
|
-
onClose();
|
|
177
|
-
if (code !== 0 && code !== null) {
|
|
178
|
-
const msg = stderrBuf.trim() || `Agent exited with code ${code}`;
|
|
179
|
-
this.rejectDispatch(new Error(msg));
|
|
180
|
-
this.emitEvent({ state: 'error', message: msg });
|
|
181
|
-
}
|
|
182
|
-
else if (!this.dispatchObservedEvent) {
|
|
183
|
-
this.rejectDispatch(new Error('Custom agent exited without protocol events'));
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
this.acceptDispatch();
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
proc.on('error', (err) => {
|
|
190
|
-
onClose();
|
|
191
|
-
this.rejectDispatch(err);
|
|
192
|
-
this.emit('error', err);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
handleProtocolEvent(event) {
|
|
196
|
-
const { state } = event;
|
|
197
|
-
if (!state)
|
|
198
|
-
return;
|
|
199
|
-
this.dispatchObservedEvent = true;
|
|
200
|
-
switch (state) {
|
|
201
|
-
case 'delta':
|
|
202
|
-
this.acceptDispatch();
|
|
203
|
-
this.emitEvent({ state: 'delta', text: event.text ?? '', thinking: event.thinking });
|
|
204
|
-
break;
|
|
205
|
-
case 'final':
|
|
206
|
-
this.acceptDispatch();
|
|
207
|
-
if (event.agentSessionId)
|
|
208
|
-
this.agentSessionId = event.agentSessionId;
|
|
209
|
-
this.emitEvent({ state: 'final', usage: event.usage, agentSessionId: this.agentSessionId ?? undefined });
|
|
210
|
-
break;
|
|
211
|
-
case 'error':
|
|
212
|
-
this.rejectDispatch(new Error(event.message ?? 'unknown error'));
|
|
213
|
-
this.emitEvent({ state: 'error', message: event.message ?? 'unknown error' });
|
|
214
|
-
break;
|
|
215
|
-
case 'tool-call':
|
|
216
|
-
this.acceptDispatch();
|
|
217
|
-
this.emitEvent({ state: 'tool-call', name: event.name ?? '', args: event.args });
|
|
218
|
-
break;
|
|
219
|
-
case 'tool-result':
|
|
220
|
-
this.acceptDispatch();
|
|
221
|
-
this.emitEvent({ state: 'tool-result', name: event.name ?? '', result: event.result ?? '' });
|
|
222
|
-
break;
|
|
223
|
-
case 'notify':
|
|
224
|
-
this.acceptDispatch();
|
|
225
|
-
this.emitEvent({ state: 'notify', text: event.text ?? '', title: event.title, source: event.source });
|
|
226
|
-
break;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
startDispatchGuard() {
|
|
230
|
-
this.acceptDispatch();
|
|
231
|
-
let guard;
|
|
232
|
-
const promise = new Promise((resolve, reject) => {
|
|
233
|
-
guard = {
|
|
234
|
-
settled: false,
|
|
235
|
-
timer: setTimeout(() => this.acceptDispatch(guard), DISPATCH_GUARD_MS),
|
|
236
|
-
resolve,
|
|
237
|
-
reject,
|
|
238
|
-
promise: Promise.resolve(),
|
|
239
|
-
};
|
|
240
|
-
});
|
|
241
|
-
guard.promise = promise;
|
|
242
|
-
this.dispatchGuard = guard;
|
|
243
|
-
return guard;
|
|
244
|
-
}
|
|
245
|
-
acceptDispatch(guard = this.dispatchGuard) {
|
|
246
|
-
if (!guard || guard.settled)
|
|
247
|
-
return;
|
|
248
|
-
guard.settled = true;
|
|
249
|
-
clearTimeout(guard.timer);
|
|
250
|
-
if (this.dispatchGuard === guard)
|
|
251
|
-
this.dispatchGuard = null;
|
|
252
|
-
guard.resolve();
|
|
253
|
-
}
|
|
254
|
-
rejectDispatch(error, guard = this.dispatchGuard) {
|
|
255
|
-
if (!guard || guard.settled)
|
|
256
|
-
return;
|
|
257
|
-
guard.settled = true;
|
|
258
|
-
clearTimeout(guard.timer);
|
|
259
|
-
if (this.dispatchGuard === guard)
|
|
260
|
-
this.dispatchGuard = null;
|
|
261
|
-
guard.reject(error);
|
|
262
|
-
}
|
|
263
|
-
emitEvent(partial) {
|
|
264
|
-
const event = { ...partial, runId: this.runId, seq: this.seq++ };
|
|
265
|
-
this.emit('agentEvent', event);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
export function registerCustomAgent(name, entry) {
|
|
269
|
-
const agentType = `custom:${name}`;
|
|
270
|
-
registerAgent(agentType, () => new CustomAgentAdapter(name, entry));
|
|
271
|
-
}
|
|
1
|
+
import{createInterface as d}from"node:readline";import{randomUUID as a}from"node:crypto";import{AgentAdapter as p,registerAgent as l}from"./adapter.js";import{spawnCommandString as c}from"./command-spec.js";import{buildAgentProcessEnv as h}from"../agent-env.js";const m=3e3;class u extends p{type;command;mode;proactive;sessionId=null;agentSessionId=null;workDir=null;runId="";seq=0;stdioProcess=null;spawnProcess=null;dispatchGuard=null;dispatchObservedEvent=!1;constructor(s,t){super(),this.type=`custom:${s}`,this.command=t.command,this.mode=t.caps.mode,this.proactive=t.caps.proactive??!1}async start(s,t,r){this.sessionId=s,this.workDir=t,this.seq=0,r&&(this.agentSessionId=r),this.mode==="stdio"&&await this.startStdioProcess()}async send(s,t){this.runId=a(),this.seq=0,this.mode==="stdio"?await this.sendStdio(s,t):await this.runSpawn(s,t)}async resume(s){if(this.mode==="stdio"){const t=JSON.stringify({method:"resume",id:a(),params:{sessionId:this.sessionId,agentSessionId:s}});this.stdioProcess?.stdin?.write(t+`
|
|
2
|
+
`)}}async stop(){this.mode==="stdio"?await this.stopStdioProcess():await this.killSpawnProcess()}async runSpawn(s,t){await this.killSpawnProcess();const r=this.startDispatchGuard();this.dispatchObservedEvent=!1;const i=["/run","--workdir",this.workDir??process.cwd()];this.sessionId&&i.push("--session",this.sessionId),this.agentSessionId&&i.push("--resume",this.agentSessionId),t&&i.push("--model",t);const e=c(this.command,i,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:h()});this.spawnProcess=e,this.attachOutputHandlers(e,()=>{this.spawnProcess===e&&(this.spawnProcess=null)}),e.stdin?.once("error",o=>this.rejectDispatch(o)),e.stdin?.write(s),e.stdin?.end(),await r.promise}async killSpawnProcess(){const s=this.spawnProcess;s&&(this.spawnProcess=null,s.kill("SIGTERM"),await new Promise(t=>{s.on("close",t),setTimeout(()=>{s.kill("SIGKILL"),t()},3e3)}))}async startStdioProcess(){const s=c(this.command,["/start","--workdir",this.workDir??process.cwd()],{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:h()});this.stdioProcess=s,this.attachOutputHandlers(s,()=>{this.stdioProcess===s&&(this.stdioProcess=null,this.emit("error",new Error("Custom agent process exited unexpectedly")))})}async sendStdio(s,t){this.stdioProcess||await this.startStdioProcess();const r=this.startDispatchGuard();this.dispatchObservedEvent=!1;const i=JSON.stringify({method:"send",id:a(),params:{sessionId:this.sessionId,text:s,modelId:t}});this.stdioProcess?.stdin?.once("error",e=>this.rejectDispatch(e)),this.stdioProcess?.stdin?.write(i+`
|
|
3
|
+
`),await r.promise}async stopStdioProcess(){const s=this.stdioProcess;if(!s)return;const t=JSON.stringify({method:"stop",id:a()});s.stdin?.write(t+`
|
|
4
|
+
`),await new Promise(r=>{const i=setTimeout(()=>{s.kill("SIGTERM"),setTimeout(()=>{s.kill("SIGKILL"),r()},3e3)},5e3);s.on("close",()=>{clearTimeout(i),r()})}),this.stdioProcess=null}attachOutputHandlers(s,t){d({input:s.stdout}).on("line",e=>{if(e.trim())try{const o=JSON.parse(e);this.handleProtocolEvent(o)}catch{}});let i="";s.stderr?.on("data",e=>{i+=e.toString()}),s.on("close",e=>{if(t(),e!==0&&e!==null){const o=i.trim()||`Agent exited with code ${e}`;this.rejectDispatch(new Error(o)),this.emitEvent({state:"error",message:o})}else this.dispatchObservedEvent?this.acceptDispatch():this.rejectDispatch(new Error("Custom agent exited without protocol events"))}),s.on("error",e=>{t(),this.rejectDispatch(e),this.emit("error",e)})}handleProtocolEvent(s){const{state:t}=s;if(t)switch(this.dispatchObservedEvent=!0,t){case"delta":this.acceptDispatch(),this.emitEvent({state:"delta",text:s.text??"",thinking:s.thinking});break;case"final":this.acceptDispatch(),s.agentSessionId&&(this.agentSessionId=s.agentSessionId),this.emitEvent({state:"final",usage:s.usage,agentSessionId:this.agentSessionId??void 0});break;case"error":this.rejectDispatch(new Error(s.message??"unknown error")),this.emitEvent({state:"error",message:s.message??"unknown error"});break;case"tool-call":this.acceptDispatch(),this.emitEvent({state:"tool-call",name:s.name??"",args:s.args});break;case"tool-result":this.acceptDispatch(),this.emitEvent({state:"tool-result",name:s.name??"",result:s.result??""});break;case"notify":this.acceptDispatch(),this.emitEvent({state:"notify",text:s.text??"",title:s.title,source:s.source});break}}startDispatchGuard(){this.acceptDispatch();let s;const t=new Promise((r,i)=>{s={settled:!1,timer:setTimeout(()=>this.acceptDispatch(s),m),resolve:r,reject:i,promise:Promise.resolve()}});return s.promise=t,this.dispatchGuard=s,s}acceptDispatch(s=this.dispatchGuard){!s||s.settled||(s.settled=!0,clearTimeout(s.timer),this.dispatchGuard===s&&(this.dispatchGuard=null),s.resolve())}rejectDispatch(s,t=this.dispatchGuard){!t||t.settled||(t.settled=!0,clearTimeout(t.timer),this.dispatchGuard===t&&(this.dispatchGuard=null),t.reject(s))}emitEvent(s){const t={...s,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}}function D(n,s){const t=`custom:${n}`;l(t,()=>new u(n,s))}export{u as CustomAgentAdapter,D as registerCustomAgent};
|
|
@@ -1,56 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { loadConfig } from '../config/index.js';
|
|
3
|
-
import { getCommandVersion, resolveBuiltinCommand } from './command-spec.js';
|
|
4
|
-
const AGENTS = AVAILABLE_BUILTIN_AGENT_TYPES.filter((agent) => agent !== 'pi' && agent !== 'manager');
|
|
5
|
-
function getCustomAgentModels(caps) {
|
|
6
|
-
const ids = caps.models?.length
|
|
7
|
-
? caps.models
|
|
8
|
-
: caps.model
|
|
9
|
-
? [caps.model]
|
|
10
|
-
: [];
|
|
11
|
-
const defaultModel = caps.defaultModel ?? caps.model;
|
|
12
|
-
return ids.map((id) => ({
|
|
13
|
-
id,
|
|
14
|
-
name: id,
|
|
15
|
-
isDefault: id === defaultModel,
|
|
16
|
-
}));
|
|
17
|
-
}
|
|
18
|
-
export function detectAgents() {
|
|
19
|
-
// Pi and Manager are always available. Manager delegates to Codex/Claude at run time.
|
|
20
|
-
const detected = [
|
|
21
|
-
{ type: 'pi', command: 'shennian', args: [], version: undefined },
|
|
22
|
-
{
|
|
23
|
-
type: 'manager',
|
|
24
|
-
command: 'shennian',
|
|
25
|
-
args: ['manager'],
|
|
26
|
-
version: undefined,
|
|
27
|
-
models: [
|
|
28
|
-
{ id: 'codex', name: 'Codex', provider: 'shennian', isDefault: true },
|
|
29
|
-
{ id: 'claude', name: 'Claude Code', provider: 'shennian' },
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
];
|
|
33
|
-
for (const agent of AGENTS) {
|
|
34
|
-
const spec = resolveBuiltinCommand(agent);
|
|
35
|
-
if (!spec)
|
|
36
|
-
continue;
|
|
37
|
-
const version = getCommandVersion(spec);
|
|
38
|
-
detected.push({
|
|
39
|
-
type: agent,
|
|
40
|
-
command: spec.command,
|
|
41
|
-
args: spec.args,
|
|
42
|
-
version,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
const config = loadConfig();
|
|
46
|
-
for (const [name, entry] of Object.entries(config.customAgents ?? {})) {
|
|
47
|
-
detected.push({
|
|
48
|
-
type: `custom:${name}`,
|
|
49
|
-
command: entry.command,
|
|
50
|
-
args: [],
|
|
51
|
-
version: entry.caps.version,
|
|
52
|
-
models: getCustomAgentModels(entry.caps),
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return detected;
|
|
56
|
-
}
|
|
1
|
+
import{AVAILABLE_BUILTIN_AGENT_TYPES as s}from"@shennian/wire";import{loadConfig as d}from"../config/index.js";import{getCommandVersion as r,resolveBuiltinCommand as a}from"./command-spec.js";const i=s.filter(e=>e!=="pi"&&e!=="manager");function c(e){const t=e.models?.length?e.models:e.model?[e.model]:[],o=e.defaultModel??e.model;return t.map(n=>({id:n,name:n,isDefault:n===o}))}function g(){const e=[{type:"pi",command:"shennian",args:[],version:void 0},{type:"manager",command:"shennian",args:["manager"],version:void 0,models:[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}]}];for(const o of i){const n=a(o);if(!n)continue;const m=r(n);e.push({type:o,command:n.command,args:n.args,version:m})}const t=d();for(const[o,n]of Object.entries(t.customAgents??{}))e.push({type:`custom:${o}`,command:n.command,args:[],version:n.caps.version,models:c(n.caps)});return e}export{g as detectAgents};
|