import { useState, useEffect } from "react"; import { Link, useNavigate } from "react-router-dom"; import { Settings as SettingsIcon, Loader2, CheckCircle2, AlertCircle, AlertTriangle, MessageSquare, Activity, Github, Globe, ChevronRight, Info, Sparkles, Building2, Upload, Link2, RefreshCw, Trash2, Files, LayoutTemplate, History, ShieldCheck, Settings2 } from "lucide-react"; import { apiBaseURL, getAuthToken } from "@/lib/api"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Badge } from "@/components/ui/badge"; import { Switch } from "@/components/ui/switch"; import PromptRoleSettings from "@/components/ai-steward/PromptRoleSettings"; import { FEISHU_EVENT_MODE_OPTIONS, type FeishuEventMode, getFeishuEventModeLabel, } from "@/lib/feishuEventMode"; // ==================== Types ==================== interface IntegrationSource { id: string; name: string; description: string; icon: any; status: "available" | "configured" | "needs_setup" | "unavailable"; priority: "high" | "medium" | "low"; estimated_benefit: string; setup_time: string; auto_detected: boolean; config_fields?: ConfigField[]; setup_guide?: string[]; } interface ConfigField { key: string; label: string; type: "text" | "password" | "url" | "toggle"; placeholder?: string; required: boolean; description?: string; } interface AIConfigSuggestion { recommended_sources: string[]; reasoning: string; estimated_impact: string; } interface ConfigStatus { feishu: { configured: boolean; app_id?: string; event_mode?: FeishuEventMode; }; wecom: { configured: boolean; corp_id?: string; agent_id?: string; token_preview?: string; encoding_aes_key_preview?: string; }; github: { configured: boolean; repos?: string[] }; browser: { installed: boolean }; hn_monitor: { active: boolean; last_run?: string }; } interface KnowledgeDoc { id: number; title: string; file_type: string; source_type: string; file_url?: string | null; status: "processing" | "complete" | "failed"; created_at?: string | null; last_fetched_at?: string | null; error_message?: string | null; } export default function AIConfigPage() { const navigate = useNavigate(); const [, setLoading] = useState(true); const [checking, setChecking] = useState(null); const [status, setStatus] = useState(null); const [suggestion, setSuggestion] = useState(null); const [activeTab, setActiveTab] = useState("overview"); const [scrollToSection, setScrollToSection] = useState(null); // Feishu config form const [feishuConfig, setFeishuConfig] = useState({ app_id: "", app_secret: "", event_mode: "long_connection" as FeishuEventMode }); // WeChat Work config form const [wecomConfig, setWecomConfig] = useState({ corp_id: "", agent_id: "", app_secret: "", token: "", encoding_aes_key: "" }); // GitHub config form const [githubConfig, setGithubConfig] = useState({ repo_url: "", webhook_url: "", access_token: "" }); // Monitor settings const [monitorSettings, setMonitorSettings] = useState({ hn_enabled: false, hn_interval: 30, browser_enabled: false }); const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null); const [wecomCopyTip, setWecomCopyTip] = useState(""); const [knowledgeDocs, setKnowledgeDocs] = useState([]); const [knowledgeFile, setKnowledgeFile] = useState(null); const [knowledgeURL, setKnowledgeURL] = useState(""); const [knowledgeURLTitle, setKnowledgeURLTitle] = useState(""); // Guide expansion state const [showFeishuGuide, setShowFeishuGuide] = useState(false); const [showWecomGuide, setShowWecomGuide] = useState(false); const [editingFeishu, setEditingFeishu] = useState(false); const [editingWecom, setEditingWecom] = useState(false); const [editingGithub, setEditingGithub] = useState(false); const governanceTools = [ { id: "brief-center", name: "增量任务包中心", description: "生成与查看任务包卡片", to: "/ai-config/task-brief-center", icon: Files, }, { id: "brief-template", name: "任务包模板管理", description: "统一维护模板与规范", to: "/ai-config/task-brief-templates", icon: LayoutTemplate, }, { id: "brief-runs", name: "任务包生成记录", description: "查看生成历史与状态", to: "/ai-config/task-brief-runs", icon: History, }, { id: "contract-board", name: "契约同步看板", description: "检查契约文档同步状态", to: "/ai-config/contract-sync-board", icon: ShieldCheck, }, { id: "model-routing", name: "模型路由配置", description: "动态切换函数模型路由", to: "/ai-config/model-routing-config", icon: Settings2, }, ]; // ==================== Integration Sources ==================== const integrationSources: IntegrationSource[] = [ { id: "feishu", name: "飞书群聊", description: "自动捕获群聊中的需求讨论,AI 分析价值", icon: MessageSquare, status: status?.feishu?.configured ? "configured" : "needs_setup", priority: "high", estimated_benefit: "每天自动捕获 5-10 个需求信号", setup_time: "5 分钟", auto_detected: true, config_fields: [ { key: "app_id", label: "应用编号", type: "text", placeholder: "cli_xxxxxxxxxxxxx", required: true }, { key: "app_secret", label: "应用密钥", type: "password", placeholder: "应用密钥", required: true }, ], setup_guide: [ "访问 https://open.feishu.cn/ 创建自建应用", "在「凭证与基础信息」获取应用编号和应用密钥", "飞书接入已统一为长连接模式,无需再配置回调地址", "添加权限:im:message, im:message:group_at_msg, im:chat", "订阅事件:接收消息 v1 (message.receive_v1)", "保存后后端会自动重启飞书长连接" ] }, { id: "wecom", name: "企业微信", description: "自动捕获企业微信群消息,AI 分析需求价值", icon: Building2, status: status?.wecom?.configured ? "configured" : "needs_setup", priority: "high", estimated_benefit: "每天自动捕获 5-10 个需求信号", setup_time: "5 分钟", auto_detected: true, config_fields: [ { key: "corp_id", label: "企业编号", type: "text", placeholder: "wwxxxxxxxxxxxxxx", required: true }, { key: "agent_id", label: "应用编号", type: "text", placeholder: "1000002", required: true }, { key: "app_secret", label: "应用密钥", type: "password", placeholder: "应用密钥", required: true }, { key: "token", label: "验证令牌", type: "text", placeholder: "回调验证令牌", required: true }, { key: "encoding_aes_key", label: "消息加密密钥", type: "text", placeholder: "消息加密密钥(43位)", required: true } ], setup_guide: [ "访问 https://work.weixin.qq.com/ 创建应用", "在「应用管理」获取应用编号和应用密钥", "在「我的企业」获取企业编号", "在「应用管理」-「接收消息」设置验证令牌和消息加密密钥", "添加权限:通讯录权限、消息权限", "点击保存后,复制回调地址到企业微信配置" ] }, { id: "hn", name: "技术资讯监控(HN)", description: "定时抓取技术前沿,分析行业趋势", icon: Activity, status: status?.hn_monitor?.active ? "configured" : "available", priority: "medium", estimated_benefit: "每周捕获 2-3 个高价值技术趋势", setup_time: "1 分钟", auto_detected: true, config_fields: [ { key: "hn_interval", label: "抓取间隔(分钟)", type: "text", placeholder: "30", required: false } ] }, { id: "github", name: "代码仓监控", description: "跟踪竞品仓库、上游依赖更新", icon: Github, status: status?.github?.configured ? "configured" : "available", priority: "medium", estimated_benefit: "及时获知竞品动态和依赖更新", setup_time: "10 分钟", auto_detected: true, config_fields: [ { key: "repo_url", label: "仓库地址", type: "url", placeholder: "https://github.com/user/repo", required: true }, { key: "access_token", label: "访问令牌", type: "password", placeholder: "ghp_xxxxxxxxxxxx", required: false } ] }, { id: "browser", name: "浏览器扩展", description: "监控访问的技术文档、竞品页面", icon: Globe, status: status?.browser?.installed ? "configured" : "needs_setup", priority: "low", estimated_benefit: "自动捕获浏览时的有价值内容", setup_time: "2 分钟", auto_detected: false, config_fields: [], setup_guide: [ "从 Chrome 应用商店安装 PMFlow 扩展", "登录您的 PMFlow 账号", "扩展会自动监控技术文档和竞品页面" ] } ]; // ==================== API Calls ==================== const loadStatus = async () => { setLoading(true); try { const token = getAuthToken(); if (!token) { navigate("/login"); return; } // Check Feishu config const feishuRes = await fetch(`${apiBaseURL}/feishu/config`, { headers: { Authorization: `Bearer ${token}` } }); if (feishuRes.ok) { const feishuData = await feishuRes.json(); const mode = "long_connection" as FeishuEventMode; setStatus(prev => ({ ...prev!, feishu: { configured: feishuData.is_configured, app_id: feishuData.app_id, event_mode: mode, }, })); setFeishuConfig({ app_id: feishuData.app_id || "", app_secret: feishuData.app_secret || "", event_mode: mode, }); } // Check WeChat Work config const wecomRes = await fetch(`${apiBaseURL}/wecom/config`, { headers: { Authorization: `Bearer ${token}` } }); if (wecomRes.ok) { const wecomData = await wecomRes.json(); setStatus(prev => ({ ...prev!, wecom: { configured: wecomData.is_configured, corp_id: wecomData.corp_id, agent_id: wecomData.agent_id, token_preview: wecomData.token_preview || "", encoding_aes_key_preview: wecomData.encoding_aes_key_preview || "", }, })); setWecomConfig({ corp_id: wecomData.corp_id || "", agent_id: wecomData.agent_id || "", app_secret: wecomData.app_secret || "", token: wecomData.token || "", encoding_aes_key: wecomData.encoding_aes_key || "", }); } // Get AI suggestions const suggestRes = await fetch(`${apiBaseURL}/ai-steward/config/suggest`, { headers: { Authorization: `Bearer ${token}` } }); if (suggestRes.ok) { const suggestData = await suggestRes.json(); setSuggestion(suggestData); } } catch (err) { console.error("Failed to load status:", err); } finally { setLoading(false); } }; const saveFeishuConfig = async () => { setChecking("feishu"); setMessage(null); if (!feishuConfig.app_id || !feishuConfig.app_secret) { setMessage({ type: "error", text: "请填写应用编号和应用密钥" }); setChecking(null); return; } try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/feishu/config`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify(feishuConfig) }); if (response.ok) { setMessage({ type: "success", text: "飞书配置已保存" }); setEditingFeishu(false); await loadStatus(); } else { const error = await response.json(); setMessage({ type: "error", text: error.detail || "保存失败" }); } } catch (err) { setMessage({ type: "error", text: "网络错误,请重试" }); } finally { setChecking(null); } }; const testFeishuConnection = async () => { setChecking("feishu-test"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/feishu/test-connection`, { method: "POST", headers: { Authorization: `Bearer ${token}` } }); const data = await response.json(); if (data.status === "success") { setMessage({ type: "success", text: "飞书连接测试成功!" }); } else { setMessage({ type: "error", text: data.message || "连接测试失败" }); } } catch (err) { setMessage({ type: "error", text: "测试失败" }); } finally { setChecking(null); } }; const deleteFeishuConfig = async () => { if (!confirm("确定要删除飞书配置吗?删除后将无法从飞书群聊捕获信号。")) return; setChecking("feishu-delete"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/feishu/config`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }); if (response.ok) { setMessage({ type: "success", text: "配置已删除" }); setFeishuConfig({ app_id: "", app_secret: "", event_mode: "long_connection" }); setEditingFeishu(false); await loadStatus(); } else { setMessage({ type: "error", text: "删除失败" }); } } catch (err) { setMessage({ type: "error", text: "网络错误" }); } finally { setChecking(null); } }; const saveWecomConfig = async () => { setChecking("wecom"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/wecom/config`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify(wecomConfig) }); if (response.ok) { setMessage({ type: "success", text: "企业微信配置已保存" }); setEditingWecom(false); await loadStatus(); } else { const error = await response.json(); setMessage({ type: "error", text: error.detail || "保存失败" }); } } catch (err) { setMessage({ type: "error", text: "网络错误,请重试" }); } finally { setChecking(null); } }; const testWecomConnection = async () => { setChecking("wecom-test"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/wecom/test-connection`, { method: "POST", headers: { Authorization: `Bearer ${token}` } }); const data = await response.json(); if (data.status === "success") { setMessage({ type: "success", text: "企业微信连接测试成功!" }); } else { setMessage({ type: "error", text: data.message || "连接测试失败" }); } } catch (err) { setMessage({ type: "error", text: "测试失败" }); } finally { setChecking(null); } }; const deleteWecomConfig = async () => { if (!confirm("确定要删除企业微信配置吗?删除后将无法从企业微信群聊捕获信号。")) return; setChecking("wecom-delete"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/wecom/config`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` } }); if (response.ok) { setMessage({ type: "success", text: "配置已删除" }); setWecomConfig({ corp_id: "", agent_id: "", app_secret: "", token: "", encoding_aes_key: "" }); setEditingWecom(false); await loadStatus(); } else { setMessage({ type: "error", text: "删除失败" }); } } catch (err) { setMessage({ type: "error", text: "网络错误" }); } finally { setChecking(null); } }; const getPublicBaseUrl = () => { const normalized = apiBaseURL.replace(/\/api\/?$/, ""); if (/^https?:\/\//i.test(normalized)) { return normalized.replace(/\/$/, ""); } return window.location.origin.replace(/\/$/, ""); }; const getWecomWebhookUrl = () => `${getPublicBaseUrl()}/wecom/webhook`; const startHNMonitor = async () => { setChecking("hn"); setMessage(null); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/ai-steward/signal/start-hn-monitor?interval_minutes=${monitorSettings.hn_interval}`, { method: "POST", headers: { Authorization: `Bearer ${token}` } }); if (response.ok) { setMessage({ type: "success", text: "技术资讯监控已启动" }); setMonitorSettings(prev => ({ ...prev!, hn_enabled: true })); } else { setMessage({ type: "error", text: "启动失败" }); } } catch (err) { setMessage({ type: "error", text: "网络错误" }); } finally { setChecking(null); } }; const copyText = async (text: string) => { try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(text); return true; } } catch { // fallback below } try { const input = document.createElement("textarea"); input.value = text; input.style.position = "fixed"; input.style.opacity = "0"; input.style.left = "-9999px"; document.body.appendChild(input); input.focus(); input.select(); const ok = document.execCommand("copy"); document.body.removeChild(input); return ok; } catch { return false; } }; const handleCopyWebhook = async (text: string) => { const ok = await copyText(text); if (ok) { setMessage({ type: "success", text: "已复制到剪切板" }); setWecomCopyTip("已复制到剪切板"); setTimeout(() => setWecomCopyTip(""), 1500); return; } setMessage({ type: "error", text: "复制失败,请手动复制地址" }); setWecomCopyTip("复制失败"); setTimeout(() => setWecomCopyTip(""), 1500); }; const loadKnowledgeDocs = async () => { try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/rag/knowledge-base/docs`, { headers: { Authorization: `Bearer ${token}` } }); if (!response.ok) return; const payload = await response.json(); const docs = (payload?.data ?? payload) || []; setKnowledgeDocs(Array.isArray(docs) ? docs : []); } catch (err) { console.error("Failed to load knowledge docs:", err); } }; const uploadKnowledgeFile = async () => { if (!knowledgeFile) { setMessage({ type: "error", text: "请先选择文件" }); return; } setChecking("knowledge-upload"); try { const token = getAuthToken(); const formData = new FormData(); formData.append("file", knowledgeFile); const response = await fetch(`${apiBaseURL}/rag/knowledge-base/upload`, { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: formData, }); const payload = await response.json().catch(() => ({})); if (!response.ok) { setMessage({ type: "error", text: payload?.detail || "上传失败" }); return; } setKnowledgeFile(null); setMessage({ type: "success", text: "文件已提交,正在向量化处理" }); await loadKnowledgeDocs(); } catch (err) { setMessage({ type: "error", text: "上传失败,请检查网络" }); } finally { setChecking(null); } }; const addKnowledgeURL = async () => { if (!knowledgeURL.trim()) { setMessage({ type: "error", text: "请输入 URL" }); return; } setChecking("knowledge-url"); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/rag/knowledge-base/urls`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ url: knowledgeURL.trim(), title: knowledgeURLTitle.trim() || undefined, }), }); const payload = await response.json().catch(() => ({})); if (!response.ok) { setMessage({ type: "error", text: payload?.detail || "URL 添加失败" }); return; } setKnowledgeURL(""); setKnowledgeURLTitle(""); setMessage({ type: "success", text: "URL 已加入知识库,正在抓取与向量化" }); await loadKnowledgeDocs(); } catch (err) { setMessage({ type: "error", text: "URL 添加失败,请稍后重试" }); } finally { setChecking(null); } }; const refreshKnowledgeDoc = async (docId: number) => { setChecking(`knowledge-refresh-${docId}`); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/rag/knowledge-base/docs/${docId}/refresh`, { method: "POST", headers: { Authorization: `Bearer ${token}` }, }); if (!response.ok) { const payload = await response.json().catch(() => ({})); setMessage({ type: "error", text: payload?.detail || "刷新失败" }); return; } setMessage({ type: "success", text: "已触发刷新,正在处理" }); await loadKnowledgeDocs(); } catch (err) { setMessage({ type: "error", text: "刷新失败,请稍后重试" }); } finally { setChecking(null); } }; const deleteKnowledgeDoc = async (docId: number) => { if (!confirm("确认删除该知识库条目及其向量数据?")) return; setChecking(`knowledge-delete-${docId}`); try { const token = getAuthToken(); const response = await fetch(`${apiBaseURL}/rag/knowledge-base/docs/${docId}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` }, }); if (!response.ok) { const payload = await response.json().catch(() => ({})); setMessage({ type: "error", text: payload?.detail || "删除失败" }); return; } setMessage({ type: "success", text: "已删除知识库条目" }); await loadKnowledgeDocs(); } catch (err) { setMessage({ type: "error", text: "删除失败,请稍后重试" }); } finally { setChecking(null); } }; // ==================== Initial Load ==================== // Scroll to section when tab changes to configure useEffect(() => { if (activeTab === "configure" && scrollToSection) { // Small delay to ensure the tab content is rendered setTimeout(() => { const element = document.getElementById(`config-${scrollToSection}`); if (element) { element.scrollIntoView({ behavior: "smooth", block: "start" }); } setScrollToSection(null); }, 100); } }, [activeTab, scrollToSection]); const handleConfigureClick = (sourceId: string) => { setScrollToSection(sourceId); setActiveTab("configure"); }; useEffect(() => { setStatus({ feishu: { configured: false }, wecom: { configured: false }, github: { configured: false }, browser: { installed: false }, hn_monitor: { active: false } }); loadStatus(); }, []); useEffect(() => { if (activeTab !== "knowledge") return; loadKnowledgeDocs(); }, [activeTab]); useEffect(() => { if (activeTab !== "knowledge") return; if (!knowledgeDocs.some((item) => item.status === "processing")) return; const timer = setInterval(() => { loadKnowledgeDocs(); }, 3000); return () => clearInterval(timer); }, [activeTab, knowledgeDocs]); // ==================== Helper Components ==================== const StatusBadge = ({ status }: { status: IntegrationSource["status"] }) => { const config = { configured: { label: "已配置", variant: "default" as const, icon: CheckCircle2, color: "text-green-600" }, available: { label: "可用", variant: "secondary" as const, icon: Sparkles, color: "text-blue-600" }, needs_setup: { label: "待配置", variant: "outline" as const, icon: AlertTriangle, color: "text-orange-600" }, unavailable: { label: "不可用", variant: "secondary" as const, icon: AlertCircle, color: "text-slate-400" } }; const { label, variant, icon: Icon, color } = config[status]; return ( {label} ); }; const PriorityBadge = ({ priority }: { priority: IntegrationSource["priority"] }) => { const config = { high: { label: "高优先级", className: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300" }, medium: { label: "中优先级", className: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300" }, low: { label: "低优先级", className: "bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300" } }; const { label, className } = config[priority]; return {label}; }; // ==================== Render ==================== return (
{/* Header */}

