@ai-setting/roy-agent-cli 1.5.25 → 1.5.28

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