@ai-setting/roy-agent-cli 1.5.24 → 1.5.26
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/bin/roy-agent.js +642 -626
- package/dist/index.js +644 -626
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7239,7 +7239,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
7239
7239
|
var require_package = __commonJS((exports, module) => {
|
|
7240
7240
|
module.exports = {
|
|
7241
7241
|
name: "@ai-setting/roy-agent-cli",
|
|
7242
|
-
version: "1.5.
|
|
7242
|
+
version: "1.5.26",
|
|
7243
7243
|
type: "module",
|
|
7244
7244
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
7245
7245
|
main: "./dist/index.js",
|
|
@@ -7265,8 +7265,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
7265
7265
|
typecheck: "npx tsc --noEmit --skipLibCheck"
|
|
7266
7266
|
},
|
|
7267
7267
|
dependencies: {
|
|
7268
|
-
"@ai-setting/roy-agent-coder-harness": "1.5.
|
|
7269
|
-
"@ai-setting/roy-agent-core": "1.5.
|
|
7268
|
+
"@ai-setting/roy-agent-coder-harness": "^1.5.26",
|
|
7269
|
+
"@ai-setting/roy-agent-core": "^1.5.26",
|
|
7270
7270
|
chalk: "^5.6.2",
|
|
7271
7271
|
commander: "^14.0.3",
|
|
7272
7272
|
pyright: "^1.1.409",
|
|
@@ -8276,327 +8276,333 @@ class TaskEventHandler {
|
|
|
8276
8276
|
}
|
|
8277
8277
|
|
|
8278
8278
|
// src/commands/act.ts
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
}
|
|
8334
|
-
const envService = new EnvironmentService(output);
|
|
8335
|
-
let pluginAdapterDispose = null;
|
|
8336
|
-
let lspManagerDispose = null;
|
|
8337
|
-
const rawPlugins = args.plugin;
|
|
8338
|
-
const pluginNames = Array.isArray(rawPlugins) ? rawPlugins : rawPlugins ? [rawPlugins] : [];
|
|
8339
|
-
const CODER_HARNESS_PLUGINS = new Set([
|
|
8340
|
-
"lsp",
|
|
8341
|
-
"code-check",
|
|
8342
|
-
"reminder",
|
|
8343
|
-
"tslsp",
|
|
8344
|
-
"pylsp",
|
|
8345
|
-
"mdlsp"
|
|
8346
|
-
]);
|
|
8347
|
-
const coderPluginNames = [];
|
|
8348
|
-
const otherPluginNames = [];
|
|
8349
|
-
for (const plugin of pluginNames) {
|
|
8350
|
-
const name = plugin.split(":")[0];
|
|
8351
|
-
if (CODER_HARNESS_PLUGINS.has(name)) {
|
|
8352
|
-
coderPluginNames.push(plugin);
|
|
8353
|
-
} else {
|
|
8354
|
-
otherPluginNames.push(plugin);
|
|
8355
|
-
}
|
|
8356
|
-
}
|
|
8357
|
-
if (otherPluginNames.length > 0 && !quiet) {
|
|
8358
|
-
output.info(`\uD83D\uDCCC 加载插件: ${otherPluginNames.join(", ")}`);
|
|
8359
|
-
}
|
|
8360
|
-
try {
|
|
8361
|
-
if (!quiet) {
|
|
8362
|
-
output.info("初始化环境...");
|
|
8363
|
-
}
|
|
8364
|
-
await envService.create({
|
|
8365
|
-
envName: args.env,
|
|
8366
|
-
configPath: args.config,
|
|
8367
|
-
plugins: [...otherPluginNames, ...coderPluginNames]
|
|
8368
|
-
});
|
|
8369
|
-
const env = envService.getEnvironment();
|
|
8370
|
-
const sessionComponent = envService.getSession();
|
|
8371
|
-
if (!sessionComponent) {
|
|
8372
|
-
output.error("SessionComponent not available");
|
|
8279
|
+
function createActCommand(externalEnvService) {
|
|
8280
|
+
return {
|
|
8281
|
+
command: "act [message]",
|
|
8282
|
+
describe: "自然语言交互 - 通过自然语言驱动整个操作系统",
|
|
8283
|
+
builder: (yargs) => yargs.positional("message", {
|
|
8284
|
+
describe: "要执行的消息",
|
|
8285
|
+
type: "string"
|
|
8286
|
+
}).option("continue", {
|
|
8287
|
+
alias: "c",
|
|
8288
|
+
describe: "继续上次会话",
|
|
8289
|
+
type: "boolean",
|
|
8290
|
+
default: false
|
|
8291
|
+
}).option("session", {
|
|
8292
|
+
alias: "s",
|
|
8293
|
+
describe: "指定会话 ID",
|
|
8294
|
+
type: "string"
|
|
8295
|
+
}).option("model", {
|
|
8296
|
+
describe: "使用的模型",
|
|
8297
|
+
type: "string"
|
|
8298
|
+
}).option("config", {
|
|
8299
|
+
alias: "C",
|
|
8300
|
+
describe: "配置文件路径",
|
|
8301
|
+
type: "string"
|
|
8302
|
+
}).option("quiet", {
|
|
8303
|
+
describe: "安静模式(默认开启)",
|
|
8304
|
+
type: "boolean",
|
|
8305
|
+
default: true
|
|
8306
|
+
}).option("reasoning", {
|
|
8307
|
+
alias: "r",
|
|
8308
|
+
describe: "显示 AI 思考过程",
|
|
8309
|
+
type: "boolean",
|
|
8310
|
+
default: false
|
|
8311
|
+
}).option("tool-calls", {
|
|
8312
|
+
describe: "显示工具调用",
|
|
8313
|
+
type: "boolean",
|
|
8314
|
+
default: false
|
|
8315
|
+
}).option("tool-results", {
|
|
8316
|
+
describe: "显示工具执行结果",
|
|
8317
|
+
type: "boolean",
|
|
8318
|
+
default: false
|
|
8319
|
+
}).option("plugin", {
|
|
8320
|
+
alias: "p",
|
|
8321
|
+
describe: "启用 coder plugin (tslsp, pylsp, mdlsp, lsp, code-check, reminder)",
|
|
8322
|
+
type: "array",
|
|
8323
|
+
string: true
|
|
8324
|
+
}),
|
|
8325
|
+
async handler(args) {
|
|
8326
|
+
const quiet = args.quiet ?? true;
|
|
8327
|
+
CliQuietModeService.getInstance().setQuiet(quiet);
|
|
8328
|
+
const output = new OutputService;
|
|
8329
|
+
output.configure({ quiet });
|
|
8330
|
+
if (!args.message) {
|
|
8331
|
+
output.error("请提供要执行的消息,使用方式:roy-agent act <消息>");
|
|
8332
|
+
output.info('示例:roy-agent act "帮我写一个 hello world"');
|
|
8373
8333
|
process.exit(1);
|
|
8374
8334
|
}
|
|
8375
|
-
const
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
const
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8335
|
+
const shouldDisposeEnvService = !externalEnvService;
|
|
8336
|
+
const envService = externalEnvService ?? new EnvironmentService(output);
|
|
8337
|
+
let pluginAdapterDispose = null;
|
|
8338
|
+
let lspManagerDispose = null;
|
|
8339
|
+
const rawPlugins = args.plugin;
|
|
8340
|
+
const pluginNames = Array.isArray(rawPlugins) ? rawPlugins : rawPlugins ? [rawPlugins] : [];
|
|
8341
|
+
const CODER_HARNESS_PLUGINS = new Set([
|
|
8342
|
+
"lsp",
|
|
8343
|
+
"code-check",
|
|
8344
|
+
"reminder",
|
|
8345
|
+
"tslsp",
|
|
8346
|
+
"pylsp",
|
|
8347
|
+
"mdlsp"
|
|
8348
|
+
]);
|
|
8349
|
+
const coderPluginNames = [];
|
|
8350
|
+
const otherPluginNames = [];
|
|
8351
|
+
for (const plugin of pluginNames) {
|
|
8352
|
+
const name = plugin.split(":")[0];
|
|
8353
|
+
if (CODER_HARNESS_PLUGINS.has(name)) {
|
|
8354
|
+
coderPluginNames.push(plugin);
|
|
8389
8355
|
} else {
|
|
8390
|
-
|
|
8356
|
+
otherPluginNames.push(plugin);
|
|
8391
8357
|
}
|
|
8392
8358
|
}
|
|
8393
|
-
if (
|
|
8394
|
-
|
|
8395
|
-
const session = await sessionComponent.get(sessionId);
|
|
8396
|
-
if (session) {
|
|
8397
|
-
if (!quiet) {
|
|
8398
|
-
output.info(`会话: ${session.title} (${sessionId})`);
|
|
8399
|
-
}
|
|
8400
|
-
} else {
|
|
8401
|
-
output.warn(`会话不存在: ${sessionId},将创建新会话`);
|
|
8402
|
-
sessionId = undefined;
|
|
8403
|
-
}
|
|
8359
|
+
if (otherPluginNames.length > 0 && !quiet) {
|
|
8360
|
+
output.info(`\uD83D\uDCCC 加载插件: ${otherPluginNames.join(", ")}`);
|
|
8404
8361
|
}
|
|
8405
|
-
|
|
8406
|
-
const newSession = await sessionComponent.create({
|
|
8407
|
-
title: `Session - ${new Date().toLocaleString("zh-CN")}`
|
|
8408
|
-
});
|
|
8409
|
-
sessionId = newSession.id;
|
|
8410
|
-
isNewSession = true;
|
|
8411
|
-
await sessionComponent.setActiveSession(sessionId);
|
|
8362
|
+
try {
|
|
8412
8363
|
if (!quiet) {
|
|
8413
|
-
output.info(
|
|
8364
|
+
output.info("初始化环境...");
|
|
8414
8365
|
}
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
}
|
|
8421
|
-
const promptComponent = env.getComponent("prompt");
|
|
8422
|
-
if (llmComponent && promptComponent) {
|
|
8423
|
-
sessionComponent.setSummaryComponents(promptComponent, llmComponent);
|
|
8424
|
-
}
|
|
8425
|
-
if (coderPluginNames.length > 0) {
|
|
8426
|
-
try {
|
|
8427
|
-
const { globalHookManager: globalHookManager2 } = await import("@ai-setting/roy-agent-core");
|
|
8428
|
-
const { createPluginHookAdapter, createGlobalLSPManager } = await import("@ai-setting/roy-agent-coder-harness");
|
|
8429
|
-
const adapter = createPluginHookAdapter(globalHookManager2, {
|
|
8430
|
-
enableLSP: coderPluginNames.includes("lsp"),
|
|
8431
|
-
enableCodeCheck: coderPluginNames.includes("code-check"),
|
|
8432
|
-
enableReminder: coderPluginNames.includes("reminder"),
|
|
8433
|
-
enableTSLSP: coderPluginNames.includes("tslsp"),
|
|
8434
|
-
enablePylsp: coderPluginNames.includes("pylsp"),
|
|
8435
|
-
enableMdlsp: coderPluginNames.includes("mdlsp")
|
|
8366
|
+
if (!externalEnvService) {
|
|
8367
|
+
await envService.create({
|
|
8368
|
+
envName: args.env,
|
|
8369
|
+
configPath: args.config,
|
|
8370
|
+
plugins: [...otherPluginNames, ...coderPluginNames]
|
|
8436
8371
|
});
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8372
|
+
}
|
|
8373
|
+
const env = envService.getEnvironment();
|
|
8374
|
+
const sessionComponent = envService.getSession();
|
|
8375
|
+
if (!sessionComponent) {
|
|
8376
|
+
output.error("SessionComponent not available");
|
|
8377
|
+
process.exit(1);
|
|
8378
|
+
}
|
|
8379
|
+
const taskEventHandlerForCleanup = new TaskEventHandler({
|
|
8380
|
+
env,
|
|
8381
|
+
enabled: true
|
|
8382
|
+
});
|
|
8383
|
+
const stopTaskEventHandlerCleanup2 = taskEventHandlerForCleanup.start();
|
|
8384
|
+
let sessionId = args.session;
|
|
8385
|
+
if (args.continue && !sessionId) {
|
|
8386
|
+
const activeSession = await sessionComponent.getActiveSession();
|
|
8387
|
+
if (activeSession) {
|
|
8388
|
+
sessionId = activeSession.id;
|
|
8389
|
+
if (!quiet) {
|
|
8390
|
+
output.info(`继续会话: ${activeSession.title} (${sessionId})`);
|
|
8445
8391
|
}
|
|
8392
|
+
} else {
|
|
8393
|
+
output.warn("没有找到上次会话,将创建新会话");
|
|
8446
8394
|
}
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8395
|
+
}
|
|
8396
|
+
if (sessionId) {
|
|
8397
|
+
await sessionComponent.setActiveSession(sessionId);
|
|
8398
|
+
const session = await sessionComponent.get(sessionId);
|
|
8399
|
+
if (session) {
|
|
8400
|
+
if (!quiet) {
|
|
8401
|
+
output.info(`会话: ${session.title} (${sessionId})`);
|
|
8402
|
+
}
|
|
8403
|
+
} else {
|
|
8404
|
+
output.warn(`会话不存在: ${sessionId},将创建新会话`);
|
|
8405
|
+
sessionId = undefined;
|
|
8406
|
+
}
|
|
8407
|
+
}
|
|
8408
|
+
if (!sessionId) {
|
|
8409
|
+
const newSession = await sessionComponent.create({
|
|
8410
|
+
title: `Session - ${new Date().toLocaleString("zh-CN")}`
|
|
8411
|
+
});
|
|
8412
|
+
sessionId = newSession.id;
|
|
8413
|
+
await sessionComponent.setActiveSession(sessionId);
|
|
8414
|
+
if (!quiet) {
|
|
8415
|
+
output.info(`创建新会话: ${newSession.title} (${sessionId})`);
|
|
8416
|
+
}
|
|
8417
|
+
}
|
|
8418
|
+
const llmComponent = envService.getLLM();
|
|
8419
|
+
if (!env) {
|
|
8420
|
+
output.error("Environment not available");
|
|
8421
|
+
process.exit(1);
|
|
8422
|
+
}
|
|
8423
|
+
const promptComponent = env.getComponent("prompt");
|
|
8424
|
+
if (llmComponent && promptComponent) {
|
|
8425
|
+
sessionComponent.setSummaryComponents(promptComponent, llmComponent);
|
|
8426
|
+
}
|
|
8427
|
+
if (coderPluginNames.length > 0) {
|
|
8428
|
+
try {
|
|
8429
|
+
const { globalHookManager: globalHookManager2 } = await import("@ai-setting/roy-agent-core");
|
|
8430
|
+
const { createPluginHookAdapter, createGlobalLSPManager } = await import("@ai-setting/roy-agent-coder-harness");
|
|
8431
|
+
const adapter = createPluginHookAdapter(globalHookManager2, {
|
|
8432
|
+
enableLSP: coderPluginNames.includes("lsp"),
|
|
8433
|
+
enableCodeCheck: coderPluginNames.includes("code-check"),
|
|
8434
|
+
enableReminder: coderPluginNames.includes("reminder"),
|
|
8435
|
+
enableTSLSP: coderPluginNames.includes("tslsp"),
|
|
8436
|
+
enablePylsp: coderPluginNames.includes("pylsp"),
|
|
8437
|
+
enableMdlsp: coderPluginNames.includes("mdlsp")
|
|
8438
|
+
});
|
|
8439
|
+
await adapter.initialize();
|
|
8440
|
+
pluginAdapterDispose = () => adapter.dispose();
|
|
8441
|
+
const enabledPlugins = coderPluginNames.filter((p) => CODER_HARNESS_PLUGINS.has(p.split(":")[0]));
|
|
8442
|
+
if (enabledPlugins.length > 0) {
|
|
8443
|
+
console.log(`已启用插件: ${enabledPlugins.join(", ")}`);
|
|
8444
|
+
output.success(`✅ 已启用插件: ${enabledPlugins.join(", ")}`);
|
|
8445
|
+
if (coderPluginNames.includes("lsp") && !quiet) {
|
|
8446
|
+
output.info(`\uD83D\uDD27 LSP 服务预加载中,首次诊断可能需要等待...`);
|
|
8457
8447
|
}
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
if (!quiet) {
|
|
8469
|
-
output.success("✅ LSP 服务器预热完成");
|
|
8470
|
-
}
|
|
8471
|
-
}).catch((err) => {
|
|
8472
|
-
if (!quiet) {
|
|
8473
|
-
output.warn(`⚠ LSP 预热部分失败: ${err.message}`);
|
|
8448
|
+
}
|
|
8449
|
+
if (coderPluginNames.includes("lsp")) {
|
|
8450
|
+
try {
|
|
8451
|
+
const { createLSPConfigLoader } = await import("@ai-setting/roy-agent-coder-harness");
|
|
8452
|
+
const configLoader = createLSPConfigLoader();
|
|
8453
|
+
const lspConfig = configLoader.load();
|
|
8454
|
+
if (!quiet) {
|
|
8455
|
+
output.info("正在预热 LSP 服务器...");
|
|
8456
|
+
if (lspConfig.preload) {
|
|
8457
|
+
output.info("\uD83D\uDCCB 使用配置文件中的预加载设置");
|
|
8474
8458
|
}
|
|
8459
|
+
}
|
|
8460
|
+
const lspManager = createGlobalLSPManager({
|
|
8461
|
+
idleTimeout: lspConfig.idleTimeout ?? 300000,
|
|
8462
|
+
maxConnections: lspConfig.maxConnections ?? 10,
|
|
8463
|
+
autoDownload: lspConfig.autoInstall ?? false,
|
|
8464
|
+
preloadLanguages: lspConfig.preloadLanguages
|
|
8475
8465
|
});
|
|
8466
|
+
lspManager.registerShutdownHandler();
|
|
8467
|
+
lspManagerDispose = () => lspManager.dispose();
|
|
8468
|
+
if (lspConfig.preload || coderPluginNames.includes("lsp")) {
|
|
8469
|
+
lspManager.prewarm().then(() => {
|
|
8470
|
+
if (!quiet) {
|
|
8471
|
+
output.success("✅ LSP 服务器预热完成");
|
|
8472
|
+
}
|
|
8473
|
+
}).catch((err) => {
|
|
8474
|
+
if (!quiet) {
|
|
8475
|
+
output.warn(`⚠ LSP 预热部分失败: ${err.message}`);
|
|
8476
|
+
}
|
|
8477
|
+
});
|
|
8478
|
+
}
|
|
8479
|
+
} catch (error) {
|
|
8480
|
+
output.warn(`⚠ LSP 预热失败: ${error}`);
|
|
8476
8481
|
}
|
|
8477
|
-
} catch (error) {
|
|
8478
|
-
output.warn(`⚠ LSP 预热失败: ${error}`);
|
|
8479
8482
|
}
|
|
8483
|
+
} catch (error) {
|
|
8484
|
+
output.error(`❌ 加载 coder-harness 插件失败: ${error}`);
|
|
8480
8485
|
}
|
|
8481
|
-
} catch (error) {
|
|
8482
|
-
output.error(`❌ 加载 coder-harness 插件失败: ${error}`);
|
|
8483
8486
|
}
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
streamService.setContextInfo(contextConfig.contextWindow, contextConfig.contextWindow * contextConfig.thresholdRatio);
|
|
8493
|
-
}
|
|
8494
|
-
const unsubscribe = env.subscribeTo([
|
|
8495
|
-
"llm.start",
|
|
8496
|
-
"llm.text",
|
|
8497
|
-
"llm.reasoning",
|
|
8498
|
-
"llm.tool_call",
|
|
8499
|
-
"llm.completed",
|
|
8500
|
-
"llm.error",
|
|
8501
|
-
"tool.result",
|
|
8502
|
-
"tool.error",
|
|
8503
|
-
"context.threshold_exceeded",
|
|
8504
|
-
"context.compacting",
|
|
8505
|
-
"context.compacted"
|
|
8506
|
-
], (event) => {
|
|
8507
|
-
if (event.type === "llm.tool_call" && args.toolCalls) {
|
|
8508
|
-
const payload = event.payload;
|
|
8509
|
-
output.log(`\uD83D\uDD27 ${payload.toolCall.name}`);
|
|
8510
|
-
output.log(` ${payload.toolCall.arguments}`);
|
|
8511
|
-
return;
|
|
8487
|
+
const streamService = new StreamOutputService({
|
|
8488
|
+
showReasoning: args.reasoning,
|
|
8489
|
+
showToolCalls: args.toolCalls,
|
|
8490
|
+
showToolResults: args.toolResults
|
|
8491
|
+
});
|
|
8492
|
+
if (llmComponent) {
|
|
8493
|
+
const contextConfig = llmComponent.getContextThresholdConfig("minimax");
|
|
8494
|
+
streamService.setContextInfo(contextConfig.contextWindow, contextConfig.contextWindow * contextConfig.thresholdRatio);
|
|
8512
8495
|
}
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8496
|
+
const unsubscribe = env.subscribeTo([
|
|
8497
|
+
"llm.start",
|
|
8498
|
+
"llm.text",
|
|
8499
|
+
"llm.reasoning",
|
|
8500
|
+
"llm.tool_call",
|
|
8501
|
+
"llm.completed",
|
|
8502
|
+
"llm.error",
|
|
8503
|
+
"tool.result",
|
|
8504
|
+
"tool.error",
|
|
8505
|
+
"context.threshold_exceeded",
|
|
8506
|
+
"context.compacting",
|
|
8507
|
+
"context.compacted"
|
|
8508
|
+
], (event) => {
|
|
8509
|
+
if (event.type === "llm.tool_call" && args.toolCalls) {
|
|
8510
|
+
const payload = event.payload;
|
|
8511
|
+
output.log(`\uD83D\uDD27 ${payload.toolCall.name}`);
|
|
8512
|
+
output.log(` ${payload.toolCall.arguments}`);
|
|
8513
|
+
return;
|
|
8514
|
+
}
|
|
8515
|
+
if (event.type === "tool.result" && args.toolResults) {
|
|
8516
|
+
const payload = event.payload;
|
|
8517
|
+
const result2 = payload.result?.output ?? payload.result?.error ?? "无输出";
|
|
8518
|
+
output.log(`\uD83D\uDCE4 ${payload.name}: ${String(result2).substring(0, 200)}`);
|
|
8519
|
+
return;
|
|
8520
|
+
}
|
|
8521
|
+
if (event.type === "tool.error") {
|
|
8522
|
+
const payload = event.payload;
|
|
8523
|
+
output.error(`❌ ${payload.toolName ?? "unknown"}: ${payload.error ?? "unknown error"}`);
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
if (event.type === "context.threshold_exceeded" && !quiet) {
|
|
8527
|
+
const payload = event.payload;
|
|
8528
|
+
output.warn(`⚙ 上下文阈值 (${payload.totalTokens}/${payload.contextWindow})`);
|
|
8529
|
+
}
|
|
8530
|
+
if (event.type === "context.compacting" && !quiet) {
|
|
8531
|
+
output.info("⚙ 压缩中...");
|
|
8532
|
+
}
|
|
8533
|
+
if (event.type === "context.compacted" && !quiet) {
|
|
8534
|
+
const payload = event.payload;
|
|
8535
|
+
output.success(`✓ 已压缩 (${payload.checkpointId ?? "unknown"})`);
|
|
8536
|
+
}
|
|
8537
|
+
streamService.handleEvent(event);
|
|
8538
|
+
});
|
|
8539
|
+
if (!quiet) {
|
|
8540
|
+
output.info(`执行: ${args.message}`);
|
|
8518
8541
|
}
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8542
|
+
const provider = getTracerProvider2();
|
|
8543
|
+
const tracer = provider.getTracer("roy-tracer");
|
|
8544
|
+
const rootSpan = tracer.startSpan("act.execute", {
|
|
8545
|
+
attributes: {
|
|
8546
|
+
message: args.message.substring(0, 200),
|
|
8547
|
+
sessionId
|
|
8548
|
+
}
|
|
8549
|
+
});
|
|
8550
|
+
const traceId = rootSpan.spanContext.traceId;
|
|
8551
|
+
if (!quiet) {
|
|
8552
|
+
output.info(`[Trace] ${traceId}`);
|
|
8523
8553
|
}
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8554
|
+
provider.setGlobalContext(rootSpan.spanContext);
|
|
8555
|
+
const contextHandler = new ContextHandlerService(env, sessionComponent, { maxRetries: 1, autoCompact: true });
|
|
8556
|
+
const context = {
|
|
8557
|
+
sessionId,
|
|
8558
|
+
metadata: {
|
|
8559
|
+
originalQuery: args.message,
|
|
8560
|
+
traceId
|
|
8561
|
+
}
|
|
8562
|
+
};
|
|
8563
|
+
let result;
|
|
8564
|
+
try {
|
|
8565
|
+
result = await contextHandler.handleQueryWithContext(args.message, context);
|
|
8566
|
+
rootSpan.end(result);
|
|
8567
|
+
} catch (error) {
|
|
8568
|
+
rootSpan.setAttribute("error", String(error));
|
|
8569
|
+
rootSpan.end(undefined, error instanceof Error ? error : new Error(String(error)));
|
|
8570
|
+
if (error instanceof ContextError2 && error.code === ErrorCodes2.CONTEXT_THRESHOLD_EXCEEDED) {
|
|
8571
|
+
output.error(`上下文阈值超出限制: ${error.usage?.totalTokens}/${error.contextWindow}`);
|
|
8572
|
+
output.info("请手动压缩会话: roy-agent sessions compact " + (sessionId || "<session-id>"));
|
|
8573
|
+
}
|
|
8574
|
+
throw error;
|
|
8575
|
+
} finally {
|
|
8576
|
+
provider.setGlobalContext(undefined);
|
|
8527
8577
|
}
|
|
8528
|
-
|
|
8529
|
-
|
|
8578
|
+
unsubscribe();
|
|
8579
|
+
if (!quiet) {
|
|
8580
|
+
output.success("执行完成");
|
|
8530
8581
|
}
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8582
|
+
} catch (error) {
|
|
8583
|
+
output.error(`执行失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
8584
|
+
if (process.env.DEBUG) {
|
|
8585
|
+
console.error(error);
|
|
8534
8586
|
}
|
|
8535
|
-
|
|
8536
|
-
}
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
}
|
|
8540
|
-
const provider = getTracerProvider2();
|
|
8541
|
-
const tracer = provider.getTracer("roy-tracer");
|
|
8542
|
-
const rootSpan = tracer.startSpan("act.execute", {
|
|
8543
|
-
attributes: {
|
|
8544
|
-
message: args.message.substring(0, 200),
|
|
8545
|
-
sessionId
|
|
8587
|
+
process.exit(1);
|
|
8588
|
+
} finally {
|
|
8589
|
+
if (typeof stopTaskEventHandlerCleanup === "function") {
|
|
8590
|
+
stopTaskEventHandlerCleanup();
|
|
8546
8591
|
}
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
if (!quiet) {
|
|
8550
|
-
output.info(`[Trace] ${traceId}`);
|
|
8551
|
-
}
|
|
8552
|
-
provider.setGlobalContext(rootSpan.spanContext);
|
|
8553
|
-
const contextHandler = new ContextHandlerService(env, sessionComponent, { maxRetries: 1, autoCompact: true });
|
|
8554
|
-
const context = {
|
|
8555
|
-
sessionId,
|
|
8556
|
-
metadata: {
|
|
8557
|
-
originalQuery: args.message,
|
|
8558
|
-
traceId
|
|
8592
|
+
if (lspManagerDispose) {
|
|
8593
|
+
await lspManagerDispose();
|
|
8559
8594
|
}
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
} catch (error) {
|
|
8566
|
-
rootSpan.setAttribute("error", String(error));
|
|
8567
|
-
rootSpan.end(undefined, error instanceof Error ? error : new Error(String(error)));
|
|
8568
|
-
if (error instanceof ContextError2 && error.code === ErrorCodes2.CONTEXT_THRESHOLD_EXCEEDED) {
|
|
8569
|
-
output.error(`上下文阈值超出限制: ${error.usage?.totalTokens}/${error.contextWindow}`);
|
|
8570
|
-
output.info("请手动压缩会话: roy-agent sessions compact " + (sessionId || "<session-id>"));
|
|
8595
|
+
if (pluginAdapterDispose) {
|
|
8596
|
+
await pluginAdapterDispose();
|
|
8597
|
+
}
|
|
8598
|
+
if (shouldDisposeEnvService) {
|
|
8599
|
+
await envService.dispose();
|
|
8571
8600
|
}
|
|
8572
|
-
throw error;
|
|
8573
|
-
} finally {
|
|
8574
|
-
provider.setGlobalContext(undefined);
|
|
8575
|
-
}
|
|
8576
|
-
unsubscribe();
|
|
8577
|
-
if (!quiet) {
|
|
8578
|
-
output.success("执行完成");
|
|
8579
|
-
}
|
|
8580
|
-
} catch (error) {
|
|
8581
|
-
output.error(`执行失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
8582
|
-
if (process.env.DEBUG) {
|
|
8583
|
-
console.error(error);
|
|
8584
|
-
}
|
|
8585
|
-
process.exit(1);
|
|
8586
|
-
} finally {
|
|
8587
|
-
if (typeof stopTaskEventHandlerCleanup === "function") {
|
|
8588
|
-
stopTaskEventHandlerCleanup();
|
|
8589
|
-
}
|
|
8590
|
-
if (lspManagerDispose) {
|
|
8591
|
-
await lspManagerDispose();
|
|
8592
|
-
}
|
|
8593
|
-
if (pluginAdapterDispose) {
|
|
8594
|
-
await pluginAdapterDispose();
|
|
8595
8601
|
}
|
|
8596
|
-
await envService.dispose();
|
|
8597
8602
|
}
|
|
8598
|
-
}
|
|
8599
|
-
}
|
|
8603
|
+
};
|
|
8604
|
+
}
|
|
8605
|
+
var ActCommand = createActCommand();
|
|
8600
8606
|
|
|
8601
8607
|
// src/commands/interactive.ts
|
|
8602
8608
|
import * as readline2 from "readline";
|
|
@@ -9545,367 +9551,377 @@ ${chalk4.bold("╰")}${chalk4.dim("─".repeat(49))}${chalk4.bold("╯")}
|
|
|
9545
9551
|
`);
|
|
9546
9552
|
}
|
|
9547
9553
|
}
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
const
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
await envService.create({
|
|
9614
|
-
configPath: args.config,
|
|
9615
|
-
plugins: componentPluginNames
|
|
9616
|
-
});
|
|
9617
|
-
const env = envService.getEnvironment();
|
|
9618
|
-
if (!env) {
|
|
9619
|
-
output.error("Failed to create environment");
|
|
9620
|
-
process.exit(1);
|
|
9621
|
-
}
|
|
9622
|
-
const sessionComponent = envService.getSession();
|
|
9623
|
-
if (!sessionComponent) {
|
|
9624
|
-
output.error("Failed to create session component");
|
|
9625
|
-
process.exit(1);
|
|
9626
|
-
}
|
|
9627
|
-
const llmComponent = envService.getLLM();
|
|
9628
|
-
const promptComponent = env.getComponent("prompt");
|
|
9629
|
-
const { COLORS: STREAM_COLORS, resetStreamAbort: resetStream } = await Promise.resolve().then(() => (init_stream_output_service(), exports_stream_output_service));
|
|
9630
|
-
const sessionManager = new SessionManager({
|
|
9631
|
-
sessionComponent,
|
|
9632
|
-
output,
|
|
9633
|
-
quiet: true
|
|
9634
|
-
});
|
|
9635
|
-
const sessionResult = await sessionManager.init(args.session, args.continue);
|
|
9636
|
-
const { sessionId, sessionTitle } = sessionResult;
|
|
9637
|
-
if (llmComponent && promptComponent) {
|
|
9638
|
-
sessionComponent.setSummaryComponents(promptComponent, llmComponent);
|
|
9554
|
+
function createInteractiveCommand(externalEnvService) {
|
|
9555
|
+
return {
|
|
9556
|
+
command: "interactive",
|
|
9557
|
+
aliases: ["i", "repl"],
|
|
9558
|
+
describe: "交互式模式 - 多轮对话交互",
|
|
9559
|
+
builder: (yargs) => yargs.option("session", {
|
|
9560
|
+
alias: "s",
|
|
9561
|
+
describe: "指定会话 ID",
|
|
9562
|
+
type: "string"
|
|
9563
|
+
}).option("continue", {
|
|
9564
|
+
alias: "c",
|
|
9565
|
+
describe: "继续上次会话",
|
|
9566
|
+
type: "boolean",
|
|
9567
|
+
default: false
|
|
9568
|
+
}).option("config", {
|
|
9569
|
+
alias: "C",
|
|
9570
|
+
describe: "配置文件路径",
|
|
9571
|
+
type: "string"
|
|
9572
|
+
}).option("reasoning", {
|
|
9573
|
+
alias: "r",
|
|
9574
|
+
describe: "显示 AI 思考过程",
|
|
9575
|
+
type: "boolean",
|
|
9576
|
+
default: false
|
|
9577
|
+
}).option("tool-calls", {
|
|
9578
|
+
describe: "显示工具调用",
|
|
9579
|
+
type: "boolean",
|
|
9580
|
+
default: false
|
|
9581
|
+
}).option("tool-results", {
|
|
9582
|
+
describe: "显示工具执行结果",
|
|
9583
|
+
type: "boolean",
|
|
9584
|
+
default: false
|
|
9585
|
+
}).option("event-source", {
|
|
9586
|
+
alias: "es",
|
|
9587
|
+
describe: "启动时一并启动的事件源 ID",
|
|
9588
|
+
type: "string"
|
|
9589
|
+
}).option("plugin", {
|
|
9590
|
+
alias: "p",
|
|
9591
|
+
describe: "启用 plugin (tslsp, pylsp, mdlsp, lsp, code-check, reminder, memory, task-tag)",
|
|
9592
|
+
type: "array",
|
|
9593
|
+
string: true
|
|
9594
|
+
}),
|
|
9595
|
+
async handler(args) {
|
|
9596
|
+
CliQuietModeService.getInstance().setQuiet(true);
|
|
9597
|
+
const output = new OutputService;
|
|
9598
|
+
const shouldDisposeEnvService = !externalEnvService;
|
|
9599
|
+
const envService = externalEnvService ?? new EnvironmentService(output);
|
|
9600
|
+
const CODER_HARNESS_PLUGINS = new Set([
|
|
9601
|
+
"lsp",
|
|
9602
|
+
"code-check",
|
|
9603
|
+
"reminder",
|
|
9604
|
+
"tslsp",
|
|
9605
|
+
"pylsp",
|
|
9606
|
+
"mdlsp"
|
|
9607
|
+
]);
|
|
9608
|
+
const rawPlugins = args.plugin;
|
|
9609
|
+
const pluginNames = Array.isArray(rawPlugins) ? rawPlugins : rawPlugins ? [rawPlugins] : [];
|
|
9610
|
+
const coderPluginNames = [];
|
|
9611
|
+
const componentPluginNames = [];
|
|
9612
|
+
for (const plugin of pluginNames) {
|
|
9613
|
+
const name = plugin.split(":")[0];
|
|
9614
|
+
if (CODER_HARNESS_PLUGINS.has(name)) {
|
|
9615
|
+
coderPluginNames.push(plugin);
|
|
9616
|
+
} else {
|
|
9617
|
+
componentPluginNames.push(plugin);
|
|
9618
|
+
}
|
|
9639
9619
|
}
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
});
|
|
9646
|
-
queryExecutor.initStreamOutput(llmComponent);
|
|
9647
|
-
let pluginAdapterDispose = null;
|
|
9648
|
-
let lspManagerDispose = null;
|
|
9649
|
-
let memoryPluginDispose = null;
|
|
9650
|
-
let memoryPluginInstance = null;
|
|
9651
|
-
if (coderPluginNames.length > 0) {
|
|
9652
|
-
try {
|
|
9653
|
-
const { globalHookManager: globalHookManager2 } = await import("@ai-setting/roy-agent-core");
|
|
9654
|
-
const { createPluginHookAdapter, createGlobalLSPManager } = await import("@ai-setting/roy-agent-coder-harness");
|
|
9655
|
-
const adapter = createPluginHookAdapter(globalHookManager2, {
|
|
9656
|
-
enableLSP: coderPluginNames.includes("lsp"),
|
|
9657
|
-
enableCodeCheck: coderPluginNames.includes("code-check"),
|
|
9658
|
-
enableReminder: coderPluginNames.includes("reminder"),
|
|
9659
|
-
enableTSLSP: coderPluginNames.includes("tslsp"),
|
|
9660
|
-
enablePylsp: coderPluginNames.includes("pylsp"),
|
|
9661
|
-
enableMdlsp: coderPluginNames.includes("mdlsp")
|
|
9620
|
+
try {
|
|
9621
|
+
if (!externalEnvService) {
|
|
9622
|
+
await envService.create({
|
|
9623
|
+
configPath: args.config,
|
|
9624
|
+
plugins: componentPluginNames
|
|
9662
9625
|
});
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9626
|
+
}
|
|
9627
|
+
const env = envService.getEnvironment();
|
|
9628
|
+
if (!env) {
|
|
9629
|
+
output.error("Failed to create environment");
|
|
9630
|
+
process.exit(1);
|
|
9631
|
+
}
|
|
9632
|
+
const sessionComponent = envService.getSession();
|
|
9633
|
+
if (!sessionComponent) {
|
|
9634
|
+
output.error("Failed to create session component");
|
|
9635
|
+
process.exit(1);
|
|
9636
|
+
}
|
|
9637
|
+
const llmComponent = envService.getLLM();
|
|
9638
|
+
const promptComponent = env.getComponent("prompt");
|
|
9639
|
+
const { COLORS: STREAM_COLORS, resetStreamAbort: resetStream } = await Promise.resolve().then(() => (init_stream_output_service(), exports_stream_output_service));
|
|
9640
|
+
const sessionManager = new SessionManager({
|
|
9641
|
+
sessionComponent,
|
|
9642
|
+
output,
|
|
9643
|
+
quiet: true
|
|
9644
|
+
});
|
|
9645
|
+
const sessionResult = await sessionManager.init(args.session, args.continue);
|
|
9646
|
+
const { sessionId, sessionTitle } = sessionResult;
|
|
9647
|
+
if (llmComponent && promptComponent) {
|
|
9648
|
+
sessionComponent.setSummaryComponents(promptComponent, llmComponent);
|
|
9649
|
+
}
|
|
9650
|
+
const queryExecutor = new QueryExecutor({
|
|
9651
|
+
env,
|
|
9652
|
+
sessionComponent,
|
|
9653
|
+
output,
|
|
9654
|
+
quiet: true
|
|
9655
|
+
});
|
|
9656
|
+
queryExecutor.initStreamOutput(llmComponent);
|
|
9657
|
+
let pluginAdapterDispose = null;
|
|
9658
|
+
let lspManagerDispose = null;
|
|
9659
|
+
let memoryPluginDispose = null;
|
|
9660
|
+
let memoryPluginInstance = null;
|
|
9661
|
+
if (coderPluginNames.length > 0) {
|
|
9662
|
+
try {
|
|
9663
|
+
const { globalHookManager: globalHookManager2 } = await import("@ai-setting/roy-agent-core");
|
|
9664
|
+
const { createPluginHookAdapter, createGlobalLSPManager } = await import("@ai-setting/roy-agent-coder-harness");
|
|
9665
|
+
const adapter = createPluginHookAdapter(globalHookManager2, {
|
|
9666
|
+
enableLSP: coderPluginNames.includes("lsp"),
|
|
9667
|
+
enableCodeCheck: coderPluginNames.includes("code-check"),
|
|
9668
|
+
enableReminder: coderPluginNames.includes("reminder"),
|
|
9669
|
+
enableTSLSP: coderPluginNames.includes("tslsp"),
|
|
9670
|
+
enablePylsp: coderPluginNames.includes("pylsp"),
|
|
9671
|
+
enableMdlsp: coderPluginNames.includes("mdlsp")
|
|
9672
|
+
});
|
|
9673
|
+
await adapter.initialize();
|
|
9674
|
+
pluginAdapterDispose = () => adapter.dispose();
|
|
9675
|
+
const enabledPlugins = coderPluginNames.filter((p) => CODER_HARNESS_PLUGINS.has(p.split(":")[0]));
|
|
9676
|
+
if (enabledPlugins.length > 0) {
|
|
9677
|
+
console.log(`已启用插件: ${enabledPlugins.join(", ")}`);
|
|
9678
|
+
output.success(`✅ 已启用插件: ${enabledPlugins.join(", ")}`);
|
|
9679
|
+
}
|
|
9680
|
+
if (coderPluginNames.includes("memory")) {
|
|
9681
|
+
try {
|
|
9682
|
+
const memoryPluginInstance2 = envService.getMemoryPlugin?.();
|
|
9683
|
+
if (memoryPluginInstance2) {
|
|
9684
|
+
const agentComponent = env.getComponent("agent");
|
|
9685
|
+
if (agentComponent?.registerPlugin) {
|
|
9686
|
+
if (!agentComponent.getAgent("default")) {
|
|
9687
|
+
agentComponent.registerAgent("default", { type: "primary" });
|
|
9688
|
+
}
|
|
9689
|
+
const pluginWrapper = {
|
|
9690
|
+
name: memoryPluginInstance2.name,
|
|
9691
|
+
version: "1.0.0",
|
|
9692
|
+
hooks: memoryPluginInstance2.hooks,
|
|
9693
|
+
execute: async (ctx) => {
|
|
9694
|
+
await memoryPluginInstance2.execute(ctx);
|
|
9695
|
+
return { continue: true };
|
|
9696
|
+
}
|
|
9697
|
+
};
|
|
9698
|
+
agentComponent.registerPlugin("default", pluginWrapper);
|
|
9699
|
+
output.success("✅ Memory 插件已注册到 Agent");
|
|
9678
9700
|
}
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9701
|
+
memoryPluginDispose = async () => {
|
|
9702
|
+
if (memoryPluginInstance2) {
|
|
9703
|
+
memoryPluginInstance2.prepareShutdown();
|
|
9704
|
+
if (memoryPluginInstance2.hasPendingTasks()) {
|
|
9705
|
+
console.log("\uD83D\uDCBE 正在保存记忆,请稍候...");
|
|
9706
|
+
await memoryPluginInstance2.waitForCompletion();
|
|
9707
|
+
}
|
|
9708
|
+
await memoryPluginInstance2.dispose();
|
|
9709
|
+
console.log("\uD83D\uDCBE 记忆已保存完毕");
|
|
9686
9710
|
}
|
|
9687
9711
|
};
|
|
9688
|
-
|
|
9689
|
-
output.
|
|
9712
|
+
} else {
|
|
9713
|
+
output.warn("⚠️ Memory 插件未在 EnvironmentService 中初始化");
|
|
9690
9714
|
}
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
memoryPluginInstance2.prepareShutdown();
|
|
9694
|
-
if (memoryPluginInstance2.hasPendingTasks()) {
|
|
9695
|
-
console.log("\uD83D\uDCBE 正在保存记忆,请稍候...");
|
|
9696
|
-
await memoryPluginInstance2.waitForCompletion();
|
|
9697
|
-
}
|
|
9698
|
-
await memoryPluginInstance2.dispose();
|
|
9699
|
-
console.log("\uD83D\uDCBE 记忆已保存完毕");
|
|
9700
|
-
}
|
|
9701
|
-
};
|
|
9702
|
-
} else {
|
|
9703
|
-
output.warn("⚠️ Memory 插件未在 EnvironmentService 中初始化");
|
|
9715
|
+
} catch (error) {
|
|
9716
|
+
output.warn(`⚠️ Memory 插件加载失败: ${error}`);
|
|
9704
9717
|
}
|
|
9705
|
-
} catch (error) {
|
|
9706
|
-
output.warn(`⚠️ Memory 插件加载失败: ${error}`);
|
|
9707
9718
|
}
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
preloadLanguages: lspConfig.preloadLanguages
|
|
9723
|
-
});
|
|
9724
|
-
lspManager.registerShutdownHandler();
|
|
9725
|
-
lspManagerDispose = () => lspManager.dispose();
|
|
9726
|
-
if (lspConfig.preload || coderPluginNames.includes("lsp")) {
|
|
9727
|
-
lspManager.prewarm().then(() => {
|
|
9728
|
-
output.success("✅ LSP 服务器预热完成");
|
|
9729
|
-
}).catch((err) => {
|
|
9730
|
-
output.warn(`⚠ LSP 预热部分失败: ${err.message}`);
|
|
9719
|
+
if (coderPluginNames.includes("lsp")) {
|
|
9720
|
+
try {
|
|
9721
|
+
const { createLSPConfigLoader } = await import("@ai-setting/roy-agent-coder-harness");
|
|
9722
|
+
const configLoader = createLSPConfigLoader();
|
|
9723
|
+
const lspConfig = configLoader.load();
|
|
9724
|
+
output.info("正在预热 LSP 服务器...");
|
|
9725
|
+
if (lspConfig.preload) {
|
|
9726
|
+
output.info("\uD83D\uDCCB 使用配置文件中的预加载设置");
|
|
9727
|
+
}
|
|
9728
|
+
const lspManager = createGlobalLSPManager({
|
|
9729
|
+
idleTimeout: lspConfig.idleTimeout ?? 300000,
|
|
9730
|
+
maxConnections: lspConfig.maxConnections ?? 10,
|
|
9731
|
+
autoDownload: lspConfig.autoInstall ?? false,
|
|
9732
|
+
preloadLanguages: lspConfig.preloadLanguages
|
|
9731
9733
|
});
|
|
9734
|
+
lspManager.registerShutdownHandler();
|
|
9735
|
+
lspManagerDispose = () => lspManager.dispose();
|
|
9736
|
+
if (lspConfig.preload || coderPluginNames.includes("lsp")) {
|
|
9737
|
+
lspManager.prewarm().then(() => {
|
|
9738
|
+
output.success("✅ LSP 服务器预热完成");
|
|
9739
|
+
}).catch((err) => {
|
|
9740
|
+
output.warn(`⚠ LSP 预热部分失败: ${err.message}`);
|
|
9741
|
+
});
|
|
9742
|
+
}
|
|
9743
|
+
} catch (error) {
|
|
9744
|
+
output.warn(`⚠ LSP 预热失败: ${error}`);
|
|
9732
9745
|
}
|
|
9733
|
-
} catch (error) {
|
|
9734
|
-
output.warn(`⚠ LSP 预热失败: ${error}`);
|
|
9735
9746
|
}
|
|
9747
|
+
} catch (error) {
|
|
9748
|
+
output.error(`❌ 加载 coder-harness 插件失败: ${error}`);
|
|
9736
9749
|
}
|
|
9737
|
-
} catch (error) {
|
|
9738
|
-
output.error(`❌ 加载 coder-harness 插件失败: ${error}`);
|
|
9739
9750
|
}
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
},
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
}
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
output.error(`❌ 压缩失败: ${result.error}`);
|
|
9773
|
-
}
|
|
9774
|
-
},
|
|
9775
|
-
onShutdown: async () => {
|
|
9776
|
-
if (memoryPluginDispose) {
|
|
9777
|
-
if (memoryPluginInstance && memoryPluginInstance.hasPendingTasks()) {
|
|
9778
|
-
console.log("\uD83D\uDCBE 正在保存记忆,请稍候...");
|
|
9779
|
-
await memoryPluginInstance.waitForCompletion();
|
|
9751
|
+
const repl = new REPL({
|
|
9752
|
+
sessionId,
|
|
9753
|
+
sessionTitle,
|
|
9754
|
+
onExecute: async (message, traceId) => {
|
|
9755
|
+
resetStreamAbort();
|
|
9756
|
+
return queryExecutor.execute(message, sessionId, {
|
|
9757
|
+
showReasoning: args.reasoning,
|
|
9758
|
+
showToolCalls: args.toolCalls,
|
|
9759
|
+
showToolResults: args.toolResults
|
|
9760
|
+
}, traceId);
|
|
9761
|
+
},
|
|
9762
|
+
onStatus: async () => {
|
|
9763
|
+
const session = await sessionComponent.get(sessionId);
|
|
9764
|
+
return {
|
|
9765
|
+
sessionId,
|
|
9766
|
+
sessionTitle,
|
|
9767
|
+
messageCount: session?.messageCount ?? 0,
|
|
9768
|
+
tokenCount: 0
|
|
9769
|
+
};
|
|
9770
|
+
},
|
|
9771
|
+
onSwitchSession: async (newSessionId) => {
|
|
9772
|
+
const result = await sessionManager.switchSession(newSessionId);
|
|
9773
|
+
queryExecutor.dispose();
|
|
9774
|
+
return result;
|
|
9775
|
+
},
|
|
9776
|
+
onCompact: async () => {
|
|
9777
|
+
output.info("\uD83D\uDD04 正在压缩上下文...");
|
|
9778
|
+
const result = await queryExecutor.compact(sessionId);
|
|
9779
|
+
if (result.success) {
|
|
9780
|
+
output.success(`✓ 压缩完成,清理了 ${result.deletedMessageCount} 条消息`);
|
|
9781
|
+
} else {
|
|
9782
|
+
output.error(`❌ 压缩失败: ${result.error}`);
|
|
9780
9783
|
}
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9784
|
+
},
|
|
9785
|
+
onShutdown: async () => {
|
|
9786
|
+
if (memoryPluginDispose) {
|
|
9787
|
+
if (memoryPluginInstance && memoryPluginInstance.hasPendingTasks()) {
|
|
9788
|
+
console.log("\uD83D\uDCBE 正在保存记忆,请稍候...");
|
|
9789
|
+
await memoryPluginInstance.waitForCompletion();
|
|
9790
|
+
}
|
|
9791
|
+
await memoryPluginDispose();
|
|
9792
|
+
console.log("\uD83D\uDCBE 记忆已保存完毕");
|
|
9793
|
+
}
|
|
9794
|
+
if (lspManagerDispose) {
|
|
9795
|
+
await lspManagerDispose();
|
|
9796
|
+
}
|
|
9797
|
+
if (pluginAdapterDispose) {
|
|
9798
|
+
await pluginAdapterDispose();
|
|
9799
|
+
}
|
|
9800
|
+
eventHandler.stop();
|
|
9801
|
+
queryExecutor.dispose();
|
|
9802
|
+
const eventSourceComponent = env.getComponent("event-source");
|
|
9803
|
+
if (eventSourceComponent) {
|
|
9804
|
+
const sources = eventSourceComponent.list?.();
|
|
9805
|
+
if (sources && sources.length > 0) {
|
|
9806
|
+
for (const source of sources) {
|
|
9807
|
+
const status = eventSourceComponent.getStatus?.(source.id);
|
|
9808
|
+
logger4.debug(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
9809
|
+
if (status !== "stopped" && status !== "created") {
|
|
9810
|
+
try {
|
|
9811
|
+
await eventSourceComponent.stopSource(source.id);
|
|
9812
|
+
output.info(`✓ 已停止事件源: ${source.name} (${status})`);
|
|
9813
|
+
} catch (error) {
|
|
9814
|
+
output.warn(`⚠️ 停止事件源 ${source.name} 失败: ${error}`);
|
|
9815
|
+
}
|
|
9805
9816
|
}
|
|
9806
9817
|
}
|
|
9807
9818
|
}
|
|
9808
9819
|
}
|
|
9820
|
+
if (shouldDisposeEnvService) {
|
|
9821
|
+
await envService.dispose();
|
|
9822
|
+
}
|
|
9809
9823
|
}
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
onEvent: async (message) => {
|
|
9819
|
-
await repl.handleEventMessage(message);
|
|
9820
|
-
}
|
|
9821
|
-
});
|
|
9822
|
-
const stopEventHandler = eventHandler.start();
|
|
9823
|
-
const eventSourceId = args.eventSource;
|
|
9824
|
-
let eventSourceStarted = false;
|
|
9825
|
-
if (eventSourceId) {
|
|
9826
|
-
const eventSourceComponent = env.getComponent("event-source");
|
|
9827
|
-
if (!eventSourceComponent || typeof eventSourceComponent.startSource !== "function") {
|
|
9828
|
-
output.error(`❌ 未找到事件源组件或 startSource 方法`);
|
|
9829
|
-
output.info(`请确保 EventSourceComponent 已正确注册`);
|
|
9830
|
-
process.exit(1);
|
|
9831
|
-
}
|
|
9832
|
-
const sources = eventSourceComponent.list();
|
|
9833
|
-
const matchedSource = sources.find((s) => s.id === eventSourceId || s.id.startsWith(eventSourceId));
|
|
9834
|
-
if (!matchedSource) {
|
|
9835
|
-
output.error(`❌ 事件源不存在: ${eventSourceId}`);
|
|
9836
|
-
output.info(`可用的事件源:`);
|
|
9837
|
-
for (const s of sources) {
|
|
9838
|
-
output.info(` - ${s.id}: ${s.name} (${s.type})`);
|
|
9824
|
+
}, env);
|
|
9825
|
+
const eventHandler = new EventHandler({
|
|
9826
|
+
env,
|
|
9827
|
+
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
9828
|
+
formatter: new EventMessageFormatter({ prefix: "[通知]" }),
|
|
9829
|
+
isIdle: () => repl.isIdle(),
|
|
9830
|
+
onEvent: async (message) => {
|
|
9831
|
+
await repl.handleEventMessage(message);
|
|
9839
9832
|
}
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
const
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9833
|
+
});
|
|
9834
|
+
const stopEventHandler = eventHandler.start();
|
|
9835
|
+
const eventSourceId = args.eventSource;
|
|
9836
|
+
if (eventSourceId) {
|
|
9837
|
+
const eventSourceComponent = env.getComponent("event-source");
|
|
9838
|
+
if (!eventSourceComponent || typeof eventSourceComponent.startSource !== "function") {
|
|
9839
|
+
output.error(`❌ 未找到事件源组件或 startSource 方法`);
|
|
9840
|
+
output.info(`请确保 EventSourceComponent 已正确注册`);
|
|
9841
|
+
process.exit(1);
|
|
9842
|
+
}
|
|
9843
|
+
const sources = eventSourceComponent.list();
|
|
9844
|
+
const matchedSource = sources.find((s) => s.id === eventSourceId || s.id.startsWith(eventSourceId));
|
|
9845
|
+
if (!matchedSource) {
|
|
9846
|
+
output.error(`❌ 事件源不存在: ${eventSourceId}`);
|
|
9847
|
+
output.info(`可用的事件源:`);
|
|
9848
|
+
for (const s of sources) {
|
|
9849
|
+
output.info(` - ${s.id}: ${s.name} (${s.type})`);
|
|
9854
9850
|
}
|
|
9855
|
-
eventSourceStarted = true;
|
|
9856
|
-
output.success(`\uD83D\uDCE1 已启动事件源: ${matchedSource.name} (${verifyStatus})`);
|
|
9857
|
-
} catch (error) {
|
|
9858
|
-
output.error(`❌ 启动事件源失败: ${error}`);
|
|
9859
|
-
output.info(`常见问题:`);
|
|
9860
|
-
output.info(` - lark-cli 事件源:确保已安装并登录 lark-cli`);
|
|
9861
|
-
output.info(` - websocket 事件源:确保目标服务器可达`);
|
|
9862
|
-
output.info(` - timer 事件源:检查配置是否正确`);
|
|
9863
9851
|
process.exit(1);
|
|
9864
9852
|
}
|
|
9853
|
+
const actualId = matchedSource.id;
|
|
9854
|
+
const status = eventSourceComponent.getStatus(actualId);
|
|
9855
|
+
if (status === "running") {
|
|
9856
|
+
output.info(`\uD83D\uDCE1 事件源 ${matchedSource.name} 已在运行中`);
|
|
9857
|
+
} else {
|
|
9858
|
+
try {
|
|
9859
|
+
await eventSourceComponent.startSource(actualId);
|
|
9860
|
+
const verifyStatus = eventSourceComponent.getStatus(actualId);
|
|
9861
|
+
if (verifyStatus !== "running") {
|
|
9862
|
+
output.error(`❌ 事件源启动后状态异常: ${verifyStatus}`);
|
|
9863
|
+
output.info(`请检查日志确认后台进程是否正常运行`);
|
|
9864
|
+
process.exit(1);
|
|
9865
|
+
}
|
|
9866
|
+
output.success(`\uD83D\uDCE1 已启动事件源: ${matchedSource.name} (${verifyStatus})`);
|
|
9867
|
+
} catch (error) {
|
|
9868
|
+
output.error(`❌ 启动事件源失败: ${error}`);
|
|
9869
|
+
output.info(`常见问题:`);
|
|
9870
|
+
output.info(` - lark-cli 事件源:确保已安装并登录 lark-cli`);
|
|
9871
|
+
output.info(` - websocket 事件源:确保目标服务器可达`);
|
|
9872
|
+
output.info(` - timer 事件源:检查配置是否正确`);
|
|
9873
|
+
process.exit(1);
|
|
9874
|
+
}
|
|
9875
|
+
}
|
|
9865
9876
|
}
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9877
|
+
let sigintHandler;
|
|
9878
|
+
sigintHandler = () => {
|
|
9879
|
+
repl.handleSigint();
|
|
9880
|
+
};
|
|
9881
|
+
process.on("SIGINT", sigintHandler);
|
|
9882
|
+
await repl.start();
|
|
9883
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
9884
|
+
console.log("正在清理资源...");
|
|
9885
|
+
if (lspManagerDispose) {
|
|
9886
|
+
await lspManagerDispose();
|
|
9887
|
+
}
|
|
9888
|
+
if (pluginAdapterDispose) {
|
|
9889
|
+
await pluginAdapterDispose();
|
|
9890
|
+
}
|
|
9891
|
+
eventHandler.stop();
|
|
9892
|
+
queryExecutor.dispose();
|
|
9893
|
+
const esComponent = env.getComponent("event-source");
|
|
9894
|
+
if (esComponent) {
|
|
9895
|
+
const sources = esComponent.list?.();
|
|
9896
|
+
if (sources) {
|
|
9897
|
+
for (const source of sources) {
|
|
9898
|
+
const status = esComponent.getStatus?.(source.id);
|
|
9899
|
+
if (status === "running") {
|
|
9900
|
+
try {
|
|
9901
|
+
await esComponent.stopSource(source.id);
|
|
9902
|
+
output.info(`✓ 已停止事件源: ${source.name}`);
|
|
9903
|
+
} catch (error) {
|
|
9904
|
+
output.warn(`⚠️ 停止事件源 ${source.name} 失败: ${error}`);
|
|
9905
|
+
}
|
|
9895
9906
|
}
|
|
9896
9907
|
}
|
|
9897
9908
|
}
|
|
9898
9909
|
}
|
|
9910
|
+
if (shouldDisposeEnvService) {
|
|
9911
|
+
await envService.dispose();
|
|
9912
|
+
}
|
|
9913
|
+
} catch (error) {
|
|
9914
|
+
output.error(`启动交互模式失败: ${error}`);
|
|
9915
|
+
throw error;
|
|
9916
|
+
} finally {
|
|
9917
|
+
if (shouldDisposeEnvService) {
|
|
9918
|
+
await envService.dispose();
|
|
9919
|
+
}
|
|
9899
9920
|
}
|
|
9900
|
-
await envService.dispose();
|
|
9901
|
-
} catch (error) {
|
|
9902
|
-
output.error(`启动交互模式失败: ${error}`);
|
|
9903
|
-
throw error;
|
|
9904
|
-
} finally {
|
|
9905
|
-
await envService.dispose();
|
|
9906
9921
|
}
|
|
9907
|
-
}
|
|
9908
|
-
}
|
|
9922
|
+
};
|
|
9923
|
+
}
|
|
9924
|
+
var InteractiveCommand = createInteractiveCommand();
|
|
9909
9925
|
|
|
9910
9926
|
// src/commands/sessions/list.ts
|
|
9911
9927
|
import chalk5 from "chalk";
|
|
@@ -17681,6 +17697,8 @@ async function runCli() {
|
|
|
17681
17697
|
}
|
|
17682
17698
|
export {
|
|
17683
17699
|
runCli,
|
|
17700
|
+
createInteractiveCommand,
|
|
17701
|
+
createActCommand,
|
|
17684
17702
|
WorkflowValidateCommand,
|
|
17685
17703
|
WorkflowUpdateCommand,
|
|
17686
17704
|
WorkflowStopCommand,
|