style(format): format
This commit is contained in:
parent
f4090ede9d
commit
88b6b27465
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import datetime
|
from typing import TYPE_CHECKING
|
||||||
from typing import TYPE_CHECKING, Optional
|
|
||||||
|
|
||||||
from deepagents.backends.protocol import BackendProtocol, EditResult, WriteResult
|
from deepagents.backends.protocol import BackendProtocol, EditResult, WriteResult
|
||||||
from deepagents.backends.utils import FileInfo, GrepMatch
|
from deepagents.backends.utils import FileInfo, GrepMatch
|
||||||
@ -29,7 +28,7 @@ class MinIOBackend(BackendProtocol):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
bucket_name: str = "chat-attachments",
|
bucket_name: str = "chat-attachments",
|
||||||
minio_client: Optional[MinIOClient] = None,
|
minio_client: MinIOClient | None = None,
|
||||||
):
|
):
|
||||||
self.bucket_name = bucket_name
|
self.bucket_name = bucket_name
|
||||||
self._client = minio_client
|
self._client = minio_client
|
||||||
@ -51,7 +50,7 @@ class MinIOBackend(BackendProtocol):
|
|||||||
"""
|
"""
|
||||||
return path.lstrip("/")
|
return path.lstrip("/")
|
||||||
|
|
||||||
def _parse_path(self, path: str) -> tuple[Optional[str], Optional[str]]:
|
def _parse_path(self, path: str) -> tuple[str | None, str | None]:
|
||||||
"""解析路径,提取 thread_id 和 filename。
|
"""解析路径,提取 thread_id 和 filename。
|
||||||
|
|
||||||
支持两种格式:
|
支持两种格式:
|
||||||
@ -203,7 +202,7 @@ class MinIOBackend(BackendProtocol):
|
|||||||
# 添加行号
|
# 添加行号
|
||||||
start = max(0, offset)
|
start = max(0, offset)
|
||||||
end = start + limit
|
end = start + limit
|
||||||
numbered_lines = [f"{i+1}:{line}" for i, line in enumerate(lines[start:end], start + 1)]
|
numbered_lines = [f"{i + 1}:{line}" for i, line in enumerate(lines[start:end], start + 1)]
|
||||||
return "\n".join(numbered_lines)
|
return "\n".join(numbered_lines)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"MinIOBackend.read failed for {file_path}: {e}")
|
logger.error(f"MinIOBackend.read failed for {file_path}: {e}")
|
||||||
@ -288,8 +287,8 @@ class MinIOBackend(BackendProtocol):
|
|||||||
def grep_raw(
|
def grep_raw(
|
||||||
self,
|
self,
|
||||||
pattern: str,
|
pattern: str,
|
||||||
path: Optional[str] = None,
|
path: str | None = None,
|
||||||
glob: Optional[str] = None,
|
glob: str | None = None,
|
||||||
) -> list[GrepMatch] | str:
|
) -> list[GrepMatch] | str:
|
||||||
"""搜索文件内容。
|
"""搜索文件内容。
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class AttachmentMiddleware(AgentMiddleware[AttachmentState]):
|
|||||||
# 尝试从输入中获取 attachments(LangGraph 会将输入 state 合并)
|
# 尝试从输入中获取 attachments(LangGraph 会将输入 state 合并)
|
||||||
if not attachments:
|
if not attachments:
|
||||||
# 检查是否有其他方式传递的附件
|
# 检查是否有其他方式传递的附件
|
||||||
logger.info(f"AttachmentMiddleware: checking for attachments in other locations...")
|
logger.info("AttachmentMiddleware: checking for attachments in other locations...")
|
||||||
# 输入可能直接在 state 中
|
# 输入可能直接在 state 中
|
||||||
logger.info(f"AttachmentMiddleware: state type = {type(request.state)}")
|
logger.info(f"AttachmentMiddleware: state type = {type(request.state)}")
|
||||||
|
|
||||||
@ -97,21 +97,23 @@ class AttachmentMiddleware(AgentMiddleware[AttachmentState]):
|
|||||||
thread_id = None
|
thread_id = None
|
||||||
|
|
||||||
# 0. 尝试从 request.runtime 获取(LangChain runtime)
|
# 0. 尝试从 request.runtime 获取(LangChain runtime)
|
||||||
if hasattr(request, 'runtime') and request.runtime:
|
if hasattr(request, "runtime") and request.runtime:
|
||||||
runtime = request.runtime
|
runtime = request.runtime
|
||||||
logger.info(f"AttachmentMiddleware: runtime type = {type(runtime)}")
|
logger.info(f"AttachmentMiddleware: runtime type = {type(runtime)}")
|
||||||
logger.info(f"AttachmentMiddleware: runtime attrs = {[a for a in dir(runtime) if not a.startswith('_')]}")
|
logger.info(
|
||||||
|
f"AttachmentMiddleware: runtime attrs = {[a for a in dir(runtime) if not a.startswith('_')]}"
|
||||||
|
)
|
||||||
|
|
||||||
# 检查 runtime.context
|
# 检查 runtime.context
|
||||||
if hasattr(runtime, 'context') and runtime.context:
|
if hasattr(runtime, "context") and runtime.context:
|
||||||
ctx = runtime.context
|
ctx = runtime.context
|
||||||
logger.info(f"AttachmentMiddleware: runtime.context type = {type(ctx)}")
|
logger.info(f"AttachmentMiddleware: runtime.context type = {type(ctx)}")
|
||||||
# 如果是 Pydantic 模型,使用 model_dump()
|
# 如果是 Pydantic 模型,使用 model_dump()
|
||||||
if hasattr(ctx, 'model_dump'):
|
if hasattr(ctx, "model_dump"):
|
||||||
ctx_dict = ctx.model_dump()
|
ctx_dict = ctx.model_dump()
|
||||||
logger.info(f"AttachmentMiddleware: runtime.context keys = {list(ctx_dict.keys())}")
|
logger.info(f"AttachmentMiddleware: runtime.context keys = {list(ctx_dict.keys())}")
|
||||||
thread_id = ctx_dict.get("thread_id")
|
thread_id = ctx_dict.get("thread_id")
|
||||||
elif hasattr(ctx, '__dict__'):
|
elif hasattr(ctx, "__dict__"):
|
||||||
logger.info(f"AttachmentMiddleware: runtime.context __dict__ = {ctx.__dict__}")
|
logger.info(f"AttachmentMiddleware: runtime.context __dict__ = {ctx.__dict__}")
|
||||||
thread_id = ctx.__dict__.get("thread_id")
|
thread_id = ctx.__dict__.get("thread_id")
|
||||||
elif isinstance(ctx, dict):
|
elif isinstance(ctx, dict):
|
||||||
@ -120,13 +122,13 @@ class AttachmentMiddleware(AgentMiddleware[AttachmentState]):
|
|||||||
|
|
||||||
# 如果还没有 thread_id,检查 runtime 其他属性
|
# 如果还没有 thread_id,检查 runtime 其他属性
|
||||||
if not thread_id:
|
if not thread_id:
|
||||||
for attr in ['state', 'config', 'configurable']:
|
for attr in ["state", "config", "configurable"]:
|
||||||
if hasattr(runtime, attr):
|
if hasattr(runtime, attr):
|
||||||
val = getattr(runtime, attr)
|
val = getattr(runtime, attr)
|
||||||
logger.info(f"AttachmentMiddleware: runtime.{attr} = {type(val)}")
|
logger.info(f"AttachmentMiddleware: runtime.{attr} = {type(val)}")
|
||||||
if isinstance(val, dict):
|
if isinstance(val, dict):
|
||||||
thread_id = val.get("thread_id")
|
thread_id = val.get("thread_id")
|
||||||
elif hasattr(val, 'get'):
|
elif hasattr(val, "get"):
|
||||||
thread_id = val.get("thread_id")
|
thread_id = val.get("thread_id")
|
||||||
if thread_id:
|
if thread_id:
|
||||||
break
|
break
|
||||||
@ -147,8 +149,8 @@ class AttachmentMiddleware(AgentMiddleware[AttachmentState]):
|
|||||||
if input_context is not None:
|
if input_context is not None:
|
||||||
if isinstance(input_context, dict):
|
if isinstance(input_context, dict):
|
||||||
thread_id = input_context.get("thread_id")
|
thread_id = input_context.get("thread_id")
|
||||||
elif hasattr(input_context, 'thread_id'):
|
elif hasattr(input_context, "thread_id"):
|
||||||
thread_id = getattr(input_context, 'thread_id', None)
|
thread_id = getattr(input_context, "thread_id", None)
|
||||||
|
|
||||||
logger.info(f"AttachmentMiddleware: thread_id = {thread_id}")
|
logger.info(f"AttachmentMiddleware: thread_id = {thread_id}")
|
||||||
logger.info(f"AttachmentMiddleware: has config = {hasattr(request, 'config')}")
|
logger.info(f"AttachmentMiddleware: has config = {hasattr(request, 'config')}")
|
||||||
|
|||||||
@ -147,7 +147,7 @@ def _offload_tool_result(msg: ToolMessage, threshold: int, token_counter: TokenC
|
|||||||
|
|
||||||
# 构建文件头部信息
|
# 构建文件头部信息
|
||||||
header_lines = [
|
header_lines = [
|
||||||
f"=== Tool Invocation ===",
|
"=== Tool Invocation ===",
|
||||||
f"Tool: {tool_name}",
|
f"Tool: {tool_name}",
|
||||||
f"Tool Call ID: {tool_call_id}",
|
f"Tool Call ID: {tool_call_id}",
|
||||||
"=" * 40,
|
"=" * 40,
|
||||||
|
|||||||
@ -35,8 +35,8 @@ class MySQLSecurityChecker:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 移除SQL注释(-- 和 /* */)后再验证
|
# 移除SQL注释(-- 和 /* */)后再验证
|
||||||
sql_clean = re.sub(r'--.*$', '', sql, flags=re.MULTILINE)
|
sql_clean = re.sub(r"--.*$", "", sql, flags=re.MULTILINE)
|
||||||
sql_clean = re.sub(r'/\*.*?\*/', '', sql_clean)
|
sql_clean = re.sub(r"/\*.*?\*/", "", sql_clean)
|
||||||
sql_upper = sql_clean.strip().upper()
|
sql_upper = sql_clean.strip().upper()
|
||||||
|
|
||||||
# 检查是否是允许的操作
|
# 检查是否是允许的操作
|
||||||
|
|||||||
@ -140,7 +140,7 @@ class DeepAgent(BaseAgent):
|
|||||||
PatchToolCallsMiddleware(),
|
PatchToolCallsMiddleware(),
|
||||||
summary_middleware,
|
summary_middleware,
|
||||||
],
|
],
|
||||||
general_purpose_agent=True
|
general_purpose_agent=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 使用 create_deep_agent 创建深度智能体
|
# 使用 create_deep_agent 创建深度智能体
|
||||||
|
|||||||
@ -11,7 +11,6 @@ from src.agents.common.toolkits.mysql import get_mysql_tools
|
|||||||
from src.services.mcp_service import get_mcp_server_names, get_tools_from_all_servers
|
from src.services.mcp_service import get_mcp_server_names, get_tools_from_all_servers
|
||||||
from src.utils import logger
|
from src.utils import logger
|
||||||
|
|
||||||
|
|
||||||
PROMPT = """你的任务是根据用户的指令,使用数据库工具和图表绘制工具,构建 SQL 查询报告。
|
PROMPT = """你的任务是根据用户的指令,使用数据库工具和图表绘制工具,构建 SQL 查询报告。
|
||||||
你需要根据用户的指令,生成相应的 SQL 查询,并将查询结果以报表的形式返回给用户。
|
你需要根据用户的指令,生成相应的 SQL 查询,并将查询结果以报表的形式返回给用户。
|
||||||
在生成报表时,你可以调用工具生成图表,以更直观地展示数据。
|
在生成报表时,你可以调用工具生成图表,以更直观地展示数据。
|
||||||
@ -22,9 +21,11 @@ PROMPT = """你的任务是根据用户的指令,使用数据库工具和图
|
|||||||
3. 必要时,使用网络检索相关工具补充信息。
|
3. 必要时,使用网络检索相关工具补充信息。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class ReporterContext(BaseContext):
|
class ReporterContext(BaseContext):
|
||||||
"""覆盖 BaseContext,定义数据库报表助手智能体的可配置参数"""
|
"""覆盖 BaseContext,定义数据库报表助手智能体的可配置参数"""
|
||||||
|
|
||||||
# 覆盖 system_prompt,提供更具体的默认值
|
# 覆盖 system_prompt,提供更具体的默认值
|
||||||
system_prompt: Annotated[str, {"__template_metadata__": {"kind": "prompt"}}] = field(
|
system_prompt: Annotated[str, {"__template_metadata__": {"kind": "prompt"}}] = field(
|
||||||
default=PROMPT,
|
default=PROMPT,
|
||||||
|
|||||||
@ -112,7 +112,6 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="message-input-wrapper">
|
<div class="message-input-wrapper">
|
||||||
|
|
||||||
<!-- 加载状态:加载消息 -->
|
<!-- 加载状态:加载消息 -->
|
||||||
<div v-if="isLoadingMessages" class="chat-loading">
|
<div v-if="isLoadingMessages" class="chat-loading">
|
||||||
<div class="loading-spinner"></div>
|
<div class="loading-spinner"></div>
|
||||||
|
|||||||
@ -78,16 +78,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<FolderOpen
|
<FolderOpen v-if="expanded" :size="18" class="folder-icon open" />
|
||||||
v-if="expanded"
|
<Folder v-else :size="18" class="folder-icon" />
|
||||||
:size="18"
|
|
||||||
class="folder-icon open"
|
|
||||||
/>
|
|
||||||
<Folder
|
|
||||||
v-else
|
|
||||||
:size="18"
|
|
||||||
class="folder-icon"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #title="{ data }">
|
<template #title="{ data }">
|
||||||
@ -146,16 +138,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<FolderOpen
|
<FolderOpen v-if="expanded" :size="18" class="folder-icon open" />
|
||||||
v-if="expanded"
|
<Folder v-else :size="18" class="folder-icon" />
|
||||||
:size="18"
|
|
||||||
class="folder-icon open"
|
|
||||||
/>
|
|
||||||
<Folder
|
|
||||||
v-else
|
|
||||||
:size="18"
|
|
||||||
class="folder-icon"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template #title="{ data }">
|
<template #title="{ data }">
|
||||||
@ -250,7 +234,17 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, onMounted, onUpdated, nextTick } from 'vue'
|
import { computed, ref, onMounted, onUpdated, nextTick } from 'vue'
|
||||||
import { Download, X, Plus, Info, FolderCode, RefreshCw, Folder, FolderOpen, Trash2 } from 'lucide-vue-next'
|
import {
|
||||||
|
Download,
|
||||||
|
X,
|
||||||
|
Plus,
|
||||||
|
Info,
|
||||||
|
FolderCode,
|
||||||
|
RefreshCw,
|
||||||
|
Folder,
|
||||||
|
FolderOpen,
|
||||||
|
Trash2
|
||||||
|
} from 'lucide-vue-next'
|
||||||
import {
|
import {
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
@ -425,16 +419,16 @@ const buildTreeData = (filesList) => {
|
|||||||
// User asked for "last 5 chars".
|
// User asked for "last 5 chars".
|
||||||
// If we treat the whole thing as a string:
|
// If we treat the whole thing as a string:
|
||||||
if (part.length > 5) {
|
if (part.length > 5) {
|
||||||
nameEnd = part.slice(-5)
|
nameEnd = part.slice(-5)
|
||||||
nameStart = part.slice(0, -5)
|
nameStart = part.slice(0, -5)
|
||||||
} else {
|
} else {
|
||||||
nameStart = part
|
nameStart = part
|
||||||
nameEnd = ''
|
nameEnd = ''
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (part.length > 5) {
|
if (part.length > 5) {
|
||||||
nameEnd = part.slice(-5)
|
nameEnd = part.slice(-5)
|
||||||
nameStart = part.slice(0, -5)
|
nameStart = part.slice(0, -5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1078,8 @@ const stopResize = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
font-family:
|
||||||
|
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--gray-800);
|
color: var(--gray-800);
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
|||||||
@ -25,7 +25,9 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const toolCallName = computed(() => props.toolCall.name || props.toolCall.function?.name || 'edit_file')
|
const toolCallName = computed(
|
||||||
|
() => props.toolCall.name || props.toolCall.function?.name || 'edit_file'
|
||||||
|
)
|
||||||
|
|
||||||
const parsedArgs = computed(() => {
|
const parsedArgs = computed(() => {
|
||||||
const args = props.toolCall.args || props.toolCall.function?.arguments
|
const args = props.toolCall.args || props.toolCall.function?.arguments
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user