@ai-setting/roy-agent-cli 1.7.20 → 1.7.30
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 +140 -1145
- package/dist/index.js +140 -1145
- package/dist/roy-agent-linux-x64/bin/roy-agent +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1087,7 +1087,7 @@ var init_slash_command_popup = __esm(() => {
|
|
|
1087
1087
|
});
|
|
1088
1088
|
});
|
|
1089
1089
|
|
|
1090
|
-
// src/render/markdown.
|
|
1090
|
+
// src/render/markdown.ts
|
|
1091
1091
|
import { Marked } from "marked";
|
|
1092
1092
|
import { highlight } from "cli-highlight";
|
|
1093
1093
|
function setMarkdownEnabled(enabled) {
|
|
@@ -1496,8 +1496,7 @@ var init_markdown = __esm(() => {
|
|
|
1496
1496
|
ANSI_CSI_RE = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
1497
1497
|
});
|
|
1498
1498
|
|
|
1499
|
-
// src/tui/Markdown.
|
|
1500
|
-
import React2 from "react";
|
|
1499
|
+
// src/tui/Markdown.tsx
|
|
1501
1500
|
import { Text as Text2 } from "ink";
|
|
1502
1501
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
1503
1502
|
var Markdown = ({ text, width }) => {
|
|
@@ -1514,7 +1513,7 @@ var init_Markdown = __esm(() => {
|
|
|
1514
1513
|
init_markdown();
|
|
1515
1514
|
});
|
|
1516
1515
|
|
|
1517
|
-
// src/tui/theme.
|
|
1516
|
+
// src/tui/theme.ts
|
|
1518
1517
|
function shouldSuppressColors(env) {
|
|
1519
1518
|
if (env.NO_COLOR && env.NO_COLOR !== "0" && env.NO_COLOR !== "false") {
|
|
1520
1519
|
return true;
|
|
@@ -1558,11 +1557,14 @@ var init_theme = __esm(() => {
|
|
|
1558
1557
|
};
|
|
1559
1558
|
});
|
|
1560
1559
|
|
|
1561
|
-
// src/tui/StatusBar.
|
|
1562
|
-
import React3 from "react";
|
|
1560
|
+
// src/tui/StatusBar.tsx
|
|
1563
1561
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
1564
1562
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
1565
|
-
var StatusBar = ({
|
|
1563
|
+
var StatusBar = ({
|
|
1564
|
+
model,
|
|
1565
|
+
workdir,
|
|
1566
|
+
tokenCount
|
|
1567
|
+
}) => {
|
|
1566
1568
|
const theme = getTheme();
|
|
1567
1569
|
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
1568
1570
|
borderStyle: "single",
|
|
@@ -1673,7 +1675,7 @@ __export(exports_repl_ink, {
|
|
|
1673
1675
|
REPLInk: () => REPLInk,
|
|
1674
1676
|
MultilineInput: () => MultilineInput
|
|
1675
1677
|
});
|
|
1676
|
-
import * as
|
|
1678
|
+
import * as React2 from "react";
|
|
1677
1679
|
import { Box as Box3, Text as Text4, Static, useApp, useInput as useInput2 } from "ink";
|
|
1678
1680
|
import { createLogger as createLogger5 } from "@ai-setting/roy-agent-core";
|
|
1679
1681
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
@@ -1698,7 +1700,7 @@ function REPLInk(props) {
|
|
|
1698
1700
|
onEscape
|
|
1699
1701
|
} = props;
|
|
1700
1702
|
const { exit: appExit } = useApp();
|
|
1701
|
-
const [messages, setMessages] =
|
|
1703
|
+
const [messages, setMessages] = React2.useState(() => [
|
|
1702
1704
|
withMessageId({
|
|
1703
1705
|
role: "system",
|
|
1704
1706
|
kind: "welcome",
|
|
@@ -1706,47 +1708,47 @@ function REPLInk(props) {
|
|
|
1706
1708
|
}),
|
|
1707
1709
|
...initialMessages.map(withMessageId)
|
|
1708
1710
|
]);
|
|
1709
|
-
const [mode, setMode] =
|
|
1710
|
-
const [statusBarCtx, setStatusBarCtxState] =
|
|
1711
|
+
const [mode, setMode] = React2.useState(initialMode);
|
|
1712
|
+
const [statusBarCtx, setStatusBarCtxState] = React2.useState({
|
|
1711
1713
|
mode: initialMode,
|
|
1712
1714
|
cwd: initialStatusBarCtx.cwd ?? initialContext.cwd,
|
|
1713
1715
|
gitBranch: initialStatusBarCtx.gitBranch,
|
|
1714
1716
|
model: initialStatusBarCtx.model ?? initialContext.model
|
|
1715
1717
|
});
|
|
1716
|
-
const [inputValue, setInputValue] =
|
|
1717
|
-
const [popupIndex, setPopupIndex] =
|
|
1718
|
-
const filteredCmds =
|
|
1718
|
+
const [inputValue, setInputValue] = React2.useState("");
|
|
1719
|
+
const [popupIndex, setPopupIndex] = React2.useState(0);
|
|
1720
|
+
const filteredCmds = React2.useMemo(() => {
|
|
1719
1721
|
if (!/^\/\S*$/.test(inputValue))
|
|
1720
1722
|
return [];
|
|
1721
1723
|
return filterCommands(inputValue);
|
|
1722
1724
|
}, [inputValue]);
|
|
1723
1725
|
const showPopup = filteredCmds.length > 0;
|
|
1724
|
-
|
|
1726
|
+
React2.useEffect(() => {
|
|
1725
1727
|
setPopupIndex(0);
|
|
1726
1728
|
}, [filteredCmds]);
|
|
1727
1729
|
const safePopupIndex = clampSelectedIndex(popupIndex, filteredCmds.length);
|
|
1728
|
-
const handlePopupSelect =
|
|
1730
|
+
const handlePopupSelect = React2.useCallback((cmd) => {
|
|
1729
1731
|
multilineInputRef.current?.setBuffer(cmd.cmd + " ");
|
|
1730
1732
|
setInputValue(cmd.cmd + " ");
|
|
1731
1733
|
}, []);
|
|
1732
|
-
const handlePopupClose =
|
|
1734
|
+
const handlePopupClose = React2.useCallback(() => {
|
|
1733
1735
|
const current = multilineInputRef.current?.getBuffer() ?? "";
|
|
1734
1736
|
const stripped = current.replace(/^\/+/, "");
|
|
1735
1737
|
multilineInputRef.current?.setBuffer(stripped);
|
|
1736
1738
|
setInputValue(stripped);
|
|
1737
1739
|
}, []);
|
|
1738
|
-
const handlePopupIndexChange =
|
|
1740
|
+
const handlePopupIndexChange = React2.useCallback((idx) => {
|
|
1739
1741
|
setPopupIndex(idx);
|
|
1740
1742
|
}, []);
|
|
1741
|
-
const streamingIndexRef =
|
|
1742
|
-
const lastFlushTsRef =
|
|
1743
|
+
const streamingIndexRef = React2.useRef(-1);
|
|
1744
|
+
const lastFlushTsRef = React2.useRef(0);
|
|
1743
1745
|
const STALE_STREAM_THRESHOLD_MS = 1000;
|
|
1744
|
-
const multilineInputRef =
|
|
1745
|
-
const lastEscapeTsRef =
|
|
1746
|
-
const pendingDeltaRef =
|
|
1747
|
-
const throttleTimerRef =
|
|
1748
|
-
const isFirstDeltaInStreamRef =
|
|
1749
|
-
const flushStreamingDelta =
|
|
1746
|
+
const multilineInputRef = React2.useRef(null);
|
|
1747
|
+
const lastEscapeTsRef = React2.useRef(0);
|
|
1748
|
+
const pendingDeltaRef = React2.useRef("");
|
|
1749
|
+
const throttleTimerRef = React2.useRef(null);
|
|
1750
|
+
const isFirstDeltaInStreamRef = React2.useRef(true);
|
|
1751
|
+
const flushStreamingDelta = React2.useCallback(() => {
|
|
1750
1752
|
const delta = pendingDeltaRef.current;
|
|
1751
1753
|
pendingDeltaRef.current = "";
|
|
1752
1754
|
throttleTimerRef.current = null;
|
|
@@ -1775,7 +1777,7 @@ function REPLInk(props) {
|
|
|
1775
1777
|
});
|
|
1776
1778
|
lastFlushTsRef.current = Date.now();
|
|
1777
1779
|
}, []);
|
|
1778
|
-
|
|
1780
|
+
React2.useEffect(() => {
|
|
1779
1781
|
return () => {
|
|
1780
1782
|
if (throttleTimerRef.current !== null) {
|
|
1781
1783
|
clearTimeout(throttleTimerRef.current);
|
|
@@ -1783,8 +1785,8 @@ function REPLInk(props) {
|
|
|
1783
1785
|
}
|
|
1784
1786
|
};
|
|
1785
1787
|
}, []);
|
|
1786
|
-
const apiRef =
|
|
1787
|
-
|
|
1788
|
+
const apiRef = React2.useRef(null);
|
|
1789
|
+
React2.useEffect(() => {
|
|
1788
1790
|
const api = {
|
|
1789
1791
|
appendMessage: (msg) => {
|
|
1790
1792
|
setMessages((msgs) => [...msgs, withMessageId(msg)]);
|
|
@@ -1860,7 +1862,7 @@ function REPLInk(props) {
|
|
|
1860
1862
|
apiRef.current = api;
|
|
1861
1863
|
onReady?.(api);
|
|
1862
1864
|
}, [appExit, onCommand, onReady]);
|
|
1863
|
-
const handleEscapeCascade =
|
|
1865
|
+
const handleEscapeCascade = React2.useCallback(() => {
|
|
1864
1866
|
const now = Date.now();
|
|
1865
1867
|
if (now - lastEscapeTsRef.current < 100) {
|
|
1866
1868
|
return;
|
|
@@ -1904,7 +1906,7 @@ function REPLInk(props) {
|
|
|
1904
1906
|
}
|
|
1905
1907
|
}
|
|
1906
1908
|
});
|
|
1907
|
-
const handleSubmit =
|
|
1909
|
+
const handleSubmit = React2.useCallback(async (value) => {
|
|
1908
1910
|
if (!value || value.trim() === "") {
|
|
1909
1911
|
return;
|
|
1910
1912
|
}
|
|
@@ -1933,7 +1935,7 @@ function REPLInk(props) {
|
|
|
1933
1935
|
]);
|
|
1934
1936
|
}
|
|
1935
1937
|
}, [onCommand, onSubmit]);
|
|
1936
|
-
const staticItems =
|
|
1938
|
+
const staticItems = React2.useMemo(() => {
|
|
1937
1939
|
if (messages.length <= 1)
|
|
1938
1940
|
return [];
|
|
1939
1941
|
return messages.slice(0, -1);
|
|
@@ -1941,8 +1943,8 @@ function REPLInk(props) {
|
|
|
1941
1943
|
const tailMsg = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
1942
1944
|
const terminalWidth = process.stdout.columns ?? 80;
|
|
1943
1945
|
const terminalHeight = process.stdout.rows ?? 24;
|
|
1944
|
-
const dynamicTailBounds =
|
|
1945
|
-
const staticTailBounds =
|
|
1946
|
+
const dynamicTailBounds = React2.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
1947
|
+
const staticTailBounds = React2.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
1946
1948
|
const tailKey = messages.length > 0 ? tailMsg?.id ?? `tail-${messages.length - 1}` : "tail-empty";
|
|
1947
1949
|
const statusBarModel = shortModel(statusBarCtx.model);
|
|
1948
1950
|
const statusBarWorkdir = statusBarCtx.cwd;
|
|
@@ -2009,7 +2011,7 @@ function shortModel(model) {
|
|
|
2009
2011
|
}
|
|
2010
2012
|
async function renderInkREPL(props) {
|
|
2011
2013
|
const ink = await import("ink");
|
|
2012
|
-
const { waitUntilExit } = ink.render(
|
|
2014
|
+
const { waitUntilExit } = ink.render(React2.createElement(REPLInk, props));
|
|
2013
2015
|
await waitUntilExit();
|
|
2014
2016
|
}
|
|
2015
2017
|
var MarkdownBounded, inkLogger, _msgIdCounter = 0, MultilineInput, MessageView;
|
|
@@ -2021,7 +2023,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2021
2023
|
init_Markdown();
|
|
2022
2024
|
init_StatusBar();
|
|
2023
2025
|
init_dynamic_tail();
|
|
2024
|
-
MarkdownBounded =
|
|
2026
|
+
MarkdownBounded = React2.memo(({ text, bounds, width }) => {
|
|
2025
2027
|
const out = renderBoundedAssistant(text, bounds, width);
|
|
2026
2028
|
if (!out) {
|
|
2027
2029
|
return null;
|
|
@@ -2031,16 +2033,16 @@ var init_repl_ink = __esm(() => {
|
|
|
2031
2033
|
}, undefined, false, undefined, this);
|
|
2032
2034
|
});
|
|
2033
2035
|
inkLogger = createLogger5("repl-ink");
|
|
2034
|
-
MultilineInput =
|
|
2036
|
+
MultilineInput = React2.memo(React2.forwardRef(function MultilineInput2(props, ref) {
|
|
2035
2037
|
const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
|
|
2036
|
-
const [buffer, setBuffer] =
|
|
2037
|
-
const [cursor, setCursor] =
|
|
2038
|
-
|
|
2038
|
+
const [buffer, setBuffer] = React2.useState("");
|
|
2039
|
+
const [cursor, setCursor] = React2.useState(0);
|
|
2040
|
+
React2.useEffect(() => {
|
|
2039
2041
|
if (popupActive || buffer.startsWith("/")) {
|
|
2040
2042
|
onChange?.(buffer);
|
|
2041
2043
|
}
|
|
2042
2044
|
}, [buffer, onChange, popupActive]);
|
|
2043
|
-
|
|
2045
|
+
React2.useImperativeHandle(ref, () => ({
|
|
2044
2046
|
clearBuffer: () => {
|
|
2045
2047
|
setBuffer("");
|
|
2046
2048
|
setCursor(0);
|
|
@@ -2278,7 +2280,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2278
2280
|
})
|
|
2279
2281
|
}, undefined, false, undefined, this);
|
|
2280
2282
|
}));
|
|
2281
|
-
MessageView =
|
|
2283
|
+
MessageView = React2.memo(function MessageView2({
|
|
2282
2284
|
msg,
|
|
2283
2285
|
terminalWidth,
|
|
2284
2286
|
tailBounds
|
|
@@ -9458,7 +9460,7 @@ class CliQuietModeService {
|
|
|
9458
9460
|
// package.json
|
|
9459
9461
|
var package_default = {
|
|
9460
9462
|
name: "@ai-setting/roy-agent-cli",
|
|
9461
|
-
version: "1.7.
|
|
9463
|
+
version: "1.7.30",
|
|
9462
9464
|
type: "module",
|
|
9463
9465
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9464
9466
|
main: "./dist/index.js",
|
|
@@ -13639,25 +13641,27 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13639
13641
|
var InteractiveCommand = createInteractiveCommand();
|
|
13640
13642
|
|
|
13641
13643
|
// src/commands/run.ts
|
|
13642
|
-
import
|
|
13644
|
+
import React6 from "react";
|
|
13643
13645
|
import { render } from "ink";
|
|
13644
13646
|
|
|
13645
|
-
// src/RunTui.
|
|
13646
|
-
import
|
|
13647
|
+
// src/RunTui.tsx
|
|
13648
|
+
import { useState as useState6, useCallback as useCallback4, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
13647
13649
|
import { Box as Box6, Text as Text8, useApp as useApp2 } from "ink";
|
|
13648
13650
|
|
|
13649
|
-
// src/tui/App.
|
|
13651
|
+
// src/tui/App.tsx
|
|
13650
13652
|
init_Markdown();
|
|
13651
|
-
import React6 from "react";
|
|
13652
13653
|
import { Box as Box4, Static as Static2, Text as Text6 } from "ink";
|
|
13653
13654
|
|
|
13654
|
-
// src/tui/Spinner.
|
|
13655
|
+
// src/tui/Spinner.tsx
|
|
13655
13656
|
init_theme();
|
|
13656
|
-
import
|
|
13657
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
13657
13658
|
import { Text as Text5 } from "ink";
|
|
13658
13659
|
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
13659
13660
|
var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
13660
|
-
var Spinner = ({
|
|
13661
|
+
var Spinner = ({
|
|
13662
|
+
label,
|
|
13663
|
+
intervalMs = 80
|
|
13664
|
+
}) => {
|
|
13661
13665
|
const [frame, setFrame] = useState3(0);
|
|
13662
13666
|
const theme = getTheme();
|
|
13663
13667
|
useEffect3(() => {
|
|
@@ -13681,7 +13685,7 @@ var Spinner = ({ label, intervalMs = 80 }) => {
|
|
|
13681
13685
|
}, undefined, true, undefined, this);
|
|
13682
13686
|
};
|
|
13683
13687
|
|
|
13684
|
-
// src/tui/App.
|
|
13688
|
+
// src/tui/App.tsx
|
|
13685
13689
|
init_StatusBar();
|
|
13686
13690
|
init_theme();
|
|
13687
13691
|
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
@@ -13752,7 +13756,14 @@ var HistoryEntry = ({ item }) => {
|
|
|
13752
13756
|
]
|
|
13753
13757
|
}, undefined, true, undefined, this);
|
|
13754
13758
|
};
|
|
13755
|
-
var App = ({
|
|
13759
|
+
var App = ({
|
|
13760
|
+
history,
|
|
13761
|
+
status,
|
|
13762
|
+
model,
|
|
13763
|
+
workdir,
|
|
13764
|
+
streamingText,
|
|
13765
|
+
tokenCount
|
|
13766
|
+
}) => {
|
|
13756
13767
|
const theme = getTheme();
|
|
13757
13768
|
return /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13758
13769
|
flexDirection: "column",
|
|
@@ -13819,15 +13830,22 @@ var App = ({ history, status, model, workdir, streamingText, tokenCount }) => {
|
|
|
13819
13830
|
}, undefined, true, undefined, this);
|
|
13820
13831
|
};
|
|
13821
13832
|
|
|
13822
|
-
// src/tui/index.
|
|
13833
|
+
// src/tui/index.ts
|
|
13823
13834
|
init_Markdown();
|
|
13824
13835
|
init_StatusBar();
|
|
13825
13836
|
|
|
13826
|
-
// src/tui/TextInput.
|
|
13827
|
-
import
|
|
13837
|
+
// src/tui/TextInput.tsx
|
|
13838
|
+
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
13828
13839
|
import { Box as Box5, Text as Text7, useInput as useInput3 } from "ink";
|
|
13829
13840
|
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
13830
|
-
var TextInput = ({
|
|
13841
|
+
var TextInput = ({
|
|
13842
|
+
label,
|
|
13843
|
+
prefix,
|
|
13844
|
+
onSubmit,
|
|
13845
|
+
onCancel,
|
|
13846
|
+
placeholder,
|
|
13847
|
+
history = []
|
|
13848
|
+
}) => {
|
|
13831
13849
|
const [value, setValue] = useState4("");
|
|
13832
13850
|
const [historyIndex, setHistoryIndex] = useState4(-1);
|
|
13833
13851
|
const [draft, setDraft] = useState4("");
|
|
@@ -13917,12 +13935,11 @@ var TextInput = ({ label, prefix, onSubmit, onCancel, placeholder, history = []
|
|
|
13917
13935
|
}, undefined, true, undefined, this);
|
|
13918
13936
|
};
|
|
13919
13937
|
|
|
13920
|
-
// src/tui/index.
|
|
13938
|
+
// src/tui/index.ts
|
|
13921
13939
|
init_theme();
|
|
13940
|
+
init_welcome_card2();
|
|
13922
13941
|
|
|
13923
|
-
// src/tui/
|
|
13924
|
-
init_welcome_card();
|
|
13925
|
-
// src/tui/use-streaming-accumulator.js
|
|
13942
|
+
// src/tui/use-streaming-accumulator.ts
|
|
13926
13943
|
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
13927
13944
|
function useStreamingAccumulator() {
|
|
13928
13945
|
const [status, setStatus] = useState5("idle");
|
|
@@ -13956,10 +13973,10 @@ function useStreamingAccumulator() {
|
|
|
13956
13973
|
return { status, streamingText, start, append, finish, fail };
|
|
13957
13974
|
}
|
|
13958
13975
|
|
|
13959
|
-
// src/RunTui.
|
|
13976
|
+
// src/RunTui.tsx
|
|
13960
13977
|
init_markdown();
|
|
13961
13978
|
|
|
13962
|
-
// src/slash.
|
|
13979
|
+
// src/slash.ts
|
|
13963
13980
|
var CLEAR_SENTINEL = "__CLEAR__";
|
|
13964
13981
|
function dispatchSlashCommand(raw, ctx) {
|
|
13965
13982
|
const text = raw.trim();
|
|
@@ -14031,9 +14048,18 @@ function dispatchSlashCommand(raw, ctx) {
|
|
|
14031
14048
|
}
|
|
14032
14049
|
}
|
|
14033
14050
|
|
|
14034
|
-
// src/RunTui.
|
|
14051
|
+
// src/RunTui.tsx
|
|
14035
14052
|
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
14036
|
-
var RunScreen = ({
|
|
14053
|
+
var RunScreen = ({
|
|
14054
|
+
handleQuery,
|
|
14055
|
+
streamHandleQuery,
|
|
14056
|
+
model,
|
|
14057
|
+
workdir,
|
|
14058
|
+
maxLines: initialMaxLines,
|
|
14059
|
+
markdownEnabled: markdownEnabled2,
|
|
14060
|
+
onExit,
|
|
14061
|
+
onRegisterHandlers
|
|
14062
|
+
}) => {
|
|
14037
14063
|
const [history, setHistory] = useState6([]);
|
|
14038
14064
|
const [errorMessage, setErrorMessage] = useState6(null);
|
|
14039
14065
|
const [maxLines, setMaxLines] = useState6(initialMaxLines);
|
|
@@ -14229,1088 +14255,49 @@ var RunTui_default = RunScreen;
|
|
|
14229
14255
|
// src/commands/run.ts
|
|
14230
14256
|
init_markdown();
|
|
14231
14257
|
|
|
14232
|
-
// src/commands/
|
|
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
|
|
15225
|
-
};
|
|
15226
|
-
}
|
|
15227
|
-
}
|
|
15228
|
-
function extractTriggerSessionId2(event) {
|
|
15229
|
-
const triggerSessionId = event?.metadata?.trigger_session_id;
|
|
15230
|
-
if (typeof triggerSessionId === "string" && triggerSessionId.length > 0) {
|
|
15231
|
-
return triggerSessionId;
|
|
15232
|
-
}
|
|
15233
|
-
return;
|
|
15234
|
-
}
|
|
15235
|
-
|
|
15236
|
-
// src/commands/lifecycle.js
|
|
15237
|
-
var DEFAULT_LOGGER2 = {
|
|
15238
|
-
warn: (msg) => console.error(`[shutdown] ${msg}`)
|
|
15239
|
-
};
|
|
15240
|
-
function registerShutdownHandlers2(cleanup, options = {}) {
|
|
15241
|
-
const logger7 = options.logger ?? DEFAULT_LOGGER2;
|
|
15242
|
-
const exitCode = options.exitCode ?? 0;
|
|
15243
|
-
const shutdownMessage = options.shutdownMessage ?? "Cleaning up...";
|
|
15244
|
-
let shuttingDown = false;
|
|
15245
|
-
const shutdown = async (signal) => {
|
|
15246
|
-
if (shuttingDown) {
|
|
15247
|
-
return;
|
|
15248
|
-
}
|
|
15249
|
-
shuttingDown = true;
|
|
15250
|
-
try {
|
|
15251
|
-
logger7.debug?.(`[${signal}] ${shutdownMessage}`);
|
|
15252
|
-
} catch {}
|
|
15253
|
-
if (cleanup) {
|
|
15254
|
-
try {
|
|
15255
|
-
await cleanup();
|
|
15256
|
-
} catch (err) {
|
|
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
|
-
}
|
|
15266
|
-
}
|
|
15267
|
-
}
|
|
15268
|
-
try {
|
|
15269
|
-
process.exit(exitCode);
|
|
15270
|
-
} catch {}
|
|
15271
|
-
};
|
|
15272
|
-
process.on("SIGINT", shutdown);
|
|
15273
|
-
process.on("SIGTERM", shutdown);
|
|
15274
|
-
return {
|
|
15275
|
-
dispose: () => {
|
|
15276
|
-
process.removeListener("SIGINT", shutdown);
|
|
15277
|
-
process.removeListener("SIGTERM", shutdown);
|
|
15278
|
-
}
|
|
15279
|
-
};
|
|
15280
|
-
}
|
|
15281
|
-
|
|
15282
|
-
// src/commands/run-shutdown.js
|
|
14258
|
+
// src/commands/run-shutdown.ts
|
|
15283
14259
|
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
15284
14260
|
async function shutdownRunSteps(deps) {
|
|
15285
|
-
const {
|
|
14261
|
+
const {
|
|
14262
|
+
lspManagerDispose,
|
|
14263
|
+
pluginAdapterDispose,
|
|
14264
|
+
stopEventHandler,
|
|
14265
|
+
stopTaskEventHandler,
|
|
14266
|
+
queryExecutor,
|
|
14267
|
+
env,
|
|
14268
|
+
envService,
|
|
14269
|
+
shouldDisposeEnvService,
|
|
14270
|
+
output,
|
|
14271
|
+
logger: logger6
|
|
14272
|
+
} = deps;
|
|
15286
14273
|
try {
|
|
15287
14274
|
stopEventHandler();
|
|
15288
14275
|
} catch (err) {
|
|
15289
|
-
|
|
14276
|
+
logger6?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
15290
14277
|
}
|
|
15291
14278
|
try {
|
|
15292
14279
|
stopTaskEventHandler();
|
|
15293
14280
|
} catch (err) {
|
|
15294
|
-
|
|
14281
|
+
logger6?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
15295
14282
|
}
|
|
15296
14283
|
if (lspManagerDispose) {
|
|
15297
14284
|
try {
|
|
15298
14285
|
await lspManagerDispose();
|
|
15299
14286
|
} catch (err) {
|
|
15300
|
-
|
|
14287
|
+
logger6?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
15301
14288
|
}
|
|
15302
14289
|
}
|
|
15303
14290
|
if (pluginAdapterDispose) {
|
|
15304
14291
|
try {
|
|
15305
14292
|
await pluginAdapterDispose();
|
|
15306
14293
|
} catch (err) {
|
|
15307
|
-
|
|
14294
|
+
logger6?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
15308
14295
|
}
|
|
15309
14296
|
}
|
|
15310
14297
|
try {
|
|
15311
14298
|
queryExecutor.dispose();
|
|
15312
14299
|
} catch (err) {
|
|
15313
|
-
|
|
14300
|
+
logger6?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
15314
14301
|
}
|
|
15315
14302
|
try {
|
|
15316
14303
|
const eventSourceComponent = env.getComponent("event-source");
|
|
@@ -15319,7 +14306,7 @@ async function shutdownRunSteps(deps) {
|
|
|
15319
14306
|
if (sources && sources.length > 0) {
|
|
15320
14307
|
for (const source of sources) {
|
|
15321
14308
|
const status = eventSourceComponent.getStatus?.(source.id);
|
|
15322
|
-
|
|
14309
|
+
logger6?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
15323
14310
|
if (status !== "stopped" && status !== "created") {
|
|
15324
14311
|
try {
|
|
15325
14312
|
await eventSourceComponent.stopSource(source.id);
|
|
@@ -15332,20 +14319,20 @@ async function shutdownRunSteps(deps) {
|
|
|
15332
14319
|
}
|
|
15333
14320
|
}
|
|
15334
14321
|
} catch (err) {
|
|
15335
|
-
|
|
14322
|
+
logger6?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
15336
14323
|
}
|
|
15337
14324
|
if (shouldDisposeEnvService) {
|
|
15338
14325
|
try {
|
|
15339
14326
|
await envService.dispose();
|
|
15340
14327
|
} catch (err) {
|
|
15341
|
-
|
|
14328
|
+
logger6?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
15342
14329
|
}
|
|
15343
14330
|
}
|
|
15344
14331
|
try {
|
|
15345
14332
|
await TempFileManager3.getInstance().cleanupAll();
|
|
15346
|
-
|
|
14333
|
+
logger6?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
15347
14334
|
} catch (err) {
|
|
15348
|
-
|
|
14335
|
+
logger6?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
15349
14336
|
}
|
|
15350
14337
|
}
|
|
15351
14338
|
|
|
@@ -15371,14 +14358,14 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15371
14358
|
if (!sessionComponent) {
|
|
15372
14359
|
throw new Error("Failed to create session component");
|
|
15373
14360
|
}
|
|
15374
|
-
const sessionManager = new
|
|
14361
|
+
const sessionManager = new SessionManager({
|
|
15375
14362
|
sessionComponent,
|
|
15376
14363
|
output,
|
|
15377
14364
|
quiet: true
|
|
15378
14365
|
});
|
|
15379
14366
|
const sessionResult = await sessionManager.init(options.session, options.continue);
|
|
15380
14367
|
const sessionId = sessionResult.sessionId;
|
|
15381
|
-
const queryExecutor = new
|
|
14368
|
+
const queryExecutor = new QueryExecutor({
|
|
15382
14369
|
env,
|
|
15383
14370
|
sessionComponent,
|
|
15384
14371
|
output,
|
|
@@ -15388,13 +14375,13 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15388
14375
|
let agentContext = undefined;
|
|
15389
14376
|
if (options.agent && options.agent !== "default") {
|
|
15390
14377
|
const agentComponent = env.getComponent("agent");
|
|
15391
|
-
const validation =
|
|
14378
|
+
const validation = validateActAgent(agentComponent, options.agent);
|
|
15392
14379
|
if (!validation.valid) {
|
|
15393
14380
|
output.error(validation.message);
|
|
15394
14381
|
output.info("提示: roy-agent agents list");
|
|
15395
14382
|
process.exit(1);
|
|
15396
14383
|
}
|
|
15397
|
-
agentContext =
|
|
14384
|
+
agentContext = buildActAgentContext(options.agent);
|
|
15398
14385
|
}
|
|
15399
14386
|
let eventSourceSystemPrompt;
|
|
15400
14387
|
const rawEventSourceIds = options.eventSource;
|
|
@@ -15406,9 +14393,9 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15406
14393
|
output.info("请确保 EventSourceComponent 已正确注册");
|
|
15407
14394
|
process.exit(1);
|
|
15408
14395
|
}
|
|
15409
|
-
const summary = await
|
|
15410
|
-
const preloadedPrompts =
|
|
15411
|
-
eventSourceSystemPrompt = preloadedPrompts.length > 0 ?
|
|
14396
|
+
const summary = await startEventSources(eventSourceIds, eventSourceComponent, output);
|
|
14397
|
+
const preloadedPrompts = collectEventSourceSystemPrompts(eventSourceIds, eventSourceComponent);
|
|
14398
|
+
eventSourceSystemPrompt = preloadedPrompts.length > 0 ? joinResolvedSystemPrompts(preloadedPrompts) : undefined;
|
|
15412
14399
|
if (eventSourceIds.length === 1 && summary.failedCount > 0) {
|
|
15413
14400
|
process.exit(1);
|
|
15414
14401
|
}
|
|
@@ -15432,14 +14419,14 @@ async function loadHandleQuery(options, hooks) {
|
|
|
15432
14419
|
}, undefined, mergedContext);
|
|
15433
14420
|
return String(result ?? "");
|
|
15434
14421
|
};
|
|
15435
|
-
const taskEventHandler = new
|
|
14422
|
+
const taskEventHandler = new TaskEventHandler({
|
|
15436
14423
|
env,
|
|
15437
14424
|
enabled: true
|
|
15438
14425
|
});
|
|
15439
|
-
const eventHandler = new
|
|
14426
|
+
const eventHandler = new EventHandler({
|
|
15440
14427
|
env,
|
|
15441
14428
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
15442
|
-
formatter: new
|
|
14429
|
+
formatter: new EventMessageFormatter({ prefix: "[通知]" }),
|
|
15443
14430
|
isIdle: hooks?.isIdle ?? (() => true),
|
|
15444
14431
|
sessionComponent,
|
|
15445
14432
|
onEvent: async (_message) => {},
|
|
@@ -15589,7 +14576,7 @@ function createRunCommand() {
|
|
|
15589
14576
|
isIdle: () => runState.isIdle(),
|
|
15590
14577
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
15591
14578
|
});
|
|
15592
|
-
const shutdownHandle =
|
|
14579
|
+
const shutdownHandle = registerShutdownHandlers(async () => {
|
|
15593
14580
|
await shutdownRunSteps({
|
|
15594
14581
|
lspManagerDispose: null,
|
|
15595
14582
|
pluginAdapterDispose: null,
|
|
@@ -15606,7 +14593,7 @@ function createRunCommand() {
|
|
|
15606
14593
|
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt);
|
|
15607
14594
|
const stopEventHandler = eventHandler.start();
|
|
15608
14595
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
15609
|
-
const { waitUntilExit } = render(
|
|
14596
|
+
const { waitUntilExit } = render(React6.createElement(RunTui_default, {
|
|
15610
14597
|
handleQuery,
|
|
15611
14598
|
streamHandleQuery,
|
|
15612
14599
|
model: argv.model,
|
|
@@ -15643,15 +14630,23 @@ function createRunCommand() {
|
|
|
15643
14630
|
var RunCommand = createRunCommand();
|
|
15644
14631
|
|
|
15645
14632
|
// src/commands/chat.ts
|
|
15646
|
-
import
|
|
14633
|
+
import React8 from "react";
|
|
15647
14634
|
import { render as render2 } from "ink";
|
|
15648
14635
|
|
|
15649
|
-
// src/ChatTui.
|
|
15650
|
-
import
|
|
14636
|
+
// src/ChatTui.tsx
|
|
14637
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
15651
14638
|
import { Box as Box7, useApp as useApp3 } from "ink";
|
|
15652
14639
|
init_markdown();
|
|
15653
14640
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
15654
|
-
var ChatScreen = ({
|
|
14641
|
+
var ChatScreen = ({
|
|
14642
|
+
handleQuery,
|
|
14643
|
+
streamHandleQuery,
|
|
14644
|
+
message,
|
|
14645
|
+
model,
|
|
14646
|
+
workdir,
|
|
14647
|
+
maxLines,
|
|
14648
|
+
markdownEnabled: markdownEnabled2
|
|
14649
|
+
}) => {
|
|
15655
14650
|
const [history, setHistory] = useState7([
|
|
15656
14651
|
{ role: "user", content: message, id: "h-init-1" }
|
|
15657
14652
|
]);
|
|
@@ -15786,7 +14781,7 @@ function createChatCommand() {
|
|
|
15786
14781
|
}
|
|
15787
14782
|
const maxLines = Number.parseInt(argv.maxLines ?? "500", 10);
|
|
15788
14783
|
const handleQuery = await loadHandleQuery2(argv);
|
|
15789
|
-
const { waitUntilExit } = render2(
|
|
14784
|
+
const { waitUntilExit } = render2(React8.createElement(ChatTui_default, {
|
|
15790
14785
|
handleQuery,
|
|
15791
14786
|
message: argv.message,
|
|
15792
14787
|
model: argv.model,
|
|
@@ -26747,7 +25742,7 @@ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync
|
|
|
26747
25742
|
import { join as join6, resolve } from "node:path";
|
|
26748
25743
|
import { homedir as homedir4 } from "node:os";
|
|
26749
25744
|
|
|
26750
|
-
// src/commands/install/cleanup-stale-plugin-copies.
|
|
25745
|
+
// src/commands/install/cleanup-stale-plugin-copies.ts
|
|
26751
25746
|
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, cpSync } from "node:fs";
|
|
26752
25747
|
import { join as join5 } from "node:path";
|
|
26753
25748
|
import { homedir as nodeHomedir, tmpdir as nodeTmpdir } from "node:os";
|