AI 智能配置中心

AI 自动识别可配置的集成源,一键启用主动捕获能力

{/* AI Suggestion Card */} {suggestion && (

AI 建议配置方案

{suggestion.reasoning}

预期影响: {suggestion.estimated_impact}

)} {/* Message */} {message && (
{message.type === "success" ? ( ) : ( )} {message.text}
)} 配置治理工具 新增治理页面统一收敛到智能配置中心入口,避免侧栏信息过载。
{governanceTools.map(({ id, name, description, to, icon: Icon }) => (

{name}

{description}

))}
{/* Main Content */} 集成源概览 快速配置 知识库 高级设置 Prompt 设置 {/* Overview Tab */}
{integrationSources.map((source) => { const Icon = source.icon; return (
{source.name} {source.description}
优先级
预计收益 {source.estimated_benefit}
配置耗时 {source.setup_time}
); })}
{/* Quick Configure Tab */}
{/* Feishu Config */}
飞书群聊集成 {status?.feishu?.configured && ( 已配置 )}
AI 自动从飞书群聊捕获需求信号,无需手动录入
{/* Setup Guide */} {showFeishuGuide && (

飞书配置指南(6 步完成)

{integrationSources.find(s => s.id === "feishu")?.setup_guide?.map((step, index) => (
{index + 1}
{step}
))}
⚠️ 配置完成后,请点击下方"测试连接"按钮验证
)} {status?.feishu?.configured && !editingFeishu ? (
飞书已配置 {status.feishu.app_id && ( (应用编号: {status.feishu.app_id}) )}

当前接收模式:{getFeishuEventModeLabel(status.feishu.event_mode || "long_connection")}

) : (
{status?.feishu?.configured && (
正在修改已有配置:已自动回填当前配置,可直接核对并修改后保存。
)}

飞书接入已统一为 long_connection

{FEISHU_EVENT_MODE_OPTIONS.map((option) => ( ))}
setFeishuConfig({ ...feishuConfig, app_id: e.target.value })} />
setFeishuConfig({ ...feishuConfig, app_secret: e.target.value })} />
已切换到飞书长连接模式。无需配置 Webhook、Encrypt Key 或 Verification Token。
{status?.feishu?.configured && ( )}
)}
当前选择的是「长连接」模式,无需配置 Webhook 请求地址。
{/* WeChat Work Config */}
企业微信集成 {status?.wecom?.configured && ( 已配置 )}
AI 自动从企业微信群聊捕获需求信号,无需手动录入
{/* Setup Guide */} {showWecomGuide && (

企业微信配置指南(6 步完成)

{integrationSources.find(s => s.id === "wecom")?.setup_guide?.map((step, index) => (
{index + 1}
{step}
))}
⚠️ 配置完成后,请点击下方"测试连接"按钮验证
)} {status?.wecom?.configured && !editingWecom ? (
企业微信已配置 {status.wecom.corp_id && ( (企业编号: {status.wecom.corp_id}) )}
{status.wecom.agent_id && (

应用编号:{status.wecom.agent_id}

)}

Token: {status.wecom.token_preview || "未设置"},EncodingAESKey: {status.wecom.encoding_aes_key_preview || "未设置"}

) : (
{status?.wecom?.configured && (
正在修改已有配置:已自动回填当前配置,可直接核对并修改后保存。
)}
setWecomConfig({ ...wecomConfig, corp_id: e.target.value })} />
setWecomConfig({ ...wecomConfig, agent_id: e.target.value })} />
setWecomConfig({ ...wecomConfig, app_secret: e.target.value })} />
setWecomConfig({ ...wecomConfig, token: e.target.value })} />
setWecomConfig({ ...wecomConfig, encoding_aes_key: e.target.value })} />
{status?.wecom?.configured && ( )}
)} {/* 回调地址 */}
{wecomCopyTip && {wecomCopyTip}}
{getWecomWebhookUrl()}

