@ai-setting/roy-agent-cli 1.7.16 → 1.7.17

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/index.js CHANGED
@@ -1677,7 +1677,7 @@ __export(exports_repl_ink, {
1677
1677
  });
1678
1678
  import * as React2 from "react";
1679
1679
  import { Box as Box3, Text as Text4, Static, useApp, useInput as useInput2 } from "ink";
1680
- import { createLogger as createLogger4 } from "@ai-setting/roy-agent-core";
1680
+ import { createLogger as createLogger5 } from "@ai-setting/roy-agent-core";
1681
1681
  import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
1682
1682
  function nextMessageId() {
1683
1683
  _msgIdCounter += 1;
@@ -2032,7 +2032,7 @@ var init_repl_ink = __esm(() => {
2032
2032
  children: out
2033
2033
  }, undefined, false, undefined, this);
2034
2034
  });
2035
- inkLogger = createLogger4("repl-ink");
2035
+ inkLogger = createLogger5("repl-ink");
2036
2036
  MultilineInput = React2.memo(React2.forwardRef(function MultilineInput2(props, ref) {
2037
2037
  const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
2038
2038
  const [buffer, setBuffer] = React2.useState("");
@@ -9460,7 +9460,7 @@ class CliQuietModeService {
9460
9460
  // package.json
9461
9461
  var package_default = {
9462
9462
  name: "@ai-setting/roy-agent-cli",
9463
- version: "1.7.15",
9463
+ version: "1.7.17",
9464
9464
  type: "module",
9465
9465
  description: "CLI for roy-agent - Non-interactive command execution",
9466
9466
  main: "./dist/index.js",
@@ -10380,6 +10380,8 @@ __legacyDecorateClassTS([
10380
10380
  import { ContextError as ContextError2, ErrorCodes as ErrorCodes2, getTracerProvider as getTracerProvider2 } from "@ai-setting/roy-agent-core";
10381
10381
 
10382
10382
  // src/commands/shared/task-event-handler.ts
10383
+ import { createLogger as createLogger4 } from "@ai-setting/roy-agent-core";
10384
+ var logger4 = createLogger4("task-event-handler");
10383
10385
  var TASK_EVENTS = {
10384
10386
  CREATED: "task.created",
10385
10387
  UPDATED: "task.updated",
@@ -10406,14 +10408,14 @@ class TaskEventHandler {
10406
10408
  this.handleEvent(event);
10407
10409
  }
10408
10410
  });
10409
- console.log("[TaskEventHandler] Started");
10411
+ logger4.info("[TaskEventHandler] Started");
10410
10412
  return () => this.stop();
10411
10413
  }
10412
10414
  stop() {
10413
10415
  if (this.unsubscribe) {
10414
10416
  this.unsubscribe();
10415
10417
  this.unsubscribe = null;
10416
- console.log("[TaskEventHandler] Stopped");
10418
+ logger4.info("[TaskEventHandler] Stopped");
10417
10419
  }
10418
10420
  }
10419
10421
  handleEvent(event) {
@@ -10438,47 +10440,47 @@ class TaskEventHandler {
10438
10440
  this.logTaskDelegated(payload);
10439
10441
  break;
10440
10442
  default:
10441
- console.log(`[${event.type}]`, payload);
10443
+ logger4.info(`[${event.type}]`, payload);
10442
10444
  }
10443
10445
  }
10444
10446
  logTaskCreated(payload) {
10445
10447
  const task = payload.task;
10446
- console.log(`\uD83D\uDCDD Task created: #${task.id} - ${task.title}`);
10447
- console.log(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}`);
10448
+ logger4.info(`\uD83D\uDCDD Task created: #${task.id} - ${task.title}`);
10449
+ logger4.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}`);
10448
10450
  if (task.project_path) {
10449
- console.log(` Project: ${task.project_path}`);
10451
+ logger4.info(` Project: ${task.project_path}`);
10450
10452
  }
10451
10453
  if (task.context) {
10452
- console.log(` Context: ${task.context}`);
10454
+ logger4.info(` Context: ${task.context}`);
10453
10455
  }
10454
10456
  }
10455
10457
  logTaskUpdated(payload) {
10456
10458
  const task = payload.task;
10457
10459
  const changes = payload.changes;
10458
- console.log(`✏️ Task updated: #${task.id} - ${task.title}`);
10459
- console.log(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}, Progress: ${task.progress}%`);
10460
+ logger4.info(`✏️ Task updated: #${task.id} - ${task.title}`);
10461
+ logger4.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}, Progress: ${task.progress}%`);
10460
10462
  if (changes) {
10461
- console.log(` Changes: ${JSON.stringify(changes)}`);
10463
+ logger4.info(` Changes: ${JSON.stringify(changes)}`);
10462
10464
  }
10463
10465
  }
10464
10466
  logTaskCompleted(payload) {
10465
10467
  const task = payload.task;
10466
- console.log(`✅ Task completed: #${task.id} - ${task.title}`);
10467
- console.log(` Progress: ${task.progress}%, Updated: ${task.updatedAt}`);
10468
+ logger4.info(`✅ Task completed: #${task.id} - ${task.title}`);
10469
+ logger4.info(` Progress: ${task.progress}%, Updated: ${task.updatedAt}`);
10468
10470
  }
10469
10471
  logTaskDeleted(payload) {
10470
- console.log(`\uD83D\uDDD1️ Task deleted: #${payload.taskId}`);
10472
+ logger4.info(`\uD83D\uDDD1️ Task deleted: #${payload.taskId}`);
10471
10473
  }
10472
10474
  logOperationAdded(payload) {
10473
10475
  const op = payload.operation;
10474
- console.log(`\uD83D\uDCCB Operation added to task #${payload.taskId}:`);
10475
- console.log(` [${op.milestoneType}] ${op.milestoneTitle}`);
10476
- console.log(` Session: ${op.sessionId}`);
10476
+ logger4.info(`\uD83D\uDCCB Operation added to task #${payload.taskId}:`);
10477
+ logger4.info(` [${op.milestoneType}] ${op.milestoneTitle}`);
10478
+ logger4.info(` Session: ${op.sessionId}`);
10477
10479
  }
10478
10480
  logTaskDelegated(payload) {
10479
- console.log(`\uD83D\uDE80 Task delegated: #${payload.taskId}`);
10480
- console.log(` Background: ${payload.backgroundTaskId}, Type: ${payload.subagentType}`);
10481
- console.log(` ${payload.description}`);
10481
+ logger4.info(`\uD83D\uDE80 Task delegated: #${payload.taskId}`);
10482
+ logger4.info(` Background: ${payload.backgroundTaskId}, Type: ${payload.subagentType}`);
10483
+ logger4.info(` ${payload.description}`);
10482
10484
  }
10483
10485
  }
10484
10486
 
@@ -10556,9 +10558,9 @@ async function runActShutdownCleanup(deps) {
10556
10558
  envService,
10557
10559
  shouldDisposeEnvService,
10558
10560
  output,
10559
- logger: logger4
10561
+ logger: logger5
10560
10562
  } = deps;
10561
- const log = logger4 ?? {
10563
+ const log = logger5 ?? {
10562
10564
  debug: () => {},
10563
10565
  warn: (msg) => console.warn(msg)
10564
10566
  };
@@ -11702,7 +11704,7 @@ function hasActiveDescendants(env, parentSessionId) {
11702
11704
 
11703
11705
  // src/commands/interactive.ts
11704
11706
  init_stream_output_service();
11705
- import { createLogger as createLogger5, getTracerProvider as getTracerProvider3 } from "@ai-setting/roy-agent-core";
11707
+ import { createLogger as createLogger6, getTracerProvider as getTracerProvider3 } from "@ai-setting/roy-agent-core";
11706
11708
 
11707
11709
  // src/commands/input-handler.ts
11708
11710
  class InputHandler {
@@ -12027,7 +12029,7 @@ async function shutdownInteractiveSteps(deps) {
12027
12029
  envService,
12028
12030
  shouldDisposeEnvService,
12029
12031
  output,
12030
- logger: logger4,
12032
+ logger: logger5,
12031
12033
  console: consoleLike
12032
12034
  } = deps;
12033
12035
  const log = (msg) => consoleLike?.log?.(msg) ?? console.log(msg);
@@ -12040,7 +12042,7 @@ async function shutdownInteractiveSteps(deps) {
12040
12042
  await memoryPluginDispose();
12041
12043
  log("\uD83D\uDCBE 记忆已保存完毕");
12042
12044
  } catch (err) {
12043
- logger4.warn(`[Shutdown] MemoryPlugin dispose failed: ${err}`);
12045
+ logger5.warn(`[Shutdown] MemoryPlugin dispose failed: ${err}`);
12044
12046
  output.warn(`⚠️ 记忆保存失败: ${err}`);
12045
12047
  }
12046
12048
  }
@@ -12048,25 +12050,25 @@ async function shutdownInteractiveSteps(deps) {
12048
12050
  try {
12049
12051
  await lspManagerDispose();
12050
12052
  } catch (err) {
12051
- logger4.warn(`[Shutdown] LSP Manager dispose failed: ${err}`);
12053
+ logger5.warn(`[Shutdown] LSP Manager dispose failed: ${err}`);
12052
12054
  }
12053
12055
  }
12054
12056
  if (pluginAdapterDispose) {
12055
12057
  try {
12056
12058
  await pluginAdapterDispose();
12057
12059
  } catch (err) {
12058
- logger4.warn(`[Shutdown] PluginAdapter dispose failed: ${err}`);
12060
+ logger5.warn(`[Shutdown] PluginAdapter dispose failed: ${err}`);
12059
12061
  }
12060
12062
  }
12061
12063
  try {
12062
12064
  eventHandler.stop();
12063
12065
  } catch (err) {
12064
- logger4.warn(`[Shutdown] EventHandler.stop failed: ${err}`);
12066
+ logger5.warn(`[Shutdown] EventHandler.stop failed: ${err}`);
12065
12067
  }
12066
12068
  try {
12067
12069
  queryExecutor.dispose();
12068
12070
  } catch (err) {
12069
- logger4.warn(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
12071
+ logger5.warn(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
12070
12072
  }
12071
12073
  try {
12072
12074
  const eventSourceComponent = env.getComponent("event-source");
@@ -12075,7 +12077,7 @@ async function shutdownInteractiveSteps(deps) {
12075
12077
  if (sources && sources.length > 0) {
12076
12078
  for (const source of sources) {
12077
12079
  const status = eventSourceComponent.getStatus?.(source.id);
12078
- logger4.debug(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
12080
+ logger5.debug(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
12079
12081
  if (status !== "stopped" && status !== "created") {
12080
12082
  try {
12081
12083
  await eventSourceComponent.stopSource(source.id);
@@ -12088,20 +12090,20 @@ async function shutdownInteractiveSteps(deps) {
12088
12090
  }
12089
12091
  }
12090
12092
  } catch (err) {
12091
- logger4.warn(`[Shutdown] EventSource cleanup failed: ${err}`);
12093
+ logger5.warn(`[Shutdown] EventSource cleanup failed: ${err}`);
12092
12094
  }
12093
12095
  if (shouldDisposeEnvService) {
12094
12096
  try {
12095
12097
  await envService.dispose();
12096
12098
  } catch (err) {
12097
- logger4.warn(`[Shutdown] envService.dispose failed: ${err}`);
12099
+ logger5.warn(`[Shutdown] envService.dispose failed: ${err}`);
12098
12100
  }
12099
12101
  }
12100
12102
  try {
12101
12103
  await TempFileManager2.getInstance().cleanupAll();
12102
- logger4.debug("[Shutdown] TempFileManager cleaned up");
12104
+ logger5.debug("[Shutdown] TempFileManager cleaned up");
12103
12105
  } catch (err) {
12104
- logger4.warn(`[Shutdown] TempFileManager cleanup failed: ${err}`);
12106
+ logger5.warn(`[Shutdown] TempFileManager cleanup failed: ${err}`);
12105
12107
  }
12106
12108
  }
12107
12109
 
@@ -12291,7 +12293,7 @@ var COLOR_BY_STATUS = {
12291
12293
  busy: COLORS.accent
12292
12294
  };
12293
12295
  // src/commands/interactive.ts
12294
- var logger4 = createLogger5("cli:interactive");
12296
+ var logger5 = createLogger6("cli:interactive");
12295
12297
  var USER_PROMPT = COLORS.accent("❯ ");
12296
12298
 
12297
12299
  class REPL {
@@ -12483,10 +12485,10 @@ ${COLORS.system("[正在中断...]")}`);
12483
12485
  const agentComponent = this.env.getComponent("agent");
12484
12486
  if (agentComponent?.abortAll) {
12485
12487
  agentComponent.abortAll();
12486
- logger4.debug("[/abort] AgentComponent.abortAll() called");
12488
+ logger5.debug("[/abort] AgentComponent.abortAll() called");
12487
12489
  } else if (agentComponent?.abort) {
12488
12490
  agentComponent.abort("default");
12489
- logger4.debug("[/abort] AgentComponent.abort('default') called (fallback)");
12491
+ logger5.debug("[/abort] AgentComponent.abort('default') called (fallback)");
12490
12492
  }
12491
12493
  }
12492
12494
  abortStream();
@@ -12581,7 +12583,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
12581
12583
  try {
12582
12584
  await this.options.onAfterExecute(this.lastUsage);
12583
12585
  } catch (hookError) {
12584
- logger4.warn("onAfterExecute hook failed (ink path)", { error: String(hookError) });
12586
+ logger5.warn("onAfterExecute hook failed (ink path)", { error: String(hookError) });
12585
12587
  }
12586
12588
  }
12587
12589
  } catch (err) {
@@ -12601,7 +12603,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
12601
12603
  await this.shutdown();
12602
12604
  resolve();
12603
12605
  }).catch(async (err) => {
12604
- logger4.error("ink REPL render failed", { error: String(err) });
12606
+ logger5.error("ink REPL render failed", { error: String(err) });
12605
12607
  await this.shutdown();
12606
12608
  resolve();
12607
12609
  });
@@ -12658,7 +12660,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
12658
12660
  }
12659
12661
  if (key.name === "escape") {
12660
12662
  this.handleEscKey().catch((err) => {
12661
- logger4.warn(`[Esc] handleEscKey failed: ${err}`);
12663
+ logger5.warn(`[Esc] handleEscKey failed: ${err}`);
12662
12664
  });
12663
12665
  }
12664
12666
  };
@@ -12853,7 +12855,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
12853
12855
  try {
12854
12856
  await this.options.onAfterExecute(this.lastUsage);
12855
12857
  } catch (hookError) {
12856
- logger4.warn("onAfterExecute hook failed", { error: String(hookError) });
12858
+ logger5.warn("onAfterExecute hook failed", { error: String(hookError) });
12857
12859
  }
12858
12860
  }
12859
12861
  } catch (error) {
@@ -13016,12 +13018,12 @@ ${COLORS.error("❌ 执行失败: " + error)}
13016
13018
  }
13017
13019
  async handleEscKey() {
13018
13020
  if (this.isShuttingDown) {
13019
- logger4.debug("[Esc] handler entered (isShuttingDown=true) → early return");
13021
+ logger5.debug("[Esc] handler entered (isShuttingDown=true) → early return");
13020
13022
  return;
13021
13023
  }
13022
13024
  const mainSessionIdEarly = this.options.sessionId;
13023
13025
  const hasActiveDescendant = mainSessionIdEarly ? hasActiveDescendants(this.env, mainSessionIdEarly) : false;
13024
- logger4.debug(`[Esc] handler entered: isExecuting=${this.isExecuting} hasActiveDescendant=${hasActiveDescendant} lastEscPressTime=${this.lastEscPressTime}`);
13026
+ logger5.debug(`[Esc] handler entered: isExecuting=${this.isExecuting} hasActiveDescendant=${hasActiveDescendant} lastEscPressTime=${this.lastEscPressTime}`);
13025
13027
  const now = Date.now();
13026
13028
  const isExecuting = this.isExecuting;
13027
13029
  const canCascade = isExecuting || hasActiveDescendant;
@@ -13030,17 +13032,17 @@ ${COLORS.error("❌ 执行失败: " + error)}
13030
13032
  this.lastEscPressTime = now;
13031
13033
  }
13032
13034
  if (!canCascade) {
13033
- logger4.debug("[Esc] idle no-op: isExecuting=false, no active descendant");
13035
+ logger5.debug("[Esc] idle no-op: isExecuting=false, no active descendant");
13034
13036
  return;
13035
13037
  }
13036
13038
  if (this.env) {
13037
13039
  const agentComponent = this.env.getComponent("agent");
13038
13040
  if (agentComponent?.abortAll) {
13039
13041
  agentComponent.abortAll();
13040
- logger4.debug("[Esc] AgentComponent.abortAll() called");
13042
+ logger5.debug("[Esc] AgentComponent.abortAll() called");
13041
13043
  } else if (agentComponent?.abort) {
13042
13044
  agentComponent.abort("default");
13043
- logger4.debug("[Esc] AgentComponent.abort('default') called (fallback)");
13045
+ logger5.debug("[Esc] AgentComponent.abort('default') called (fallback)");
13044
13046
  }
13045
13047
  }
13046
13048
  abortStream();
@@ -13048,7 +13050,7 @@ ${COLORS.error("❌ 执行失败: " + error)}
13048
13050
  try {
13049
13051
  this.inkApi.finishAssistantStream();
13050
13052
  } catch (err) {
13051
- logger4.warn("[Esc] finishAssistantStream failed", { error: String(err) });
13053
+ logger5.warn("[Esc] finishAssistantStream failed", { error: String(err) });
13052
13054
  }
13053
13055
  }
13054
13056
  const mainSessionId = this.options.sessionId;
@@ -13061,9 +13063,9 @@ ${COLORS.error("❌ 执行失败: " + error)}
13061
13063
  timer = setTimeout(() => reject(new Error("cascade timeout 5s")), 5000);
13062
13064
  })
13063
13065
  ]);
13064
- logger4.info(`[Esc] cascade stop force=${result.force} tasks=${result.stoppedTaskIds.length} workflows=${result.stoppedWorkflowSessionIds.length} errors=${result.errors.length}`);
13066
+ logger5.info(`[Esc] cascade stop force=${result.force} tasks=${result.stoppedTaskIds.length} workflows=${result.stoppedWorkflowSessionIds.length} errors=${result.errors.length}`);
13065
13067
  } catch (err) {
13066
- logger4.warn(`[Esc] cascade stop failed: ${err}`);
13068
+ logger5.warn(`[Esc] cascade stop failed: ${err}`);
13067
13069
  } finally {
13068
13070
  if (timer !== undefined)
13069
13071
  clearTimeout(timer);
@@ -13445,7 +13447,7 @@ function createInteractiveCommand(externalEnvService) {
13445
13447
  envService,
13446
13448
  shouldDisposeEnvService,
13447
13449
  output,
13448
- logger: logger4,
13450
+ logger: logger5,
13449
13451
  console
13450
13452
  });
13451
13453
  }
@@ -25492,24 +25494,106 @@ var LspCommand = {
25492
25494
 
25493
25495
  // src/commands/install/index.ts
25494
25496
  import { spawnSync } from "node:child_process";
25495
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync, mkdirSync, rmSync } from "node:fs";
25496
- import { join as join5, resolve } from "node:path";
25497
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync, mkdirSync, rmSync as rmSync2 } from "node:fs";
25498
+ import { join as join6, resolve } from "node:path";
25497
25499
  import { homedir as homedir4 } from "node:os";
25500
+
25501
+ // src/commands/install/cleanup-stale-plugin-copies.ts
25502
+ import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, cpSync } from "node:fs";
25503
+ import { join as join5 } from "node:path";
25504
+ import { homedir as nodeHomedir, tmpdir as nodeTmpdir } from "node:os";
25505
+ function cleanupStalePluginCopies(packageName, options) {
25506
+ const HOME = options.homedir ?? nodeHomedir();
25507
+ const paths = options.localNodeModulesPaths ?? [
25508
+ join5(HOME, "node_modules"),
25509
+ join5(HOME, ".roy-agent", "node_modules")
25510
+ ];
25511
+ const backupRoot = options.backupDir ?? nodeTmpdir();
25512
+ const result = {
25513
+ cleaned: [],
25514
+ skipped: [],
25515
+ backups: []
25516
+ };
25517
+ if (!options.globalVersion) {
25518
+ for (const p of paths) {
25519
+ const candidate = join5(p, packageName);
25520
+ result.skipped.push({ path: candidate, reason: "no-global-version" });
25521
+ }
25522
+ return result;
25523
+ }
25524
+ for (const nmPath of paths) {
25525
+ const localPkgDir = join5(nmPath, packageName);
25526
+ const localPkgJson = join5(localPkgDir, "package.json");
25527
+ if (!existsSync4(localPkgJson)) {
25528
+ result.skipped.push({ path: localPkgDir, reason: "no-local-copy" });
25529
+ continue;
25530
+ }
25531
+ let localVersion = null;
25532
+ try {
25533
+ const pkg = JSON.parse(readFileSync3(localPkgJson, "utf-8"));
25534
+ localVersion = typeof pkg.version === "string" ? pkg.version : null;
25535
+ } catch {
25536
+ localVersion = null;
25537
+ }
25538
+ const shouldClean = localVersion === null || compareVersions(localVersion, options.globalVersion) < 0;
25539
+ if (!shouldClean) {
25540
+ result.skipped.push({ path: localPkgDir, reason: "local-equal-or-newer" });
25541
+ continue;
25542
+ }
25543
+ let backupPath = null;
25544
+ try {
25545
+ const safeName = packageName.replace(/@/g, "").replace(/[^a-zA-Z0-9._/-]/g, "-");
25546
+ const safeLocalVersion = (localVersion ?? "unknown").replace(/[^a-zA-Z0-9._-]/g, "-");
25547
+ const timestamp = Date.now();
25548
+ backupPath = join5(backupRoot, `${safeName}-${safeLocalVersion}-backup-${timestamp}`);
25549
+ cpSync(localPkgDir, backupPath, { recursive: true });
25550
+ result.backups.push({ originalPath: localPkgDir, backupPath });
25551
+ } catch (err) {
25552
+ backupPath = null;
25553
+ console.warn(`⚠️ Failed to backup stale copy at '${localPkgDir}': ${err}`);
25554
+ }
25555
+ try {
25556
+ rmSync(localPkgDir, { recursive: true, force: true });
25557
+ result.cleaned.push(localPkgDir);
25558
+ } catch (err) {
25559
+ console.warn(`⚠️ Failed to remove stale copy at '${localPkgDir}': ${err}`);
25560
+ result.skipped.push({ path: localPkgDir, reason: "cleanup-failed" });
25561
+ if (backupPath) {
25562
+ console.warn(` ↪ Backup preserved at '${backupPath}' for manual recovery`);
25563
+ }
25564
+ }
25565
+ }
25566
+ return result;
25567
+ }
25568
+ function compareVersions(a, b) {
25569
+ const pa = a.split(".").map((s) => Number.parseInt(s, 10));
25570
+ const pb = b.split(".").map((s) => Number.parseInt(s, 10));
25571
+ for (let i = 0;i < 3; i++) {
25572
+ const na = Number.isFinite(pa[i]) ? pa[i] : 0;
25573
+ const nb = Number.isFinite(pb[i]) ? pb[i] : 0;
25574
+ const diff = na - nb;
25575
+ if (diff !== 0)
25576
+ return diff;
25577
+ }
25578
+ return 0;
25579
+ }
25580
+
25581
+ // src/commands/install/index.ts
25498
25582
  function getConfigDir(scope) {
25499
- return scope === "global" ? join5(homedir4(), ".roy-agent") : join5(process.cwd(), ".roy");
25583
+ return scope === "global" ? join6(homedir4(), ".roy-agent") : join6(process.cwd(), ".roy");
25500
25584
  }
25501
25585
  function detectDefaultScope() {
25502
- const projectDir = join5(process.cwd(), ".roy");
25503
- return existsSync4(projectDir) ? "project" : "global";
25586
+ const projectDir = join6(process.cwd(), ".roy");
25587
+ return existsSync5(projectDir) ? "project" : "global";
25504
25588
  }
25505
25589
  function getConfigPath(scope) {
25506
- return join5(getConfigDir(scope), "plugins.json");
25590
+ return join6(getConfigDir(scope), "plugins.json");
25507
25591
  }
25508
25592
  function loadPlugins(scope) {
25509
25593
  const configPath = getConfigPath(scope);
25510
25594
  try {
25511
- if (existsSync4(configPath)) {
25512
- const raw = readFileSync3(configPath, "utf-8");
25595
+ if (existsSync5(configPath)) {
25596
+ const raw = readFileSync4(configPath, "utf-8");
25513
25597
  const config = JSON.parse(raw);
25514
25598
  return config.plugins ?? [];
25515
25599
  }
@@ -25519,7 +25603,7 @@ function loadPlugins(scope) {
25519
25603
  function savePlugins(plugins, scope) {
25520
25604
  const configDir = getConfigDir(scope);
25521
25605
  const configPath = getConfigPath(scope);
25522
- if (!existsSync4(configDir)) {
25606
+ if (!existsSync5(configDir)) {
25523
25607
  mkdirSync(configDir, { recursive: true });
25524
25608
  }
25525
25609
  const config = { plugins };
@@ -25535,10 +25619,10 @@ function stripVersionSpec(packageName) {
25535
25619
  function readPackageInfo(packageName) {
25536
25620
  const bareName = packageName.startsWith("/") || packageName.startsWith(".") ? packageName : stripVersionSpec(packageName);
25537
25621
  if (packageName.startsWith("/") || packageName.startsWith(".")) {
25538
- const localPkgPath = join5(packageName, "package.json");
25539
- if (existsSync4(localPkgPath)) {
25622
+ const localPkgPath = join6(packageName, "package.json");
25623
+ if (existsSync5(localPkgPath)) {
25540
25624
  try {
25541
- const pkg = JSON.parse(readFileSync3(localPkgPath, "utf-8"));
25625
+ const pkg = JSON.parse(readFileSync4(localPkgPath, "utf-8"));
25542
25626
  return {
25543
25627
  version: pkg.version ?? "0.0.0",
25544
25628
  name: pkg.name ?? packageName,
@@ -25550,19 +25634,19 @@ function readPackageInfo(packageName) {
25550
25634
  }
25551
25635
  }
25552
25636
  const searchPaths = [
25553
- join5(process.cwd(), "node_modules", bareName, "package.json"),
25637
+ join6(process.cwd(), "node_modules", bareName, "package.json"),
25554
25638
  resolve(process.cwd(), "..", "node_modules", bareName, "package.json"),
25555
- join5(process.cwd(), ".roy", "plugins", bareName, "package.json"),
25639
+ join6(process.cwd(), ".roy", "plugins", bareName, "package.json"),
25556
25640
  ...(() => {
25557
25641
  const globalRoot = getNpmGlobalRoot();
25558
- return globalRoot ? [join5(globalRoot, bareName, "package.json")] : [];
25642
+ return globalRoot ? [join6(globalRoot, bareName, "package.json")] : [];
25559
25643
  })(),
25560
- join5(homedir4(), ".roy-agent", "node_modules", bareName, "package.json")
25644
+ join6(homedir4(), ".roy-agent", "node_modules", bareName, "package.json")
25561
25645
  ];
25562
25646
  for (const pkgPath of searchPaths) {
25563
25647
  try {
25564
- if (existsSync4(pkgPath)) {
25565
- const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
25648
+ if (existsSync5(pkgPath)) {
25649
+ const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
25566
25650
  return {
25567
25651
  version: pkg.version ?? "0.0.0",
25568
25652
  name: pkg.name ?? bareName,
@@ -25584,19 +25668,6 @@ function getNpmGlobalRoot() {
25584
25668
  }
25585
25669
  return null;
25586
25670
  }
25587
- function cleanupStaleCpCopy(packageName) {
25588
- const cpDir = join5(homedir4(), ".roy-agent", "node_modules", packageName);
25589
- if (!existsSync4(cpDir)) {
25590
- return false;
25591
- }
25592
- try {
25593
- rmSync(cpDir, { recursive: true, force: true });
25594
- return true;
25595
- } catch (err) {
25596
- console.warn(`⚠️ Failed to clean stale cp copy at '${cpDir}': ${err}`);
25597
- return false;
25598
- }
25599
- }
25600
25671
  async function verifyInstalledVersion(packageName, declaredVersion) {
25601
25672
  const actual = readPackageInfo(packageName);
25602
25673
  if (!actual || !actual.version) {
@@ -25608,15 +25679,15 @@ async function verifyInstalledVersion(packageName, declaredVersion) {
25608
25679
  return { ok: true, actualVersion: actual.version };
25609
25680
  }
25610
25681
  function getPackageManagerCommand() {
25611
- if (existsSync4(join5(process.cwd(), "pnpm-lock.yaml"))) {
25612
- if (existsSync4(join5(process.cwd(), "pnpm-workspace.yaml"))) {
25682
+ if (existsSync5(join6(process.cwd(), "pnpm-lock.yaml"))) {
25683
+ if (existsSync5(join6(process.cwd(), "pnpm-workspace.yaml"))) {
25613
25684
  return "pnpm -w";
25614
25685
  }
25615
25686
  return "pnpm";
25616
25687
  }
25617
- if (existsSync4(join5(process.cwd(), "yarn.lock")))
25688
+ if (existsSync5(join6(process.cwd(), "yarn.lock")))
25618
25689
  return "yarn";
25619
- if (existsSync4(join5(process.cwd(), "bun.lock")) || existsSync4(join5(process.cwd(), "bun.lockb")))
25690
+ if (existsSync5(join6(process.cwd(), "bun.lock")) || existsSync5(join6(process.cwd(), "bun.lockb")))
25620
25691
  return "bun";
25621
25692
  return "npm";
25622
25693
  }
@@ -25655,14 +25726,14 @@ var InstallPackageCommand = {
25655
25726
  }
25656
25727
  resolvedName = info2.name;
25657
25728
  const srcDir = resolve(packageName);
25658
- if (!existsSync4(srcDir)) {
25729
+ if (!existsSync5(srcDir)) {
25659
25730
  console.error(`
25660
25731
  ❌ Local path '${srcDir}' does not exist.
25661
25732
  `);
25662
25733
  process.exit(1);
25663
25734
  }
25664
- const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
25665
- if (!existsSync4(pluginDir)) {
25735
+ const pluginDir = join6(process.cwd(), ".roy", "plugins", resolvedName);
25736
+ if (!existsSync5(pluginDir)) {
25666
25737
  mkdirSync(pluginDir, { recursive: true });
25667
25738
  }
25668
25739
  const result = spawnSync("cp", ["-r", `${srcDir}/.`, pluginDir], {
@@ -25697,12 +25768,12 @@ var InstallPackageCommand = {
25697
25768
  process.exit(1);
25698
25769
  }
25699
25770
  resolvedName = info2.name;
25700
- const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
25701
- if (!existsSync4(pluginDir)) {
25771
+ const pluginDir = join6(process.cwd(), ".roy", "plugins", resolvedName);
25772
+ if (!existsSync5(pluginDir)) {
25702
25773
  mkdirSync(pluginDir, { recursive: true });
25703
25774
  }
25704
- const nmPath = join5(process.cwd(), "node_modules", packageName);
25705
- if (existsSync4(nmPath)) {
25775
+ const nmPath = join6(process.cwd(), "node_modules", packageName);
25776
+ if (existsSync5(nmPath)) {
25706
25777
  spawnSync("cp", ["-r", `${nmPath}/.`, pluginDir], { stdio: "inherit", shell: false });
25707
25778
  }
25708
25779
  }
@@ -25722,11 +25793,24 @@ var InstallPackageCommand = {
25722
25793
  }
25723
25794
  const tmpInfo = readPackageInfo(packageName);
25724
25795
  if (tmpInfo) {
25725
- const cleaned = cleanupStaleCpCopy(tmpInfo.name);
25726
- if (cleaned) {
25796
+ const cleanupResult = cleanupStalePluginCopies(tmpInfo.name, {
25797
+ globalVersion: tmpInfo.version,
25798
+ homedir: homedir4()
25799
+ });
25800
+ if (cleanupResult.cleaned.length > 0) {
25727
25801
  console.log(`
25728
- \uD83E\uDDF9 Cleaned stale cp copy: ~/.roy-agent/node_modules/${tmpInfo.name}
25729
- `);
25802
+ \uD83E\uDDF9 Cleaned stale plugin copies:`);
25803
+ for (const path9 of cleanupResult.cleaned) {
25804
+ console.log(` - ${path9}`);
25805
+ }
25806
+ if (cleanupResult.backups.length > 0) {
25807
+ console.log(`
25808
+ \uD83D\uDCE6 Backups (for manual recovery):`);
25809
+ for (const b of cleanupResult.backups) {
25810
+ console.log(` ${b.originalPath} → ${b.backupPath}`);
25811
+ }
25812
+ }
25813
+ console.log();
25730
25814
  }
25731
25815
  }
25732
25816
  }
@@ -25851,8 +25935,8 @@ var InstallRemoveCommand = {
25851
25935
  \uD83D\uDDD1️ Removing plugin: ${plugin.packageName}@${plugin.version} (${scope})
25852
25936
  `);
25853
25937
  if (scope === "project") {
25854
- const pluginDir = join5(process.cwd(), ".roy", "plugins", plugin.packageName);
25855
- if (existsSync4(pluginDir)) {
25938
+ const pluginDir = join6(process.cwd(), ".roy", "plugins", plugin.packageName);
25939
+ if (existsSync5(pluginDir)) {
25856
25940
  spawnSync("rm", ["-rf", pluginDir], { stdio: "inherit", shell: false });
25857
25941
  console.log(` Removed plugin directory: ${pluginDir}`);
25858
25942
  }
@@ -25867,8 +25951,8 @@ var InstallRemoveCommand = {
25867
25951
  `);
25868
25952
  process.exit(result.status ?? 1);
25869
25953
  }
25870
- const globalNm = join5(homedir4(), ".roy-agent", "node_modules", plugin.packageName);
25871
- if (existsSync4(globalNm)) {
25954
+ const globalNm = join6(homedir4(), ".roy-agent", "node_modules", plugin.packageName);
25955
+ if (existsSync5(globalNm)) {
25872
25956
  spawnSync("rm", ["-rf", globalNm], { stdio: "inherit", shell: false });
25873
25957
  }
25874
25958
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-cli",
3
- "version": "1.7.16",
3
+ "version": "1.7.17",
4
4
  "type": "module",
5
5
  "description": "CLI for roy-agent - Non-interactive command execution",
6
6
  "main": "./dist/index.js",
@@ -87,4 +87,4 @@
87
87
  "bugs": {
88
88
  "url": "https://github.com/ai-setting/roy-agent/issues"
89
89
  }
90
- }
90
+ }