feat: AI 工具架构重构与微信增强 (0.2.17 → 0.2.22)
0.2.17 收束模型初始工具列表: - 仅暴露 query_capabilities/query_capability_detail/call_capability 三个入口 - API 能力统一通过 iAs HTTP API 封装,删除重复 YAML 工具 0.2.18 系统提示词拆分: - 固定系统提示词硬编码,动态附加部分 AI 可维护 - 新增 update_additional_system_prompt 能力和持久化 0.2.19 上下文增强与打断语义: - /new 拥有最高打断语义,取消运行中任务并清除当前 turn - raw_message JSONB 原文入库,群聊按 group_id 隔离作用域 - 工具调用说明替代动态附加系统提示词 0.2.20 微信输入中状态: - 改用官方 getconfig + sendtyping 流程,显式管理 typing 状态 0.2.21 API 文档功能分组: - /v1/api-docs 返回 groups,帮助 AI 按功能面发现接口 0.2.22 AI API 能力去重: - 移除与 HTTP endpoint 重复的专用能力,统一用 query_api_docs + call_http_api - 删除不再编译的 web/memory 工具文件
This commit is contained in:
@@ -32,6 +32,8 @@ interface MessageRow {
|
||||
content: string;
|
||||
tool_call_id?: string;
|
||||
tool_calls?: string;
|
||||
raw_message?: unknown;
|
||||
external_message_id?: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
@@ -58,8 +60,9 @@ interface SimulatorResponse {
|
||||
has_query: boolean;
|
||||
scope_key: string;
|
||||
tools: Tool[];
|
||||
default_messages: { role: string; content: string }[];
|
||||
default_messages: Array<Record<string, unknown>>;
|
||||
default_system_prompt: string;
|
||||
tool_call_instruction?: string;
|
||||
sessions: SessionRow[];
|
||||
messages: MessageRow[];
|
||||
memories: MemoryRow[];
|
||||
@@ -92,15 +95,17 @@ export function ContextSimulatorPage() {
|
||||
const channel = searchParams.get("channel") || "wechat";
|
||||
const accountId = searchParams.get("account_id") || "";
|
||||
const fromUserId = searchParams.get("from_user_id") || "";
|
||||
const groupId = searchParams.get("group_id") || "";
|
||||
|
||||
// 编辑器状态
|
||||
const [messages, setMessages] = useState<{ role: string; content: string }[]>([]);
|
||||
const [messages, setMessages] = useState<Array<Record<string, unknown>>>([]);
|
||||
const [selectedTools, setSelectedTools] = useState<Set<string>>(new Set());
|
||||
|
||||
const loadData = (values: {
|
||||
channel: string;
|
||||
accountId: string;
|
||||
fromUserId: string;
|
||||
groupId: string;
|
||||
}) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
@@ -108,6 +113,7 @@ export function ContextSimulatorPage() {
|
||||
if (values.channel) params.channel = values.channel;
|
||||
if (values.accountId) params.account_id = values.accountId;
|
||||
if (values.fromUserId) params.from_user_id = values.fromUserId;
|
||||
if (values.groupId) params.group_id = values.groupId;
|
||||
|
||||
apiGet<SimulatorResponse>("/v1/context/simulator", params)
|
||||
.then((res) => {
|
||||
@@ -120,8 +126,8 @@ export function ContextSimulatorPage() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadData({ channel, accountId, fromUserId });
|
||||
}, [channel, accountId, fromUserId]);
|
||||
loadData({ channel, accountId, fromUserId, groupId });
|
||||
}, [channel, accountId, fromUserId, groupId]);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
@@ -130,9 +136,11 @@ export function ContextSimulatorPage() {
|
||||
const c = (form.get("channel") as string) || "";
|
||||
const a = (form.get("account_id") as string) || "";
|
||||
const f = (form.get("from_user_id") as string) || "";
|
||||
const g = (form.get("group_id") as string) || "";
|
||||
if (c) params.set("channel", c);
|
||||
if (a) params.set("account_id", a);
|
||||
if (f) params.set("from_user_id", f);
|
||||
if (g) params.set("group_id", g);
|
||||
setSearchParams(params);
|
||||
};
|
||||
|
||||
@@ -238,6 +246,15 @@ export function ContextSimulatorPage() {
|
||||
className="w-32 border border-gray-300 rounded px-2.5 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-500 mb-0.5">group_id</label>
|
||||
<input
|
||||
name="group_id"
|
||||
defaultValue={groupId}
|
||||
placeholder="group"
|
||||
className="w-32 border border-gray-300 rounded px-2.5 py-1.5 text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-blue-600 text-white px-4 py-1.5 rounded text-sm font-medium hover:bg-blue-700 transition"
|
||||
@@ -267,7 +284,13 @@ export function ContextSimulatorPage() {
|
||||
<span>消息 {data.messages.length} 条</span>
|
||||
<span>记忆 {data.memories.length} 条</span>
|
||||
<span>摘要 {data.summaries.length} 条</span>
|
||||
<span>工具调用说明 {data.tool_call_instruction ? "已配置" : "未配置"}</span>
|
||||
</div>
|
||||
{data.tool_call_instruction && (
|
||||
<div className="mt-2 text-green-700 whitespace-pre-wrap">
|
||||
工具调用说明:{data.tool_call_instruction}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -315,7 +338,7 @@ export function ContextSimulatorPage() {
|
||||
<span className="text-sm font-medium text-gray-800">{tool.name}</span>
|
||||
<span
|
||||
className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${
|
||||
tool.source === "内置"
|
||||
tool.source === "入口"
|
||||
? "bg-blue-100 text-blue-700"
|
||||
: "bg-orange-100 text-orange-700"
|
||||
}`}
|
||||
@@ -369,7 +392,7 @@ export function ContextSimulatorPage() {
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
className="text-xs border rounded px-1.5 py-0.5 bg-white"
|
||||
value={msg.role}
|
||||
value={String(msg.role || "user")}
|
||||
onChange={(e) => {
|
||||
const next = [...messages];
|
||||
next[i] = { ...next[i], role: e.target.value };
|
||||
@@ -397,7 +420,7 @@ export function ContextSimulatorPage() {
|
||||
<textarea
|
||||
className="w-full border rounded px-2 py-1.5 text-sm font-mono bg-white resize-y"
|
||||
rows={3}
|
||||
value={msg.content}
|
||||
value={String(msg.content || "")}
|
||||
onChange={(e) => {
|
||||
const next = [...messages];
|
||||
next[i] = { ...next[i], content: e.target.value };
|
||||
|
||||
+48
-14
@@ -6,11 +6,13 @@ interface ToolParam {
|
||||
param_type: string;
|
||||
required: boolean;
|
||||
description: string;
|
||||
default?: string;
|
||||
}
|
||||
|
||||
interface ToolItem {
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
source: string;
|
||||
path?: string;
|
||||
params: ToolParam[];
|
||||
@@ -21,8 +23,9 @@ interface ToolsResponse {
|
||||
success: boolean;
|
||||
total: number;
|
||||
tools_path: string;
|
||||
builtin_tools: ToolItem[];
|
||||
capability_tools: ToolItem[];
|
||||
entry_tools: ToolItem[];
|
||||
api_tools: ToolItem[];
|
||||
http_tools: ToolItem[];
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
@@ -56,6 +59,12 @@ export function ToolsPage() {
|
||||
|
||||
if (!data) return null;
|
||||
|
||||
const sourceClass = (item: ToolItem) => {
|
||||
if (item.category === "entry") return "bg-slate-100 text-slate-700";
|
||||
if (item.category === "api") return "bg-blue-50 text-blue-700";
|
||||
return "bg-emerald-50 text-emerald-700";
|
||||
};
|
||||
|
||||
const renderToolCard = (item: ToolItem) => (
|
||||
<article
|
||||
key={item.name}
|
||||
@@ -70,7 +79,11 @@ export function ToolsPage() {
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<span className="shrink-0 inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-semibold bg-blue-50 text-blue-700">
|
||||
<span
|
||||
className={`shrink-0 inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-semibold ${sourceClass(
|
||||
item
|
||||
)}`}
|
||||
>
|
||||
{item.source}
|
||||
</span>
|
||||
</div>
|
||||
@@ -102,6 +115,11 @@ export function ToolsPage() {
|
||||
可选
|
||||
</span>
|
||||
)}
|
||||
{param.default && (
|
||||
<span className="text-[11px] font-medium text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded">
|
||||
默认 {param.default}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-gray-500">{param.description}</p>
|
||||
</div>
|
||||
@@ -131,7 +149,7 @@ export function ToolsPage() {
|
||||
<div className="mb-7">
|
||||
<h1 className="text-2xl md:text-3xl font-bold tracking-tight">工具列表</h1>
|
||||
<p className="mt-1.5 text-sm text-gray-500">
|
||||
共 {data.total} 个工具;YAML 工具目录:
|
||||
共 {data.total} 个工具与能力;HTTP 能力目录:
|
||||
<code className="text-xs bg-gray-200 text-gray-700 px-1.5 py-0.5 rounded">
|
||||
{data.tools_path}
|
||||
</code>
|
||||
@@ -153,35 +171,51 @@ export function ToolsPage() {
|
||||
|
||||
<section className="mb-8">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-lg font-semibold">内置工具</h2>
|
||||
<span className="text-sm text-gray-400">{data.builtin_tools.length} 个</span>
|
||||
<h2 className="text-lg font-semibold">入口工具</h2>
|
||||
<span className="text-sm text-gray-400">{data.entry_tools.length} 个</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{data.builtin_tools.length === 0 ? (
|
||||
{data.entry_tools.length === 0 ? (
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-5 text-sm text-gray-400">
|
||||
暂无工具
|
||||
</div>
|
||||
) : (
|
||||
data.builtin_tools.map(renderToolCard)
|
||||
data.entry_tools.map(renderToolCard)
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-lg font-semibold">YAML 工具</h2>
|
||||
<span className="text-sm text-gray-400">{data.capability_tools.length} 个</span>
|
||||
<h2 className="text-lg font-semibold">API 能力</h2>
|
||||
<span className="text-sm text-gray-400">{data.api_tools.length} 个</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{data.capability_tools.length === 0 ? (
|
||||
{data.api_tools.length === 0 ? (
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-5 text-sm text-gray-400">
|
||||
暂无工具
|
||||
暂无能力
|
||||
</div>
|
||||
) : (
|
||||
data.capability_tools.map(renderToolCard)
|
||||
data.api_tools.map(renderToolCard)
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h2 className="text-lg font-semibold">HTTP 能力</h2>
|
||||
<span className="text-sm text-gray-400">{data.http_tools.length} 个</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{data.http_tools.length === 0 ? (
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-5 text-sm text-gray-400">
|
||||
暂无能力
|
||||
</div>
|
||||
) : (
|
||||
data.http_tools.map(renderToolCard)
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user