+ + AI 思考逻辑 (Think Process) +
+ ++ + + 知识库召回溯源 () +
+ +Select to begin
+diff --git a/pocket-base/bai-web-main.pb.js b/pocket-base/bai-web-main.pb.js index c51b5f1..699a94a 100644 --- a/pocket-base/bai-web-main.pb.js +++ b/pocket-base/bai-web-main.pb.js @@ -4,3 +4,6 @@ require(`${__hooks}/bai_web_pb_hooks/pages/document-manage.js`) require(`${__hooks}/bai_web_pb_hooks/pages/product-manage.js`) require(`${__hooks}/bai_web_pb_hooks/pages/dictionary-manage.js`) require(`${__hooks}/bai_web_pb_hooks/pages/sdk-permission-manage.js`) +require(`${__hooks}/bai_chat_alm_hooks/bai-ai-manage-main.pb.js`) +require(`${__hooks}/bai_chat_alm_hooks/bai-chat.pb.js`) +require(`${__hooks}/bai_chat_alm_hooks/bai-sql-lab.pb.js`) diff --git a/pocket-base/bai_chat_alm_hooks/bai-ai-manage-main.pb.js b/pocket-base/bai_chat_alm_hooks/bai-ai-manage-main.pb.js new file mode 100644 index 0000000..a646783 --- /dev/null +++ b/pocket-base/bai_chat_alm_hooks/bai-ai-manage-main.pb.js @@ -0,0 +1,122 @@ +// ============================================================================== +// 模块: BAI 业务审计子系统 (v1.8 完整功能稳态版) +// ============================================================================== + +routerAdd("GET", "/bai-ai-manage", (c) => { + try { + const html = $template.loadFiles(__hooks + "/bai_chat_alm_hooks/views/ai-manage-index.html").render({}); + const safeHtml = String(html || "") + const guardScript = '' + const guardedHtml = safeHtml.indexOf("") !== -1 + ? safeHtml.replace("", guardScript + "") + : guardScript + safeHtml + + return c.html(200, guardedHtml); + } catch (err) { + return c.json(500, { message: "HTML 模板渲染失败: " + err.message }); + } +}); + +// 1. 获取用户列表 +routerAdd("GET", "/pb-api-v1/audit/users", (c) => { + try { + const info = c.requestInfo(); + const days = parseInt(info.query["days"] || "0"); + + // 保持原有的时间过滤逻辑 + let timeClause = (days > 0) ? `AND c.createdAt > ${new Date().getTime() - (days * 24 * 60 * 1000)}` : ""; + + // 【核心修正】SQL 采用 LEFT JOIN 确保 thread_id 为空的 API 对话不被漏掉 + // 注意:这里去掉了可能引起语法错误的注释,使用了探针兼容的 SQL + const sql = ` + SELECT + COALESCE(t.slug, t.name, 'API_USER') as phone, + COUNT(c.id) as chat_count, + MAX(c.createdAt) as last_active + FROM workspace_chats c + LEFT JOIN workspace_threads t ON c.thread_id = t.id + WHERE 1=1 ${timeClause} + GROUP BY phone + ORDER BY last_active DESC + `; + + // 保持对 3010 探针的调用 + const res = $http.send({ + url: "http://bai-alm-audit-api:3010/api/v1/audit/query", + method: "POST", + body: JSON.stringify({ "sql": sql, "params": [] }), + headers: { "Content-Type": "application/json" } + }); + + // 保持原有的 PB 用户姓名映射逻辑 + let phoneToNameMap = {}; + const pbRecords = $app.findAllRecords("tbl_auth_users"); + pbRecords.forEach(r => { + phoneToNameMap[r.getString("users_phone")] = r.getString("users_name"); + }); + + const data = (res.json.data || []).map(u => ({ + ...u, + name: phoneToNameMap[u.phone] || (u.phone === 'API_USER' ? '微信测试用户' : "") + })); + + return c.json(200, { code: 200, data }); + } catch (err) { + return c.json(500, { message: "Users API Error: " + err.message }); + } +}); + +// 2. 获取流水记录 +routerAdd("GET", "/pb-api-v1/audit/chat-list", (c) => { + try { + const info = c.requestInfo(); + const phone = info.query["phone"]; + const page = parseInt(info.query["page"] || "1"); + const days = parseInt(info.query["days"] || "0"); + const offset = (page - 1) * 50; + + let timeClause = (days > 0) ? `AND c.createdAt > ${new Date().getTime() - (days * 24 * 60 * 60 * 1000)}` : ""; + + // 【核心修正】针对 API_USER 的特殊查询逻辑 + let whereClause = ""; + if (phone === "API_USER") { + whereClause = `WHERE c.thread_id IS NULL`; + } else { + whereClause = `WHERE t.slug = '${phone}' OR t.name = '${phone}'`; + } + + const sql = ` + SELECT c.id, w.name AS workspace_name, c.prompt, c.response, c.createdAt + FROM workspace_chats c + LEFT JOIN workspace_threads t ON c.thread_id = t.id + LEFT JOIN workspaces w ON c.workspaceId = w.id + ${whereClause} ${timeClause} + ORDER BY c.createdAt DESC + LIMIT 50 OFFSET ${offset} + `; + + const res = $http.send({ + url: "http://bai-alm-audit-api:3010/api/v1/audit/query", + method: "POST", + body: JSON.stringify({ "sql": sql, "params": [] }), + headers: { "Content-Type": "application/json" } + }); + + return c.json(200, { code: 200, data: res.json.data || [] }); + } catch (err) { + return c.json(500, { message: "Chat List Error: " + err.message }); + } +}); + +// 3. 全量导出保持不变 +routerAdd("GET", "/pb-api-v1/audit/export-all", (c) => { + try { + const info = c.requestInfo(); + const phone = info.query["phone"]; + let whereClause = (phone === "API_USER") ? "WHERE c.thread_id IS NULL" : `WHERE t.slug = '${phone}' OR t.name = '${phone}'`; + + const sql = `SELECT c.*, w.name AS workspace_name FROM workspace_chats c LEFT JOIN workspace_threads t ON c.thread_id = t.id LEFT JOIN workspaces w ON c.workspaceId = w.id ${whereClause} ORDER BY c.createdAt DESC;`; + const res = $http.send({ url: "http://bai-alm-audit-api:3010/api/v1/audit/query", method: "POST", body: JSON.stringify({ "sql": sql, "params": [] }), headers: { "Content-Type": "application/json" } }); + return c.json(200, { code: 200, data: res.json.data || [] }); + } catch (err) { return c.json(500, { message: err.message }); } +}); \ No newline at end of file diff --git a/pocket-base/bai_chat_alm_hooks/bai-chat.pb.js b/pocket-base/bai_chat_alm_hooks/bai-chat.pb.js new file mode 100644 index 0000000..e25c793 --- /dev/null +++ b/pocket-base/bai_chat_alm_hooks/bai-chat.pb.js @@ -0,0 +1,62 @@ +// ============================================================================== +// 模块: BAI 微信风聊天测试页 (v1.4 修复版) +// ============================================================================== + +// 1. 渲染页面路由 +routerAdd("GET", "/bai-chat", (c) => { + try { + // 确保 views/bai-chat-index.html 路径存在 + const html = $template.loadFiles(__hooks + "/bai_chat_alm_hooks/views/bai-chat-index.html").render({}); + const safeHtml = String(html || "") + const guardScript = '' + const guardedHtml = safeHtml.indexOf("") !== -1 + ? safeHtml.replace("", guardScript + "") + : guardScript + safeHtml + return c.html(200, guardedHtml); + } catch (e) { + return c.json(500, { "message": "HTML 模板渲染失败: " + e.message }); + } +}); + +// 2. 聊天转发路由 +routerAdd("POST", "/pb-api-v1/chat/send", (c) => { + try { + const info = c.requestInfo(); + // 增加安全取值逻辑 + const body = info.body || {}; + const userMsg = body.message || ""; + + if (!userMsg) { + return c.json(400, { "message": "消息内容不能为空" }); + } + + // 使用 3001 端口直连 AnythingLLM + // 如果 8888 还没创建成功,API 会自动回落到默认线程,保证不报错 + const res = $http.send({ + url: "http://bai-anythingllm:3001/api/v1/workspace/ai/chat", + method: "POST", + body: JSON.stringify({ + "message": userMsg, + "mode": "chat", + "sessionId": "8888" + }), + headers: { + "Content-Type": "application/json", + "Authorization": "Bearer SEC082V-99D48HT-GB96EZ5-BS34AMS" + }, + timeout: 120 + }); + + // 解析返回结果 + const resData = res.json || {}; + const replyText = resData.textResponse || resData.content || resData.text || "AI 未能返回有效内容"; + + return c.json(200, { + "code": 200, + "reply": replyText + }); + + } catch (err) { + return c.json(500, { "message": "转发请求失败: " + err.message }); + } +}); \ No newline at end of file diff --git a/pocket-base/bai_chat_alm_hooks/bai-sql-lab.pb.js b/pocket-base/bai_chat_alm_hooks/bai-sql-lab.pb.js new file mode 100644 index 0000000..5c45ca5 --- /dev/null +++ b/pocket-base/bai_chat_alm_hooks/bai-sql-lab.pb.js @@ -0,0 +1,79 @@ +// ============================================================================== +// 模块: BAI SQL 实验室 (底层探勘工具) - 拆分独立版 +// 路由: /bai-ai-sql-lab +// 注意: 绝不能引入 dynamic_model,防止引擎崩溃 +// ============================================================================== + +// 1. 页面 UI 挂载 (路径更新为 views 目录) +routerAdd("GET", "/bai-ai-sql-lab", (c) => { + try { + const html = $template.loadFiles(__hooks + "/bai_chat_alm_hooks/views/sql-lab-index.html").render({}); + const safeHtml = String(html || "") + const guardScript = '' + const guardedHtml = safeHtml.indexOf("") !== -1 + ? safeHtml.replace("", guardScript + "") + : guardScript + safeHtml + return c.html(200, guardedHtml); + } catch (err) { + return c.json(500, { "error": "Template Error: " + err.message }); + } +}); + +// 2. 全链路体检探针 (保持原样,属于 SQL Lab 的基础能力) +routerAdd("GET", "/pb-api-v1/diagnostics", (c) => { + let report = { pb_status: "PocketBase OK", py_network: "WAIT", sqlite_storage: "WAIT", sqlite_version: "" }; + try { + const res1 = $http.send({ url: "http://bai-alm-audit-api:3010/api/v1/audit/py-alive-check", method: "GET", timeout: 5 }); + report.py_network = res1.statusCode === 200 ? "ALIVE" : "ERROR"; + + const res2 = $http.send({ url: "http://bai-alm-audit-api:3010/api/v1/audit/sqlite-read-check", method: "GET", timeout: 5 }); + report.sqlite_storage = res2.statusCode === 200 ? "READY" : "ERROR"; + + if (res2.statusCode === 200 && res2.json.message) { + const match = res2.json.message.match(/版本:\s*([\d\.]+)/); + report.sqlite_version = match ? match[1] : "未知"; + report.sqlite_detail = res2.json.message; + } else { + report.sqlite_detail = res2.raw; + } + + return c.json(200, report); + } catch (err) { + report.py_network = "ERROR"; + report.sqlite_storage = "ERROR"; + report.sqlite_detail = err.message; + return c.json(500, report); + } +}); + +// 3. 万能 SQL 执行透传通道 (彻底修复 Body 读取方式) +routerAdd("POST", "/pb-api-v1/sql-ops", (c) => { + try { + // PB v0.23+ 官方推荐的无依赖 Body 读取方式 + const reqBody = c.requestInfo().body; + const sqlStatement = reqBody.sql || ""; + + if (!sqlStatement) { + return c.json(400, { "message": "SQL 指令不能为空" }); + } + + const res = $http.send({ + url: "http://bai-alm-audit-api:3010/api/v1/audit/query", + method: "POST", + body: JSON.stringify({ "sql": sqlStatement, "params": [] }), + headers: { "Content-Type": "application/json" }, + timeout: 15 + }); + + if (res.statusCode !== 200) { + return c.json(res.statusCode, { + code: res.statusCode, + message: res.json?.detail || res.raw || "探针层执行报错" + }); + } + + return c.json(200, { code: 200, data: res.json.data || [] }); + } catch (err) { + return c.json(500, { code: 500, message: "PB穿透异常: " + err.message }); + } +}); \ No newline at end of file diff --git a/pocket-base/bai_chat_alm_hooks/views/ai-manage-index.html b/pocket-base/bai_chat_alm_hooks/views/ai-manage-index.html new file mode 100644 index 0000000..3b9beb5 --- /dev/null +++ b/pocket-base/bai_chat_alm_hooks/views/ai-manage-index.html @@ -0,0 +1,464 @@ + + +
+ + +Select to begin
+| + + | + +
|---|
| + + |