Resolve merge conflicts
This commit is contained in:
1 parent
e96cc97462
commit
22be6325a8
3 files changed
+53
-35
No files matched your search
@@ -7,7 +7,7 @@ import {
|
|||||||
Settings2Icon,
|
Settings2Icon,
|
||||||
Trash2Icon,
|
Trash2Icon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -28,8 +28,7 @@ import {
|
|||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import { useAgents } from "@/core/agents/hooks";
|
import { useAgentSelector } from "@/core/agents/hooks";
|
||||||
import { getStoredAuth } from "@/core/auth";
|
|
||||||
import {
|
import {
|
||||||
useCreateCustomPrompt,
|
useCreateCustomPrompt,
|
||||||
useCustomPrompts,
|
useCustomPrompts,
|
||||||
@@ -165,10 +164,9 @@ function ManagePromptsDialog({
|
|||||||
const createPrompt = useCreateCustomPrompt();
|
const createPrompt = useCreateCustomPrompt();
|
||||||
const updatePrompt = useUpdateCustomPrompt();
|
const updatePrompt = useUpdateCustomPrompt();
|
||||||
const deletePrompt = useDeleteCustomPrompt();
|
const deletePrompt = useDeleteCustomPrompt();
|
||||||
const { agents } = useAgents();
|
const { agents } = useAgentSelector();
|
||||||
const preferences = useUserPreferences();
|
const preferences = useUserPreferences();
|
||||||
const updatePreferences = useUpdateUserPreferences();
|
const updatePreferences = useUpdateUserPreferences();
|
||||||
const currentUserId = getStoredAuth()?.user_id ?? null;
|
|
||||||
const [editingId, setEditingId] = useState<string | null>(null);
|
const [editingId, setEditingId] = useState<string | null>(null);
|
||||||
const [title, setTitle] = useState("");
|
const [title, setTitle] = useState("");
|
||||||
const [content, setContent] = useState("");
|
const [content, setContent] = useState("");
|
||||||
@@ -176,16 +174,7 @@ function ManagePromptsDialog({
|
|||||||
|
|
||||||
const saving = createPrompt.isPending || updatePrompt.isPending;
|
const saving = createPrompt.isPending || updatePrompt.isPending;
|
||||||
|
|
||||||
const selectableAgents = useMemo(() => {
|
const selectableAgents = agents;
|
||||||
const owned = currentUserId
|
|
||||||
? agents.filter((agent) => agent.user_id === currentUserId)
|
|
||||||
: [];
|
|
||||||
if (agentId && !owned.some((agent) => agent.id === agentId)) {
|
|
||||||
const bound = agents.find((agent) => agent.id === agentId);
|
|
||||||
if (bound) return [bound, ...owned];
|
|
||||||
}
|
|
||||||
return owned;
|
|
||||||
}, [agents, agentId, currentUserId]);
|
|
||||||
|
|
||||||
const agentNameById = (id?: string | null) =>
|
const agentNameById = (id?: string | null) =>
|
||||||
id ? agents.find((agent) => agent.id === id)?.name ?? null : null;
|
id ? agents.find((agent) => agent.id === id)?.name ?? null : null;
|
||||||
@@ -235,7 +224,11 @@ function ManagePromptsDialog({
|
|||||||
setEditingId(id);
|
setEditingId(id);
|
||||||
setTitle(target.title);
|
setTitle(target.title);
|
||||||
setContent(target.content);
|
setContent(target.content);
|
||||||
setAgentId(target.agent_id || undefined);
|
setAgentId(
|
||||||
|
target.agent_id && selectableAgents.some((agent) => agent.id === target.agent_id)
|
||||||
|
? target.agent_id
|
||||||
|
: undefined,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleHideAdmin = async (next: boolean) => {
|
const handleToggleHideAdmin = async (next: boolean) => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from datetime import datetime, timedelta
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from sqlalchemy import and_, case, desc, func, or_, select
|
from sqlalchemy import and_, case, desc, func, not_, or_, select
|
||||||
from langchain_core.messages import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from app.gateway.deps import (
|
from app.gateway.deps import (
|
||||||
@@ -355,6 +355,22 @@ def _run_time_filter(since: datetime, until: datetime):
|
|||||||
return and_(RunRow.created_at >= since, RunRow.created_at <= until)
|
return and_(RunRow.created_at >= since, RunRow.created_at <= until)
|
||||||
|
|
||||||
|
|
||||||
|
def _non_scheduled_run_filter():
|
||||||
|
"""Exclude scheduler-generated runs that predate scheduled_task_runs links."""
|
||||||
|
return or_(
|
||||||
|
RunRow.first_human_message.is_(None),
|
||||||
|
not_(RunRow.first_human_message.like("【定时任务触发】%")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _non_scheduled_tool_filter():
|
||||||
|
return or_(
|
||||||
|
ToolCallMetricRow.run_id.is_(None),
|
||||||
|
RunRow.run_id.is_(None),
|
||||||
|
_non_scheduled_run_filter(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _tool_time_filter(since: datetime, until: datetime):
|
def _tool_time_filter(since: datetime, until: datetime):
|
||||||
return and_(ToolCallMetricRow.created_at >= since, ToolCallMetricRow.created_at <= until)
|
return and_(ToolCallMetricRow.created_at >= since, ToolCallMetricRow.created_at <= until)
|
||||||
|
|
||||||
@@ -404,6 +420,7 @@ def _apply_run_scope(
|
|||||||
stmt = stmt.where(RunRow.status != "error")
|
stmt = stmt.where(RunRow.status != "error")
|
||||||
if not include_scheduled:
|
if not include_scheduled:
|
||||||
stmt = stmt.where(or_(run_id_column.is_(None), run_id_column.not_in(_scheduled_run_ids_stmt())))
|
stmt = stmt.where(or_(run_id_column.is_(None), run_id_column.not_in(_scheduled_run_ids_stmt())))
|
||||||
|
stmt = stmt.where(_non_scheduled_run_filter())
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
|
|
||||||
@@ -417,6 +434,7 @@ def _apply_tool_scope(
|
|||||||
stmt = _apply_user_scope(stmt, ToolCallMetricRow.user_id, exclude_user_ids=exclude_user_ids, include_admins=include_admins)
|
stmt = _apply_user_scope(stmt, ToolCallMetricRow.user_id, exclude_user_ids=exclude_user_ids, include_admins=include_admins)
|
||||||
if not include_scheduled:
|
if not include_scheduled:
|
||||||
stmt = stmt.where(or_(ToolCallMetricRow.run_id.is_(None), ToolCallMetricRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
stmt = stmt.where(or_(ToolCallMetricRow.run_id.is_(None), ToolCallMetricRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
||||||
|
stmt = stmt.outerjoin(RunRow, RunRow.run_id == ToolCallMetricRow.run_id).where(_non_scheduled_tool_filter())
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
|
|
||||||
@@ -910,6 +928,7 @@ async def _query_overview(
|
|||||||
if not include_scheduled:
|
if not include_scheduled:
|
||||||
run_where.append(or_(RunRow.run_id.is_(None), RunRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
run_where.append(or_(RunRow.run_id.is_(None), RunRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
||||||
tool_where.append(or_(ToolCallMetricRow.run_id.is_(None), ToolCallMetricRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
tool_where.append(or_(ToolCallMetricRow.run_id.is_(None), ToolCallMetricRow.run_id.not_in(_scheduled_run_ids_stmt())))
|
||||||
|
tool_where.append(_non_scheduled_tool_filter())
|
||||||
|
|
||||||
total_users_stmt = select(func.count(UserRow.id))
|
total_users_stmt = select(func.count(UserRow.id))
|
||||||
total_users_stmt = _apply_user_scope(total_users_stmt, UserRow.id, exclude_user_ids=exclude_user_ids, include_admins=include_admins)
|
total_users_stmt = _apply_user_scope(total_users_stmt, UserRow.id, exclude_user_ids=exclude_user_ids, include_admins=include_admins)
|
||||||
@@ -928,7 +947,9 @@ async def _query_overview(
|
|||||||
select(
|
select(
|
||||||
func.count(ToolCallMetricRow.id),
|
func.count(ToolCallMetricRow.id),
|
||||||
func.sum(case((func.nullif(ToolCallMetricRow.skill_name, "").is_not(None), 1), else_=0)),
|
func.sum(case((func.nullif(ToolCallMetricRow.skill_name, "").is_not(None), 1), else_=0)),
|
||||||
).where(*tool_where)
|
)
|
||||||
|
.outerjoin(RunRow, RunRow.run_id == ToolCallMetricRow.run_id)
|
||||||
|
.where(*tool_where)
|
||||||
)).one()
|
)).one()
|
||||||
|
|
||||||
return AdminLeaderboardOverview(
|
return AdminLeaderboardOverview(
|
||||||
|
|||||||
@@ -147,18 +147,7 @@ title:
|
|||||||
# - keep:压缩后保留多少最近的上下文(同样支持 tokens / messages / fraction)。
|
# - keep:压缩后保留多少最近的上下文(同样支持 tokens / messages / fraction)。
|
||||||
# - trim_tokens_to_summarize:喂给摘要模型的消息最多裁到多少 token。
|
# - trim_tokens_to_summarize:喂给摘要模型的消息最多裁到多少 token。
|
||||||
# - model_name:生成摘要用的模型(留空则用主对话模型)。
|
# - model_name:生成摘要用的模型(留空则用主对话模型)。
|
||||||
summarization:
|
|
||||||
enabled: true
|
|
||||||
# model_name: deepseek-chat
|
|
||||||
trigger:
|
|
||||||
- type: tokens
|
|
||||||
value: 60000
|
|
||||||
- type: messages
|
|
||||||
value: 80
|
|
||||||
keep:
|
|
||||||
type: messages
|
|
||||||
value: 20
|
|
||||||
trim_tokens_to_summarize: 4000
|
|
||||||
skills:
|
skills:
|
||||||
path: /app/skills
|
path: /app/skills
|
||||||
security_scan:
|
security_scan:
|
||||||
@@ -187,10 +176,7 @@ auth_login:
|
|||||||
ca_cert_path: "" # 可选:PEM 格式 CA 包路径,设置后优先生效并启用校验
|
ca_cert_path: "" # 可选:PEM 格式 CA 包路径,设置后优先生效并启用校验
|
||||||
# 日志系统入口(仅管理员可见):右下角「设置」菜单中会多出一个「日志系统」入口,
|
# 日志系统入口(仅管理员可见):右下角「设置」菜单中会多出一个「日志系统」入口,
|
||||||
# 点击后在新标签页打开下面的 url。enabled 关掉则不显示该入口。
|
# 点击后在新标签页打开下面的 url。enabled 关掉则不显示该入口。
|
||||||
log_system:
|
|
||||||
enabled: true
|
|
||||||
url: "https://your-log-system.example.com"
|
|
||||||
label: "日志系统"
|
|
||||||
database:
|
database:
|
||||||
backend: mysql
|
backend: mysql
|
||||||
mysql_url: $MYSQL_DATABASE_URL
|
mysql_url: $MYSQL_DATABASE_URL
|
||||||
@@ -269,4 +255,22 @@ memory:
|
|||||||
scan_content: true # 注入/外渗模式扫描
|
scan_content: true # 注入/外渗模式扫描
|
||||||
block_invisible_unicode: true
|
block_invisible_unicode: true
|
||||||
# streaming_scrubber:预留字段,代码尚未实现 —— 待版本支持后取消注释。
|
# streaming_scrubber:预留字段,代码尚未实现 —— 待版本支持后取消注释。
|
||||||
# streaming_scrubber: true # SSE 流前清洗 <memory-context>
|
# streaming_scrubber: true # SSE 流前清洗 <memory-context>
|
||||||
|
|
||||||
|
log_system:
|
||||||
|
enabled: true
|
||||||
|
url: "https://your-log-system.example.com"
|
||||||
|
label: "日志系统"
|
||||||
|
|
||||||
|
summarization:
|
||||||
|
enabled: true
|
||||||
|
# model_name: deepseek-chat
|
||||||
|
trigger:
|
||||||
|
- type: tokens
|
||||||
|
value: 60000
|
||||||
|
- type: messages
|
||||||
|
value: 80
|
||||||
|
keep:
|
||||||
|
type: messages
|
||||||
|
value: 20
|
||||||
|
trim_tokens_to_summarize: 4000
|
||||||
Reference in new issue
Block a user