feat(config): 添加任务配置中的模型模式支持

- 在config.json中为任务添加mode和useBrowser字段
- 默认使用glm-5模型模式

feat(ui): 更新前端界面显示模型信息并添加模型选择功能

- 在任务表格中添加模型列显示
- 在新增/编辑任务表单中添加模型选择下拉框
- 支持多种模型选项包括qwen3.5-plus、qwen3-max等
- 更新表格列数以适应新增的模型列

feat(core): 实现任务模型模式的功能支持

- 在agentService.js中添加normalizeMode函数处理模型模式
- 修改createTask和runAgentTask函数支持mode参数
- 在scheduler.js中实现任务的模型模式配置
- 在server.js中添加模型模式的标准化和API支持
- 为任务运行时添加模型模式的日志输出
```
This commit is contained in:
2026-03-10 18:11:11 +08:00
parent b9270428db
commit 40118ec508
5 changed files with 66 additions and 6 deletions

View File

@@ -8,6 +8,13 @@ const DEFAULT_POLL_INTERVAL = 3000; // 3秒轮询
const DEFAULT_TIMEOUT = 3600000; // 1小时超时
const FETCH_TIMEOUT = 30000; // 单次 fetch 30秒超时
const MAX_FETCH_RETRIES = 5; // 网络错误最多重试5次
const DEFAULT_MODE = 'qwen3.5-plus';
function normalizeMode(value) {
if (typeof value === 'string' && value.trim()) return value.trim();
return DEFAULT_MODE;
}
function generateTaskId() {
return `task-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
@@ -43,13 +50,14 @@ async function fetchWithRetry(url, fetchOptions, retries = MAX_FETCH_RETRIES, lo
async function createTask(prompt, options = {}) {
const baseUrl = options.baseUrl || DEFAULT_BASE_URL;
const useBrowser = options.useBrowser ?? false;
const mode = normalizeMode(options.mode);
const taskId = generateTaskId();
const logPrefix = options.logPrefix || '[Agent]';
const res = await fetchWithRetry(`${baseUrl}/agent/createTask`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ taskId, prompt, useBrowser }),
body: JSON.stringify({ taskId, prompt, useBrowser, mode }),
}, MAX_FETCH_RETRIES, logPrefix);
if (!res.ok) {
@@ -97,12 +105,14 @@ async function checkTask(taskId, options = {}) {
export async function runAgentTask(prompt, options = {}) {
const baseUrl = options.baseUrl || DEFAULT_BASE_URL;
const useBrowser = options.useBrowser ?? false;
const mode = normalizeMode(options.mode);
const pollInterval = options.pollInterval || DEFAULT_POLL_INTERVAL;
const timeout = options.timeout || DEFAULT_TIMEOUT;
const logPrefix = options.logPrefix || '[Agent]';
console.log(`${logPrefix} 创建任务...`);
const { taskId } = await createTask(prompt, { baseUrl, useBrowser, logPrefix });
console.log(`${logPrefix} 使用 mode: ${mode}`);
const { taskId } = await createTask(prompt, { baseUrl, useBrowser, mode, logPrefix });
console.log(`${logPrefix} 任务已创建: ${taskId}`);
const startTime = Date.now();

View File

@@ -10,6 +10,12 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const RESULTS_PATH = join(__dirname, '..', 'results.json');
const DEFAULT_TASK_MODE = 'qwen3.5-plus';
function normalizeTaskMode(value) {
if (typeof value === 'string' && value.trim()) return value.trim();
return DEFAULT_TASK_MODE;
}
function loadConfig() {
try {
@@ -47,10 +53,13 @@ function appendResult(result) {
async function runTask(task, agentCfg) {
const useBrowser = typeof task.useBrowser === 'boolean' ? task.useBrowser : agentCfg.useBrowser;
const mode = normalizeTaskMode(task.mode);
console.log(`[定时任务][Agent] ${task.city}:开始执行`);
console.log(`[定时任务][Agent] ${task.city}mode=${mode}`);
const { results } = await runAgentTask(task.prompt, {
baseUrl: agentCfg.baseUrl,
useBrowser,
mode,
pollInterval: agentCfg.pollInterval,
timeout: agentCfg.timeout,
logPrefix: `[定时任务][Agent][${task.city}]`,

View File

@@ -18,6 +18,7 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const CONFIG_PATH = join(__dirname, '..', 'config.json');
const RESULTS_PATH = join(__dirname, '..', 'results.json');
const DEFAULT_TASK_MODE = 'qwen3.5-plus';
function readConfig() {
return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
@@ -31,6 +32,11 @@ function normalizeUseBrowser(value) {
return value === true || value === 'true';
}
function normalizeTaskMode(value) {
if (typeof value === 'string' && value.trim()) return value.trim();
return DEFAULT_TASK_MODE;
}
// ========== 抓取结果存取 ==========
function readResults() {
@@ -119,7 +125,8 @@ app.get('/api/results/filters', (req, res) => {
app.get('/api/tasks', (req, res) => {
try {
const cfg = readConfig();
res.json({ success: true, data: cfg.tasks || [] });
const tasks = (cfg.tasks || []).map(t => ({ ...t, mode: normalizeTaskMode(t.mode) }));
res.json({ success: true, data: tasks });
} catch (e) {
res.status(500).json({ success: false, error: e.message });
}
@@ -135,6 +142,7 @@ app.post('/api/tasks', (req, res) => {
prompt: req.body.prompt || '',
enabled: req.body.enabled !== false,
useBrowser: normalizeUseBrowser(req.body.useBrowser),
mode: normalizeTaskMode(req.body.mode),
};
cfg.tasks.push(item);
saveConfig(cfg);
@@ -153,6 +161,9 @@ app.put('/api/tasks/:id', (req, res) => {
if (Object.prototype.hasOwnProperty.call(patch, 'useBrowser')) {
patch.useBrowser = normalizeUseBrowser(patch.useBrowser);
}
if (Object.prototype.hasOwnProperty.call(patch, 'mode')) {
patch.mode = normalizeTaskMode(patch.mode);
}
cfg.tasks[idx] = { ...cfg.tasks[idx], ...patch, id: req.params.id };
saveConfig(cfg);
res.json({ success: true, data: cfg.tasks[idx] });
@@ -183,11 +194,14 @@ async function runTask(task) {
const cfg = readConfig();
const agentCfg = cfg.agent || {};
const useBrowser = typeof task.useBrowser === 'boolean' ? task.useBrowser : agentCfg.useBrowser;
const mode = normalizeTaskMode(task.mode);
console.log(`[Agent] ${task.city}:开始执行`);
console.log(`[Agent] ${task.city}mode=${mode}`);
const { results } = await runAgentTask(task.prompt, {
baseUrl: agentCfg.baseUrl,
useBrowser,
mode,
pollInterval: agentCfg.pollInterval,
timeout: agentCfg.timeout,
logPrefix: `[Agent][${task.city}]`,