复制此回调地址到企业微信管理后台 - 应用管理 - 接收消息 - 请求地址

{/* HN Monitor */}
技术资讯监控(HN) {status?.hn_monitor?.active && ( 运行中 )}
定时抓取 HN 首页,AI 分析技术趋势

每 {monitorSettings.hn_interval} 分钟抓取一次

{ if (checked) startHNMonitor(); setMonitorSettings({ ...monitorSettings, hn_enabled: checked }); }} />
{!monitorSettings.hn_enabled && ( )}
{/* GitHub */}
代码仓监控 {status?.github?.configured && ( 已配置 )}
跟踪竞品仓库更新、上游依赖变更
{status?.github?.configured && !editingGithub ? (
代码仓监控已配置 {status.github.repos && ( ({status.github.repos.length} 个仓库) )}
) : (
setGithubConfig({ ...githubConfig, repo_url: e.target.value })} />

支持输入多个仓库,用逗号分隔

setGithubConfig({ ...githubConfig, webhook_url: e.target.value })} />

仓库侧配置的回调地址

setGithubConfig({ ...githubConfig, access_token: e.target.value })} />

用于获取仓库信息的个人访问令牌

{status?.github?.configured && ( )}
)}
{/* Browser Extension */}
浏览器扩展 敬请期待
自动监控访问的技术文档、竞品页面

