@keyou007/agent-bot 0.1.11 → 0.1.13-alpha.0
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/.env.example +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +63 -44
- package/README.zh.md +63 -44
- package/config.example.yaml +8 -22
- package/dist/cli/AgentPrerequisites.js +262 -0
- package/dist/cli/AgentPrerequisites.js.map +1 -0
- package/dist/cli/DefaultAgentSelection.js +47 -0
- package/dist/cli/DefaultAgentSelection.js.map +1 -0
- package/dist/cli/FeishuAppConfiguration.js +1 -1
- package/dist/cli/FeishuAppConfiguration.js.map +1 -1
- package/dist/cli/FeishuAppRegistration.js +2 -2
- package/dist/cli/FeishuAppRegistration.js.map +1 -1
- package/dist/cli/Initializer.js +166 -3
- package/dist/cli/Initializer.js.map +1 -1
- package/dist/cli/ServerStarter.js +7 -2
- package/dist/cli/ServerStarter.js.map +1 -1
- package/dist/cli/controlProtocol.js.map +1 -1
- package/dist/cli/help.js +24 -20
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/taskGroupOptions.js +95 -0
- package/dist/cli/taskGroupOptions.js.map +1 -0
- package/dist/cli.js +268 -6
- package/dist/cli.js.map +1 -1
- package/dist/codex/AppServerConnection.js +3 -3
- package/dist/codex/AppServerConnection.js.map +1 -1
- package/dist/codex/CodexProcessManager.js +4 -4
- package/dist/codex/CodexProcessManager.js.map +1 -1
- package/dist/codex/CodexRuntime.js +63 -25
- package/dist/codex/CodexRuntime.js.map +1 -1
- package/dist/config/loadConfig.js +8 -22
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.js +6 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/console/ConsoleConnector.js +3 -3
- package/dist/console/ConsoleConnector.js.map +1 -1
- package/dist/console/ConsoleTurnPresenter.js +14 -7
- package/dist/console/ConsoleTurnPresenter.js.map +1 -1
- package/dist/deprecated-cli.js +5 -0
- package/dist/deprecated-cli.js.map +1 -0
- package/dist/feishu/CardRenderer.js +13 -12
- package/dist/feishu/CardRenderer.js.map +1 -1
- package/dist/feishu/FeishuTurnPresenter.js +9 -5
- package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
- package/dist/feishu/transport.js +1 -1
- package/dist/feishu/transport.js.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/presentation/OutboundRouter.js +2 -2
- package/dist/presentation/OutboundRouter.js.map +1 -1
- package/dist/presentation/TurnStateReducer.js +2 -1
- package/dist/presentation/TurnStateReducer.js.map +1 -1
- package/dist/proxy/ProxySessionController.js +128 -72
- package/dist/proxy/ProxySessionController.js.map +1 -1
- package/dist/runtime/AcpRuntimeAdapter.js +3 -2
- package/dist/runtime/AcpRuntimeAdapter.js.map +1 -1
- package/dist/runtime/createAgentRuntimeRegistry.js +1 -1
- package/dist/runtime/createAgentRuntimeRegistry.js.map +1 -1
- package/dist/supervision/systemEnvironment.js +129 -0
- package/dist/supervision/systemEnvironment.js.map +1 -0
- package/dist/supervisor.js +13 -1
- package/dist/supervisor.js.map +1 -1
- package/docs/technical-reference.md +53 -34
- package/docs/technical-reference.zh.md +53 -34
- package/npm-shrinkwrap.json +4 -3
- package/package.json +9 -4
- package/skills/agent-bot/SKILL.md +72 -33
- package/src/cli/AgentPrerequisites.ts +377 -0
- package/src/cli/DefaultAgentSelection.ts +56 -0
- package/src/cli/FeishuAppConfiguration.ts +2 -2
- package/src/cli/FeishuAppRegistration.ts +4 -4
- package/src/cli/Initializer.ts +206 -5
- package/src/cli/ServerStarter.ts +8 -3
- package/src/cli/controlProtocol.ts +21 -1
- package/src/cli/help.ts +24 -20
- package/src/cli/taskGroupOptions.ts +149 -0
- package/src/cli.ts +391 -9
- package/src/codex/AppServerConnection.ts +3 -3
- package/src/codex/CodexProcessManager.ts +4 -4
- package/src/codex/CodexRuntime.ts +84 -31
- package/src/config/loadConfig.ts +8 -22
- package/src/config/schema.ts +7 -1
- package/src/console/ConsoleConnector.ts +3 -3
- package/src/console/ConsoleTurnPresenter.ts +20 -7
- package/src/deprecated-cli.ts +9 -0
- package/src/feishu/CardRenderer.ts +13 -12
- package/src/feishu/FeishuTurnPresenter.ts +15 -1
- package/src/feishu/transport.ts +1 -1
- package/src/index.ts +34 -3
- package/src/presentation/OutboundRouter.ts +15 -3
- package/src/presentation/TurnStateReducer.ts +2 -0
- package/src/presentation/turnViewTypes.ts +1 -0
- package/src/proxy/ProxySessionController.ts +217 -73
- package/src/runtime/AcpRuntimeAdapter.ts +3 -1
- package/src/runtime/createAgentRuntimeRegistry.ts +1 -1
- package/src/supervision/systemEnvironment.ts +174 -0
- package/src/supervisor.ts +12 -1
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
export type SupportedAgentId = "codex" | "traex";
|
|
4
|
+
export type SupportedAgentState = "missing" | "outdated" | "ready";
|
|
5
|
+
export type AgentMaintenanceKind = "install" | "upgrade";
|
|
6
|
+
|
|
7
|
+
export interface AgentCommandResult {
|
|
8
|
+
status: number | null;
|
|
9
|
+
stdout: string;
|
|
10
|
+
stderr: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface AgentCommandSpec {
|
|
15
|
+
command: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
display: string;
|
|
18
|
+
timeoutMs: number;
|
|
19
|
+
env?: NodeJS.ProcessEnv;
|
|
20
|
+
inheritStdio?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type AgentCommandRunner = (command: AgentCommandSpec) => Promise<AgentCommandResult>;
|
|
24
|
+
|
|
25
|
+
export interface SupportedAgentInspection {
|
|
26
|
+
id: SupportedAgentId;
|
|
27
|
+
name: string;
|
|
28
|
+
state: SupportedAgentState;
|
|
29
|
+
installedVersion?: string;
|
|
30
|
+
latestVersion?: string;
|
|
31
|
+
latestCheckFailed?: boolean;
|
|
32
|
+
action?: {
|
|
33
|
+
kind: AgentMaintenanceKind;
|
|
34
|
+
command: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface InspectSupportedAgentsOptions {
|
|
39
|
+
platform?: NodeJS.Platform;
|
|
40
|
+
env?: NodeJS.ProcessEnv;
|
|
41
|
+
run?: AgentCommandRunner;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const CODEX_PACKAGE = "@openai/codex";
|
|
45
|
+
const TRAEX_CHANNEL = "alpha";
|
|
46
|
+
const TRAEX_INSTALL_BASE_URL = "https://code.byted.org/api/tos-proxy/download";
|
|
47
|
+
|
|
48
|
+
export async function inspectSupportedAgents(
|
|
49
|
+
options: InspectSupportedAgentsOptions = {},
|
|
50
|
+
): Promise<SupportedAgentInspection[]> {
|
|
51
|
+
return Promise.all([
|
|
52
|
+
inspectSupportedAgent("codex", options),
|
|
53
|
+
inspectSupportedAgent("traex", options),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function inspectSupportedAgent(
|
|
58
|
+
id: SupportedAgentId,
|
|
59
|
+
options: InspectSupportedAgentsOptions = {},
|
|
60
|
+
): Promise<SupportedAgentInspection> {
|
|
61
|
+
const platform = options.platform ?? process.platform;
|
|
62
|
+
const env = options.env ?? process.env;
|
|
63
|
+
const run = options.run ?? runAgentCommand;
|
|
64
|
+
return id === "codex"
|
|
65
|
+
? inspectCodex(platform, env, run)
|
|
66
|
+
: inspectTraex(platform, env, run);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function runSupportedAgentMaintenance(
|
|
70
|
+
id: SupportedAgentId,
|
|
71
|
+
kind: AgentMaintenanceKind,
|
|
72
|
+
options: InspectSupportedAgentsOptions = {},
|
|
73
|
+
): Promise<AgentCommandResult> {
|
|
74
|
+
const platform = options.platform ?? process.platform;
|
|
75
|
+
const env = options.env ?? process.env;
|
|
76
|
+
const run = options.run ?? runAgentCommand;
|
|
77
|
+
const command = maintenanceCommand(id, kind, platform, env);
|
|
78
|
+
const result = await run({ ...command, inheritStdio: true });
|
|
79
|
+
if (id !== "codex" || kind !== "upgrade" || commandSucceeded(result)) return result;
|
|
80
|
+
const fallback = codexNpmInstallCommand(platform, env);
|
|
81
|
+
return run({ ...fallback, inheritStdio: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function inspectCodex(
|
|
85
|
+
platform: NodeJS.Platform,
|
|
86
|
+
env: NodeJS.ProcessEnv,
|
|
87
|
+
run: AgentCommandRunner,
|
|
88
|
+
): Promise<SupportedAgentInspection> {
|
|
89
|
+
const installed = await run(capturedCommand("codex", ["--version"], platform, env, 5_000));
|
|
90
|
+
const installedVersion = commandVersion(installed);
|
|
91
|
+
if (!installedVersion) return missingInspection("codex", "Codex", platform, env);
|
|
92
|
+
|
|
93
|
+
const latest = await run(capturedCommand(
|
|
94
|
+
"npm",
|
|
95
|
+
["view", CODEX_PACKAGE, "version", "--json"],
|
|
96
|
+
platform,
|
|
97
|
+
env,
|
|
98
|
+
15_000,
|
|
99
|
+
));
|
|
100
|
+
const latestVersion = npmVersion(latest);
|
|
101
|
+
if (!latestVersion) {
|
|
102
|
+
return { id: "codex", name: "Codex", state: "ready", installedVersion, latestCheckFailed: true };
|
|
103
|
+
}
|
|
104
|
+
if (compareSemanticVersions(installedVersion, latestVersion) < 0) {
|
|
105
|
+
return {
|
|
106
|
+
id: "codex",
|
|
107
|
+
name: "Codex",
|
|
108
|
+
state: "outdated",
|
|
109
|
+
installedVersion,
|
|
110
|
+
latestVersion,
|
|
111
|
+
action: maintenanceAction("codex", "upgrade", platform, env),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { id: "codex", name: "Codex", state: "ready", installedVersion, latestVersion };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function inspectTraex(
|
|
118
|
+
platform: NodeJS.Platform,
|
|
119
|
+
env: NodeJS.ProcessEnv,
|
|
120
|
+
run: AgentCommandRunner,
|
|
121
|
+
): Promise<SupportedAgentInspection> {
|
|
122
|
+
const installed = await run(capturedCommand("traex", ["--version"], platform, env, 5_000));
|
|
123
|
+
const installedVersion = commandVersion(installed);
|
|
124
|
+
if (!installedVersion) return missingInspection("traex", "TraeX", platform, env);
|
|
125
|
+
|
|
126
|
+
const latest = await run(capturedCommand(
|
|
127
|
+
"traex",
|
|
128
|
+
["update", "--channel", TRAEX_CHANNEL, "check"],
|
|
129
|
+
platform,
|
|
130
|
+
env,
|
|
131
|
+
15_000,
|
|
132
|
+
));
|
|
133
|
+
const latestVersion = /^Latest TraeCode CLI version:\s*(\S+)/mu.exec(commandOutput(latest))?.[1];
|
|
134
|
+
if (!latestVersion) {
|
|
135
|
+
return { id: "traex", name: "TraeX", state: "ready", installedVersion, latestCheckFailed: true };
|
|
136
|
+
}
|
|
137
|
+
if (compareSemanticVersions(installedVersion, latestVersion) < 0) {
|
|
138
|
+
return {
|
|
139
|
+
id: "traex",
|
|
140
|
+
name: "TraeX",
|
|
141
|
+
state: "outdated",
|
|
142
|
+
installedVersion,
|
|
143
|
+
latestVersion,
|
|
144
|
+
action: maintenanceAction("traex", "upgrade", platform, env),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return { id: "traex", name: "TraeX", state: "ready", installedVersion, latestVersion };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function missingInspection(
|
|
151
|
+
id: SupportedAgentId,
|
|
152
|
+
name: string,
|
|
153
|
+
platform: NodeJS.Platform,
|
|
154
|
+
env: NodeJS.ProcessEnv,
|
|
155
|
+
): SupportedAgentInspection {
|
|
156
|
+
return {
|
|
157
|
+
id,
|
|
158
|
+
name,
|
|
159
|
+
state: "missing",
|
|
160
|
+
action: maintenanceAction(id, "install", platform, env),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function maintenanceAction(
|
|
165
|
+
id: SupportedAgentId,
|
|
166
|
+
kind: AgentMaintenanceKind,
|
|
167
|
+
platform: NodeJS.Platform,
|
|
168
|
+
env: NodeJS.ProcessEnv,
|
|
169
|
+
): SupportedAgentInspection["action"] {
|
|
170
|
+
const command = maintenanceCommand(id, kind, platform, env);
|
|
171
|
+
return { kind, command: command.display };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function maintenanceCommand(
|
|
175
|
+
id: SupportedAgentId,
|
|
176
|
+
kind: AgentMaintenanceKind,
|
|
177
|
+
platform: NodeJS.Platform,
|
|
178
|
+
env: NodeJS.ProcessEnv,
|
|
179
|
+
): AgentCommandSpec {
|
|
180
|
+
if (id === "codex") {
|
|
181
|
+
return kind === "install"
|
|
182
|
+
? codexNpmInstallCommand(platform, env)
|
|
183
|
+
: commandSpec("codex", ["update"], platform, env, 5 * 60_000);
|
|
184
|
+
}
|
|
185
|
+
if (kind === "upgrade") {
|
|
186
|
+
return commandSpec("traex", ["update", "--channel", TRAEX_CHANNEL], platform, env, 5 * 60_000);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const installEnv = {
|
|
190
|
+
...env,
|
|
191
|
+
TRAEX_INSTALL_ASSUME_YES: "1",
|
|
192
|
+
TRAEX_INSTALL_CHANNEL: TRAEX_CHANNEL,
|
|
193
|
+
};
|
|
194
|
+
if (platform === "win32") {
|
|
195
|
+
const scriptUrl = `${TRAEX_INSTALL_BASE_URL}/traex_install_windows.ps1`;
|
|
196
|
+
return {
|
|
197
|
+
command: "powershell.exe",
|
|
198
|
+
args: [
|
|
199
|
+
"-NoProfile",
|
|
200
|
+
"-ExecutionPolicy",
|
|
201
|
+
"Bypass",
|
|
202
|
+
"-Command",
|
|
203
|
+
`Invoke-RestMethod -Uri '${scriptUrl}' | Invoke-Expression`,
|
|
204
|
+
],
|
|
205
|
+
display: `$env:TRAEX_INSTALL_CHANNEL='${TRAEX_CHANNEL}'; irm '${scriptUrl}' | iex`,
|
|
206
|
+
timeoutMs: 5 * 60_000,
|
|
207
|
+
env: installEnv,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const scriptUrl = `${TRAEX_INSTALL_BASE_URL}/traex_install.sh`;
|
|
211
|
+
return {
|
|
212
|
+
command: "bash",
|
|
213
|
+
args: ["-c", `curl -fsSL '${scriptUrl}' | bash`],
|
|
214
|
+
display: `curl -fsSL '${scriptUrl}' | TRAEX_INSTALL_CHANNEL=${TRAEX_CHANNEL} bash`,
|
|
215
|
+
timeoutMs: 5 * 60_000,
|
|
216
|
+
env: installEnv,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function codexNpmInstallCommand(
|
|
221
|
+
platform: NodeJS.Platform,
|
|
222
|
+
env: NodeJS.ProcessEnv,
|
|
223
|
+
): AgentCommandSpec {
|
|
224
|
+
return commandSpec(
|
|
225
|
+
"npm",
|
|
226
|
+
["install", "--global", `${CODEX_PACKAGE}@latest`],
|
|
227
|
+
platform,
|
|
228
|
+
env,
|
|
229
|
+
5 * 60_000,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function commandSucceeded(result: AgentCommandResult): boolean {
|
|
234
|
+
return result.status === 0 && !result.error;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function capturedCommand(
|
|
238
|
+
command: string,
|
|
239
|
+
args: string[],
|
|
240
|
+
platform: NodeJS.Platform,
|
|
241
|
+
env: NodeJS.ProcessEnv,
|
|
242
|
+
timeoutMs: number,
|
|
243
|
+
): AgentCommandSpec {
|
|
244
|
+
return commandSpec(command, args, platform, env, timeoutMs);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function commandSpec(
|
|
248
|
+
command: string,
|
|
249
|
+
args: string[],
|
|
250
|
+
_platform: NodeJS.Platform,
|
|
251
|
+
env: NodeJS.ProcessEnv,
|
|
252
|
+
timeoutMs: number,
|
|
253
|
+
): AgentCommandSpec {
|
|
254
|
+
return {
|
|
255
|
+
command,
|
|
256
|
+
args,
|
|
257
|
+
display: [command, ...args].join(" "),
|
|
258
|
+
timeoutMs,
|
|
259
|
+
env,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function commandVersion(result: AgentCommandResult): string | undefined {
|
|
264
|
+
if (result.status !== 0) return undefined;
|
|
265
|
+
return versionInText(commandOutput(result));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function npmVersion(result: AgentCommandResult): string | undefined {
|
|
269
|
+
if (result.status !== 0) return undefined;
|
|
270
|
+
const output = result.stdout.trim();
|
|
271
|
+
try {
|
|
272
|
+
const parsed = JSON.parse(output) as unknown;
|
|
273
|
+
return typeof parsed === "string" ? versionInText(parsed) : undefined;
|
|
274
|
+
} catch {
|
|
275
|
+
return versionInText(output);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function commandOutput(result: AgentCommandResult): string {
|
|
280
|
+
return [result.stdout, result.stderr].filter(Boolean).join("\n");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function versionInText(value: string): string | undefined {
|
|
284
|
+
return /\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)\b/u.exec(value)?.[1];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function compareSemanticVersions(left: string, right: string): number {
|
|
288
|
+
const leftVersion = parseSemanticVersion(left);
|
|
289
|
+
const rightVersion = parseSemanticVersion(right);
|
|
290
|
+
if (!leftVersion || !rightVersion) return 0;
|
|
291
|
+
for (let index = 0; index < 3; index += 1) {
|
|
292
|
+
const difference = leftVersion.core[index]! - rightVersion.core[index]!;
|
|
293
|
+
if (difference !== 0) return difference;
|
|
294
|
+
}
|
|
295
|
+
if (!leftVersion.prerelease && !rightVersion.prerelease) return 0;
|
|
296
|
+
if (!leftVersion.prerelease) return 1;
|
|
297
|
+
if (!rightVersion.prerelease) return -1;
|
|
298
|
+
const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
|
|
299
|
+
for (let index = 0; index < length; index += 1) {
|
|
300
|
+
const leftPart = leftVersion.prerelease[index];
|
|
301
|
+
const rightPart = rightVersion.prerelease[index];
|
|
302
|
+
if (leftPart === undefined) return -1;
|
|
303
|
+
if (rightPart === undefined) return 1;
|
|
304
|
+
if (leftPart === rightPart) continue;
|
|
305
|
+
const leftNumber = /^\d+$/u.test(leftPart) ? Number(leftPart) : undefined;
|
|
306
|
+
const rightNumber = /^\d+$/u.test(rightPart) ? Number(rightPart) : undefined;
|
|
307
|
+
if (leftNumber !== undefined && rightNumber !== undefined) return leftNumber - rightNumber;
|
|
308
|
+
if (leftNumber !== undefined) return -1;
|
|
309
|
+
if (rightNumber !== undefined) return 1;
|
|
310
|
+
return leftPart.localeCompare(rightPart);
|
|
311
|
+
}
|
|
312
|
+
return 0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function parseSemanticVersion(value: string): {
|
|
316
|
+
core: [number, number, number];
|
|
317
|
+
prerelease?: string[];
|
|
318
|
+
} | undefined {
|
|
319
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/u.exec(value);
|
|
320
|
+
if (!match) return undefined;
|
|
321
|
+
return {
|
|
322
|
+
core: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
323
|
+
...(match[4] ? { prerelease: match[4].split(".") } : {}),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function runAgentCommand(command: AgentCommandSpec): Promise<AgentCommandResult> {
|
|
328
|
+
return new Promise((resolve) => {
|
|
329
|
+
const invocation = resolveInvocation(command);
|
|
330
|
+
const child = spawn(invocation.command, invocation.args, {
|
|
331
|
+
env: command.env ?? process.env,
|
|
332
|
+
windowsHide: true,
|
|
333
|
+
stdio: command.inheritStdio ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
334
|
+
});
|
|
335
|
+
const stdout: Buffer[] = [];
|
|
336
|
+
const stderr: Buffer[] = [];
|
|
337
|
+
if (!command.inheritStdio) {
|
|
338
|
+
child.stdout?.on("data", (chunk: Buffer) => stdout.push(chunk));
|
|
339
|
+
child.stderr?.on("data", (chunk: Buffer) => stderr.push(chunk));
|
|
340
|
+
}
|
|
341
|
+
let error: string | undefined;
|
|
342
|
+
let timedOut = false;
|
|
343
|
+
const timer = setTimeout(() => {
|
|
344
|
+
timedOut = true;
|
|
345
|
+
child.kill();
|
|
346
|
+
}, command.timeoutMs);
|
|
347
|
+
child.once("error", (spawnError) => {
|
|
348
|
+
error = spawnError.message;
|
|
349
|
+
});
|
|
350
|
+
child.once("close", (status) => {
|
|
351
|
+
clearTimeout(timer);
|
|
352
|
+
resolve({
|
|
353
|
+
status,
|
|
354
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
355
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
356
|
+
...(error || timedOut ? { error: timedOut ? `Timed out after ${command.timeoutMs}ms.` : error } : {}),
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function resolveInvocation(command: AgentCommandSpec): { command: string; args: string[] } {
|
|
363
|
+
if (process.platform !== "win32" || /\.exe$/iu.test(command.command)) {
|
|
364
|
+
return { command: command.command, args: command.args };
|
|
365
|
+
}
|
|
366
|
+
const commandLine = [command.command, ...command.args].map(quoteCmdArgument).join(" ");
|
|
367
|
+
return {
|
|
368
|
+
command: process.env.ComSpec ?? "cmd.exe",
|
|
369
|
+
args: ["/d", "/s", "/c", commandLine],
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function quoteCmdArgument(value: string): string {
|
|
374
|
+
return /^[A-Za-z0-9_@./:\\=+-]+$/u.test(value)
|
|
375
|
+
? value
|
|
376
|
+
: `"${value.replaceAll('"', '""')}"`;
|
|
377
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ConfiguredAgentOption } from "./Initializer.js";
|
|
2
|
+
import type { SupportedAgentInspection } from "./AgentPrerequisites.js";
|
|
3
|
+
|
|
4
|
+
export interface SelectableDefaultAgent extends ConfiguredAgentOption {
|
|
5
|
+
installedVersion?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function selectableDefaultAgents(
|
|
9
|
+
configured: ConfiguredAgentOption[],
|
|
10
|
+
inspections: SupportedAgentInspection[],
|
|
11
|
+
): SelectableDefaultAgent[] {
|
|
12
|
+
const supported = new Map(inspections.map((inspection) => [inspection.id, inspection]));
|
|
13
|
+
return configured.flatMap((agent) => {
|
|
14
|
+
const inspection = supported.get(agent.name as SupportedAgentInspection["id"]);
|
|
15
|
+
if (inspection && !inspection.installedVersion) return [];
|
|
16
|
+
return [{
|
|
17
|
+
...agent,
|
|
18
|
+
...(inspection?.installedVersion ? { installedVersion: inspection.installedVersion } : {}),
|
|
19
|
+
}];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function parseMaintenanceSelection(input: string, choiceCount: number): number[] | undefined {
|
|
24
|
+
const value = input.trim();
|
|
25
|
+
if (!value) return [];
|
|
26
|
+
if (/^(?:a|all)$/iu.test(value)) return Array.from({ length: choiceCount }, (_, index) => index);
|
|
27
|
+
const tokens = value.split(/[,,\s]+/u).filter(Boolean);
|
|
28
|
+
const selected = new Set<number>();
|
|
29
|
+
for (const token of tokens) {
|
|
30
|
+
const number = Number(token);
|
|
31
|
+
if (!Number.isInteger(number) || number < 1 || number > choiceCount) return undefined;
|
|
32
|
+
selected.add(number - 1);
|
|
33
|
+
}
|
|
34
|
+
return [...selected].sort((left, right) => left - right);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function resolveDefaultAgentChoice(
|
|
38
|
+
input: string,
|
|
39
|
+
choices: SelectableDefaultAgent[],
|
|
40
|
+
currentAgent?: string,
|
|
41
|
+
): number | undefined {
|
|
42
|
+
const value = input.trim();
|
|
43
|
+
if (!value) {
|
|
44
|
+
const currentIndex = choices.findIndex((choice) => choice.name === currentAgent);
|
|
45
|
+
return currentIndex >= 0 ? currentIndex : undefined;
|
|
46
|
+
}
|
|
47
|
+
const number = Number(value);
|
|
48
|
+
if (Number.isInteger(number) && number >= 1 && number <= choices.length) return number - 1;
|
|
49
|
+
const exactIndex = choices.findIndex((choice) => choice.name === value);
|
|
50
|
+
if (exactIndex >= 0) return exactIndex;
|
|
51
|
+
const folded = value.toLocaleLowerCase("en-US");
|
|
52
|
+
const matches = choices
|
|
53
|
+
.map((choice, index) => ({ choice, index }))
|
|
54
|
+
.filter(({ choice }) => choice.name.toLocaleLowerCase("en-US") === folded);
|
|
55
|
+
return matches.length === 1 ? matches[0]?.index : undefined;
|
|
56
|
+
}
|
|
@@ -222,8 +222,8 @@ export async function ensureFeishuAppConfiguration(
|
|
|
222
222
|
? cliText(` Last check failed: ${lastError.message}`, ` 上次检查失败:${lastError.message}`)
|
|
223
223
|
: "";
|
|
224
224
|
throw new Error(cliText(
|
|
225
|
-
`Timed out waiting for the core Lark scopes and message event. Run
|
|
226
|
-
`等待飞书核心权限和消息事件超时。请重新运行
|
|
225
|
+
`Timed out waiting for the core Lark scopes and message event. Run agentbot init again.${detail}`,
|
|
226
|
+
`等待飞书核心权限和消息事件超时。请重新运行 agentbot init。${detail}`,
|
|
227
227
|
));
|
|
228
228
|
}
|
|
229
229
|
|
|
@@ -120,8 +120,8 @@ export async function registerFeishuApp(options: FeishuAppRegistrationOptions =
|
|
|
120
120
|
case "expired_token":
|
|
121
121
|
case "invalid_grant":
|
|
122
122
|
throw new Error(cliText(
|
|
123
|
-
"The Lark app creation link expired. Run
|
|
124
|
-
"飞书应用创建链接已过期,请重新运行
|
|
123
|
+
"The Lark app creation link expired. Run agentbot init again.",
|
|
124
|
+
"飞书应用创建链接已过期,请重新运行 agentbot init。",
|
|
125
125
|
));
|
|
126
126
|
default:
|
|
127
127
|
throwRegistrationError(payload, cliText("Lark app creation failed", "飞书应用创建失败"));
|
|
@@ -129,8 +129,8 @@ export async function registerFeishuApp(options: FeishuAppRegistrationOptions =
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
throw new Error(cliText(
|
|
132
|
-
"Timed out waiting for Lark app creation. Run
|
|
133
|
-
"等待飞书应用创建超时,请重新运行
|
|
132
|
+
"Timed out waiting for Lark app creation. Run agentbot init again.",
|
|
133
|
+
"等待飞书应用创建超时,请重新运行 agentbot init。",
|
|
134
134
|
));
|
|
135
135
|
}
|
|
136
136
|
|