@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/bin/roy-agent.js +11185 -45970
- package/dist/index.js +186 -102
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +2 -2
- package/dist/bin/roy-agent.js.map +0 -481
- package/dist/dev/bin/roy-agent.js +0 -60825
- package/dist/dev/bin/roy-agent.js.map +0 -481
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
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10443
|
+
logger4.info(`[${event.type}]`, payload);
|
|
10442
10444
|
}
|
|
10443
10445
|
}
|
|
10444
10446
|
logTaskCreated(payload) {
|
|
10445
10447
|
const task = payload.task;
|
|
10446
|
-
|
|
10447
|
-
|
|
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
|
-
|
|
10451
|
+
logger4.info(` Project: ${task.project_path}`);
|
|
10450
10452
|
}
|
|
10451
10453
|
if (task.context) {
|
|
10452
|
-
|
|
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
|
-
|
|
10459
|
-
|
|
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
|
-
|
|
10463
|
+
logger4.info(` Changes: ${JSON.stringify(changes)}`);
|
|
10462
10464
|
}
|
|
10463
10465
|
}
|
|
10464
10466
|
logTaskCompleted(payload) {
|
|
10465
10467
|
const task = payload.task;
|
|
10466
|
-
|
|
10467
|
-
|
|
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
|
-
|
|
10472
|
+
logger4.info(`\uD83D\uDDD1️ Task deleted: #${payload.taskId}`);
|
|
10471
10473
|
}
|
|
10472
10474
|
logOperationAdded(payload) {
|
|
10473
10475
|
const op = payload.operation;
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
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
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
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:
|
|
10561
|
+
logger: logger5
|
|
10560
10562
|
} = deps;
|
|
10561
|
-
const log =
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12060
|
+
logger5.warn(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
12059
12061
|
}
|
|
12060
12062
|
}
|
|
12061
12063
|
try {
|
|
12062
12064
|
eventHandler.stop();
|
|
12063
12065
|
} catch (err) {
|
|
12064
|
-
|
|
12066
|
+
logger5.warn(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
12065
12067
|
}
|
|
12066
12068
|
try {
|
|
12067
12069
|
queryExecutor.dispose();
|
|
12068
12070
|
} catch (err) {
|
|
12069
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12099
|
+
logger5.warn(`[Shutdown] envService.dispose failed: ${err}`);
|
|
12098
12100
|
}
|
|
12099
12101
|
}
|
|
12100
12102
|
try {
|
|
12101
12103
|
await TempFileManager2.getInstance().cleanupAll();
|
|
12102
|
-
|
|
12104
|
+
logger5.debug("[Shutdown] TempFileManager cleaned up");
|
|
12103
12105
|
} catch (err) {
|
|
12104
|
-
|
|
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
|
|
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
|
-
|
|
12488
|
+
logger5.debug("[/abort] AgentComponent.abortAll() called");
|
|
12487
12489
|
} else if (agentComponent?.abort) {
|
|
12488
12490
|
agentComponent.abort("default");
|
|
12489
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13042
|
+
logger5.debug("[Esc] AgentComponent.abortAll() called");
|
|
13041
13043
|
} else if (agentComponent?.abort) {
|
|
13042
13044
|
agentComponent.abort("default");
|
|
13043
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
25496
|
-
import { join as
|
|
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" ?
|
|
25583
|
+
return scope === "global" ? join6(homedir4(), ".roy-agent") : join6(process.cwd(), ".roy");
|
|
25500
25584
|
}
|
|
25501
25585
|
function detectDefaultScope() {
|
|
25502
|
-
const projectDir =
|
|
25503
|
-
return
|
|
25586
|
+
const projectDir = join6(process.cwd(), ".roy");
|
|
25587
|
+
return existsSync5(projectDir) ? "project" : "global";
|
|
25504
25588
|
}
|
|
25505
25589
|
function getConfigPath(scope) {
|
|
25506
|
-
return
|
|
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 (
|
|
25512
|
-
const raw =
|
|
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 (!
|
|
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 =
|
|
25539
|
-
if (
|
|
25622
|
+
const localPkgPath = join6(packageName, "package.json");
|
|
25623
|
+
if (existsSync5(localPkgPath)) {
|
|
25540
25624
|
try {
|
|
25541
|
-
const pkg = JSON.parse(
|
|
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
|
-
|
|
25637
|
+
join6(process.cwd(), "node_modules", bareName, "package.json"),
|
|
25554
25638
|
resolve(process.cwd(), "..", "node_modules", bareName, "package.json"),
|
|
25555
|
-
|
|
25639
|
+
join6(process.cwd(), ".roy", "plugins", bareName, "package.json"),
|
|
25556
25640
|
...(() => {
|
|
25557
25641
|
const globalRoot = getNpmGlobalRoot();
|
|
25558
|
-
return globalRoot ? [
|
|
25642
|
+
return globalRoot ? [join6(globalRoot, bareName, "package.json")] : [];
|
|
25559
25643
|
})(),
|
|
25560
|
-
|
|
25644
|
+
join6(homedir4(), ".roy-agent", "node_modules", bareName, "package.json")
|
|
25561
25645
|
];
|
|
25562
25646
|
for (const pkgPath of searchPaths) {
|
|
25563
25647
|
try {
|
|
25564
|
-
if (
|
|
25565
|
-
const pkg = JSON.parse(
|
|
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 (
|
|
25612
|
-
if (
|
|
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 (
|
|
25688
|
+
if (existsSync5(join6(process.cwd(), "yarn.lock")))
|
|
25618
25689
|
return "yarn";
|
|
25619
|
-
if (
|
|
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 (!
|
|
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 =
|
|
25665
|
-
if (!
|
|
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 =
|
|
25701
|
-
if (!
|
|
25771
|
+
const pluginDir = join6(process.cwd(), ".roy", "plugins", resolvedName);
|
|
25772
|
+
if (!existsSync5(pluginDir)) {
|
|
25702
25773
|
mkdirSync(pluginDir, { recursive: true });
|
|
25703
25774
|
}
|
|
25704
|
-
const nmPath =
|
|
25705
|
-
if (
|
|
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
|
|
25726
|
-
|
|
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
|
|
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 =
|
|
25855
|
-
if (
|
|
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 =
|
|
25871
|
-
if (
|
|
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
|
}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-setting/roy-agent-cli",
|
|
3
|
-
"version": "1.7.
|
|
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
|
+
}
|