feat(proxy): 新增全局出口代理配置
所有目标流量可经统一的全局代理出网(http/https/socks5,支持 user:pass): - 开启流量捕获时,作为 MITM 记录代理的上游(流量照录再经代理出网); 拦截与透传两条路径都走上游,不泄露源 IP。 - 关闭捕获时,直接注入 agent 的 bash 环境与 WebFetch;proxyEnv 增加 ALL_PROXY 以支持 socks5。 配置存于 settings KV 表(无需迁移),前端系统配置页新增「全局代理」卡片。 与网络搜索代理、LLM 代理相互独立。
This commit is contained in:
1 parent
651b961ffc
commit
b513b656aa
10 files changed
+349
-34
No files matched your search
@@ -26,6 +26,8 @@ export default function SystemSettingsPage() {
|
||||
const [savingTavilyKey, setSavingTavilyKey] = React.useState(false);
|
||||
const [proxyInput, setProxyInput] = React.useState("");
|
||||
const [savingProxy, setSavingProxy] = React.useState(false);
|
||||
const [globalProxyInput, setGlobalProxyInput] = React.useState("");
|
||||
const [savingGlobalProxy, setSavingGlobalProxy] = React.useState(false);
|
||||
const [testing, setTesting] = React.useState(false);
|
||||
const [loaded, setLoaded] = React.useState(false);
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
@@ -46,6 +48,7 @@ export default function SystemSettingsPage() {
|
||||
setBraveKeySet(!!s.brave_key_set);
|
||||
setTavilyKeySet(!!s.tavily_key_set);
|
||||
setProxyInput(s.web_search_proxy || "");
|
||||
setGlobalProxyInput(s.global_proxy || "");
|
||||
setPyInterp(s.python_interpreter || "");
|
||||
setWorkers(String(s.workers ?? 3));
|
||||
setInjectPlanner(s.constraints_inject_planner !== false);
|
||||
@@ -180,6 +183,18 @@ export default function SystemSettingsPage() {
|
||||
.finally(() => setSavingProxy(false));
|
||||
};
|
||||
|
||||
const saveGlobalProxy = () => {
|
||||
setSavingGlobalProxy(true);
|
||||
api
|
||||
.setSettings({ global_proxy: globalProxyInput.trim() })
|
||||
.then((s) => {
|
||||
apply(s);
|
||||
toast.success(globalProxyInput.trim() ? "已保存全局代理" : "已清除全局代理(改为直连)");
|
||||
})
|
||||
.catch((e) => toast.error("保存失败:" + (e as Error).message))
|
||||
.finally(() => setSavingGlobalProxy(false));
|
||||
};
|
||||
|
||||
// Run a real "test" search ("test") against the CURRENT form values (backend +
|
||||
// proxy + entered key), falling back to saved values server-side. Toasts result.
|
||||
const runTest = () => {
|
||||
@@ -241,6 +256,48 @@ export default function SystemSettingsPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="mb-4 break-inside-avoid md:mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-base">
|
||||
<RadioTowerIcon className="size-4" />
|
||||
全局代理
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
所有 Agent 的<b>目标流量</b>经此代理出网(隐藏源 IP / 走跳板)。支持 <b>http / https / socks5</b>,可带{" "}
|
||||
<code>user:pass</code> 认证。留空=直连。
|
||||
<br />
|
||||
开启<b>流量捕获</b>时,它作为记录代理的<b>上游</b>(流量仍全量落库,再经此代理出网);关闭捕获时,直接注入
|
||||
Agent 的 bash / WebFetch 出网。与网络搜索代理、LLM 代理相互独立。
|
||||
<br />
|
||||
<b>提示</b>:socks5 在<b>关闭捕获</b>时依赖各命令行工具对 <code>ALL_PROXY</code> 的支持(curl 可用,部分工具可能忽略);
|
||||
若主要用 socks5,建议开启流量捕获——此路径由 MITM 亲自拨号,工具无感知、稳定生效。
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-2">
|
||||
<Label htmlFor="global-proxy" className="text-sm font-normal text-muted-foreground">
|
||||
代理地址
|
||||
</Label>
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
id="global-proxy"
|
||||
autoComplete="off"
|
||||
placeholder="socks5://user:pass@host:1080 或 http://host:port(留空=直连)"
|
||||
value={globalProxyInput}
|
||||
disabled={!loaded || savingGlobalProxy}
|
||||
onChange={(e) => setGlobalProxyInput(e.target.value)}
|
||||
/>
|
||||
<Button type="button" onClick={saveGlobalProxy} disabled={!loaded || savingGlobalProxy}>
|
||||
保存
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{globalProxyInput.trim()
|
||||
? "已配置 · 所有目标流量经此代理出网"
|
||||
: "未配置 · 目标流量直连出网"}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="mb-4 break-inside-avoid md:mb-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-base">
|
||||
|
||||
@@ -3315,6 +3315,7 @@ export const settings: Settings = {
|
||||
brave_key_set: false,
|
||||
tavily_key_set: true,
|
||||
web_search_proxy: "",
|
||||
global_proxy: "",
|
||||
python_interpreter: "/usr/bin/python3",
|
||||
workers: 3,
|
||||
llm_pool_enabled: true,
|
||||
|
||||
@@ -866,6 +866,9 @@ export interface Settings {
|
||||
tavily_search_api_key?: string;
|
||||
// 独立出口代理(http/https/socks5),用于访问搜索端点;与记录流量的 MITM 代理无关。空=直连。
|
||||
web_search_proxy?: string;
|
||||
// 全局出口代理(http/https/socks5,可带 user:pass),所有目标流量走它。开启流量捕获时作为
|
||||
// MITM 上游;关闭捕获时直接注入 agent 的 bash/WebFetch。空=直连。
|
||||
global_proxy?: string;
|
||||
python_interpreter?: string; // 自定义脚本工具的 python 解释器路径(空=运行时检测)
|
||||
workers?: number; // 并发工作 agent 数(默认3);对之后启动的任务生效
|
||||
// 任务并发上限:同时「运行中」的任务数上限。关闭=不限;开启后新建任务超限则排队,有空位自动启动。
|
||||
|
||||
Reference in new issue
Block a user