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