@ai-setting/roy-agent-cli 1.7.55 → 1.7.57
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 +549 -105
- package/dist/index.js +549 -105
- package/dist/roy-agent-linux-x64/bin/roy-agent +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -364,25 +364,46 @@ var exports_stream_output_service = {};
|
|
|
364
364
|
__export(exports_stream_output_service, {
|
|
365
365
|
streamAbortSignal: () => streamAbortSignal,
|
|
366
366
|
resetStreamAbort: () => resetStreamAbort,
|
|
367
|
+
isStreamAborted: () => isStreamAborted,
|
|
367
368
|
hasNumericUsage: () => hasNumericUsage,
|
|
368
369
|
abortStream: () => abortStream,
|
|
370
|
+
__resetAllStreamAbortForTest: () => __resetAllStreamAbortForTest,
|
|
369
371
|
StreamOutputService: () => StreamOutputService,
|
|
370
372
|
COLORS: () => COLORS
|
|
371
373
|
});
|
|
372
374
|
import chalk2 from "chalk";
|
|
373
375
|
import { createLogger as createLogger2, TracedAs as TracedAs2 } from "@ai-setting/roy-agent-core";
|
|
374
|
-
function resetStreamAbort() {
|
|
375
|
-
|
|
376
|
+
function resetStreamAbort(scope) {
|
|
377
|
+
if (scope === undefined) {
|
|
378
|
+
streamAbortSignal.aborted = false;
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
abortedRuns.delete(scope);
|
|
376
382
|
}
|
|
377
|
-
function abortStream() {
|
|
378
|
-
|
|
383
|
+
function abortStream(scope) {
|
|
384
|
+
if (scope === undefined) {
|
|
385
|
+
streamAbortSignal.aborted = true;
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
abortedRuns.add(scope);
|
|
389
|
+
}
|
|
390
|
+
function isStreamAborted(scope) {
|
|
391
|
+
if (streamAbortSignal.aborted)
|
|
392
|
+
return true;
|
|
393
|
+
if (scope === undefined)
|
|
394
|
+
return false;
|
|
395
|
+
return abortedRuns.has(scope);
|
|
396
|
+
}
|
|
397
|
+
function __resetAllStreamAbortForTest() {
|
|
398
|
+
streamAbortSignal.aborted = false;
|
|
399
|
+
abortedRuns.clear();
|
|
379
400
|
}
|
|
380
401
|
function hasNumericUsage(usage) {
|
|
381
402
|
if (!usage)
|
|
382
403
|
return false;
|
|
383
404
|
return typeof usage.promptTokens === "number" || typeof usage.completionTokens === "number" || typeof usage.totalTokens === "number" || typeof usage.cacheRead === "number" || typeof usage.cacheWrite === "number" || typeof usage.promptTokensTotal === "number";
|
|
384
405
|
}
|
|
385
|
-
var logger2, COLORS, streamAbortSignal, StreamOutputService;
|
|
406
|
+
var logger2, COLORS, streamAbortSignal, abortedRuns, StreamOutputService;
|
|
386
407
|
var init_stream_output_service = __esm(() => {
|
|
387
408
|
init_markdown_renderer();
|
|
388
409
|
logger2 = createLogger2("stream-output");
|
|
@@ -405,6 +426,7 @@ var init_stream_output_service = __esm(() => {
|
|
|
405
426
|
streamAbortSignal = {
|
|
406
427
|
aborted: false
|
|
407
428
|
};
|
|
429
|
+
abortedRuns = new Set;
|
|
408
430
|
StreamOutputService = class StreamOutputService {
|
|
409
431
|
fullText = "";
|
|
410
432
|
fullReasoning = "";
|
|
@@ -420,6 +442,9 @@ var init_stream_output_service = __esm(() => {
|
|
|
420
442
|
reasoningClosedByText = false;
|
|
421
443
|
chunkCallback = undefined;
|
|
422
444
|
silent = false;
|
|
445
|
+
sessionFilter = undefined;
|
|
446
|
+
acceptsSidelessEvents = true;
|
|
447
|
+
runId = undefined;
|
|
423
448
|
constructor(options = {}) {
|
|
424
449
|
this.options = options;
|
|
425
450
|
this.silent = options.silent ?? false;
|
|
@@ -434,6 +459,15 @@ var init_stream_output_service = __esm(() => {
|
|
|
434
459
|
setChunkCallback(cb) {
|
|
435
460
|
this.chunkCallback = cb;
|
|
436
461
|
}
|
|
462
|
+
setSessionFilter(sessionId) {
|
|
463
|
+
this.sessionFilter = sessionId;
|
|
464
|
+
}
|
|
465
|
+
setAcceptsSidelessEvents(accepts) {
|
|
466
|
+
this.acceptsSidelessEvents = accepts;
|
|
467
|
+
}
|
|
468
|
+
setRunId(runId) {
|
|
469
|
+
this.runId = runId;
|
|
470
|
+
}
|
|
437
471
|
emitChunk(event) {
|
|
438
472
|
if (!this.chunkCallback)
|
|
439
473
|
return;
|
|
@@ -454,7 +488,8 @@ var init_stream_output_service = __esm(() => {
|
|
|
454
488
|
console.log(message);
|
|
455
489
|
}
|
|
456
490
|
checkAbort() {
|
|
457
|
-
|
|
491
|
+
const aborted = this.runId !== undefined ? isStreamAborted(this.runId) : streamAbortSignal.aborted;
|
|
492
|
+
if (aborted) {
|
|
458
493
|
this.logStdout(`
|
|
459
494
|
${COLORS.system("[已中断]")}
|
|
460
495
|
`);
|
|
@@ -462,7 +497,25 @@ ${COLORS.system("[已中断]")}
|
|
|
462
497
|
}
|
|
463
498
|
return false;
|
|
464
499
|
}
|
|
500
|
+
extractEventSessionId(event) {
|
|
501
|
+
const fromMeta = event?.metadata?.sessionId;
|
|
502
|
+
if (typeof fromMeta === "string" && fromMeta.length > 0)
|
|
503
|
+
return fromMeta;
|
|
504
|
+
const fromPayload = event?.payload?.metadata?.sessionId;
|
|
505
|
+
if (typeof fromPayload === "string" && fromPayload.length > 0)
|
|
506
|
+
return fromPayload;
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
465
509
|
handleEvent(event) {
|
|
510
|
+
if (this.sessionFilter !== undefined) {
|
|
511
|
+
const eventSessionId = this.extractEventSessionId(event);
|
|
512
|
+
if (eventSessionId === undefined) {
|
|
513
|
+
if (!this.acceptsSidelessEvents)
|
|
514
|
+
return;
|
|
515
|
+
} else if (eventSessionId !== this.sessionFilter) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
466
519
|
if (this.checkAbort()) {
|
|
467
520
|
return;
|
|
468
521
|
}
|
|
@@ -9585,7 +9638,7 @@ class CliQuietModeService {
|
|
|
9585
9638
|
// package.json
|
|
9586
9639
|
var package_default = {
|
|
9587
9640
|
name: "@ai-setting/roy-agent-cli",
|
|
9588
|
-
version: "1.7.
|
|
9641
|
+
version: "1.7.57",
|
|
9589
9642
|
type: "module",
|
|
9590
9643
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9591
9644
|
main: "./dist/index.js",
|
|
@@ -11238,6 +11291,9 @@ class QueryExecutor {
|
|
|
11238
11291
|
showToolResults: false
|
|
11239
11292
|
};
|
|
11240
11293
|
_pendingContextConfig = null;
|
|
11294
|
+
_pendingSessionScope = undefined;
|
|
11295
|
+
_pendingAcceptsSideless = undefined;
|
|
11296
|
+
_sidelessPolicyExplicit = false;
|
|
11241
11297
|
_pendingChunkCallback = undefined;
|
|
11242
11298
|
failureNotifier;
|
|
11243
11299
|
constructor(options) {
|
|
@@ -11276,6 +11332,14 @@ class QueryExecutor {
|
|
|
11276
11332
|
this.streamService.setChunkCallback(this._pendingChunkCallback);
|
|
11277
11333
|
this._pendingChunkCallback = undefined;
|
|
11278
11334
|
}
|
|
11335
|
+
if (this._pendingAcceptsSideless !== undefined) {
|
|
11336
|
+
this.streamService.setAcceptsSidelessEvents(this._pendingAcceptsSideless);
|
|
11337
|
+
this._pendingAcceptsSideless = undefined;
|
|
11338
|
+
}
|
|
11339
|
+
if (this._pendingSessionScope !== undefined) {
|
|
11340
|
+
this.streamService.setSessionFilter(this._pendingSessionScope);
|
|
11341
|
+
this.streamService.setRunId(this._pendingSessionScope);
|
|
11342
|
+
}
|
|
11279
11343
|
if (this._pendingContextConfig) {
|
|
11280
11344
|
this.streamService.setContextInfo(this._pendingContextConfig.contextWindow, this._pendingContextConfig.contextWindow * this._pendingContextConfig.thresholdRatio);
|
|
11281
11345
|
this._pendingContextConfig = null;
|
|
@@ -11301,6 +11365,18 @@ class QueryExecutor {
|
|
|
11301
11365
|
this._pendingChunkCallback = cb;
|
|
11302
11366
|
}
|
|
11303
11367
|
}
|
|
11368
|
+
setSessionScope(sessionId) {
|
|
11369
|
+
this._pendingSessionScope = sessionId;
|
|
11370
|
+
if (this.streamService) {
|
|
11371
|
+
this.streamService.setSessionFilter(sessionId);
|
|
11372
|
+
this.streamService.setRunId(sessionId);
|
|
11373
|
+
}
|
|
11374
|
+
}
|
|
11375
|
+
setAcceptsSidelessEvents(accepts) {
|
|
11376
|
+
this._pendingAcceptsSideless = accepts;
|
|
11377
|
+
this._sidelessPolicyExplicit = true;
|
|
11378
|
+
this.streamService?.setAcceptsSidelessEvents(accepts);
|
|
11379
|
+
}
|
|
11304
11380
|
handleEvent(event) {
|
|
11305
11381
|
if (event.type === "context.threshold_exceeded" && !this.quiet) {
|
|
11306
11382
|
const payload = event.payload;
|
|
@@ -11321,6 +11397,13 @@ class QueryExecutor {
|
|
|
11321
11397
|
showToolResults: streamOptions?.showToolResults ?? this.streamOptions.showToolResults
|
|
11322
11398
|
};
|
|
11323
11399
|
this.subscribeToEvents(options);
|
|
11400
|
+
if (sessionId) {
|
|
11401
|
+
this.streamService?.setSessionFilter(sessionId);
|
|
11402
|
+
this.streamService?.setRunId(sessionId);
|
|
11403
|
+
if (!this._sidelessPolicyExplicit) {
|
|
11404
|
+
this.streamService?.setAcceptsSidelessEvents(true);
|
|
11405
|
+
}
|
|
11406
|
+
}
|
|
11324
11407
|
this.streamService?.reset();
|
|
11325
11408
|
if (!this.quiet) {
|
|
11326
11409
|
this.output.info(`执行: ${message}`);
|
|
@@ -11695,6 +11778,10 @@ import {
|
|
|
11695
11778
|
} from "@ai-setting/roy-agent-core";
|
|
11696
11779
|
|
|
11697
11780
|
// src/commands/shared/event-handler.ts
|
|
11781
|
+
import {
|
|
11782
|
+
getEnvContext,
|
|
11783
|
+
runWithEnvContextAsync
|
|
11784
|
+
} from "@ai-setting/roy-agent-core/env";
|
|
11698
11785
|
import { TracedAs as TracedAs5 } from "@ai-setting/roy-agent-core";
|
|
11699
11786
|
import { notifyReactFailure as notifyReactFailure2 } from "@ai-setting/roy-agent-core/env/error-reply";
|
|
11700
11787
|
function parseLarkPerTaskChatId(contextJson) {
|
|
@@ -11716,6 +11803,8 @@ var NOTIFY_V2_TERMINAL_TYPES = new Set([
|
|
|
11716
11803
|
]);
|
|
11717
11804
|
|
|
11718
11805
|
class EventHandler {
|
|
11806
|
+
static DEFAULT_LANE_KEY = "__default__";
|
|
11807
|
+
static DEFAULT_MAX_CONCURRENT_SESSIONS = 4;
|
|
11719
11808
|
env;
|
|
11720
11809
|
eventTypes;
|
|
11721
11810
|
onEvent;
|
|
@@ -11723,10 +11812,25 @@ class EventHandler {
|
|
|
11723
11812
|
formatter;
|
|
11724
11813
|
isIdle;
|
|
11725
11814
|
idleCheckInterval;
|
|
11726
|
-
|
|
11727
|
-
|
|
11815
|
+
isSessionIdleFn = null;
|
|
11816
|
+
maxConcurrentSessions;
|
|
11817
|
+
lanes = new Map;
|
|
11818
|
+
runningLanes = new Set;
|
|
11819
|
+
laneTails = new Map;
|
|
11820
|
+
get isProcessing() {
|
|
11821
|
+
return this.runningLanes.size > 0;
|
|
11822
|
+
}
|
|
11823
|
+
chatSessionCache = new Map;
|
|
11824
|
+
inFlightCount = 0;
|
|
11825
|
+
legacyQueue = [];
|
|
11826
|
+
get queue() {
|
|
11827
|
+
return this.legacyQueue;
|
|
11828
|
+
}
|
|
11728
11829
|
isStopped = false;
|
|
11729
11830
|
unsubscribe = null;
|
|
11831
|
+
activeSlots = 0;
|
|
11832
|
+
slotWaiters = [];
|
|
11833
|
+
sessionChains = new Map;
|
|
11730
11834
|
sessionComponent = null;
|
|
11731
11835
|
activeEventSessionId = null;
|
|
11732
11836
|
resolvedSessionByTrigger = new Map;
|
|
@@ -11739,6 +11843,9 @@ class EventHandler {
|
|
|
11739
11843
|
this.onEventWithEnv = options.onEventWithEnv;
|
|
11740
11844
|
this.formatter = options.formatter ?? new EventMessageFormatter;
|
|
11741
11845
|
this.isIdle = options.isIdle ?? (() => true);
|
|
11846
|
+
this.isSessionIdleFn = options.isSessionIdle ?? null;
|
|
11847
|
+
const maxSessions = options.maxConcurrentSessions;
|
|
11848
|
+
this.maxConcurrentSessions = typeof maxSessions === "number" && Number.isFinite(maxSessions) && maxSessions >= 1 ? Math.floor(maxSessions) : EventHandler.DEFAULT_MAX_CONCURRENT_SESSIONS;
|
|
11742
11849
|
this.idleCheckInterval = options.idleCheckInterval ?? 100;
|
|
11743
11850
|
this.sessionComponent = options.sessionComponent ?? null;
|
|
11744
11851
|
this.eventStore = options.eventStore ?? null;
|
|
@@ -11776,8 +11883,13 @@ class EventHandler {
|
|
|
11776
11883
|
this.unsubscribe();
|
|
11777
11884
|
this.unsubscribe = null;
|
|
11778
11885
|
}
|
|
11779
|
-
this.
|
|
11780
|
-
this.
|
|
11886
|
+
this.lanes.clear();
|
|
11887
|
+
this.legacyQueue = [];
|
|
11888
|
+
this.laneTails.clear();
|
|
11889
|
+
const waiters = this.slotWaiters.splice(0, this.slotWaiters.length);
|
|
11890
|
+
for (const w of waiters)
|
|
11891
|
+
w();
|
|
11892
|
+
this.activeSlots = 0;
|
|
11781
11893
|
this.clearActiveSession();
|
|
11782
11894
|
}
|
|
11783
11895
|
async handleEvent(event) {
|
|
@@ -11899,77 +12011,218 @@ class EventHandler {
|
|
|
11899
12011
|
await this.onEvent(formatted.message);
|
|
11900
12012
|
}
|
|
11901
12013
|
}
|
|
12014
|
+
laneKeyFor(item) {
|
|
12015
|
+
if (item.chatId)
|
|
12016
|
+
return item.chatId;
|
|
12017
|
+
if (item.triggerSessionId)
|
|
12018
|
+
return `trigger:${item.triggerSessionId}`;
|
|
12019
|
+
return EventHandler.DEFAULT_LANE_KEY;
|
|
12020
|
+
}
|
|
11902
12021
|
enqueue(formattedEvent) {
|
|
11903
12022
|
if (this.isStopped) {
|
|
11904
12023
|
return;
|
|
11905
12024
|
}
|
|
11906
|
-
|
|
11907
|
-
if (!
|
|
11908
|
-
|
|
12025
|
+
const item = { ...formattedEvent };
|
|
12026
|
+
if (!item.envContext) {
|
|
12027
|
+
item.envContext = getEnvContext();
|
|
12028
|
+
}
|
|
12029
|
+
const laneKey = this.laneKeyFor(item);
|
|
12030
|
+
const lane = this.lanes.get(laneKey);
|
|
12031
|
+
if (lane) {
|
|
12032
|
+
lane.push(item);
|
|
12033
|
+
} else {
|
|
12034
|
+
this.lanes.set(laneKey, [item]);
|
|
11909
12035
|
}
|
|
12036
|
+
this.scheduleLane(laneKey);
|
|
11910
12037
|
}
|
|
11911
12038
|
getQueueLength() {
|
|
11912
|
-
|
|
12039
|
+
let total = this.legacyQueue.length + this.inFlightCount;
|
|
12040
|
+
for (const lane of this.lanes.values()) {
|
|
12041
|
+
total += lane.length;
|
|
12042
|
+
}
|
|
12043
|
+
return total;
|
|
11913
12044
|
}
|
|
11914
12045
|
isQueueEmpty() {
|
|
11915
|
-
return this.
|
|
12046
|
+
return this.getQueueLength() === 0;
|
|
11916
12047
|
}
|
|
11917
|
-
|
|
11918
|
-
this.
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
12048
|
+
isSessionIdle(laneKey) {
|
|
12049
|
+
return !this.runningLanes.has(laneKey);
|
|
12050
|
+
}
|
|
12051
|
+
getRunningLaneKeys() {
|
|
12052
|
+
return Array.from(this.runningLanes);
|
|
12053
|
+
}
|
|
12054
|
+
scheduleLane(laneKey) {
|
|
12055
|
+
if (this.isStopped)
|
|
12056
|
+
return;
|
|
12057
|
+
if (this.runningLanes.has(laneKey))
|
|
12058
|
+
return;
|
|
12059
|
+
this.runningLanes.add(laneKey);
|
|
12060
|
+
const tail = this.runLane(laneKey).catch((err) => {
|
|
12061
|
+
console.error(`[EventHandler] lane ${laneKey} 处理异常:`, err);
|
|
12062
|
+
}).finally(() => {
|
|
12063
|
+
this.runningLanes.delete(laneKey);
|
|
12064
|
+
this.laneTails.delete(laneKey);
|
|
12065
|
+
const rest = this.lanes.get(laneKey);
|
|
12066
|
+
if (rest && rest.length > 0) {
|
|
12067
|
+
this.scheduleLane(laneKey);
|
|
11924
12068
|
}
|
|
11925
|
-
|
|
11926
|
-
|
|
12069
|
+
});
|
|
12070
|
+
this.laneTails.set(laneKey, tail);
|
|
12071
|
+
}
|
|
12072
|
+
async runLane(laneKey) {
|
|
12073
|
+
while (!this.isStopped) {
|
|
12074
|
+
const lane = this.lanes.get(laneKey);
|
|
12075
|
+
if (!lane || lane.length === 0) {
|
|
11927
12076
|
break;
|
|
11928
12077
|
}
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
12078
|
+
const head = lane[0];
|
|
12079
|
+
const sessionId = await runWithEnvContextAsync(head.envContext, () => this.resolveSessionForItem(laneKey, head));
|
|
12080
|
+
if (this.isStopped)
|
|
12081
|
+
break;
|
|
12082
|
+
const canonicalKey = sessionId ?? laneKey;
|
|
12083
|
+
if (canonicalKey !== laneKey) {
|
|
12084
|
+
const mine = this.lanes.get(laneKey) ?? [];
|
|
12085
|
+
if (mine.length > 0) {
|
|
12086
|
+
const target = this.lanes.get(canonicalKey);
|
|
12087
|
+
if (target) {
|
|
12088
|
+
target.push(...mine);
|
|
12089
|
+
} else {
|
|
12090
|
+
this.lanes.set(canonicalKey, mine);
|
|
11938
12091
|
}
|
|
12092
|
+
this.lanes.delete(laneKey);
|
|
12093
|
+
this.scheduleLane(canonicalKey);
|
|
11939
12094
|
}
|
|
11940
|
-
|
|
11941
|
-
console.warn(`[EventHandler] Failed to ensure chat-keyed session (chatId=${item.chatId}), ` + `falling back to trigger_session_id path`);
|
|
11942
|
-
sessionId = await this.ensureActiveSession(item.triggerSessionId);
|
|
11943
|
-
}
|
|
11944
|
-
} else {
|
|
11945
|
-
sessionId = await this.ensureActiveSession(item.triggerSessionId);
|
|
12095
|
+
return;
|
|
11946
12096
|
}
|
|
12097
|
+
await this.waitForIdle(sessionId ?? laneKey);
|
|
12098
|
+
if (this.isStopped)
|
|
12099
|
+
break;
|
|
12100
|
+
const claimKey = sessionId ?? laneKey;
|
|
12101
|
+
const releaseClaim = await this.claimSession(claimKey);
|
|
11947
12102
|
if (this.isStopped) {
|
|
12103
|
+
releaseClaim();
|
|
11948
12104
|
break;
|
|
11949
12105
|
}
|
|
11950
|
-
|
|
11951
|
-
|
|
12106
|
+
await this.acquireSlot();
|
|
12107
|
+
if (this.isStopped) {
|
|
12108
|
+
releaseClaim();
|
|
12109
|
+
this.releaseSlot();
|
|
12110
|
+
break;
|
|
11952
12111
|
}
|
|
11953
12112
|
try {
|
|
12113
|
+
const item = lane.shift();
|
|
12114
|
+
if (!item)
|
|
12115
|
+
break;
|
|
12116
|
+
this.inFlightCount++;
|
|
12117
|
+
try {
|
|
12118
|
+
await this.processItem(item, sessionId);
|
|
12119
|
+
} finally {
|
|
12120
|
+
this.inFlightCount--;
|
|
12121
|
+
}
|
|
12122
|
+
} finally {
|
|
12123
|
+
releaseClaim();
|
|
12124
|
+
this.releaseSlot();
|
|
12125
|
+
}
|
|
12126
|
+
}
|
|
12127
|
+
const rest = this.lanes.get(laneKey);
|
|
12128
|
+
if (!rest || rest.length === 0) {
|
|
12129
|
+
this.lanes.delete(laneKey);
|
|
12130
|
+
}
|
|
12131
|
+
}
|
|
12132
|
+
async resolveSessionForItem(laneKey, item) {
|
|
12133
|
+
if (item.sessionResolved) {
|
|
12134
|
+
return item.resolvedSessionId ?? null;
|
|
12135
|
+
}
|
|
12136
|
+
const resolved = await this.resolveSessionForItemUncached(laneKey, item);
|
|
12137
|
+
item.sessionResolved = true;
|
|
12138
|
+
item.resolvedSessionId = resolved;
|
|
12139
|
+
return resolved;
|
|
12140
|
+
}
|
|
12141
|
+
async resolveSessionForItemUncached(laneKey, item) {
|
|
12142
|
+
if (item.chatId && this.sessionComponent) {
|
|
12143
|
+
const cached = this.chatSessionCache.get(item.chatId);
|
|
12144
|
+
if (cached)
|
|
12145
|
+
return cached;
|
|
12146
|
+
let resolved = await this.ensureChatSession(item.chatId);
|
|
12147
|
+
if (!resolved) {
|
|
12148
|
+
console.warn(`[EventHandler] Failed to ensure chat-keyed session (chatId=${item.chatId}), ` + `falling back to trigger_session_id path`);
|
|
12149
|
+
resolved = await this.ensureActiveSession(item.triggerSessionId);
|
|
12150
|
+
} else {
|
|
12151
|
+
this.chatSessionCache.set(item.chatId, resolved);
|
|
12152
|
+
}
|
|
12153
|
+
return resolved;
|
|
12154
|
+
}
|
|
12155
|
+
return this.ensureActiveSession(item.triggerSessionId);
|
|
12156
|
+
}
|
|
12157
|
+
async processItem(item, sessionId) {
|
|
12158
|
+
if (sessionId) {
|
|
12159
|
+
item.eventSessionId = sessionId;
|
|
12160
|
+
}
|
|
12161
|
+
try {
|
|
12162
|
+
await runWithEnvContextAsync(item.envContext, async () => {
|
|
11954
12163
|
if (this.onEventWithEnv) {
|
|
11955
12164
|
await this.onEventWithEnv(item);
|
|
11956
|
-
|
|
12165
|
+
return;
|
|
11957
12166
|
}
|
|
11958
12167
|
await this.onEvent(item.message);
|
|
11959
|
-
}
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
}
|
|
11968
|
-
|
|
11969
|
-
|
|
12168
|
+
});
|
|
12169
|
+
} catch (error) {
|
|
12170
|
+
console.error(`[EventHandler] 处理事件失败:`, error);
|
|
12171
|
+
try {
|
|
12172
|
+
await notifyReactFailure2({
|
|
12173
|
+
error,
|
|
12174
|
+
envEvent: item.envEvent,
|
|
12175
|
+
sessionId: sessionId ?? undefined
|
|
12176
|
+
});
|
|
12177
|
+
} catch (notifyErr) {
|
|
12178
|
+
console.error(`[EventHandler] 失败说明回飞书异常:`, notifyErr);
|
|
11970
12179
|
}
|
|
11971
12180
|
}
|
|
11972
|
-
|
|
12181
|
+
}
|
|
12182
|
+
async processQueue() {
|
|
12183
|
+
if (this.isStopped)
|
|
12184
|
+
return;
|
|
12185
|
+
if (this.legacyQueue.length > 0) {
|
|
12186
|
+
const pending = this.legacyQueue.splice(0, this.legacyQueue.length);
|
|
12187
|
+
for (const item of pending) {
|
|
12188
|
+
if (!item.envContext) {
|
|
12189
|
+
item.envContext = getEnvContext();
|
|
12190
|
+
}
|
|
12191
|
+
const laneKey = this.laneKeyFor(item);
|
|
12192
|
+
const lane = this.lanes.get(laneKey);
|
|
12193
|
+
if (lane)
|
|
12194
|
+
lane.push(item);
|
|
12195
|
+
else
|
|
12196
|
+
this.lanes.set(laneKey, [item]);
|
|
12197
|
+
}
|
|
12198
|
+
}
|
|
12199
|
+
for (const [laneKey, lane] of Array.from(this.lanes.entries())) {
|
|
12200
|
+
if (lane.length > 0)
|
|
12201
|
+
this.scheduleLane(laneKey);
|
|
12202
|
+
}
|
|
12203
|
+
const tails = Array.from(this.laneTails.values());
|
|
12204
|
+
if (tails.length > 0) {
|
|
12205
|
+
await Promise.all(tails.map((t) => t.catch(() => {
|
|
12206
|
+
return;
|
|
12207
|
+
})));
|
|
12208
|
+
}
|
|
12209
|
+
}
|
|
12210
|
+
async acquireSlot() {
|
|
12211
|
+
if (this.activeSlots < this.maxConcurrentSessions) {
|
|
12212
|
+
this.activeSlots++;
|
|
12213
|
+
return;
|
|
12214
|
+
}
|
|
12215
|
+
await new Promise((resolve) => {
|
|
12216
|
+
this.slotWaiters.push(resolve);
|
|
12217
|
+
});
|
|
12218
|
+
this.activeSlots++;
|
|
12219
|
+
}
|
|
12220
|
+
releaseSlot() {
|
|
12221
|
+
if (this.activeSlots > 0)
|
|
12222
|
+
this.activeSlots--;
|
|
12223
|
+
const next = this.slotWaiters.shift();
|
|
12224
|
+
if (next)
|
|
12225
|
+
next();
|
|
11973
12226
|
}
|
|
11974
12227
|
async ensureActiveSession(triggerSessionIdOverride) {
|
|
11975
12228
|
if (!this.sessionComponent)
|
|
@@ -12079,6 +12332,7 @@ class EventHandler {
|
|
|
12079
12332
|
clearActiveSession() {
|
|
12080
12333
|
this.activeEventSessionId = null;
|
|
12081
12334
|
this.resolvedSessionByTrigger.clear();
|
|
12335
|
+
this.chatSessionCache.clear();
|
|
12082
12336
|
}
|
|
12083
12337
|
cacheResolvedSession(triggerSessionIdOverride, sessionId) {
|
|
12084
12338
|
if (triggerSessionIdOverride && sessionId) {
|
|
@@ -12088,11 +12342,38 @@ class EventHandler {
|
|
|
12088
12342
|
getActiveEventSessionId() {
|
|
12089
12343
|
return this.activeEventSessionId;
|
|
12090
12344
|
}
|
|
12091
|
-
async waitForIdle() {
|
|
12092
|
-
while (!this.isStopped && !this.
|
|
12345
|
+
async waitForIdle(sessionId) {
|
|
12346
|
+
while (!this.isStopped && !this.isLaneIdle(sessionId)) {
|
|
12093
12347
|
await this.sleep(this.idleCheckInterval);
|
|
12094
12348
|
}
|
|
12095
12349
|
}
|
|
12350
|
+
isLaneIdle(sessionId) {
|
|
12351
|
+
if (this.isSessionIdleFn && sessionId) {
|
|
12352
|
+
return this.isSessionIdleFn(sessionId);
|
|
12353
|
+
}
|
|
12354
|
+
return this.isIdle();
|
|
12355
|
+
}
|
|
12356
|
+
claimSession(sessionKey) {
|
|
12357
|
+
const prev = this.sessionChains.get(sessionKey) ?? Promise.resolve();
|
|
12358
|
+
let releaseFn;
|
|
12359
|
+
const current = new Promise((resolve) => {
|
|
12360
|
+
releaseFn = resolve;
|
|
12361
|
+
});
|
|
12362
|
+
const tail = prev.then(() => current);
|
|
12363
|
+
this.sessionChains.set(sessionKey, tail);
|
|
12364
|
+
return prev.then(() => {
|
|
12365
|
+
let released = false;
|
|
12366
|
+
return () => {
|
|
12367
|
+
if (released)
|
|
12368
|
+
return;
|
|
12369
|
+
released = true;
|
|
12370
|
+
releaseFn();
|
|
12371
|
+
if (this.sessionChains.get(sessionKey) === tail) {
|
|
12372
|
+
this.sessionChains.delete(sessionKey);
|
|
12373
|
+
}
|
|
12374
|
+
};
|
|
12375
|
+
});
|
|
12376
|
+
}
|
|
12096
12377
|
sleep(ms) {
|
|
12097
12378
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12098
12379
|
}
|
|
@@ -12187,12 +12468,24 @@ function createEventHandlerForInteractive(options) {
|
|
|
12187
12468
|
const dbPath = options.dbPath ?? createDefaultEventStoreDbPath();
|
|
12188
12469
|
const eventStore = getOrCreateEventStore(dbPath);
|
|
12189
12470
|
const getHandlerForEsType = getHandlerForEsTypeForEnv(options.env);
|
|
12471
|
+
const maxConcurrentSessions = options.maxConcurrentSessions ?? readMaxConcurrentSessionsFromEnv();
|
|
12190
12472
|
return new EventHandler({
|
|
12191
12473
|
...options,
|
|
12474
|
+
...maxConcurrentSessions !== undefined ? { maxConcurrentSessions } : {},
|
|
12192
12475
|
eventStore,
|
|
12193
12476
|
getHandlerForEsType
|
|
12194
12477
|
});
|
|
12195
12478
|
}
|
|
12479
|
+
var MAX_CONCURRENT_SESSIONS_ENV = "ROY_AGENT_MAX_CONCURRENT_SESSIONS";
|
|
12480
|
+
function readMaxConcurrentSessionsFromEnv(env = process.env) {
|
|
12481
|
+
const raw = env[MAX_CONCURRENT_SESSIONS_ENV];
|
|
12482
|
+
if (raw === undefined || raw.trim() === "")
|
|
12483
|
+
return;
|
|
12484
|
+
const parsed = Number(raw);
|
|
12485
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
12486
|
+
return;
|
|
12487
|
+
return Math.max(1, Math.floor(parsed));
|
|
12488
|
+
}
|
|
12196
12489
|
|
|
12197
12490
|
// src/commands/shared/esc-active-descendant.ts
|
|
12198
12491
|
function hasActiveDescendants(env, parentSessionId) {
|
|
@@ -12865,7 +13158,8 @@ var USER_PROMPT = COLORS.accent("❯ ");
|
|
|
12865
13158
|
class REPL {
|
|
12866
13159
|
rl;
|
|
12867
13160
|
options;
|
|
12868
|
-
|
|
13161
|
+
executingSessions = new Map;
|
|
13162
|
+
static LEGACY_SESSION_KEY = "__legacy_isExecuting__";
|
|
12869
13163
|
replMode = "ready";
|
|
12870
13164
|
statusBarCtx = {};
|
|
12871
13165
|
isAltEnterPending = false;
|
|
@@ -13058,7 +13352,10 @@ ${COLORS.system("[正在中断...]")}`);
|
|
|
13058
13352
|
}
|
|
13059
13353
|
}
|
|
13060
13354
|
abortStream();
|
|
13061
|
-
this.
|
|
13355
|
+
for (const sid of this.getExecutingSessionIds()) {
|
|
13356
|
+
abortStream(sid);
|
|
13357
|
+
}
|
|
13358
|
+
this.abortAllExecutingSessions();
|
|
13062
13359
|
console.log(`${COLORS.system("[已中断,可以继续输入]")}`);
|
|
13063
13360
|
} else {
|
|
13064
13361
|
console.log(`
|
|
@@ -13143,7 +13440,8 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
13143
13440
|
this.inkApi = api;
|
|
13144
13441
|
},
|
|
13145
13442
|
onSubmit: async (input) => {
|
|
13146
|
-
|
|
13443
|
+
const inkSessionId = this.options.sessionId;
|
|
13444
|
+
this.markSessionExecuting(inkSessionId, true);
|
|
13147
13445
|
inkApiRef?.setMode("executing");
|
|
13148
13446
|
try {
|
|
13149
13447
|
await this.options.onExecute(input);
|
|
@@ -13161,7 +13459,7 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
13161
13459
|
inkApiRef?.appendMessage({ role: "system", content: `[Error] ${msg}` });
|
|
13162
13460
|
throw err;
|
|
13163
13461
|
} finally {
|
|
13164
|
-
this.
|
|
13462
|
+
this.markSessionExecuting(inkSessionId, false);
|
|
13165
13463
|
}
|
|
13166
13464
|
},
|
|
13167
13465
|
onCommand: async (cmd) => {
|
|
@@ -13314,7 +13612,8 @@ ${COLORS.error("❓ 未知命令: /" + cmd + "}")}`);
|
|
|
13314
13612
|
}
|
|
13315
13613
|
}
|
|
13316
13614
|
async handleMessage(message) {
|
|
13317
|
-
|
|
13615
|
+
const inputSessionId = this.options.sessionId;
|
|
13616
|
+
if (!this.isSessionIdle(inputSessionId)) {
|
|
13318
13617
|
console.log(`
|
|
13319
13618
|
${COLORS.system("⏳ 上一次请求尚未完成,请稍候...")}
|
|
13320
13619
|
`);
|
|
@@ -13381,7 +13680,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
13381
13680
|
};
|
|
13382
13681
|
}
|
|
13383
13682
|
}
|
|
13384
|
-
|
|
13683
|
+
const agentContext = {
|
|
13385
13684
|
agentType: agentFromEvent,
|
|
13386
13685
|
pluginEnabled,
|
|
13387
13686
|
envEvent: envEventForAgent,
|
|
@@ -13389,9 +13688,12 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
13389
13688
|
eventSessionId,
|
|
13390
13689
|
systemPrompt: envEvent.metadata?.systemPrompt
|
|
13391
13690
|
};
|
|
13392
|
-
await this.executeInternal(message, {
|
|
13691
|
+
await this.executeInternal(message, {
|
|
13692
|
+
showPrompt: true,
|
|
13693
|
+
sessionId: eventSessionId,
|
|
13694
|
+
agentContext
|
|
13695
|
+
});
|
|
13393
13696
|
}
|
|
13394
|
-
currentAgentContext = undefined;
|
|
13395
13697
|
lastReplyChannel = undefined;
|
|
13396
13698
|
lastReplyChannelByChat = new Map;
|
|
13397
13699
|
static REPLY_CHANNEL_CHAT_CACHE_MAX = 100;
|
|
@@ -13410,7 +13712,56 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
13410
13712
|
}
|
|
13411
13713
|
}
|
|
13412
13714
|
isIdle() {
|
|
13413
|
-
return !this.
|
|
13715
|
+
return !this.anySessionBusy();
|
|
13716
|
+
}
|
|
13717
|
+
anySessionBusy() {
|
|
13718
|
+
for (const count of this.execSet().values()) {
|
|
13719
|
+
if (count > 0)
|
|
13720
|
+
return true;
|
|
13721
|
+
}
|
|
13722
|
+
return false;
|
|
13723
|
+
}
|
|
13724
|
+
execSet() {
|
|
13725
|
+
if (!this.executingSessions)
|
|
13726
|
+
this.executingSessions = new Map;
|
|
13727
|
+
return this.executingSessions;
|
|
13728
|
+
}
|
|
13729
|
+
get isExecuting() {
|
|
13730
|
+
return this.anySessionBusy();
|
|
13731
|
+
}
|
|
13732
|
+
set isExecuting(executing) {
|
|
13733
|
+
if (!executing) {
|
|
13734
|
+
this.execSet().clear();
|
|
13735
|
+
return;
|
|
13736
|
+
}
|
|
13737
|
+
this.execSet().set(REPL.LEGACY_SESSION_KEY, 1);
|
|
13738
|
+
}
|
|
13739
|
+
markSessionExecuting(sessionId, executing) {
|
|
13740
|
+
const counts = this.execSet();
|
|
13741
|
+
if (executing) {
|
|
13742
|
+
counts.set(sessionId, (counts.get(sessionId) ?? 0) + 1);
|
|
13743
|
+
return;
|
|
13744
|
+
}
|
|
13745
|
+
const current = counts.get(sessionId) ?? 0;
|
|
13746
|
+
if (current <= 1) {
|
|
13747
|
+
counts.delete(sessionId);
|
|
13748
|
+
} else {
|
|
13749
|
+
counts.set(sessionId, current - 1);
|
|
13750
|
+
}
|
|
13751
|
+
}
|
|
13752
|
+
isSessionIdle(sessionId) {
|
|
13753
|
+
return (this.execSet().get(sessionId) ?? 0) <= 0;
|
|
13754
|
+
}
|
|
13755
|
+
getExecutingSessionIds() {
|
|
13756
|
+
const ids = [];
|
|
13757
|
+
for (const [sid, count] of this.execSet().entries()) {
|
|
13758
|
+
if (count > 0)
|
|
13759
|
+
ids.push(sid);
|
|
13760
|
+
}
|
|
13761
|
+
return ids;
|
|
13762
|
+
}
|
|
13763
|
+
abortAllExecutingSessions() {
|
|
13764
|
+
this.execSet().clear();
|
|
13414
13765
|
}
|
|
13415
13766
|
setMode(mode, detail) {
|
|
13416
13767
|
this.replMode = mode;
|
|
@@ -13433,30 +13784,37 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
13433
13784
|
}));
|
|
13434
13785
|
}
|
|
13435
13786
|
async executeInternal(message, options) {
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13787
|
+
const execSessionId = options.sessionId ?? this.options.sessionId;
|
|
13788
|
+
const agentContext = {
|
|
13789
|
+
...options.agentContext,
|
|
13790
|
+
eventSessionId: options.agentContext?.eventSessionId ?? execSessionId
|
|
13791
|
+
};
|
|
13440
13792
|
resetStreamAbort();
|
|
13441
13793
|
const provider = getTracerProvider3();
|
|
13442
13794
|
const tracer = provider.getTracer("roy-tracer");
|
|
13443
|
-
const
|
|
13795
|
+
const payloadTraceContext = agentContext?.envEvent?.metadata?.traceContext;
|
|
13796
|
+
const existingContext = payloadTraceContext ?? provider.getGlobalContext();
|
|
13444
13797
|
let rootSpan;
|
|
13445
13798
|
let traceId;
|
|
13446
|
-
|
|
13447
|
-
rootSpan = tracer.startSpan("interactive.execute", {
|
|
13448
|
-
parent: existingContext
|
|
13449
|
-
});
|
|
13450
|
-
traceId = existingContext.traceId;
|
|
13451
|
-
} else {
|
|
13452
|
-
rootSpan = tracer.startSpan("interactive.execute");
|
|
13453
|
-
traceId = rootSpan.spanContext.traceId;
|
|
13454
|
-
provider.setGlobalContext(rootSpan.spanContext);
|
|
13455
|
-
}
|
|
13456
|
-
console.log(`${COLORS.system("[Trace] " + traceId)}`);
|
|
13457
|
-
console.log(`${COLORS.progress("[thinking...]")}`);
|
|
13799
|
+
let runTraceContext = existingContext;
|
|
13458
13800
|
try {
|
|
13459
|
-
|
|
13801
|
+
this.markSessionExecuting(execSessionId, true);
|
|
13802
|
+
this.setMode("executing");
|
|
13803
|
+
await provider.withGlobalContext(runTraceContext, async () => {
|
|
13804
|
+
if (existingContext) {
|
|
13805
|
+
rootSpan = tracer.startSpan("interactive.execute", {
|
|
13806
|
+
parent: existingContext
|
|
13807
|
+
});
|
|
13808
|
+
traceId = existingContext.traceId;
|
|
13809
|
+
} else {
|
|
13810
|
+
rootSpan = tracer.startSpan("interactive.execute");
|
|
13811
|
+
traceId = rootSpan.spanContext.traceId;
|
|
13812
|
+
runTraceContext = rootSpan.spanContext;
|
|
13813
|
+
}
|
|
13814
|
+
console.log(`${COLORS.system("[Trace] " + traceId)}`);
|
|
13815
|
+
console.log(`${COLORS.progress("[thinking...]")}`);
|
|
13816
|
+
await this.options.onExecute(message, traceId, agentContext);
|
|
13817
|
+
});
|
|
13460
13818
|
if (this.options.onAfterExecute) {
|
|
13461
13819
|
try {
|
|
13462
13820
|
await this.options.onAfterExecute(this.lastUsage);
|
|
@@ -13472,7 +13830,7 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
13472
13830
|
console.error(`
|
|
13473
13831
|
${COLORS.error("❌ 执行失败: " + error)}
|
|
13474
13832
|
`);
|
|
13475
|
-
rootSpan
|
|
13833
|
+
rootSpan?.setAttribute("error", String(error));
|
|
13476
13834
|
try {
|
|
13477
13835
|
await notifyReactFailure3({
|
|
13478
13836
|
error,
|
|
@@ -13484,14 +13842,15 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13484
13842
|
}
|
|
13485
13843
|
}
|
|
13486
13844
|
} finally {
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13845
|
+
try {
|
|
13846
|
+
provider.runInGlobalContextSync(runTraceContext, () => rootSpan?.end());
|
|
13847
|
+
} catch (endErr) {
|
|
13848
|
+
logger6.warn("root span end failed (ignored)", { error: String(endErr) });
|
|
13849
|
+
}
|
|
13850
|
+
this.markSessionExecuting(execSessionId, false);
|
|
13851
|
+
if (this.isIdle()) {
|
|
13852
|
+
this.setMode("ready");
|
|
13492
13853
|
}
|
|
13493
|
-
this.isExecuting = false;
|
|
13494
|
-
this.setMode("ready");
|
|
13495
13854
|
if (options.showPrompt) {
|
|
13496
13855
|
this.redrawInputArea();
|
|
13497
13856
|
if (this.rl) {
|
|
@@ -13661,6 +14020,9 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13661
14020
|
}
|
|
13662
14021
|
}
|
|
13663
14022
|
abortStream();
|
|
14023
|
+
for (const sid of this.getExecutingSessionIds()) {
|
|
14024
|
+
abortStream(sid);
|
|
14025
|
+
}
|
|
13664
14026
|
if (this.inkApi && typeof this.inkApi.finishAssistantStream === "function") {
|
|
13665
14027
|
try {
|
|
13666
14028
|
this.inkApi.finishAssistantStream();
|
|
@@ -13687,7 +14049,7 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
13687
14049
|
}
|
|
13688
14050
|
}
|
|
13689
14051
|
if (isExecuting) {
|
|
13690
|
-
this.
|
|
14052
|
+
this.abortAllExecutingSessions();
|
|
13691
14053
|
}
|
|
13692
14054
|
this.setMode("ready");
|
|
13693
14055
|
if (this.rl) {
|
|
@@ -13890,6 +14252,57 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13890
14252
|
quiet: true,
|
|
13891
14253
|
silent: useInk
|
|
13892
14254
|
});
|
|
14255
|
+
const MAX_SESSION_EXECUTORS = 16;
|
|
14256
|
+
const sessionExecutors = new Map;
|
|
14257
|
+
const runningTurns = new Set;
|
|
14258
|
+
let sessionChunkCallback = undefined;
|
|
14259
|
+
const getSessionExecutor = (sid) => {
|
|
14260
|
+
if (!sid)
|
|
14261
|
+
return queryExecutor;
|
|
14262
|
+
const cached = sessionExecutors.get(sid);
|
|
14263
|
+
if (cached) {
|
|
14264
|
+
sessionExecutors.delete(sid);
|
|
14265
|
+
sessionExecutors.set(sid, cached);
|
|
14266
|
+
return cached;
|
|
14267
|
+
}
|
|
14268
|
+
const created = new QueryExecutor({
|
|
14269
|
+
env,
|
|
14270
|
+
sessionComponent,
|
|
14271
|
+
output,
|
|
14272
|
+
quiet: true,
|
|
14273
|
+
silent: true
|
|
14274
|
+
});
|
|
14275
|
+
created.initStreamOutput(llmComponent);
|
|
14276
|
+
created.setSessionScope(sid);
|
|
14277
|
+
created.setAcceptsSidelessEvents(false);
|
|
14278
|
+
created.setChunkCallback(sessionChunkCallback);
|
|
14279
|
+
sessionExecutors.set(sid, created);
|
|
14280
|
+
while (sessionExecutors.size > MAX_SESSION_EXECUTORS) {
|
|
14281
|
+
let victim;
|
|
14282
|
+
for (const key of sessionExecutors.keys()) {
|
|
14283
|
+
if (!runningTurns.has(key)) {
|
|
14284
|
+
victim = key;
|
|
14285
|
+
break;
|
|
14286
|
+
}
|
|
14287
|
+
}
|
|
14288
|
+
if (victim === undefined)
|
|
14289
|
+
break;
|
|
14290
|
+
const evicted = sessionExecutors.get(victim);
|
|
14291
|
+
sessionExecutors.delete(victim);
|
|
14292
|
+
try {
|
|
14293
|
+
evicted?.dispose();
|
|
14294
|
+
} catch {}
|
|
14295
|
+
}
|
|
14296
|
+
return created;
|
|
14297
|
+
};
|
|
14298
|
+
const disposeSessionExecutors = () => {
|
|
14299
|
+
for (const ex of sessionExecutors.values()) {
|
|
14300
|
+
try {
|
|
14301
|
+
ex.dispose();
|
|
14302
|
+
} catch {}
|
|
14303
|
+
}
|
|
14304
|
+
sessionExecutors.clear();
|
|
14305
|
+
};
|
|
13893
14306
|
let currentAgentContext = undefined;
|
|
13894
14307
|
if (args.agent && args.agent !== "default") {
|
|
13895
14308
|
const agentComponent = env.getComponent("agent");
|
|
@@ -13992,7 +14405,8 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13992
14405
|
version: getPackageVersion(),
|
|
13993
14406
|
useInk,
|
|
13994
14407
|
onExecute: async (message, traceId, agentContext) => {
|
|
13995
|
-
|
|
14408
|
+
const runSessionId = agentContext?.eventSessionId;
|
|
14409
|
+
resetStreamAbort(runSessionId);
|
|
13996
14410
|
const preloadedPrompts = eventSourceSystemPrompts;
|
|
13997
14411
|
const eventSourceSystemPrompt = preloadedPrompts.length > 0 ? joinResolvedSystemPrompts(preloadedPrompts) : undefined;
|
|
13998
14412
|
const mergedContext = {
|
|
@@ -14007,16 +14421,27 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
14007
14421
|
}
|
|
14008
14422
|
};
|
|
14009
14423
|
const effectiveSessionId = mergedContext.eventSessionId ?? sessionId;
|
|
14010
|
-
const
|
|
14011
|
-
|
|
14012
|
-
|
|
14013
|
-
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
|
|
14424
|
+
const isEventDrivenTurn = !!runSessionId && runSessionId !== sessionId;
|
|
14425
|
+
const exec2 = isEventDrivenTurn ? getSessionExecutor(effectiveSessionId) : queryExecutor;
|
|
14426
|
+
runningTurns.add(effectiveSessionId);
|
|
14427
|
+
try {
|
|
14428
|
+
const result = await exec2.execute(message, effectiveSessionId, {
|
|
14429
|
+
showReasoning: args.reasoning,
|
|
14430
|
+
showToolCalls: args.toolCalls,
|
|
14431
|
+
showToolResults: args.toolResults
|
|
14432
|
+
}, traceId, mergedContext);
|
|
14433
|
+
if (result && !exec2.getFullText()) {
|
|
14434
|
+
console.log(result);
|
|
14435
|
+
} else if (isEventDrivenTurn) {
|
|
14436
|
+
const full = exec2.getFullText();
|
|
14437
|
+
if (full)
|
|
14438
|
+
console.log(full);
|
|
14439
|
+
}
|
|
14440
|
+
repl.setLastUsage(exec2.getLastUsage());
|
|
14441
|
+
return result;
|
|
14442
|
+
} finally {
|
|
14443
|
+
runningTurns.delete(effectiveSessionId);
|
|
14017
14444
|
}
|
|
14018
|
-
repl.setLastUsage(queryExecutor.getLastUsage());
|
|
14019
|
-
return result;
|
|
14020
14445
|
},
|
|
14021
14446
|
onAfterExecute: (usage) => {
|
|
14022
14447
|
if (useInk)
|
|
@@ -14041,6 +14466,7 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
14041
14466
|
onSwitchSession: async (newSessionId) => {
|
|
14042
14467
|
const result = await sessionManager.switchSession(newSessionId);
|
|
14043
14468
|
queryExecutor.dispose();
|
|
14469
|
+
disposeSessionExecutors();
|
|
14044
14470
|
return result;
|
|
14045
14471
|
},
|
|
14046
14472
|
onCompact: async () => {
|
|
@@ -14090,6 +14516,7 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
14090
14516
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
14091
14517
|
formatter: new EventMessageFormatter({ prefix: "[通知]" }),
|
|
14092
14518
|
isIdle: () => repl.isIdle(),
|
|
14519
|
+
isSessionIdle: (sid) => repl.isSessionIdle(sid),
|
|
14093
14520
|
sessionComponent,
|
|
14094
14521
|
onEvent: async (_message) => {},
|
|
14095
14522
|
onEventWithEnv: async (formattedEvent) => {
|
|
@@ -14123,6 +14550,20 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
14123
14550
|
repl.sessionManager = sessionManager;
|
|
14124
14551
|
repl.sessionComponent = sessionComponent;
|
|
14125
14552
|
repl._queryExecutor = queryExecutor;
|
|
14553
|
+
{
|
|
14554
|
+
let inkCb = null;
|
|
14555
|
+
Object.defineProperty(repl, "inkChunkCallback", {
|
|
14556
|
+
configurable: true,
|
|
14557
|
+
get: () => inkCb,
|
|
14558
|
+
set: (cb) => {
|
|
14559
|
+
inkCb = cb;
|
|
14560
|
+
sessionChunkCallback = cb ?? undefined;
|
|
14561
|
+
for (const ex of sessionExecutors.values()) {
|
|
14562
|
+
ex.setChunkCallback(sessionChunkCallback);
|
|
14563
|
+
}
|
|
14564
|
+
}
|
|
14565
|
+
});
|
|
14566
|
+
}
|
|
14126
14567
|
await repl.start();
|
|
14127
14568
|
process.removeListener("SIGINT", sigintHandler);
|
|
14128
14569
|
console.log("正在清理资源...");
|
|
@@ -14134,6 +14575,7 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
14134
14575
|
}
|
|
14135
14576
|
eventHandler.stop();
|
|
14136
14577
|
queryExecutor.dispose();
|
|
14578
|
+
disposeSessionExecutors();
|
|
14137
14579
|
const esComponent = env.getComponent("event-source");
|
|
14138
14580
|
if (esComponent) {
|
|
14139
14581
|
const sources = esComponent.list?.();
|
|
@@ -15501,6 +15943,7 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15501
15943
|
const llmComponent = envService.getLLM();
|
|
15502
15944
|
queryExecutor.initStreamOutput(llmComponent ?? null);
|
|
15503
15945
|
const handleQuery = async (message, envEvent) => {
|
|
15946
|
+
const eventTraceContext = envEvent?.metadata?.traceContext;
|
|
15504
15947
|
const mergedContext = {
|
|
15505
15948
|
...agentContext,
|
|
15506
15949
|
model: options.model,
|
|
@@ -15515,7 +15958,7 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15515
15958
|
showReasoning: options.reasoning ?? true,
|
|
15516
15959
|
showToolCalls: options.toolCalls ?? true,
|
|
15517
15960
|
showToolResults: options.toolResults ?? false
|
|
15518
|
-
},
|
|
15961
|
+
}, eventTraceContext?.traceId, mergedContext);
|
|
15519
15962
|
return String(result ?? "");
|
|
15520
15963
|
};
|
|
15521
15964
|
const taskEventHandler = new TaskEventHandler({
|
|
@@ -15592,6 +16035,7 @@ function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext
|
|
|
15592
16035
|
break;
|
|
15593
16036
|
}
|
|
15594
16037
|
});
|
|
16038
|
+
const eventTraceContext = envEvent?.metadata?.traceContext;
|
|
15595
16039
|
const mergedContext = {
|
|
15596
16040
|
...agentContext,
|
|
15597
16041
|
model: options.model,
|
|
@@ -15606,7 +16050,7 @@ function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext
|
|
|
15606
16050
|
showReasoning: options.reasoning ?? true,
|
|
15607
16051
|
showToolCalls: true,
|
|
15608
16052
|
showToolResults: true
|
|
15609
|
-
},
|
|
16053
|
+
}, eventTraceContext?.traceId, mergedContext);
|
|
15610
16054
|
return String(result ?? "");
|
|
15611
16055
|
};
|
|
15612
16056
|
}
|