mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-20 21:57:14 +08:00
feat: add enable_thinking config to control deep reasoning on web console
This commit is contained in:
@@ -125,9 +125,8 @@
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.agent-thinking-step .thinking-header.no-toggle { cursor: default; }
|
||||
.agent-thinking-step .thinking-header:not(.no-toggle):hover { color: #64748b; }
|
||||
.dark .agent-thinking-step .thinking-header:not(.no-toggle):hover { color: #cbd5e1; }
|
||||
.agent-thinking-step .thinking-header:hover { color: #64748b; }
|
||||
.dark .agent-thinking-step .thinking-header:hover { color: #cbd5e1; }
|
||||
.agent-thinking-step .thinking-header i:first-child { font-size: 0.625rem; margin-top: 1px; }
|
||||
.agent-thinking-step .thinking-chevron {
|
||||
font-size: 0.5rem;
|
||||
@@ -158,6 +157,11 @@
|
||||
.agent-thinking-step .thinking-full p { margin: 0.25em 0; }
|
||||
.agent-thinking-step .thinking-full p:first-child { margin-top: 0; }
|
||||
.agent-thinking-step .thinking-full p:last-child { margin-bottom: 0; }
|
||||
.agent-thinking-step .thinking-duration {
|
||||
font-size: 0.625rem;
|
||||
color: #b0b8c4;
|
||||
margin-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
/* Content step - real text output frozen before tool calls */
|
||||
.agent-content-step {
|
||||
|
||||
@@ -38,6 +38,7 @@ const I18N = {
|
||||
config_max_tokens: '最大上下文 Token', config_max_tokens_hint: '对话中 Agent 能输入的最大 Token 长度,超过后会智能压缩处理',
|
||||
config_max_turns: '最大记忆轮次', config_max_turns_hint: '一问一答为一轮,超过后会智能压缩处理',
|
||||
config_max_steps: '最大执行步数', config_max_steps_hint: '单次对话中 Agent 最多调用工具的次数',
|
||||
config_enable_thinking: '深度思考', config_enable_thinking_hint: '启用后在 Web 端展示模型推理过程',
|
||||
config_channel_type: '通道类型',
|
||||
config_provider: '模型厂商', config_model_name: '模型',
|
||||
config_custom_model_hint: '输入自定义模型名称',
|
||||
@@ -80,6 +81,7 @@ const I18N = {
|
||||
logs_title: '日志', logs_desc: '实时日志输出 (run.log)',
|
||||
logs_live: '实时', logs_coming_msg: '日志流即将在此提供。将连接 run.log 实现类似 tail -f 的实时输出。',
|
||||
error_send: '发送失败,请稍后再试。', error_timeout: '请求超时,请再试一次。',
|
||||
thinking_in_progress: '思考中...', thinking_done: '已深度思考', thinking_duration: '耗时',
|
||||
},
|
||||
en: {
|
||||
console: 'Console',
|
||||
@@ -108,6 +110,7 @@ const I18N = {
|
||||
config_max_tokens: 'Max Context Tokens', config_max_tokens_hint: 'Max tokens the Agent can input per conversation, auto-compressed when exceeded',
|
||||
config_max_turns: 'Max Memory Turns', config_max_turns_hint: 'One Q&A pair = one turn, auto-compressed when exceeded',
|
||||
config_max_steps: 'Max Steps', config_max_steps_hint: 'Max tool calls the Agent can make in a single conversation',
|
||||
config_enable_thinking: 'Deep Thinking', config_enable_thinking_hint: 'Show model reasoning on web console',
|
||||
config_channel_type: 'Channel Type',
|
||||
config_provider: 'Provider', config_model_name: 'Model',
|
||||
config_custom_model_hint: 'Enter custom model name',
|
||||
@@ -150,6 +153,7 @@ const I18N = {
|
||||
logs_title: 'Logs', logs_desc: 'Real-time log output (run.log)',
|
||||
logs_live: 'Live', logs_coming_msg: 'Log streaming will be available here. Connects to run.log for real-time output similar to tail -f.',
|
||||
error_send: 'Failed to send. Please try again.', error_timeout: 'Request timeout. Please try again.',
|
||||
thinking_in_progress: 'Thinking...', thinking_done: 'Thought', thinking_duration: 'Duration',
|
||||
}
|
||||
};
|
||||
|
||||
@@ -863,6 +867,7 @@ function startSSE(requestId, loadingEl, timestamp) {
|
||||
let currentToolEl = null;
|
||||
let currentReasoningEl = null; // live reasoning bubble
|
||||
let reasoningText = '';
|
||||
let reasoningStartTime = 0;
|
||||
let done = false;
|
||||
|
||||
const MAX_RECONNECTS = 10;
|
||||
@@ -907,28 +912,25 @@ function startSSE(requestId, loadingEl, timestamp) {
|
||||
ensureBotEl();
|
||||
reasoningText += item.content;
|
||||
if (!currentReasoningEl) {
|
||||
reasoningStartTime = Date.now();
|
||||
currentReasoningEl = document.createElement('div');
|
||||
currentReasoningEl.className = 'agent-step agent-thinking-step';
|
||||
currentReasoningEl.innerHTML = `
|
||||
<div class="thinking-header" onclick="this.parentElement.classList.toggle('expanded')">
|
||||
<i class="fas fa-lightbulb text-amber-400 flex-shrink-0"></i>
|
||||
<span class="thinking-summary"></span>
|
||||
<span class="thinking-summary">${t('thinking_in_progress')}</span>
|
||||
<i class="fas fa-chevron-right thinking-chevron"></i>
|
||||
</div>
|
||||
<div class="thinking-full"></div>`;
|
||||
stepsEl.appendChild(currentReasoningEl);
|
||||
}
|
||||
const oneLine = reasoningText.trim().replace(/\n+/g, ' ');
|
||||
currentReasoningEl.querySelector('.thinking-summary').textContent =
|
||||
oneLine.length > 80 ? oneLine.substring(0, 80) + '…' : oneLine;
|
||||
currentReasoningEl.querySelector('.thinking-full').innerHTML = renderMarkdown(reasoningText);
|
||||
scrollChatToBottom();
|
||||
|
||||
} else if (item.type === 'delta') {
|
||||
ensureBotEl();
|
||||
if (currentReasoningEl) {
|
||||
if (reasoningText.trim().replace(/\n+/g, ' ').length <= 80)
|
||||
currentReasoningEl.classList.add('no-expand');
|
||||
finalizeThinking(currentReasoningEl, reasoningStartTime, reasoningText);
|
||||
currentReasoningEl = null;
|
||||
reasoningText = '';
|
||||
}
|
||||
@@ -951,8 +953,7 @@ function startSSE(requestId, loadingEl, timestamp) {
|
||||
} else if (item.type === 'tool_start') {
|
||||
ensureBotEl();
|
||||
if (currentReasoningEl) {
|
||||
if (reasoningText.trim().replace(/\n+/g, ' ').length <= 80)
|
||||
currentReasoningEl.classList.add('no-expand');
|
||||
finalizeThinking(currentReasoningEl, reasoningStartTime, reasoningText);
|
||||
currentReasoningEl = null;
|
||||
reasoningText = '';
|
||||
}
|
||||
@@ -1089,8 +1090,7 @@ function startSSE(requestId, loadingEl, timestamp) {
|
||||
if (done) return;
|
||||
|
||||
if (currentReasoningEl) {
|
||||
if (reasoningText.trim().replace(/\n+/g, ' ').length <= 80)
|
||||
currentReasoningEl.classList.add('no-expand');
|
||||
finalizeThinking(currentReasoningEl, reasoningStartTime, reasoningText);
|
||||
currentReasoningEl = null;
|
||||
reasoningText = '';
|
||||
}
|
||||
@@ -1214,28 +1214,24 @@ function renderToolCallsHtml(toolCalls) {
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function finalizeThinking(el, startTime, text) {
|
||||
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
||||
el.querySelector('.thinking-summary').textContent = t('thinking_done');
|
||||
const fullDiv = el.querySelector('.thinking-full');
|
||||
fullDiv.innerHTML = `<div class="thinking-duration">${t('thinking_duration')} ${elapsed}s</div>` + renderMarkdown(text);
|
||||
}
|
||||
|
||||
function renderThinkingHtml(text) {
|
||||
if (!text || !text.trim()) return '';
|
||||
const full = text.trim();
|
||||
const oneLine = full.replace(/\n+/g, ' ');
|
||||
if (oneLine.length > 80) {
|
||||
const truncated = oneLine.substring(0, 80) + '…';
|
||||
return `
|
||||
return `
|
||||
<div class="agent-step agent-thinking-step">
|
||||
<div class="thinking-header" onclick="this.parentElement.classList.toggle('expanded')">
|
||||
<i class="fas fa-lightbulb text-amber-400 flex-shrink-0"></i>
|
||||
<span class="thinking-summary">${escapeHtml(truncated)}</span>
|
||||
<span class="thinking-summary">${t('thinking_done')}</span>
|
||||
<i class="fas fa-chevron-right thinking-chevron"></i>
|
||||
</div>
|
||||
<div class="thinking-full">${renderMarkdown(full)}</div>
|
||||
</div>`;
|
||||
}
|
||||
return `
|
||||
<div class="agent-step agent-thinking-step no-expand">
|
||||
<div class="thinking-header no-toggle">
|
||||
<i class="fas fa-lightbulb text-amber-400 flex-shrink-0"></i>
|
||||
<span>${escapeHtml(oneLine)}</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -1649,6 +1645,7 @@ function initConfigView(data) {
|
||||
document.getElementById('cfg-max-tokens').value = data.agent_max_context_tokens || 50000;
|
||||
document.getElementById('cfg-max-turns').value = data.agent_max_context_turns || 20;
|
||||
document.getElementById('cfg-max-steps').value = data.agent_max_steps || 20;
|
||||
document.getElementById('cfg-enable-thinking').checked = data.enable_thinking !== false;
|
||||
|
||||
const pwdInput = document.getElementById('cfg-password');
|
||||
const maskedPwd = data.web_password_masked || '';
|
||||
@@ -1883,6 +1880,7 @@ function saveAgentConfig() {
|
||||
agent_max_context_tokens: parseInt(document.getElementById('cfg-max-tokens').value) || 50000,
|
||||
agent_max_context_turns: parseInt(document.getElementById('cfg-max-turns').value) || 20,
|
||||
agent_max_steps: parseInt(document.getElementById('cfg-max-steps').value) || 20,
|
||||
enable_thinking: document.getElementById('cfg-enable-thinking').checked,
|
||||
};
|
||||
|
||||
const btn = document.getElementById('cfg-agent-save');
|
||||
|
||||
Reference in New Issue
Block a user