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