浏览器扩展正在开发中

支持功能:自动捕获页面内容、智能分析价值

{/* Knowledge Base Tab */}
文件上传 支持 PDF / Word / Markdown / TXT,上传后自动分块与向量化。 setKnowledgeFile(e.target.files?.[0] || null)} />
{knowledgeFile ? `已选择: ${knowledgeFile.name}` : "未选择文件"}
URL 知识源 添加公开文档 URL,系统自动抓取并向量化,可手动刷新。 setKnowledgeURLTitle(e.target.value)} /> setKnowledgeURL(e.target.value)} />
知识库列表 处理中状态会每 3 秒自动刷新。 {knowledgeDocs.length === 0 ? (
暂无知识库条目
) : (
{knowledgeDocs.map((doc) => (
{doc.title}
类型: {doc.file_type} · 来源: {doc.source_type}
上传时间: {doc.created_at ? new Date(doc.created_at).toLocaleString() : "-"} {doc.last_fetched_at ? ` · 最近抓取: ${new Date(doc.last_fetched_at).toLocaleString()}` : ""}
{doc.file_url && (
{doc.file_url}
)} {doc.error_message && (
{doc.error_message}
)}
{doc.status === "processing" ? "processing" : doc.status === "complete" ? "complete" : "failed"} {doc.source_type === "url" && ( )}
))}
)}
{/* Advanced Tab */}
自动检测规则 AI 自动判断信号价值的阈值设置
影响分 ≥ 0.7

低于此阈值的信号将被忽略,减少噪音

中等

控制认知冲突检测的严格程度

每天 9:00

个性化每日简报的推送时间

数据同步设置 控制数据同步频率和范围

重要事件立即推送

导入过去 30 天的聊天记录

新信号自动关联到活跃项目

{/* Prompt Profiles Tab */}
); }