@ai-setting/roy-agent-cli 1.7.19 → 1.7.20
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 +1148 -143
- package/dist/index.js +1148 -143
- package/dist/roy-agent-linux-x64/bin/roy-agent +0 -0
- package/package.json +1 -1
package/dist/bin/roy-agent.js
CHANGED
|
@@ -1088,7 +1088,7 @@ var init_slash_command_popup = __esm(() => {
|
|
|
1088
1088
|
});
|
|
1089
1089
|
});
|
|
1090
1090
|
|
|
1091
|
-
// src/render/markdown.
|
|
1091
|
+
// src/render/markdown.js
|
|
1092
1092
|
import { Marked } from "marked";
|
|
1093
1093
|
import { highlight } from "cli-highlight";
|
|
1094
1094
|
function setMarkdownEnabled(enabled) {
|
|
@@ -1497,7 +1497,8 @@ var init_markdown = __esm(() => {
|
|
|
1497
1497
|
ANSI_CSI_RE = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
1498
1498
|
});
|
|
1499
1499
|
|
|
1500
|
-
// src/tui/Markdown.
|
|
1500
|
+
// src/tui/Markdown.js
|
|
1501
|
+
import React2 from "react";
|
|
1501
1502
|
import { Text as Text2 } from "ink";
|
|
1502
1503
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
1503
1504
|
var Markdown = ({ text, width }) => {
|
|
@@ -1514,7 +1515,7 @@ var init_Markdown = __esm(() => {
|
|
|
1514
1515
|
init_markdown();
|
|
1515
1516
|
});
|
|
1516
1517
|
|
|
1517
|
-
// src/tui/theme.
|
|
1518
|
+
// src/tui/theme.js
|
|
1518
1519
|
function shouldSuppressColors(env) {
|
|
1519
1520
|
if (env.NO_COLOR && env.NO_COLOR !== "0" && env.NO_COLOR !== "false") {
|
|
1520
1521
|
return true;
|
|
@@ -1558,14 +1559,11 @@ var init_theme = __esm(() => {
|
|
|
1558
1559
|
};
|
|
1559
1560
|
});
|
|
1560
1561
|
|
|
1561
|
-
// src/tui/StatusBar.
|
|
1562
|
+
// src/tui/StatusBar.js
|
|
1563
|
+
import React3 from "react";
|
|
1562
1564
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
1563
1565
|
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
1564
|
-
var StatusBar = ({
|
|
1565
|
-
model,
|
|
1566
|
-
workdir,
|
|
1567
|
-
tokenCount
|
|
1568
|
-
}) => {
|
|
1566
|
+
var StatusBar = ({ model, workdir, tokenCount }) => {
|
|
1569
1567
|
const theme = getTheme();
|
|
1570
1568
|
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
1571
1569
|
borderStyle: "single",
|
|
@@ -1676,7 +1674,7 @@ __export(exports_repl_ink, {
|
|
|
1676
1674
|
REPLInk: () => REPLInk,
|
|
1677
1675
|
MultilineInput: () => MultilineInput
|
|
1678
1676
|
});
|
|
1679
|
-
import * as
|
|
1677
|
+
import * as React4 from "react";
|
|
1680
1678
|
import { Box as Box3, Text as Text4, Static, useApp, useInput as useInput2 } from "ink";
|
|
1681
1679
|
import { createLogger as createLogger5 } from "@ai-setting/roy-agent-core";
|
|
1682
1680
|
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
@@ -1701,7 +1699,7 @@ function REPLInk(props) {
|
|
|
1701
1699
|
onEscape
|
|
1702
1700
|
} = props;
|
|
1703
1701
|
const { exit: appExit } = useApp();
|
|
1704
|
-
const [messages, setMessages] =
|
|
1702
|
+
const [messages, setMessages] = React4.useState(() => [
|
|
1705
1703
|
withMessageId({
|
|
1706
1704
|
role: "system",
|
|
1707
1705
|
kind: "welcome",
|
|
@@ -1709,47 +1707,47 @@ function REPLInk(props) {
|
|
|
1709
1707
|
}),
|
|
1710
1708
|
...initialMessages.map(withMessageId)
|
|
1711
1709
|
]);
|
|
1712
|
-
const [mode, setMode] =
|
|
1713
|
-
const [statusBarCtx, setStatusBarCtxState] =
|
|
1710
|
+
const [mode, setMode] = React4.useState(initialMode);
|
|
1711
|
+
const [statusBarCtx, setStatusBarCtxState] = React4.useState({
|
|
1714
1712
|
mode: initialMode,
|
|
1715
1713
|
cwd: initialStatusBarCtx.cwd ?? initialContext.cwd,
|
|
1716
1714
|
gitBranch: initialStatusBarCtx.gitBranch,
|
|
1717
1715
|
model: initialStatusBarCtx.model ?? initialContext.model
|
|
1718
1716
|
});
|
|
1719
|
-
const [inputValue, setInputValue] =
|
|
1720
|
-
const [popupIndex, setPopupIndex] =
|
|
1721
|
-
const filteredCmds =
|
|
1717
|
+
const [inputValue, setInputValue] = React4.useState("");
|
|
1718
|
+
const [popupIndex, setPopupIndex] = React4.useState(0);
|
|
1719
|
+
const filteredCmds = React4.useMemo(() => {
|
|
1722
1720
|
if (!/^\/\S*$/.test(inputValue))
|
|
1723
1721
|
return [];
|
|
1724
1722
|
return filterCommands(inputValue);
|
|
1725
1723
|
}, [inputValue]);
|
|
1726
1724
|
const showPopup = filteredCmds.length > 0;
|
|
1727
|
-
|
|
1725
|
+
React4.useEffect(() => {
|
|
1728
1726
|
setPopupIndex(0);
|
|
1729
1727
|
}, [filteredCmds]);
|
|
1730
1728
|
const safePopupIndex = clampSelectedIndex(popupIndex, filteredCmds.length);
|
|
1731
|
-
const handlePopupSelect =
|
|
1729
|
+
const handlePopupSelect = React4.useCallback((cmd) => {
|
|
1732
1730
|
multilineInputRef.current?.setBuffer(cmd.cmd + " ");
|
|
1733
1731
|
setInputValue(cmd.cmd + " ");
|
|
1734
1732
|
}, []);
|
|
1735
|
-
const handlePopupClose =
|
|
1733
|
+
const handlePopupClose = React4.useCallback(() => {
|
|
1736
1734
|
const current = multilineInputRef.current?.getBuffer() ?? "";
|
|
1737
1735
|
const stripped = current.replace(/^\/+/, "");
|
|
1738
1736
|
multilineInputRef.current?.setBuffer(stripped);
|
|
1739
1737
|
setInputValue(stripped);
|
|
1740
1738
|
}, []);
|
|
1741
|
-
const handlePopupIndexChange =
|
|
1739
|
+
const handlePopupIndexChange = React4.useCallback((idx) => {
|
|
1742
1740
|
setPopupIndex(idx);
|
|
1743
1741
|
}, []);
|
|
1744
|
-
const streamingIndexRef =
|
|
1745
|
-
const lastFlushTsRef =
|
|
1742
|
+
const streamingIndexRef = React4.useRef(-1);
|
|
1743
|
+
const lastFlushTsRef = React4.useRef(0);
|
|
1746
1744
|
const STALE_STREAM_THRESHOLD_MS = 1000;
|
|
1747
|
-
const multilineInputRef =
|
|
1748
|
-
const lastEscapeTsRef =
|
|
1749
|
-
const pendingDeltaRef =
|
|
1750
|
-
const throttleTimerRef =
|
|
1751
|
-
const isFirstDeltaInStreamRef =
|
|
1752
|
-
const flushStreamingDelta =
|
|
1745
|
+
const multilineInputRef = React4.useRef(null);
|
|
1746
|
+
const lastEscapeTsRef = React4.useRef(0);
|
|
1747
|
+
const pendingDeltaRef = React4.useRef("");
|
|
1748
|
+
const throttleTimerRef = React4.useRef(null);
|
|
1749
|
+
const isFirstDeltaInStreamRef = React4.useRef(true);
|
|
1750
|
+
const flushStreamingDelta = React4.useCallback(() => {
|
|
1753
1751
|
const delta = pendingDeltaRef.current;
|
|
1754
1752
|
pendingDeltaRef.current = "";
|
|
1755
1753
|
throttleTimerRef.current = null;
|
|
@@ -1778,7 +1776,7 @@ function REPLInk(props) {
|
|
|
1778
1776
|
});
|
|
1779
1777
|
lastFlushTsRef.current = Date.now();
|
|
1780
1778
|
}, []);
|
|
1781
|
-
|
|
1779
|
+
React4.useEffect(() => {
|
|
1782
1780
|
return () => {
|
|
1783
1781
|
if (throttleTimerRef.current !== null) {
|
|
1784
1782
|
clearTimeout(throttleTimerRef.current);
|
|
@@ -1786,8 +1784,8 @@ function REPLInk(props) {
|
|
|
1786
1784
|
}
|
|
1787
1785
|
};
|
|
1788
1786
|
}, []);
|
|
1789
|
-
const apiRef =
|
|
1790
|
-
|
|
1787
|
+
const apiRef = React4.useRef(null);
|
|
1788
|
+
React4.useEffect(() => {
|
|
1791
1789
|
const api = {
|
|
1792
1790
|
appendMessage: (msg) => {
|
|
1793
1791
|
setMessages((msgs) => [...msgs, withMessageId(msg)]);
|
|
@@ -1863,7 +1861,7 @@ function REPLInk(props) {
|
|
|
1863
1861
|
apiRef.current = api;
|
|
1864
1862
|
onReady?.(api);
|
|
1865
1863
|
}, [appExit, onCommand, onReady]);
|
|
1866
|
-
const handleEscapeCascade =
|
|
1864
|
+
const handleEscapeCascade = React4.useCallback(() => {
|
|
1867
1865
|
const now = Date.now();
|
|
1868
1866
|
if (now - lastEscapeTsRef.current < 100) {
|
|
1869
1867
|
return;
|
|
@@ -1907,7 +1905,7 @@ function REPLInk(props) {
|
|
|
1907
1905
|
}
|
|
1908
1906
|
}
|
|
1909
1907
|
});
|
|
1910
|
-
const handleSubmit =
|
|
1908
|
+
const handleSubmit = React4.useCallback(async (value) => {
|
|
1911
1909
|
if (!value || value.trim() === "") {
|
|
1912
1910
|
return;
|
|
1913
1911
|
}
|
|
@@ -1936,7 +1934,7 @@ function REPLInk(props) {
|
|
|
1936
1934
|
]);
|
|
1937
1935
|
}
|
|
1938
1936
|
}, [onCommand, onSubmit]);
|
|
1939
|
-
const staticItems =
|
|
1937
|
+
const staticItems = React4.useMemo(() => {
|
|
1940
1938
|
if (messages.length <= 1)
|
|
1941
1939
|
return [];
|
|
1942
1940
|
return messages.slice(0, -1);
|
|
@@ -1944,8 +1942,8 @@ function REPLInk(props) {
|
|
|
1944
1942
|
const tailMsg = messages.length > 0 ? messages[messages.length - 1] : null;
|
|
1945
1943
|
const terminalWidth = process.stdout.columns ?? 80;
|
|
1946
1944
|
const terminalHeight = process.stdout.rows ?? 24;
|
|
1947
|
-
const dynamicTailBounds =
|
|
1948
|
-
const staticTailBounds =
|
|
1945
|
+
const dynamicTailBounds = React4.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
1946
|
+
const staticTailBounds = React4.useMemo(() => computeDynamicTailBounds(terminalHeight, 12, showPopup), [terminalHeight, showPopup]);
|
|
1949
1947
|
const tailKey = messages.length > 0 ? tailMsg?.id ?? `tail-${messages.length - 1}` : "tail-empty";
|
|
1950
1948
|
const statusBarModel = shortModel(statusBarCtx.model);
|
|
1951
1949
|
const statusBarWorkdir = statusBarCtx.cwd;
|
|
@@ -2012,7 +2010,7 @@ function shortModel(model) {
|
|
|
2012
2010
|
}
|
|
2013
2011
|
async function renderInkREPL(props) {
|
|
2014
2012
|
const ink = await import("ink");
|
|
2015
|
-
const { waitUntilExit } = ink.render(
|
|
2013
|
+
const { waitUntilExit } = ink.render(React4.createElement(REPLInk, props));
|
|
2016
2014
|
await waitUntilExit();
|
|
2017
2015
|
}
|
|
2018
2016
|
var MarkdownBounded, inkLogger, _msgIdCounter = 0, MultilineInput, MessageView;
|
|
@@ -2024,7 +2022,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2024
2022
|
init_Markdown();
|
|
2025
2023
|
init_StatusBar();
|
|
2026
2024
|
init_dynamic_tail();
|
|
2027
|
-
MarkdownBounded =
|
|
2025
|
+
MarkdownBounded = React4.memo(({ text, bounds, width }) => {
|
|
2028
2026
|
const out = renderBoundedAssistant(text, bounds, width);
|
|
2029
2027
|
if (!out) {
|
|
2030
2028
|
return null;
|
|
@@ -2034,16 +2032,16 @@ var init_repl_ink = __esm(() => {
|
|
|
2034
2032
|
}, undefined, false, undefined, this);
|
|
2035
2033
|
});
|
|
2036
2034
|
inkLogger = createLogger5("repl-ink");
|
|
2037
|
-
MultilineInput =
|
|
2035
|
+
MultilineInput = React4.memo(React4.forwardRef(function MultilineInput2(props, ref) {
|
|
2038
2036
|
const { onSubmit, placeholder, popupActive, onChange, onEscape } = props;
|
|
2039
|
-
const [buffer, setBuffer] =
|
|
2040
|
-
const [cursor, setCursor] =
|
|
2041
|
-
|
|
2037
|
+
const [buffer, setBuffer] = React4.useState("");
|
|
2038
|
+
const [cursor, setCursor] = React4.useState(0);
|
|
2039
|
+
React4.useEffect(() => {
|
|
2042
2040
|
if (popupActive || buffer.startsWith("/")) {
|
|
2043
2041
|
onChange?.(buffer);
|
|
2044
2042
|
}
|
|
2045
2043
|
}, [buffer, onChange, popupActive]);
|
|
2046
|
-
|
|
2044
|
+
React4.useImperativeHandle(ref, () => ({
|
|
2047
2045
|
clearBuffer: () => {
|
|
2048
2046
|
setBuffer("");
|
|
2049
2047
|
setCursor(0);
|
|
@@ -2281,7 +2279,7 @@ var init_repl_ink = __esm(() => {
|
|
|
2281
2279
|
})
|
|
2282
2280
|
}, undefined, false, undefined, this);
|
|
2283
2281
|
}));
|
|
2284
|
-
MessageView =
|
|
2282
|
+
MessageView = React4.memo(function MessageView2({
|
|
2285
2283
|
msg,
|
|
2286
2284
|
terminalWidth,
|
|
2287
2285
|
tailBounds
|
|
@@ -9461,7 +9459,7 @@ class CliQuietModeService {
|
|
|
9461
9459
|
// package.json
|
|
9462
9460
|
var package_default = {
|
|
9463
9461
|
name: "@ai-setting/roy-agent-cli",
|
|
9464
|
-
version: "1.7.
|
|
9462
|
+
version: "1.7.20",
|
|
9465
9463
|
type: "module",
|
|
9466
9464
|
description: "CLI for roy-agent - Non-interactive command execution",
|
|
9467
9465
|
main: "./dist/index.js",
|
|
@@ -13642,27 +13640,25 @@ function createInteractiveCommand(externalEnvService) {
|
|
|
13642
13640
|
var InteractiveCommand = createInteractiveCommand();
|
|
13643
13641
|
|
|
13644
13642
|
// src/commands/run.ts
|
|
13645
|
-
import
|
|
13643
|
+
import React9 from "react";
|
|
13646
13644
|
import { render } from "ink";
|
|
13647
13645
|
|
|
13648
|
-
// src/RunTui.
|
|
13649
|
-
import { useState as useState6, useCallback as useCallback4, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
13646
|
+
// src/RunTui.js
|
|
13647
|
+
import React8, { useState as useState6, useCallback as useCallback4, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
13650
13648
|
import { Box as Box6, Text as Text8, useApp as useApp2 } from "ink";
|
|
13651
13649
|
|
|
13652
|
-
// src/tui/App.
|
|
13650
|
+
// src/tui/App.js
|
|
13653
13651
|
init_Markdown();
|
|
13652
|
+
import React6 from "react";
|
|
13654
13653
|
import { Box as Box4, Static as Static2, Text as Text6 } from "ink";
|
|
13655
13654
|
|
|
13656
|
-
// src/tui/Spinner.
|
|
13655
|
+
// src/tui/Spinner.js
|
|
13657
13656
|
init_theme();
|
|
13658
|
-
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
13657
|
+
import React5, { useEffect as useEffect3, useState as useState3 } from "react";
|
|
13659
13658
|
import { Text as Text5 } from "ink";
|
|
13660
13659
|
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
13661
13660
|
var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
13662
|
-
var Spinner = ({
|
|
13663
|
-
label,
|
|
13664
|
-
intervalMs = 80
|
|
13665
|
-
}) => {
|
|
13661
|
+
var Spinner = ({ label, intervalMs = 80 }) => {
|
|
13666
13662
|
const [frame, setFrame] = useState3(0);
|
|
13667
13663
|
const theme = getTheme();
|
|
13668
13664
|
useEffect3(() => {
|
|
@@ -13686,7 +13682,7 @@ var Spinner = ({
|
|
|
13686
13682
|
}, undefined, true, undefined, this);
|
|
13687
13683
|
};
|
|
13688
13684
|
|
|
13689
|
-
// src/tui/App.
|
|
13685
|
+
// src/tui/App.js
|
|
13690
13686
|
init_StatusBar();
|
|
13691
13687
|
init_theme();
|
|
13692
13688
|
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
@@ -13757,14 +13753,7 @@ var HistoryEntry = ({ item }) => {
|
|
|
13757
13753
|
]
|
|
13758
13754
|
}, undefined, true, undefined, this);
|
|
13759
13755
|
};
|
|
13760
|
-
var App = ({
|
|
13761
|
-
history,
|
|
13762
|
-
status,
|
|
13763
|
-
model,
|
|
13764
|
-
workdir,
|
|
13765
|
-
streamingText,
|
|
13766
|
-
tokenCount
|
|
13767
|
-
}) => {
|
|
13756
|
+
var App = ({ history, status, model, workdir, streamingText, tokenCount }) => {
|
|
13768
13757
|
const theme = getTheme();
|
|
13769
13758
|
return /* @__PURE__ */ jsxDEV6(Box4, {
|
|
13770
13759
|
flexDirection: "column",
|
|
@@ -13831,22 +13820,15 @@ var App = ({
|
|
|
13831
13820
|
}, undefined, true, undefined, this);
|
|
13832
13821
|
};
|
|
13833
13822
|
|
|
13834
|
-
// src/tui/index.
|
|
13823
|
+
// src/tui/index.js
|
|
13835
13824
|
init_Markdown();
|
|
13836
13825
|
init_StatusBar();
|
|
13837
13826
|
|
|
13838
|
-
// src/tui/TextInput.
|
|
13839
|
-
import { useEffect as useEffect4, useState as useState4 } from "react";
|
|
13827
|
+
// src/tui/TextInput.js
|
|
13828
|
+
import React7, { useEffect as useEffect4, useState as useState4 } from "react";
|
|
13840
13829
|
import { Box as Box5, Text as Text7, useInput as useInput3 } from "ink";
|
|
13841
13830
|
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
13842
|
-
var TextInput = ({
|
|
13843
|
-
label,
|
|
13844
|
-
prefix,
|
|
13845
|
-
onSubmit,
|
|
13846
|
-
onCancel,
|
|
13847
|
-
placeholder,
|
|
13848
|
-
history = []
|
|
13849
|
-
}) => {
|
|
13831
|
+
var TextInput = ({ label, prefix, onSubmit, onCancel, placeholder, history = [] }) => {
|
|
13850
13832
|
const [value, setValue] = useState4("");
|
|
13851
13833
|
const [historyIndex, setHistoryIndex] = useState4(-1);
|
|
13852
13834
|
const [draft, setDraft] = useState4("");
|
|
@@ -13936,11 +13918,12 @@ var TextInput = ({
|
|
|
13936
13918
|
}, undefined, true, undefined, this);
|
|
13937
13919
|
};
|
|
13938
13920
|
|
|
13939
|
-
// src/tui/index.
|
|
13921
|
+
// src/tui/index.js
|
|
13940
13922
|
init_theme();
|
|
13941
|
-
init_welcome_card2();
|
|
13942
13923
|
|
|
13943
|
-
// src/tui/
|
|
13924
|
+
// src/tui/welcome-card.js
|
|
13925
|
+
init_welcome_card();
|
|
13926
|
+
// src/tui/use-streaming-accumulator.js
|
|
13944
13927
|
import { useCallback as useCallback3, useState as useState5 } from "react";
|
|
13945
13928
|
function useStreamingAccumulator() {
|
|
13946
13929
|
const [status, setStatus] = useState5("idle");
|
|
@@ -13974,10 +13957,10 @@ function useStreamingAccumulator() {
|
|
|
13974
13957
|
return { status, streamingText, start, append, finish, fail };
|
|
13975
13958
|
}
|
|
13976
13959
|
|
|
13977
|
-
// src/RunTui.
|
|
13960
|
+
// src/RunTui.js
|
|
13978
13961
|
init_markdown();
|
|
13979
13962
|
|
|
13980
|
-
// src/slash.
|
|
13963
|
+
// src/slash.js
|
|
13981
13964
|
var CLEAR_SENTINEL = "__CLEAR__";
|
|
13982
13965
|
function dispatchSlashCommand(raw, ctx) {
|
|
13983
13966
|
const text = raw.trim();
|
|
@@ -14049,18 +14032,9 @@ function dispatchSlashCommand(raw, ctx) {
|
|
|
14049
14032
|
}
|
|
14050
14033
|
}
|
|
14051
14034
|
|
|
14052
|
-
// src/RunTui.
|
|
14035
|
+
// src/RunTui.js
|
|
14053
14036
|
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
14054
|
-
var RunScreen = ({
|
|
14055
|
-
handleQuery,
|
|
14056
|
-
streamHandleQuery,
|
|
14057
|
-
model,
|
|
14058
|
-
workdir,
|
|
14059
|
-
maxLines: initialMaxLines,
|
|
14060
|
-
markdownEnabled: markdownEnabled2,
|
|
14061
|
-
onExit,
|
|
14062
|
-
onRegisterHandlers
|
|
14063
|
-
}) => {
|
|
14037
|
+
var RunScreen = ({ handleQuery, streamHandleQuery, model, workdir, maxLines: initialMaxLines, markdownEnabled: markdownEnabled2, onExit, onRegisterHandlers }) => {
|
|
14064
14038
|
const [history, setHistory] = useState6([]);
|
|
14065
14039
|
const [errorMessage, setErrorMessage] = useState6(null);
|
|
14066
14040
|
const [maxLines, setMaxLines] = useState6(initialMaxLines);
|
|
@@ -14256,49 +14230,1088 @@ var RunTui_default = RunScreen;
|
|
|
14256
14230
|
// src/commands/run.ts
|
|
14257
14231
|
init_markdown();
|
|
14258
14232
|
|
|
14259
|
-
// src/commands/
|
|
14260
|
-
import {
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14233
|
+
// src/commands/shared/session-manager.js
|
|
14234
|
+
import { parseImageInput as parseImageInput3 } from "@ai-setting/roy-agent-core";
|
|
14235
|
+
|
|
14236
|
+
class SessionManager2 {
|
|
14237
|
+
sessionComponent;
|
|
14238
|
+
output;
|
|
14239
|
+
quiet;
|
|
14240
|
+
attachedImagesMap = new Map;
|
|
14241
|
+
constructor(options) {
|
|
14242
|
+
this.sessionComponent = options.sessionComponent;
|
|
14243
|
+
this.output = options.output;
|
|
14244
|
+
this.quiet = options.quiet;
|
|
14245
|
+
}
|
|
14246
|
+
async init(sessionId, isContinue) {
|
|
14247
|
+
let targetSessionId = sessionId;
|
|
14248
|
+
let isNewSession = false;
|
|
14249
|
+
if (isContinue && !targetSessionId) {
|
|
14250
|
+
const activeSession = await this.sessionComponent.getActiveSession();
|
|
14251
|
+
if (activeSession) {
|
|
14252
|
+
targetSessionId = activeSession.id;
|
|
14253
|
+
if (!this.quiet) {
|
|
14254
|
+
this.output.info(`继续会话: ${activeSession.title} (${targetSessionId})`);
|
|
14255
|
+
}
|
|
14256
|
+
} else {
|
|
14257
|
+
this.output.warn("没有找到上次会话,将创建新会话");
|
|
14258
|
+
}
|
|
14259
|
+
}
|
|
14260
|
+
if (targetSessionId) {
|
|
14261
|
+
await this.sessionComponent.setActiveSession(targetSessionId);
|
|
14262
|
+
const session2 = await this.sessionComponent.get(targetSessionId);
|
|
14263
|
+
if (session2) {
|
|
14264
|
+
if (!this.quiet) {
|
|
14265
|
+
this.output.info(`会话: ${session2.title} (${targetSessionId})`);
|
|
14266
|
+
}
|
|
14267
|
+
} else {
|
|
14268
|
+
this.output.warn(`会话不存在: ${targetSessionId},将创建新会话`);
|
|
14269
|
+
targetSessionId = undefined;
|
|
14270
|
+
}
|
|
14271
|
+
}
|
|
14272
|
+
if (!targetSessionId) {
|
|
14273
|
+
const newSession = await this.sessionComponent.create({
|
|
14274
|
+
title: `Session - ${new Date().toLocaleString("zh-CN")}`
|
|
14275
|
+
});
|
|
14276
|
+
targetSessionId = newSession.id;
|
|
14277
|
+
isNewSession = true;
|
|
14278
|
+
await this.sessionComponent.setActiveSession(targetSessionId);
|
|
14279
|
+
if (!this.quiet) {
|
|
14280
|
+
this.output.info(`创建新会话: ${newSession.title} (${targetSessionId})`);
|
|
14281
|
+
}
|
|
14282
|
+
}
|
|
14283
|
+
this.clearAttachments();
|
|
14284
|
+
const session = await this.sessionComponent.get(targetSessionId);
|
|
14285
|
+
return {
|
|
14286
|
+
sessionId: targetSessionId,
|
|
14287
|
+
isNewSession,
|
|
14288
|
+
sessionTitle: session?.title || "Unknown"
|
|
14289
|
+
};
|
|
14290
|
+
}
|
|
14291
|
+
async switchSession(sessionId) {
|
|
14292
|
+
return this.init(sessionId, false);
|
|
14293
|
+
}
|
|
14294
|
+
async getCurrentSession() {
|
|
14295
|
+
return this.sessionComponent.getActiveSession();
|
|
14296
|
+
}
|
|
14297
|
+
async attachImage(rawPath) {
|
|
14298
|
+
const normalized = rawPath.trim();
|
|
14299
|
+
if (!normalized) {
|
|
14300
|
+
throw new Error("attachImage: empty path");
|
|
14301
|
+
}
|
|
14302
|
+
const existing = this.attachedImagesMap.get(normalized);
|
|
14303
|
+
if (existing) {
|
|
14304
|
+
return existing;
|
|
14305
|
+
}
|
|
14306
|
+
const part = await parseImageInput3(normalized);
|
|
14307
|
+
this.attachedImagesMap.set(normalized, part);
|
|
14308
|
+
return part;
|
|
14309
|
+
}
|
|
14310
|
+
listAttachments() {
|
|
14311
|
+
return Array.from(this.attachedImagesMap.values());
|
|
14312
|
+
}
|
|
14313
|
+
clearAttachments() {
|
|
14314
|
+
this.attachedImagesMap.clear();
|
|
14315
|
+
}
|
|
14316
|
+
async getQueryPayload(text) {
|
|
14317
|
+
if (this.attachedImagesMap.size === 0) {
|
|
14318
|
+
return text;
|
|
14319
|
+
}
|
|
14320
|
+
return [
|
|
14321
|
+
{ type: "text", text },
|
|
14322
|
+
...this.listAttachments()
|
|
14323
|
+
];
|
|
14324
|
+
}
|
|
14325
|
+
}
|
|
14326
|
+
|
|
14327
|
+
// src/commands/shared/query-executor.js
|
|
14328
|
+
init_stream_output_service();
|
|
14329
|
+
import { ContextError as ContextError4, ErrorCodes as ErrorCodes4, TracedAs as TracedAs7 } from "@ai-setting/roy-agent-core";
|
|
14330
|
+
var __decorate = function(decorators, target, key, desc) {
|
|
14331
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14332
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14333
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
14334
|
+
else
|
|
14335
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14336
|
+
if (d = decorators[i])
|
|
14337
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14338
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14339
|
+
};
|
|
14340
|
+
|
|
14341
|
+
class QueryExecutor2 {
|
|
14342
|
+
env;
|
|
14343
|
+
sessionComponent;
|
|
14344
|
+
output;
|
|
14345
|
+
quiet;
|
|
14346
|
+
silent = false;
|
|
14347
|
+
streamService = null;
|
|
14348
|
+
unsubscribe = null;
|
|
14349
|
+
streamOptions = {
|
|
14350
|
+
showReasoning: true,
|
|
14351
|
+
showToolCalls: true,
|
|
14352
|
+
showToolResults: false
|
|
14353
|
+
};
|
|
14354
|
+
_pendingContextConfig = null;
|
|
14355
|
+
_pendingChunkCallback = undefined;
|
|
14356
|
+
constructor(options) {
|
|
14357
|
+
this.env = options.env;
|
|
14358
|
+
this.sessionComponent = options.sessionComponent;
|
|
14359
|
+
this.output = options.output;
|
|
14360
|
+
this.quiet = options.quiet;
|
|
14361
|
+
this.silent = options.silent ?? false;
|
|
14362
|
+
}
|
|
14363
|
+
initSummaryAgent(llmComponent, promptComponent) {
|
|
14364
|
+
const session = this.sessionComponent;
|
|
14365
|
+
if (typeof session.setSummaryComponents === "function") {
|
|
14366
|
+
session.setSummaryComponents(promptComponent, llmComponent);
|
|
14367
|
+
}
|
|
14368
|
+
}
|
|
14369
|
+
initStreamOutput(llmComponent, providerId = "minimax") {
|
|
14370
|
+
if (llmComponent) {
|
|
14371
|
+
const contextConfig = llmComponent.getContextThresholdConfig(providerId);
|
|
14372
|
+
this._pendingContextConfig = contextConfig;
|
|
14373
|
+
}
|
|
14374
|
+
}
|
|
14375
|
+
subscribeToEvents(options) {
|
|
14376
|
+
this.streamOptions = options;
|
|
14377
|
+
if (this.streamService) {
|
|
14378
|
+
this.streamService.setOptions(options);
|
|
14379
|
+
}
|
|
14380
|
+
if (this.unsubscribe) {
|
|
14381
|
+
return;
|
|
14382
|
+
}
|
|
14383
|
+
this.streamService = new StreamOutputService({
|
|
14384
|
+
...options,
|
|
14385
|
+
silent: this.silent ?? false
|
|
14386
|
+
});
|
|
14387
|
+
if (this._pendingChunkCallback !== undefined) {
|
|
14388
|
+
this.streamService.setChunkCallback(this._pendingChunkCallback);
|
|
14389
|
+
this._pendingChunkCallback = undefined;
|
|
14390
|
+
}
|
|
14391
|
+
if (this._pendingContextConfig) {
|
|
14392
|
+
this.streamService.setContextInfo(this._pendingContextConfig.contextWindow, this._pendingContextConfig.contextWindow * this._pendingContextConfig.thresholdRatio);
|
|
14393
|
+
this._pendingContextConfig = null;
|
|
14394
|
+
}
|
|
14395
|
+
this.unsubscribe = this.env.subscribeTo([
|
|
14396
|
+
"llm.start",
|
|
14397
|
+
"llm.text",
|
|
14398
|
+
"llm.reasoning",
|
|
14399
|
+
"llm.completed",
|
|
14400
|
+
"llm.error",
|
|
14401
|
+
"tool.call",
|
|
14402
|
+
"tool.result",
|
|
14403
|
+
"tool.error",
|
|
14404
|
+
"context.threshold_exceeded",
|
|
14405
|
+
"context.compacting",
|
|
14406
|
+
"context.compacted"
|
|
14407
|
+
], (event) => this.handleEvent(event));
|
|
14408
|
+
}
|
|
14409
|
+
setChunkCallback(cb) {
|
|
14410
|
+
if (this.streamService) {
|
|
14411
|
+
this.streamService.setChunkCallback(cb);
|
|
14412
|
+
} else {
|
|
14413
|
+
this._pendingChunkCallback = cb;
|
|
14414
|
+
}
|
|
14415
|
+
}
|
|
14416
|
+
handleEvent(event) {
|
|
14417
|
+
if (event.type === "context.threshold_exceeded" && !this.quiet) {
|
|
14418
|
+
const payload = event.payload;
|
|
14419
|
+
this.output.warn(`⚙ 上下文阈值 (${payload.totalTokens}/${payload.contextWindow})`);
|
|
14420
|
+
}
|
|
14421
|
+
if (event.type === "context.compacting" && !this.quiet) {
|
|
14422
|
+
this.output.info("⚙ 压缩中...");
|
|
14423
|
+
}
|
|
14424
|
+
if (event.type === "context.compacted" && !this.quiet) {
|
|
14425
|
+
this.output.success(`✓ 已压缩 (${event.payload.checkpointId})`);
|
|
14426
|
+
}
|
|
14427
|
+
this.streamService?.handleEvent(event);
|
|
14428
|
+
}
|
|
14429
|
+
async execute(message, sessionId, streamOptions, traceId, agentContext) {
|
|
14430
|
+
const options = {
|
|
14431
|
+
showReasoning: streamOptions?.showReasoning ?? this.streamOptions.showReasoning,
|
|
14432
|
+
showToolCalls: streamOptions?.showToolCalls ?? this.streamOptions.showToolCalls,
|
|
14433
|
+
showToolResults: streamOptions?.showToolResults ?? this.streamOptions.showToolResults
|
|
14434
|
+
};
|
|
14435
|
+
this.subscribeToEvents(options);
|
|
14436
|
+
this.streamService?.reset();
|
|
14437
|
+
if (!this.quiet) {
|
|
14438
|
+
this.output.info(`执行: ${message}`);
|
|
14439
|
+
}
|
|
14440
|
+
const contextHandler = new ContextHandlerService(this.env, this.sessionComponent, { maxRetries: 1, autoCompact: true });
|
|
14441
|
+
const { systemPrompt: agentContextSystemPrompt, eventSourceSystemPrompt: agentContextPreloadedPrompts, ...restAgentContext } = agentContext ?? {};
|
|
14442
|
+
let eventSourceFinalPrompt;
|
|
14443
|
+
if (typeof agentContextSystemPrompt === "string" && agentContextSystemPrompt.length > 0) {
|
|
14444
|
+
eventSourceFinalPrompt = agentContextSystemPrompt;
|
|
14445
|
+
} else if (typeof agentContextPreloadedPrompts === "string" && agentContextPreloadedPrompts.length > 0) {
|
|
14446
|
+
eventSourceFinalPrompt = agentContextPreloadedPrompts;
|
|
14447
|
+
}
|
|
14448
|
+
const context = {
|
|
14449
|
+
sessionId,
|
|
14450
|
+
metadata: {
|
|
14451
|
+
originalQuery: message,
|
|
14452
|
+
traceId,
|
|
14453
|
+
systemPrompt: eventSourceFinalPrompt
|
|
14454
|
+
},
|
|
14455
|
+
...restAgentContext
|
|
14456
|
+
};
|
|
14457
|
+
let result;
|
|
14458
|
+
try {
|
|
14459
|
+
result = await contextHandler.handleQueryWithContext(message, context);
|
|
14460
|
+
} catch (error) {
|
|
14461
|
+
if (error instanceof ContextError4 && error.code === ErrorCodes4.CONTEXT_THRESHOLD_EXCEEDED) {
|
|
14462
|
+
this.output.error(`上下文阈值超出限制: ${error.usage?.totalTokens}/${error.contextWindow}`);
|
|
14463
|
+
this.output.info("请手动压缩会话: roy-agent sessions compact " + sessionId);
|
|
14464
|
+
}
|
|
14465
|
+
throw error;
|
|
14466
|
+
}
|
|
14467
|
+
if (!this.quiet) {
|
|
14468
|
+
this.output.success("执行完成");
|
|
14469
|
+
}
|
|
14470
|
+
return result;
|
|
14471
|
+
}
|
|
14472
|
+
dispose() {
|
|
14473
|
+
if (this.unsubscribe) {
|
|
14474
|
+
this.unsubscribe();
|
|
14475
|
+
this.unsubscribe = null;
|
|
14476
|
+
}
|
|
14477
|
+
}
|
|
14478
|
+
getFullText() {
|
|
14479
|
+
return this.streamService?.getFullText() ?? "";
|
|
14480
|
+
}
|
|
14481
|
+
getLastUsage() {
|
|
14482
|
+
return this.streamService?.getUsageInfo() ?? null;
|
|
14483
|
+
}
|
|
14484
|
+
resetStream() {
|
|
14485
|
+
this.streamService?.reset();
|
|
14486
|
+
}
|
|
14487
|
+
async compact(sessionId) {
|
|
14488
|
+
try {
|
|
14489
|
+
const envCore = this.env.getComponent("core");
|
|
14490
|
+
if (envCore?.pushEnvEvent) {
|
|
14491
|
+
envCore.pushEnvEvent({
|
|
14492
|
+
type: "context.compacting",
|
|
14493
|
+
metadata: { sessionId },
|
|
14494
|
+
payload: {}
|
|
14495
|
+
});
|
|
14496
|
+
}
|
|
14497
|
+
const result = await this.sessionComponent.compact(sessionId, {
|
|
14498
|
+
summary: "Manual compact from interactive mode"
|
|
14499
|
+
});
|
|
14500
|
+
if (envCore?.pushEnvEvent) {
|
|
14501
|
+
envCore.pushEnvEvent({
|
|
14502
|
+
type: "context.compacted",
|
|
14503
|
+
metadata: { sessionId },
|
|
14504
|
+
payload: {
|
|
14505
|
+
checkpointId: result.checkpoint.id,
|
|
14506
|
+
messagesCompacted: result.deletedMessageCount
|
|
14507
|
+
}
|
|
14508
|
+
});
|
|
14509
|
+
}
|
|
14510
|
+
return {
|
|
14511
|
+
success: true,
|
|
14512
|
+
checkpoint: result.checkpoint,
|
|
14513
|
+
deletedMessageCount: result.deletedMessageCount
|
|
14514
|
+
};
|
|
14515
|
+
} catch (error) {
|
|
14516
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14517
|
+
this.output.error(`压缩失败: ${errorMessage}`);
|
|
14518
|
+
return {
|
|
14519
|
+
success: false,
|
|
14520
|
+
error: errorMessage
|
|
14521
|
+
};
|
|
14522
|
+
}
|
|
14523
|
+
}
|
|
14524
|
+
}
|
|
14525
|
+
__decorate([
|
|
14526
|
+
TracedAs7("cli.query-executor.execute", { recordParams: true, log: true })
|
|
14527
|
+
], QueryExecutor2.prototype, "execute", null);
|
|
14528
|
+
|
|
14529
|
+
// src/commands/interactive-event-sources.js
|
|
14530
|
+
import { TracedAs as TracedAs8 } from "@ai-setting/roy-agent-core";
|
|
14531
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
14532
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14533
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14534
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
14535
|
+
else
|
|
14536
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14537
|
+
if (d = decorators[i])
|
|
14538
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14539
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14540
|
+
};
|
|
14541
|
+
async function startSingleEventSource2(eventSourceComponent, output, eventSourceId) {
|
|
14542
|
+
return EventSourceStarter2.instance.runSingle(eventSourceComponent, output, eventSourceId);
|
|
14543
|
+
}
|
|
14544
|
+
async function startEventSources2(eventSourceIds, eventSourceComponent, output) {
|
|
14545
|
+
return EventSourceStarter2.instance.run(eventSourceIds, eventSourceComponent, output);
|
|
14546
|
+
}
|
|
14547
|
+
|
|
14548
|
+
class EventSourceStarter2 {
|
|
14549
|
+
static instance = new EventSourceStarter2;
|
|
14550
|
+
async run(eventSourceIds, eventSourceComponent, output) {
|
|
14551
|
+
return startEventSourcesImpl2(eventSourceIds, eventSourceComponent, output);
|
|
14552
|
+
}
|
|
14553
|
+
async runSingle(eventSourceComponent, output, eventSourceId) {
|
|
14554
|
+
return startSingleEventSourceImpl2(eventSourceComponent, output, eventSourceId);
|
|
14555
|
+
}
|
|
14556
|
+
}
|
|
14557
|
+
__decorate2([
|
|
14558
|
+
TracedAs8("interactive.startEventSources", { recordParams: false, log: false })
|
|
14559
|
+
], EventSourceStarter2.prototype, "run", null);
|
|
14560
|
+
__decorate2([
|
|
14561
|
+
TracedAs8("interactive.startSingleEventSource", { recordParams: false, log: false })
|
|
14562
|
+
], EventSourceStarter2.prototype, "runSingle", null);
|
|
14563
|
+
async function startEventSourcesImpl2(eventSourceIds, eventSourceComponent, output) {
|
|
14564
|
+
const results = [];
|
|
14565
|
+
if (!eventSourceIds || eventSourceIds.length === 0) {
|
|
14566
|
+
return { results, total: 0, successCount: 0, failedCount: 0 };
|
|
14567
|
+
}
|
|
14568
|
+
for (const id of eventSourceIds) {
|
|
14569
|
+
if (!id)
|
|
14570
|
+
continue;
|
|
14571
|
+
const result = await startSingleEventSource2(eventSourceComponent, output, id);
|
|
14572
|
+
results.push(result);
|
|
14573
|
+
}
|
|
14574
|
+
const successCount = results.filter((r) => r.success).length;
|
|
14575
|
+
const failedCount = results.length - successCount;
|
|
14576
|
+
if (results.length > 1) {
|
|
14577
|
+
if (failedCount > 0) {
|
|
14578
|
+
output.info(`
|
|
14579
|
+
✅ 成功启动 ${successCount}/${results.length} 个事件源`);
|
|
14580
|
+
} else {
|
|
14581
|
+
output.success(`
|
|
14582
|
+
✅ 成功启动 ${successCount}/${results.length} 个事件源`);
|
|
14583
|
+
}
|
|
14584
|
+
}
|
|
14585
|
+
return { results, total: results.length, successCount, failedCount };
|
|
14586
|
+
}
|
|
14587
|
+
async function startSingleEventSourceImpl2(eventSourceComponent, output, eventSourceId) {
|
|
14588
|
+
const sources = eventSourceComponent.list();
|
|
14589
|
+
const matchedSource = sources.find((s) => s.id === eventSourceId || s.id.startsWith(eventSourceId));
|
|
14590
|
+
if (!matchedSource) {
|
|
14591
|
+
output.error(`❌ 事件源不存在: ${eventSourceId}`);
|
|
14592
|
+
output.info(`可用的事件源:`);
|
|
14593
|
+
for (const s of sources) {
|
|
14594
|
+
output.info(` - ${s.id.substring(0, 8)}: ${s.name} (${s.type})`);
|
|
14595
|
+
}
|
|
14596
|
+
return {
|
|
14597
|
+
id: eventSourceId,
|
|
14598
|
+
name: eventSourceId,
|
|
14599
|
+
success: false,
|
|
14600
|
+
status: "not_found",
|
|
14601
|
+
error: `EventSource not found: ${eventSourceId}`
|
|
14602
|
+
};
|
|
14603
|
+
}
|
|
14604
|
+
const actualId = matchedSource.id;
|
|
14605
|
+
const status = eventSourceComponent.getStatus(actualId);
|
|
14606
|
+
if (status === "running") {
|
|
14607
|
+
output.info(`\uD83D\uDCE1 事件源 ${matchedSource.name} 已在运行中`);
|
|
14608
|
+
return {
|
|
14609
|
+
id: actualId,
|
|
14610
|
+
name: matchedSource.name,
|
|
14611
|
+
success: true,
|
|
14612
|
+
status: "skipped"
|
|
14613
|
+
};
|
|
14614
|
+
}
|
|
14615
|
+
try {
|
|
14616
|
+
await eventSourceComponent.startSource(actualId);
|
|
14617
|
+
const verifyStatus = eventSourceComponent.getStatus(actualId);
|
|
14618
|
+
if (verifyStatus !== "running") {
|
|
14619
|
+
const errMsg = `启动后状态异常: ${verifyStatus}`;
|
|
14620
|
+
output.error(`❌ ${errMsg}`);
|
|
14621
|
+
return {
|
|
14622
|
+
id: actualId,
|
|
14623
|
+
name: matchedSource.name,
|
|
14624
|
+
success: false,
|
|
14625
|
+
status: "failed",
|
|
14626
|
+
error: errMsg
|
|
14627
|
+
};
|
|
14628
|
+
}
|
|
14629
|
+
output.success(`\uD83D\uDCE1 已启动事件源: ${matchedSource.name} (${verifyStatus})`);
|
|
14630
|
+
return {
|
|
14631
|
+
id: actualId,
|
|
14632
|
+
name: matchedSource.name,
|
|
14633
|
+
success: true,
|
|
14634
|
+
status: "started"
|
|
14635
|
+
};
|
|
14636
|
+
} catch (error) {
|
|
14637
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
14638
|
+
output.error(`❌ 启动事件源失败: ${matchedSource.name} - ${errMsg}`);
|
|
14639
|
+
return {
|
|
14640
|
+
id: actualId,
|
|
14641
|
+
name: matchedSource.name,
|
|
14642
|
+
success: false,
|
|
14643
|
+
status: "failed",
|
|
14644
|
+
error: errMsg
|
|
14645
|
+
};
|
|
14646
|
+
}
|
|
14647
|
+
}
|
|
14648
|
+
|
|
14649
|
+
// src/commands/collect-event-source-system-prompts.js
|
|
14650
|
+
import { resolveBountyIMSystemPrompt as resolveBountyIMSystemPrompt2 } from "@ai-setting/roy-agent-core";
|
|
14651
|
+
function resolveSystemPromptForSource2(config) {
|
|
14652
|
+
if (config.type === "bounty-im") {
|
|
14653
|
+
const imServerUrl = config.imServerUrl || config.options && config.options.imServerUrl;
|
|
14654
|
+
const address = config.address || config.options && config.options.address || "unknown";
|
|
14655
|
+
return resolveBountyIMSystemPrompt2({
|
|
14656
|
+
configSystemPrompt: config.systemPrompt,
|
|
14657
|
+
currentAddress: address,
|
|
14658
|
+
imServerUrl
|
|
14659
|
+
});
|
|
14660
|
+
}
|
|
14661
|
+
return config.systemPrompt;
|
|
14662
|
+
}
|
|
14663
|
+
function collectEventSourceSystemPrompts2(eventSourceIds, eventSourceComponent) {
|
|
14664
|
+
const result = [];
|
|
14665
|
+
for (const id of eventSourceIds) {
|
|
14666
|
+
const config = eventSourceComponent.get(id);
|
|
14667
|
+
if (!config)
|
|
14668
|
+
continue;
|
|
14669
|
+
const prompt = resolveSystemPromptForSource2(config);
|
|
14670
|
+
if (!prompt)
|
|
14671
|
+
continue;
|
|
14672
|
+
result.push({ id, type: config.type, prompt });
|
|
14673
|
+
}
|
|
14674
|
+
return result;
|
|
14675
|
+
}
|
|
14676
|
+
function joinResolvedSystemPrompts2(prompts) {
|
|
14677
|
+
return prompts.map((p) => p.prompt).join(`
|
|
14678
|
+
|
|
14679
|
+
---
|
|
14680
|
+
|
|
14681
|
+
`);
|
|
14682
|
+
}
|
|
14683
|
+
|
|
14684
|
+
// src/commands/act-agent-validation.js
|
|
14685
|
+
function validateActAgent2(agentComponent, agentName) {
|
|
14686
|
+
if (!agentName || agentName === "default") {
|
|
14687
|
+
return { valid: true };
|
|
14688
|
+
}
|
|
14689
|
+
if (!agentComponent?.getAgent(agentName)) {
|
|
14690
|
+
return {
|
|
14691
|
+
valid: false,
|
|
14692
|
+
message: `Agent "${agentName}" 不存在`
|
|
14693
|
+
};
|
|
14694
|
+
}
|
|
14695
|
+
return { valid: true };
|
|
14696
|
+
}
|
|
14697
|
+
function buildActAgentContext2(agentName) {
|
|
14698
|
+
if (!agentName || agentName === "default") {
|
|
14699
|
+
return;
|
|
14700
|
+
}
|
|
14701
|
+
return { agentType: agentName };
|
|
14702
|
+
}
|
|
14703
|
+
|
|
14704
|
+
// src/commands/shared/event-handler.js
|
|
14705
|
+
import { TracedAs as TracedAs9 } from "@ai-setting/roy-agent-core";
|
|
14706
|
+
var __decorate3 = function(decorators, target, key, desc) {
|
|
14707
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14708
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
14709
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
14710
|
+
else
|
|
14711
|
+
for (var i = decorators.length - 1;i >= 0; i--)
|
|
14712
|
+
if (d = decorators[i])
|
|
14713
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14714
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
14715
|
+
};
|
|
14716
|
+
|
|
14717
|
+
class EventHandler2 {
|
|
14718
|
+
env;
|
|
14719
|
+
eventTypes;
|
|
14720
|
+
onEvent;
|
|
14721
|
+
onEventWithEnv;
|
|
14722
|
+
formatter;
|
|
14723
|
+
isIdle;
|
|
14724
|
+
idleCheckInterval;
|
|
14725
|
+
queue = [];
|
|
14726
|
+
isProcessing = false;
|
|
14727
|
+
isStopped = false;
|
|
14728
|
+
unsubscribe = null;
|
|
14729
|
+
sessionComponent = null;
|
|
14730
|
+
activeEventSessionId = null;
|
|
14731
|
+
constructor(options) {
|
|
14732
|
+
this.env = options.env;
|
|
14733
|
+
this.eventTypes = options.eventTypes;
|
|
14734
|
+
this.onEvent = options.onEvent;
|
|
14735
|
+
this.onEventWithEnv = options.onEventWithEnv;
|
|
14736
|
+
this.formatter = options.formatter ?? new EventMessageFormatter;
|
|
14737
|
+
this.isIdle = options.isIdle ?? (() => true);
|
|
14738
|
+
this.idleCheckInterval = options.idleCheckInterval ?? 100;
|
|
14739
|
+
this.sessionComponent = options.sessionComponent ?? null;
|
|
14740
|
+
}
|
|
14741
|
+
start() {
|
|
14742
|
+
this.isStopped = false;
|
|
14743
|
+
this.unsubscribe = this.env.subscribeAll((event) => {
|
|
14744
|
+
if (this.matchesEventType(event.type)) {
|
|
14745
|
+
this.handleEvent(event);
|
|
14746
|
+
}
|
|
14747
|
+
});
|
|
14748
|
+
return () => this.stop();
|
|
14749
|
+
}
|
|
14750
|
+
matchesEventType(eventType) {
|
|
14751
|
+
for (const pattern of this.eventTypes) {
|
|
14752
|
+
if (this.matchPattern(eventType, pattern)) {
|
|
14753
|
+
return true;
|
|
14754
|
+
}
|
|
14755
|
+
}
|
|
14756
|
+
return false;
|
|
14757
|
+
}
|
|
14758
|
+
matchPattern(eventType, pattern) {
|
|
14759
|
+
if (pattern === "*")
|
|
14760
|
+
return true;
|
|
14761
|
+
if (pattern.endsWith(".*")) {
|
|
14762
|
+
const prefix = pattern.slice(0, -2);
|
|
14763
|
+
return eventType === prefix || eventType.startsWith(prefix + ".");
|
|
14764
|
+
}
|
|
14765
|
+
return eventType === pattern;
|
|
14766
|
+
}
|
|
14767
|
+
stop() {
|
|
14768
|
+
this.isStopped = true;
|
|
14769
|
+
if (this.unsubscribe) {
|
|
14770
|
+
this.unsubscribe();
|
|
14771
|
+
this.unsubscribe = null;
|
|
14772
|
+
}
|
|
14773
|
+
this.queue = [];
|
|
14774
|
+
this.isProcessing = false;
|
|
14775
|
+
this.clearActiveSession();
|
|
14776
|
+
}
|
|
14777
|
+
handleEvent(event) {
|
|
14778
|
+
if (this.isStopped) {
|
|
14779
|
+
return;
|
|
14780
|
+
}
|
|
14781
|
+
const formatted = this.formatter.formatWithEvent(event);
|
|
14782
|
+
this.enqueue(formatted);
|
|
14783
|
+
}
|
|
14784
|
+
enqueue(formattedEvent) {
|
|
14785
|
+
if (this.isStopped) {
|
|
14786
|
+
return;
|
|
14787
|
+
}
|
|
14788
|
+
this.queue.push(formattedEvent);
|
|
14789
|
+
if (!this.isProcessing) {
|
|
14790
|
+
this.processQueue();
|
|
14791
|
+
}
|
|
14792
|
+
}
|
|
14793
|
+
getQueueLength() {
|
|
14794
|
+
return this.queue.length;
|
|
14795
|
+
}
|
|
14796
|
+
isQueueEmpty() {
|
|
14797
|
+
return this.queue.length === 0;
|
|
14798
|
+
}
|
|
14799
|
+
async processQueue() {
|
|
14800
|
+
this.isProcessing = true;
|
|
14801
|
+
const sessionId = await this.ensureActiveSession();
|
|
14802
|
+
if (this.isStopped) {
|
|
14803
|
+
this.clearActiveSession();
|
|
14804
|
+
this.isProcessing = false;
|
|
14805
|
+
return;
|
|
14806
|
+
}
|
|
14807
|
+
while (!this.isStopped && this.queue.length > 0) {
|
|
14808
|
+
await this.waitForIdle();
|
|
14809
|
+
if (this.isStopped) {
|
|
14810
|
+
break;
|
|
14811
|
+
}
|
|
14812
|
+
const item = this.queue.shift();
|
|
14813
|
+
if (!item) {
|
|
14814
|
+
break;
|
|
14815
|
+
}
|
|
14816
|
+
if (sessionId) {
|
|
14817
|
+
item.eventSessionId = sessionId;
|
|
14818
|
+
}
|
|
14819
|
+
try {
|
|
14820
|
+
if (this.onEventWithEnv) {
|
|
14821
|
+
await this.onEventWithEnv(item);
|
|
14822
|
+
continue;
|
|
14823
|
+
}
|
|
14824
|
+
await this.onEvent(item.message);
|
|
14825
|
+
} catch (error) {
|
|
14826
|
+
console.error(`[EventHandler] 处理事件失败:`, error);
|
|
14827
|
+
}
|
|
14828
|
+
}
|
|
14829
|
+
this.isProcessing = false;
|
|
14830
|
+
}
|
|
14831
|
+
async ensureActiveSession() {
|
|
14832
|
+
if (!this.sessionComponent)
|
|
14833
|
+
return null;
|
|
14834
|
+
if (this.activeEventSessionId)
|
|
14835
|
+
return this.activeEventSessionId;
|
|
14836
|
+
const triggerSessionId = this.queue.map((item) => item.triggerSessionId).find((id) => !!id);
|
|
14837
|
+
if (triggerSessionId) {
|
|
14838
|
+
try {
|
|
14839
|
+
const existing = await this.sessionComponent.get(triggerSessionId);
|
|
14840
|
+
if (existing) {
|
|
14841
|
+
if (this.isStopped) {
|
|
14842
|
+
return null;
|
|
14843
|
+
}
|
|
14844
|
+
this.activeEventSessionId = existing.id;
|
|
14845
|
+
await this.sessionComponent.setActiveSession(existing.id);
|
|
14846
|
+
return existing.id;
|
|
14847
|
+
}
|
|
14848
|
+
console.warn(`[EventHandler] Parent session ${triggerSessionId} not found, trying global active session`);
|
|
14849
|
+
} catch (error) {
|
|
14850
|
+
console.error(`[EventHandler] Failed to lookup parent session ${triggerSessionId}:`, error);
|
|
14851
|
+
}
|
|
14852
|
+
}
|
|
14853
|
+
try {
|
|
14854
|
+
const activeId = this.sessionComponent.getActiveSessionId();
|
|
14855
|
+
if (activeId) {
|
|
14856
|
+
const existing = await this.sessionComponent.get(activeId);
|
|
14857
|
+
if (existing) {
|
|
14858
|
+
if (this.isStopped) {
|
|
14859
|
+
return null;
|
|
14860
|
+
}
|
|
14861
|
+
this.activeEventSessionId = existing.id;
|
|
14862
|
+
return existing.id;
|
|
14863
|
+
}
|
|
14864
|
+
}
|
|
14865
|
+
} catch (error) {
|
|
14866
|
+
console.error(`[EventHandler] Failed to lookup global active session:`, error);
|
|
14867
|
+
}
|
|
14868
|
+
return this.createNewEventSession();
|
|
14869
|
+
}
|
|
14870
|
+
async createNewEventSession() {
|
|
14871
|
+
try {
|
|
14872
|
+
const session = await this.sessionComponent.create({
|
|
14873
|
+
title: `Event Session - ${new Date().toLocaleString()}`
|
|
14874
|
+
});
|
|
14875
|
+
if (this.isStopped) {
|
|
14876
|
+
this.activeEventSessionId = null;
|
|
14877
|
+
return null;
|
|
14878
|
+
}
|
|
14879
|
+
this.activeEventSessionId = session.id;
|
|
14880
|
+
await this.sessionComponent.setActiveSession(session.id);
|
|
14881
|
+
return session.id;
|
|
14882
|
+
} catch (error) {
|
|
14883
|
+
console.error(`[EventHandler] 创建事件 session 失败:`, error);
|
|
14884
|
+
return null;
|
|
14885
|
+
}
|
|
14886
|
+
}
|
|
14887
|
+
clearActiveSession() {
|
|
14888
|
+
this.activeEventSessionId = null;
|
|
14889
|
+
}
|
|
14890
|
+
getActiveEventSessionId() {
|
|
14891
|
+
return this.activeEventSessionId;
|
|
14892
|
+
}
|
|
14893
|
+
async waitForIdle() {
|
|
14894
|
+
while (!this.isStopped && !this.isIdle()) {
|
|
14895
|
+
await this.sleep(this.idleCheckInterval);
|
|
14896
|
+
}
|
|
14897
|
+
}
|
|
14898
|
+
sleep(ms) {
|
|
14899
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
14900
|
+
}
|
|
14901
|
+
}
|
|
14902
|
+
__decorate3([
|
|
14903
|
+
TracedAs9("cli.event-handler.handleEvent", { recordParams: true })
|
|
14904
|
+
], EventHandler2.prototype, "handleEvent", null);
|
|
14905
|
+
|
|
14906
|
+
// src/commands/shared/task-event-handler.js
|
|
14907
|
+
import { createLogger as createLogger7 } from "@ai-setting/roy-agent-core";
|
|
14908
|
+
var logger6 = createLogger7("task-event-handler");
|
|
14909
|
+
var TASK_EVENTS2 = {
|
|
14910
|
+
CREATED: "task.created",
|
|
14911
|
+
UPDATED: "task.updated",
|
|
14912
|
+
COMPLETED: "task.completed",
|
|
14913
|
+
DELETED: "task.deleted",
|
|
14914
|
+
OPERATION_ADDED: "task.operation_added",
|
|
14915
|
+
DELEGATED: "task.delegated"
|
|
14916
|
+
};
|
|
14917
|
+
|
|
14918
|
+
class TaskEventHandler2 {
|
|
14919
|
+
env;
|
|
14920
|
+
enabled;
|
|
14921
|
+
unsubscribe = null;
|
|
14922
|
+
constructor(options) {
|
|
14923
|
+
this.env = options.env;
|
|
14924
|
+
this.enabled = options.enabled ?? true;
|
|
14925
|
+
}
|
|
14926
|
+
start() {
|
|
14927
|
+
if (!this.enabled) {
|
|
14928
|
+
return () => {};
|
|
14929
|
+
}
|
|
14930
|
+
this.unsubscribe = this.env.subscribeAll((event) => {
|
|
14931
|
+
if (event.type.startsWith("task.")) {
|
|
14932
|
+
this.handleEvent(event);
|
|
14933
|
+
}
|
|
14934
|
+
});
|
|
14935
|
+
logger6.info("[TaskEventHandler] Started");
|
|
14936
|
+
return () => this.stop();
|
|
14937
|
+
}
|
|
14938
|
+
stop() {
|
|
14939
|
+
if (this.unsubscribe) {
|
|
14940
|
+
this.unsubscribe();
|
|
14941
|
+
this.unsubscribe = null;
|
|
14942
|
+
logger6.info("[TaskEventHandler] Stopped");
|
|
14943
|
+
}
|
|
14944
|
+
}
|
|
14945
|
+
handleEvent(event) {
|
|
14946
|
+
const payload = event.payload;
|
|
14947
|
+
switch (event.type) {
|
|
14948
|
+
case TASK_EVENTS2.CREATED:
|
|
14949
|
+
this.logTaskCreated(payload);
|
|
14950
|
+
break;
|
|
14951
|
+
case TASK_EVENTS2.UPDATED:
|
|
14952
|
+
this.logTaskUpdated(payload);
|
|
14953
|
+
break;
|
|
14954
|
+
case TASK_EVENTS2.COMPLETED:
|
|
14955
|
+
this.logTaskCompleted(payload);
|
|
14956
|
+
break;
|
|
14957
|
+
case TASK_EVENTS2.DELETED:
|
|
14958
|
+
this.logTaskDeleted(payload);
|
|
14959
|
+
break;
|
|
14960
|
+
case TASK_EVENTS2.OPERATION_ADDED:
|
|
14961
|
+
this.logOperationAdded(payload);
|
|
14962
|
+
break;
|
|
14963
|
+
case TASK_EVENTS2.DELEGATED:
|
|
14964
|
+
this.logTaskDelegated(payload);
|
|
14965
|
+
break;
|
|
14966
|
+
default:
|
|
14967
|
+
logger6.info(`[${event.type}]`, payload);
|
|
14968
|
+
}
|
|
14969
|
+
}
|
|
14970
|
+
logTaskCreated(payload) {
|
|
14971
|
+
const task = payload.task;
|
|
14972
|
+
logger6.info(`\uD83D\uDCDD Task created: #${task.id} - ${task.title}`);
|
|
14973
|
+
logger6.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}`);
|
|
14974
|
+
if (task.project_path) {
|
|
14975
|
+
logger6.info(` Project: ${task.project_path}`);
|
|
14976
|
+
}
|
|
14977
|
+
if (task.context) {
|
|
14978
|
+
logger6.info(` Context: ${task.context}`);
|
|
14979
|
+
}
|
|
14980
|
+
}
|
|
14981
|
+
logTaskUpdated(payload) {
|
|
14982
|
+
const task = payload.task;
|
|
14983
|
+
const changes = payload.changes;
|
|
14984
|
+
logger6.info(`✏️ Task updated: #${task.id} - ${task.title}`);
|
|
14985
|
+
logger6.info(` Status: ${task.status}, Priority: ${task.priority}, Type: ${task.type || "normal"}, Progress: ${task.progress}%`);
|
|
14986
|
+
if (changes) {
|
|
14987
|
+
logger6.info(` Changes: ${JSON.stringify(changes)}`);
|
|
14988
|
+
}
|
|
14989
|
+
}
|
|
14990
|
+
logTaskCompleted(payload) {
|
|
14991
|
+
const task = payload.task;
|
|
14992
|
+
logger6.info(`✅ Task completed: #${task.id} - ${task.title}`);
|
|
14993
|
+
logger6.info(` Progress: ${task.progress}%, Updated: ${task.updatedAt}`);
|
|
14994
|
+
}
|
|
14995
|
+
logTaskDeleted(payload) {
|
|
14996
|
+
logger6.info(`\uD83D\uDDD1️ Task deleted: #${payload.taskId}`);
|
|
14997
|
+
}
|
|
14998
|
+
logOperationAdded(payload) {
|
|
14999
|
+
const op = payload.operation;
|
|
15000
|
+
logger6.info(`\uD83D\uDCCB Operation added to task #${payload.taskId}:`);
|
|
15001
|
+
logger6.info(` [${op.milestoneType}] ${op.milestoneTitle}`);
|
|
15002
|
+
logger6.info(` Session: ${op.sessionId}`);
|
|
15003
|
+
}
|
|
15004
|
+
logTaskDelegated(payload) {
|
|
15005
|
+
logger6.info(`\uD83D\uDE80 Task delegated: #${payload.taskId}`);
|
|
15006
|
+
logger6.info(` Background: ${payload.backgroundTaskId}, Type: ${payload.subagentType}`);
|
|
15007
|
+
logger6.info(` ${payload.description}`);
|
|
15008
|
+
}
|
|
15009
|
+
}
|
|
15010
|
+
|
|
15011
|
+
// src/commands/shared/event-message-formatter.js
|
|
15012
|
+
var TaskEventTypes2 = {
|
|
15013
|
+
TASK_STARTED: "task.background.started",
|
|
15014
|
+
TASK_PROGRESS: "task.background.progress",
|
|
15015
|
+
TASK_COMPLETED: "task.background.completed",
|
|
15016
|
+
TASK_FAILED: "task.background.failed",
|
|
15017
|
+
TASK_TIMEOUT: "task.background.timeout",
|
|
15018
|
+
TASK_STOPPED: "task.background.stopped",
|
|
15019
|
+
TASK_ASK_USER: "task.background.ask_user"
|
|
15020
|
+
};
|
|
15021
|
+
var EventSourceEventTypes2 = {
|
|
15022
|
+
EVENT_SOURCE_STARTED: "event-source.started",
|
|
15023
|
+
EVENT_SOURCE_STOPPED: "event-source.stopped",
|
|
15024
|
+
EVENT_SOURCE_EVENT_PREFIX: "event-source.event."
|
|
15025
|
+
};
|
|
15026
|
+
|
|
15027
|
+
class EventMessageFormatter2 {
|
|
15028
|
+
prefix;
|
|
15029
|
+
showTimestamp;
|
|
15030
|
+
constructor(options = {}) {
|
|
15031
|
+
this.prefix = options.prefix ?? "[通知]";
|
|
15032
|
+
this.showTimestamp = options.showTimestamp ?? false;
|
|
15033
|
+
}
|
|
15034
|
+
format(event) {
|
|
15035
|
+
const { type, payload } = event;
|
|
15036
|
+
switch (type) {
|
|
15037
|
+
case TaskEventTypes2.TASK_STARTED:
|
|
15038
|
+
return this.formatTaskStarted(payload);
|
|
15039
|
+
case TaskEventTypes2.TASK_PROGRESS:
|
|
15040
|
+
return this.formatTaskProgress(payload);
|
|
15041
|
+
case TaskEventTypes2.TASK_COMPLETED:
|
|
15042
|
+
return this.formatTaskCompleted(payload);
|
|
15043
|
+
case TaskEventTypes2.TASK_FAILED:
|
|
15044
|
+
return this.formatTaskFailed(payload);
|
|
15045
|
+
case TaskEventTypes2.TASK_TIMEOUT:
|
|
15046
|
+
return this.formatTaskTimeout(payload);
|
|
15047
|
+
case TaskEventTypes2.TASK_STOPPED:
|
|
15048
|
+
return this.formatTaskStopped(payload);
|
|
15049
|
+
case TaskEventTypes2.TASK_ASK_USER:
|
|
15050
|
+
return this.formatTaskAskUser(payload);
|
|
15051
|
+
case EventSourceEventTypes2.EVENT_SOURCE_STARTED:
|
|
15052
|
+
return this.formatEventSourceStarted(payload);
|
|
15053
|
+
case EventSourceEventTypes2.EVENT_SOURCE_STOPPED:
|
|
15054
|
+
return this.formatEventSourceStopped(payload);
|
|
15055
|
+
default:
|
|
15056
|
+
if (type.startsWith(EventSourceEventTypes2.EVENT_SOURCE_EVENT_PREFIX)) {
|
|
15057
|
+
return this.formatEventSourceEvent(event);
|
|
15058
|
+
}
|
|
15059
|
+
return this.formatGeneric(event);
|
|
15060
|
+
}
|
|
15061
|
+
}
|
|
15062
|
+
formatTaskStarted(payload) {
|
|
15063
|
+
const desc = payload.description || "未命名任务";
|
|
15064
|
+
return `${this.prefix} \uD83D\uDCE2 后台任务「${desc}」已启动`;
|
|
15065
|
+
}
|
|
15066
|
+
formatTaskProgress(payload) {
|
|
15067
|
+
const desc = payload.description || "未命名任务";
|
|
15068
|
+
const message = payload.progressMessage || "";
|
|
15069
|
+
const taskId = payload.associatedTaskId;
|
|
15070
|
+
let result = `${this.prefix} \uD83D\uDD04 后台任务「${desc}」`;
|
|
15071
|
+
if (taskId !== undefined) {
|
|
15072
|
+
result += `[Task #${taskId}] `;
|
|
15073
|
+
}
|
|
15074
|
+
result += `还在进行中,请耐心等待。需查询具体进度可调用 task_get / task_operation_list 等工具`;
|
|
15075
|
+
if (message)
|
|
15076
|
+
result += ` - ${message}`;
|
|
15077
|
+
return result;
|
|
15078
|
+
}
|
|
15079
|
+
formatTaskCompleted(payload) {
|
|
15080
|
+
const desc = payload.description || "未命名任务";
|
|
15081
|
+
const result = payload.result;
|
|
15082
|
+
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15083
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
15084
|
+
const taskId = payload.associatedTaskId;
|
|
15085
|
+
let message = `${this.prefix} ✅ 后台任务「${desc}」已完成 ${time}`;
|
|
15086
|
+
if (bgProcessId) {
|
|
15087
|
+
message += `
|
|
15088
|
+
bgprocess: ${bgProcessId}`;
|
|
15089
|
+
}
|
|
15090
|
+
if (taskId !== undefined) {
|
|
15091
|
+
message += `
|
|
15092
|
+
Task #${taskId}`;
|
|
15093
|
+
}
|
|
15094
|
+
if (result) {
|
|
15095
|
+
message += `
|
|
15096
|
+
结果: ${result}`;
|
|
15097
|
+
}
|
|
15098
|
+
message += this.appendSubSessionId(payload);
|
|
15099
|
+
return message;
|
|
15100
|
+
}
|
|
15101
|
+
formatTaskFailed(payload) {
|
|
15102
|
+
const desc = payload.description || "未命名任务";
|
|
15103
|
+
const error = payload.error || "未知错误";
|
|
15104
|
+
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15105
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
15106
|
+
const taskId = payload.associatedTaskId;
|
|
15107
|
+
let message = `${this.prefix} ❌ 后台任务「${desc}」失败 ${time}`;
|
|
15108
|
+
if (bgProcessId) {
|
|
15109
|
+
message += `
|
|
15110
|
+
bgprocess: ${bgProcessId}`;
|
|
15111
|
+
}
|
|
15112
|
+
if (taskId !== undefined) {
|
|
15113
|
+
message += `
|
|
15114
|
+
Task #${taskId}`;
|
|
15115
|
+
}
|
|
15116
|
+
if (error) {
|
|
15117
|
+
const truncatedError = error.length > 100 ? error.substring(0, 100) + "..." : error;
|
|
15118
|
+
message += `
|
|
15119
|
+
错误: ${truncatedError}`;
|
|
15120
|
+
}
|
|
15121
|
+
message += this.appendSubSessionId(payload);
|
|
15122
|
+
return message;
|
|
15123
|
+
}
|
|
15124
|
+
formatTaskTimeout(payload) {
|
|
15125
|
+
const desc = payload.description || "未命名任务";
|
|
15126
|
+
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15127
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
15128
|
+
const taskId = payload.associatedTaskId;
|
|
15129
|
+
let message = `${this.prefix} ⏱️ 后台任务「${desc}」超时 ${time}`;
|
|
15130
|
+
if (bgProcessId) {
|
|
15131
|
+
message += `
|
|
15132
|
+
bgprocess: ${bgProcessId}`;
|
|
15133
|
+
}
|
|
15134
|
+
if (taskId !== undefined) {
|
|
15135
|
+
message += `
|
|
15136
|
+
Task #${taskId}`;
|
|
15137
|
+
}
|
|
15138
|
+
message += this.appendSubSessionId(payload);
|
|
15139
|
+
return message;
|
|
15140
|
+
}
|
|
15141
|
+
formatTaskStopped(payload) {
|
|
15142
|
+
const desc = payload.description || "未命名任务";
|
|
15143
|
+
const time = payload.executionTimeMs ? `(${this.formatDuration(payload.executionTimeMs)})` : "";
|
|
15144
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
15145
|
+
const taskId = payload.associatedTaskId;
|
|
15146
|
+
let message = `${this.prefix} \uD83D\uDED1 后台任务「${desc}」已停止 ${time}`;
|
|
15147
|
+
if (bgProcessId) {
|
|
15148
|
+
message += `
|
|
15149
|
+
bgprocess: ${bgProcessId}`;
|
|
15150
|
+
}
|
|
15151
|
+
if (taskId !== undefined) {
|
|
15152
|
+
message += `
|
|
15153
|
+
Task #${taskId}`;
|
|
15154
|
+
}
|
|
15155
|
+
message += this.appendSubSessionId(payload);
|
|
15156
|
+
return message;
|
|
15157
|
+
}
|
|
15158
|
+
formatTaskAskUser(payload) {
|
|
15159
|
+
const desc = payload.description || "未命名任务";
|
|
15160
|
+
const bgProcessId = payload.backgroundTaskId || "";
|
|
15161
|
+
const subSessionId = payload.subSessionId || "";
|
|
15162
|
+
const query = payload.query || "(空问题)";
|
|
15163
|
+
let message = `${this.prefix} ❓ 后台子代理「${desc}」请求用户输入`;
|
|
15164
|
+
if (bgProcessId) {
|
|
15165
|
+
message += `
|
|
15166
|
+
bgprocess: ${bgProcessId}`;
|
|
15167
|
+
}
|
|
15168
|
+
if (subSessionId) {
|
|
15169
|
+
message += `
|
|
15170
|
+
subSessionId: ${subSessionId}`;
|
|
15171
|
+
}
|
|
15172
|
+
message += `
|
|
15173
|
+
|
|
15174
|
+
${query}`;
|
|
15175
|
+
if (payload.hints && payload.hints.length > 0) {
|
|
15176
|
+
message += `
|
|
15177
|
+
|
|
15178
|
+
[\uD83E\uDD16 Agent 操作提示]`;
|
|
15179
|
+
for (const hint of payload.hints) {
|
|
15180
|
+
message += `
|
|
15181
|
+
${hint}`;
|
|
15182
|
+
}
|
|
15183
|
+
}
|
|
15184
|
+
return message;
|
|
15185
|
+
}
|
|
15186
|
+
appendSubSessionId(payload) {
|
|
15187
|
+
if (payload.subSessionId) {
|
|
15188
|
+
return `
|
|
15189
|
+
subSessionId: ${payload.subSessionId}`;
|
|
15190
|
+
}
|
|
15191
|
+
return "";
|
|
15192
|
+
}
|
|
15193
|
+
formatGeneric(event) {
|
|
15194
|
+
return `${this.prefix} 收到事件: ${event.type}`;
|
|
15195
|
+
}
|
|
15196
|
+
formatEventSourceStarted(payload) {
|
|
15197
|
+
return `${this.prefix} \uD83D\uDCE1 事件源「${payload.sourceId}」(类型: ${payload.sourceType}) 已启动`;
|
|
15198
|
+
}
|
|
15199
|
+
formatEventSourceStopped(payload) {
|
|
15200
|
+
return `${this.prefix} \uD83D\uDCE1 事件源「${payload.sourceId}」(类型: ${payload.sourceType}) 已停止`;
|
|
15201
|
+
}
|
|
15202
|
+
formatEventSourceEvent(event) {
|
|
15203
|
+
const payload = event.payload;
|
|
15204
|
+
const sourceType = payload?.sourceType || "unknown";
|
|
15205
|
+
const message = payload?.message || "";
|
|
15206
|
+
if (message) {
|
|
15207
|
+
return `[${sourceType}] ${message}`;
|
|
15208
|
+
}
|
|
15209
|
+
return `[${sourceType}] ${JSON.stringify(payload, null, 2)}`;
|
|
15210
|
+
}
|
|
15211
|
+
formatDuration(ms) {
|
|
15212
|
+
if (ms < 1000)
|
|
15213
|
+
return `${ms}ms`;
|
|
15214
|
+
if (ms < 60000)
|
|
15215
|
+
return `${(ms / 1000).toFixed(1)}秒`;
|
|
15216
|
+
const minutes = Math.floor(ms / 60000);
|
|
15217
|
+
const seconds = Math.floor(ms % 60000 / 1000);
|
|
15218
|
+
return `${minutes}分${seconds}秒`;
|
|
15219
|
+
}
|
|
15220
|
+
formatWithEvent(event) {
|
|
15221
|
+
const triggerSessionId = extractTriggerSessionId2(event);
|
|
15222
|
+
return {
|
|
15223
|
+
message: this.format(event),
|
|
15224
|
+
envEvent: event,
|
|
15225
|
+
triggerSessionId
|
|
15226
|
+
};
|
|
15227
|
+
}
|
|
15228
|
+
}
|
|
15229
|
+
function extractTriggerSessionId2(event) {
|
|
15230
|
+
const triggerSessionId = event?.metadata?.trigger_session_id;
|
|
15231
|
+
if (typeof triggerSessionId === "string" && triggerSessionId.length > 0) {
|
|
15232
|
+
return triggerSessionId;
|
|
15233
|
+
}
|
|
15234
|
+
return;
|
|
15235
|
+
}
|
|
15236
|
+
|
|
15237
|
+
// src/commands/lifecycle.js
|
|
15238
|
+
var DEFAULT_LOGGER2 = {
|
|
15239
|
+
warn: (msg) => console.error(`[shutdown] ${msg}`)
|
|
15240
|
+
};
|
|
15241
|
+
function registerShutdownHandlers2(cleanup, options = {}) {
|
|
15242
|
+
const logger7 = options.logger ?? DEFAULT_LOGGER2;
|
|
15243
|
+
const exitCode = options.exitCode ?? 0;
|
|
15244
|
+
const shutdownMessage = options.shutdownMessage ?? "Cleaning up...";
|
|
15245
|
+
let shuttingDown = false;
|
|
15246
|
+
const shutdown = async (signal) => {
|
|
15247
|
+
if (shuttingDown) {
|
|
15248
|
+
return;
|
|
15249
|
+
}
|
|
15250
|
+
shuttingDown = true;
|
|
15251
|
+
try {
|
|
15252
|
+
logger7.debug?.(`[${signal}] ${shutdownMessage}`);
|
|
15253
|
+
} catch {}
|
|
15254
|
+
if (cleanup) {
|
|
15255
|
+
try {
|
|
15256
|
+
await cleanup();
|
|
15257
|
+
} catch (err) {
|
|
15258
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
15259
|
+
try {
|
|
15260
|
+
logger7.warn(`Cleanup failed: ${message}`);
|
|
15261
|
+
} catch {
|
|
15262
|
+
try {
|
|
15263
|
+
process.stderr.write(`[shutdown] Cleanup failed: ${message}
|
|
15264
|
+
`);
|
|
15265
|
+
} catch {}
|
|
15266
|
+
}
|
|
15267
|
+
}
|
|
15268
|
+
}
|
|
15269
|
+
try {
|
|
15270
|
+
process.exit(exitCode);
|
|
15271
|
+
} catch {}
|
|
15272
|
+
};
|
|
15273
|
+
process.on("SIGINT", shutdown);
|
|
15274
|
+
process.on("SIGTERM", shutdown);
|
|
15275
|
+
return {
|
|
15276
|
+
dispose: () => {
|
|
15277
|
+
process.removeListener("SIGINT", shutdown);
|
|
15278
|
+
process.removeListener("SIGTERM", shutdown);
|
|
15279
|
+
}
|
|
15280
|
+
};
|
|
15281
|
+
}
|
|
15282
|
+
|
|
15283
|
+
// src/commands/run-shutdown.js
|
|
15284
|
+
import { TempFileManager as TempFileManager3 } from "@ai-setting/roy-agent-core/utils/temp-file-manager";
|
|
15285
|
+
async function shutdownRunSteps(deps) {
|
|
15286
|
+
const { lspManagerDispose, pluginAdapterDispose, stopEventHandler, stopTaskEventHandler, queryExecutor, env, envService, shouldDisposeEnvService, output, logger: logger7 } = deps;
|
|
14274
15287
|
try {
|
|
14275
15288
|
stopEventHandler();
|
|
14276
15289
|
} catch (err) {
|
|
14277
|
-
|
|
15290
|
+
logger7?.warn?.(`[Shutdown] EventHandler.stop failed: ${err}`);
|
|
14278
15291
|
}
|
|
14279
15292
|
try {
|
|
14280
15293
|
stopTaskEventHandler();
|
|
14281
15294
|
} catch (err) {
|
|
14282
|
-
|
|
15295
|
+
logger7?.warn?.(`[Shutdown] TaskEventHandler.stop failed: ${err}`);
|
|
14283
15296
|
}
|
|
14284
15297
|
if (lspManagerDispose) {
|
|
14285
15298
|
try {
|
|
14286
15299
|
await lspManagerDispose();
|
|
14287
15300
|
} catch (err) {
|
|
14288
|
-
|
|
15301
|
+
logger7?.warn?.(`[Shutdown] LSP Manager dispose failed: ${err}`);
|
|
14289
15302
|
}
|
|
14290
15303
|
}
|
|
14291
15304
|
if (pluginAdapterDispose) {
|
|
14292
15305
|
try {
|
|
14293
15306
|
await pluginAdapterDispose();
|
|
14294
15307
|
} catch (err) {
|
|
14295
|
-
|
|
15308
|
+
logger7?.warn?.(`[Shutdown] PluginAdapter dispose failed: ${err}`);
|
|
14296
15309
|
}
|
|
14297
15310
|
}
|
|
14298
15311
|
try {
|
|
14299
15312
|
queryExecutor.dispose();
|
|
14300
15313
|
} catch (err) {
|
|
14301
|
-
|
|
15314
|
+
logger7?.warn?.(`[Shutdown] QueryExecutor.dispose failed: ${err}`);
|
|
14302
15315
|
}
|
|
14303
15316
|
try {
|
|
14304
15317
|
const eventSourceComponent = env.getComponent("event-source");
|
|
@@ -14307,7 +15320,7 @@ async function shutdownRunSteps(deps) {
|
|
|
14307
15320
|
if (sources && sources.length > 0) {
|
|
14308
15321
|
for (const source of sources) {
|
|
14309
15322
|
const status = eventSourceComponent.getStatus?.(source.id);
|
|
14310
|
-
|
|
15323
|
+
logger7?.debug?.(`[Shutdown] 检查事件源: ${source.id}, 状态: ${status}`);
|
|
14311
15324
|
if (status !== "stopped" && status !== "created") {
|
|
14312
15325
|
try {
|
|
14313
15326
|
await eventSourceComponent.stopSource(source.id);
|
|
@@ -14320,20 +15333,20 @@ async function shutdownRunSteps(deps) {
|
|
|
14320
15333
|
}
|
|
14321
15334
|
}
|
|
14322
15335
|
} catch (err) {
|
|
14323
|
-
|
|
15336
|
+
logger7?.warn?.(`[Shutdown] EventSource cleanup failed: ${err}`);
|
|
14324
15337
|
}
|
|
14325
15338
|
if (shouldDisposeEnvService) {
|
|
14326
15339
|
try {
|
|
14327
15340
|
await envService.dispose();
|
|
14328
15341
|
} catch (err) {
|
|
14329
|
-
|
|
15342
|
+
logger7?.warn?.(`[Shutdown] envService.dispose failed: ${err}`);
|
|
14330
15343
|
}
|
|
14331
15344
|
}
|
|
14332
15345
|
try {
|
|
14333
15346
|
await TempFileManager3.getInstance().cleanupAll();
|
|
14334
|
-
|
|
15347
|
+
logger7?.debug?.("[Shutdown] TempFileManager cleaned up");
|
|
14335
15348
|
} catch (err) {
|
|
14336
|
-
|
|
15349
|
+
logger7?.warn?.(`[Shutdown] TempFileManager cleanup failed: ${err}`);
|
|
14337
15350
|
}
|
|
14338
15351
|
}
|
|
14339
15352
|
|
|
@@ -14359,14 +15372,14 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14359
15372
|
if (!sessionComponent) {
|
|
14360
15373
|
throw new Error("Failed to create session component");
|
|
14361
15374
|
}
|
|
14362
|
-
const sessionManager = new
|
|
15375
|
+
const sessionManager = new SessionManager2({
|
|
14363
15376
|
sessionComponent,
|
|
14364
15377
|
output,
|
|
14365
15378
|
quiet: true
|
|
14366
15379
|
});
|
|
14367
15380
|
const sessionResult = await sessionManager.init(options.session, options.continue);
|
|
14368
15381
|
const sessionId = sessionResult.sessionId;
|
|
14369
|
-
const queryExecutor = new
|
|
15382
|
+
const queryExecutor = new QueryExecutor2({
|
|
14370
15383
|
env,
|
|
14371
15384
|
sessionComponent,
|
|
14372
15385
|
output,
|
|
@@ -14376,13 +15389,13 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14376
15389
|
let agentContext = undefined;
|
|
14377
15390
|
if (options.agent && options.agent !== "default") {
|
|
14378
15391
|
const agentComponent = env.getComponent("agent");
|
|
14379
|
-
const validation =
|
|
15392
|
+
const validation = validateActAgent2(agentComponent, options.agent);
|
|
14380
15393
|
if (!validation.valid) {
|
|
14381
15394
|
output.error(validation.message);
|
|
14382
15395
|
output.info("提示: roy-agent agents list");
|
|
14383
15396
|
process.exit(1);
|
|
14384
15397
|
}
|
|
14385
|
-
agentContext =
|
|
15398
|
+
agentContext = buildActAgentContext2(options.agent);
|
|
14386
15399
|
}
|
|
14387
15400
|
let eventSourceSystemPrompt;
|
|
14388
15401
|
const rawEventSourceIds = options.eventSource;
|
|
@@ -14394,9 +15407,9 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14394
15407
|
output.info("请确保 EventSourceComponent 已正确注册");
|
|
14395
15408
|
process.exit(1);
|
|
14396
15409
|
}
|
|
14397
|
-
const summary = await
|
|
14398
|
-
const preloadedPrompts =
|
|
14399
|
-
eventSourceSystemPrompt = preloadedPrompts.length > 0 ?
|
|
15410
|
+
const summary = await startEventSources2(eventSourceIds, eventSourceComponent, output);
|
|
15411
|
+
const preloadedPrompts = collectEventSourceSystemPrompts2(eventSourceIds, eventSourceComponent);
|
|
15412
|
+
eventSourceSystemPrompt = preloadedPrompts.length > 0 ? joinResolvedSystemPrompts2(preloadedPrompts) : undefined;
|
|
14400
15413
|
if (eventSourceIds.length === 1 && summary.failedCount > 0) {
|
|
14401
15414
|
process.exit(1);
|
|
14402
15415
|
}
|
|
@@ -14420,14 +15433,14 @@ async function loadHandleQuery(options, hooks) {
|
|
|
14420
15433
|
}, undefined, mergedContext);
|
|
14421
15434
|
return String(result ?? "");
|
|
14422
15435
|
};
|
|
14423
|
-
const taskEventHandler = new
|
|
15436
|
+
const taskEventHandler = new TaskEventHandler2({
|
|
14424
15437
|
env,
|
|
14425
15438
|
enabled: true
|
|
14426
15439
|
});
|
|
14427
|
-
const eventHandler = new
|
|
15440
|
+
const eventHandler = new EventHandler2({
|
|
14428
15441
|
env,
|
|
14429
15442
|
eventTypes: ["task.background.*", "event-source.event.*"],
|
|
14430
|
-
formatter: new
|
|
15443
|
+
formatter: new EventMessageFormatter2({ prefix: "[通知]" }),
|
|
14431
15444
|
isIdle: hooks?.isIdle ?? (() => true),
|
|
14432
15445
|
sessionComponent,
|
|
14433
15446
|
onEvent: async (_message) => {},
|
|
@@ -14577,7 +15590,7 @@ function createRunCommand() {
|
|
|
14577
15590
|
isIdle: () => runState.isIdle(),
|
|
14578
15591
|
onNotification: (msg, envEvent) => runState.onNotification(msg, envEvent)
|
|
14579
15592
|
});
|
|
14580
|
-
const shutdownHandle =
|
|
15593
|
+
const shutdownHandle = registerShutdownHandlers2(async () => {
|
|
14581
15594
|
await shutdownRunSteps({
|
|
14582
15595
|
lspManagerDispose: null,
|
|
14583
15596
|
pluginAdapterDispose: null,
|
|
@@ -14594,7 +15607,7 @@ function createRunCommand() {
|
|
|
14594
15607
|
const streamHandleQuery = createStreamHandleQuery(queryExecutor, sessionId, argv, agentContext, eventSourceSystemPrompt);
|
|
14595
15608
|
const stopEventHandler = eventHandler.start();
|
|
14596
15609
|
const stopTaskEventHandler = taskEventHandler.start();
|
|
14597
|
-
const { waitUntilExit } = render(
|
|
15610
|
+
const { waitUntilExit } = render(React9.createElement(RunTui_default, {
|
|
14598
15611
|
handleQuery,
|
|
14599
15612
|
streamHandleQuery,
|
|
14600
15613
|
model: argv.model,
|
|
@@ -14631,23 +15644,15 @@ function createRunCommand() {
|
|
|
14631
15644
|
var RunCommand = createRunCommand();
|
|
14632
15645
|
|
|
14633
15646
|
// src/commands/chat.ts
|
|
14634
|
-
import
|
|
15647
|
+
import React11 from "react";
|
|
14635
15648
|
import { render as render2 } from "ink";
|
|
14636
15649
|
|
|
14637
|
-
// src/ChatTui.
|
|
14638
|
-
import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
15650
|
+
// src/ChatTui.js
|
|
15651
|
+
import React10, { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
|
|
14639
15652
|
import { Box as Box7, useApp as useApp3 } from "ink";
|
|
14640
15653
|
init_markdown();
|
|
14641
15654
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
14642
|
-
var ChatScreen = ({
|
|
14643
|
-
handleQuery,
|
|
14644
|
-
streamHandleQuery,
|
|
14645
|
-
message,
|
|
14646
|
-
model,
|
|
14647
|
-
workdir,
|
|
14648
|
-
maxLines,
|
|
14649
|
-
markdownEnabled: markdownEnabled2
|
|
14650
|
-
}) => {
|
|
15655
|
+
var ChatScreen = ({ handleQuery, streamHandleQuery, message, model, workdir, maxLines, markdownEnabled: markdownEnabled2 }) => {
|
|
14651
15656
|
const [history, setHistory] = useState7([
|
|
14652
15657
|
{ role: "user", content: message, id: "h-init-1" }
|
|
14653
15658
|
]);
|
|
@@ -14782,7 +15787,7 @@ function createChatCommand() {
|
|
|
14782
15787
|
}
|
|
14783
15788
|
const maxLines = Number.parseInt(argv.maxLines ?? "500", 10);
|
|
14784
15789
|
const handleQuery = await loadHandleQuery2(argv);
|
|
14785
|
-
const { waitUntilExit } = render2(
|
|
15790
|
+
const { waitUntilExit } = render2(React11.createElement(ChatTui_default, {
|
|
14786
15791
|
handleQuery,
|
|
14787
15792
|
message: argv.message,
|
|
14788
15793
|
model: argv.model,
|
|
@@ -23739,7 +24744,7 @@ var WorkflowAddCommand = {
|
|
|
23739
24744
|
process.exit(1);
|
|
23740
24745
|
}
|
|
23741
24746
|
if (!agentComponent.getAgent("workflow-extract")) {
|
|
23742
|
-
output.error("Built-in 'workflow-extract' agent is not available. ");
|
|
24747
|
+
output.error("Built-in 'workflow-extract' agent is not available. This usually means the environment was not fully initialized.");
|
|
23743
24748
|
process.exit(1);
|
|
23744
24749
|
}
|
|
23745
24750
|
const prompt = `## 任务
|
|
@@ -25743,7 +26748,7 @@ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync
|
|
|
25743
26748
|
import { join as join6, resolve } from "node:path";
|
|
25744
26749
|
import { homedir as homedir4 } from "node:os";
|
|
25745
26750
|
|
|
25746
|
-
// src/commands/install/cleanup-stale-plugin-copies.
|
|
26751
|
+
// src/commands/install/cleanup-stale-plugin-copies.js
|
|
25747
26752
|
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, cpSync } from "node:fs";
|
|
25748
26753
|
import { join as join5 } from "node:path";
|
|
25749
26754
|
import { homedir as nodeHomedir, tmpdir as nodeTmpdir } from "node:os";
|