@ai-setting/roy-agent-cli 1.7.17 → 1.7.19
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 +271 -27
- package/dist/index.js +271 -27
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +1 -1
package/dist/bin/roy-agent.js
CHANGED
|
@@ -9461,7 +9461,7 @@ class CliQuietModeService {
|
|
|
9461
9461
|
// package.json
|
|
9462
9462
|
var package_default = {
|
|
9463
9463
|
name: "@ai-setting/roy-agent-cli",
|
|
9464
|
-
version: "1.7.
|
|
9464
|
+
version: "1.7.19",
|
|
9465
9465
|
type: "module",
|
|
9466
9466
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9467
9467
|
main: "./dist/index.js",
|
|
@@ -11294,7 +11294,8 @@ var TaskEventTypes = {
|
|
|
11294
11294
|
TASK_COMPLETED: "task.background.completed",
|
|
11295
11295
|
TASK_FAILED: "task.background.failed",
|
|
11296
11296
|
TASK_TIMEOUT: "task.background.timeout",
|
|
11297
|
-
TASK_STOPPED: "task.background.stopped"
|
|
11297
|
+
TASK_STOPPED: "task.background.stopped",
|
|
11298
|
+
TASK_ASK_USER: "task.background.ask_user"
|
|
11298
11299
|
};
|
|
11299
11300
|
var EventSourceEventTypes = {
|
|
11300
11301
|
EVENT_SOURCE_STARTED: "event-source.started",
|
|
@@ -11324,6 +11325,8 @@ class EventMessageFormatter {
|
|
|
11324
11325
|
return this.formatTaskTimeout(payload);
|
|
11325
11326
|
case TaskEventTypes.TASK_STOPPED:
|
|
11326
11327
|
return this.formatTaskStopped(payload);
|
|
11328
|
+
case TaskEventTypes.TASK_ASK_USER:
|
|
11329
|
+
return this.formatTaskAskUser(payload);
|
|
11327
11330
|
case EventSourceEventTypes.EVENT_SOURCE_STARTED:
|
|
11328
11331
|
return this.formatEventSourceStarted(payload);
|
|
11329
11332
|
case EventSourceEventTypes.EVENT_SOURCE_STOPPED:
|
|
@@ -11431,6 +11434,34 @@ Task #${taskId}`;
|
|
|
11431
11434
|
message += this.appendSubSessionId(payload);
|
|
11432
11435
|
return message;
|
|
11433
11436
|
}
|
|
11437
|
+
formatTaskAskUser(payload) {
|
|
11438
|
+
const desc = payload.description || "未命名任务";
|
|
11439
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
11440
|
+
const subSessionId = payload.subSessionId || "";
|
|
11441
|
+
const query = payload.query || "(空问题)";
|
|
11442
|
+
let message = `${this.prefix} ❓ 后台子代理「${desc}」请求用户输入`;
|
|
11443
|
+
if (bgProcessId) {
|
|
11444
|
+
message += `
|
|
11445
|
+
bgprocess: ${bgProcessId}`;
|
|
11446
|
+
}
|
|
11447
|
+
if (subSessionId) {
|
|
11448
|
+
message += `
|
|
11449
|
+
subSessionId: ${subSessionId}`;
|
|
11450
|
+
}
|
|
11451
|
+
message += `
|
|
11452
|
+
|
|
11453
|
+
${query}`;
|
|
11454
|
+
if (payload.hints && payload.hints.length > 0) {
|
|
11455
|
+
message += `
|
|
11456
|
+
|
|
11457
|
+
[\uD83E\uDD16 Agent 操作提示]`;
|
|
11458
|
+
for (const hint of payload.hints) {
|
|
11459
|
+
message += `
|
|
11460
|
+
${hint}`;
|
|
11461
|
+
}
|
|
11462
|
+
}
|
|
11463
|
+
return message;
|
|
11464
|
+
}
|
|
11434
11465
|
appendSubSessionId(payload) {
|
|
11435
11466
|
if (payload.subSessionId) {
|
|
11436
11467
|
return `
|
|
@@ -12108,6 +12139,52 @@ async function shutdownInteractiveSteps(deps) {
|
|
|
12108
12139
|
}
|
|
12109
12140
|
}
|
|
12110
12141
|
|
|
12142
|
+
// src/commands/lifecycle.ts
|
|
12143
|
+
var DEFAULT_LOGGER = {
|
|
12144
|
+
warn: (msg) => console.error(`[shutdown] ${msg}`)
|
|
12145
|
+
};
|
|
12146
|
+
function registerShutdownHandlers(cleanup, options = {}) {
|
|
12147
|
+
const logger5 = options.logger ?? DEFAULT_LOGGER;
|
|
12148
|
+
const exitCode = options.exitCode ?? 0;
|
|
12149
|
+
const shutdownMessage = options.shutdownMessage ?? "Cleaning up...";
|
|
12150
|
+
let shuttingDown = false;
|
|
12151
|
+
const shutdown = async (signal) => {
|
|
12152
|
+
if (shuttingDown) {
|
|
12153
|
+
return;
|
|
12154
|
+
}
|
|
12155
|
+
shuttingDown = true;
|
|
12156
|
+
try {
|
|
12157
|
+
logger5.debug?.(`[${signal}] ${shutdownMessage}`);
|
|
12158
|
+
} catch {}
|
|
12159
|
+
if (cleanup) {
|
|
12160
|
+
try {
|
|
12161
|
+
await cleanup();
|
|
12162
|
+
} catch (err) {
|
|
12163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12164
|
+
try {
|
|
12165
|
+
logger5.warn(`Cleanup failed: ${message}`);
|
|
12166
|
+
} catch {
|
|
12167
|
+
try {
|
|
12168
|
+
process.stderr.write(`[shutdown] Cleanup failed: ${message}
|
|
12169
|
+
`);
|
|
12170
|
+
} catch {}
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
try {
|
|
12175
|
+
process.exit(exitCode);
|
|
12176
|
+
} catch {}
|
|
12177
|
+
};
|
|
12178
|
+
process.on("SIGINT", shutdown);
|
|
12179
|
+
process.on("SIGTERM", shutdown);
|
|
12180
|
+
return {
|
|
12181
|
+
dispose: () => {
|
|
12182
|
+
process.removeListener("SIGINT", shutdown);
|
|
12183
|
+
process.removeListener("SIGTERM", shutdown);
|
|
12184
|
+
}
|
|
12185
|
+
};
|
|
12186
|
+
}
|
|
12187
|
+
|
|
12111
12188
|
// src/commands/interactive.ts
|
|
12112
12189
|
import { AskUserError, cascadeStopSessionTree } from "@ai-setting/roy-agent-core";
|
|
12113
12190
|
|
|
@@ -12793,10 +12870,23 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12793
12870
|
}
|
|
12794
12871
|
}
|
|
12795
12872
|
const agentFromEvent = envEvent.metadata?.agent;
|
|
12873
|
+
let envEventForAgent = envEvent;
|
|
12874
|
+
const eventReplyChannel = envEvent?.metadata?.replyChannel;
|
|
12875
|
+
if (eventReplyChannel) {
|
|
12876
|
+
this.lastReplyChannel = eventReplyChannel;
|
|
12877
|
+
} else if (this.lastReplyChannel) {
|
|
12878
|
+
envEventForAgent = {
|
|
12879
|
+
...envEvent,
|
|
12880
|
+
metadata: {
|
|
12881
|
+
...envEvent?.metadata ?? {},
|
|
12882
|
+
replyChannel: this.lastReplyChannel
|
|
12883
|
+
}
|
|
12884
|
+
};
|
|
12885
|
+
}
|
|
12796
12886
|
this.currentAgentContext = {
|
|
12797
12887
|
agentType: agentFromEvent,
|
|
12798
12888
|
pluginEnabled,
|
|
12799
|
-
envEvent,
|
|
12889
|
+
envEvent: envEventForAgent,
|
|
12800
12890
|
plugins,
|
|
12801
12891
|
eventSessionId,
|
|
12802
12892
|
systemPrompt: envEvent.metadata?.systemPrompt
|
|
@@ -12804,6 +12894,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12804
12894
|
await this.executeInternal(message, { showPrompt: true });
|
|
12805
12895
|
}
|
|
12806
12896
|
currentAgentContext = undefined;
|
|
12897
|
+
lastReplyChannel = undefined;
|
|
12807
12898
|
isIdle() {
|
|
12808
12899
|
return !this.isExecuting;
|
|
12809
12900
|
}
|
|
@@ -13453,6 +13544,22 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13453
13544
|
});
|
|
13454
13545
|
}
|
|
13455
13546
|
}, env);
|
|
13547
|
+
registerShutdownHandlers(async () => {
|
|
13548
|
+
await shutdownInteractiveSteps({
|
|
13549
|
+
memoryPluginDispose,
|
|
13550
|
+
memoryPluginInstance,
|
|
13551
|
+
lspManagerDispose,
|
|
13552
|
+
pluginAdapterDispose,
|
|
13553
|
+
eventHandler,
|
|
13554
|
+
queryExecutor,
|
|
13555
|
+
env,
|
|
13556
|
+
envService,
|
|
13557
|
+
shouldDisposeEnvService,
|
|
13558
|
+
output,
|
|
13559
|
+
logger: logger5,
|
|
13560
|
+
console
|
|
13561
|
+
});
|
|
13562
|
+
});
|
|
13456
13563
|
const eventHandler = new EventHandler({
|
|
13457
13564
|
env,
|
|
13458
13565
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
@@ -13682,9 +13789,9 @@ var App = ({
|
|
|
13682
13789
|
}, undefined, true, undefined, this),
|
|
13683
13790
|
/* @__PURE__ */ jsxDEV6(Static2, {
|
|
13684
13791
|
items: history,
|
|
13685
|
-
children: (item) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13792
|
+
children: (item, index) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13686
13793
|
item
|
|
13687
|
-
}, `${item.role}:${
|
|
13794
|
+
}, item.id ?? `${item.role}:${index}`, false, undefined, this)
|
|
13688
13795
|
}, undefined, false, undefined, this),
|
|
13689
13796
|
status === "thinking" ? /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13690
13797
|
marginBottom: 1,
|
|
@@ -13965,6 +14072,7 @@ var RunScreen = ({
|
|
|
13965
14072
|
const assistantTurnCountRef = useRef2(0);
|
|
13966
14073
|
const isProcessingRef = useRef2(0);
|
|
13967
14074
|
const executeQueryRef = useRef2(null);
|
|
14075
|
+
const historyIdRef = useRef2(0);
|
|
13968
14076
|
const width = process.stdout.columns ?? 80;
|
|
13969
14077
|
const doExit = useCallback4(() => {
|
|
13970
14078
|
onExit?.();
|
|
@@ -13983,15 +14091,20 @@ var RunScreen = ({
|
|
|
13983
14091
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
13984
14092
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
13985
14093
|
stream.finish();
|
|
13986
|
-
|
|
14094
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14095
|
+
setHistory((h) => [
|
|
14096
|
+
...h,
|
|
14097
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14098
|
+
]);
|
|
13987
14099
|
assistantTurnCountRef.current += 1;
|
|
13988
14100
|
} catch (err) {
|
|
13989
14101
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13990
14102
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
13991
14103
|
setErrorMessage(msg);
|
|
14104
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
13992
14105
|
setHistory((h) => [
|
|
13993
14106
|
...h,
|
|
13994
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14107
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
13995
14108
|
]);
|
|
13996
14109
|
} finally {
|
|
13997
14110
|
isProcessingRef.current -= 1;
|
|
@@ -14004,9 +14117,10 @@ var RunScreen = ({
|
|
|
14004
14117
|
if (!onRegisterHandlers)
|
|
14005
14118
|
return;
|
|
14006
14119
|
const handleNotification = async (message, _envEvent) => {
|
|
14120
|
+
const notifId = `h${++historyIdRef.current}`;
|
|
14007
14121
|
setHistory((h) => [
|
|
14008
14122
|
...h,
|
|
14009
|
-
{ role: "tool", content: `\uD83D\uDCE2 ${message}
|
|
14123
|
+
{ role: "tool", content: `\uD83D\uDCE2 ${message}`, id: notifId }
|
|
14010
14124
|
]);
|
|
14011
14125
|
if (executeQueryRef.current) {
|
|
14012
14126
|
await executeQueryRef.current(message);
|
|
@@ -14030,10 +14144,12 @@ var RunScreen = ({
|
|
|
14030
14144
|
};
|
|
14031
14145
|
const result = dispatchSlashCommand(trimmed, slashCtx);
|
|
14032
14146
|
if (result.kind === "exit") {
|
|
14147
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14148
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14033
14149
|
setHistory((h) => [
|
|
14034
14150
|
...h,
|
|
14035
|
-
{ role: "user", content: trimmed },
|
|
14036
|
-
{ role: "tool", content: "\uD83D\uDC4B Goodbye!" }
|
|
14151
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14152
|
+
{ role: "tool", content: "\uD83D\uDC4B Goodbye!", id: toolId }
|
|
14037
14153
|
]);
|
|
14038
14154
|
doExit();
|
|
14039
14155
|
return;
|
|
@@ -14047,35 +14163,46 @@ var RunScreen = ({
|
|
|
14047
14163
|
setErrorMessage(null);
|
|
14048
14164
|
return;
|
|
14049
14165
|
}
|
|
14166
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14167
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14050
14168
|
setHistory((h) => [
|
|
14051
14169
|
...h,
|
|
14052
|
-
{ role: "user", content: trimmed },
|
|
14053
|
-
{ role: "tool", content: result.message }
|
|
14170
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14171
|
+
{ role: "tool", content: result.message, id: toolId }
|
|
14054
14172
|
]);
|
|
14055
14173
|
return;
|
|
14056
14174
|
}
|
|
14057
14175
|
if (result.kind === "unknown") {
|
|
14176
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14177
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14058
14178
|
setHistory((h) => [
|
|
14059
14179
|
...h,
|
|
14060
|
-
{ role: "user", content: trimmed },
|
|
14061
|
-
{ role: "tool", content: `⚠ ${result.message}
|
|
14180
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14181
|
+
{ role: "tool", content: `⚠ ${result.message}`, id: toolId }
|
|
14062
14182
|
]);
|
|
14063
14183
|
return;
|
|
14064
14184
|
}
|
|
14065
14185
|
if (result.kind === "set-max-lines") {
|
|
14066
14186
|
setMaxLines(result.value);
|
|
14187
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14188
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14067
14189
|
setHistory((h) => [
|
|
14068
14190
|
...h,
|
|
14069
|
-
{ role: "user", content: trimmed },
|
|
14191
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14070
14192
|
{
|
|
14071
14193
|
role: "tool",
|
|
14072
|
-
content: `max-lines set to ${result.value}
|
|
14194
|
+
content: `max-lines set to ${result.value}`,
|
|
14195
|
+
id: toolId
|
|
14073
14196
|
}
|
|
14074
14197
|
]);
|
|
14075
14198
|
return;
|
|
14076
14199
|
}
|
|
14077
14200
|
setErrorMessage(null);
|
|
14078
|
-
|
|
14201
|
+
const userId = `h${++historyIdRef.current}`;
|
|
14202
|
+
setHistory((h) => [
|
|
14203
|
+
...h,
|
|
14204
|
+
{ role: "user", content: trimmed, id: userId }
|
|
14205
|
+
]);
|
|
14079
14206
|
setUserHistory((uh) => [trimmed, ...uh]);
|
|
14080
14207
|
userTurnCountRef.current += 1;
|
|
14081
14208
|
await executeQuery(trimmed);
|
|
@@ -14128,6 +14255,89 @@ var RunTui_default = RunScreen;
|
|
|
14128
14255
|
|
|
14129
14256
|
// src/commands/run.ts
|
|
14130
14257
|
init_markdown();
|
|
14258
|
+
|
|
14259
|
+
// src/commands/run-shutdown.ts
|
|
14260
|
+
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
14261
|
+
async function shutdownRunSteps(deps) {
|
|
14262
|
+
const {
|
|
14263
|
+
lspManagerDispose,
|
|
14264
|
+
pluginAdapterDispose,
|
|
14265
|
+
stopEventHandler,
|
|
14266
|
+
stopTaskEventHandler,
|
|
14267
|
+
queryExecutor,
|
|
14268
|
+
env,
|
|
14269
|
+
envService,
|
|
14270
|
+
shouldDisposeEnvService,
|
|
14271
|
+
output,
|
|
14272
|
+
logger: logger6
|
|
14273
|
+
} = deps;
|
|
14274
|
+
try {
|
|
14275
|
+
stopEventHandler();
|
|
14276
|
+
} catch (err) {
|
|
14277
|
+
logger6?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
14278
|
+
}
|
|
14279
|
+
try {
|
|
14280
|
+
stopTaskEventHandler();
|
|
14281
|
+
} catch (err) {
|
|
14282
|
+
logger6?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
14283
|
+
}
|
|
14284
|
+
if (lspManagerDispose) {
|
|
14285
|
+
try {
|
|
14286
|
+
await lspManagerDispose();
|
|
14287
|
+
} catch (err) {
|
|
14288
|
+
logger6?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
14289
|
+
}
|
|
14290
|
+
}
|
|
14291
|
+
if (pluginAdapterDispose) {
|
|
14292
|
+
try {
|
|
14293
|
+
await pluginAdapterDispose();
|
|
14294
|
+
} catch (err) {
|
|
14295
|
+
logger6?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
14296
|
+
}
|
|
14297
|
+
}
|
|
14298
|
+
try {
|
|
14299
|
+
queryExecutor.dispose();
|
|
14300
|
+
} catch (err) {
|
|
14301
|
+
logger6?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
14302
|
+
}
|
|
14303
|
+
try {
|
|
14304
|
+
const eventSourceComponent = env.getComponent("event-source");
|
|
14305
|
+
if (eventSourceComponent) {
|
|
14306
|
+
const sources = eventSourceComponent.list?.();
|
|
14307
|
+
if (sources && sources.length > 0) {
|
|
14308
|
+
for (const source of sources) {
|
|
14309
|
+
const status = eventSourceComponent.getStatus?.(source.id);
|
|
14310
|
+
logger6?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
14311
|
+
if (status !== "stopped" && status !== "created") {
|
|
14312
|
+
try {
|
|
14313
|
+
await eventSourceComponent.stopSource(source.id);
|
|
14314
|
+
output?.info?.(`✓ 已停止事件源: ${source.name} (${status})`);
|
|
14315
|
+
} catch (error) {
|
|
14316
|
+
output?.warn?.(`⚠️ 停止事件源 ${source.name} 失败: ${error}`);
|
|
14317
|
+
}
|
|
14318
|
+
}
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
}
|
|
14322
|
+
} catch (err) {
|
|
14323
|
+
logger6?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
14324
|
+
}
|
|
14325
|
+
if (shouldDisposeEnvService) {
|
|
14326
|
+
try {
|
|
14327
|
+
await envService.dispose();
|
|
14328
|
+
} catch (err) {
|
|
14329
|
+
logger6?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
14330
|
+
}
|
|
14331
|
+
}
|
|
14332
|
+
try {
|
|
14333
|
+
await TempFileManager3.getInstance().cleanupAll();
|
|
14334
|
+
logger6?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
14335
|
+
} catch (err) {
|
|
14336
|
+
logger6?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
14337
|
+
}
|
|
14338
|
+
}
|
|
14339
|
+
|
|
14340
|
+
// src/commands/run.ts
|
|
14131
14341
|
async function loadHandleQuery(options, hooks) {
|
|
14132
14342
|
const quiet = CliQuietModeService.getInstance().isQuiet();
|
|
14133
14343
|
const output = new OutputService2;
|
|
@@ -14237,7 +14447,8 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14237
14447
|
eventSourceSystemPrompt,
|
|
14238
14448
|
sessionComponent,
|
|
14239
14449
|
eventHandler,
|
|
14240
|
-
taskEventHandler
|
|
14450
|
+
taskEventHandler,
|
|
14451
|
+
sessionManager
|
|
14241
14452
|
};
|
|
14242
14453
|
}
|
|
14243
14454
|
function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext, eventSourceSystemPrompt) {
|
|
@@ -14353,16 +14564,33 @@ function createRunCommand() {
|
|
|
14353
14564
|
};
|
|
14354
14565
|
const {
|
|
14355
14566
|
handleQuery,
|
|
14567
|
+
envService,
|
|
14568
|
+
env,
|
|
14356
14569
|
queryExecutor,
|
|
14357
14570
|
sessionId,
|
|
14358
14571
|
agentContext,
|
|
14359
14572
|
eventSourceSystemPrompt,
|
|
14360
14573
|
eventHandler,
|
|
14361
|
-
taskEventHandler
|
|
14574
|
+
taskEventHandler,
|
|
14575
|
+
sessionManager: _sessionManager
|
|
14362
14576
|
} = await loadHandleQuery(argv, {
|
|
14363
14577
|
isIdle: () => runState.isIdle(),
|
|
14364
14578
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
14365
14579
|
});
|
|
14580
|
+
const shutdownHandle = registerShutdownHandlers(async () => {
|
|
14581
|
+
await shutdownRunSteps({
|
|
14582
|
+
lspManagerDispose: null,
|
|
14583
|
+
pluginAdapterDispose: null,
|
|
14584
|
+
stopEventHandler,
|
|
14585
|
+
stopTaskEventHandler,
|
|
14586
|
+
queryExecutor,
|
|
14587
|
+
env,
|
|
14588
|
+
envService,
|
|
14589
|
+
shouldDisposeEnvService: true,
|
|
14590
|
+
output: undefined,
|
|
14591
|
+
logger: undefined
|
|
14592
|
+
});
|
|
14593
|
+
});
|
|
14366
14594
|
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt);
|
|
14367
14595
|
const stopEventHandler = eventHandler.start();
|
|
14368
14596
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
@@ -14382,9 +14610,19 @@ function createRunCommand() {
|
|
|
14382
14610
|
try {
|
|
14383
14611
|
await waitUntilExit();
|
|
14384
14612
|
} finally {
|
|
14385
|
-
|
|
14386
|
-
|
|
14387
|
-
|
|
14613
|
+
shutdownHandle.dispose();
|
|
14614
|
+
await shutdownRunSteps({
|
|
14615
|
+
lspManagerDispose: null,
|
|
14616
|
+
pluginAdapterDispose: null,
|
|
14617
|
+
stopEventHandler,
|
|
14618
|
+
stopTaskEventHandler,
|
|
14619
|
+
queryExecutor,
|
|
14620
|
+
env,
|
|
14621
|
+
envService,
|
|
14622
|
+
shouldDisposeEnvService: true,
|
|
14623
|
+
output: undefined,
|
|
14624
|
+
logger: undefined
|
|
14625
|
+
});
|
|
14388
14626
|
process.exit(0);
|
|
14389
14627
|
}
|
|
14390
14628
|
}
|
|
@@ -14397,7 +14635,7 @@ import React8 from "react";
|
|
|
14397
14635
|
import { render as render2 } from "ink";
|
|
14398
14636
|
|
|
14399
14637
|
// src/ChatTui.tsx
|
|
14400
|
-
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
14638
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
14401
14639
|
import { Box as Box7, useApp as useApp3 } from "ink";
|
|
14402
14640
|
init_markdown();
|
|
14403
14641
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
@@ -14411,8 +14649,9 @@ var ChatScreen = ({
|
|
|
14411
14649
|
markdownEnabled: markdownEnabled2
|
|
14412
14650
|
}) => {
|
|
14413
14651
|
const [history, setHistory] = useState7([
|
|
14414
|
-
{ role: "user", content: message }
|
|
14652
|
+
{ role: "user", content: message, id: "h-init-1" }
|
|
14415
14653
|
]);
|
|
14654
|
+
const historyIdRef = useRef3(1);
|
|
14416
14655
|
const stream = useStreamingAccumulator();
|
|
14417
14656
|
const { exit } = useApp3();
|
|
14418
14657
|
const width = process.stdout.columns ?? 80;
|
|
@@ -14432,16 +14671,21 @@ var ChatScreen = ({
|
|
|
14432
14671
|
stream.finish();
|
|
14433
14672
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
14434
14673
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
14435
|
-
|
|
14674
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14675
|
+
setHistory((h) => [
|
|
14676
|
+
...h,
|
|
14677
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14678
|
+
]);
|
|
14436
14679
|
setTimeout(() => exit(), 100);
|
|
14437
14680
|
} catch (err) {
|
|
14438
14681
|
if (cancelled)
|
|
14439
14682
|
return;
|
|
14440
14683
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14441
14684
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
14685
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
14442
14686
|
setHistory((h) => [
|
|
14443
14687
|
...h,
|
|
14444
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14688
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
14445
14689
|
]);
|
|
14446
14690
|
setTimeout(() => exit(), 100);
|
|
14447
14691
|
}
|
|
@@ -23495,7 +23739,7 @@ var WorkflowAddCommand = {
|
|
|
23495
23739
|
process.exit(1);
|
|
23496
23740
|
}
|
|
23497
23741
|
if (!agentComponent.getAgent("workflow-extract")) {
|
|
23498
|
-
output.error("Built-in 'workflow-extract' agent is not available.
|
|
23742
|
+
output.error("Built-in 'workflow-extract' agent is not available. ");
|
|
23499
23743
|
process.exit(1);
|
|
23500
23744
|
}
|
|
23501
23745
|
const prompt = `## 任务
|
package/dist/index.js
CHANGED
|
@@ -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.19",
|
|
9464
9464
|
type: "module",
|
|
9465
9465
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9466
9466
|
main: "./dist/index.js",
|
|
@@ -11293,7 +11293,8 @@ var TaskEventTypes = {
|
|
|
11293
11293
|
TASK_COMPLETED: "task.background.completed",
|
|
11294
11294
|
TASK_FAILED: "task.background.failed",
|
|
11295
11295
|
TASK_TIMEOUT: "task.background.timeout",
|
|
11296
|
-
TASK_STOPPED: "task.background.stopped"
|
|
11296
|
+
TASK_STOPPED: "task.background.stopped",
|
|
11297
|
+
TASK_ASK_USER: "task.background.ask_user"
|
|
11297
11298
|
};
|
|
11298
11299
|
var EventSourceEventTypes = {
|
|
11299
11300
|
EVENT_SOURCE_STARTED: "event-source.started",
|
|
@@ -11323,6 +11324,8 @@ class EventMessageFormatter {
|
|
|
11323
11324
|
return this.formatTaskTimeout(payload);
|
|
11324
11325
|
case TaskEventTypes.TASK_STOPPED:
|
|
11325
11326
|
return this.formatTaskStopped(payload);
|
|
11327
|
+
case TaskEventTypes.TASK_ASK_USER:
|
|
11328
|
+
return this.formatTaskAskUser(payload);
|
|
11326
11329
|
case EventSourceEventTypes.EVENT_SOURCE_STARTED:
|
|
11327
11330
|
return this.formatEventSourceStarted(payload);
|
|
11328
11331
|
case EventSourceEventTypes.EVENT_SOURCE_STOPPED:
|
|
@@ -11430,6 +11433,34 @@ Task #${taskId}`;
|
|
|
11430
11433
|
message += this.appendSubSessionId(payload);
|
|
11431
11434
|
return message;
|
|
11432
11435
|
}
|
|
11436
|
+
formatTaskAskUser(payload) {
|
|
11437
|
+
const desc = payload.description || "未命名任务";
|
|
11438
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
11439
|
+
const subSessionId = payload.subSessionId || "";
|
|
11440
|
+
const query = payload.query || "(空问题)";
|
|
11441
|
+
let message = `${this.prefix} ❓ 后台子代理「${desc}」请求用户输入`;
|
|
11442
|
+
if (bgProcessId) {
|
|
11443
|
+
message += `
|
|
11444
|
+
bgprocess: ${bgProcessId}`;
|
|
11445
|
+
}
|
|
11446
|
+
if (subSessionId) {
|
|
11447
|
+
message += `
|
|
11448
|
+
subSessionId: ${subSessionId}`;
|
|
11449
|
+
}
|
|
11450
|
+
message += `
|
|
11451
|
+
|
|
11452
|
+
${query}`;
|
|
11453
|
+
if (payload.hints && payload.hints.length > 0) {
|
|
11454
|
+
message += `
|
|
11455
|
+
|
|
11456
|
+
[\uD83E\uDD16 Agent 操作提示]`;
|
|
11457
|
+
for (const hint of payload.hints) {
|
|
11458
|
+
message += `
|
|
11459
|
+
${hint}`;
|
|
11460
|
+
}
|
|
11461
|
+
}
|
|
11462
|
+
return message;
|
|
11463
|
+
}
|
|
11433
11464
|
appendSubSessionId(payload) {
|
|
11434
11465
|
if (payload.subSessionId) {
|
|
11435
11466
|
return `
|
|
@@ -12107,6 +12138,52 @@ async function shutdownInteractiveSteps(deps) {
|
|
|
12107
12138
|
}
|
|
12108
12139
|
}
|
|
12109
12140
|
|
|
12141
|
+
// src/commands/lifecycle.ts
|
|
12142
|
+
var DEFAULT_LOGGER = {
|
|
12143
|
+
warn: (msg) => console.error(`[shutdown] ${msg}`)
|
|
12144
|
+
};
|
|
12145
|
+
function registerShutdownHandlers(cleanup, options = {}) {
|
|
12146
|
+
const logger5 = options.logger ?? DEFAULT_LOGGER;
|
|
12147
|
+
const exitCode = options.exitCode ?? 0;
|
|
12148
|
+
const shutdownMessage = options.shutdownMessage ?? "Cleaning up...";
|
|
12149
|
+
let shuttingDown = false;
|
|
12150
|
+
const shutdown = async (signal) => {
|
|
12151
|
+
if (shuttingDown) {
|
|
12152
|
+
return;
|
|
12153
|
+
}
|
|
12154
|
+
shuttingDown = true;
|
|
12155
|
+
try {
|
|
12156
|
+
logger5.debug?.(`[${signal}] ${shutdownMessage}`);
|
|
12157
|
+
} catch {}
|
|
12158
|
+
if (cleanup) {
|
|
12159
|
+
try {
|
|
12160
|
+
await cleanup();
|
|
12161
|
+
} catch (err) {
|
|
12162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12163
|
+
try {
|
|
12164
|
+
logger5.warn(`Cleanup failed: ${message}`);
|
|
12165
|
+
} catch {
|
|
12166
|
+
try {
|
|
12167
|
+
process.stderr.write(`[shutdown] Cleanup failed: ${message}
|
|
12168
|
+
`);
|
|
12169
|
+
} catch {}
|
|
12170
|
+
}
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
try {
|
|
12174
|
+
process.exit(exitCode);
|
|
12175
|
+
} catch {}
|
|
12176
|
+
};
|
|
12177
|
+
process.on("SIGINT", shutdown);
|
|
12178
|
+
process.on("SIGTERM", shutdown);
|
|
12179
|
+
return {
|
|
12180
|
+
dispose: () => {
|
|
12181
|
+
process.removeListener("SIGINT", shutdown);
|
|
12182
|
+
process.removeListener("SIGTERM", shutdown);
|
|
12183
|
+
}
|
|
12184
|
+
};
|
|
12185
|
+
}
|
|
12186
|
+
|
|
12110
12187
|
// src/commands/interactive.ts
|
|
12111
12188
|
import { AskUserError, cascadeStopSessionTree } from "@ai-setting/roy-agent-core";
|
|
12112
12189
|
|
|
@@ -12792,10 +12869,23 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12792
12869
|
}
|
|
12793
12870
|
}
|
|
12794
12871
|
const agentFromEvent = envEvent.metadata?.agent;
|
|
12872
|
+
let envEventForAgent = envEvent;
|
|
12873
|
+
const eventReplyChannel = envEvent?.metadata?.replyChannel;
|
|
12874
|
+
if (eventReplyChannel) {
|
|
12875
|
+
this.lastReplyChannel = eventReplyChannel;
|
|
12876
|
+
} else if (this.lastReplyChannel) {
|
|
12877
|
+
envEventForAgent = {
|
|
12878
|
+
...envEvent,
|
|
12879
|
+
metadata: {
|
|
12880
|
+
...envEvent?.metadata ?? {},
|
|
12881
|
+
replyChannel: this.lastReplyChannel
|
|
12882
|
+
}
|
|
12883
|
+
};
|
|
12884
|
+
}
|
|
12795
12885
|
this.currentAgentContext = {
|
|
12796
12886
|
agentType: agentFromEvent,
|
|
12797
12887
|
pluginEnabled,
|
|
12798
|
-
envEvent,
|
|
12888
|
+
envEvent: envEventForAgent,
|
|
12799
12889
|
plugins,
|
|
12800
12890
|
eventSessionId,
|
|
12801
12891
|
systemPrompt: envEvent.metadata?.systemPrompt
|
|
@@ -12803,6 +12893,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12803
12893
|
await this.executeInternal(message, { showPrompt: true });
|
|
12804
12894
|
}
|
|
12805
12895
|
currentAgentContext = undefined;
|
|
12896
|
+
lastReplyChannel = undefined;
|
|
12806
12897
|
isIdle() {
|
|
12807
12898
|
return !this.isExecuting;
|
|
12808
12899
|
}
|
|
@@ -13452,6 +13543,22 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13452
13543
|
});
|
|
13453
13544
|
}
|
|
13454
13545
|
}, env);
|
|
13546
|
+
registerShutdownHandlers(async () => {
|
|
13547
|
+
await shutdownInteractiveSteps({
|
|
13548
|
+
memoryPluginDispose,
|
|
13549
|
+
memoryPluginInstance,
|
|
13550
|
+
lspManagerDispose,
|
|
13551
|
+
pluginAdapterDispose,
|
|
13552
|
+
eventHandler,
|
|
13553
|
+
queryExecutor,
|
|
13554
|
+
env,
|
|
13555
|
+
envService,
|
|
13556
|
+
shouldDisposeEnvService,
|
|
13557
|
+
output,
|
|
13558
|
+
logger: logger5,
|
|
13559
|
+
console
|
|
13560
|
+
});
|
|
13561
|
+
});
|
|
13455
13562
|
const eventHandler = new EventHandler({
|
|
13456
13563
|
env,
|
|
13457
13564
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
@@ -13681,9 +13788,9 @@ var App = ({
|
|
|
13681
13788
|
}, undefined, true, undefined, this),
|
|
13682
13789
|
/* @__PURE__ */ jsxDEV6(Static2, {
|
|
13683
13790
|
items: history,
|
|
13684
|
-
children: (item) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13791
|
+
children: (item, index) => /* @__PURE__ */ jsxDEV6(HistoryEntry, {
|
|
13685
13792
|
item
|
|
13686
|
-
}, `${item.role}:${
|
|
13793
|
+
}, item.id ?? `${item.role}:${index}`, false, undefined, this)
|
|
13687
13794
|
}, undefined, false, undefined, this),
|
|
13688
13795
|
status === "thinking" ? /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13689
13796
|
marginBottom: 1,
|
|
@@ -13964,6 +14071,7 @@ var RunScreen = ({
|
|
|
13964
14071
|
const assistantTurnCountRef = useRef2(0);
|
|
13965
14072
|
const isProcessingRef = useRef2(0);
|
|
13966
14073
|
const executeQueryRef = useRef2(null);
|
|
14074
|
+
const historyIdRef = useRef2(0);
|
|
13967
14075
|
const width = process.stdout.columns ?? 80;
|
|
13968
14076
|
const doExit = useCallback4(() => {
|
|
13969
14077
|
onExit?.();
|
|
@@ -13982,15 +14090,20 @@ var RunScreen = ({
|
|
|
13982
14090
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
13983
14091
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
13984
14092
|
stream.finish();
|
|
13985
|
-
|
|
14093
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14094
|
+
setHistory((h) => [
|
|
14095
|
+
...h,
|
|
14096
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14097
|
+
]);
|
|
13986
14098
|
assistantTurnCountRef.current += 1;
|
|
13987
14099
|
} catch (err) {
|
|
13988
14100
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13989
14101
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
13990
14102
|
setErrorMessage(msg);
|
|
14103
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
13991
14104
|
setHistory((h) => [
|
|
13992
14105
|
...h,
|
|
13993
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14106
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
13994
14107
|
]);
|
|
13995
14108
|
} finally {
|
|
13996
14109
|
isProcessingRef.current -= 1;
|
|
@@ -14003,9 +14116,10 @@ var RunScreen = ({
|
|
|
14003
14116
|
if (!onRegisterHandlers)
|
|
14004
14117
|
return;
|
|
14005
14118
|
const handleNotification = async (message, _envEvent) => {
|
|
14119
|
+
const notifId = `h${++historyIdRef.current}`;
|
|
14006
14120
|
setHistory((h) => [
|
|
14007
14121
|
...h,
|
|
14008
|
-
{ role: "tool", content: `\uD83D\uDCE2 ${message}
|
|
14122
|
+
{ role: "tool", content: `\uD83D\uDCE2 ${message}`, id: notifId }
|
|
14009
14123
|
]);
|
|
14010
14124
|
if (executeQueryRef.current) {
|
|
14011
14125
|
await executeQueryRef.current(message);
|
|
@@ -14029,10 +14143,12 @@ var RunScreen = ({
|
|
|
14029
14143
|
};
|
|
14030
14144
|
const result = dispatchSlashCommand(trimmed, slashCtx);
|
|
14031
14145
|
if (result.kind === "exit") {
|
|
14146
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14147
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14032
14148
|
setHistory((h) => [
|
|
14033
14149
|
...h,
|
|
14034
|
-
{ role: "user", content: trimmed },
|
|
14035
|
-
{ role: "tool", content: "\uD83D\uDC4B Goodbye!" }
|
|
14150
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14151
|
+
{ role: "tool", content: "\uD83D\uDC4B Goodbye!", id: toolId }
|
|
14036
14152
|
]);
|
|
14037
14153
|
doExit();
|
|
14038
14154
|
return;
|
|
@@ -14046,35 +14162,46 @@ var RunScreen = ({
|
|
|
14046
14162
|
setErrorMessage(null);
|
|
14047
14163
|
return;
|
|
14048
14164
|
}
|
|
14165
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14166
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14049
14167
|
setHistory((h) => [
|
|
14050
14168
|
...h,
|
|
14051
|
-
{ role: "user", content: trimmed },
|
|
14052
|
-
{ role: "tool", content: result.message }
|
|
14169
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14170
|
+
{ role: "tool", content: result.message, id: toolId }
|
|
14053
14171
|
]);
|
|
14054
14172
|
return;
|
|
14055
14173
|
}
|
|
14056
14174
|
if (result.kind === "unknown") {
|
|
14175
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14176
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14057
14177
|
setHistory((h) => [
|
|
14058
14178
|
...h,
|
|
14059
|
-
{ role: "user", content: trimmed },
|
|
14060
|
-
{ role: "tool", content: `⚠ ${result.message}
|
|
14179
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14180
|
+
{ role: "tool", content: `⚠ ${result.message}`, id: toolId }
|
|
14061
14181
|
]);
|
|
14062
14182
|
return;
|
|
14063
14183
|
}
|
|
14064
14184
|
if (result.kind === "set-max-lines") {
|
|
14065
14185
|
setMaxLines(result.value);
|
|
14186
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14187
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14066
14188
|
setHistory((h) => [
|
|
14067
14189
|
...h,
|
|
14068
|
-
{ role: "user", content: trimmed },
|
|
14190
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14069
14191
|
{
|
|
14070
14192
|
role: "tool",
|
|
14071
|
-
content: `max-lines set to ${result.value}
|
|
14193
|
+
content: `max-lines set to ${result.value}`,
|
|
14194
|
+
id: toolId
|
|
14072
14195
|
}
|
|
14073
14196
|
]);
|
|
14074
14197
|
return;
|
|
14075
14198
|
}
|
|
14076
14199
|
setErrorMessage(null);
|
|
14077
|
-
|
|
14200
|
+
const userId = `h${++historyIdRef.current}`;
|
|
14201
|
+
setHistory((h) => [
|
|
14202
|
+
...h,
|
|
14203
|
+
{ role: "user", content: trimmed, id: userId }
|
|
14204
|
+
]);
|
|
14078
14205
|
setUserHistory((uh) => [trimmed, ...uh]);
|
|
14079
14206
|
userTurnCountRef.current += 1;
|
|
14080
14207
|
await executeQuery(trimmed);
|
|
@@ -14127,6 +14254,89 @@ var RunTui_default = RunScreen;
|
|
|
14127
14254
|
|
|
14128
14255
|
// src/commands/run.ts
|
|
14129
14256
|
init_markdown();
|
|
14257
|
+
|
|
14258
|
+
// src/commands/run-shutdown.ts
|
|
14259
|
+
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
14260
|
+
async function shutdownRunSteps(deps) {
|
|
14261
|
+
const {
|
|
14262
|
+
lspManagerDispose,
|
|
14263
|
+
pluginAdapterDispose,
|
|
14264
|
+
stopEventHandler,
|
|
14265
|
+
stopTaskEventHandler,
|
|
14266
|
+
queryExecutor,
|
|
14267
|
+
env,
|
|
14268
|
+
envService,
|
|
14269
|
+
shouldDisposeEnvService,
|
|
14270
|
+
output,
|
|
14271
|
+
logger: logger6
|
|
14272
|
+
} = deps;
|
|
14273
|
+
try {
|
|
14274
|
+
stopEventHandler();
|
|
14275
|
+
} catch (err) {
|
|
14276
|
+
logger6?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
14277
|
+
}
|
|
14278
|
+
try {
|
|
14279
|
+
stopTaskEventHandler();
|
|
14280
|
+
} catch (err) {
|
|
14281
|
+
logger6?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
14282
|
+
}
|
|
14283
|
+
if (lspManagerDispose) {
|
|
14284
|
+
try {
|
|
14285
|
+
await lspManagerDispose();
|
|
14286
|
+
} catch (err) {
|
|
14287
|
+
logger6?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
14288
|
+
}
|
|
14289
|
+
}
|
|
14290
|
+
if (pluginAdapterDispose) {
|
|
14291
|
+
try {
|
|
14292
|
+
await pluginAdapterDispose();
|
|
14293
|
+
} catch (err) {
|
|
14294
|
+
logger6?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
14295
|
+
}
|
|
14296
|
+
}
|
|
14297
|
+
try {
|
|
14298
|
+
queryExecutor.dispose();
|
|
14299
|
+
} catch (err) {
|
|
14300
|
+
logger6?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
14301
|
+
}
|
|
14302
|
+
try {
|
|
14303
|
+
const eventSourceComponent = env.getComponent("event-source");
|
|
14304
|
+
if (eventSourceComponent) {
|
|
14305
|
+
const sources = eventSourceComponent.list?.();
|
|
14306
|
+
if (sources && sources.length > 0) {
|
|
14307
|
+
for (const source of sources) {
|
|
14308
|
+
const status = eventSourceComponent.getStatus?.(source.id);
|
|
14309
|
+
logger6?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
14310
|
+
if (status !== "stopped" && status !== "created") {
|
|
14311
|
+
try {
|
|
14312
|
+
await eventSourceComponent.stopSource(source.id);
|
|
14313
|
+
output?.info?.(`✓ 已停止事件源: ${source.name} (${status})`);
|
|
14314
|
+
} catch (error) {
|
|
14315
|
+
output?.warn?.(`⚠️ 停止事件源 ${source.name} 失败: ${error}`);
|
|
14316
|
+
}
|
|
14317
|
+
}
|
|
14318
|
+
}
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
} catch (err) {
|
|
14322
|
+
logger6?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
14323
|
+
}
|
|
14324
|
+
if (shouldDisposeEnvService) {
|
|
14325
|
+
try {
|
|
14326
|
+
await envService.dispose();
|
|
14327
|
+
} catch (err) {
|
|
14328
|
+
logger6?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
14329
|
+
}
|
|
14330
|
+
}
|
|
14331
|
+
try {
|
|
14332
|
+
await TempFileManager3.getInstance().cleanupAll();
|
|
14333
|
+
logger6?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
14334
|
+
} catch (err) {
|
|
14335
|
+
logger6?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
14336
|
+
}
|
|
14337
|
+
}
|
|
14338
|
+
|
|
14339
|
+
// src/commands/run.ts
|
|
14130
14340
|
async function loadHandleQuery(options, hooks) {
|
|
14131
14341
|
const quiet = CliQuietModeService.getInstance().isQuiet();
|
|
14132
14342
|
const output = new OutputService2;
|
|
@@ -14236,7 +14446,8 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14236
14446
|
eventSourceSystemPrompt,
|
|
14237
14447
|
sessionComponent,
|
|
14238
14448
|
eventHandler,
|
|
14239
|
-
taskEventHandler
|
|
14449
|
+
taskEventHandler,
|
|
14450
|
+
sessionManager
|
|
14240
14451
|
};
|
|
14241
14452
|
}
|
|
14242
14453
|
function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext, eventSourceSystemPrompt) {
|
|
@@ -14352,16 +14563,33 @@ function createRunCommand() {
|
|
|
14352
14563
|
};
|
|
14353
14564
|
const {
|
|
14354
14565
|
handleQuery,
|
|
14566
|
+
envService,
|
|
14567
|
+
env,
|
|
14355
14568
|
queryExecutor,
|
|
14356
14569
|
sessionId,
|
|
14357
14570
|
agentContext,
|
|
14358
14571
|
eventSourceSystemPrompt,
|
|
14359
14572
|
eventHandler,
|
|
14360
|
-
taskEventHandler
|
|
14573
|
+
taskEventHandler,
|
|
14574
|
+
sessionManager: _sessionManager
|
|
14361
14575
|
} = await loadHandleQuery(argv, {
|
|
14362
14576
|
isIdle: () => runState.isIdle(),
|
|
14363
14577
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
14364
14578
|
});
|
|
14579
|
+
const shutdownHandle = registerShutdownHandlers(async () => {
|
|
14580
|
+
await shutdownRunSteps({
|
|
14581
|
+
lspManagerDispose: null,
|
|
14582
|
+
pluginAdapterDispose: null,
|
|
14583
|
+
stopEventHandler,
|
|
14584
|
+
stopTaskEventHandler,
|
|
14585
|
+
queryExecutor,
|
|
14586
|
+
env,
|
|
14587
|
+
envService,
|
|
14588
|
+
shouldDisposeEnvService: true,
|
|
14589
|
+
output: undefined,
|
|
14590
|
+
logger: undefined
|
|
14591
|
+
});
|
|
14592
|
+
});
|
|
14365
14593
|
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt);
|
|
14366
14594
|
const stopEventHandler = eventHandler.start();
|
|
14367
14595
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
@@ -14381,9 +14609,19 @@ function createRunCommand() {
|
|
|
14381
14609
|
try {
|
|
14382
14610
|
await waitUntilExit();
|
|
14383
14611
|
} finally {
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
14612
|
+
shutdownHandle.dispose();
|
|
14613
|
+
await shutdownRunSteps({
|
|
14614
|
+
lspManagerDispose: null,
|
|
14615
|
+
pluginAdapterDispose: null,
|
|
14616
|
+
stopEventHandler,
|
|
14617
|
+
stopTaskEventHandler,
|
|
14618
|
+
queryExecutor,
|
|
14619
|
+
env,
|
|
14620
|
+
envService,
|
|
14621
|
+
shouldDisposeEnvService: true,
|
|
14622
|
+
output: undefined,
|
|
14623
|
+
logger: undefined
|
|
14624
|
+
});
|
|
14387
14625
|
process.exit(0);
|
|
14388
14626
|
}
|
|
14389
14627
|
}
|
|
@@ -14396,7 +14634,7 @@ import React8 from "react";
|
|
|
14396
14634
|
import { render as render2 } from "ink";
|
|
14397
14635
|
|
|
14398
14636
|
// src/ChatTui.tsx
|
|
14399
|
-
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
14637
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
14400
14638
|
import { Box as Box7, useApp as useApp3 } from "ink";
|
|
14401
14639
|
init_markdown();
|
|
14402
14640
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
@@ -14410,8 +14648,9 @@ var ChatScreen = ({
|
|
|
14410
14648
|
markdownEnabled: markdownEnabled2
|
|
14411
14649
|
}) => {
|
|
14412
14650
|
const [history, setHistory] = useState7([
|
|
14413
|
-
{ role: "user", content: message }
|
|
14651
|
+
{ role: "user", content: message, id: "h-init-1" }
|
|
14414
14652
|
]);
|
|
14653
|
+
const historyIdRef = useRef3(1);
|
|
14415
14654
|
const stream = useStreamingAccumulator();
|
|
14416
14655
|
const { exit } = useApp3();
|
|
14417
14656
|
const width = process.stdout.columns ?? 80;
|
|
@@ -14431,16 +14670,21 @@ var ChatScreen = ({
|
|
|
14431
14670
|
stream.finish();
|
|
14432
14671
|
const rendered = markdownEnabled2 ? renderMarkdown(responseText, { width }) : responseText;
|
|
14433
14672
|
const finalText = truncateForTerminal(rendered, maxLines);
|
|
14434
|
-
|
|
14673
|
+
const assistantId = `h${++historyIdRef.current}`;
|
|
14674
|
+
setHistory((h) => [
|
|
14675
|
+
...h,
|
|
14676
|
+
{ role: "assistant", content: finalText, id: assistantId }
|
|
14677
|
+
]);
|
|
14435
14678
|
setTimeout(() => exit(), 100);
|
|
14436
14679
|
} catch (err) {
|
|
14437
14680
|
if (cancelled)
|
|
14438
14681
|
return;
|
|
14439
14682
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14440
14683
|
stream.fail(err instanceof Error ? err : new Error(msg));
|
|
14684
|
+
const errorId = `h${++historyIdRef.current}`;
|
|
14441
14685
|
setHistory((h) => [
|
|
14442
14686
|
...h,
|
|
14443
|
-
{ role: "tool", content: `❌ Error: ${msg}
|
|
14687
|
+
{ role: "tool", content: `❌ Error: ${msg}`, id: errorId }
|
|
14444
14688
|
]);
|
|
14445
14689
|
setTimeout(() => exit(), 100);
|
|
14446
14690
|
}
|
|
@@ -23494,7 +23738,7 @@ var WorkflowAddCommand = {
|
|
|
23494
23738
|
process.exit(1);
|
|
23495
23739
|
}
|
|
23496
23740
|
if (!agentComponent.getAgent("workflow-extract")) {
|
|
23497
|
-
output.error("Built-in 'workflow-extract' agent is not available.
|
|
23741
|
+
output.error("Built-in 'workflow-extract' agent is not available. ");
|
|
23498
23742
|
process.exit(1);
|
|
23499
23743
|
}
|
|
23500
23744
|
const prompt = `## 任务
|
|
Binary file
|