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