@ai-setting/roy-agent-cli 1.7.20 → 1.7.21
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 +1245 -1377
- package/dist/index.js +1245 -1377
- package/dist/roy-agent-linux-x64/bin/roy-agent +2 -2
- package/package.json +1 -1
package/dist/bin/roy-agent.js
CHANGED
|
@@ -360,6 +360,97 @@ var init_markdown_renderer = __esm(() => {
|
|
|
360
360
|
], MarkdownRenderer.prototype, "push", null);
|
|
361
361
|
});
|
|
362
362
|
|
|
363
|
+
// src/services/stdout-batcher.ts
|
|
364
|
+
function createStdoutBatcher(options = {}) {
|
|
365
|
+
const flushIntervalMs = options.flushIntervalMs ?? 16;
|
|
366
|
+
const maxBufferBytes = options.maxBufferBytes ?? 4096;
|
|
367
|
+
const writeFn = options.writeFn ?? ((chunk) => {
|
|
368
|
+
process.stdout.write(chunk);
|
|
369
|
+
return true;
|
|
370
|
+
});
|
|
371
|
+
const onFlush = options.onFlush;
|
|
372
|
+
let buffer = "";
|
|
373
|
+
let queuedWrites = 0;
|
|
374
|
+
let timer = null;
|
|
375
|
+
let totalBatches = 0;
|
|
376
|
+
let totalWrites = 0;
|
|
377
|
+
let totalBytes = 0;
|
|
378
|
+
let lastBatchWrites = 0;
|
|
379
|
+
function performFlush() {
|
|
380
|
+
if (buffer.length === 0)
|
|
381
|
+
return;
|
|
382
|
+
const chunk = buffer;
|
|
383
|
+
buffer = "";
|
|
384
|
+
lastBatchWrites = queuedWrites;
|
|
385
|
+
queuedWrites = 0;
|
|
386
|
+
totalBatches += 1;
|
|
387
|
+
totalBytes += chunk.length;
|
|
388
|
+
writeFn(chunk);
|
|
389
|
+
if (onFlush) {
|
|
390
|
+
onFlush({
|
|
391
|
+
writesInLastBatch: lastBatchWrites,
|
|
392
|
+
totalBatches,
|
|
393
|
+
totalBytes
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function scheduleFlush() {
|
|
398
|
+
if (timer !== null)
|
|
399
|
+
return;
|
|
400
|
+
timer = setTimeout(() => {
|
|
401
|
+
timer = null;
|
|
402
|
+
performFlush();
|
|
403
|
+
}, flushIntervalMs);
|
|
404
|
+
}
|
|
405
|
+
function maybeForceFlush() {
|
|
406
|
+
if (buffer.length >= maxBufferBytes) {
|
|
407
|
+
if (timer !== null) {
|
|
408
|
+
clearTimeout(timer);
|
|
409
|
+
timer = null;
|
|
410
|
+
}
|
|
411
|
+
performFlush();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function write(chunk) {
|
|
415
|
+
if (chunk.length === 0)
|
|
416
|
+
return;
|
|
417
|
+
buffer += chunk;
|
|
418
|
+
queuedWrites += 1;
|
|
419
|
+
totalWrites += 1;
|
|
420
|
+
scheduleFlush();
|
|
421
|
+
maybeForceFlush();
|
|
422
|
+
}
|
|
423
|
+
function flushNow() {
|
|
424
|
+
if (timer !== null) {
|
|
425
|
+
clearTimeout(timer);
|
|
426
|
+
timer = null;
|
|
427
|
+
}
|
|
428
|
+
performFlush();
|
|
429
|
+
}
|
|
430
|
+
function cancel() {
|
|
431
|
+
if (timer !== null) {
|
|
432
|
+
clearTimeout(timer);
|
|
433
|
+
timer = null;
|
|
434
|
+
}
|
|
435
|
+
buffer = "";
|
|
436
|
+
queuedWrites = 0;
|
|
437
|
+
}
|
|
438
|
+
function getStats() {
|
|
439
|
+
return {
|
|
440
|
+
batches: totalBatches,
|
|
441
|
+
queuedWrites: totalWrites,
|
|
442
|
+
totalBytes,
|
|
443
|
+
writesInLastBatch: lastBatchWrites
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
write,
|
|
448
|
+
flushNow,
|
|
449
|
+
cancel,
|
|
450
|
+
getStats
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
363
454
|
// src/services/stream-output.service.ts
|
|
364
455
|
var exports_stream_output_service = {};
|
|
365
456
|
__export(exports_stream_output_service, {
|
|
@@ -370,14 +461,26 @@ __export(exports_stream_output_service, {
|
|
|
370
461
|
COLORS: () => COLORS
|
|
371
462
|
});
|
|
372
463
|
import chalk2 from "chalk";
|
|
373
|
-
import {
|
|
464
|
+
import {
|
|
465
|
+
createLogger as createLogger2,
|
|
466
|
+
TracedAs as TracedAs2,
|
|
467
|
+
wrapFunction
|
|
468
|
+
} from "@ai-setting/roy-agent-core";
|
|
469
|
+
function isStdoutBatchEnabled() {
|
|
470
|
+
const v = process.env.ROY_AGENT_BATCH_STDOUT;
|
|
471
|
+
if (v === undefined)
|
|
472
|
+
return true;
|
|
473
|
+
if (v === "0" || v === "false" || v === "no")
|
|
474
|
+
return false;
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
374
477
|
function resetStreamAbort() {
|
|
375
478
|
streamAbortSignal.aborted = false;
|
|
376
479
|
}
|
|
377
480
|
function abortStream() {
|
|
378
481
|
streamAbortSignal.aborted = true;
|
|
379
482
|
}
|
|
380
|
-
var logger2, COLORS, streamAbortSignal, StreamOutputService;
|
|
483
|
+
var logger2, COLORS, emitBatchFlushSpanImpl = (stats) => {}, emitBatchFlushSpan, emitSilentModeSkippedSpanImpl = (textLength) => {}, emitSilentModeSkippedSpan, streamAbortSignal, StreamOutputService;
|
|
381
484
|
var init_stream_output_service = __esm(() => {
|
|
382
485
|
init_markdown_renderer();
|
|
383
486
|
logger2 = createLogger2("stream-output");
|
|
@@ -397,6 +500,28 @@ var init_stream_output_service = __esm(() => {
|
|
|
397
500
|
error: chalk2.red,
|
|
398
501
|
progress: chalk2.dim
|
|
399
502
|
};
|
|
503
|
+
emitBatchFlushSpan = wrapFunction(emitBatchFlushSpanImpl, "cli.stream-output.writeStdout-batched", {
|
|
504
|
+
recordParams: true,
|
|
505
|
+
recordResult: false,
|
|
506
|
+
log: false,
|
|
507
|
+
paramFilter: (args) => {
|
|
508
|
+
const s = args[0] ?? {};
|
|
509
|
+
return {
|
|
510
|
+
writesInLastBatch: s.writesInLastBatch ?? 0,
|
|
511
|
+
totalBatches: s.batches ?? 0,
|
|
512
|
+
totalBytes: s.totalBytes ?? 0
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
emitSilentModeSkippedSpan = wrapFunction(emitSilentModeSkippedSpanImpl, "stream-output.silent-mode-skipped", {
|
|
517
|
+
recordParams: true,
|
|
518
|
+
recordResult: false,
|
|
519
|
+
log: false,
|
|
520
|
+
paramFilter: (args) => ({
|
|
521
|
+
"text.length": typeof args[0] === "number" ? args[0] : 0,
|
|
522
|
+
reason: "silent=true (Ink mode)"
|
|
523
|
+
})
|
|
524
|
+
});
|
|
400
525
|
streamAbortSignal = {
|
|
401
526
|
aborted: false
|
|
402
527
|
};
|
|
@@ -415,6 +540,7 @@ var init_stream_output_service = __esm(() => {
|
|
|
415
540
|
reasoningClosedByText = false;
|
|
416
541
|
chunkCallback = undefined;
|
|
417
542
|
silent = false;
|
|
543
|
+
stdoutBatcher = null;
|
|
418
544
|
constructor(options = {}) {
|
|
419
545
|
this.options = options;
|
|
420
546
|
this.silent = options.silent ?? false;
|
|
@@ -439,9 +565,33 @@ var init_stream_output_service = __esm(() => {
|
|
|
439
565
|
}
|
|
440
566
|
}
|
|
441
567
|
writeStdout(text) {
|
|
442
|
-
if (this.silent)
|
|
568
|
+
if (this.silent) {
|
|
569
|
+
emitSilentModeSkippedSpan(text.length);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (!isStdoutBatchEnabled()) {
|
|
573
|
+
process.stdout.write(text);
|
|
443
574
|
return;
|
|
444
|
-
|
|
575
|
+
}
|
|
576
|
+
if (this.stdoutBatcher === null) {
|
|
577
|
+
this.stdoutBatcher = createStdoutBatcher({
|
|
578
|
+
flushIntervalMs: 16,
|
|
579
|
+
onFlush: (stats) => {
|
|
580
|
+
emitBatchFlushSpan(stats);
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
this.stdoutBatcher.write(text);
|
|
585
|
+
}
|
|
586
|
+
flushStdout() {
|
|
587
|
+
if (this.stdoutBatcher !== null) {
|
|
588
|
+
this.stdoutBatcher.flushNow();
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
cancelStdout() {
|
|
592
|
+
if (this.stdoutBatcher !== null) {
|
|
593
|
+
this.stdoutBatcher.cancel();
|
|
594
|
+
}
|
|
445
595
|
}
|
|
446
596
|
logStdout(message) {
|
|
447
597
|
if (this.silent)
|
|
@@ -686,8 +836,60 @@ ${COLORS.system("[已中断]")}
|
|
|
686
836
|
this.reasoningStarted = false;
|
|
687
837
|
this.reasoningClosedByText = false;
|
|
688
838
|
this.thinkingPrinted = false;
|
|
839
|
+
this.flushStdout();
|
|
689
840
|
}
|
|
690
841
|
};
|
|
842
|
+
__legacyDecorateClassTS([
|
|
843
|
+
TracedAs2("cli.stream-output.writeStdout", {
|
|
844
|
+
recordParams: true,
|
|
845
|
+
recordResult: false,
|
|
846
|
+
log: false,
|
|
847
|
+
paramFilter: (args) => ({
|
|
848
|
+
"text.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
849
|
+
"text.head": typeof args[0] === "string" ? args[0].slice(0, 32) : "",
|
|
850
|
+
"text.tail": typeof args[0] === "string" ? args[0].slice(-32) : "",
|
|
851
|
+
"batch.enabled": isStdoutBatchEnabled() ? 1 : 0
|
|
852
|
+
})
|
|
853
|
+
}),
|
|
854
|
+
__legacyMetadataTS("design:type", Function),
|
|
855
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
856
|
+
String
|
|
857
|
+
]),
|
|
858
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
859
|
+
], StreamOutputService.prototype, "writeStdout", null);
|
|
860
|
+
__legacyDecorateClassTS([
|
|
861
|
+
TracedAs2("stream.handle-event", {
|
|
862
|
+
recordParams: true,
|
|
863
|
+
recordResult: false,
|
|
864
|
+
paramFilter: (args) => {
|
|
865
|
+
const e = args[0] ?? {};
|
|
866
|
+
const payload = e.payload ?? {};
|
|
867
|
+
return {
|
|
868
|
+
"event.type": e.type ?? "unknown",
|
|
869
|
+
"event.payload.kind": payload && typeof payload === "object" ? Object.keys(payload).join(",") : ""
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
}),
|
|
873
|
+
__legacyMetadataTS("design:type", Function),
|
|
874
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
875
|
+
typeof EnvEvent === "undefined" ? Object : EnvEvent
|
|
876
|
+
]),
|
|
877
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
878
|
+
], StreamOutputService.prototype, "handleEvent", null);
|
|
879
|
+
__legacyDecorateClassTS([
|
|
880
|
+
TracedAs2("stream.handle-start", {
|
|
881
|
+
recordParams: true,
|
|
882
|
+
recordResult: false,
|
|
883
|
+
paramFilter: (args) => ({
|
|
884
|
+
model: args[0]?.metadata?.model ?? ""
|
|
885
|
+
})
|
|
886
|
+
}),
|
|
887
|
+
__legacyMetadataTS("design:type", Function),
|
|
888
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
889
|
+
Object
|
|
890
|
+
]),
|
|
891
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
892
|
+
], StreamOutputService.prototype, "handleStart", null);
|
|
691
893
|
__legacyDecorateClassTS([
|
|
692
894
|
TracedAs2("stream.handle-text", {
|
|
693
895
|
recordParams: true,
|
|
@@ -703,6 +905,102 @@ ${COLORS.system("[已中断]")}
|
|
|
703
905
|
]),
|
|
704
906
|
__legacyMetadataTS("design:returntype", undefined)
|
|
705
907
|
], StreamOutputService.prototype, "handleText", null);
|
|
908
|
+
__legacyDecorateClassTS([
|
|
909
|
+
TracedAs2("stream.handle-reasoning", {
|
|
910
|
+
recordParams: true,
|
|
911
|
+
recordResult: false,
|
|
912
|
+
paramFilter: (args) => ({
|
|
913
|
+
"delta.length": args[0]?.delta?.length ?? 0,
|
|
914
|
+
"content.length": args[0]?.content?.length ?? 0,
|
|
915
|
+
phase: args[0]?.phase ?? ""
|
|
916
|
+
})
|
|
917
|
+
}),
|
|
918
|
+
__legacyMetadataTS("design:type", Function),
|
|
919
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
920
|
+
Object
|
|
921
|
+
]),
|
|
922
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
923
|
+
], StreamOutputService.prototype, "handleReasoning", null);
|
|
924
|
+
__legacyDecorateClassTS([
|
|
925
|
+
TracedAs2("stream.handle-tool-call", {
|
|
926
|
+
recordParams: true,
|
|
927
|
+
recordResult: false,
|
|
928
|
+
log: true,
|
|
929
|
+
paramFilter: (args) => {
|
|
930
|
+
const p = args[0] ?? {};
|
|
931
|
+
return {
|
|
932
|
+
"tool.name": p.name ?? "unknown",
|
|
933
|
+
"tool.id": p.id ?? "",
|
|
934
|
+
"tool.args.keys": p.arguments ? Object.keys(p.arguments).join(",") : ""
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
}),
|
|
938
|
+
__legacyMetadataTS("design:type", Function),
|
|
939
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
940
|
+
Object
|
|
941
|
+
]),
|
|
942
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
943
|
+
], StreamOutputService.prototype, "handleToolCall", null);
|
|
944
|
+
__legacyDecorateClassTS([
|
|
945
|
+
TracedAs2("stream.handle-tool-result", {
|
|
946
|
+
recordParams: true,
|
|
947
|
+
recordResult: false,
|
|
948
|
+
log: true,
|
|
949
|
+
paramFilter: (args) => {
|
|
950
|
+
const p = args[0] ?? {};
|
|
951
|
+
const result = p.result?.output ?? p.result?.error;
|
|
952
|
+
return {
|
|
953
|
+
"tool.name": p.name ?? "unknown",
|
|
954
|
+
"tool.result.kind": result !== undefined ? typeof result : "none",
|
|
955
|
+
"tool.result.preview": typeof result === "string" ? result.substring(0, 80) : typeof result === "object" && result !== null ? JSON.stringify(result).substring(0, 80) : ""
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
}),
|
|
959
|
+
__legacyMetadataTS("design:type", Function),
|
|
960
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
961
|
+
Object
|
|
962
|
+
]),
|
|
963
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
964
|
+
], StreamOutputService.prototype, "handleToolResult", null);
|
|
965
|
+
__legacyDecorateClassTS([
|
|
966
|
+
TracedAs2("stream.handle-tool-error", {
|
|
967
|
+
recordParams: true,
|
|
968
|
+
recordResult: false,
|
|
969
|
+
log: true,
|
|
970
|
+
paramFilter: (args) => {
|
|
971
|
+
const p = args[0] ?? {};
|
|
972
|
+
return {
|
|
973
|
+
"tool.name": p.toolName ?? "unknown",
|
|
974
|
+
"tool.error.preview": typeof p.error === "string" ? p.error.substring(0, 120) : ""
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
}),
|
|
978
|
+
__legacyMetadataTS("design:type", Function),
|
|
979
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
980
|
+
Object
|
|
981
|
+
]),
|
|
982
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
983
|
+
], StreamOutputService.prototype, "handleToolError", null);
|
|
984
|
+
__legacyDecorateClassTS([
|
|
985
|
+
TracedAs2("stream.handle-completed", {
|
|
986
|
+
recordParams: true,
|
|
987
|
+
recordResult: false,
|
|
988
|
+
paramFilter: (args) => {
|
|
989
|
+
const meta = args[0]?.metadata;
|
|
990
|
+
return {
|
|
991
|
+
model: meta?.model ?? "",
|
|
992
|
+
"usage.promptTokens": meta?.usage?.promptTokens ?? 0,
|
|
993
|
+
"usage.completionTokens": meta?.usage?.completionTokens ?? 0,
|
|
994
|
+
"usage.totalTokens": meta?.usage?.totalTokens ?? 0
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
}),
|
|
998
|
+
__legacyMetadataTS("design:type", Function),
|
|
999
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
1000
|
+
Object
|
|
1001
|
+
]),
|
|
1002
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
1003
|
+
], StreamOutputService.prototype, "handleCompleted", null);
|
|
706
1004
|
});
|
|
707
1005
|
|
|
708
1006
|
// src/commands/ui/mascot/glasses-girl.ts
|
|
@@ -1088,9 +1386,10 @@ var init_slash_command_popup = __esm(() => {
|
|
|
1088
1386
|
});
|
|
1089
1387
|
});
|
|
1090
1388
|
|
|
1091
|
-
// src/render/markdown.
|
|
1389
|
+
// src/render/markdown.ts
|
|
1092
1390
|
import { Marked } from "marked";
|
|
1093
1391
|
import { highlight } from "cli-highlight";
|
|
1392
|
+
import { wrapFunction as wrapFunction2 } from "@ai-setting/roy-agent-core";
|
|
1094
1393
|
function setMarkdownEnabled(enabled) {
|
|
1095
1394
|
markdownEnabled = enabled;
|
|
1096
1395
|
}
|
|
@@ -1333,7 +1632,50 @@ function wrapLine(line, width) {
|
|
|
1333
1632
|
return out.join(`
|
|
1334
1633
|
`);
|
|
1335
1634
|
}
|
|
1336
|
-
function
|
|
1635
|
+
function cacheLookup(key) {
|
|
1636
|
+
for (let i = 0;i < renderCache.length; i++) {
|
|
1637
|
+
if (renderCache[i].key === key) {
|
|
1638
|
+
const entry = renderCache[i];
|
|
1639
|
+
if (i > 0) {
|
|
1640
|
+
renderCache.splice(i, 1);
|
|
1641
|
+
renderCache.unshift(entry);
|
|
1642
|
+
}
|
|
1643
|
+
return entry.value;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
function cacheInsert(key, value, text, width) {
|
|
1649
|
+
if (renderCache.length >= MAX_CACHE_ENTRIES) {
|
|
1650
|
+
renderCache.pop();
|
|
1651
|
+
}
|
|
1652
|
+
renderCache.unshift({ key, value, text, width });
|
|
1653
|
+
renderCacheStats.size = renderCache.length;
|
|
1654
|
+
}
|
|
1655
|
+
function findPrefixCacheEntry(text, width) {
|
|
1656
|
+
let best;
|
|
1657
|
+
let bestLen = -1;
|
|
1658
|
+
for (let i = 0;i < renderCache.length; i++) {
|
|
1659
|
+
const e = renderCache[i];
|
|
1660
|
+
if (e.width !== width)
|
|
1661
|
+
continue;
|
|
1662
|
+
if (e.text.length === 0)
|
|
1663
|
+
continue;
|
|
1664
|
+
if (text.startsWith(e.text) && e.text.length > bestLen) {
|
|
1665
|
+
best = e;
|
|
1666
|
+
bestLen = e.text.length;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
return best;
|
|
1670
|
+
}
|
|
1671
|
+
function isSuffixSafeToLexIndependently(suffix) {
|
|
1672
|
+
if (suffix.length === 0)
|
|
1673
|
+
return true;
|
|
1674
|
+
if (suffix.charCodeAt(0) !== 10)
|
|
1675
|
+
return true;
|
|
1676
|
+
return false;
|
|
1677
|
+
}
|
|
1678
|
+
function renderMarkdownImpl(text, options = {}) {
|
|
1337
1679
|
const width = options.width ?? 80;
|
|
1338
1680
|
if (!markdownEnabled) {
|
|
1339
1681
|
return wrapLine(text, width);
|
|
@@ -1341,6 +1683,28 @@ function renderMarkdown(text, options = {}) {
|
|
|
1341
1683
|
if (!text || text.trim() === "") {
|
|
1342
1684
|
return "";
|
|
1343
1685
|
}
|
|
1686
|
+
const key = text + "\x00" + width;
|
|
1687
|
+
const cached = cacheLookup(key);
|
|
1688
|
+
if (cached !== undefined) {
|
|
1689
|
+
renderCacheStats.hits++;
|
|
1690
|
+
renderCacheStats.cachedHits++;
|
|
1691
|
+
return cached;
|
|
1692
|
+
}
|
|
1693
|
+
const prefixEntry = findPrefixCacheEntry(text, width);
|
|
1694
|
+
if (prefixEntry !== undefined) {
|
|
1695
|
+
const suffix = text.slice(prefixEntry.text.length);
|
|
1696
|
+
if (isSuffixSafeToLexIndependently(suffix)) {
|
|
1697
|
+
const suffixRender = renderMarkdownImpl(suffix, { width });
|
|
1698
|
+
const combined = prefixEntry.value + suffixRender;
|
|
1699
|
+
cacheInsert(key, combined, text, width);
|
|
1700
|
+
renderCacheStats.hits++;
|
|
1701
|
+
renderCacheStats.prefixHits++;
|
|
1702
|
+
renderCacheStats.partialParses++;
|
|
1703
|
+
return combined;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
renderCacheStats.misses++;
|
|
1707
|
+
renderCacheStats.partialParses++;
|
|
1344
1708
|
let tokens;
|
|
1345
1709
|
try {
|
|
1346
1710
|
tokens = marked.lexer(text);
|
|
@@ -1354,9 +1718,11 @@ function renderMarkdown(text, options = {}) {
|
|
|
1354
1718
|
lines.push(block);
|
|
1355
1719
|
}
|
|
1356
1720
|
}
|
|
1357
|
-
|
|
1721
|
+
const result = lines.join(`
|
|
1358
1722
|
|
|
1359
1723
|
`);
|
|
1724
|
+
cacheInsert(key, result, text, width);
|
|
1725
|
+
return result;
|
|
1360
1726
|
}
|
|
1361
1727
|
function truncateForTerminal(text, maxLines) {
|
|
1362
1728
|
if (maxLines <= 0) {
|
|
@@ -1452,7 +1818,7 @@ function tailTruncateToRows(line, rows, width) {
|
|
|
1452
1818
|
const tail = segments.join("");
|
|
1453
1819
|
return tail + ANSI2.reset;
|
|
1454
1820
|
}
|
|
1455
|
-
var ANSI2, DEFAULT_THEME, markdownEnabled = true, marked, ANSI_CSI_RE;
|
|
1821
|
+
var ANSI2, DEFAULT_THEME, markdownEnabled = true, marked, MAX_CACHE_ENTRIES = 32, renderCache, renderCacheStats, renderMarkdown, ANSI_CSI_RE;
|
|
1456
1822
|
var init_markdown = __esm(() => {
|
|
1457
1823
|
ANSI2 = {
|
|
1458
1824
|
reset: "\x1B[0m",
|
|
@@ -1494,11 +1860,36 @@ var init_markdown = __esm(() => {
|
|
|
1494
1860
|
breaks: false,
|
|
1495
1861
|
pedantic: false
|
|
1496
1862
|
});
|
|
1863
|
+
renderCache = [];
|
|
1864
|
+
renderCacheStats = {
|
|
1865
|
+
hits: 0,
|
|
1866
|
+
prefixHits: 0,
|
|
1867
|
+
misses: 0,
|
|
1868
|
+
partialParses: 0,
|
|
1869
|
+
cachedHits: 0,
|
|
1870
|
+
size: 0
|
|
1871
|
+
};
|
|
1872
|
+
renderMarkdown = wrapFunction2(renderMarkdownImpl, "markdown.render", {
|
|
1873
|
+
recordParams: true,
|
|
1874
|
+
recordResult: true,
|
|
1875
|
+
paramFilter: (args) => ({
|
|
1876
|
+
"input.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
1877
|
+
"options.width": typeof args[1]?.width === "number" ? args[1].width : 0
|
|
1878
|
+
}),
|
|
1879
|
+
resultFilter: (result) => ({
|
|
1880
|
+
"output.length": typeof result === "string" ? result.length : 0,
|
|
1881
|
+
"cache.hits": renderCacheStats.hits,
|
|
1882
|
+
"cache.prefixHits": renderCacheStats.prefixHits,
|
|
1883
|
+
"cache.misses": renderCacheStats.misses,
|
|
1884
|
+
"cache.partialParses": renderCacheStats.partialParses,
|
|
1885
|
+
"cache.size": renderCacheStats.size
|
|
1886
|
+
}),
|
|
1887
|
+
log: false
|
|
1888
|
+
});
|
|
1497
1889
|
ANSI_CSI_RE = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
1498
1890
|
});
|
|
1499
1891
|
|
|
1500
|
-
// src/tui/Markdown.
|
|
1501
|
-
import React2 from "react";
|
|
1892
|
+
// src/tui/Markdown.tsx
|
|
1502
1893
|
import { Text as Text2 } from "ink";
|
|
1503
1894
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
1504
1895
|
var Markdown = ({ text, width }) => {
|
|
@@ -1515,7 +1906,7 @@ var init_Markdown = __esm(() => {
|
|
|
1515
1906
|
init_markdown();
|
|
1516
1907
|
});
|
|
1517
1908
|
|
|
1518
|
-
// src/tui/theme.
|
|
1909
|
+
// src/tui/theme.ts
|
|
1519
1910
|
function shouldSuppressColors(env) {
|
|
1520
1911
|
if (env.NO_COLOR && env.NO_COLOR !== "0" && env.NO_COLOR !== "false") {
|
|
1521
1912
|
return true;
|
|
@@ -1559,11 +1950,14 @@ var init_theme = __esm(() => {
|
|
|
1559
1950
|
};
|
|
1560
1951
|
});
|
|
1561
1952
|
|
|
1562
|
-
// src/tui/StatusBar.
|
|
1563
|
-
import React3 from "react";
|
|
1953
|
+
// src/tui/StatusBar.tsx
|
|
1564
1954
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
1565
1955
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
1566
|
-
var StatusBar = ({
|
|
1956
|
+
var StatusBar = ({
|
|
1957
|
+
model,
|
|
1958
|
+
workdir,
|
|
1959
|
+
tokenCount
|
|
1960
|
+
}) => {
|
|
1567
1961
|
const theme = getTheme();
|
|
1568
1962
|
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
1569
1963
|
borderStyle: "single",
|
|
@@ -1674,7 +2068,7 @@ __export(exports_repl_ink, {
|
|
|
1674
2068
|
REPLInk: () => REPLInk,
|
|
1675
2069
|
MultilineInput: () => MultilineInput
|
|
1676
2070
|
});
|
|
1677
|
-
import * as
|
|
2071
|
+
import * as React2 from "react";
|
|
1678
2072
|
import { Box as Box3, Text as Text4, Static, useApp, useInput as useInput2 } from "ink";
|
|
1679
2073
|
import { createLogger as createLogger5 } from "@ai-setting/roy-agent-core";
|
|
1680
2074
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
@@ -1699,7 +2093,7 @@ function REPLInk(props) {
|
|
|
1699
2093
|
onEscape
|
|
1700
2094
|
} = props;
|
|
1701
2095
|
const { exit: appExit } = useApp();
|
|
1702
|
-
const [messages, setMessages] =
|
|
2096
|
+
const [messages, setMessages] = React2.useState(() => [
|
|
1703
2097
|
withMessageId({
|
|
1704
2098
|
role: "system",
|
|
1705
2099
|
kind: "welcome",
|
|
@@ -1707,47 +2101,47 @@ function REPLInk(props) {
|
|
|
1707
2101
|
}),
|
|
1708
2102
|
...initialMessages.map(withMessageId)
|
|
1709
2103
|
]);
|
|
1710
|
-
const [mode, setMode] =
|
|
1711
|
-
const [statusBarCtx, setStatusBarCtxState] =
|
|
2104
|
+
const [mode, setMode] = React2.useState(initialMode);
|
|
2105
|
+
const [statusBarCtx, setStatusBarCtxState] = React2.useState({
|
|
1712
2106
|
mode: initialMode,
|
|
1713
2107
|
cwd: initialStatusBarCtx.cwd ?? initialContext.cwd,
|
|
1714
2108
|
gitBranch: initialStatusBarCtx.gitBranch,
|
|
1715
2109
|
model: initialStatusBarCtx.model ?? initialContext.model
|
|
1716
2110
|
});
|
|
1717
|
-
const [inputValue, setInputValue] =
|
|
1718
|
-
const [popupIndex, setPopupIndex] =
|
|
1719
|
-
const filteredCmds =
|
|
2111
|
+
const [inputValue, setInputValue] = React2.useState("");
|
|
2112
|
+
const [popupIndex, setPopupIndex] = React2.useState(0);
|
|
2113
|
+
const filteredCmds = React2.useMemo(() => {
|
|
1720
2114
|
if (!/^\/\S*$/.test(inputValue))
|
|
1721
2115
|
return [];
|
|
1722
2116
|
return filterCommands(inputValue);
|
|
1723
2117
|
}, [inputValue]);
|
|
1724
2118
|
const showPopup = filteredCmds.length > 0;
|
|
1725
|
-
|
|
2119
|
+
React2.useEffect(() => {
|
|
1726
2120
|
setPopupIndex(0);
|
|
1727
2121
|
}, [filteredCmds]);
|
|
1728
2122
|
const safePopupIndex = clampSelectedIndex(popupIndex, filteredCmds.length);
|
|
1729
|
-
const handlePopupSelect =
|
|
2123
|
+
const handlePopupSelect = React2.useCallback((cmd) => {
|
|
1730
2124
|
multilineInputRef.current?.setBuffer(cmd.cmd + " ");
|
|
1731
2125
|
setInputValue(cmd.cmd + " ");
|
|
1732
2126
|
}, []);
|
|
1733
|
-
const handlePopupClose =
|
|
2127
|
+
const handlePopupClose = React2.useCallback(() => {
|
|
1734
2128
|
const current = multilineInputRef.current?.getBuffer() ?? "";
|
|
1735
2129
|
const stripped = current.replace(/^\/+/, "");
|
|
1736
2130
|
multilineInputRef.current?.setBuffer(stripped);
|
|
1737
2131
|
setInputValue(stripped);
|
|
1738
2132
|
}, []);
|
|
1739
|
-
const handlePopupIndexChange =
|
|
2133
|
+
const handlePopupIndexChange = React2.useCallback((idx) => {
|
|
1740
2134
|
setPopupIndex(idx);
|
|
1741
2135
|
}, []);
|
|
1742
|
-
const streamingIndexRef =
|
|
1743
|
-
const lastFlushTsRef =
|
|
2136
|
+
const streamingIndexRef = React2.useRef(-1);
|
|
2137
|
+
const lastFlushTsRef = React2.useRef(0);
|
|
1744
2138
|
const STALE_STREAM_THRESHOLD_MS = 1000;
|
|
1745
|
-
const multilineInputRef =
|
|
1746
|
-
const lastEscapeTsRef =
|
|
1747
|
-
const pendingDeltaRef =
|
|
1748
|
-
const throttleTimerRef =
|
|
1749
|
-
const isFirstDeltaInStreamRef =
|
|
1750
|
-
const flushStreamingDelta =
|
|
2139
|
+
const multilineInputRef = React2.useRef(null);
|
|
2140
|
+
const lastEscapeTsRef = React2.useRef(0);
|
|
2141
|
+
const pendingDeltaRef = React2.useRef("");
|
|
2142
|
+
const throttleTimerRef = React2.useRef(null);
|
|
2143
|
+
const isFirstDeltaInStreamRef = React2.useRef(true);
|
|
2144
|
+
const flushStreamingDelta = React2.useCallback(() => {
|
|
1751
2145
|
const delta = pendingDeltaRef.current;
|
|
1752
2146
|
pendingDeltaRef.current = "";
|
|
1753
2147
|
throttleTimerRef.current = null;
|
|
@@ -1776,7 +2170,7 @@ function REPLInk(props) {
|
|
|
1776
2170
|
});
|
|
1777
2171
|
lastFlushTsRef.current = Date.now();
|
|
1778
2172
|
}, []);
|
|
1779
|
-
|
|
2173
|
+
React2.useEffect(() => {
|
|
1780
2174
|
return () => {
|
|
1781
2175
|
if (throttleTimerRef.current !== null) {
|
|
1782
2176
|
clearTimeout(throttleTimerRef.current);
|
|
@@ -1784,8 +2178,8 @@ function REPLInk(props) {
|
|
|
1784
2178
|
}
|
|
1785
2179
|
};
|
|
1786
2180
|
}, []);
|
|
1787
|
-
const apiRef =
|
|
1788
|
-
|
|
2181
|
+
const apiRef = React2.useRef(null);
|
|
2182
|
+
React2.useEffect(() => {
|
|
1789
2183
|
const api = {
|
|
1790
2184
|
appendMessage: (msg) => {
|
|
1791
2185
|
setMessages((msgs) => [...msgs, withMessageId(msg)]);
|
|
@@ -1861,7 +2255,7 @@ function REPLInk(props) {
|
|
|
1861
2255
|
apiRef.current = api;
|
|
1862
2256
|
onReady?.(api);
|
|
1863
2257
|
}, [appExit, onCommand, onReady]);
|
|
1864
|
-
const handleEscapeCascade =
|
|
2258
|
+
const handleEscapeCascade = React2.useCallback(() => {
|
|
1865
2259
|
const now = Date.now();
|
|
1866
2260
|
if (now - lastEscapeTsRef.current < 100) {
|
|
1867
2261
|
return;
|
|
@@ -1905,7 +2299,7 @@ function REPLInk(props) {
|
|
|
1905
2299
|
}
|
|
1906
2300
|
}
|
|
1907
2301
|
});
|
|
1908
|
-
const handleSubmit =
|
|
2302
|
+
const handleSubmit = React2.useCallback(async (value) => {
|
|
1909
2303
|
if (!value || value.trim() === "") {
|
|
1910
2304
|
return;
|
|
1911
2305
|
}
|
|
@@ -1934,7 +2328,7 @@ function REPLInk(props) {
|
|
|
1934
2328
|
]);
|
|
1935
2329
|
}
|
|
1936
2330
|
}, [onCommand, onSubmit]);
|
|
1937
|
-
const staticItems =
|
|
2331
|
+
const staticItems = React2.useMemo(() => {
|
|
1938
2332
|
if (messages.length <= 1)
|
|
1939
2333
|
return [];
|
|
1940
2334
|
return messages.slice(0, -1);
|
|
@@ -1942,8 +2336,8 @@ function REPLInk(props) {
|
|
|
1942
2336
|
const tailMsg = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
1943
2337
|
const terminalWidth = process.stdout.columns ?? 80;
|
|
1944
2338
|
const terminalHeight = process.stdout.rows ?? 24;
|
|
1945
|
-
const dynamicTailBounds =
|
|
1946
|
-
const staticTailBounds =
|
|
2339
|
+
const dynamicTailBounds = React2.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
2340
|
+
const staticTailBounds = React2.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
1947
2341
|
const tailKey = messages.length > 0 ? tailMsg?.id ?? `tail-${messages.length - 1}` : "tail-empty";
|
|
1948
2342
|
const statusBarModel = shortModel(statusBarCtx.model);
|
|
1949
2343
|
const statusBarWorkdir = statusBarCtx.cwd;
|
|
@@ -2010,7 +2404,7 @@ function shortModel(model) {
|
|
|
2010
2404
|
}
|
|
2011
2405
|
async function renderInkREPL(props) {
|
|
2012
2406
|
const ink = await import("ink");
|
|
2013
|
-
const { waitUntilExit } = ink.render(
|
|
2407
|
+
const { waitUntilExit } = ink.render(React2.createElement(REPLInk, props));
|
|
2014
2408
|
await waitUntilExit();
|
|
2015
2409
|
}
|
|
2016
2410
|
var MarkdownBounded, inkLogger, _msgIdCounter = 0, MultilineInput, MessageView;
|
|
@@ -2022,7 +2416,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2022
2416
|
init_Markdown();
|
|
2023
2417
|
init_StatusBar();
|
|
2024
2418
|
init_dynamic_tail();
|
|
2025
|
-
MarkdownBounded =
|
|
2419
|
+
MarkdownBounded = React2.memo(({ text, bounds, width }) => {
|
|
2026
2420
|
const out = renderBoundedAssistant(text, bounds, width);
|
|
2027
2421
|
if (!out) {
|
|
2028
2422
|
return null;
|
|
@@ -2032,16 +2426,16 @@ var init_repl_ink = __esm(() => {
|
|
|
2032
2426
|
}, undefined, false, undefined, this);
|
|
2033
2427
|
});
|
|
2034
2428
|
inkLogger = createLogger5("repl-ink");
|
|
2035
|
-
MultilineInput =
|
|
2429
|
+
MultilineInput = React2.memo(React2.forwardRef(function MultilineInput2(props, ref) {
|
|
2036
2430
|
const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
|
|
2037
|
-
const [buffer, setBuffer] =
|
|
2038
|
-
const [cursor, setCursor] =
|
|
2039
|
-
|
|
2431
|
+
const [buffer, setBuffer] = React2.useState("");
|
|
2432
|
+
const [cursor, setCursor] = React2.useState(0);
|
|
2433
|
+
React2.useEffect(() => {
|
|
2040
2434
|
if (popupActive || buffer.startsWith("/")) {
|
|
2041
2435
|
onChange?.(buffer);
|
|
2042
2436
|
}
|
|
2043
2437
|
}, [buffer, onChange, popupActive]);
|
|
2044
|
-
|
|
2438
|
+
React2.useImperativeHandle(ref, () => ({
|
|
2045
2439
|
clearBuffer: () => {
|
|
2046
2440
|
setBuffer("");
|
|
2047
2441
|
setCursor(0);
|
|
@@ -2279,7 +2673,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2279
2673
|
})
|
|
2280
2674
|
}, undefined, false, undefined, this);
|
|
2281
2675
|
}));
|
|
2282
|
-
MessageView =
|
|
2676
|
+
MessageView = React2.memo(function MessageView2({
|
|
2283
2677
|
msg,
|
|
2284
2678
|
terminalWidth,
|
|
2285
2679
|
tailBounds
|
|
@@ -9459,7 +9853,7 @@ class CliQuietModeService {
|
|
|
9459
9853
|
// package.json
|
|
9460
9854
|
var package_default = {
|
|
9461
9855
|
name: "@ai-setting/roy-agent-cli",
|
|
9462
|
-
version: "1.7.
|
|
9856
|
+
version: "1.7.21",
|
|
9463
9857
|
type: "module",
|
|
9464
9858
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9465
9859
|
main: "./dist/index.js",
|
|
@@ -10614,6 +11008,21 @@ function finalizeActStdout(args) {
|
|
|
10614
11008
|
output.log(result);
|
|
10615
11009
|
}
|
|
10616
11010
|
|
|
11011
|
+
// src/commands/shared/debug-trace.ts
|
|
11012
|
+
function printTraceIdAfterResponse(traceId, options) {
|
|
11013
|
+
const enabled = typeof options === "boolean" ? options : options.enabled;
|
|
11014
|
+
if (!enabled)
|
|
11015
|
+
return;
|
|
11016
|
+
const writer = typeof options === "object" && options.write ? options.write : (chunk) => process.stderr.write(chunk);
|
|
11017
|
+
writer(`[Trace] ${traceId}
|
|
11018
|
+
`);
|
|
11019
|
+
if (typeof options === "object" && typeof options.tuiSink === "function") {
|
|
11020
|
+
try {
|
|
11021
|
+
options.tuiSink(traceId);
|
|
11022
|
+
} catch (_tuiErr) {}
|
|
11023
|
+
}
|
|
11024
|
+
}
|
|
11025
|
+
|
|
10617
11026
|
// src/commands/act.ts
|
|
10618
11027
|
function detectWorkspaceRoot(cwd = process.cwd(), runGit = execFileSync) {
|
|
10619
11028
|
try {
|
|
@@ -10681,6 +11090,10 @@ function createActCommand(externalEnvService) {
|
|
|
10681
11090
|
describe: "附加图片到消息(可多次传入;支持本地路径 / http(s) URL / data:base64)",
|
|
10682
11091
|
type: "array",
|
|
10683
11092
|
string: true
|
|
11093
|
+
}).option("debug-on", {
|
|
11094
|
+
describe: "调试模式:响应结束后输出 [Trace] <traceId>(stderr),便于追踪调用 trace",
|
|
11095
|
+
type: "boolean",
|
|
11096
|
+
default: false
|
|
10684
11097
|
}),
|
|
10685
11098
|
async handler(args) {
|
|
10686
11099
|
const quiet = args.quiet ?? true;
|
|
@@ -10917,9 +11330,6 @@ function createActCommand(externalEnvService) {
|
|
|
10917
11330
|
}
|
|
10918
11331
|
});
|
|
10919
11332
|
const traceId = rootSpan.spanContext.traceId;
|
|
10920
|
-
if (!quiet) {
|
|
10921
|
-
output.info(`[Trace] ${traceId}`);
|
|
10922
|
-
}
|
|
10923
11333
|
provider.setGlobalContext(rootSpan.spanContext);
|
|
10924
11334
|
const contextHandler = new ContextHandlerService(env, sessionComponent, { maxRetries: 1, autoCompact: true });
|
|
10925
11335
|
const context = {
|
|
@@ -10954,6 +11364,7 @@ function createActCommand(externalEnvService) {
|
|
|
10954
11364
|
streamService,
|
|
10955
11365
|
output
|
|
10956
11366
|
});
|
|
11367
|
+
printTraceIdAfterResponse(traceId, args.debugOn ?? false);
|
|
10957
11368
|
if (!quiet) {
|
|
10958
11369
|
if (isWorkflowPausedActResult(result)) {
|
|
10959
11370
|
output.warn("工作流已暂停,等待用户输入(见上方 resume 提示)");
|
|
@@ -11272,6 +11683,35 @@ class QueryExecutor {
|
|
|
11272
11683
|
}
|
|
11273
11684
|
}
|
|
11274
11685
|
}
|
|
11686
|
+
__legacyDecorateClassTS([
|
|
11687
|
+
TracedAs4("cli.query-executor.setChunkCallback", {
|
|
11688
|
+
recordParams: true,
|
|
11689
|
+
recordResult: false,
|
|
11690
|
+
log: true,
|
|
11691
|
+
paramFilter: (args) => ({
|
|
11692
|
+
"cb.isFunction": typeof args[0] === "function"
|
|
11693
|
+
})
|
|
11694
|
+
}),
|
|
11695
|
+
__legacyMetadataTS("design:type", Function),
|
|
11696
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
11697
|
+
typeof StreamChunkCallback === "undefined" ? Object : StreamChunkCallback
|
|
11698
|
+
]),
|
|
11699
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
11700
|
+
], QueryExecutor.prototype, "setChunkCallback", null);
|
|
11701
|
+
__legacyDecorateClassTS([
|
|
11702
|
+
TracedAs4("cli.query-executor.handleEvent", {
|
|
11703
|
+
recordParams: true,
|
|
11704
|
+
recordResult: false,
|
|
11705
|
+
paramFilter: (args) => ({
|
|
11706
|
+
"event.type": args[0]?.type ?? "unknown"
|
|
11707
|
+
})
|
|
11708
|
+
}),
|
|
11709
|
+
__legacyMetadataTS("design:type", Function),
|
|
11710
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
11711
|
+
Object
|
|
11712
|
+
]),
|
|
11713
|
+
__legacyMetadataTS("design:returntype", undefined)
|
|
11714
|
+
], QueryExecutor.prototype, "handleEvent", null);
|
|
11275
11715
|
__legacyDecorateClassTS([
|
|
11276
11716
|
TracedAs4("cli.query-executor.execute", { recordParams: true, log: true }),
|
|
11277
11717
|
__legacyMetadataTS("design:type", Function),
|
|
@@ -11698,6 +12138,16 @@ class EventHandler {
|
|
|
11698
12138
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11699
12139
|
}
|
|
11700
12140
|
}
|
|
12141
|
+
__legacyDecorateClassTS([
|
|
12142
|
+
TracedAs5("cli.event-handler.start", {
|
|
12143
|
+
recordParams: false,
|
|
12144
|
+
recordResult: false,
|
|
12145
|
+
log: true
|
|
12146
|
+
}),
|
|
12147
|
+
__legacyMetadataTS("design:type", Function),
|
|
12148
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
12149
|
+
__legacyMetadataTS("design:returntype", Function)
|
|
12150
|
+
], EventHandler.prototype, "start", null);
|
|
11701
12151
|
__legacyDecorateClassTS([
|
|
11702
12152
|
TracedAs5("cli.event-handler.handleEvent", { recordParams: true }),
|
|
11703
12153
|
__legacyMetadataTS("design:type", Function),
|
|
@@ -11706,6 +12156,16 @@ __legacyDecorateClassTS([
|
|
|
11706
12156
|
]),
|
|
11707
12157
|
__legacyMetadataTS("design:returntype", undefined)
|
|
11708
12158
|
], EventHandler.prototype, "handleEvent", null);
|
|
12159
|
+
__legacyDecorateClassTS([
|
|
12160
|
+
TracedAs5("cli.event-handler.processQueue", {
|
|
12161
|
+
recordParams: false,
|
|
12162
|
+
recordResult: false,
|
|
12163
|
+
log: true
|
|
12164
|
+
}),
|
|
12165
|
+
__legacyMetadataTS("design:type", Function),
|
|
12166
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
12167
|
+
__legacyMetadataTS("design:returntype", typeof Promise === "undefined" ? Object : Promise)
|
|
12168
|
+
], EventHandler.prototype, "processQueue", null);
|
|
11709
12169
|
|
|
11710
12170
|
// src/commands/shared/esc-active-descendant.ts
|
|
11711
12171
|
function hasActiveDescendants(env, parentSessionId) {
|
|
@@ -12652,8 +13112,23 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
12652
13112
|
onSubmit: async (input) => {
|
|
12653
13113
|
this.isExecuting = true;
|
|
12654
13114
|
inkApiRef?.setMode("executing");
|
|
13115
|
+
const inkTracerProvider = getTracerProvider3();
|
|
13116
|
+
const inkTracer = inkTracerProvider.getTracer("roy-tracer");
|
|
13117
|
+
const inkExistingContext = inkTracerProvider.getGlobalContext();
|
|
13118
|
+
let inkRootSpan;
|
|
13119
|
+
let inkTurnTraceId;
|
|
13120
|
+
if (inkExistingContext) {
|
|
13121
|
+
inkRootSpan = inkTracer.startSpan("interactive.execute", {
|
|
13122
|
+
parent: inkExistingContext
|
|
13123
|
+
});
|
|
13124
|
+
inkTurnTraceId = inkExistingContext.traceId;
|
|
13125
|
+
} else {
|
|
13126
|
+
inkRootSpan = inkTracer.startSpan("interactive.execute");
|
|
13127
|
+
inkTurnTraceId = inkRootSpan.spanContext.traceId;
|
|
13128
|
+
inkTracerProvider.setGlobalContext(inkRootSpan.spanContext);
|
|
13129
|
+
}
|
|
12655
13130
|
try {
|
|
12656
|
-
await this.options.onExecute(input);
|
|
13131
|
+
await this.options.onExecute(input, inkTurnTraceId, undefined);
|
|
12657
13132
|
inkApiRef?.setMode("ready");
|
|
12658
13133
|
if (this.options.onAfterExecute) {
|
|
12659
13134
|
try {
|
|
@@ -12668,6 +13143,26 @@ ${COLORS.system("[没有正在执行的请求]")}`);
|
|
|
12668
13143
|
inkApiRef?.appendMessage({ role: "system", content: `[Error] ${msg}` });
|
|
12669
13144
|
throw err;
|
|
12670
13145
|
} finally {
|
|
13146
|
+
try {
|
|
13147
|
+
printTraceIdAfterResponse(inkTurnTraceId, {
|
|
13148
|
+
enabled: this.options.debugOn ?? false,
|
|
13149
|
+
tuiSink: (traceId) => {
|
|
13150
|
+
inkApiRef?.appendMessage({
|
|
13151
|
+
role: "system",
|
|
13152
|
+
content: `\uD83D\uDD0D [Trace] ${traceId}`
|
|
13153
|
+
});
|
|
13154
|
+
}
|
|
13155
|
+
});
|
|
13156
|
+
} catch (traceErr) {
|
|
13157
|
+
logger5.warn("printTraceIdAfterResponse failed (ink path)", {
|
|
13158
|
+
error: String(traceErr)
|
|
13159
|
+
});
|
|
13160
|
+
}
|
|
13161
|
+
try {
|
|
13162
|
+
inkRootSpan.end();
|
|
13163
|
+
} catch (spanErr) {
|
|
13164
|
+
logger5.warn("inkRootSpan.end failed", { error: String(spanErr) });
|
|
13165
|
+
}
|
|
12671
13166
|
this.isExecuting = false;
|
|
12672
13167
|
}
|
|
12673
13168
|
},
|
|
@@ -12937,7 +13432,6 @@ ${COLORS.system("[通知2] ❯ " + message.replace(/\n/g, `
|
|
|
12937
13432
|
traceId = rootSpan.spanContext.traceId;
|
|
12938
13433
|
provider.setGlobalContext(rootSpan.spanContext);
|
|
12939
13434
|
}
|
|
12940
|
-
console.log(`${COLORS.system("[Trace] " + traceId)}`);
|
|
12941
13435
|
console.log(`${COLORS.progress("[thinking...]")}`);
|
|
12942
13436
|
try {
|
|
12943
13437
|
await this.options.onExecute(message, traceId, agentContext);
|
|
@@ -12960,6 +13454,7 @@ ${COLORS.error("❌ 执行失败: " + error)}
|
|
|
12960
13454
|
}
|
|
12961
13455
|
} finally {
|
|
12962
13456
|
rootSpan.end();
|
|
13457
|
+
printTraceIdAfterResponse(traceId, this.options.debugOn ?? false);
|
|
12963
13458
|
if (existingContext) {
|
|
12964
13459
|
provider.setGlobalContext(existingContext);
|
|
12965
13460
|
} else {
|
|
@@ -13300,6 +13795,10 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13300
13795
|
describe: "Default agent 名字(默认 Roy,可被覆盖)",
|
|
13301
13796
|
type: "string",
|
|
13302
13797
|
default: "Roy"
|
|
13798
|
+
}).option("debug-on", {
|
|
13799
|
+
describe: "调试模式:每次 turn 结束后输出 [Trace] <traceId>(stderr),便于追踪调用 trace",
|
|
13800
|
+
type: "boolean",
|
|
13801
|
+
default: false
|
|
13303
13802
|
}),
|
|
13304
13803
|
async handler(args) {
|
|
13305
13804
|
CliQuietModeService.getInstance().setQuiet(true);
|
|
@@ -13466,6 +13965,7 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13466
13965
|
model: args.model,
|
|
13467
13966
|
version: getPackageVersion(),
|
|
13468
13967
|
useInk,
|
|
13968
|
+
debugOn: args.debugOn ?? false,
|
|
13469
13969
|
onExecute: async (message, traceId, agentContext) => {
|
|
13470
13970
|
resetStreamAbort();
|
|
13471
13971
|
const preloadedPrompts = eventSourceSystemPrompts;
|
|
@@ -13640,25 +14140,28 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13640
14140
|
var InteractiveCommand = createInteractiveCommand();
|
|
13641
14141
|
|
|
13642
14142
|
// src/commands/run.ts
|
|
13643
|
-
import
|
|
14143
|
+
import React8 from "react";
|
|
13644
14144
|
import { render } from "ink";
|
|
13645
14145
|
|
|
13646
|
-
// src/RunTui.
|
|
13647
|
-
import
|
|
13648
|
-
import { Box as
|
|
14146
|
+
// src/RunTui.tsx
|
|
14147
|
+
import { useState as useState6, useCallback as useCallback4, useRef as useRef5, useEffect as useEffect7, useMemo as useMemo3 } from "react";
|
|
14148
|
+
import { Box as Box7, Text as Text9, useApp as useApp2 } from "ink";
|
|
13649
14149
|
|
|
13650
|
-
// src/tui/App.
|
|
14150
|
+
// src/tui/App.tsx
|
|
13651
14151
|
init_Markdown();
|
|
13652
|
-
import
|
|
14152
|
+
import React4, { useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
13653
14153
|
import { Box as Box4, Static as Static2, Text as Text6 } from "ink";
|
|
13654
14154
|
|
|
13655
|
-
// src/tui/Spinner.
|
|
14155
|
+
// src/tui/Spinner.tsx
|
|
13656
14156
|
init_theme();
|
|
13657
|
-
import
|
|
14157
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
13658
14158
|
import { Text as Text5 } from "ink";
|
|
13659
14159
|
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
13660
14160
|
var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
13661
|
-
var Spinner = ({
|
|
14161
|
+
var Spinner = ({
|
|
14162
|
+
label,
|
|
14163
|
+
intervalMs = 80
|
|
14164
|
+
}) => {
|
|
13662
14165
|
const [frame, setFrame] = useState3(0);
|
|
13663
14166
|
const theme = getTheme();
|
|
13664
14167
|
useEffect3(() => {
|
|
@@ -13682,15 +14185,48 @@ var Spinner = ({ label, intervalMs = 80 }) => {
|
|
|
13682
14185
|
}, undefined, true, undefined, this);
|
|
13683
14186
|
};
|
|
13684
14187
|
|
|
13685
|
-
// src/tui/App.
|
|
14188
|
+
// src/tui/App.tsx
|
|
13686
14189
|
init_StatusBar();
|
|
13687
14190
|
init_theme();
|
|
14191
|
+
import { wrapFunction as wrapFunction3 } from "@ai-setting/roy-agent-core";
|
|
13688
14192
|
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
13689
14193
|
var ROLE_PREFIX = {
|
|
13690
14194
|
user: "\uD83D\uDC64 You",
|
|
13691
14195
|
assistant: "\uD83E\uDD16 Agent",
|
|
13692
14196
|
tool: "\uD83D\uDD27 Tool"
|
|
13693
14197
|
};
|
|
14198
|
+
var emitAppRenderSpanImpl = (snapshot) => {};
|
|
14199
|
+
var emitAppRenderSpan = wrapFunction3(emitAppRenderSpanImpl, "tui.app.render", {
|
|
14200
|
+
recordParams: true,
|
|
14201
|
+
recordResult: false,
|
|
14202
|
+
log: true,
|
|
14203
|
+
paramFilter: (args) => {
|
|
14204
|
+
const s = args[0] ?? {};
|
|
14205
|
+
return {
|
|
14206
|
+
renderCount: s.renderCount ?? 0,
|
|
14207
|
+
historyLength: s.historyLength ?? 0,
|
|
14208
|
+
status: s.status ?? "unknown"
|
|
14209
|
+
};
|
|
14210
|
+
}
|
|
14211
|
+
});
|
|
14212
|
+
var emitRenderScheduledSpanImpl = (parentRenderCount) => {};
|
|
14213
|
+
var emitRenderScheduledSpan = wrapFunction3(emitRenderScheduledSpanImpl, "tui.app.render-scheduled", {
|
|
14214
|
+
recordParams: true,
|
|
14215
|
+
recordResult: false,
|
|
14216
|
+
log: false,
|
|
14217
|
+
paramFilter: (args) => ({
|
|
14218
|
+
parentRenderCount: args[0] ?? 0
|
|
14219
|
+
})
|
|
14220
|
+
});
|
|
14221
|
+
var emitRenderThrottledSpanImpl = (parentRenderCount) => {};
|
|
14222
|
+
var emitRenderThrottledSpan = wrapFunction3(emitRenderThrottledSpanImpl, "tui.app.render-throttled", {
|
|
14223
|
+
recordParams: true,
|
|
14224
|
+
recordResult: false,
|
|
14225
|
+
log: false,
|
|
14226
|
+
paramFilter: (args) => ({
|
|
14227
|
+
parentRenderCount: args[0] ?? 0
|
|
14228
|
+
})
|
|
14229
|
+
});
|
|
13694
14230
|
var RoleLabel = ({ role }) => {
|
|
13695
14231
|
const theme = getTheme();
|
|
13696
14232
|
const roleColor = role === "user" ? theme.user : role === "assistant" ? theme.assistant : theme.tool;
|
|
@@ -13753,8 +14289,23 @@ var HistoryEntry = ({ item }) => {
|
|
|
13753
14289
|
]
|
|
13754
14290
|
}, undefined, true, undefined, this);
|
|
13755
14291
|
};
|
|
13756
|
-
var App = ({
|
|
14292
|
+
var App = ({
|
|
14293
|
+
history,
|
|
14294
|
+
status,
|
|
14295
|
+
model,
|
|
14296
|
+
workdir,
|
|
14297
|
+
tokenCount
|
|
14298
|
+
}) => {
|
|
13757
14299
|
const theme = getTheme();
|
|
14300
|
+
const renderCountRef = useRef2(0);
|
|
14301
|
+
renderCountRef.current += 1;
|
|
14302
|
+
useEffect4(() => {
|
|
14303
|
+
emitAppRenderSpan({
|
|
14304
|
+
renderCount: renderCountRef.current,
|
|
14305
|
+
historyLength: history.length,
|
|
14306
|
+
status
|
|
14307
|
+
});
|
|
14308
|
+
});
|
|
13758
14309
|
return /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13759
14310
|
flexDirection: "column",
|
|
13760
14311
|
minHeight: 20,
|
|
@@ -13788,21 +14339,7 @@ var App = ({ history, status, model, workdir, streamingText, tokenCount }) => {
|
|
|
13788
14339
|
label: "Agent is thinking..."
|
|
13789
14340
|
}, undefined, false, undefined, this)
|
|
13790
14341
|
}, undefined, false, undefined, this) : null,
|
|
13791
|
-
status === "streaming"
|
|
13792
|
-
flexDirection: "column",
|
|
13793
|
-
marginBottom: 1,
|
|
13794
|
-
children: [
|
|
13795
|
-
/* @__PURE__ */ jsxDEV6(RoleLabel, {
|
|
13796
|
-
role: "assistant"
|
|
13797
|
-
}, undefined, false, undefined, this),
|
|
13798
|
-
/* @__PURE__ */ jsxDEV6(Box4, {
|
|
13799
|
-
marginLeft: 2,
|
|
13800
|
-
children: /* @__PURE__ */ jsxDEV6(Markdown, {
|
|
13801
|
-
text: streamingText
|
|
13802
|
-
}, undefined, false, undefined, this)
|
|
13803
|
-
}, undefined, false, undefined, this)
|
|
13804
|
-
]
|
|
13805
|
-
}, undefined, true, undefined, this) : status === "streaming" ? /* @__PURE__ */ jsxDEV6(Box4, {
|
|
14342
|
+
status === "streaming" ? /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13806
14343
|
marginBottom: 1,
|
|
13807
14344
|
children: /* @__PURE__ */ jsxDEV6(Spinner, {
|
|
13808
14345
|
label: "Generating response..."
|
|
@@ -13819,20 +14356,156 @@ var App = ({ history, status, model, workdir, streamingText, tokenCount }) => {
|
|
|
13819
14356
|
]
|
|
13820
14357
|
}, undefined, true, undefined, this);
|
|
13821
14358
|
};
|
|
13822
|
-
|
|
13823
|
-
|
|
14359
|
+
function areAppPropsEqual(prev, next) {
|
|
14360
|
+
if (prev.status !== next.status)
|
|
14361
|
+
return false;
|
|
14362
|
+
if (prev.model !== next.model)
|
|
14363
|
+
return false;
|
|
14364
|
+
if (prev.workdir !== next.workdir)
|
|
14365
|
+
return false;
|
|
14366
|
+
if (prev.tokenCount !== next.tokenCount)
|
|
14367
|
+
return false;
|
|
14368
|
+
if (prev.history !== next.history)
|
|
14369
|
+
return false;
|
|
14370
|
+
return true;
|
|
14371
|
+
}
|
|
14372
|
+
var parentRenderCountRef = { current: 0 };
|
|
14373
|
+
var AppThrottledImpl = (props) => {
|
|
14374
|
+
parentRenderCountRef.current += 1;
|
|
14375
|
+
emitRenderScheduledSpan(parentRenderCountRef.current);
|
|
14376
|
+
return /* @__PURE__ */ jsxDEV6(App, {
|
|
14377
|
+
...props
|
|
14378
|
+
}, undefined, false, undefined, this);
|
|
14379
|
+
};
|
|
14380
|
+
var AppThrottled = React4.memo(AppThrottledImpl, areAppPropsEqual);
|
|
14381
|
+
AppThrottled.displayName = "App(throttled)";
|
|
14382
|
+
var lastMemoResult = null;
|
|
14383
|
+
var instrumentedAreEqual = (prev, next) => {
|
|
14384
|
+
const equal = areAppPropsEqual(prev, next);
|
|
14385
|
+
if (equal && lastMemoResult !== true) {
|
|
14386
|
+
emitRenderThrottledSpan(parentRenderCountRef.current);
|
|
14387
|
+
}
|
|
14388
|
+
lastMemoResult = equal;
|
|
14389
|
+
return equal;
|
|
14390
|
+
};
|
|
14391
|
+
var AppMemo = React4.memo(AppThrottledImpl, instrumentedAreEqual);
|
|
14392
|
+
AppMemo.displayName = "App(memo-throttled)";
|
|
14393
|
+
// src/tui/StreamingOverlay.tsx
|
|
13824
14394
|
init_Markdown();
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
import React7, { useEffect as useEffect4, useState as useState4 } from "react";
|
|
13829
|
-
import { Box as Box5, Text as Text7, useInput as useInput3 } from "ink";
|
|
14395
|
+
import { useEffect as useEffect5, useRef as useRef3 } from "react";
|
|
14396
|
+
import { Box as Box5, Text as Text7 } from "ink";
|
|
14397
|
+
import { wrapFunction as wrapFunction4 } from "@ai-setting/roy-agent-core";
|
|
13830
14398
|
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
13831
|
-
var
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
14399
|
+
var emitOverlayRenderSpanImpl = (snapshot) => {};
|
|
14400
|
+
var emitOverlayRenderSpan = wrapFunction4(emitOverlayRenderSpanImpl, "streaming-overlay.render", {
|
|
14401
|
+
recordParams: true,
|
|
14402
|
+
recordResult: false,
|
|
14403
|
+
log: false,
|
|
14404
|
+
paramFilter: (args) => {
|
|
14405
|
+
const s = args[0] ?? {};
|
|
14406
|
+
return {
|
|
14407
|
+
renderCount: s.renderCount ?? 0,
|
|
14408
|
+
streamingTextLength: s.streamingTextLength ?? 0,
|
|
14409
|
+
status: s.status ?? "unknown"
|
|
14410
|
+
};
|
|
14411
|
+
}
|
|
14412
|
+
});
|
|
14413
|
+
var emitOverlayMarkdownSpanImpl = (snapshot) => {};
|
|
14414
|
+
var emitOverlayMarkdownSpan = wrapFunction4(emitOverlayMarkdownSpanImpl, "streaming-overlay.markdown-render", {
|
|
14415
|
+
recordParams: true,
|
|
14416
|
+
recordResult: false,
|
|
14417
|
+
log: false,
|
|
14418
|
+
paramFilter: (args) => {
|
|
14419
|
+
const s = args[0] ?? {};
|
|
14420
|
+
return {
|
|
14421
|
+
inputLength: s.inputLength ?? 0,
|
|
14422
|
+
renderCount: s.renderCount ?? 0
|
|
14423
|
+
};
|
|
14424
|
+
}
|
|
14425
|
+
});
|
|
14426
|
+
var StreamingOverlay = ({
|
|
14427
|
+
streamingText,
|
|
14428
|
+
status,
|
|
14429
|
+
markdownEnabled: markdownEnabled2,
|
|
14430
|
+
width
|
|
14431
|
+
}) => {
|
|
14432
|
+
const renderCountRef = useRef3(0);
|
|
14433
|
+
renderCountRef.current += 1;
|
|
14434
|
+
useEffect5(() => {
|
|
14435
|
+
emitOverlayRenderSpan({
|
|
14436
|
+
renderCount: renderCountRef.current,
|
|
14437
|
+
streamingTextLength: streamingText.length,
|
|
14438
|
+
status
|
|
14439
|
+
});
|
|
14440
|
+
});
|
|
14441
|
+
if (status === "thinking") {
|
|
14442
|
+
return /* @__PURE__ */ jsxDEV7(Box5, {
|
|
14443
|
+
marginBottom: 1,
|
|
14444
|
+
children: /* @__PURE__ */ jsxDEV7(Text7, {
|
|
14445
|
+
dimColor: true,
|
|
14446
|
+
children: "\uD83E\uDD14 thinking..."
|
|
14447
|
+
}, undefined, false, undefined, this)
|
|
14448
|
+
}, undefined, false, undefined, this);
|
|
14449
|
+
}
|
|
14450
|
+
if (status === "idle") {
|
|
14451
|
+
return null;
|
|
14452
|
+
}
|
|
14453
|
+
if (!streamingText) {
|
|
14454
|
+
return /* @__PURE__ */ jsxDEV7(Box5, {
|
|
14455
|
+
marginBottom: 1,
|
|
14456
|
+
children: /* @__PURE__ */ jsxDEV7(Text7, {
|
|
14457
|
+
dimColor: true,
|
|
14458
|
+
children: "⏳ generating response..."
|
|
14459
|
+
}, undefined, false, undefined, this)
|
|
14460
|
+
}, undefined, false, undefined, this);
|
|
14461
|
+
}
|
|
14462
|
+
const effectiveWidth = width ?? process.stdout.columns ?? 80;
|
|
14463
|
+
emitOverlayMarkdownSpan({
|
|
14464
|
+
inputLength: streamingText.length,
|
|
14465
|
+
renderCount: renderCountRef.current
|
|
14466
|
+
});
|
|
14467
|
+
return /* @__PURE__ */ jsxDEV7(Box5, {
|
|
14468
|
+
flexDirection: "column",
|
|
14469
|
+
marginBottom: 1,
|
|
14470
|
+
children: [
|
|
14471
|
+
/* @__PURE__ */ jsxDEV7(Text7, {
|
|
14472
|
+
bold: true,
|
|
14473
|
+
color: "cyan",
|
|
14474
|
+
children: "\uD83E\uDD16 Agent"
|
|
14475
|
+
}, undefined, false, undefined, this),
|
|
14476
|
+
/* @__PURE__ */ jsxDEV7(Box5, {
|
|
14477
|
+
marginLeft: 2,
|
|
14478
|
+
children: markdownEnabled2 ? /* @__PURE__ */ jsxDEV7(Markdown, {
|
|
14479
|
+
text: streamingText,
|
|
14480
|
+
width: effectiveWidth
|
|
14481
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7(Text7, {
|
|
14482
|
+
children: streamingText
|
|
14483
|
+
}, undefined, false, undefined, this)
|
|
14484
|
+
}, undefined, false, undefined, this)
|
|
14485
|
+
]
|
|
14486
|
+
}, undefined, true, undefined, this);
|
|
14487
|
+
};
|
|
14488
|
+
|
|
14489
|
+
// src/tui/index.ts
|
|
14490
|
+
init_Markdown();
|
|
14491
|
+
init_StatusBar();
|
|
14492
|
+
|
|
14493
|
+
// src/tui/TextInput.tsx
|
|
14494
|
+
import { useEffect as useEffect6, useState as useState4 } from "react";
|
|
14495
|
+
import { Box as Box6, Text as Text8, useInput as useInput3 } from "ink";
|
|
14496
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
14497
|
+
var TextInput = ({
|
|
14498
|
+
label,
|
|
14499
|
+
prefix,
|
|
14500
|
+
onSubmit,
|
|
14501
|
+
onCancel,
|
|
14502
|
+
placeholder,
|
|
14503
|
+
history = []
|
|
14504
|
+
}) => {
|
|
14505
|
+
const [value, setValue] = useState4("");
|
|
14506
|
+
const [historyIndex, setHistoryIndex] = useState4(-1);
|
|
14507
|
+
const [draft, setDraft] = useState4("");
|
|
14508
|
+
useEffect6(() => {
|
|
13836
14509
|
setHistoryIndex(-1);
|
|
13837
14510
|
}, [history.length]);
|
|
13838
14511
|
useInput3((input, key) => {
|
|
@@ -13886,9 +14559,9 @@ var TextInput = ({ label, prefix, onSubmit, onCancel, placeholder, history = []
|
|
|
13886
14559
|
setValue((v) => v + input);
|
|
13887
14560
|
}
|
|
13888
14561
|
});
|
|
13889
|
-
return /* @__PURE__ */
|
|
14562
|
+
return /* @__PURE__ */ jsxDEV8(Box6, {
|
|
13890
14563
|
children: [
|
|
13891
|
-
/* @__PURE__ */
|
|
14564
|
+
/* @__PURE__ */ jsxDEV8(Text8, {
|
|
13892
14565
|
bold: true,
|
|
13893
14566
|
color: "green",
|
|
13894
14567
|
children: [
|
|
@@ -13896,21 +14569,21 @@ var TextInput = ({ label, prefix, onSubmit, onCancel, placeholder, history = []
|
|
|
13896
14569
|
" "
|
|
13897
14570
|
]
|
|
13898
14571
|
}, undefined, true, undefined, this),
|
|
13899
|
-
/* @__PURE__ */
|
|
14572
|
+
/* @__PURE__ */ jsxDEV8(Text8, {
|
|
13900
14573
|
bold: true,
|
|
13901
14574
|
children: [
|
|
13902
14575
|
label,
|
|
13903
14576
|
": "
|
|
13904
14577
|
]
|
|
13905
14578
|
}, undefined, true, undefined, this),
|
|
13906
|
-
/* @__PURE__ */
|
|
14579
|
+
/* @__PURE__ */ jsxDEV8(Text8, {
|
|
13907
14580
|
children: value
|
|
13908
14581
|
}, undefined, false, undefined, this),
|
|
13909
|
-
!value && placeholder ? /* @__PURE__ */
|
|
14582
|
+
!value && placeholder ? /* @__PURE__ */ jsxDEV8(Text8, {
|
|
13910
14583
|
dimColor: true,
|
|
13911
14584
|
children: placeholder
|
|
13912
14585
|
}, undefined, false, undefined, this) : null,
|
|
13913
|
-
historyIndex !== -1 ? /* @__PURE__ */
|
|
14586
|
+
historyIndex !== -1 ? /* @__PURE__ */ jsxDEV8(Text8, {
|
|
13914
14587
|
dimColor: true,
|
|
13915
14588
|
children: " (history)"
|
|
13916
14589
|
}, undefined, false, undefined, this) : null
|
|
@@ -13918,49 +14591,110 @@ var TextInput = ({ label, prefix, onSubmit, onCancel, placeholder, history = []
|
|
|
13918
14591
|
}, undefined, true, undefined, this);
|
|
13919
14592
|
};
|
|
13920
14593
|
|
|
13921
|
-
// src/tui/index.
|
|
14594
|
+
// src/tui/index.ts
|
|
13922
14595
|
init_theme();
|
|
14596
|
+
init_welcome_card2();
|
|
13923
14597
|
|
|
13924
|
-
// src/tui/
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
14598
|
+
// src/tui/use-streaming-accumulator.ts
|
|
14599
|
+
import { useCallback as useCallback3, useRef as useRef4, useState as useState5 } from "react";
|
|
14600
|
+
import { wrapFunction as wrapFunction5 } from "@ai-setting/roy-agent-core";
|
|
13928
14601
|
function useStreamingAccumulator() {
|
|
13929
14602
|
const [status, setStatus] = useState5("idle");
|
|
13930
14603
|
const [streamingText, setStreamingText] = useState5("");
|
|
13931
|
-
const
|
|
14604
|
+
const appendCountRef = useRef4(0);
|
|
14605
|
+
const pendingBufferRef = useRef4("");
|
|
14606
|
+
const flushScheduledRef = useRef4(false);
|
|
14607
|
+
const flushBuffer = useCallback3(() => {
|
|
14608
|
+
flushScheduledRef.current = false;
|
|
14609
|
+
const buf = pendingBufferRef.current;
|
|
14610
|
+
if (buf.length === 0)
|
|
14611
|
+
return;
|
|
14612
|
+
pendingBufferRef.current = "";
|
|
14613
|
+
setStreamingText((prev) => prev + buf);
|
|
14614
|
+
}, []);
|
|
14615
|
+
const lastStatusRef = useRef4("idle");
|
|
14616
|
+
const startImpl = useCallback3(() => {
|
|
13932
14617
|
setStreamingText("");
|
|
13933
14618
|
setStatus("thinking");
|
|
14619
|
+
lastStatusRef.current = "thinking";
|
|
14620
|
+
appendCountRef.current = 0;
|
|
13934
14621
|
}, []);
|
|
13935
|
-
const
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
14622
|
+
const appendImpl = useCallback3((chunk) => {
|
|
14623
|
+
pendingBufferRef.current += chunk;
|
|
14624
|
+
if (!flushScheduledRef.current) {
|
|
14625
|
+
flushScheduledRef.current = true;
|
|
14626
|
+
queueMicrotask(flushBuffer);
|
|
14627
|
+
}
|
|
14628
|
+
if (lastStatusRef.current !== "streaming") {
|
|
14629
|
+
setStatus("streaming");
|
|
14630
|
+
lastStatusRef.current = "streaming";
|
|
14631
|
+
}
|
|
14632
|
+
appendCountRef.current += 1;
|
|
14633
|
+
}, [flushBuffer]);
|
|
14634
|
+
const finishImpl = useCallback3(() => {
|
|
14635
|
+
if (pendingBufferRef.current.length > 0) {
|
|
14636
|
+
flushBuffer();
|
|
14637
|
+
}
|
|
13941
14638
|
let snapshot = "";
|
|
13942
14639
|
setStreamingText((prev) => {
|
|
13943
14640
|
snapshot = prev;
|
|
13944
14641
|
return "";
|
|
13945
14642
|
});
|
|
13946
|
-
return snapshot;
|
|
13947
|
-
}, []);
|
|
13948
|
-
const fail = useCallback3((_err) => {
|
|
13949
14643
|
setStatus("idle");
|
|
14644
|
+
lastStatusRef.current = "idle";
|
|
14645
|
+
return snapshot;
|
|
14646
|
+
}, [flushBuffer]);
|
|
14647
|
+
const failImpl = useCallback3((_err) => {
|
|
14648
|
+
if (pendingBufferRef.current.length > 0) {
|
|
14649
|
+
flushBuffer();
|
|
14650
|
+
}
|
|
13950
14651
|
let snapshot = "";
|
|
13951
14652
|
setStreamingText((prev) => {
|
|
13952
14653
|
snapshot = prev;
|
|
13953
14654
|
return "";
|
|
13954
14655
|
});
|
|
14656
|
+
setStatus("idle");
|
|
14657
|
+
lastStatusRef.current = "idle";
|
|
13955
14658
|
return snapshot;
|
|
13956
|
-
}, []);
|
|
14659
|
+
}, [flushBuffer]);
|
|
14660
|
+
const start = wrapFunction5(startImpl, "streaming.start", {
|
|
14661
|
+
recordParams: false,
|
|
14662
|
+
recordResult: false,
|
|
14663
|
+
log: true
|
|
14664
|
+
});
|
|
14665
|
+
const append = wrapFunction5(appendImpl, "streaming.append", {
|
|
14666
|
+
recordParams: true,
|
|
14667
|
+
recordResult: false,
|
|
14668
|
+
log: true,
|
|
14669
|
+
paramFilter: (args) => ({
|
|
14670
|
+
"chunk.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
14671
|
+
"chunk.head": typeof args[0] === "string" ? args[0].slice(0, 32) : "",
|
|
14672
|
+
"chunk.tail": typeof args[0] === "string" ? args[0].slice(-32) : ""
|
|
14673
|
+
})
|
|
14674
|
+
});
|
|
14675
|
+
const finish = wrapFunction5(finishImpl, "streaming.finish", {
|
|
14676
|
+
recordParams: false,
|
|
14677
|
+
recordResult: true,
|
|
14678
|
+
log: true,
|
|
14679
|
+
resultFilter: (result) => ({
|
|
14680
|
+
"snapshot.length": typeof result === "string" ? result.length : 0
|
|
14681
|
+
})
|
|
14682
|
+
});
|
|
14683
|
+
const fail = wrapFunction5(failImpl, "streaming.fail", {
|
|
14684
|
+
recordParams: true,
|
|
14685
|
+
recordResult: false,
|
|
14686
|
+
log: true,
|
|
14687
|
+
paramFilter: (args) => ({
|
|
14688
|
+
"err.message": args[0] instanceof Error ? args[0].message : String(args[0])
|
|
14689
|
+
})
|
|
14690
|
+
});
|
|
13957
14691
|
return { status, streamingText, start, append, finish, fail };
|
|
13958
14692
|
}
|
|
13959
14693
|
|
|
13960
|
-
// src/RunTui.
|
|
14694
|
+
// src/RunTui.tsx
|
|
13961
14695
|
init_markdown();
|
|
13962
14696
|
|
|
13963
|
-
// src/slash.
|
|
14697
|
+
// src/slash.ts
|
|
13964
14698
|
var CLEAR_SENTINEL = "__CLEAR__";
|
|
13965
14699
|
function dispatchSlashCommand(raw, ctx) {
|
|
13966
14700
|
const text = raw.trim();
|
|
@@ -14032,9 +14766,19 @@ function dispatchSlashCommand(raw, ctx) {
|
|
|
14032
14766
|
}
|
|
14033
14767
|
}
|
|
14034
14768
|
|
|
14035
|
-
// src/RunTui.
|
|
14036
|
-
import {
|
|
14037
|
-
|
|
14769
|
+
// src/RunTui.tsx
|
|
14770
|
+
import { wrapFunction as wrapFunction6 } from "@ai-setting/roy-agent-core";
|
|
14771
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
14772
|
+
var RunScreen = ({
|
|
14773
|
+
handleQuery,
|
|
14774
|
+
streamHandleQuery,
|
|
14775
|
+
model,
|
|
14776
|
+
workdir,
|
|
14777
|
+
maxLines: initialMaxLines,
|
|
14778
|
+
markdownEnabled: markdownEnabled2,
|
|
14779
|
+
onExit,
|
|
14780
|
+
onRegisterHandlers
|
|
14781
|
+
}) => {
|
|
14038
14782
|
const [history, setHistory] = useState6([]);
|
|
14039
14783
|
const [errorMessage, setErrorMessage] = useState6(null);
|
|
14040
14784
|
const [maxLines, setMaxLines] = useState6(initialMaxLines);
|
|
@@ -14042,17 +14786,17 @@ var RunScreen = ({ handleQuery, streamHandleQuery, model, workdir, maxLines: ini
|
|
|
14042
14786
|
const stream = useStreamingAccumulator();
|
|
14043
14787
|
const status = stream.status;
|
|
14044
14788
|
const { exit } = useApp2();
|
|
14045
|
-
const userTurnCountRef =
|
|
14046
|
-
const assistantTurnCountRef =
|
|
14047
|
-
const isProcessingRef =
|
|
14048
|
-
const executeQueryRef =
|
|
14049
|
-
const historyIdRef =
|
|
14789
|
+
const userTurnCountRef = useRef5(0);
|
|
14790
|
+
const assistantTurnCountRef = useRef5(0);
|
|
14791
|
+
const isProcessingRef = useRef5(0);
|
|
14792
|
+
const executeQueryRef = useRef5(null);
|
|
14793
|
+
const historyIdRef = useRef5(0);
|
|
14050
14794
|
const width = process.stdout.columns ?? 80;
|
|
14051
14795
|
const doExit = useCallback4(() => {
|
|
14052
14796
|
onExit?.();
|
|
14053
14797
|
exit();
|
|
14054
14798
|
}, [onExit, exit]);
|
|
14055
|
-
const
|
|
14799
|
+
const executeQueryImpl = useCallback4(async (message) => {
|
|
14056
14800
|
isProcessingRef.current += 1;
|
|
14057
14801
|
stream.start();
|
|
14058
14802
|
try {
|
|
@@ -14084,1234 +14828,232 @@ var RunScreen = ({ handleQuery, streamHandleQuery, model, workdir, maxLines: ini
|
|
|
14084
14828
|
isProcessingRef.current -= 1;
|
|
14085
14829
|
}
|
|
14086
14830
|
}, [handleQuery, markdownEnabled2, maxLines, stream, streamHandleQuery, width]);
|
|
14087
|
-
|
|
14831
|
+
const executeQuery = useMemo3(() => wrapFunction6(executeQueryImpl, "tui.run-tui.executeQuery", {
|
|
14832
|
+
recordParams: true,
|
|
14833
|
+
recordResult: false,
|
|
14834
|
+
log: true,
|
|
14835
|
+
paramFilter: (args) => ({
|
|
14836
|
+
"message.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
14837
|
+
"message.head": typeof args[0] === "string" ? args[0].slice(0, 60) : "",
|
|
14838
|
+
"isProcessingRef.before": (isProcessingRef.current ?? 0) + 1,
|
|
14839
|
+
streaming: !!streamHandleQuery
|
|
14840
|
+
})
|
|
14841
|
+
}), [executeQueryImpl, streamHandleQuery]);
|
|
14842
|
+
useEffect7(() => {
|
|
14088
14843
|
executeQueryRef.current = executeQuery;
|
|
14089
14844
|
}, [executeQuery]);
|
|
14090
|
-
|
|
14845
|
+
useEffect7(() => {
|
|
14091
14846
|
if (!onRegisterHandlers)
|
|
14092
14847
|
return;
|
|
14093
|
-
const
|
|
14848
|
+
const handleNotificationImpl = async (message, _envEvent) => {
|
|
14094
14849
|
const notifId = `h${++historyIdRef.current}`;
|
|
14095
|
-
setHistory((h) => [
|
|
14096
|
-
...h,
|
|
14097
|
-
{ role: "tool", content: `\uD83D\uDCE2 ${message}`, id: notifId }
|
|
14098
|
-
]);
|
|
14099
|
-
if (executeQueryRef.current) {
|
|
14100
|
-
await executeQueryRef.current(message);
|
|
14101
|
-
}
|
|
14102
|
-
};
|
|
14103
|
-
const isIdle = () => {
|
|
14104
|
-
return isProcessingRef.current === 0;
|
|
14105
|
-
};
|
|
14106
|
-
onRegisterHandlers({ onNotification: handleNotification, isIdle });
|
|
14107
|
-
}, [onRegisterHandlers]);
|
|
14108
|
-
const handleSubmit = useCallback4(async (raw) => {
|
|
14109
|
-
const trimmed = raw.trim();
|
|
14110
|
-
if (!trimmed)
|
|
14111
|
-
return;
|
|
14112
|
-
const slashCtx = {
|
|
14113
|
-
model,
|
|
14114
|
-
workdir,
|
|
14115
|
-
maxLines,
|
|
14116
|
-
userTurnCount: userTurnCountRef.current,
|
|
14117
|
-
assistantTurnCount: assistantTurnCountRef.current
|
|
14118
|
-
};
|
|
14119
|
-
const result = dispatchSlashCommand(trimmed, slashCtx);
|
|
14120
|
-
if (result.kind === "exit") {
|
|
14121
|
-
const userId2 = `h${++historyIdRef.current}`;
|
|
14122
|
-
const toolId = `h${++historyIdRef.current}`;
|
|
14123
|
-
setHistory((h) => [
|
|
14124
|
-
...h,
|
|
14125
|
-
{ role: "user", content: trimmed, id: userId2 },
|
|
14126
|
-
{ role: "tool", content: "\uD83D\uDC4B Goodbye!", id: toolId }
|
|
14127
|
-
]);
|
|
14128
|
-
doExit();
|
|
14129
|
-
return;
|
|
14130
|
-
}
|
|
14131
|
-
if (result.kind === "handled") {
|
|
14132
|
-
if (result.message === CLEAR_SENTINEL) {
|
|
14133
|
-
setHistory([]);
|
|
14134
|
-
setUserHistory([]);
|
|
14135
|
-
userTurnCountRef.current = 0;
|
|
14136
|
-
assistantTurnCountRef.current = 0;
|
|
14137
|
-
setErrorMessage(null);
|
|
14138
|
-
return;
|
|
14139
|
-
}
|
|
14140
|
-
const userId2 = `h${++historyIdRef.current}`;
|
|
14141
|
-
const toolId = `h${++historyIdRef.current}`;
|
|
14142
|
-
setHistory((h) => [
|
|
14143
|
-
...h,
|
|
14144
|
-
{ role: "user", content: trimmed, id: userId2 },
|
|
14145
|
-
{ role: "tool", content: result.message, id: toolId }
|
|
14146
|
-
]);
|
|
14147
|
-
return;
|
|
14148
|
-
}
|
|
14149
|
-
if (result.kind === "unknown") {
|
|
14150
|
-
const userId2 = `h${++historyIdRef.current}`;
|
|
14151
|
-
const toolId = `h${++historyIdRef.current}`;
|
|
14152
|
-
setHistory((h) => [
|
|
14153
|
-
...h,
|
|
14154
|
-
{ role: "user", content: trimmed, id: userId2 },
|
|
14155
|
-
{ role: "tool", content: `⚠ ${result.message}`, id: toolId }
|
|
14156
|
-
]);
|
|
14157
|
-
return;
|
|
14158
|
-
}
|
|
14159
|
-
if (result.kind === "set-max-lines") {
|
|
14160
|
-
setMaxLines(result.value);
|
|
14161
|
-
const userId2 = `h${++historyIdRef.current}`;
|
|
14162
|
-
const toolId = `h${++historyIdRef.current}`;
|
|
14163
|
-
setHistory((h) => [
|
|
14164
|
-
...h,
|
|
14165
|
-
{ role: "user", content: trimmed, id: userId2 },
|
|
14166
|
-
{
|
|
14167
|
-
role: "tool",
|
|
14168
|
-
content: `max-lines set to ${result.value}`,
|
|
14169
|
-
id: toolId
|
|
14170
|
-
}
|
|
14171
|
-
]);
|
|
14172
|
-
return;
|
|
14173
|
-
}
|
|
14174
|
-
setErrorMessage(null);
|
|
14175
|
-
const userId = `h${++historyIdRef.current}`;
|
|
14176
|
-
setHistory((h) => [
|
|
14177
|
-
...h,
|
|
14178
|
-
{ role: "user", content: trimmed, id: userId }
|
|
14179
|
-
]);
|
|
14180
|
-
setUserHistory((uh) => [trimmed, ...uh]);
|
|
14181
|
-
userTurnCountRef.current += 1;
|
|
14182
|
-
await executeQuery(trimmed);
|
|
14183
|
-
}, [
|
|
14184
|
-
doExit,
|
|
14185
|
-
exit,
|
|
14186
|
-
executeQuery,
|
|
14187
|
-
maxLines,
|
|
14188
|
-
model,
|
|
14189
|
-
workdir
|
|
14190
|
-
]);
|
|
14191
|
-
const handleCancel = useCallback4(() => {
|
|
14192
|
-
doExit();
|
|
14193
|
-
}, [doExit]);
|
|
14194
|
-
return /* @__PURE__ */ jsxDEV8(Box6, {
|
|
14195
|
-
flexDirection: "column",
|
|
14196
|
-
children: [
|
|
14197
|
-
/* @__PURE__ */ jsxDEV8(App, {
|
|
14198
|
-
history,
|
|
14199
|
-
status,
|
|
14200
|
-
model,
|
|
14201
|
-
workdir,
|
|
14202
|
-
streamingText: stream.streamingText
|
|
14203
|
-
}, undefined, false, undefined, this),
|
|
14204
|
-
status === "idle" ? /* @__PURE__ */ jsxDEV8(Box6, {
|
|
14205
|
-
marginTop: 1,
|
|
14206
|
-
children: /* @__PURE__ */ jsxDEV8(TextInput, {
|
|
14207
|
-
label: "You",
|
|
14208
|
-
prefix: "\uD83D\uDC64",
|
|
14209
|
-
placeholder: 'Type a message, "/help", or "exit"',
|
|
14210
|
-
onSubmit: handleSubmit,
|
|
14211
|
-
onCancel: handleCancel,
|
|
14212
|
-
history: userHistory
|
|
14213
|
-
}, undefined, false, undefined, this)
|
|
14214
|
-
}, undefined, false, undefined, this) : null,
|
|
14215
|
-
errorMessage ? /* @__PURE__ */ jsxDEV8(Box6, {
|
|
14216
|
-
marginTop: 1,
|
|
14217
|
-
children: /* @__PURE__ */ jsxDEV8(Text8, {
|
|
14218
|
-
color: "red",
|
|
14219
|
-
children: [
|
|
14220
|
-
"⚠ ",
|
|
14221
|
-
errorMessage
|
|
14222
|
-
]
|
|
14223
|
-
}, undefined, true, undefined, this)
|
|
14224
|
-
}, undefined, false, undefined, this) : null
|
|
14225
|
-
]
|
|
14226
|
-
}, undefined, true, undefined, this);
|
|
14227
|
-
};
|
|
14228
|
-
var RunTui_default = RunScreen;
|
|
14229
|
-
|
|
14230
|
-
// src/commands/run.ts
|
|
14231
|
-
init_markdown();
|
|
14232
|
-
|
|
14233
|
-
// src/commands/shared/session-manager.js
|
|
14234
|
-
import { parseImageInput as parseImageInput3 } from "@ai-setting/roy-agent-core";
|
|
14235
|
-
|
|
14236
|
-
class SessionManager2 {
|
|
14237
|
-
sessionComponent;
|
|
14238
|
-
output;
|
|
14239
|
-
quiet;
|
|
14240
|
-
attachedImagesMap = new Map;
|
|
14241
|
-
constructor(options) {
|
|
14242
|
-
this.sessionComponent = options.sessionComponent;
|
|
14243
|
-
this.output = options.output;
|
|
14244
|
-
this.quiet = options.quiet;
|
|
14245
|
-
}
|
|
14246
|
-
async init(sessionId, isContinue) {
|
|
14247
|
-
let targetSessionId = sessionId;
|
|
14248
|
-
let isNewSession = false;
|
|
14249
|
-
if (isContinue && !targetSessionId) {
|
|
14250
|
-
const activeSession = await this.sessionComponent.getActiveSession();
|
|
14251
|
-
if (activeSession) {
|
|
14252
|
-
targetSessionId = activeSession.id;
|
|
14253
|
-
if (!this.quiet) {
|
|
14254
|
-
this.output.info(`继续会话: ${activeSession.title} (${targetSessionId})`);
|
|
14255
|
-
}
|
|
14256
|
-
} else {
|
|
14257
|
-
this.output.warn("没有找到上次会话,将创建新会话");
|
|
14258
|
-
}
|
|
14259
|
-
}
|
|
14260
|
-
if (targetSessionId) {
|
|
14261
|
-
await this.sessionComponent.setActiveSession(targetSessionId);
|
|
14262
|
-
const session2 = await this.sessionComponent.get(targetSessionId);
|
|
14263
|
-
if (session2) {
|
|
14264
|
-
if (!this.quiet) {
|
|
14265
|
-
this.output.info(`会话: ${session2.title} (${targetSessionId})`);
|
|
14266
|
-
}
|
|
14267
|
-
} else {
|
|
14268
|
-
this.output.warn(`会话不存在: ${targetSessionId},将创建新会话`);
|
|
14269
|
-
targetSessionId = undefined;
|
|
14270
|
-
}
|
|
14271
|
-
}
|
|
14272
|
-
if (!targetSessionId) {
|
|
14273
|
-
const newSession = await this.sessionComponent.create({
|
|
14274
|
-
title: `Session - ${new Date().toLocaleString("zh-CN")}`
|
|
14275
|
-
});
|
|
14276
|
-
targetSessionId = newSession.id;
|
|
14277
|
-
isNewSession = true;
|
|
14278
|
-
await this.sessionComponent.setActiveSession(targetSessionId);
|
|
14279
|
-
if (!this.quiet) {
|
|
14280
|
-
this.output.info(`创建新会话: ${newSession.title} (${targetSessionId})`);
|
|
14281
|
-
}
|
|
14282
|
-
}
|
|
14283
|
-
this.clearAttachments();
|
|
14284
|
-
const session = await this.sessionComponent.get(targetSessionId);
|
|
14285
|
-
return {
|
|
14286
|
-
sessionId: targetSessionId,
|
|
14287
|
-
isNewSession,
|
|
14288
|
-
sessionTitle: session?.title || "Unknown"
|
|
14289
|
-
};
|
|
14290
|
-
}
|
|
14291
|
-
async switchSession(sessionId) {
|
|
14292
|
-
return this.init(sessionId, false);
|
|
14293
|
-
}
|
|
14294
|
-
async getCurrentSession() {
|
|
14295
|
-
return this.sessionComponent.getActiveSession();
|
|
14296
|
-
}
|
|
14297
|
-
async attachImage(rawPath) {
|
|
14298
|
-
const normalized = rawPath.trim();
|
|
14299
|
-
if (!normalized) {
|
|
14300
|
-
throw new Error("attachImage: empty path");
|
|
14301
|
-
}
|
|
14302
|
-
const existing = this.attachedImagesMap.get(normalized);
|
|
14303
|
-
if (existing) {
|
|
14304
|
-
return existing;
|
|
14305
|
-
}
|
|
14306
|
-
const part = await parseImageInput3(normalized);
|
|
14307
|
-
this.attachedImagesMap.set(normalized, part);
|
|
14308
|
-
return part;
|
|
14309
|
-
}
|
|
14310
|
-
listAttachments() {
|
|
14311
|
-
return Array.from(this.attachedImagesMap.values());
|
|
14312
|
-
}
|
|
14313
|
-
clearAttachments() {
|
|
14314
|
-
this.attachedImagesMap.clear();
|
|
14315
|
-
}
|
|
14316
|
-
async getQueryPayload(text) {
|
|
14317
|
-
if (this.attachedImagesMap.size === 0) {
|
|
14318
|
-
return text;
|
|
14319
|
-
}
|
|
14320
|
-
return [
|
|
14321
|
-
{ type: "text", text },
|
|
14322
|
-
...this.listAttachments()
|
|
14323
|
-
];
|
|
14324
|
-
}
|
|
14325
|
-
}
|
|
14326
|
-
|
|
14327
|
-
// src/commands/shared/query-executor.js
|
|
14328
|
-
init_stream_output_service();
|
|
14329
|
-
import { ContextError as ContextError4, ErrorCodes as ErrorCodes4, TracedAs as TracedAs7 } from "@ai-setting/roy-agent-core";
|
|
14330
|
-
var __decorate = function(decorators, target, key, desc) {
|
|
14331
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14332
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14333
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
14334
|
-
else
|
|
14335
|
-
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14336
|
-
if (d = decorators[i])
|
|
14337
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14338
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14339
|
-
};
|
|
14340
|
-
|
|
14341
|
-
class QueryExecutor2 {
|
|
14342
|
-
env;
|
|
14343
|
-
sessionComponent;
|
|
14344
|
-
output;
|
|
14345
|
-
quiet;
|
|
14346
|
-
silent = false;
|
|
14347
|
-
streamService = null;
|
|
14348
|
-
unsubscribe = null;
|
|
14349
|
-
streamOptions = {
|
|
14350
|
-
showReasoning: true,
|
|
14351
|
-
showToolCalls: true,
|
|
14352
|
-
showToolResults: false
|
|
14353
|
-
};
|
|
14354
|
-
_pendingContextConfig = null;
|
|
14355
|
-
_pendingChunkCallback = undefined;
|
|
14356
|
-
constructor(options) {
|
|
14357
|
-
this.env = options.env;
|
|
14358
|
-
this.sessionComponent = options.sessionComponent;
|
|
14359
|
-
this.output = options.output;
|
|
14360
|
-
this.quiet = options.quiet;
|
|
14361
|
-
this.silent = options.silent ?? false;
|
|
14362
|
-
}
|
|
14363
|
-
initSummaryAgent(llmComponent, promptComponent) {
|
|
14364
|
-
const session = this.sessionComponent;
|
|
14365
|
-
if (typeof session.setSummaryComponents === "function") {
|
|
14366
|
-
session.setSummaryComponents(promptComponent, llmComponent);
|
|
14367
|
-
}
|
|
14368
|
-
}
|
|
14369
|
-
initStreamOutput(llmComponent, providerId = "minimax") {
|
|
14370
|
-
if (llmComponent) {
|
|
14371
|
-
const contextConfig = llmComponent.getContextThresholdConfig(providerId);
|
|
14372
|
-
this._pendingContextConfig = contextConfig;
|
|
14373
|
-
}
|
|
14374
|
-
}
|
|
14375
|
-
subscribeToEvents(options) {
|
|
14376
|
-
this.streamOptions = options;
|
|
14377
|
-
if (this.streamService) {
|
|
14378
|
-
this.streamService.setOptions(options);
|
|
14379
|
-
}
|
|
14380
|
-
if (this.unsubscribe) {
|
|
14381
|
-
return;
|
|
14382
|
-
}
|
|
14383
|
-
this.streamService = new StreamOutputService({
|
|
14384
|
-
...options,
|
|
14385
|
-
silent: this.silent ?? false
|
|
14386
|
-
});
|
|
14387
|
-
if (this._pendingChunkCallback !== undefined) {
|
|
14388
|
-
this.streamService.setChunkCallback(this._pendingChunkCallback);
|
|
14389
|
-
this._pendingChunkCallback = undefined;
|
|
14390
|
-
}
|
|
14391
|
-
if (this._pendingContextConfig) {
|
|
14392
|
-
this.streamService.setContextInfo(this._pendingContextConfig.contextWindow, this._pendingContextConfig.contextWindow * this._pendingContextConfig.thresholdRatio);
|
|
14393
|
-
this._pendingContextConfig = null;
|
|
14394
|
-
}
|
|
14395
|
-
this.unsubscribe = this.env.subscribeTo([
|
|
14396
|
-
"llm.start",
|
|
14397
|
-
"llm.text",
|
|
14398
|
-
"llm.reasoning",
|
|
14399
|
-
"llm.completed",
|
|
14400
|
-
"llm.error",
|
|
14401
|
-
"tool.call",
|
|
14402
|
-
"tool.result",
|
|
14403
|
-
"tool.error",
|
|
14404
|
-
"context.threshold_exceeded",
|
|
14405
|
-
"context.compacting",
|
|
14406
|
-
"context.compacted"
|
|
14407
|
-
], (event) => this.handleEvent(event));
|
|
14408
|
-
}
|
|
14409
|
-
setChunkCallback(cb) {
|
|
14410
|
-
if (this.streamService) {
|
|
14411
|
-
this.streamService.setChunkCallback(cb);
|
|
14412
|
-
} else {
|
|
14413
|
-
this._pendingChunkCallback = cb;
|
|
14414
|
-
}
|
|
14415
|
-
}
|
|
14416
|
-
handleEvent(event) {
|
|
14417
|
-
if (event.type === "context.threshold_exceeded" && !this.quiet) {
|
|
14418
|
-
const payload = event.payload;
|
|
14419
|
-
this.output.warn(`⚙ 上下文阈值 (${payload.totalTokens}/${payload.contextWindow})`);
|
|
14420
|
-
}
|
|
14421
|
-
if (event.type === "context.compacting" && !this.quiet) {
|
|
14422
|
-
this.output.info("⚙ 压缩中...");
|
|
14423
|
-
}
|
|
14424
|
-
if (event.type === "context.compacted" && !this.quiet) {
|
|
14425
|
-
this.output.success(`✓ 已压缩 (${event.payload.checkpointId})`);
|
|
14426
|
-
}
|
|
14427
|
-
this.streamService?.handleEvent(event);
|
|
14428
|
-
}
|
|
14429
|
-
async execute(message, sessionId, streamOptions, traceId, agentContext) {
|
|
14430
|
-
const options = {
|
|
14431
|
-
showReasoning: streamOptions?.showReasoning ?? this.streamOptions.showReasoning,
|
|
14432
|
-
showToolCalls: streamOptions?.showToolCalls ?? this.streamOptions.showToolCalls,
|
|
14433
|
-
showToolResults: streamOptions?.showToolResults ?? this.streamOptions.showToolResults
|
|
14434
|
-
};
|
|
14435
|
-
this.subscribeToEvents(options);
|
|
14436
|
-
this.streamService?.reset();
|
|
14437
|
-
if (!this.quiet) {
|
|
14438
|
-
this.output.info(`执行: ${message}`);
|
|
14439
|
-
}
|
|
14440
|
-
const contextHandler = new ContextHandlerService(this.env, this.sessionComponent, { maxRetries: 1, autoCompact: true });
|
|
14441
|
-
const { systemPrompt: agentContextSystemPrompt, eventSourceSystemPrompt: agentContextPreloadedPrompts, ...restAgentContext } = agentContext ?? {};
|
|
14442
|
-
let eventSourceFinalPrompt;
|
|
14443
|
-
if (typeof agentContextSystemPrompt === "string" && agentContextSystemPrompt.length > 0) {
|
|
14444
|
-
eventSourceFinalPrompt = agentContextSystemPrompt;
|
|
14445
|
-
} else if (typeof agentContextPreloadedPrompts === "string" && agentContextPreloadedPrompts.length > 0) {
|
|
14446
|
-
eventSourceFinalPrompt = agentContextPreloadedPrompts;
|
|
14447
|
-
}
|
|
14448
|
-
const context = {
|
|
14449
|
-
sessionId,
|
|
14450
|
-
metadata: {
|
|
14451
|
-
originalQuery: message,
|
|
14452
|
-
traceId,
|
|
14453
|
-
systemPrompt: eventSourceFinalPrompt
|
|
14454
|
-
},
|
|
14455
|
-
...restAgentContext
|
|
14456
|
-
};
|
|
14457
|
-
let result;
|
|
14458
|
-
try {
|
|
14459
|
-
result = await contextHandler.handleQueryWithContext(message, context);
|
|
14460
|
-
} catch (error) {
|
|
14461
|
-
if (error instanceof ContextError4 && error.code === ErrorCodes4.CONTEXT_THRESHOLD_EXCEEDED) {
|
|
14462
|
-
this.output.error(`上下文阈值超出限制: ${error.usage?.totalTokens}/${error.contextWindow}`);
|
|
14463
|
-
this.output.info("请手动压缩会话: roy-agent sessions compact " + sessionId);
|
|
14464
|
-
}
|
|
14465
|
-
throw error;
|
|
14466
|
-
}
|
|
14467
|
-
if (!this.quiet) {
|
|
14468
|
-
this.output.success("执行完成");
|
|
14469
|
-
}
|
|
14470
|
-
return result;
|
|
14471
|
-
}
|
|
14472
|
-
dispose() {
|
|
14473
|
-
if (this.unsubscribe) {
|
|
14474
|
-
this.unsubscribe();
|
|
14475
|
-
this.unsubscribe = null;
|
|
14476
|
-
}
|
|
14477
|
-
}
|
|
14478
|
-
getFullText() {
|
|
14479
|
-
return this.streamService?.getFullText() ?? "";
|
|
14480
|
-
}
|
|
14481
|
-
getLastUsage() {
|
|
14482
|
-
return this.streamService?.getUsageInfo() ?? null;
|
|
14483
|
-
}
|
|
14484
|
-
resetStream() {
|
|
14485
|
-
this.streamService?.reset();
|
|
14486
|
-
}
|
|
14487
|
-
async compact(sessionId) {
|
|
14488
|
-
try {
|
|
14489
|
-
const envCore = this.env.getComponent("core");
|
|
14490
|
-
if (envCore?.pushEnvEvent) {
|
|
14491
|
-
envCore.pushEnvEvent({
|
|
14492
|
-
type: "context.compacting",
|
|
14493
|
-
metadata: { sessionId },
|
|
14494
|
-
payload: {}
|
|
14495
|
-
});
|
|
14496
|
-
}
|
|
14497
|
-
const result = await this.sessionComponent.compact(sessionId, {
|
|
14498
|
-
summary: "Manual compact from interactive mode"
|
|
14499
|
-
});
|
|
14500
|
-
if (envCore?.pushEnvEvent) {
|
|
14501
|
-
envCore.pushEnvEvent({
|
|
14502
|
-
type: "context.compacted",
|
|
14503
|
-
metadata: { sessionId },
|
|
14504
|
-
payload: {
|
|
14505
|
-
checkpointId: result.checkpoint.id,
|
|
14506
|
-
messagesCompacted: result.deletedMessageCount
|
|
14507
|
-
}
|
|
14508
|
-
});
|
|
14509
|
-
}
|
|
14510
|
-
return {
|
|
14511
|
-
success: true,
|
|
14512
|
-
checkpoint: result.checkpoint,
|
|
14513
|
-
deletedMessageCount: result.deletedMessageCount
|
|
14514
|
-
};
|
|
14515
|
-
} catch (error) {
|
|
14516
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14517
|
-
this.output.error(`压缩失败: ${errorMessage}`);
|
|
14518
|
-
return {
|
|
14519
|
-
success: false,
|
|
14520
|
-
error: errorMessage
|
|
14521
|
-
};
|
|
14522
|
-
}
|
|
14523
|
-
}
|
|
14524
|
-
}
|
|
14525
|
-
__decorate([
|
|
14526
|
-
TracedAs7("cli.query-executor.execute", { recordParams: true, log: true })
|
|
14527
|
-
], QueryExecutor2.prototype, "execute", null);
|
|
14528
|
-
|
|
14529
|
-
// src/commands/interactive-event-sources.js
|
|
14530
|
-
import { TracedAs as TracedAs8 } from "@ai-setting/roy-agent-core";
|
|
14531
|
-
var __decorate2 = function(decorators, target, key, desc) {
|
|
14532
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14533
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14534
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
14535
|
-
else
|
|
14536
|
-
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14537
|
-
if (d = decorators[i])
|
|
14538
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14539
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14540
|
-
};
|
|
14541
|
-
async function startSingleEventSource2(eventSourceComponent, output, eventSourceId) {
|
|
14542
|
-
return EventSourceStarter2.instance.runSingle(eventSourceComponent, output, eventSourceId);
|
|
14543
|
-
}
|
|
14544
|
-
async function startEventSources2(eventSourceIds, eventSourceComponent, output) {
|
|
14545
|
-
return EventSourceStarter2.instance.run(eventSourceIds, eventSourceComponent, output);
|
|
14546
|
-
}
|
|
14547
|
-
|
|
14548
|
-
class EventSourceStarter2 {
|
|
14549
|
-
static instance = new EventSourceStarter2;
|
|
14550
|
-
async run(eventSourceIds, eventSourceComponent, output) {
|
|
14551
|
-
return startEventSourcesImpl2(eventSourceIds, eventSourceComponent, output);
|
|
14552
|
-
}
|
|
14553
|
-
async runSingle(eventSourceComponent, output, eventSourceId) {
|
|
14554
|
-
return startSingleEventSourceImpl2(eventSourceComponent, output, eventSourceId);
|
|
14555
|
-
}
|
|
14556
|
-
}
|
|
14557
|
-
__decorate2([
|
|
14558
|
-
TracedAs8("interactive.startEventSources", { recordParams: false, log: false })
|
|
14559
|
-
], EventSourceStarter2.prototype, "run", null);
|
|
14560
|
-
__decorate2([
|
|
14561
|
-
TracedAs8("interactive.startSingleEventSource", { recordParams: false, log: false })
|
|
14562
|
-
], EventSourceStarter2.prototype, "runSingle", null);
|
|
14563
|
-
async function startEventSourcesImpl2(eventSourceIds, eventSourceComponent, output) {
|
|
14564
|
-
const results = [];
|
|
14565
|
-
if (!eventSourceIds || eventSourceIds.length === 0) {
|
|
14566
|
-
return { results, total: 0, successCount: 0, failedCount: 0 };
|
|
14567
|
-
}
|
|
14568
|
-
for (const id of eventSourceIds) {
|
|
14569
|
-
if (!id)
|
|
14570
|
-
continue;
|
|
14571
|
-
const result = await startSingleEventSource2(eventSourceComponent, output, id);
|
|
14572
|
-
results.push(result);
|
|
14573
|
-
}
|
|
14574
|
-
const successCount = results.filter((r) => r.success).length;
|
|
14575
|
-
const failedCount = results.length - successCount;
|
|
14576
|
-
if (results.length > 1) {
|
|
14577
|
-
if (failedCount > 0) {
|
|
14578
|
-
output.info(`
|
|
14579
|
-
✅ 成功启动 ${successCount}/${results.length} 个事件源`);
|
|
14580
|
-
} else {
|
|
14581
|
-
output.success(`
|
|
14582
|
-
✅ 成功启动 ${successCount}/${results.length} 个事件源`);
|
|
14583
|
-
}
|
|
14584
|
-
}
|
|
14585
|
-
return { results, total: results.length, successCount, failedCount };
|
|
14586
|
-
}
|
|
14587
|
-
async function startSingleEventSourceImpl2(eventSourceComponent, output, eventSourceId) {
|
|
14588
|
-
const sources = eventSourceComponent.list();
|
|
14589
|
-
const matchedSource = sources.find((s) => s.id === eventSourceId || s.id.startsWith(eventSourceId));
|
|
14590
|
-
if (!matchedSource) {
|
|
14591
|
-
output.error(`❌ 事件源不存在: ${eventSourceId}`);
|
|
14592
|
-
output.info(`可用的事件源:`);
|
|
14593
|
-
for (const s of sources) {
|
|
14594
|
-
output.info(` - ${s.id.substring(0, 8)}: ${s.name} (${s.type})`);
|
|
14595
|
-
}
|
|
14596
|
-
return {
|
|
14597
|
-
id: eventSourceId,
|
|
14598
|
-
name: eventSourceId,
|
|
14599
|
-
success: false,
|
|
14600
|
-
status: "not_found",
|
|
14601
|
-
error: `EventSource not found: ${eventSourceId}`
|
|
14602
|
-
};
|
|
14603
|
-
}
|
|
14604
|
-
const actualId = matchedSource.id;
|
|
14605
|
-
const status = eventSourceComponent.getStatus(actualId);
|
|
14606
|
-
if (status === "running") {
|
|
14607
|
-
output.info(`\uD83D\uDCE1 事件源 ${matchedSource.name} 已在运行中`);
|
|
14608
|
-
return {
|
|
14609
|
-
id: actualId,
|
|
14610
|
-
name: matchedSource.name,
|
|
14611
|
-
success: true,
|
|
14612
|
-
status: "skipped"
|
|
14613
|
-
};
|
|
14614
|
-
}
|
|
14615
|
-
try {
|
|
14616
|
-
await eventSourceComponent.startSource(actualId);
|
|
14617
|
-
const verifyStatus = eventSourceComponent.getStatus(actualId);
|
|
14618
|
-
if (verifyStatus !== "running") {
|
|
14619
|
-
const errMsg = `启动后状态异常: ${verifyStatus}`;
|
|
14620
|
-
output.error(`❌ ${errMsg}`);
|
|
14621
|
-
return {
|
|
14622
|
-
id: actualId,
|
|
14623
|
-
name: matchedSource.name,
|
|
14624
|
-
success: false,
|
|
14625
|
-
status: "failed",
|
|
14626
|
-
error: errMsg
|
|
14627
|
-
};
|
|
14628
|
-
}
|
|
14629
|
-
output.success(`\uD83D\uDCE1 已启动事件源: ${matchedSource.name} (${verifyStatus})`);
|
|
14630
|
-
return {
|
|
14631
|
-
id: actualId,
|
|
14632
|
-
name: matchedSource.name,
|
|
14633
|
-
success: true,
|
|
14634
|
-
status: "started"
|
|
14635
|
-
};
|
|
14636
|
-
} catch (error) {
|
|
14637
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
14638
|
-
output.error(`❌ 启动事件源失败: ${matchedSource.name} - ${errMsg}`);
|
|
14639
|
-
return {
|
|
14640
|
-
id: actualId,
|
|
14641
|
-
name: matchedSource.name,
|
|
14642
|
-
success: false,
|
|
14643
|
-
status: "failed",
|
|
14644
|
-
error: errMsg
|
|
14645
|
-
};
|
|
14646
|
-
}
|
|
14647
|
-
}
|
|
14648
|
-
|
|
14649
|
-
// src/commands/collect-event-source-system-prompts.js
|
|
14650
|
-
import { resolveBountyIMSystemPrompt as resolveBountyIMSystemPrompt2 } from "@ai-setting/roy-agent-core";
|
|
14651
|
-
function resolveSystemPromptForSource2(config) {
|
|
14652
|
-
if (config.type === "bounty-im") {
|
|
14653
|
-
const imServerUrl = config.imServerUrl || config.options && config.options.imServerUrl;
|
|
14654
|
-
const address = config.address || config.options && config.options.address || "unknown";
|
|
14655
|
-
return resolveBountyIMSystemPrompt2({
|
|
14656
|
-
configSystemPrompt: config.systemPrompt,
|
|
14657
|
-
currentAddress: address,
|
|
14658
|
-
imServerUrl
|
|
14659
|
-
});
|
|
14660
|
-
}
|
|
14661
|
-
return config.systemPrompt;
|
|
14662
|
-
}
|
|
14663
|
-
function collectEventSourceSystemPrompts2(eventSourceIds, eventSourceComponent) {
|
|
14664
|
-
const result = [];
|
|
14665
|
-
for (const id of eventSourceIds) {
|
|
14666
|
-
const config = eventSourceComponent.get(id);
|
|
14667
|
-
if (!config)
|
|
14668
|
-
continue;
|
|
14669
|
-
const prompt = resolveSystemPromptForSource2(config);
|
|
14670
|
-
if (!prompt)
|
|
14671
|
-
continue;
|
|
14672
|
-
result.push({ id, type: config.type, prompt });
|
|
14673
|
-
}
|
|
14674
|
-
return result;
|
|
14675
|
-
}
|
|
14676
|
-
function joinResolvedSystemPrompts2(prompts) {
|
|
14677
|
-
return prompts.map((p) => p.prompt).join(`
|
|
14678
|
-
|
|
14679
|
-
---
|
|
14680
|
-
|
|
14681
|
-
`);
|
|
14682
|
-
}
|
|
14683
|
-
|
|
14684
|
-
// src/commands/act-agent-validation.js
|
|
14685
|
-
function validateActAgent2(agentComponent, agentName) {
|
|
14686
|
-
if (!agentName || agentName === "default") {
|
|
14687
|
-
return { valid: true };
|
|
14688
|
-
}
|
|
14689
|
-
if (!agentComponent?.getAgent(agentName)) {
|
|
14690
|
-
return {
|
|
14691
|
-
valid: false,
|
|
14692
|
-
message: `Agent "${agentName}" 不存在`
|
|
14693
|
-
};
|
|
14694
|
-
}
|
|
14695
|
-
return { valid: true };
|
|
14696
|
-
}
|
|
14697
|
-
function buildActAgentContext2(agentName) {
|
|
14698
|
-
if (!agentName || agentName === "default") {
|
|
14699
|
-
return;
|
|
14700
|
-
}
|
|
14701
|
-
return { agentType: agentName };
|
|
14702
|
-
}
|
|
14703
|
-
|
|
14704
|
-
// src/commands/shared/event-handler.js
|
|
14705
|
-
import { TracedAs as TracedAs9 } from "@ai-setting/roy-agent-core";
|
|
14706
|
-
var __decorate3 = function(decorators, target, key, desc) {
|
|
14707
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14708
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14709
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
14710
|
-
else
|
|
14711
|
-
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14712
|
-
if (d = decorators[i])
|
|
14713
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14714
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14715
|
-
};
|
|
14716
|
-
|
|
14717
|
-
class EventHandler2 {
|
|
14718
|
-
env;
|
|
14719
|
-
eventTypes;
|
|
14720
|
-
onEvent;
|
|
14721
|
-
onEventWithEnv;
|
|
14722
|
-
formatter;
|
|
14723
|
-
isIdle;
|
|
14724
|
-
idleCheckInterval;
|
|
14725
|
-
queue = [];
|
|
14726
|
-
isProcessing = false;
|
|
14727
|
-
isStopped = false;
|
|
14728
|
-
unsubscribe = null;
|
|
14729
|
-
sessionComponent = null;
|
|
14730
|
-
activeEventSessionId = null;
|
|
14731
|
-
constructor(options) {
|
|
14732
|
-
this.env = options.env;
|
|
14733
|
-
this.eventTypes = options.eventTypes;
|
|
14734
|
-
this.onEvent = options.onEvent;
|
|
14735
|
-
this.onEventWithEnv = options.onEventWithEnv;
|
|
14736
|
-
this.formatter = options.formatter ?? new EventMessageFormatter;
|
|
14737
|
-
this.isIdle = options.isIdle ?? (() => true);
|
|
14738
|
-
this.idleCheckInterval = options.idleCheckInterval ?? 100;
|
|
14739
|
-
this.sessionComponent = options.sessionComponent ?? null;
|
|
14740
|
-
}
|
|
14741
|
-
start() {
|
|
14742
|
-
this.isStopped = false;
|
|
14743
|
-
this.unsubscribe = this.env.subscribeAll((event) => {
|
|
14744
|
-
if (this.matchesEventType(event.type)) {
|
|
14745
|
-
this.handleEvent(event);
|
|
14746
|
-
}
|
|
14747
|
-
});
|
|
14748
|
-
return () => this.stop();
|
|
14749
|
-
}
|
|
14750
|
-
matchesEventType(eventType) {
|
|
14751
|
-
for (const pattern of this.eventTypes) {
|
|
14752
|
-
if (this.matchPattern(eventType, pattern)) {
|
|
14753
|
-
return true;
|
|
14754
|
-
}
|
|
14755
|
-
}
|
|
14756
|
-
return false;
|
|
14757
|
-
}
|
|
14758
|
-
matchPattern(eventType, pattern) {
|
|
14759
|
-
if (pattern === "*")
|
|
14760
|
-
return true;
|
|
14761
|
-
if (pattern.endsWith(".*")) {
|
|
14762
|
-
const prefix = pattern.slice(0, -2);
|
|
14763
|
-
return eventType === prefix || eventType.startsWith(prefix + ".");
|
|
14764
|
-
}
|
|
14765
|
-
return eventType === pattern;
|
|
14766
|
-
}
|
|
14767
|
-
stop() {
|
|
14768
|
-
this.isStopped = true;
|
|
14769
|
-
if (this.unsubscribe) {
|
|
14770
|
-
this.unsubscribe();
|
|
14771
|
-
this.unsubscribe = null;
|
|
14772
|
-
}
|
|
14773
|
-
this.queue = [];
|
|
14774
|
-
this.isProcessing = false;
|
|
14775
|
-
this.clearActiveSession();
|
|
14776
|
-
}
|
|
14777
|
-
handleEvent(event) {
|
|
14778
|
-
if (this.isStopped) {
|
|
14779
|
-
return;
|
|
14780
|
-
}
|
|
14781
|
-
const formatted = this.formatter.formatWithEvent(event);
|
|
14782
|
-
this.enqueue(formatted);
|
|
14783
|
-
}
|
|
14784
|
-
enqueue(formattedEvent) {
|
|
14785
|
-
if (this.isStopped) {
|
|
14786
|
-
return;
|
|
14787
|
-
}
|
|
14788
|
-
this.queue.push(formattedEvent);
|
|
14789
|
-
if (!this.isProcessing) {
|
|
14790
|
-
this.processQueue();
|
|
14791
|
-
}
|
|
14792
|
-
}
|
|
14793
|
-
getQueueLength() {
|
|
14794
|
-
return this.queue.length;
|
|
14795
|
-
}
|
|
14796
|
-
isQueueEmpty() {
|
|
14797
|
-
return this.queue.length === 0;
|
|
14798
|
-
}
|
|
14799
|
-
async processQueue() {
|
|
14800
|
-
this.isProcessing = true;
|
|
14801
|
-
const sessionId = await this.ensureActiveSession();
|
|
14802
|
-
if (this.isStopped) {
|
|
14803
|
-
this.clearActiveSession();
|
|
14804
|
-
this.isProcessing = false;
|
|
14805
|
-
return;
|
|
14806
|
-
}
|
|
14807
|
-
while (!this.isStopped && this.queue.length > 0) {
|
|
14808
|
-
await this.waitForIdle();
|
|
14809
|
-
if (this.isStopped) {
|
|
14810
|
-
break;
|
|
14811
|
-
}
|
|
14812
|
-
const item = this.queue.shift();
|
|
14813
|
-
if (!item) {
|
|
14814
|
-
break;
|
|
14815
|
-
}
|
|
14816
|
-
if (sessionId) {
|
|
14817
|
-
item.eventSessionId = sessionId;
|
|
14818
|
-
}
|
|
14819
|
-
try {
|
|
14820
|
-
if (this.onEventWithEnv) {
|
|
14821
|
-
await this.onEventWithEnv(item);
|
|
14822
|
-
continue;
|
|
14823
|
-
}
|
|
14824
|
-
await this.onEvent(item.message);
|
|
14825
|
-
} catch (error) {
|
|
14826
|
-
console.error(`[EventHandler] 处理事件失败:`, error);
|
|
14827
|
-
}
|
|
14828
|
-
}
|
|
14829
|
-
this.isProcessing = false;
|
|
14830
|
-
}
|
|
14831
|
-
async ensureActiveSession() {
|
|
14832
|
-
if (!this.sessionComponent)
|
|
14833
|
-
return null;
|
|
14834
|
-
if (this.activeEventSessionId)
|
|
14835
|
-
return this.activeEventSessionId;
|
|
14836
|
-
const triggerSessionId = this.queue.map((item) => item.triggerSessionId).find((id) => !!id);
|
|
14837
|
-
if (triggerSessionId) {
|
|
14838
|
-
try {
|
|
14839
|
-
const existing = await this.sessionComponent.get(triggerSessionId);
|
|
14840
|
-
if (existing) {
|
|
14841
|
-
if (this.isStopped) {
|
|
14842
|
-
return null;
|
|
14843
|
-
}
|
|
14844
|
-
this.activeEventSessionId = existing.id;
|
|
14845
|
-
await this.sessionComponent.setActiveSession(existing.id);
|
|
14846
|
-
return existing.id;
|
|
14847
|
-
}
|
|
14848
|
-
console.warn(`[EventHandler] Parent session ${triggerSessionId} not found, trying global active session`);
|
|
14849
|
-
} catch (error) {
|
|
14850
|
-
console.error(`[EventHandler] Failed to lookup parent session ${triggerSessionId}:`, error);
|
|
14851
|
-
}
|
|
14852
|
-
}
|
|
14853
|
-
try {
|
|
14854
|
-
const activeId = this.sessionComponent.getActiveSessionId();
|
|
14855
|
-
if (activeId) {
|
|
14856
|
-
const existing = await this.sessionComponent.get(activeId);
|
|
14857
|
-
if (existing) {
|
|
14858
|
-
if (this.isStopped) {
|
|
14859
|
-
return null;
|
|
14860
|
-
}
|
|
14861
|
-
this.activeEventSessionId = existing.id;
|
|
14862
|
-
return existing.id;
|
|
14863
|
-
}
|
|
14864
|
-
}
|
|
14865
|
-
} catch (error) {
|
|
14866
|
-
console.error(`[EventHandler] Failed to lookup global active session:`, error);
|
|
14867
|
-
}
|
|
14868
|
-
return this.createNewEventSession();
|
|
14869
|
-
}
|
|
14870
|
-
async createNewEventSession() {
|
|
14871
|
-
try {
|
|
14872
|
-
const session = await this.sessionComponent.create({
|
|
14873
|
-
title: `Event Session - ${new Date().toLocaleString()}`
|
|
14874
|
-
});
|
|
14875
|
-
if (this.isStopped) {
|
|
14876
|
-
this.activeEventSessionId = null;
|
|
14877
|
-
return null;
|
|
14878
|
-
}
|
|
14879
|
-
this.activeEventSessionId = session.id;
|
|
14880
|
-
await this.sessionComponent.setActiveSession(session.id);
|
|
14881
|
-
return session.id;
|
|
14882
|
-
} catch (error) {
|
|
14883
|
-
console.error(`[EventHandler] 创建事件 session 失败:`, error);
|
|
14884
|
-
return null;
|
|
14885
|
-
}
|
|
14886
|
-
}
|
|
14887
|
-
clearActiveSession() {
|
|
14888
|
-
this.activeEventSessionId = null;
|
|
14889
|
-
}
|
|
14890
|
-
getActiveEventSessionId() {
|
|
14891
|
-
return this.activeEventSessionId;
|
|
14892
|
-
}
|
|
14893
|
-
async waitForIdle() {
|
|
14894
|
-
while (!this.isStopped && !this.isIdle()) {
|
|
14895
|
-
await this.sleep(this.idleCheckInterval);
|
|
14896
|
-
}
|
|
14897
|
-
}
|
|
14898
|
-
sleep(ms) {
|
|
14899
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
14900
|
-
}
|
|
14901
|
-
}
|
|
14902
|
-
__decorate3([
|
|
14903
|
-
TracedAs9("cli.event-handler.handleEvent", { recordParams: true })
|
|
14904
|
-
], EventHandler2.prototype, "handleEvent", null);
|
|
14905
|
-
|
|
14906
|
-
// src/commands/shared/task-event-handler.js
|
|
14907
|
-
import { createLogger as createLogger7 } from "@ai-setting/roy-agent-core";
|
|
14908
|
-
var logger6 = createLogger7("task-event-handler");
|
|
14909
|
-
var TASK_EVENTS2 = {
|
|
14910
|
-
CREATED: "task.created",
|
|
14911
|
-
UPDATED: "task.updated",
|
|
14912
|
-
COMPLETED: "task.completed",
|
|
14913
|
-
DELETED: "task.deleted",
|
|
14914
|
-
OPERATION_ADDED: "task.operation_added",
|
|
14915
|
-
DELEGATED: "task.delegated"
|
|
14916
|
-
};
|
|
14917
|
-
|
|
14918
|
-
class TaskEventHandler2 {
|
|
14919
|
-
env;
|
|
14920
|
-
enabled;
|
|
14921
|
-
unsubscribe = null;
|
|
14922
|
-
constructor(options) {
|
|
14923
|
-
this.env = options.env;
|
|
14924
|
-
this.enabled = options.enabled ?? true;
|
|
14925
|
-
}
|
|
14926
|
-
start() {
|
|
14927
|
-
if (!this.enabled) {
|
|
14928
|
-
return () => {};
|
|
14929
|
-
}
|
|
14930
|
-
this.unsubscribe = this.env.subscribeAll((event) => {
|
|
14931
|
-
if (event.type.startsWith("task.")) {
|
|
14932
|
-
this.handleEvent(event);
|
|
14933
|
-
}
|
|
14934
|
-
});
|
|
14935
|
-
logger6.info("[TaskEventHandler] Started");
|
|
14936
|
-
return () => this.stop();
|
|
14937
|
-
}
|
|
14938
|
-
stop() {
|
|
14939
|
-
if (this.unsubscribe) {
|
|
14940
|
-
this.unsubscribe();
|
|
14941
|
-
this.unsubscribe = null;
|
|
14942
|
-
logger6.info("[TaskEventHandler] Stopped");
|
|
14943
|
-
}
|
|
14944
|
-
}
|
|
14945
|
-
handleEvent(event) {
|
|
14946
|
-
const payload = event.payload;
|
|
14947
|
-
switch (event.type) {
|
|
14948
|
-
case TASK_EVENTS2.CREATED:
|
|
14949
|
-
this.logTaskCreated(payload);
|
|
14950
|
-
break;
|
|
14951
|
-
case TASK_EVENTS2.UPDATED:
|
|
14952
|
-
this.logTaskUpdated(payload);
|
|
14953
|
-
break;
|
|
14954
|
-
case TASK_EVENTS2.COMPLETED:
|
|
14955
|
-
this.logTaskCompleted(payload);
|
|
14956
|
-
break;
|
|
14957
|
-
case TASK_EVENTS2.DELETED:
|
|
14958
|
-
this.logTaskDeleted(payload);
|
|
14959
|
-
break;
|
|
14960
|
-
case TASK_EVENTS2.OPERATION_ADDED:
|
|
14961
|
-
this.logOperationAdded(payload);
|
|
14962
|
-
break;
|
|
14963
|
-
case TASK_EVENTS2.DELEGATED:
|
|
14964
|
-
this.logTaskDelegated(payload);
|
|
14965
|
-
break;
|
|
14966
|
-
default:
|
|
14967
|
-
logger6.info(`[${event.type}]`, payload);
|
|
14968
|
-
}
|
|
14969
|
-
}
|
|
14970
|
-
logTaskCreated(payload) {
|
|
14971
|
-
const task = payload.task;
|
|
14972
|
-
logger6.info(`\uD83D\uDCDD Task created: #${task.id} - ${task.title}`);
|
|
14973
|
-
logger6.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}`);
|
|
14974
|
-
if (task.project_path) {
|
|
14975
|
-
logger6.info(` Project: ${task.project_path}`);
|
|
14976
|
-
}
|
|
14977
|
-
if (task.context) {
|
|
14978
|
-
logger6.info(` Context: ${task.context}`);
|
|
14979
|
-
}
|
|
14980
|
-
}
|
|
14981
|
-
logTaskUpdated(payload) {
|
|
14982
|
-
const task = payload.task;
|
|
14983
|
-
const changes = payload.changes;
|
|
14984
|
-
logger6.info(`✏️ Task updated: #${task.id} - ${task.title}`);
|
|
14985
|
-
logger6.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}, Progress: ${task.progress}%`);
|
|
14986
|
-
if (changes) {
|
|
14987
|
-
logger6.info(` Changes: ${JSON.stringify(changes)}`);
|
|
14988
|
-
}
|
|
14989
|
-
}
|
|
14990
|
-
logTaskCompleted(payload) {
|
|
14991
|
-
const task = payload.task;
|
|
14992
|
-
logger6.info(`✅ Task completed: #${task.id} - ${task.title}`);
|
|
14993
|
-
logger6.info(` Progress: ${task.progress}%, Updated: ${task.updatedAt}`);
|
|
14994
|
-
}
|
|
14995
|
-
logTaskDeleted(payload) {
|
|
14996
|
-
logger6.info(`\uD83D\uDDD1️ Task deleted: #${payload.taskId}`);
|
|
14997
|
-
}
|
|
14998
|
-
logOperationAdded(payload) {
|
|
14999
|
-
const op = payload.operation;
|
|
15000
|
-
logger6.info(`\uD83D\uDCCB Operation added to task #${payload.taskId}:`);
|
|
15001
|
-
logger6.info(` [${op.milestoneType}] ${op.milestoneTitle}`);
|
|
15002
|
-
logger6.info(` Session: ${op.sessionId}`);
|
|
15003
|
-
}
|
|
15004
|
-
logTaskDelegated(payload) {
|
|
15005
|
-
logger6.info(`\uD83D\uDE80 Task delegated: #${payload.taskId}`);
|
|
15006
|
-
logger6.info(` Background: ${payload.backgroundTaskId}, Type: ${payload.subagentType}`);
|
|
15007
|
-
logger6.info(` ${payload.description}`);
|
|
15008
|
-
}
|
|
15009
|
-
}
|
|
15010
|
-
|
|
15011
|
-
// src/commands/shared/event-message-formatter.js
|
|
15012
|
-
var TaskEventTypes2 = {
|
|
15013
|
-
TASK_STARTED: "task.background.started",
|
|
15014
|
-
TASK_PROGRESS: "task.background.progress",
|
|
15015
|
-
TASK_COMPLETED: "task.background.completed",
|
|
15016
|
-
TASK_FAILED: "task.background.failed",
|
|
15017
|
-
TASK_TIMEOUT: "task.background.timeout",
|
|
15018
|
-
TASK_STOPPED: "task.background.stopped",
|
|
15019
|
-
TASK_ASK_USER: "task.background.ask_user"
|
|
15020
|
-
};
|
|
15021
|
-
var EventSourceEventTypes2 = {
|
|
15022
|
-
EVENT_SOURCE_STARTED: "event-source.started",
|
|
15023
|
-
EVENT_SOURCE_STOPPED: "event-source.stopped",
|
|
15024
|
-
EVENT_SOURCE_EVENT_PREFIX: "event-source.event."
|
|
15025
|
-
};
|
|
15026
|
-
|
|
15027
|
-
class EventMessageFormatter2 {
|
|
15028
|
-
prefix;
|
|
15029
|
-
showTimestamp;
|
|
15030
|
-
constructor(options = {}) {
|
|
15031
|
-
this.prefix = options.prefix ?? "[通知]";
|
|
15032
|
-
this.showTimestamp = options.showTimestamp ?? false;
|
|
15033
|
-
}
|
|
15034
|
-
format(event) {
|
|
15035
|
-
const { type, payload } = event;
|
|
15036
|
-
switch (type) {
|
|
15037
|
-
case TaskEventTypes2.TASK_STARTED:
|
|
15038
|
-
return this.formatTaskStarted(payload);
|
|
15039
|
-
case TaskEventTypes2.TASK_PROGRESS:
|
|
15040
|
-
return this.formatTaskProgress(payload);
|
|
15041
|
-
case TaskEventTypes2.TASK_COMPLETED:
|
|
15042
|
-
return this.formatTaskCompleted(payload);
|
|
15043
|
-
case TaskEventTypes2.TASK_FAILED:
|
|
15044
|
-
return this.formatTaskFailed(payload);
|
|
15045
|
-
case TaskEventTypes2.TASK_TIMEOUT:
|
|
15046
|
-
return this.formatTaskTimeout(payload);
|
|
15047
|
-
case TaskEventTypes2.TASK_STOPPED:
|
|
15048
|
-
return this.formatTaskStopped(payload);
|
|
15049
|
-
case TaskEventTypes2.TASK_ASK_USER:
|
|
15050
|
-
return this.formatTaskAskUser(payload);
|
|
15051
|
-
case EventSourceEventTypes2.EVENT_SOURCE_STARTED:
|
|
15052
|
-
return this.formatEventSourceStarted(payload);
|
|
15053
|
-
case EventSourceEventTypes2.EVENT_SOURCE_STOPPED:
|
|
15054
|
-
return this.formatEventSourceStopped(payload);
|
|
15055
|
-
default:
|
|
15056
|
-
if (type.startsWith(EventSourceEventTypes2.EVENT_SOURCE_EVENT_PREFIX)) {
|
|
15057
|
-
return this.formatEventSourceEvent(event);
|
|
15058
|
-
}
|
|
15059
|
-
return this.formatGeneric(event);
|
|
15060
|
-
}
|
|
15061
|
-
}
|
|
15062
|
-
formatTaskStarted(payload) {
|
|
15063
|
-
const desc = payload.description || "未命名任务";
|
|
15064
|
-
return `${this.prefix} \uD83D\uDCE2 后台任务「${desc}」已启动`;
|
|
15065
|
-
}
|
|
15066
|
-
formatTaskProgress(payload) {
|
|
15067
|
-
const desc = payload.description || "未命名任务";
|
|
15068
|
-
const message = payload.progressMessage || "";
|
|
15069
|
-
const taskId = payload.associatedTaskId;
|
|
15070
|
-
let result = `${this.prefix} \uD83D\uDD04 后台任务「${desc}」`;
|
|
15071
|
-
if (taskId !== undefined) {
|
|
15072
|
-
result += `[Task #${taskId}] `;
|
|
15073
|
-
}
|
|
15074
|
-
result += `还在进行中,请耐心等待。需查询具体进度可调用 task_get / task_operation_list 等工具`;
|
|
15075
|
-
if (message)
|
|
15076
|
-
result += ` - ${message}`;
|
|
15077
|
-
return result;
|
|
15078
|
-
}
|
|
15079
|
-
formatTaskCompleted(payload) {
|
|
15080
|
-
const desc = payload.description || "未命名任务";
|
|
15081
|
-
const result = payload.result;
|
|
15082
|
-
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15083
|
-
const bgProcessId = payload.backgroundTaskId || "";
|
|
15084
|
-
const taskId = payload.associatedTaskId;
|
|
15085
|
-
let message = `${this.prefix} ✅ 后台任务「${desc}」已完成 ${time}`;
|
|
15086
|
-
if (bgProcessId) {
|
|
15087
|
-
message += `
|
|
15088
|
-
bgprocess: ${bgProcessId}`;
|
|
15089
|
-
}
|
|
15090
|
-
if (taskId !== undefined) {
|
|
15091
|
-
message += `
|
|
15092
|
-
Task #${taskId}`;
|
|
15093
|
-
}
|
|
15094
|
-
if (result) {
|
|
15095
|
-
message += `
|
|
15096
|
-
结果: ${result}`;
|
|
15097
|
-
}
|
|
15098
|
-
message += this.appendSubSessionId(payload);
|
|
15099
|
-
return message;
|
|
15100
|
-
}
|
|
15101
|
-
formatTaskFailed(payload) {
|
|
15102
|
-
const desc = payload.description || "未命名任务";
|
|
15103
|
-
const error = payload.error || "未知错误";
|
|
15104
|
-
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15105
|
-
const bgProcessId = payload.backgroundTaskId || "";
|
|
15106
|
-
const taskId = payload.associatedTaskId;
|
|
15107
|
-
let message = `${this.prefix} ❌ 后台任务「${desc}」失败 ${time}`;
|
|
15108
|
-
if (bgProcessId) {
|
|
15109
|
-
message += `
|
|
15110
|
-
bgprocess: ${bgProcessId}`;
|
|
15111
|
-
}
|
|
15112
|
-
if (taskId !== undefined) {
|
|
15113
|
-
message += `
|
|
15114
|
-
Task #${taskId}`;
|
|
15115
|
-
}
|
|
15116
|
-
if (error) {
|
|
15117
|
-
const truncatedError = error.length > 100 ? error.substring(0, 100) + "..." : error;
|
|
15118
|
-
message += `
|
|
15119
|
-
错误: ${truncatedError}`;
|
|
15120
|
-
}
|
|
15121
|
-
message += this.appendSubSessionId(payload);
|
|
15122
|
-
return message;
|
|
15123
|
-
}
|
|
15124
|
-
formatTaskTimeout(payload) {
|
|
15125
|
-
const desc = payload.description || "未命名任务";
|
|
15126
|
-
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15127
|
-
const bgProcessId = payload.backgroundTaskId || "";
|
|
15128
|
-
const taskId = payload.associatedTaskId;
|
|
15129
|
-
let message = `${this.prefix} ⏱️ 后台任务「${desc}」超时 ${time}`;
|
|
15130
|
-
if (bgProcessId) {
|
|
15131
|
-
message += `
|
|
15132
|
-
bgprocess: ${bgProcessId}`;
|
|
15133
|
-
}
|
|
15134
|
-
if (taskId !== undefined) {
|
|
15135
|
-
message += `
|
|
15136
|
-
Task #${taskId}`;
|
|
15137
|
-
}
|
|
15138
|
-
message += this.appendSubSessionId(payload);
|
|
15139
|
-
return message;
|
|
15140
|
-
}
|
|
15141
|
-
formatTaskStopped(payload) {
|
|
15142
|
-
const desc = payload.description || "未命名任务";
|
|
15143
|
-
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15144
|
-
const bgProcessId = payload.backgroundTaskId || "";
|
|
15145
|
-
const taskId = payload.associatedTaskId;
|
|
15146
|
-
let message = `${this.prefix} \uD83D\uDED1 后台任务「${desc}」已停止 ${time}`;
|
|
15147
|
-
if (bgProcessId) {
|
|
15148
|
-
message += `
|
|
15149
|
-
bgprocess: ${bgProcessId}`;
|
|
15150
|
-
}
|
|
15151
|
-
if (taskId !== undefined) {
|
|
15152
|
-
message += `
|
|
15153
|
-
Task #${taskId}`;
|
|
15154
|
-
}
|
|
15155
|
-
message += this.appendSubSessionId(payload);
|
|
15156
|
-
return message;
|
|
15157
|
-
}
|
|
15158
|
-
formatTaskAskUser(payload) {
|
|
15159
|
-
const desc = payload.description || "未命名任务";
|
|
15160
|
-
const bgProcessId = payload.backgroundTaskId || "";
|
|
15161
|
-
const subSessionId = payload.subSessionId || "";
|
|
15162
|
-
const query = payload.query || "(空问题)";
|
|
15163
|
-
let message = `${this.prefix} ❓ 后台子代理「${desc}」请求用户输入`;
|
|
15164
|
-
if (bgProcessId) {
|
|
15165
|
-
message += `
|
|
15166
|
-
bgprocess: ${bgProcessId}`;
|
|
15167
|
-
}
|
|
15168
|
-
if (subSessionId) {
|
|
15169
|
-
message += `
|
|
15170
|
-
subSessionId: ${subSessionId}`;
|
|
15171
|
-
}
|
|
15172
|
-
message += `
|
|
15173
|
-
|
|
15174
|
-
${query}`;
|
|
15175
|
-
if (payload.hints && payload.hints.length > 0) {
|
|
15176
|
-
message += `
|
|
15177
|
-
|
|
15178
|
-
[\uD83E\uDD16 Agent 操作提示]`;
|
|
15179
|
-
for (const hint of payload.hints) {
|
|
15180
|
-
message += `
|
|
15181
|
-
${hint}`;
|
|
15182
|
-
}
|
|
15183
|
-
}
|
|
15184
|
-
return message;
|
|
15185
|
-
}
|
|
15186
|
-
appendSubSessionId(payload) {
|
|
15187
|
-
if (payload.subSessionId) {
|
|
15188
|
-
return `
|
|
15189
|
-
subSessionId: ${payload.subSessionId}`;
|
|
15190
|
-
}
|
|
15191
|
-
return "";
|
|
15192
|
-
}
|
|
15193
|
-
formatGeneric(event) {
|
|
15194
|
-
return `${this.prefix} 收到事件: ${event.type}`;
|
|
15195
|
-
}
|
|
15196
|
-
formatEventSourceStarted(payload) {
|
|
15197
|
-
return `${this.prefix} \uD83D\uDCE1 事件源「${payload.sourceId}」(类型: ${payload.sourceType}) 已启动`;
|
|
15198
|
-
}
|
|
15199
|
-
formatEventSourceStopped(payload) {
|
|
15200
|
-
return `${this.prefix} \uD83D\uDCE1 事件源「${payload.sourceId}」(类型: ${payload.sourceType}) 已停止`;
|
|
15201
|
-
}
|
|
15202
|
-
formatEventSourceEvent(event) {
|
|
15203
|
-
const payload = event.payload;
|
|
15204
|
-
const sourceType = payload?.sourceType || "unknown";
|
|
15205
|
-
const message = payload?.message || "";
|
|
15206
|
-
if (message) {
|
|
15207
|
-
return `[${sourceType}] ${message}`;
|
|
15208
|
-
}
|
|
15209
|
-
return `[${sourceType}] ${JSON.stringify(payload, null, 2)}`;
|
|
15210
|
-
}
|
|
15211
|
-
formatDuration(ms) {
|
|
15212
|
-
if (ms < 1000)
|
|
15213
|
-
return `${ms}ms`;
|
|
15214
|
-
if (ms < 60000)
|
|
15215
|
-
return `${(ms / 1000).toFixed(1)}秒`;
|
|
15216
|
-
const minutes = Math.floor(ms / 60000);
|
|
15217
|
-
const seconds = Math.floor(ms % 60000 / 1000);
|
|
15218
|
-
return `${minutes}分${seconds}秒`;
|
|
15219
|
-
}
|
|
15220
|
-
formatWithEvent(event) {
|
|
15221
|
-
const triggerSessionId = extractTriggerSessionId2(event);
|
|
15222
|
-
return {
|
|
15223
|
-
message: this.format(event),
|
|
15224
|
-
envEvent: event,
|
|
15225
|
-
triggerSessionId
|
|
14850
|
+
setHistory((h) => [
|
|
14851
|
+
...h,
|
|
14852
|
+
{ role: "tool", content: `\uD83D\uDCE2 ${message}`, id: notifId }
|
|
14853
|
+
]);
|
|
14854
|
+
if (executeQueryRef.current) {
|
|
14855
|
+
await executeQueryRef.current(message);
|
|
14856
|
+
}
|
|
15226
14857
|
};
|
|
15227
|
-
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
|
|
15235
|
-
}
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
14858
|
+
const handleNotification = wrapFunction6(handleNotificationImpl, "tui.run-tui.handleNotification", {
|
|
14859
|
+
recordParams: true,
|
|
14860
|
+
recordResult: false,
|
|
14861
|
+
log: true,
|
|
14862
|
+
paramFilter: (args) => ({
|
|
14863
|
+
"message.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
14864
|
+
"message.head": typeof args[0] === "string" ? args[0].slice(0, 60) : "",
|
|
14865
|
+
isProcessingRef: isProcessingRef.current ?? 0
|
|
14866
|
+
})
|
|
14867
|
+
});
|
|
14868
|
+
const isIdle = () => {
|
|
14869
|
+
return isProcessingRef.current === 0;
|
|
14870
|
+
};
|
|
14871
|
+
const appendTraceId = (traceId) => {
|
|
14872
|
+
const traceIdItemId = `h${++historyIdRef.current}`;
|
|
14873
|
+
setHistory((h) => [
|
|
14874
|
+
...h,
|
|
14875
|
+
{ role: "tool", content: `\uD83D\uDD0D [Trace] ${traceId}`, id: traceIdItemId }
|
|
14876
|
+
]);
|
|
14877
|
+
};
|
|
14878
|
+
onRegisterHandlers({
|
|
14879
|
+
onNotification: handleNotification,
|
|
14880
|
+
isIdle,
|
|
14881
|
+
appendTraceId
|
|
14882
|
+
});
|
|
14883
|
+
}, [onRegisterHandlers]);
|
|
14884
|
+
const handleSubmit = useCallback4(async (raw) => {
|
|
14885
|
+
const trimmed = raw.trim();
|
|
14886
|
+
if (!trimmed)
|
|
14887
|
+
return;
|
|
14888
|
+
const slashCtx = {
|
|
14889
|
+
model,
|
|
14890
|
+
workdir,
|
|
14891
|
+
maxLines,
|
|
14892
|
+
userTurnCount: userTurnCountRef.current,
|
|
14893
|
+
assistantTurnCount: assistantTurnCountRef.current
|
|
14894
|
+
};
|
|
14895
|
+
const result = dispatchSlashCommand(trimmed, slashCtx);
|
|
14896
|
+
if (result.kind === "exit") {
|
|
14897
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14898
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14899
|
+
setHistory((h) => [
|
|
14900
|
+
...h,
|
|
14901
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14902
|
+
{ role: "tool", content: "\uD83D\uDC4B Goodbye!", id: toolId }
|
|
14903
|
+
]);
|
|
14904
|
+
doExit();
|
|
15248
14905
|
return;
|
|
15249
14906
|
}
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
15259
|
-
try {
|
|
15260
|
-
logger7.warn(`Cleanup failed: ${message}`);
|
|
15261
|
-
} catch {
|
|
15262
|
-
try {
|
|
15263
|
-
process.stderr.write(`[shutdown] Cleanup failed: ${message}
|
|
15264
|
-
`);
|
|
15265
|
-
} catch {}
|
|
15266
|
-
}
|
|
14907
|
+
if (result.kind === "handled") {
|
|
14908
|
+
if (result.message === CLEAR_SENTINEL) {
|
|
14909
|
+
setHistory([]);
|
|
14910
|
+
setUserHistory([]);
|
|
14911
|
+
userTurnCountRef.current = 0;
|
|
14912
|
+
assistantTurnCountRef.current = 0;
|
|
14913
|
+
setErrorMessage(null);
|
|
14914
|
+
return;
|
|
15267
14915
|
}
|
|
14916
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14917
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14918
|
+
setHistory((h) => [
|
|
14919
|
+
...h,
|
|
14920
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14921
|
+
{ role: "tool", content: result.message, id: toolId }
|
|
14922
|
+
]);
|
|
14923
|
+
return;
|
|
15268
14924
|
}
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15274
|
-
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
process.removeListener("SIGTERM", shutdown);
|
|
14925
|
+
if (result.kind === "unknown") {
|
|
14926
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14927
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14928
|
+
setHistory((h) => [
|
|
14929
|
+
...h,
|
|
14930
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14931
|
+
{ role: "tool", content: `⚠ ${result.message}`, id: toolId }
|
|
14932
|
+
]);
|
|
14933
|
+
return;
|
|
15279
14934
|
}
|
|
15280
|
-
|
|
15281
|
-
|
|
14935
|
+
if (result.kind === "set-max-lines") {
|
|
14936
|
+
setMaxLines(result.value);
|
|
14937
|
+
const userId2 = `h${++historyIdRef.current}`;
|
|
14938
|
+
const toolId = `h${++historyIdRef.current}`;
|
|
14939
|
+
setHistory((h) => [
|
|
14940
|
+
...h,
|
|
14941
|
+
{ role: "user", content: trimmed, id: userId2 },
|
|
14942
|
+
{
|
|
14943
|
+
role: "tool",
|
|
14944
|
+
content: `max-lines set to ${result.value}`,
|
|
14945
|
+
id: toolId
|
|
14946
|
+
}
|
|
14947
|
+
]);
|
|
14948
|
+
return;
|
|
14949
|
+
}
|
|
14950
|
+
setErrorMessage(null);
|
|
14951
|
+
const userId = `h${++historyIdRef.current}`;
|
|
14952
|
+
setHistory((h) => [
|
|
14953
|
+
...h,
|
|
14954
|
+
{ role: "user", content: trimmed, id: userId }
|
|
14955
|
+
]);
|
|
14956
|
+
setUserHistory((uh) => [trimmed, ...uh]);
|
|
14957
|
+
userTurnCountRef.current += 1;
|
|
14958
|
+
await executeQuery(trimmed);
|
|
14959
|
+
}, [
|
|
14960
|
+
doExit,
|
|
14961
|
+
exit,
|
|
14962
|
+
executeQuery,
|
|
14963
|
+
maxLines,
|
|
14964
|
+
model,
|
|
14965
|
+
workdir
|
|
14966
|
+
]);
|
|
14967
|
+
const handleCancel = useCallback4(() => {
|
|
14968
|
+
doExit();
|
|
14969
|
+
}, [doExit]);
|
|
14970
|
+
return /* @__PURE__ */ jsxDEV9(Box7, {
|
|
14971
|
+
flexDirection: "column",
|
|
14972
|
+
children: [
|
|
14973
|
+
/* @__PURE__ */ jsxDEV9(AppMemo, {
|
|
14974
|
+
history,
|
|
14975
|
+
status,
|
|
14976
|
+
model,
|
|
14977
|
+
workdir
|
|
14978
|
+
}, undefined, false, undefined, this),
|
|
14979
|
+
status !== "idle" ? /* @__PURE__ */ jsxDEV9(StreamingOverlay, {
|
|
14980
|
+
streamingText: stream.streamingText,
|
|
14981
|
+
status,
|
|
14982
|
+
markdownEnabled: markdownEnabled2,
|
|
14983
|
+
width
|
|
14984
|
+
}, undefined, false, undefined, this) : null,
|
|
14985
|
+
status === "idle" ? /* @__PURE__ */ jsxDEV9(Box7, {
|
|
14986
|
+
marginTop: 1,
|
|
14987
|
+
children: /* @__PURE__ */ jsxDEV9(TextInput, {
|
|
14988
|
+
label: "You",
|
|
14989
|
+
prefix: "\uD83D\uDC64",
|
|
14990
|
+
placeholder: 'Type a message, "/help", or "exit"',
|
|
14991
|
+
onSubmit: handleSubmit,
|
|
14992
|
+
onCancel: handleCancel,
|
|
14993
|
+
history: userHistory
|
|
14994
|
+
}, undefined, false, undefined, this)
|
|
14995
|
+
}, undefined, false, undefined, this) : null,
|
|
14996
|
+
errorMessage ? /* @__PURE__ */ jsxDEV9(Box7, {
|
|
14997
|
+
marginTop: 1,
|
|
14998
|
+
children: /* @__PURE__ */ jsxDEV9(Text9, {
|
|
14999
|
+
color: "red",
|
|
15000
|
+
children: [
|
|
15001
|
+
"⚠ ",
|
|
15002
|
+
errorMessage
|
|
15003
|
+
]
|
|
15004
|
+
}, undefined, true, undefined, this)
|
|
15005
|
+
}, undefined, false, undefined, this) : null
|
|
15006
|
+
]
|
|
15007
|
+
}, undefined, true, undefined, this);
|
|
15008
|
+
};
|
|
15009
|
+
var RunTui_default = RunScreen;
|
|
15282
15010
|
|
|
15283
|
-
// src/commands/run
|
|
15011
|
+
// src/commands/run.ts
|
|
15012
|
+
init_markdown();
|
|
15013
|
+
|
|
15014
|
+
// src/commands/run-shutdown.ts
|
|
15284
15015
|
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
15285
15016
|
async function shutdownRunSteps(deps) {
|
|
15286
|
-
const {
|
|
15017
|
+
const {
|
|
15018
|
+
lspManagerDispose,
|
|
15019
|
+
pluginAdapterDispose,
|
|
15020
|
+
stopEventHandler,
|
|
15021
|
+
stopTaskEventHandler,
|
|
15022
|
+
queryExecutor,
|
|
15023
|
+
env,
|
|
15024
|
+
envService,
|
|
15025
|
+
shouldDisposeEnvService,
|
|
15026
|
+
output,
|
|
15027
|
+
logger: logger6
|
|
15028
|
+
} = deps;
|
|
15287
15029
|
try {
|
|
15288
15030
|
stopEventHandler();
|
|
15289
15031
|
} catch (err) {
|
|
15290
|
-
|
|
15032
|
+
logger6?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
15291
15033
|
}
|
|
15292
15034
|
try {
|
|
15293
15035
|
stopTaskEventHandler();
|
|
15294
15036
|
} catch (err) {
|
|
15295
|
-
|
|
15037
|
+
logger6?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
15296
15038
|
}
|
|
15297
15039
|
if (lspManagerDispose) {
|
|
15298
15040
|
try {
|
|
15299
15041
|
await lspManagerDispose();
|
|
15300
15042
|
} catch (err) {
|
|
15301
|
-
|
|
15043
|
+
logger6?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
15302
15044
|
}
|
|
15303
15045
|
}
|
|
15304
15046
|
if (pluginAdapterDispose) {
|
|
15305
15047
|
try {
|
|
15306
15048
|
await pluginAdapterDispose();
|
|
15307
15049
|
} catch (err) {
|
|
15308
|
-
|
|
15050
|
+
logger6?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
15309
15051
|
}
|
|
15310
15052
|
}
|
|
15311
15053
|
try {
|
|
15312
15054
|
queryExecutor.dispose();
|
|
15313
15055
|
} catch (err) {
|
|
15314
|
-
|
|
15056
|
+
logger6?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
15315
15057
|
}
|
|
15316
15058
|
try {
|
|
15317
15059
|
const eventSourceComponent = env.getComponent("event-source");
|
|
@@ -15320,7 +15062,7 @@ async function shutdownRunSteps(deps) {
|
|
|
15320
15062
|
if (sources && sources.length > 0) {
|
|
15321
15063
|
for (const source of sources) {
|
|
15322
15064
|
const status = eventSourceComponent.getStatus?.(source.id);
|
|
15323
|
-
|
|
15065
|
+
logger6?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
15324
15066
|
if (status !== "stopped" && status !== "created") {
|
|
15325
15067
|
try {
|
|
15326
15068
|
await eventSourceComponent.stopSource(source.id);
|
|
@@ -15333,25 +15075,29 @@ async function shutdownRunSteps(deps) {
|
|
|
15333
15075
|
}
|
|
15334
15076
|
}
|
|
15335
15077
|
} catch (err) {
|
|
15336
|
-
|
|
15078
|
+
logger6?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
15337
15079
|
}
|
|
15338
15080
|
if (shouldDisposeEnvService) {
|
|
15339
15081
|
try {
|
|
15340
15082
|
await envService.dispose();
|
|
15341
15083
|
} catch (err) {
|
|
15342
|
-
|
|
15084
|
+
logger6?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
15343
15085
|
}
|
|
15344
15086
|
}
|
|
15345
15087
|
try {
|
|
15346
15088
|
await TempFileManager3.getInstance().cleanupAll();
|
|
15347
|
-
|
|
15089
|
+
logger6?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
15348
15090
|
} catch (err) {
|
|
15349
|
-
|
|
15091
|
+
logger6?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
15350
15092
|
}
|
|
15351
15093
|
}
|
|
15352
15094
|
|
|
15353
15095
|
// src/commands/run.ts
|
|
15354
|
-
|
|
15096
|
+
import {
|
|
15097
|
+
wrapFunction as wrapFunction7,
|
|
15098
|
+
getTracerProvider as getTracerProvider4
|
|
15099
|
+
} from "@ai-setting/roy-agent-core";
|
|
15100
|
+
async function loadHandleQueryImpl(options, hooks) {
|
|
15355
15101
|
const quiet = CliQuietModeService.getInstance().isQuiet();
|
|
15356
15102
|
const output = new OutputService2;
|
|
15357
15103
|
output.configure({ quiet });
|
|
@@ -15372,14 +15118,14 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15372
15118
|
if (!sessionComponent) {
|
|
15373
15119
|
throw new Error("Failed to create session component");
|
|
15374
15120
|
}
|
|
15375
|
-
const sessionManager = new
|
|
15121
|
+
const sessionManager = new SessionManager({
|
|
15376
15122
|
sessionComponent,
|
|
15377
15123
|
output,
|
|
15378
15124
|
quiet: true
|
|
15379
15125
|
});
|
|
15380
15126
|
const sessionResult = await sessionManager.init(options.session, options.continue);
|
|
15381
15127
|
const sessionId = sessionResult.sessionId;
|
|
15382
|
-
const queryExecutor = new
|
|
15128
|
+
const queryExecutor = new QueryExecutor({
|
|
15383
15129
|
env,
|
|
15384
15130
|
sessionComponent,
|
|
15385
15131
|
output,
|
|
@@ -15389,13 +15135,13 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15389
15135
|
let agentContext = undefined;
|
|
15390
15136
|
if (options.agent && options.agent !== "default") {
|
|
15391
15137
|
const agentComponent = env.getComponent("agent");
|
|
15392
|
-
const validation =
|
|
15138
|
+
const validation = validateActAgent(agentComponent, options.agent);
|
|
15393
15139
|
if (!validation.valid) {
|
|
15394
15140
|
output.error(validation.message);
|
|
15395
15141
|
output.info("提示: roy-agent agents list");
|
|
15396
15142
|
process.exit(1);
|
|
15397
15143
|
}
|
|
15398
|
-
agentContext =
|
|
15144
|
+
agentContext = buildActAgentContext(options.agent);
|
|
15399
15145
|
}
|
|
15400
15146
|
let eventSourceSystemPrompt;
|
|
15401
15147
|
const rawEventSourceIds = options.eventSource;
|
|
@@ -15407,16 +15153,16 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15407
15153
|
output.info("请确保 EventSourceComponent 已正确注册");
|
|
15408
15154
|
process.exit(1);
|
|
15409
15155
|
}
|
|
15410
|
-
const summary = await
|
|
15411
|
-
const preloadedPrompts =
|
|
15412
|
-
eventSourceSystemPrompt = preloadedPrompts.length > 0 ?
|
|
15156
|
+
const summary = await startEventSources(eventSourceIds, eventSourceComponent, output);
|
|
15157
|
+
const preloadedPrompts = collectEventSourceSystemPrompts(eventSourceIds, eventSourceComponent);
|
|
15158
|
+
eventSourceSystemPrompt = preloadedPrompts.length > 0 ? joinResolvedSystemPrompts(preloadedPrompts) : undefined;
|
|
15413
15159
|
if (eventSourceIds.length === 1 && summary.failedCount > 0) {
|
|
15414
15160
|
process.exit(1);
|
|
15415
15161
|
}
|
|
15416
15162
|
}
|
|
15417
15163
|
const llmComponent = envService.getLLM();
|
|
15418
15164
|
queryExecutor.initStreamOutput(llmComponent ?? null);
|
|
15419
|
-
const
|
|
15165
|
+
const handleQueryImpl = async (message) => {
|
|
15420
15166
|
const mergedContext = {
|
|
15421
15167
|
...agentContext,
|
|
15422
15168
|
model: options.model,
|
|
@@ -15433,14 +15179,22 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15433
15179
|
}, undefined, mergedContext);
|
|
15434
15180
|
return String(result ?? "");
|
|
15435
15181
|
};
|
|
15436
|
-
const
|
|
15182
|
+
const handleQuery = wrapFunction7(handleQueryImpl, "cli.run.handleQuery", {
|
|
15183
|
+
recordParams: true,
|
|
15184
|
+
recordResult: false,
|
|
15185
|
+
log: true,
|
|
15186
|
+
paramFilter: (args) => ({
|
|
15187
|
+
"message.length": typeof args[0] === "string" ? args[0].length : 0
|
|
15188
|
+
})
|
|
15189
|
+
});
|
|
15190
|
+
const taskEventHandler = new TaskEventHandler({
|
|
15437
15191
|
env,
|
|
15438
15192
|
enabled: true
|
|
15439
15193
|
});
|
|
15440
|
-
const eventHandler = new
|
|
15194
|
+
const eventHandler = new EventHandler({
|
|
15441
15195
|
env,
|
|
15442
15196
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
15443
|
-
formatter: new
|
|
15197
|
+
formatter: new EventMessageFormatter({ prefix: "[通知]" }),
|
|
15444
15198
|
isIdle: hooks?.isIdle ?? (() => true),
|
|
15445
15199
|
sessionComponent,
|
|
15446
15200
|
onEvent: async (_message) => {},
|
|
@@ -15464,17 +15218,80 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15464
15218
|
sessionManager
|
|
15465
15219
|
};
|
|
15466
15220
|
}
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15221
|
+
var loadHandleQuery = wrapFunction7(loadHandleQueryImpl, "cli.run.loadHandleQuery", {
|
|
15222
|
+
recordParams: true,
|
|
15223
|
+
recordResult: false,
|
|
15224
|
+
log: true,
|
|
15225
|
+
paramFilter: (args) => {
|
|
15226
|
+
const opts = args[0] ?? {};
|
|
15227
|
+
return {
|
|
15228
|
+
"options.model": opts.model ?? "",
|
|
15229
|
+
"options.workdir": opts.workdir ?? "",
|
|
15230
|
+
"options.session": opts.session ?? "",
|
|
15231
|
+
"options.eventSource": Array.isArray(opts.eventSource) ? opts.eventSource.join(",") : opts.eventSource ?? "",
|
|
15232
|
+
"has.onNotification": !!args[1]?.onNotification
|
|
15233
|
+
};
|
|
15234
|
+
}
|
|
15235
|
+
});
|
|
15236
|
+
function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext, eventSourceSystemPrompt, onTraceId) {
|
|
15237
|
+
const innerStreamHandler = async (message, onChunk) => {
|
|
15238
|
+
const onChunkInstrumented = wrapFunction7((chunk) => {
|
|
15239
|
+
onChunk(chunk);
|
|
15240
|
+
}, "cli.run.chunkCallbackImpl.onChunk-called", {
|
|
15241
|
+
recordParams: true,
|
|
15242
|
+
recordResult: false,
|
|
15243
|
+
log: false,
|
|
15244
|
+
paramFilter: (args) => ({
|
|
15245
|
+
"chunk.length": typeof args[0] === "string" ? args[0].length : 0,
|
|
15246
|
+
"chunk.head": typeof args[0] === "string" ? args[0].slice(0, 32) : ""
|
|
15247
|
+
})
|
|
15248
|
+
});
|
|
15249
|
+
const chunkCallbackImpl = (event) => {
|
|
15470
15250
|
if (event.type === "llm.text") {
|
|
15471
15251
|
if (event.delta) {
|
|
15472
|
-
|
|
15252
|
+
onChunkInstrumented(event.delta);
|
|
15473
15253
|
} else if (event.content) {
|
|
15474
|
-
|
|
15254
|
+
onChunkInstrumented(event.content);
|
|
15475
15255
|
}
|
|
15256
|
+
return;
|
|
15476
15257
|
}
|
|
15477
|
-
|
|
15258
|
+
if (event.type === "tool.call") {
|
|
15259
|
+
const toolName = event.toolName || "unknown";
|
|
15260
|
+
const toolId = event.toolId || "";
|
|
15261
|
+
onChunkInstrumented(`
|
|
15262
|
+
\uD83D\uDD27 tool: ${toolName} (${toolId})
|
|
15263
|
+
`);
|
|
15264
|
+
return;
|
|
15265
|
+
}
|
|
15266
|
+
if (event.type === "tool.result") {
|
|
15267
|
+
onChunkInstrumented(`
|
|
15268
|
+
✓ done
|
|
15269
|
+
`);
|
|
15270
|
+
return;
|
|
15271
|
+
}
|
|
15272
|
+
if (event.type === "tool.error") {
|
|
15273
|
+
const msg = event.toolError || "error";
|
|
15274
|
+
onChunkInstrumented(`
|
|
15275
|
+
✗ ${msg}
|
|
15276
|
+
`);
|
|
15277
|
+
return;
|
|
15278
|
+
}
|
|
15279
|
+
};
|
|
15280
|
+
queryExecutor.setChunkCallback(wrapFunction7(chunkCallbackImpl, "cli.run.chunkCallback", {
|
|
15281
|
+
recordParams: true,
|
|
15282
|
+
recordResult: false,
|
|
15283
|
+
log: true,
|
|
15284
|
+
paramFilter: (args) => {
|
|
15285
|
+
const e = args[0] ?? {};
|
|
15286
|
+
return {
|
|
15287
|
+
"event.type": e.type ?? "unknown",
|
|
15288
|
+
"event.delta.length": typeof e.delta === "string" ? e.delta.length : 0,
|
|
15289
|
+
"event.content.length": typeof e.content === "string" ? e.content.length : 0,
|
|
15290
|
+
"event.toolName": e.toolName ?? "",
|
|
15291
|
+
"event.toolId": e.toolId ?? ""
|
|
15292
|
+
};
|
|
15293
|
+
}
|
|
15294
|
+
}));
|
|
15478
15295
|
const mergedContext = {
|
|
15479
15296
|
...agentContext,
|
|
15480
15297
|
model: options.model,
|
|
@@ -15484,13 +15301,37 @@ function createStreamHandleQuery(queryExecutor, sessionId, options, agentContext
|
|
|
15484
15301
|
defaultAgentName: options.defaultAgentName
|
|
15485
15302
|
}
|
|
15486
15303
|
};
|
|
15487
|
-
const
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15304
|
+
const turnSpan = getTracerProvider4().getTracer("roy-tracer").startSpan("cli.run.turn");
|
|
15305
|
+
const turnTraceId = turnSpan.spanContext.traceId;
|
|
15306
|
+
let result;
|
|
15307
|
+
try {
|
|
15308
|
+
result = await queryExecutor.execute(message, sessionId, {
|
|
15309
|
+
showReasoning: options.reasoning ?? true,
|
|
15310
|
+
showToolCalls: options.toolCalls ?? true,
|
|
15311
|
+
showToolResults: options.toolResults ?? false
|
|
15312
|
+
}, undefined, mergedContext);
|
|
15313
|
+
turnSpan.end(result);
|
|
15314
|
+
} catch (error) {
|
|
15315
|
+
turnSpan.setAttribute("error", String(error));
|
|
15316
|
+
turnSpan.end(undefined, error instanceof Error ? error : new Error(String(error)));
|
|
15317
|
+
throw error;
|
|
15318
|
+
} finally {
|
|
15319
|
+
try {
|
|
15320
|
+
onTraceId?.(turnTraceId);
|
|
15321
|
+
} catch (cbErr) {
|
|
15322
|
+
console.warn(`[Trace] sink failed: ${cbErr instanceof Error ? cbErr.message : String(cbErr)}`);
|
|
15323
|
+
}
|
|
15324
|
+
}
|
|
15492
15325
|
return String(result ?? "");
|
|
15493
15326
|
};
|
|
15327
|
+
return wrapFunction7(innerStreamHandler, "cli.run.createStreamHandleQuery", {
|
|
15328
|
+
recordParams: true,
|
|
15329
|
+
recordResult: false,
|
|
15330
|
+
log: true,
|
|
15331
|
+
paramFilter: (args) => ({
|
|
15332
|
+
"message.length": typeof args[0] === "string" ? args[0].length : 0
|
|
15333
|
+
})
|
|
15334
|
+
});
|
|
15494
15335
|
}
|
|
15495
15336
|
function createRunCommand() {
|
|
15496
15337
|
return {
|
|
@@ -15563,6 +15404,10 @@ function createRunCommand() {
|
|
|
15563
15404
|
type: "string",
|
|
15564
15405
|
describe: "Default agent 名字(默认 Roy,可被覆盖)",
|
|
15565
15406
|
default: "Roy"
|
|
15407
|
+
}).option("debug-on", {
|
|
15408
|
+
type: "boolean",
|
|
15409
|
+
describe: "调试模式:每次 turn 结束后输出 [Trace] <traceId>(stderr),便于追踪调用 trace",
|
|
15410
|
+
default: false
|
|
15566
15411
|
}),
|
|
15567
15412
|
handler: async (argv) => {
|
|
15568
15413
|
if (argv.markdown === false) {
|
|
@@ -15590,7 +15435,7 @@ function createRunCommand() {
|
|
|
15590
15435
|
isIdle: () => runState.isIdle(),
|
|
15591
15436
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
15592
15437
|
});
|
|
15593
|
-
const shutdownHandle =
|
|
15438
|
+
const shutdownHandle = registerShutdownHandlers(async () => {
|
|
15594
15439
|
await shutdownRunSteps({
|
|
15595
15440
|
lspManagerDispose: null,
|
|
15596
15441
|
pluginAdapterDispose: null,
|
|
@@ -15604,10 +15449,17 @@ function createRunCommand() {
|
|
|
15604
15449
|
logger: undefined
|
|
15605
15450
|
});
|
|
15606
15451
|
});
|
|
15607
|
-
const
|
|
15452
|
+
const debugOn = argv.debugOn ?? false;
|
|
15453
|
+
let appendTraceIdTui;
|
|
15454
|
+
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt, (traceId) => {
|
|
15455
|
+
printTraceIdAfterResponse(traceId, {
|
|
15456
|
+
enabled: debugOn,
|
|
15457
|
+
tuiSink: appendTraceIdTui
|
|
15458
|
+
});
|
|
15459
|
+
});
|
|
15608
15460
|
const stopEventHandler = eventHandler.start();
|
|
15609
15461
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
15610
|
-
const { waitUntilExit } = render(
|
|
15462
|
+
const { waitUntilExit } = render(React8.createElement(RunTui_default, {
|
|
15611
15463
|
handleQuery,
|
|
15612
15464
|
streamHandleQuery,
|
|
15613
15465
|
model: argv.model,
|
|
@@ -15617,6 +15469,7 @@ function createRunCommand() {
|
|
|
15617
15469
|
onRegisterHandlers: (handlers) => {
|
|
15618
15470
|
runState.onNotification = handlers.onNotification;
|
|
15619
15471
|
runState.isIdle = handlers.isIdle;
|
|
15472
|
+
appendTraceIdTui = handlers.appendTraceId;
|
|
15620
15473
|
},
|
|
15621
15474
|
onExit: () => {}
|
|
15622
15475
|
}), { exitOnCtrlC: true });
|
|
@@ -15644,23 +15497,31 @@ function createRunCommand() {
|
|
|
15644
15497
|
var RunCommand = createRunCommand();
|
|
15645
15498
|
|
|
15646
15499
|
// src/commands/chat.ts
|
|
15647
|
-
import
|
|
15500
|
+
import React10 from "react";
|
|
15648
15501
|
import { render as render2 } from "ink";
|
|
15649
15502
|
|
|
15650
|
-
// src/ChatTui.
|
|
15651
|
-
import
|
|
15652
|
-
import { Box as
|
|
15503
|
+
// src/ChatTui.tsx
|
|
15504
|
+
import { useEffect as useEffect8, useRef as useRef6, useState as useState7 } from "react";
|
|
15505
|
+
import { Box as Box8, useApp as useApp3 } from "ink";
|
|
15653
15506
|
init_markdown();
|
|
15654
|
-
import { jsxDEV as
|
|
15655
|
-
var ChatScreen = ({
|
|
15507
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
15508
|
+
var ChatScreen = ({
|
|
15509
|
+
handleQuery,
|
|
15510
|
+
streamHandleQuery,
|
|
15511
|
+
message,
|
|
15512
|
+
model,
|
|
15513
|
+
workdir,
|
|
15514
|
+
maxLines,
|
|
15515
|
+
markdownEnabled: markdownEnabled2
|
|
15516
|
+
}) => {
|
|
15656
15517
|
const [history, setHistory] = useState7([
|
|
15657
15518
|
{ role: "user", content: message, id: "h-init-1" }
|
|
15658
15519
|
]);
|
|
15659
|
-
const historyIdRef =
|
|
15520
|
+
const historyIdRef = useRef6(1);
|
|
15660
15521
|
const stream = useStreamingAccumulator();
|
|
15661
15522
|
const { exit } = useApp3();
|
|
15662
15523
|
const width = process.stdout.columns ?? 80;
|
|
15663
|
-
|
|
15524
|
+
useEffect8(() => {
|
|
15664
15525
|
let cancelled = false;
|
|
15665
15526
|
stream.start();
|
|
15666
15527
|
(async () => {
|
|
@@ -15699,16 +15560,23 @@ var ChatScreen = ({ handleQuery, streamHandleQuery, message, model, workdir, max
|
|
|
15699
15560
|
cancelled = true;
|
|
15700
15561
|
};
|
|
15701
15562
|
}, [handleQuery, streamHandleQuery, message, maxLines, markdownEnabled2, exit, width, stream]);
|
|
15702
|
-
return /* @__PURE__ */
|
|
15563
|
+
return /* @__PURE__ */ jsxDEV10(Box8, {
|
|
15703
15564
|
flexDirection: "column",
|
|
15704
|
-
children:
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
|
|
15708
|
-
|
|
15709
|
-
|
|
15710
|
-
|
|
15711
|
-
|
|
15565
|
+
children: [
|
|
15566
|
+
/* @__PURE__ */ jsxDEV10(AppMemo, {
|
|
15567
|
+
history,
|
|
15568
|
+
status: stream.status,
|
|
15569
|
+
model,
|
|
15570
|
+
workdir
|
|
15571
|
+
}, undefined, false, undefined, this),
|
|
15572
|
+
stream.status !== "idle" ? /* @__PURE__ */ jsxDEV10(StreamingOverlay, {
|
|
15573
|
+
streamingText: stream.streamingText,
|
|
15574
|
+
status: stream.status,
|
|
15575
|
+
markdownEnabled: markdownEnabled2,
|
|
15576
|
+
width
|
|
15577
|
+
}, undefined, false, undefined, this) : null
|
|
15578
|
+
]
|
|
15579
|
+
}, undefined, true, undefined, this);
|
|
15712
15580
|
};
|
|
15713
15581
|
var ChatTui_default = ChatScreen;
|
|
15714
15582
|
|
|
@@ -15787,7 +15655,7 @@ function createChatCommand() {
|
|
|
15787
15655
|
}
|
|
15788
15656
|
const maxLines = Number.parseInt(argv.maxLines ?? "500", 10);
|
|
15789
15657
|
const handleQuery = await loadHandleQuery2(argv);
|
|
15790
|
-
const { waitUntilExit } = render2(
|
|
15658
|
+
const { waitUntilExit } = render2(React10.createElement(ChatTui_default, {
|
|
15791
15659
|
handleQuery,
|
|
15792
15660
|
message: argv.message,
|
|
15793
15661
|
model: argv.model,
|
|
@@ -25158,9 +25026,9 @@ import chalk73 from "chalk";
|
|
|
25158
25026
|
import fs5 from "fs";
|
|
25159
25027
|
import path8 from "path";
|
|
25160
25028
|
import { createRunWorkflowTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
|
|
25161
|
-
import { getTracerProvider as
|
|
25029
|
+
import { getTracerProvider as getTracerProvider5, propagation, wrapFunction as wrapFunction8 } from "@ai-setting/roy-agent-core";
|
|
25162
25030
|
import { isValidSessionId } from "@ai-setting/roy-agent-core/env/session";
|
|
25163
|
-
var runWorkflow =
|
|
25031
|
+
var runWorkflow = wrapFunction8(async function runWorkflowImpl(args) {
|
|
25164
25032
|
const output = new OutputService2;
|
|
25165
25033
|
const envService = new EnvironmentService(output);
|
|
25166
25034
|
const traceparent = process.env.TRACEPARENT;
|
|
@@ -25180,7 +25048,7 @@ var runWorkflow = wrapFunction(async function runWorkflowImpl(args) {
|
|
|
25180
25048
|
output.info(`[OTel Trace] TRACEPARENT=${traceparent || "none"}, traceId=${traceId}, parentSpanId=${parentSpanId}`);
|
|
25181
25049
|
let workflowSpan = undefined;
|
|
25182
25050
|
try {
|
|
25183
|
-
const provider =
|
|
25051
|
+
const provider = getTracerProvider5();
|
|
25184
25052
|
await provider.initialize();
|
|
25185
25053
|
const tracer = provider.getTracer("roy-tracer");
|
|
25186
25054
|
const restoredContext = tracer.getCurrentContext();
|
|
@@ -25437,8 +25305,8 @@ var WorkflowRunCommand = {
|
|
|
25437
25305
|
// src/commands/workflow/commands/stop.ts
|
|
25438
25306
|
import chalk74 from "chalk";
|
|
25439
25307
|
import { createWorkflowRunStopTool } from "@ai-setting/roy-agent-core/env/workflow/tools";
|
|
25440
|
-
import { wrapFunction as
|
|
25441
|
-
var stopWorkflow =
|
|
25308
|
+
import { wrapFunction as wrapFunction9 } from "@ai-setting/roy-agent-core";
|
|
25309
|
+
var stopWorkflow = wrapFunction9(async function stopWorkflowImpl(args) {
|
|
25442
25310
|
const output = new OutputService2;
|
|
25443
25311
|
const envService = new EnvironmentService(output);
|
|
25444
25312
|
try {
|
|
@@ -26093,7 +25961,7 @@ Error: ${error.message}`));
|
|
|
26093
25961
|
|
|
26094
25962
|
// src/commands/workflow/commands/search.ts
|
|
26095
25963
|
import chalk78 from "chalk";
|
|
26096
|
-
import { wrapFunction as
|
|
25964
|
+
import { wrapFunction as wrapFunction10 } from "@ai-setting/roy-agent-core";
|
|
26097
25965
|
var WorkflowSearchCommand = {
|
|
26098
25966
|
command: "search",
|
|
26099
25967
|
describe: "Search workflows by keyword and/or tags (multiple tags use AND filter). v2: returns available_tags.",
|
|
@@ -26268,14 +26136,14 @@ var _runWorkflowSearchImpl = async function(opts) {
|
|
|
26268
26136
|
}
|
|
26269
26137
|
}
|
|
26270
26138
|
};
|
|
26271
|
-
var runWorkflowSearch =
|
|
26139
|
+
var runWorkflowSearch = wrapFunction10(_runWorkflowSearchImpl, "workflow.cli.search", {
|
|
26272
26140
|
recordParams: true,
|
|
26273
26141
|
recordResult: false,
|
|
26274
26142
|
log: false
|
|
26275
26143
|
});
|
|
26276
26144
|
|
|
26277
26145
|
// src/commands/workflow/commands/tag.ts
|
|
26278
|
-
import { wrapFunction as
|
|
26146
|
+
import { wrapFunction as wrapFunction11 } from "@ai-setting/roy-agent-core";
|
|
26279
26147
|
import chalk79 from "chalk";
|
|
26280
26148
|
var WorkflowTagListCommand = {
|
|
26281
26149
|
command: "list",
|
|
@@ -26475,12 +26343,12 @@ function formatDate2(iso) {
|
|
|
26475
26343
|
return iso;
|
|
26476
26344
|
}
|
|
26477
26345
|
}
|
|
26478
|
-
var runWorkflowTagList =
|
|
26346
|
+
var runWorkflowTagList = wrapFunction11(_runWorkflowTagListImpl, "workflow.cli.tag.list", {
|
|
26479
26347
|
recordParams: true,
|
|
26480
26348
|
recordResult: false,
|
|
26481
26349
|
log: false
|
|
26482
26350
|
});
|
|
26483
|
-
var runWorkflowTagGet =
|
|
26351
|
+
var runWorkflowTagGet = wrapFunction11(_runWorkflowTagGetImpl, "workflow.cli.tag.get", {
|
|
26484
26352
|
recordParams: true,
|
|
26485
26353
|
recordResult: false,
|
|
26486
26354
|
log: false
|
|
@@ -26748,7 +26616,7 @@ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync
|
|
|
26748
26616
|
import { join as join6, resolve } from "node:path";
|
|
26749
26617
|
import { homedir as homedir4 } from "node:os";
|
|
26750
26618
|
|
|
26751
|
-
// src/commands/install/cleanup-stale-plugin-copies.
|
|
26619
|
+
// src/commands/install/cleanup-stale-plugin-copies.ts
|
|
26752
26620
|
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, cpSync } from "node:fs";
|
|
26753
26621
|
import { join as join5 } from "node:path";
|
|
26754
26622
|
import { homedir as nodeHomedir, tmpdir as nodeTmpdir } from "node:os";
|