chore: opencode冗余清理 + LLM任务级模型选择 + systemd服务化
- 删除 opencode_search.py / mcp_search_server.py 及所有 MCP 引用 - 移除搜索缓存定时任务(scheduled_refresh_search_cache) - 清理前后端所有 opencode/MCP 代码和注释 - LLM 提供商量换:opencode-go→nvidia(默认)+sensenova(合规审查) - llm_configs 新增 is_default 字段,API 层互斥逻辑 - 所有定时任务支持独立 LLM 模型选择(LLM_TASK_PROVIDER env) - compliance_optimizer.py 修复:import os / 解硬编码 / 关键词过滤 - Scheduler 日志修复:始终 INSERT,避免僵尸 running 行 - Systemd 服务化:Restart=always / 单 worker / Type=exec - 搜索提供商:替换 opencode→360/搜狗/微信(免 Key) - 更新 AGENTS.md / PROGRESS.md
This commit is contained in:
@@ -103,6 +103,7 @@
|
||||
<div><span>最后运行</span><span>{{ mod.last_run || '从未' }}<span v-if="mod.last_status" :style="{marginLeft:'6px',padding:'1px 6px',borderRadius:'8px',fontSize:'11px',fontWeight:500}"><span v-if="mod.last_status==='success'" style="color:#67c23a;">✅成功</span><span v-else-if="mod.last_status==='failed'" style="color:#f56c6c;">❌失败</span><span v-else-if="mod.last_status==='running'" style="color:#e6a23c;">⏳运行中</span></span></span></div>
|
||||
<div><span>下次运行</span><span>{{ mod.next_run || '—' }}</span></div>
|
||||
<div><span>累计运行</span><span>{{ mod.total_runs }} 次 <span style="color:#67c23a;">{{ mod.success_runs }} 成功</span> <span style="color:#f56c6c;">{{ mod.failed_runs }} 失败</span><span v-if="mod.running > 0" style="color:#e6a23c;"> {{ mod.running }} 运行中</span></span></div>
|
||||
<div><span>LLM 模型</span><span>{{ (mod.params && mod.params.llm_provider) || (defaultLlmLabel || '默认') }}</span></div>
|
||||
<div style="margin-top:10px; border-bottom:none;">
|
||||
<el-button size="small" type="primary" @click.stop="triggerModule(mod.module_id)" :loading="runningModule === mod.module_id" :disabled="!mod.enabled">立即运行</el-button>
|
||||
<el-button size="small" @click.stop="openModuleDetail(mod)">查看详情</el-button>
|
||||
@@ -346,10 +347,17 @@
|
||||
<el-input v-model="drawerData.schedule" size="small" style="width:120px;" placeholder="HH:MM" :disabled="savingConfig"></el-input>
|
||||
<span style="font-size:12px;color:#909399;">每日执行时间(HH:MM)</span>
|
||||
</div>
|
||||
<div style="display:flex;gap:16px;align-items:center;margin-bottom:12px;">
|
||||
<span style="font-size:13px;color:#606266;width:60px;">LLM</span>
|
||||
<el-select v-model="drawerData.params.llm_provider" size="small" style="width:200px;" clearable placeholder="系统默认" @change="saveModuleConfig" :disabled="savingConfig">
|
||||
<el-option v-for="c in llmConfigs.filter(x=>x.is_active)" :key="c.id" :label="c.provider + ' (' + c.model + ')' + (c.is_default ? ' (默认)' : '')" :value="c.provider"/>
|
||||
</el-select>
|
||||
<span style="font-size:12px;color:#909399;">留空则使用系统默认模型</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="Object.keys(drawerData.params || {}).length > 0">
|
||||
<div v-if="Object.keys(drawerData.params || {}).filter(k => k !== 'llm_provider').length > 0">
|
||||
<div style="font-size:13px;font-weight:600;margin-bottom:12px;">参数配置</div>
|
||||
<div v-for="(val, key) in drawerData.params" :key="key" style="margin-bottom:12px;display:flex;align-items:center;gap:12px;">
|
||||
<div v-for="(val, key) in drawerData.params" v-if="key !== 'llm_provider'" :key="key" style="margin-bottom:12px;display:flex;align-items:center;gap:12px;">
|
||||
<span style="font-size:13px;color:#606266;width:120px;">{{ key }}</span>
|
||||
<el-input v-if="typeof val === 'string'" v-model="drawerData.params[key]" size="small" style="flex:1;" @change="saveModuleConfig" :disabled="savingConfig"></el-input>
|
||||
<el-input-number v-else-if="typeof val === 'number'" v-model="drawerData.params[key]" size="small" :disabled="savingConfig" @change="saveModuleConfig"></el-input-number>
|
||||
@@ -552,13 +560,11 @@ const TasksApp = {
|
||||
'scheduled_optimize': { icon: 'IconSearch', name: '合规审查', defaultTime: '04:30' },
|
||||
'scheduled_optimize_sources': { icon: 'IconSetting', name: '信息源优化', defaultTime: '05:00' },
|
||||
'scheduled_metrics_sync': { icon: 'IconDashboard', name: '指标同步', defaultTime: '06:00' },
|
||||
'scheduled_refresh_search_cache': { icon: 'IconRefresh', name: '搜索缓存', defaultTime: '01:00' },
|
||||
'scheduled_fetch_trends': { icon: 'IconRefresh', name: '热点趋势', defaultTime: '01:10' },
|
||||
'scheduled_task_monitor': { icon: 'IconRefresh', name: '任务监控', defaultTime: '*' },
|
||||
};
|
||||
const MODULE_TRIGGER_ENDPOINTS = {
|
||||
scheduled_collect: '/api/system/collect/run',
|
||||
scheduled_refresh_search_cache: '/api/system/refresh-search-cache/run',
|
||||
scheduled_fetch_trends: '/api/system/trends/run',
|
||||
scheduled_generate: '/api/system/generate/run',
|
||||
scheduled_optimize: '/api/system/review/run',
|
||||
@@ -592,6 +598,7 @@ const TasksApp = {
|
||||
sourceForm: { name: '', source_type: 'web_search', query: '', credibility: 'medium', focus: '', sort_order: 0, is_active: true },
|
||||
sourcePage: 1, sourcePageSize: 10,
|
||||
SCHEDULER_JOBS, MODULE_TRIGGER_ENDPOINTS,
|
||||
llmConfigs: [], defaultLlmLabel: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -645,17 +652,28 @@ const TasksApp = {
|
||||
async loadModules() {
|
||||
this.moduleLoading = true;
|
||||
try {
|
||||
const data = await this.api('/api/system/modules/status');
|
||||
const [data, llmConfigs] = await Promise.all([
|
||||
this.api('/api/system/modules/status'),
|
||||
this.loadLLMConfigs(),
|
||||
]);
|
||||
if (!data) return;
|
||||
this.modules = data.modules || [];
|
||||
this.schedulerRunning = data.scheduler && data.scheduler.running === true;
|
||||
} catch (e) { console.error(e); }
|
||||
finally { this.moduleLoading = false; }
|
||||
},
|
||||
async loadLLMConfigs() {
|
||||
try {
|
||||
const configs = await this.api('/api/admin/llmconfigs');
|
||||
this.llmConfigs = configs || [];
|
||||
const def = (configs || []).find(c => c.is_default);
|
||||
this.defaultLlmLabel = def ? def.provider + ' (' + def.model + ')' : '';
|
||||
} catch (e) { console.error('loadLLMConfigs error:', e); this.llmConfigs = []; }
|
||||
},
|
||||
async openModuleDetail(mod) {
|
||||
this.showDrawer = true;
|
||||
this.drawerTitle = mod.title + ' 详情';
|
||||
this.drawerData = { ...mod };
|
||||
this.drawerData = { ...mod, params: { ...(mod.params || {}) } };
|
||||
this.drawerError = '';
|
||||
this.drawerLoading = true;
|
||||
this.drawerTab = 'inputs';
|
||||
@@ -667,7 +685,7 @@ const TasksApp = {
|
||||
this.api('/api/admin/task-configs/history/' + mod.module_id + '?limit=20'),
|
||||
this.api('/api/admin/prompt-configs?module_id=' + mod.module_id),
|
||||
]);
|
||||
this.drawerData = { ...mod, ...detail };
|
||||
this.drawerData = { ...mod, ...detail, params: { ...((detail.params || mod.params || {})) } };
|
||||
this.drawerHistory = history || [];
|
||||
this.drawerPrompts = prompts || [];
|
||||
} catch (e) { this.drawerError = e.message; }
|
||||
|
||||
Reference in New Issue
Block a user