@ai-setting/roy-agent-cli 1.7.16 → 1.7.18
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 +11415 -46001
- package/dist/index.js +408 -125
- 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.18",
|
|
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,23 +12090,69 @@ 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
|
|
|
12110
|
+
// src/commands/lifecycle.ts
|
|
12111
|
+
var DEFAULT_LOGGER = {
|
|
12112
|
+
warn: (msg) => console.error(`[shutdown] ${msg}`)
|
|
12113
|
+
};
|
|
12114
|
+
function registerShutdownHandlers(cleanup, options = {}) {
|
|
12115
|
+
const logger5 = options.logger ?? DEFAULT_LOGGER;
|
|
12116
|
+
const exitCode = options.exitCode ?? 0;
|
|
12117
|
+
const shutdownMessage = options.shutdownMessage ?? "Cleaning up...";
|
|
12118
|
+
let shuttingDown = false;
|
|
12119
|
+
const shutdown = async (signal) => {
|
|
12120
|
+
if (shuttingDown) {
|
|
12121
|
+
return;
|
|
12122
|
+
}
|
|
12123
|
+
shuttingDown = true;
|
|
12124
|
+
try {
|
|
12125
|
+
logger5.debug?.(`[${signal}] ${shutdownMessage}`);
|
|
12126
|
+
} catch {}
|
|
12127
|
+
if (cleanup) {
|
|
12128
|
+
try {
|
|
12129
|
+
await cleanup();
|
|
12130
|
+
} catch (err) {
|
|
12131
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12132
|
+
try {
|
|
12133
|
+
logger5.warn(`Cleanup failed: ${message}`);
|
|
12134
|
+
} catch {
|
|
12135
|
+
try {
|
|
12136
|
+
process.stderr.write(`[shutdown] Cleanup failed: ${message}
|
|
12137
|
+
`);
|
|
12138
|
+
} catch {}
|
|
12139
|
+
}
|
|
12140
|
+
}
|
|
12141
|
+
}
|
|
12142
|
+
try {
|
|
12143
|
+
process.exit(exitCode);
|
|
12144
|
+
} catch {}
|
|
12145
|
+
};
|
|
12146
|
+
process.on("SIGINT", shutdown);
|
|
12147
|
+
process.on("SIGTERM", shutdown);
|
|
12148
|
+
return {
|
|
12149
|
+
dispose: () => {
|
|
12150
|
+
process.removeListener("SIGINT", shutdown);
|
|
12151
|
+
process.removeListener("SIGTERM", shutdown);
|
|
12152
|
+
}
|
|
12153
|
+
};
|
|
12154
|
+
}
|
|
12155
|
+
|
|
12108
12156
|
// src/commands/interactive.ts
|
|
12109
12157
|
import { AskUserError, cascadeStopSessionTree } from "@ai-setting/roy-agent-core";
|
|
12110
12158
|
|
|
@@ -12291,7 +12339,7 @@ var COLOR_BY_STATUS = {
|
|
|
12291
12339
|
busy: COLORS.accent
|
|
12292
12340
|
};
|
|
12293
12341
|
// src/commands/interactive.ts
|
|
12294
|
-
var
|
|
12342
|
+
var logger5 = createLogger6("cli:interactive");
|
|
12295
12343
|
var USER_PROMPT = COLORS.accent("❯ ");
|
|
12296
12344
|
|
|
12297
12345
|
class REPL {
|
|
@@ -12483,10 +12531,10 @@ ${COLORS.system("[正在中断...]")}`);
|
|
|
12483
12531
|
const agentComponent = this.env.getComponent("agent");
|
|
12484
12532
|
if (agentComponent?.abortAll) {
|
|
12485
12533
|
agentComponent.abortAll();
|
|
12486
|
-
|
|
12534
|
+
logger5.debug("[/abort] AgentComponent.abortAll() called");
|
|
12487
12535
|
} else if (agentComponent?.abort) {
|
|
12488
12536
|
agentComponent.abort("default");
|
|
12489
|
-
|
|
12537
|
+
logger5.debug("[/abort] AgentComponent.abort('default') called (fallback)");
|
|
12490
12538
|
}
|
|
12491
12539
|
}
|
|
12492
12540
|
abortStream();
|
|
@@ -12581,7 +12629,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
12581
12629
|
try {
|
|
12582
12630
|
await this.options.onAfterExecute(this.lastUsage);
|
|
12583
12631
|
} catch (hookError) {
|
|
12584
|
-
|
|
12632
|
+
logger5.warn("onAfterExecute hook failed (ink path)", { error: String(hookError) });
|
|
12585
12633
|
}
|
|
12586
12634
|
}
|
|
12587
12635
|
} catch (err) {
|
|
@@ -12601,7 +12649,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
12601
12649
|
await this.shutdown();
|
|
12602
12650
|
resolve();
|
|
12603
12651
|
}).catch(async (err) => {
|
|
12604
|
-
|
|
12652
|
+
logger5.error("ink REPL render failed", { error: String(err) });
|
|
12605
12653
|
await this.shutdown();
|
|
12606
12654
|
resolve();
|
|
12607
12655
|
});
|
|
@@ -12658,7 +12706,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
12658
12706
|
}
|
|
12659
12707
|
if (key.name === "escape") {
|
|
12660
12708
|
this.handleEscKey().catch((err) => {
|
|
12661
|
-
|
|
12709
|
+
logger5.warn(`[Esc] handleEscKey failed: ${err}`);
|
|
12662
12710
|
});
|
|
12663
12711
|
}
|
|
12664
12712
|
};
|
|
@@ -12853,7 +12901,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12853
12901
|
try {
|
|
12854
12902
|
await this.options.onAfterExecute(this.lastUsage);
|
|
12855
12903
|
} catch (hookError) {
|
|
12856
|
-
|
|
12904
|
+
logger5.warn("onAfterExecute hook failed", { error: String(hookError) });
|
|
12857
12905
|
}
|
|
12858
12906
|
}
|
|
12859
12907
|
} catch (error) {
|
|
@@ -13016,12 +13064,12 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13016
13064
|
}
|
|
13017
13065
|
async handleEscKey() {
|
|
13018
13066
|
if (this.isShuttingDown) {
|
|
13019
|
-
|
|
13067
|
+
logger5.debug("[Esc] handler entered (isShuttingDown=true) → early return");
|
|
13020
13068
|
return;
|
|
13021
13069
|
}
|
|
13022
13070
|
const mainSessionIdEarly = this.options.sessionId;
|
|
13023
13071
|
const hasActiveDescendant = mainSessionIdEarly ? hasActiveDescendants(this.env, mainSessionIdEarly) : false;
|
|
13024
|
-
|
|
13072
|
+
logger5.debug(`[Esc] handler entered: isExecuting=${this.isExecuting} hasActiveDescendant=${hasActiveDescendant} lastEscPressTime=${this.lastEscPressTime}`);
|
|
13025
13073
|
const now = Date.now();
|
|
13026
13074
|
const isExecuting = this.isExecuting;
|
|
13027
13075
|
const canCascade = isExecuting || hasActiveDescendant;
|
|
@@ -13030,17 +13078,17 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13030
13078
|
this.lastEscPressTime = now;
|
|
13031
13079
|
}
|
|
13032
13080
|
if (!canCascade) {
|
|
13033
|
-
|
|
13081
|
+
logger5.debug("[Esc] idle no-op: isExecuting=false, no active descendant");
|
|
13034
13082
|
return;
|
|
13035
13083
|
}
|
|
13036
13084
|
if (this.env) {
|
|
13037
13085
|
const agentComponent = this.env.getComponent("agent");
|
|
13038
13086
|
if (agentComponent?.abortAll) {
|
|
13039
13087
|
agentComponent.abortAll();
|
|
13040
|
-
|
|
13088
|
+
logger5.debug("[Esc] AgentComponent.abortAll() called");
|
|
13041
13089
|
} else if (agentComponent?.abort) {
|
|
13042
13090
|
agentComponent.abort("default");
|
|
13043
|
-
|
|
13091
|
+
logger5.debug("[Esc] AgentComponent.abort('default') called (fallback)");
|
|
13044
13092
|
}
|
|
13045
13093
|
}
|
|
13046
13094
|
abortStream();
|
|
@@ -13048,7 +13096,7 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13048
13096
|
try {
|
|
13049
13097
|
this.inkApi.finishAssistantStream();
|
|
13050
13098
|
} catch (err) {
|
|
13051
|
-
|
|
13099
|
+
logger5.warn("[Esc] finishAssistantStream failed", { error: String(err) });
|
|
13052
13100
|
}
|
|
13053
13101
|
}
|
|
13054
13102
|
const mainSessionId = this.options.sessionId;
|
|
@@ -13061,9 +13109,9 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13061
13109
|
timer = setTimeout(() => reject(new Error("cascade timeout 5s")), 5000);
|
|
13062
13110
|
})
|
|
13063
13111
|
]);
|
|
13064
|
-
|
|
13112
|
+
logger5.info(`[Esc] cascade stop force=${result.force} tasks=${result.stoppedTaskIds.length} workflows=${result.stoppedWorkflowSessionIds.length} errors=${result.errors.length}`);
|
|
13065
13113
|
} catch (err) {
|
|
13066
|
-
|
|
13114
|
+
logger5.warn(`[Esc] cascade stop failed: ${err}`);
|
|
13067
13115
|
} finally {
|
|
13068
13116
|
if (timer !== undefined)
|
|
13069
13117
|
clearTimeout(timer);
|
|
@@ -13445,11 +13493,27 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13445
13493
|
envService,
|
|
13446
13494
|
shouldDisposeEnvService,
|
|
13447
13495
|
output,
|
|
13448
|
-
logger:
|
|
13496
|
+
logger: logger5,
|
|
13449
13497
|
console
|
|
13450
13498
|
});
|
|
13451
13499
|
}
|
|
13452
13500
|
}, env);
|
|
13501
|
+
registerShutdownHandlers(async () => {
|
|
13502
|
+
await shutdownInteractiveSteps({
|
|
13503
|
+
memoryPluginDispose,
|
|
13504
|
+
memoryPluginInstance,
|
|
13505
|
+
lspManagerDispose,
|
|
13506
|
+
pluginAdapterDispose,
|
|
13507
|
+
eventHandler,
|
|
13508
|
+
queryExecutor,
|
|
13509
|
+
env,
|
|
13510
|
+
envService,
|
|
13511
|
+
shouldDisposeEnvService,
|
|
13512
|
+
output,
|
|
13513
|
+
logger: logger5,
|
|
13514
|
+
console
|
|
13515
|
+
});
|
|
13516
|
+
});
|
|
13453
13517
|
const eventHandler = new EventHandler({
|
|
13454
13518
|
env,
|
|
13455
13519
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
@@ -13679,9 +13743,9 @@ var App = ({
|
|
|
13679
13743
|
}, undefined, true, undefined, this),
|
|
13680
13744
|
/* @__PURE__ */ jsxDEV6(Static2, {
|
|
13681
13745
|
items: history,
|
|
13682
|
-
children: (item) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13746
|
+
children: (item, index) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13683
13747
|
item
|
|
13684
|
-
}, `${item.role}:${
|
|
13748
|
+
}, item.id ?? `${item.role}:${index}`, false, undefined, this)
|
|
13685
13749
|
}, undefined, false, undefined, this),
|
|
13686
13750
|
status === "thinking" ? /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13687
13751
|
marginBottom: 1,
|
|
@@ -13962,6 +14026,7 @@ var RunScreen = ({
|
|
|
13962
14026
|
const assistantTurnCountRef = useRef2(0);
|
|
13963
14027
|
const isProcessingRef = useRef2(0);
|
|
13964
14028
|
const executeQueryRef = useRef2(null);
|
|
14029
|
+
const historyIdRef = useRef2(0);
|
|
13965
14030
|
const width = process.stdout.columns ?? 80;
|
|
13966
14031
|
const doExit = useCallback4(() => {
|
|
13967
14032
|
onExit?.();
|
|
@@ -13980,15 +14045,20 @@ var RunScreen = ({
|
|
|
13980
14045
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
13981
14046
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
13982
14047
|
stream.finish();
|
|
13983
|
-
|
|
14048
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14049
|
+
setHistory((h) => [
|
|
14050
|
+
...h,
|
|
14051
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14052
|
+
]);
|
|
13984
14053
|
assistantTurnCountRef.current += 1;
|
|
13985
14054
|
} catch (err) {
|
|
13986
14055
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13987
14056
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
13988
14057
|
setErrorMessage(msg);
|
|
14058
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
13989
14059
|
setHistory((h) => [
|
|
13990
14060
|
...h,
|
|
13991
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14061
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
13992
14062
|
]);
|
|
13993
14063
|
} finally {
|
|
13994
14064
|
isProcessingRef.current -= 1;
|
|
@@ -14001,9 +14071,10 @@ var RunScreen = ({
|
|
|
14001
14071
|
if (!onRegisterHandlers)
|
|
14002
14072
|
return;
|
|
14003
14073
|
const handleNotification = async (message, _envEvent) => {
|
|
14074
|
+
const notifId = `h${++historyIdRef.current}`;
|
|
14004
14075
|
setHistory((h) => [
|
|
14005
14076
|
...h,
|
|
14006
|
-
{ role: "tool", content: `\uD83D\uDCE2 ${message}
|
|
14077
|
+
{ role: "tool", content: `\uD83D\uDCE2 ${message}`, id: notifId }
|
|
14007
14078
|
]);
|
|
14008
14079
|
if (executeQueryRef.current) {
|
|
14009
14080
|
await executeQueryRef.current(message);
|
|
@@ -14027,10 +14098,12 @@ var RunScreen = ({
|
|
|
14027
14098
|
};
|
|
14028
14099
|
const result = dispatchSlashCommand(trimmed, slashCtx);
|
|
14029
14100
|
if (result.kind === "exit") {
|
|
14101
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14102
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14030
14103
|
setHistory((h) => [
|
|
14031
14104
|
...h,
|
|
14032
|
-
{ role: "user", content: trimmed },
|
|
14033
|
-
{ role: "tool", content: "\uD83D\uDC4B Goodbye!" }
|
|
14105
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14106
|
+
{ role: "tool", content: "\uD83D\uDC4B Goodbye!", id: toolId }
|
|
14034
14107
|
]);
|
|
14035
14108
|
doExit();
|
|
14036
14109
|
return;
|
|
@@ -14044,35 +14117,46 @@ var RunScreen = ({
|
|
|
14044
14117
|
setErrorMessage(null);
|
|
14045
14118
|
return;
|
|
14046
14119
|
}
|
|
14120
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14121
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14047
14122
|
setHistory((h) => [
|
|
14048
14123
|
...h,
|
|
14049
|
-
{ role: "user", content: trimmed },
|
|
14050
|
-
{ role: "tool", content: result.message }
|
|
14124
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14125
|
+
{ role: "tool", content: result.message, id: toolId }
|
|
14051
14126
|
]);
|
|
14052
14127
|
return;
|
|
14053
14128
|
}
|
|
14054
14129
|
if (result.kind === "unknown") {
|
|
14130
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14131
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14055
14132
|
setHistory((h) => [
|
|
14056
14133
|
...h,
|
|
14057
|
-
{ role: "user", content: trimmed },
|
|
14058
|
-
{ role: "tool", content: `⚠ ${result.message}
|
|
14134
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14135
|
+
{ role: "tool", content: `⚠ ${result.message}`, id: toolId }
|
|
14059
14136
|
]);
|
|
14060
14137
|
return;
|
|
14061
14138
|
}
|
|
14062
14139
|
if (result.kind === "set-max-lines") {
|
|
14063
14140
|
setMaxLines(result.value);
|
|
14141
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14142
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14064
14143
|
setHistory((h) => [
|
|
14065
14144
|
...h,
|
|
14066
|
-
{ role: "user", content: trimmed },
|
|
14145
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14067
14146
|
{
|
|
14068
14147
|
role: "tool",
|
|
14069
|
-
content: `max-lines set to ${result.value}
|
|
14148
|
+
content: `max-lines set to ${result.value}`,
|
|
14149
|
+
id: toolId
|
|
14070
14150
|
}
|
|
14071
14151
|
]);
|
|
14072
14152
|
return;
|
|
14073
14153
|
}
|
|
14074
14154
|
setErrorMessage(null);
|
|
14075
|
-
|
|
14155
|
+
const userId = `h${++historyIdRef.current}`;
|
|
14156
|
+
setHistory((h) => [
|
|
14157
|
+
...h,
|
|
14158
|
+
{ role: "user", content: trimmed, id: userId }
|
|
14159
|
+
]);
|
|
14076
14160
|
setUserHistory((uh) => [trimmed, ...uh]);
|
|
14077
14161
|
userTurnCountRef.current += 1;
|
|
14078
14162
|
await executeQuery(trimmed);
|
|
@@ -14125,6 +14209,89 @@ var RunTui_default = RunScreen;
|
|
|
14125
14209
|
|
|
14126
14210
|
// src/commands/run.ts
|
|
14127
14211
|
init_markdown();
|
|
14212
|
+
|
|
14213
|
+
// src/commands/run-shutdown.ts
|
|
14214
|
+
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
14215
|
+
async function shutdownRunSteps(deps) {
|
|
14216
|
+
const {
|
|
14217
|
+
lspManagerDispose,
|
|
14218
|
+
pluginAdapterDispose,
|
|
14219
|
+
stopEventHandler,
|
|
14220
|
+
stopTaskEventHandler,
|
|
14221
|
+
queryExecutor,
|
|
14222
|
+
env,
|
|
14223
|
+
envService,
|
|
14224
|
+
shouldDisposeEnvService,
|
|
14225
|
+
output,
|
|
14226
|
+
logger: logger6
|
|
14227
|
+
} = deps;
|
|
14228
|
+
try {
|
|
14229
|
+
stopEventHandler();
|
|
14230
|
+
} catch (err) {
|
|
14231
|
+
logger6?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
14232
|
+
}
|
|
14233
|
+
try {
|
|
14234
|
+
stopTaskEventHandler();
|
|
14235
|
+
} catch (err) {
|
|
14236
|
+
logger6?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
14237
|
+
}
|
|
14238
|
+
if (lspManagerDispose) {
|
|
14239
|
+
try {
|
|
14240
|
+
await lspManagerDispose();
|
|
14241
|
+
} catch (err) {
|
|
14242
|
+
logger6?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
14243
|
+
}
|
|
14244
|
+
}
|
|
14245
|
+
if (pluginAdapterDispose) {
|
|
14246
|
+
try {
|
|
14247
|
+
await pluginAdapterDispose();
|
|
14248
|
+
} catch (err) {
|
|
14249
|
+
logger6?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
14250
|
+
}
|
|
14251
|
+
}
|
|
14252
|
+
try {
|
|
14253
|
+
queryExecutor.dispose();
|
|
14254
|
+
} catch (err) {
|
|
14255
|
+
logger6?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
14256
|
+
}
|
|
14257
|
+
try {
|
|
14258
|
+
const eventSourceComponent = env.getComponent("event-source");
|
|
14259
|
+
if (eventSourceComponent) {
|
|
14260
|
+
const sources = eventSourceComponent.list?.();
|
|
14261
|
+
if (sources && sources.length > 0) {
|
|
14262
|
+
for (const source of sources) {
|
|
14263
|
+
const status = eventSourceComponent.getStatus?.(source.id);
|
|
14264
|
+
logger6?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
14265
|
+
if (status !== "stopped" && status !== "created") {
|
|
14266
|
+
try {
|
|
14267
|
+
await eventSourceComponent.stopSource(source.id);
|
|
14268
|
+
output?.info?.(`✓ 已停止事件源: ${source.name} (${status})`);
|
|
14269
|
+
} catch (error) {
|
|
14270
|
+
output?.warn?.(`⚠️ 停止事件源 ${source.name} 失败: ${error}`);
|
|
14271
|
+
}
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
}
|
|
14275
|
+
}
|
|
14276
|
+
} catch (err) {
|
|
14277
|
+
logger6?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
14278
|
+
}
|
|
14279
|
+
if (shouldDisposeEnvService) {
|
|
14280
|
+
try {
|
|
14281
|
+
await envService.dispose();
|
|
14282
|
+
} catch (err) {
|
|
14283
|
+
logger6?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
14284
|
+
}
|
|
14285
|
+
}
|
|
14286
|
+
try {
|
|
14287
|
+
await TempFileManager3.getInstance().cleanupAll();
|
|
14288
|
+
logger6?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
14289
|
+
} catch (err) {
|
|
14290
|
+
logger6?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
14291
|
+
}
|
|
14292
|
+
}
|
|
14293
|
+
|
|
14294
|
+
// src/commands/run.ts
|
|
14128
14295
|
async function loadHandleQuery(options, hooks) {
|
|
14129
14296
|
const quiet = CliQuietModeService.getInstance().isQuiet();
|
|
14130
14297
|
const output = new OutputService2;
|
|
@@ -14234,7 +14401,8 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14234
14401
|
eventSourceSystemPrompt,
|
|
14235
14402
|
sessionComponent,
|
|
14236
14403
|
eventHandler,
|
|
14237
|
-
taskEventHandler
|
|
14404
|
+
taskEventHandler,
|
|
14405
|
+
sessionManager
|
|
14238
14406
|
};
|
|
14239
14407
|
}
|
|
14240
14408
|
function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext, eventSourceSystemPrompt) {
|
|
@@ -14350,16 +14518,33 @@ function createRunCommand() {
|
|
|
14350
14518
|
};
|
|
14351
14519
|
const {
|
|
14352
14520
|
handleQuery,
|
|
14521
|
+
envService,
|
|
14522
|
+
env,
|
|
14353
14523
|
queryExecutor,
|
|
14354
14524
|
sessionId,
|
|
14355
14525
|
agentContext,
|
|
14356
14526
|
eventSourceSystemPrompt,
|
|
14357
14527
|
eventHandler,
|
|
14358
|
-
taskEventHandler
|
|
14528
|
+
taskEventHandler,
|
|
14529
|
+
sessionManager: _sessionManager
|
|
14359
14530
|
} = await loadHandleQuery(argv, {
|
|
14360
14531
|
isIdle: () => runState.isIdle(),
|
|
14361
14532
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
14362
14533
|
});
|
|
14534
|
+
const shutdownHandle = registerShutdownHandlers(async () => {
|
|
14535
|
+
await shutdownRunSteps({
|
|
14536
|
+
lspManagerDispose: null,
|
|
14537
|
+
pluginAdapterDispose: null,
|
|
14538
|
+
stopEventHandler,
|
|
14539
|
+
stopTaskEventHandler,
|
|
14540
|
+
queryExecutor,
|
|
14541
|
+
env,
|
|
14542
|
+
envService,
|
|
14543
|
+
shouldDisposeEnvService: true,
|
|
14544
|
+
output: undefined,
|
|
14545
|
+
logger: undefined
|
|
14546
|
+
});
|
|
14547
|
+
});
|
|
14363
14548
|
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt);
|
|
14364
14549
|
const stopEventHandler = eventHandler.start();
|
|
14365
14550
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
@@ -14379,9 +14564,19 @@ function createRunCommand() {
|
|
|
14379
14564
|
try {
|
|
14380
14565
|
await waitUntilExit();
|
|
14381
14566
|
} finally {
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14567
|
+
shutdownHandle.dispose();
|
|
14568
|
+
await shutdownRunSteps({
|
|
14569
|
+
lspManagerDispose: null,
|
|
14570
|
+
pluginAdapterDispose: null,
|
|
14571
|
+
stopEventHandler,
|
|
14572
|
+
stopTaskEventHandler,
|
|
14573
|
+
queryExecutor,
|
|
14574
|
+
env,
|
|
14575
|
+
envService,
|
|
14576
|
+
shouldDisposeEnvService: true,
|
|
14577
|
+
output: undefined,
|
|
14578
|
+
logger: undefined
|
|
14579
|
+
});
|
|
14385
14580
|
process.exit(0);
|
|
14386
14581
|
}
|
|
14387
14582
|
}
|
|
@@ -14394,7 +14589,7 @@ import React8 from "react";
|
|
|
14394
14589
|
import { render as render2 } from "ink";
|
|
14395
14590
|
|
|
14396
14591
|
// src/ChatTui.tsx
|
|
14397
|
-
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
14592
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
14398
14593
|
import { Box as Box7, useApp as useApp3 } from "ink";
|
|
14399
14594
|
init_markdown();
|
|
14400
14595
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
@@ -14408,8 +14603,9 @@ var ChatScreen = ({
|
|
|
14408
14603
|
markdownEnabled: markdownEnabled2
|
|
14409
14604
|
}) => {
|
|
14410
14605
|
const [history, setHistory] = useState7([
|
|
14411
|
-
{ role: "user", content: message }
|
|
14606
|
+
{ role: "user", content: message, id: "h-init-1" }
|
|
14412
14607
|
]);
|
|
14608
|
+
const historyIdRef = useRef3(1);
|
|
14413
14609
|
const stream = useStreamingAccumulator();
|
|
14414
14610
|
const { exit } = useApp3();
|
|
14415
14611
|
const width = process.stdout.columns ?? 80;
|
|
@@ -14429,16 +14625,21 @@ var ChatScreen = ({
|
|
|
14429
14625
|
stream.finish();
|
|
14430
14626
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
14431
14627
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
14432
|
-
|
|
14628
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14629
|
+
setHistory((h) => [
|
|
14630
|
+
...h,
|
|
14631
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14632
|
+
]);
|
|
14433
14633
|
setTimeout(() => exit(), 100);
|
|
14434
14634
|
} catch (err) {
|
|
14435
14635
|
if (cancelled)
|
|
14436
14636
|
return;
|
|
14437
14637
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14438
14638
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
14639
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
14439
14640
|
setHistory((h) => [
|
|
14440
14641
|
...h,
|
|
14441
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14642
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
14442
14643
|
]);
|
|
14443
14644
|
setTimeout(() => exit(), 100);
|
|
14444
14645
|
}
|
|
@@ -25492,24 +25693,106 @@ var LspCommand = {
|
|
|
25492
25693
|
|
|
25493
25694
|
// src/commands/install/index.ts
|
|
25494
25695
|
import { spawnSync } from "node:child_process";
|
|
25495
|
-
import { existsSync as
|
|
25496
|
-
import { join as
|
|
25696
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync, mkdirSync, rmSync as rmSync2 } from "node:fs";
|
|
25697
|
+
import { join as join6, resolve } from "node:path";
|
|
25497
25698
|
import { homedir as homedir4 } from "node:os";
|
|
25699
|
+
|
|
25700
|
+
// src/commands/install/cleanup-stale-plugin-copies.ts
|
|
25701
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, cpSync } from "node:fs";
|
|
25702
|
+
import { join as join5 } from "node:path";
|
|
25703
|
+
import { homedir as nodeHomedir, tmpdir as nodeTmpdir } from "node:os";
|
|
25704
|
+
function cleanupStalePluginCopies(packageName, options) {
|
|
25705
|
+
const HOME = options.homedir ?? nodeHomedir();
|
|
25706
|
+
const paths = options.localNodeModulesPaths ?? [
|
|
25707
|
+
join5(HOME, "node_modules"),
|
|
25708
|
+
join5(HOME, ".roy-agent", "node_modules")
|
|
25709
|
+
];
|
|
25710
|
+
const backupRoot = options.backupDir ?? nodeTmpdir();
|
|
25711
|
+
const result = {
|
|
25712
|
+
cleaned: [],
|
|
25713
|
+
skipped: [],
|
|
25714
|
+
backups: []
|
|
25715
|
+
};
|
|
25716
|
+
if (!options.globalVersion) {
|
|
25717
|
+
for (const p of paths) {
|
|
25718
|
+
const candidate = join5(p, packageName);
|
|
25719
|
+
result.skipped.push({ path: candidate, reason: "no-global-version" });
|
|
25720
|
+
}
|
|
25721
|
+
return result;
|
|
25722
|
+
}
|
|
25723
|
+
for (const nmPath of paths) {
|
|
25724
|
+
const localPkgDir = join5(nmPath, packageName);
|
|
25725
|
+
const localPkgJson = join5(localPkgDir, "package.json");
|
|
25726
|
+
if (!existsSync4(localPkgJson)) {
|
|
25727
|
+
result.skipped.push({ path: localPkgDir, reason: "no-local-copy" });
|
|
25728
|
+
continue;
|
|
25729
|
+
}
|
|
25730
|
+
let localVersion = null;
|
|
25731
|
+
try {
|
|
25732
|
+
const pkg = JSON.parse(readFileSync3(localPkgJson, "utf-8"));
|
|
25733
|
+
localVersion = typeof pkg.version === "string" ? pkg.version : null;
|
|
25734
|
+
} catch {
|
|
25735
|
+
localVersion = null;
|
|
25736
|
+
}
|
|
25737
|
+
const shouldClean = localVersion === null || compareVersions(localVersion, options.globalVersion) < 0;
|
|
25738
|
+
if (!shouldClean) {
|
|
25739
|
+
result.skipped.push({ path: localPkgDir, reason: "local-equal-or-newer" });
|
|
25740
|
+
continue;
|
|
25741
|
+
}
|
|
25742
|
+
let backupPath = null;
|
|
25743
|
+
try {
|
|
25744
|
+
const safeName = packageName.replace(/@/g, "").replace(/[^a-zA-Z0-9._/-]/g, "-");
|
|
25745
|
+
const safeLocalVersion = (localVersion ?? "unknown").replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
25746
|
+
const timestamp = Date.now();
|
|
25747
|
+
backupPath = join5(backupRoot, `${safeName}-${safeLocalVersion}-backup-${timestamp}`);
|
|
25748
|
+
cpSync(localPkgDir, backupPath, { recursive: true });
|
|
25749
|
+
result.backups.push({ originalPath: localPkgDir, backupPath });
|
|
25750
|
+
} catch (err) {
|
|
25751
|
+
backupPath = null;
|
|
25752
|
+
console.warn(`⚠️ Failed to backup stale copy at '${localPkgDir}': ${err}`);
|
|
25753
|
+
}
|
|
25754
|
+
try {
|
|
25755
|
+
rmSync(localPkgDir, { recursive: true, force: true });
|
|
25756
|
+
result.cleaned.push(localPkgDir);
|
|
25757
|
+
} catch (err) {
|
|
25758
|
+
console.warn(`⚠️ Failed to remove stale copy at '${localPkgDir}': ${err}`);
|
|
25759
|
+
result.skipped.push({ path: localPkgDir, reason: "cleanup-failed" });
|
|
25760
|
+
if (backupPath) {
|
|
25761
|
+
console.warn(` ↪ Backup preserved at '${backupPath}' for manual recovery`);
|
|
25762
|
+
}
|
|
25763
|
+
}
|
|
25764
|
+
}
|
|
25765
|
+
return result;
|
|
25766
|
+
}
|
|
25767
|
+
function compareVersions(a, b) {
|
|
25768
|
+
const pa = a.split(".").map((s) => Number.parseInt(s, 10));
|
|
25769
|
+
const pb = b.split(".").map((s) => Number.parseInt(s, 10));
|
|
25770
|
+
for (let i = 0;i < 3; i++) {
|
|
25771
|
+
const na = Number.isFinite(pa[i]) ? pa[i] : 0;
|
|
25772
|
+
const nb = Number.isFinite(pb[i]) ? pb[i] : 0;
|
|
25773
|
+
const diff = na - nb;
|
|
25774
|
+
if (diff !== 0)
|
|
25775
|
+
return diff;
|
|
25776
|
+
}
|
|
25777
|
+
return 0;
|
|
25778
|
+
}
|
|
25779
|
+
|
|
25780
|
+
// src/commands/install/index.ts
|
|
25498
25781
|
function getConfigDir(scope) {
|
|
25499
|
-
return scope === "global" ?
|
|
25782
|
+
return scope === "global" ? join6(homedir4(), ".roy-agent") : join6(process.cwd(), ".roy");
|
|
25500
25783
|
}
|
|
25501
25784
|
function detectDefaultScope() {
|
|
25502
|
-
const projectDir =
|
|
25503
|
-
return
|
|
25785
|
+
const projectDir = join6(process.cwd(), ".roy");
|
|
25786
|
+
return existsSync5(projectDir) ? "project" : "global";
|
|
25504
25787
|
}
|
|
25505
25788
|
function getConfigPath(scope) {
|
|
25506
|
-
return
|
|
25789
|
+
return join6(getConfigDir(scope), "plugins.json");
|
|
25507
25790
|
}
|
|
25508
25791
|
function loadPlugins(scope) {
|
|
25509
25792
|
const configPath = getConfigPath(scope);
|
|
25510
25793
|
try {
|
|
25511
|
-
if (
|
|
25512
|
-
const raw =
|
|
25794
|
+
if (existsSync5(configPath)) {
|
|
25795
|
+
const raw = readFileSync4(configPath, "utf-8");
|
|
25513
25796
|
const config = JSON.parse(raw);
|
|
25514
25797
|
return config.plugins ?? [];
|
|
25515
25798
|
}
|
|
@@ -25519,7 +25802,7 @@ function loadPlugins(scope) {
|
|
|
25519
25802
|
function savePlugins(plugins, scope) {
|
|
25520
25803
|
const configDir = getConfigDir(scope);
|
|
25521
25804
|
const configPath = getConfigPath(scope);
|
|
25522
|
-
if (!
|
|
25805
|
+
if (!existsSync5(configDir)) {
|
|
25523
25806
|
mkdirSync(configDir, { recursive: true });
|
|
25524
25807
|
}
|
|
25525
25808
|
const config = { plugins };
|
|
@@ -25535,10 +25818,10 @@ function stripVersionSpec(packageName) {
|
|
|
25535
25818
|
function readPackageInfo(packageName) {
|
|
25536
25819
|
const bareName = packageName.startsWith("/") || packageName.startsWith(".") ? packageName : stripVersionSpec(packageName);
|
|
25537
25820
|
if (packageName.startsWith("/") || packageName.startsWith(".")) {
|
|
25538
|
-
const localPkgPath =
|
|
25539
|
-
if (
|
|
25821
|
+
const localPkgPath = join6(packageName, "package.json");
|
|
25822
|
+
if (existsSync5(localPkgPath)) {
|
|
25540
25823
|
try {
|
|
25541
|
-
const pkg = JSON.parse(
|
|
25824
|
+
const pkg = JSON.parse(readFileSync4(localPkgPath, "utf-8"));
|
|
25542
25825
|
return {
|
|
25543
25826
|
version: pkg.version ?? "0.0.0",
|
|
25544
25827
|
name: pkg.name ?? packageName,
|
|
@@ -25550,19 +25833,19 @@ function readPackageInfo(packageName) {
|
|
|
25550
25833
|
}
|
|
25551
25834
|
}
|
|
25552
25835
|
const searchPaths = [
|
|
25553
|
-
|
|
25836
|
+
join6(process.cwd(), "node_modules", bareName, "package.json"),
|
|
25554
25837
|
resolve(process.cwd(), "..", "node_modules", bareName, "package.json"),
|
|
25555
|
-
|
|
25838
|
+
join6(process.cwd(), ".roy", "plugins", bareName, "package.json"),
|
|
25556
25839
|
...(() => {
|
|
25557
25840
|
const globalRoot = getNpmGlobalRoot();
|
|
25558
|
-
return globalRoot ? [
|
|
25841
|
+
return globalRoot ? [join6(globalRoot, bareName, "package.json")] : [];
|
|
25559
25842
|
})(),
|
|
25560
|
-
|
|
25843
|
+
join6(homedir4(), ".roy-agent", "node_modules", bareName, "package.json")
|
|
25561
25844
|
];
|
|
25562
25845
|
for (const pkgPath of searchPaths) {
|
|
25563
25846
|
try {
|
|
25564
|
-
if (
|
|
25565
|
-
const pkg = JSON.parse(
|
|
25847
|
+
if (existsSync5(pkgPath)) {
|
|
25848
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
25566
25849
|
return {
|
|
25567
25850
|
version: pkg.version ?? "0.0.0",
|
|
25568
25851
|
name: pkg.name ?? bareName,
|
|
@@ -25584,19 +25867,6 @@ function getNpmGlobalRoot() {
|
|
|
25584
25867
|
}
|
|
25585
25868
|
return null;
|
|
25586
25869
|
}
|
|
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
25870
|
async function verifyInstalledVersion(packageName, declaredVersion) {
|
|
25601
25871
|
const actual = readPackageInfo(packageName);
|
|
25602
25872
|
if (!actual || !actual.version) {
|
|
@@ -25608,15 +25878,15 @@ async function verifyInstalledVersion(packageName, declaredVersion) {
|
|
|
25608
25878
|
return { ok: true, actualVersion: actual.version };
|
|
25609
25879
|
}
|
|
25610
25880
|
function getPackageManagerCommand() {
|
|
25611
|
-
if (
|
|
25612
|
-
if (
|
|
25881
|
+
if (existsSync5(join6(process.cwd(), "pnpm-lock.yaml"))) {
|
|
25882
|
+
if (existsSync5(join6(process.cwd(), "pnpm-workspace.yaml"))) {
|
|
25613
25883
|
return "pnpm -w";
|
|
25614
25884
|
}
|
|
25615
25885
|
return "pnpm";
|
|
25616
25886
|
}
|
|
25617
|
-
if (
|
|
25887
|
+
if (existsSync5(join6(process.cwd(), "yarn.lock")))
|
|
25618
25888
|
return "yarn";
|
|
25619
|
-
if (
|
|
25889
|
+
if (existsSync5(join6(process.cwd(), "bun.lock")) || existsSync5(join6(process.cwd(), "bun.lockb")))
|
|
25620
25890
|
return "bun";
|
|
25621
25891
|
return "npm";
|
|
25622
25892
|
}
|
|
@@ -25655,14 +25925,14 @@ var InstallPackageCommand = {
|
|
|
25655
25925
|
}
|
|
25656
25926
|
resolvedName = info2.name;
|
|
25657
25927
|
const srcDir = resolve(packageName);
|
|
25658
|
-
if (!
|
|
25928
|
+
if (!existsSync5(srcDir)) {
|
|
25659
25929
|
console.error(`
|
|
25660
25930
|
❌ Local path '${srcDir}' does not exist.
|
|
25661
25931
|
`);
|
|
25662
25932
|
process.exit(1);
|
|
25663
25933
|
}
|
|
25664
|
-
const pluginDir =
|
|
25665
|
-
if (!
|
|
25934
|
+
const pluginDir = join6(process.cwd(), ".roy", "plugins", resolvedName);
|
|
25935
|
+
if (!existsSync5(pluginDir)) {
|
|
25666
25936
|
mkdirSync(pluginDir, { recursive: true });
|
|
25667
25937
|
}
|
|
25668
25938
|
const result = spawnSync("cp", ["-r", `${srcDir}/.`, pluginDir], {
|
|
@@ -25697,12 +25967,12 @@ var InstallPackageCommand = {
|
|
|
25697
25967
|
process.exit(1);
|
|
25698
25968
|
}
|
|
25699
25969
|
resolvedName = info2.name;
|
|
25700
|
-
const pluginDir =
|
|
25701
|
-
if (!
|
|
25970
|
+
const pluginDir = join6(process.cwd(), ".roy", "plugins", resolvedName);
|
|
25971
|
+
if (!existsSync5(pluginDir)) {
|
|
25702
25972
|
mkdirSync(pluginDir, { recursive: true });
|
|
25703
25973
|
}
|
|
25704
|
-
const nmPath =
|
|
25705
|
-
if (
|
|
25974
|
+
const nmPath = join6(process.cwd(), "node_modules", packageName);
|
|
25975
|
+
if (existsSync5(nmPath)) {
|
|
25706
25976
|
spawnSync("cp", ["-r", `${nmPath}/.`, pluginDir], { stdio: "inherit", shell: false });
|
|
25707
25977
|
}
|
|
25708
25978
|
}
|
|
@@ -25722,11 +25992,24 @@ var InstallPackageCommand = {
|
|
|
25722
25992
|
}
|
|
25723
25993
|
const tmpInfo = readPackageInfo(packageName);
|
|
25724
25994
|
if (tmpInfo) {
|
|
25725
|
-
const
|
|
25726
|
-
|
|
25995
|
+
const cleanupResult = cleanupStalePluginCopies(tmpInfo.name, {
|
|
25996
|
+
globalVersion: tmpInfo.version,
|
|
25997
|
+
homedir: homedir4()
|
|
25998
|
+
});
|
|
25999
|
+
if (cleanupResult.cleaned.length > 0) {
|
|
25727
26000
|
console.log(`
|
|
25728
|
-
\uD83E\uDDF9 Cleaned stale
|
|
25729
|
-
|
|
26001
|
+
\uD83E\uDDF9 Cleaned stale plugin copies:`);
|
|
26002
|
+
for (const path9 of cleanupResult.cleaned) {
|
|
26003
|
+
console.log(` - ${path9}`);
|
|
26004
|
+
}
|
|
26005
|
+
if (cleanupResult.backups.length > 0) {
|
|
26006
|
+
console.log(`
|
|
26007
|
+
\uD83D\uDCE6 Backups (for manual recovery):`);
|
|
26008
|
+
for (const b of cleanupResult.backups) {
|
|
26009
|
+
console.log(` ${b.originalPath} → ${b.backupPath}`);
|
|
26010
|
+
}
|
|
26011
|
+
}
|
|
26012
|
+
console.log();
|
|
25730
26013
|
}
|
|
25731
26014
|
}
|
|
25732
26015
|
}
|
|
@@ -25851,8 +26134,8 @@ var InstallRemoveCommand = {
|
|
|
25851
26134
|
\uD83D\uDDD1️ Removing plugin: ${plugin.packageName}@${plugin.version} (${scope})
|
|
25852
26135
|
`);
|
|
25853
26136
|
if (scope === "project") {
|
|
25854
|
-
const pluginDir =
|
|
25855
|
-
if (
|
|
26137
|
+
const pluginDir = join6(process.cwd(), ".roy", "plugins", plugin.packageName);
|
|
26138
|
+
if (existsSync5(pluginDir)) {
|
|
25856
26139
|
spawnSync("rm", ["-rf", pluginDir], { stdio: "inherit", shell: false });
|
|
25857
26140
|
console.log(` Removed plugin directory: ${pluginDir}`);
|
|
25858
26141
|
}
|
|
@@ -25867,8 +26150,8 @@ var InstallRemoveCommand = {
|
|
|
25867
26150
|
`);
|
|
25868
26151
|
process.exit(result.status ?? 1);
|
|
25869
26152
|
}
|
|
25870
|
-
const globalNm =
|
|
25871
|
-
if (
|
|
26153
|
+
const globalNm = join6(homedir4(), ".roy-agent", "node_modules", plugin.packageName);
|
|
26154
|
+
if (existsSync5(globalNm)) {
|
|
25872
26155
|
spawnSync("rm", ["-rf", globalNm], { stdio: "inherit", shell: false });
|
|
25873
26156
|
}
|
|
25874
26157
|
}
|