refactor(cleanup): 移除余额查询功能、清理前端调试日志、规整终端输出

This commit is contained in:
JOJO 2026-07-25 12:07:04 +08:00
parent bb420b0d04
commit cf51ab0555
59 changed files with 169 additions and 1051 deletions

View File

@ -147,11 +147,6 @@ docker build -f docker/terminal.Dockerfile -t my-agent-shell:latest .
},
"models": { "default_response_max_tokens": 32768 },
"search": { "tavily_api_key": "", "tavily_api_key_2": "" },
"balance": {
"aliyun_access_key_id": "",
"aliyun_access_key_secret": "",
"usd_cny_rate": 7.1
},
"env_vars": {
"API_BASE_KIMI": "https://api.moonshot.cn/v1",
"API_KEY_KIMI": "sk-..."
@ -174,7 +169,6 @@ docker build -f docker/terminal.Dockerfile -t my-agent-shell:latest .
| `secrets.api_token_secret` | `API_TOKEN_SECRET` | API Token 加密密钥(随机 hex |
| `models.default_response_max_tokens` | `AGENT_DEFAULT_RESPONSE_MAX_TOKENS` | 单轮响应 token 全局上限 |
| `search.tavily_api_key(_2)` | `AGENT_TAVILY_API_KEY(_2)` | Tavily 搜索 Key可选 |
| `balance.aliyun_*` / `balance.usd_cny_rate` | `ALIYUN_ACCESS_KEY_ID` 等 | 可选:阿里云余额查询 |
| `env_vars.*` | 原样注入 | 任意环境变量API Key、沙箱参数等 |
> ⚠️ **以下字段已弃用/无效**,存在于旧配置中可删除:

View File

@ -74,9 +74,6 @@ def _load_dotenv():
"secrets.api_token_secret": "API_TOKEN_SECRET",
"search.tavily_api_key": "AGENT_TAVILY_API_KEY",
"search.tavily_api_key_2": "AGENT_TAVILY_API_KEY_2",
"balance.aliyun_access_key_id": "ALIYUN_ACCESS_KEY_ID",
"balance.aliyun_access_key_secret": "ALIYUN_ACCESS_KEY_SECRET",
"balance.usd_cny_rate": "USD_CNY_RATE",
"models.default_response_max_tokens": "AGENT_DEFAULT_RESPONSE_MAX_TOKENS",
}
for dotted_key, env_name in _LEGACY_MAP.items():

View File

@ -823,7 +823,7 @@ class MainTerminalCommandMixin:
if not profile.get("fast_only"):
self._mode_before_fast_only = None
try:
logger.info(
logger.debug(
"[ModelSwitch] model=%s run_mode=%s thinking=%s fast_only=%s thinking_only=%s",
self.model_key,
self.run_mode,

View File

@ -153,24 +153,13 @@ class ToolsDefinitionMainMixin:
if tool.get("function", {}).get("name") not in self.disabled_tools
]
# 调试日志:记录工具列表
# 调试日志:记录工具列表DEBUG 级,不上终端)
tool_names = [t.get("function", {}).get("name") for t in tools]
logger.info("[define_tools] 可用工具列表: %s", tool_names)
print(f"[DEBUG] define_tools: 工具数量={len(tools)}")
# 检查personalization分类状态
if hasattr(self, 'tool_categories_map') and 'personalization' in self.tool_categories_map:
cat = self.tool_categories_map['personalization']
state = self.tool_category_states.get('personalization', cat.default_enabled)
print(f"[DEBUG] personalization分类: default_enabled={cat.default_enabled}, current_state={state}")
else:
print(f"[DEBUG] personalization分类不在tool_categories_map中")
logger.debug("[define_tools] 可用工具列表: %s", tool_names)
if "manage_personalization" in tool_names:
logger.info("[define_tools] manage_personalization 工具已启用")
print("[DEBUG] manage_personalization 在可用工具列表中")
logger.debug("[define_tools] manage_personalization 工具已启用")
else:
logger.warning("[define_tools] manage_personalization 工具未找到disabled_tools=%s", self.disabled_tools)
print(f"[DEBUG] manage_personalization 不在可用工具列表中disabled_tools={self.disabled_tools}")
logger.debug("[define_tools] manage_personalization 未启用: disabled_tools=%s", self.disabled_tools)
return self._apply_intent_to_tools(tools)

View File

@ -873,7 +873,7 @@ class MainTerminalToolsExecutionMixin:
async def handle_tool_call(self, tool_name: str, arguments: Dict) -> str:
"""处理工具调用(添加参数预检查和改进错误处理)"""
logger.info("[handle_tool_call] 工具调用开始: tool_name=%s, arguments=%s", tool_name, arguments)
logger.debug("[handle_tool_call] 工具调用开始: tool_name=%s, arguments=%s", tool_name, arguments)
try:
if hasattr(self, "_apply_execution_mode_to_runtime"):
self._apply_execution_mode_to_runtime()
@ -2176,13 +2176,12 @@ class MainTerminalToolsExecutionMixin:
logger.exception("[handle_tool_call] 工具执行异常详情")
result = {"success": False, "error": f"工具执行异常: {str(e)}"}
logger.info("[handle_tool_call] 工具调用结束: tool_name=%s, result=%s", tool_name, result)
logger.debug("[handle_tool_call] 工具调用结束: tool_name=%s, result=%s", tool_name, result)
return json.dumps(result, ensure_ascii=False)
async def _execute_manage_personalization(self, arguments: Dict) -> Dict:
"""执行个性化管理操作"""
print(f"[DEBUG] _execute_manage_personalization 被调用: {arguments}")
logger.info("[_execute_manage_personalization] 方法被调用: arguments=%s", arguments)
logger.debug("[_execute_manage_personalization] 方法被调用: arguments=%s", arguments)
action = arguments.get("action")
logger.info("[_execute_manage_personalization] action=%s", action)
@ -2289,8 +2288,7 @@ class MainTerminalToolsExecutionMixin:
# 保存配置
save_personalization_config(self.data_dir, config)
print(f"[DEBUG] 配置已保存: field={field}, value={value}")
logger.info("[_execute_manage_personalization] 配置已保存到文件")
logger.info("[_execute_manage_personalization] 配置已保存到文件: field=%s", field)
# 重新加载配置到当前终端
self.apply_personalization_preferences(config)

View File

@ -6,6 +6,7 @@ from datetime import datetime
from typing import Any, Dict, List, Optional, Callable, TYPE_CHECKING
import os
from core.main_terminal import MainTerminal
from server.utils_common import debug_log
from utils.logger import setup_logger
from modules.personalization_manager import load_personalization_config
from modules.versioning_manager import ConversationVersioningManager, VersioningError
@ -50,9 +51,9 @@ class WebTerminal(MainTerminal):
bound_id = f"conv_{bound_id}"
result = self.load_conversation(bound_id, restore_model=True)
if result.get("success"):
print(f"[WebTerminal] 已加载绑定对话: {bound_id}")
debug_log(f"[WebTerminal] 已加载绑定对话: {bound_id}")
else:
print(f"[WebTerminal] 警告:绑定对话 {bound_id} 加载失败: {result.get('message') or result.get('error')}")
logger.warning("[WebTerminal] 绑定对话 %s 加载失败: %s", bound_id, result.get('message') or result.get('error'))
return
latest_list = self.context_manager.get_conversation_list(limit=1, offset=0)
@ -64,14 +65,14 @@ class WebTerminal(MainTerminal):
if conv_id:
result = self.load_conversation(conv_id, restore_model=False)
if result.get("success"):
print(f"[WebTerminal] 已加载最近对话: {conv_id}")
debug_log(f"[WebTerminal] 已加载最近对话: {conv_id}")
return
conversation_id = self.context_manager.start_new_conversation(
project_path=self.project_path,
thinking_mode=self.thinking_mode
)
print(f"[WebTerminal] 自动创建新对话: {conversation_id}")
debug_log(f"[WebTerminal] 自动创建新对话: {conversation_id}")
def __init__(
self,
@ -126,16 +127,16 @@ class WebTerminal(MainTerminal):
# 让 run_command 与实时终端共享同一容器环境
self.terminal_ops.attach_terminal_manager(self.terminal_manager)
print(f"[WebTerminal] 初始化完成,项目路径: {project_path}")
print(f"[WebTerminal] 初始模式: {self.run_mode}")
print(f"[WebTerminal] 对话管理已就绪")
debug_log(f"[WebTerminal] 初始化完成,项目路径: {project_path}")
debug_log(f"[WebTerminal] 初始模式: {self.run_mode}")
debug_log(f"[WebTerminal] 对话管理已就绪")
# 设置token更新回调
if message_callback is not None:
self.context_manager._web_terminal_callback = message_callback
print(f"[WebTerminal] 实时token统计已启用")
debug_log(f"[WebTerminal] 实时token统计已启用")
else:
print(f"[WebTerminal] 警告:message_callback为None无法启用实时token统计")
logger.warning("[WebTerminal] message_callback为None无法启用实时token统计")
# ===========================================
# 新增对话管理相关方法Web版本
# ===========================================

15
main.py
View File

@ -27,7 +27,7 @@ class AgentSystem:
async def initialize(self):
"""初始化系统"""
print("\n" + "="*50)
print("🤖 Astrion 启动")
print("🤖 Astrion 启动")
print("="*50)
# 1. 获取项目路径
@ -123,25 +123,23 @@ class AgentSystem:
project_path = Path(path_input).resolve()
if self.is_unsafe_path(str(project_path)):
raise RuntimeError(f"默认项目路径不安全: {project_path}")
raise RuntimeError(f"默认工作区路径不安全: {project_path}")
project_path.mkdir(parents=True, exist_ok=True)
if not os.access(project_path, os.R_OK | os.W_OK):
print(f"{OUTPUT_FORMATS['warning']} 对默认项目路径缺少读写权限: {project_path}")
print(f"{OUTPUT_FORMATS['warning']} 对默认工作区路径缺少读写权限: {project_path}")
self.project_path = str(project_path)
print(f"{OUTPUT_FORMATS['success']} 已选择项目路径: {self.project_path}")
print(f"{OUTPUT_FORMATS['info']} 默认工作区路径: {self.project_path}")
async def setup_run_mode(self):
"""选择运行模式"""
"""设置运行模式(当前统一入口默认 Web"""
self.web_mode = True
print(f"{OUTPUT_FORMATS['info']} 运行模式: Web默认")
async def setup_thinking_mode(self):
"""选择思考模式"""
"""设置默认思考模式(对话中可随时切换)"""
self.thinking_mode = True
print(f"{OUTPUT_FORMATS['info']} 思考模式: {'开启' if self.thinking_mode else '关闭'}(默认)")
async def init_system(self):
"""初始化系统文件"""
@ -194,7 +192,6 @@ class AgentSystem:
from web_server import run_server
print(f"\n{OUTPUT_FORMATS['success']} 正在启动Web服务器...")
print(f"{OUTPUT_FORMATS['info']} 项目路径: {self.project_path}")
port = WEB_SERVER_PORT
# 运行服务器(这会阻塞)

View File

@ -1,175 +0,0 @@
"""
Admin balance fetchers for Kimi (Moonshot), DeepSeek, and Qwen (Aliyun BSS).
Credentials (优先读取仓库根目录 .env其次环境变量):
- MOONSHOT_API_KEY : Bearer token for Kimi
- DEEPSEEK_API_KEY : Bearer token for DeepSeek
- ALIYUN_ACCESS_KEY_ID : AccessKey ID for Aliyun (Qwen billing)
- ALIYUN_ACCESS_KEY_SECRET : AccessKey Secret for Aliyun (Qwen billing)
- USD_CNY_RATE : Override USD->CNY rate (default 7.1)
"""
from __future__ import annotations
import base64
import hashlib
import hmac
import json
import os
import time
import uuid
from pathlib import Path
from typing import Any, Dict, Tuple
from urllib import parse, request
# -------- .env 读取助手(简化版,已由 config/__init__.py 统一注入) --------
def _env(key: str, default: str | None = None) -> str | None:
"""从环境变量获取配置。"""
if key in os.environ:
return os.environ[key]
return default
USD_CNY_RATE = float(_env("USD_CNY_RATE", "7.1") or "7.1")
def _http_get(url: str, headers: Dict[str, str] | None = None, timeout: int = 8) -> Tuple[Dict[str, Any] | None, str | None]:
"""Perform a simple GET request, return (json, error_message)."""
req = request.Request(url, headers=headers or {})
try:
with request.urlopen(req, timeout=timeout) as resp:
data = resp.read()
return json.loads(data.decode("utf-8")), None
except Exception as exc: # broad: network/parsing errors
return None, str(exc)
# -------- Kimi (Moonshot) --------
def fetch_kimi_balance() -> Dict[str, Any]:
api_key = _env("MOONSHOT_API_KEY") or _env("API_KEY_KIMI") or _env("AGENT_API_KEY")
if not api_key:
return {"success": False, "error": "Kimi 密钥未设置MOONSHOT_API_KEY / API_KEY_KIMI / AGENT_API_KEY"}
base = (
_env("API_BASE_KIMI")
or _env("MOONSHOT_BASE_URL")
or _env("AGENT_API_BASE_URL")
or "https://api.moonshot.ai/v1"
).rstrip("/")
url = f"{base}/users/me/balance"
payload, err = _http_get(url, headers={"Authorization": f"Bearer {api_key}"})
if err:
return {"success": False, "error": err}
try:
data = payload.get("data") or {}
available = float(data.get("available_balance", 0))
voucher = float(data.get("voucher_balance", 0))
cash = float(data.get("cash_balance", 0))
return {
"success": True,
"currency": payload.get("currency") or "CNY",
"available": available,
"voucher": voucher,
"cash": cash,
"raw": payload,
}
except Exception as exc: # pragma: no cover
return {"success": False, "error": f"解析失败: {exc}", "raw": payload}
# -------- DeepSeek --------
def fetch_deepseek_balance() -> Dict[str, Any]:
api_key = _env("DEEPSEEK_API_KEY") or _env("API_KEY_DEEPSEEK")
if not api_key:
return {"success": False, "error": "DeepSeek 密钥未设置DEEPSEEK_API_KEY / API_KEY_DEEPSEEK"}
url = "https://api.deepseek.com/user/balance"
payload, err = _http_get(url, headers={"Authorization": f"Bearer {api_key}"})
if err:
return {"success": False, "error": err}
try:
infos = payload.get("balance_infos") or []
primary = infos[0] if infos else {}
total = float(primary.get("total_balance") or 0)
granted = float(primary.get("granted_balance") or 0)
topped_up = float(primary.get("topped_up_balance") or 0)
return {
"success": True,
"currency": primary.get("currency", "CNY"),
"available": total,
"granted": granted,
"topped_up": topped_up,
"raw": payload,
}
except Exception as exc: # pragma: no cover
return {"success": False, "error": f"解析失败: {exc}", "raw": payload}
# -------- Qwen (Aliyun BSS QueryAccountBalance) --------
def _percent_encode(val: str) -> str:
res = parse.quote(str(val), safe="~")
return res.replace("+", "%20").replace("*", "%2A").replace("%7E", "~")
def _sign(params: Dict[str, Any], secret: str) -> str:
sorted_params = sorted(params.items(), key=lambda x: x[0])
canonicalized = "&".join(f"{_percent_encode(k)}={_percent_encode(v)}" for k, v in sorted_params)
string_to_sign = f"GET&%2F&{_percent_encode(canonicalized)}"
h = hmac.new((secret + "&").encode("utf-8"), string_to_sign.encode("utf-8"), hashlib.sha1)
return base64.b64encode(h.digest()).decode("utf-8")
def fetch_qwen_balance() -> Dict[str, Any]:
ak = _env("ALIYUN_ACCESS_KEY_ID")
sk = _env("ALIYUN_ACCESS_KEY_SECRET")
if not ak or not sk:
return {"success": False, "error": "缺少 ALIYUN_ACCESS_KEY_ID / ALIYUN_ACCESS_KEY_SECRET"}
params: Dict[str, Any] = {
"Format": "JSON",
"Version": "2017-12-14",
"AccessKeyId": ak,
"SignatureMethod": "HMAC-SHA1",
"Timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"SignatureVersion": "1.0",
"SignatureNonce": str(uuid.uuid4()),
"Action": "QueryAccountBalance",
"RegionId": "cn-hangzhou",
}
signature = _sign(params, sk)
params["Signature"] = signature
# 按阿里云规范组装最终查询字符串(不可用 urlencode 的 quote_plus
query = "&".join(f"{_percent_encode(k)}={_percent_encode(v)}" for k, v in params.items())
url = "https://business.aliyuncs.com/?" + query
payload, err = _http_get(url)
if err:
return {"success": False, "error": err}
try:
data = payload.get("Data") or {}
amount = float(data.get("AvailableAmount") or 0)
currency = data.get("Currency", "CNY")
return {
"success": True,
"currency": currency,
"available": amount,
"cash": float(data.get("AvailableCashAmount") or 0),
"raw": payload,
}
except Exception as exc: # pragma: no cover
return {"success": False, "error": f"解析失败: {exc}", "raw": payload}
def fetch_all_balances() -> Dict[str, Any]:
return {
"rate_usd_cny": USD_CNY_RATE,
"kimi": fetch_kimi_balance(),
"deepseek": fetch_deepseek_balance(),
"qwen": fetch_qwen_balance(),
}

View File

@ -1,4 +1,15 @@
"""Web server package entry."""
from .app import app, socketio, run_server, parse_arguments, initialize_system, resource_busy_page
"""Web server package entry.
使用 PEP 562 惰性导入避免 `python -m server.app` 时因包级提前 import
导致 'server.app' 被加载两次runpy RuntimeWarning
"""
import importlib
__all__ = ["app", "socketio", "run_server", "parse_arguments", "initialize_system", "resource_busy_page"]
def __getattr__(name):
if name in __all__:
module = importlib.import_module(".app", __name__)
return getattr(module, name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

View File

@ -28,7 +28,7 @@ from .conversation import (
summarize_upload_events,
)
from .conversation_stats import summarize_invite_codes
from modules import admin_policy_manager, balance_client
from modules import admin_policy_manager
from collections import Counter
from config import ADMIN_SECONDARY_PASSWORD_HASH, ADMIN_SECONDARY_PASSWORD, ADMIN_SECONDARY_TTL_SECONDS
@ -126,18 +126,6 @@ def admin_secondary_verify():
return jsonify({"success": True, "ttl": ADMIN_SECONDARY_TTL_SECONDS})
@admin_bp.route('/api/admin/balance', methods=['GET'])
@login_required
@admin_required
def admin_balance_api():
"""查询第三方账户余额Kimi/DeepSeek/Qwen"""
guard = _secondary_required()
if guard:
return guard
data = balance_client.fetch_all_balances()
return jsonify({"success": True, "data": data})
@admin_bp.route('/admin/assets/<path:filename>')
@login_required
@admin_required

View File

@ -1,5 +1,8 @@
# web_server.py - Web服务器修复版 - 确保text_end事件正确发送 + 停止功能)
import os as _os_early
_os_early.environ.setdefault('FLASK_SKIP_DOTENV', '1') # 抑制 Flask 的 python-dotenv 提示(项目自带 .env 解析)
import asyncio
import json
import os
@ -21,7 +24,7 @@ import time
from datetime import datetime
from collections import defaultdict, deque, Counter
from config.model_profiles import get_default_model_key, get_model_profile, get_registered_model_keys
from modules import admin_policy_manager, balance_client
from modules import admin_policy_manager
from modules.custom_tool_registry import CustomToolRegistry
import server.state as state # 共享单例
from server.auth import auth_bp
@ -221,6 +224,7 @@ from config import (
DEFAULT_CONVERSATIONS_LIMIT,
MAX_CONVERSATIONS_LIMIT,
CONVERSATIONS_DIR,
DATA_DIR,
DEFAULT_RESPONSE_MAX_TOKENS,
DEFAULT_PROJECT_PATH,
LOGS_DIR,
@ -231,6 +235,7 @@ from config import (
UPLOAD_SCAN_LOG_SUBDIR,
WEB_SERVER_PORT,
WEB_SERVER_HOST,
TERMINAL_SANDBOX_MODE,
)
from modules.user_manager import UserManager, UserWorkspace
from modules.gui_file_manager import GuiFileManager
@ -251,7 +256,7 @@ app.config['MAX_CONTENT_LENGTH'] = MAX_UPLOAD_SIZE
_secret_key = os.environ.get("WEB_SECRET_KEY") or os.environ.get("SECRET_KEY")
if not _secret_key:
_secret_key = secrets.token_hex(32)
print("[security] WEB_SECRET_KEY 未设置,已生成临时密钥(重启后失效)。")
print(f"{OUTPUT_FORMATS['warning']} WEB_SECRET_KEY 未设置,已生成临时密钥(重启后所有会话将失效)。")
app.config['SECRET_KEY'] = _secret_key
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=12)
_cookie_secure_env = (os.environ.get("WEB_COOKIE_SECURE") or "").strip().lower()
@ -1229,17 +1234,15 @@ def initialize_system(path: str, thinking_mode: bool = False):
DEBUG_LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
with DEBUG_LOG_FILE.open('w', encoding='utf-8') as f:
f.write(f"调试日志开始 - {datetime.now()}\n")
f.write(f"项目路径: {path}\n")
f.write(f"思考模式: {'思考模式' if thinking_mode else '快速模式'}\n")
f.write(f"默认工作区路径: {path}\n")
f.write(f"默认思考模式: {'思考' if thinking_mode else '快速'}(对话中可切换)\n")
f.write(f"自动修复: {'开启' if AUTO_FIX_TOOL_CALL else '关闭'}\n")
f.write(f"最大迭代: {MAX_ITERATIONS_PER_TASK}\n")
f.write(f"最大工具调用: {MAX_TOTAL_TOOL_CALLS}\n")
f.write("="*80 + "\n")
print(f"[Init] 初始化Web系统...")
print(f"[Init] 项目路径: {path}")
print(f"[Init] 运行模式: {'思考模式(首次思考,后续快速)' if thinking_mode else '快速模式(无思考)'}")
print(f"[Init] 自动修复: {'开启' if AUTO_FIX_TOOL_CALL else '关闭'}")
print(f"[Init] 调试日志: {DEBUG_LOG_FILE}")
print(f"{OUTPUT_FORMATS['info']} 初始化 Web 系统...")
print(f"{OUTPUT_FORMATS['info']} 数据目录: {DATA_DIR}")
print(f"{OUTPUT_FORMATS['info']} 调试日志: {DEBUG_LOG_FILE}")
app.config['DEFAULT_THINKING_MODE'] = thinking_mode
app.config['DEFAULT_RUN_MODE'] = "thinking" if thinking_mode else "fast"
# 同步预设子智能体角色到运行态目录
@ -1249,7 +1252,8 @@ def initialize_system(path: str, thinking_mode: bool = False):
print(f"{OUTPUT_FORMATS['success']} 预设子智能体角色同步完成")
except Exception as _e:
print(f"{OUTPUT_FORMATS['warning']} 预设子智能体角色同步失败: {_e}")
print(f"{OUTPUT_FORMATS['success']} Web系统初始化完成多用户模式")
_mode_label = "宿主机模式(单用户)" if TERMINAL_SANDBOX_MODE == "host" else "多用户模式Web"
print(f"{OUTPUT_FORMATS['success']} Web 系统初始化完成({_mode_label}")
def run_server(path: str, thinking_mode: bool = False, port: int = DEFAULT_PORT, debug: bool = False):
@ -1276,7 +1280,7 @@ def parse_arguments():
parser.add_argument(
"--path",
default=str(Path(DEFAULT_PROJECT_PATH).resolve()),
help="项目工作目录(默认使用 config.DEFAULT_PROJECT_PATH"
help="默认工作区路径(仅作兜底,工作区可在界面中管理"
)
parser.add_argument(
"--port",
@ -1292,7 +1296,7 @@ def parse_arguments():
parser.add_argument(
"--thinking-mode",
action="store_true",
help="启用思考模式(首次请求使用 reasoning"
help="新对话默认使用思考模式(对话中可随时切换"
)
return parser.parse_args()

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from server.chat import chat_bp
import json, time
import json, logging, time
from datetime import datetime
from typing import Dict, Any, Optional
from pathlib import Path
@ -8,6 +8,8 @@ from io import BytesIO
import zipfile
import os
logger = logging.getLogger(__name__)
from flask import Blueprint, jsonify, request, session, send_file
from werkzeug.utils import secure_filename
from werkzeug.exceptions import RequestEntityTooLarge
@ -111,7 +113,7 @@ def update_thinking_mode(terminal: WebTerminal, workspace: UserWorkspace, userna
has_videos=getattr(ctx, "has_videos", False)
)
except Exception as exc:
print(f"[API] 保存思考模式到对话失败: {exc}")
logger.error(f"[API] 保存思考模式到对话失败: {exc}")
status = terminal.get_status()
socketio.emit('status_update', status, room=f"user_{username}")
@ -124,7 +126,7 @@ def update_thinking_mode(terminal: WebTerminal, workspace: UserWorkspace, userna
}
})
except Exception as exc:
print(f"[API] 切换思考模式失败: {exc}")
logger.error(f"[API] 切换思考模式失败: {exc}")
code = 400 if isinstance(exc, ValueError) else 500
return jsonify({
"success": False,
@ -178,7 +180,7 @@ def update_reasoning_effort(terminal: WebTerminal, workspace: UserWorkspace, use
reasoning_effort=effort,
)
except Exception as exc:
print(f"[API] 保存推理强度到对话失败: {exc}")
logger.error(f"[API] 保存推理强度到对话失败: {exc}")
status = terminal.get_status()
socketio.emit('status_update', status, room=f"user_{username}")
@ -190,7 +192,7 @@ def update_reasoning_effort(terminal: WebTerminal, workspace: UserWorkspace, use
}
})
except Exception as exc:
print(f"[API] 设置推理强度失败: {exc}")
logger.error(f"[API] 设置推理强度失败: {exc}")
code = 400 if isinstance(exc, ValueError) else 500
return jsonify({
"success": False,
@ -253,7 +255,7 @@ def update_model(terminal: WebTerminal, workspace: UserWorkspace, username: str)
has_videos=getattr(ctx, "has_videos", False)
)
except Exception as exc:
print(f"[API] 保存模型到对话失败: {exc}")
logger.error(f"[API] 保存模型到对话失败: {exc}")
else:
print(
f"[API] 跳过模型保存:请求对话 {requested_cid} "
@ -272,7 +274,7 @@ def update_model(terminal: WebTerminal, workspace: UserWorkspace, username: str)
}
})
except Exception as exc:
print(f"[API] 切换模型失败: {exc}")
logger.error(f"[API] 切换模型失败: {exc}")
code = 400 if isinstance(exc, ValueError) else 500
return jsonify({"success": False, "error": str(exc), "message": str(exc)}), code

View File

@ -220,7 +220,6 @@ def process_message_task(terminal: WebTerminal, message: str, images, sender, cl
debug_log(f"错误恢复:保存对话状态失败: {save_error}")
# 原有的错误处理逻辑
print(f"[Task] 错误: {e}")
debug_log(f"任务处理错误: {e}")
import traceback
traceback.print_exc()

View File

@ -9,7 +9,7 @@ from config.model_profiles import get_model_profile
from utils.token_usage import extract_usage_payload
from .utils_common import debug_log, brief_log, log_backend_chunk
from .utils_common import debug_log, log_backend_chunk
from .chat_flow_runner_helpers import extract_intent_from_partial
from .chat_flow_task_support import wait_retry_delay, cancel_pending_tools
from .state import get_stop_flag, clear_stop_flag
@ -158,7 +158,7 @@ async def run_streaming_attempts(*, web_terminal, messages, tools, sender, clien
and detected_tool_intent.get(tool_id) != intent_value
):
detected_tool_intent[tool_id] = intent_value
brief_log(f"[intent] 增量提取 {tool_name}: {intent_value}")
debug_log(f"[intent] 增量提取 {tool_name}: {intent_value}")
sender('tool_intent', {
'id': tool_id,
'name': tool_name,
@ -185,10 +185,10 @@ async def run_streaming_attempts(*, web_terminal, messages, tools, sender, clien
intent_value = extract_intent_from_partial(arguments_str)
if intent_value:
detected_tool_intent[tool_id] = intent_value
brief_log(f"[intent] 预提取 {tool_name}: {intent_value}")
debug_log(f"[intent] 预提取 {tool_name}: {intent_value}")
# 立即发送工具准备中事件
brief_log(f"[tool] 准备调用 {tool_name} (id={tool_id}) intent={intent_value or '-'}")
debug_log(f"[tool] 准备调用 {tool_name} (id={tool_id}) intent={intent_value or '-'}")
sender('tool_preparing', {
'id': tool_id,
'name': tool_name,
@ -249,7 +249,7 @@ async def run_streaming_attempts(*, web_terminal, messages, tools, sender, clien
text_started = True
text_streaming = True
sender('text_start', {})
brief_log("模型输出了内容")
debug_log("模型输出了内容")
await asyncio.sleep(0.05)
full_response += content

View File

@ -1915,7 +1915,7 @@ async def handle_task_with_sender(
return
tool_call_limit_label = MAX_TOTAL_TOOL_CALLS if MAX_TOTAL_TOOL_CALLS is not None else ""
print(f"[API] 第{current_iteration}次调用 (总工具调用: {total_tool_calls}/{tool_call_limit_label})")
debug_log(f"[API] 第{current_iteration}次调用 (总工具调用: {total_tool_calls}/{tool_call_limit_label})")
stream_result = await run_streaming_attempts(
web_terminal=web_terminal,

View File

@ -7,7 +7,7 @@ import uuid
from pathlib import Path
from typing import Optional, Dict, Any, List
from .utils_common import debug_log, brief_log
from .utils_common import debug_log
from .state import MONITOR_FILE_TOOLS, MONITOR_MEMORY_TOOLS, MONITOR_SNAPSHOT_CHAR_LIMIT, MONITOR_MEMORY_ENTRY_LIMIT
from .state import tool_approval_manager, user_question_manager
from .monitor import cache_monitor_snapshot
@ -726,7 +726,7 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie
'monitor_snapshot': monitor_snapshot,
'conversation_id': conversation_id
})
brief_log(f"调用了工具: {function_name}")
debug_log(f"调用了工具: {function_name}")
await asyncio.sleep(0.3)
start_time = time.time()

View File

@ -1,9 +1,12 @@
from __future__ import annotations
import logging
import sys, os
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
if PROJECT_ROOT not in sys.path:
sys.path.insert(0, PROJECT_ROOT)
logger = logging.getLogger(__name__)
import asyncio, json, time, re, os, shutil
from datetime import datetime, timedelta
from pathlib import Path
@ -579,7 +582,7 @@ def get_conversations(terminal: WebTerminal, workspace: UserWorkspace, username:
}), 500
except Exception as e:
print(f"[API] 获取对话列表错误: {e}")
logger.error(f"[API] 获取对话列表错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -754,7 +757,7 @@ def create_conversation(terminal: WebTerminal, workspace: UserWorkspace, usernam
return jsonify(result), 500
except Exception as e:
print(f"[API] 创建对话错误: {e}")
logger.error(f"[API] 创建对话错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -793,7 +796,7 @@ def get_conversation_info(terminal: WebTerminal, workspace: UserWorkspace, usern
}), 404
except Exception as e:
print(f"[API] 获取对话信息错误: {e}")
logger.error(f"[API] 获取对话信息错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -903,7 +906,7 @@ def load_conversation(conversation_id, terminal: WebTerminal, workspace: UserWor
except Exception as e:
import traceback
print(f"[API] 加载对话错误: {e}")
logger.error(f"[API] 加载对话错误: {e}")
traceback.print_exc()
return jsonify({
"success": False,
@ -957,7 +960,7 @@ def delete_conversation(conversation_id, terminal: WebTerminal, workspace: UserW
return jsonify(result), 404 if "不存在" in result.get("message", "") else 500
except Exception as e:
print(f"[API] 删除对话错误: {e}")
logger.error(f"[API] 删除对话错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -1033,12 +1036,12 @@ def search_conversations(terminal: WebTerminal, workspace: UserWorkspace, userna
username, ws_id, terminal, workspace
)
except (ValueError, RuntimeError) as resolve_err:
print(f"[API] 搜索跳过工作区 {ws_id}: {resolve_err}")
logger.error(f"[API] 搜索跳过工作区 {ws_id}: {resolve_err}")
continue
try:
result = target_terminal.search_conversations(query, limit, multi_agent_mode=multi_agent_filter)
except Exception as search_err:
print(f"[API] 搜索工作区对话失败 {ws_id}: {search_err}")
logger.error(f"[API] 搜索工作区对话失败 {ws_id}: {search_err}")
continue
results = result.get("results") or []
if not results:
@ -1061,7 +1064,7 @@ def search_conversations(terminal: WebTerminal, workspace: UserWorkspace, userna
})
except Exception as e:
print(f"[API] 搜索对话错误: {e}")
logger.error(f"[API] 搜索对话错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -1124,7 +1127,7 @@ def get_conversation_messages(conversation_id, terminal: WebTerminal, workspace:
}), 404
except Exception as e:
print(f"[API] 获取对话消息错误: {e}")
logger.error(f"[API] 获取对话消息错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -1763,7 +1766,7 @@ def compress_conversation(conversation_id, terminal: WebTerminal, workspace: Use
return jsonify(response_payload)
except Exception as e:
print(f"[API] 压缩对话错误: {e}")
logger.error(f"[API] 压缩对话错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -2208,7 +2211,7 @@ def duplicate_conversation(conversation_id, terminal: WebTerminal, workspace: Us
return jsonify(response_payload)
except Exception as e:
print(f"[API] 复制对话错误: {e}")
logger.error(f"[API] 复制对话错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -2251,7 +2254,7 @@ def review_conversation_preview(conversation_id, terminal: WebTerminal, workspac
}
})
except Exception as e:
print(f"[API] 对话回顾预览错误: {e}")
logger.error(f"[API] 对话回顾预览错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -2307,7 +2310,7 @@ def review_conversation(conversation_id, terminal: WebTerminal, workspace: UserW
}
})
except Exception as e:
print(f"[API] 对话回顾生成错误: {e}")
logger.error(f"[API] 对话回顾生成错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -2328,7 +2331,7 @@ def get_conversations_statistics(terminal: WebTerminal, workspace: UserWorkspace
})
except Exception as e:
print(f"[API] 获取对话统计错误: {e}")
logger.error(f"[API] 获取对话统计错误: {e}")
return jsonify({
"success": False,
"error": str(e),
@ -2377,7 +2380,7 @@ def get_current_conversation(terminal: WebTerminal, workspace: UserWorkspace, us
}), 404
except Exception as e:
print(f"[API] 获取当前对话错误: {e}")
logger.error(f"[API] 获取当前对话错误: {e}")
return jsonify({
"success": False,
"error": str(e)
@ -2490,7 +2493,7 @@ def get_conversation_token_statistics(conversation_id, terminal: WebTerminal, wo
}), 404
except Exception as e:
print(f"[API] 获取token统计错误: {e}")
logger.error(f"[API] 获取token统计错误: {e}")
return jsonify({
"success": False,
"error": str(e),

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import json
import logging
import os
import time
from collections import Counter, deque
@ -8,6 +9,8 @@ from datetime import datetime, timedelta
from pathlib import Path
from typing import Any, Dict, List, Optional
logger = logging.getLogger(__name__)
from modules.user_manager import UserWorkspace
from modules.usage_tracker import QUOTA_DEFAULTS
from utils.conversation_manager import ConversationManager
@ -131,7 +134,7 @@ def _read_token_totals_file(workspace: UserWorkspace) -> Dict[str, int]:
"total_tokens": total_tokens,
}
except (OSError, json.JSONDecodeError, ValueError) as exc:
print(f"[admin] 解析 token_totals.json 失败 ({workspace.username}): {exc}")
logger.error(f"[admin] 解析 token_totals.json 失败 ({workspace.username}): {exc}")
return {"input_tokens": 0, "output_tokens": 0, "total_tokens": 0}
def _collect_conversation_token_totals(workspace: UserWorkspace) -> Dict[str, int]:
@ -148,7 +151,7 @@ def _collect_conversation_token_totals(workspace: UserWorkspace) -> Dict[str, in
"total_tokens": total_tokens,
}
except Exception as exc:
print(f"[admin] 读取 legacy token 统计失败 ({workspace.username}): {exc}")
logger.error(f"[admin] 读取 legacy token 统计失败 ({workspace.username}): {exc}")
return {"input_tokens": 0, "output_tokens": 0, "total_tokens": 0}
def collect_user_token_statistics(workspace: UserWorkspace) -> Dict[str, int]:

View File

@ -23,7 +23,7 @@ from config.model_profiles import model_supports_image, model_supports_video
@socketio.on('connect')
def handle_connect(auth):
"""客户端连接"""
print(f"[WebSocket] 客户端连接: {request.sid}")
debug_log(f"[WebSocket] 客户端连接: {request.sid}")
username = get_current_username()
token_value = (auth or {}).get('socket_token') if isinstance(auth, dict) else None
if not username or not consume_socket_token(token_value, username):
@ -75,7 +75,7 @@ def handle_connect(auth):
@socketio.on('disconnect')
def handle_disconnect():
"""客户端断开"""
print(f"[WebSocket] 客户端断开: {request.sid}")
debug_log(f"[WebSocket] 客户端断开: {request.sid}")
username = connection_users.pop(request.sid, None)
# 若同一用户仍有其他活跃连接,不因断开而停止任务
has_other_connection = False
@ -127,7 +127,7 @@ def handle_disconnect():
@socketio.on('stop_task')
def handle_stop_task():
"""处理停止任务请求"""
print(f"[停止] 收到停止请求: {request.sid}")
debug_log(f"[停止] 收到停止请求: {request.sid}")
username = connection_users.get(request.sid)
task_info = get_stop_flag(request.sid, username)
if not isinstance(task_info, dict):
@ -172,7 +172,7 @@ def handle_terminal_subscribe(data):
room_name = f"user_{username}_terminal"
join_room(room_name)
terminal_rooms[request.sid].add(room_name)
print(f"[Terminal] {request.sid} 订阅所有终端事件")
debug_log(f"[Terminal] {request.sid} 订阅所有终端事件")
# 发送当前终端状态
emit('terminal_subscribed', {
@ -184,7 +184,7 @@ def handle_terminal_subscribe(data):
room_name = f'user_{username}_terminal_{session_name}'
join_room(room_name)
terminal_rooms[request.sid].add(room_name)
print(f"[Terminal] {request.sid} 订阅终端: {session_name}")
debug_log(f"[Terminal] {request.sid} 订阅终端: {session_name}")
# 发送该终端的当前输出
output_result = terminal.terminal_manager.get_terminal_output(session_name, 100)
@ -205,7 +205,7 @@ def handle_terminal_unsubscribe(data):
leave_room(room_name)
if request.sid in terminal_rooms:
terminal_rooms[request.sid].discard(room_name)
print(f"[Terminal] {request.sid} 取消订阅终端: {session_name}")
debug_log(f"[Terminal] {request.sid} 取消订阅终端: {session_name}")
@socketio.on('get_terminal_output')
def handle_get_terminal_output(data):
@ -279,7 +279,7 @@ def handle_message(data):
emit('error', {'message': '图片和视频请分开发送'})
return
print(f"[WebSocket] 收到消息: {message}")
debug_log(f"[WebSocket] 收到消息: {message}")
debug_log(f"\n{'='*80}\n新任务开始: {message}\n{'='*80}")
record_user_activity(username)

View File

@ -272,55 +272,6 @@
</li>
</ul>
</section>
<section v-else-if="activeSection === 'balance'" key="balance" class="panel">
<div class="balance-header">
<div>
<h2>余额查询</h2>
<p class="muted">手动刷新查看 Kimi / DeepSeek / Qwen 余额</p>
</div>
<div class="balance-actions">
<span class="muted" v-if="balanceUpdatedAt"
>上次刷新{{ timeAgo(balanceUpdatedAt) }}</span
>
<button type="button" :disabled="balanceLoading" @click="fetchBalance">
{{ balanceLoading ? '查询中...' : '手动刷新' }}
</button>
</div>
</div>
<section v-if="balanceError" class="banner-error">
<strong>查询失败</strong>
<span>{{ balanceError }}</span>
</section>
<div class="balance-grid">
<div
v-for="card in balanceCards"
:key="card.key"
class="balance-card"
:class="{ error: !card.success }"
>
<div class="balance-card-head">
<h3>{{ card.label }}</h3>
<span v-if="card.success" class="status-badge online">正常</span>
<span v-else class="status-badge danger">失败</span>
</div>
<div class="balance-amount">
<strong v-if="card.amount !== null">{{ card.amount }} {{ card.currency }}</strong>
<strong v-else></strong>
<span v-if="card.amountCny !== null" class="sub"> ¥{{ card.amountCny }}</span>
</div>
<ul class="balance-meta" v-if="card.success">
<li v-if="card.extras.voucher !== undefined">{{ card.extras.voucher }}</li>
<li v-if="card.extras.cash !== undefined">现金{{ card.extras.cash }}</li>
<li v-if="card.extras.granted !== undefined">赠送{{ card.extras.granted }}</li>
<li v-if="card.extras.topped_up !== undefined">
充值{{ card.extras.topped_up }}
</li>
<li v-if="card.extras.rate">汇率 USDCNY{{ card.extras.rate }}</li>
</ul>
<p v-else class="muted small">{{ card.error || '未知错误' }}</p>
</div>
</div>
</section>
<section v-else-if="activeSection === 'invites'" key="invites" class="panel">
<h2>邀请码</h2>
<div class="stats-row">
@ -478,7 +429,7 @@ import { useSecondaryPass } from './useSecondaryPass';
type Snapshot = Record<string, any> | null;
type SectionId = 'overview' | 'usage' | 'users' | 'containers' | 'uploads' | 'balance' | 'invites' | 'passwords';
type SectionId = 'overview' | 'usage' | 'users' | 'containers' | 'uploads' | 'invites' | 'passwords';
const {
verified: secondaryVerified,
@ -497,10 +448,6 @@ const bannerError = ref<string | null>(null);
const autoRefresh = ref(true);
const activeSection = ref<SectionId>('overview');
let timer: number | undefined;
const balanceLoading = ref(false);
const balanceError = ref<string | null>(null);
const balanceData = ref<Record<string, any> | null>(null);
const balanceUpdatedAt = ref<number | null>(null);
const inviteSubmitting = ref(false);
const inviteError = ref<string | null>(null);
const newInviteCode = ref('');
@ -522,7 +469,6 @@ const sectionTabs: Array<{ id: SectionId; label: string }> = [
{ id: 'users', label: '用户' },
{ id: 'containers', label: '容器' },
{ id: 'uploads', label: '上传审计' },
{ id: 'balance', label: '余额查询' },
{ id: 'invites', label: '邀请码' },
{ id: 'passwords', label: '密码管理' }
];
@ -789,23 +735,6 @@ const removeInvite = async (code: string) => {
}
};
const fetchBalance = async () => {
balanceLoading.value = true;
balanceError.value = null;
try {
const resp = await fetch('/api/admin/balance', { credentials: 'same-origin' });
if (!resp.ok) throw new Error(`请求失败:${resp.status}`);
const payload = await resp.json();
if (!payload.success) throw new Error(payload.error || '未知错误');
balanceData.value = payload.data || {};
balanceUpdatedAt.value = Date.now();
} catch (error) {
balanceError.value = error instanceof Error ? error.message : String(error);
} finally {
balanceLoading.value = false;
}
};
const handleVerifySecondary = async () => {
await verifySecondary(secondaryPassword.value);
if (secondaryVerified.value) {
@ -819,15 +748,6 @@ watch(autoRefresh, () => {
scheduleAutoRefresh();
});
watch(
() => activeSection.value,
(val) => {
if (val === 'balance' && !balanceData.value && !balanceLoading.value) {
fetchBalance();
}
}
);
onMounted(async () => {
document.addEventListener('click', handleClickOutside);
await checkSecondary();
@ -891,36 +811,6 @@ const tokenBreakdown = computed(() => {
return list.sort((a, b) => b.total - a.total);
});
const usdToCnyRate = computed(() => balanceData.value?.rate_usd_cny ?? null);
const balanceCards = computed(() => {
const makeCard = (key: string, label: string) => {
const data = (balanceData.value as any)?.[key] || {};
const success = data.success === true;
const currency = data.currency || '—';
const amount = data.available ?? data.total ?? null;
return {
key,
label,
success,
currency,
amount,
amountCny:
data.available_cny ??
(currency === 'USD' && usdToCnyRate.value && amount != null
? Math.round(amount * usdToCnyRate.value * 100) / 100
: null),
extras: data,
error: success ? null : data.error
};
};
return [
makeCard('kimi', 'Kimi'),
makeCard('deepseek', 'DeepSeek'),
makeCard('qwen', 'Qwen / Aliyun')
];
});
const metricCards = computed(() => [
{
title: '注册用户',
@ -1593,70 +1483,6 @@ th {
box-shadow: none;
}
.balance-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
.balance-actions {
display: flex;
align-items: center;
gap: 10px;
}
.balance-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 12px;
margin-top: 12px;
}
.balance-card {
border: 1px solid rgba(118, 103, 84, 0.2);
border-radius: 14px;
padding: 12px;
background: rgba(255, 255, 255, 0.9);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.balance-card.error {
border-color: rgba(189, 93, 58, 0.4);
background: rgba(189, 93, 58, 0.08);
}
.balance-card-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 6px;
}
.balance-amount {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 8px;
}
.balance-amount .sub {
color: #6a5d4c;
font-size: 13px;
}
.balance-meta {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 4px;
color: #6a5d4c;
}
.small {
font-size: 13px;
}

View File

@ -229,35 +229,6 @@
</div>
</section>
<section class="panel">
<div class="balance-header">
<div>
<h3>余额查询</h3>
<p class="muted">Kimi / DeepSeek / Qwen</p>
</div>
<button type="button" :disabled="balanceLoading" @click="fetchBalance">
{{ balanceLoading ? '查询中...' : '刷新余额' }}
</button>
</div>
<div class="balance-grid">
<div
v-for="card in balanceCards"
:key="card.key"
class="balance-card"
:class="{ error: !card.success }"
>
<div class="balance-card-head">
<h4>{{ card.label }}</h4>
<span :class="['status-badge', card.success ? 'online' : 'danger']">
{{ card.success ? '正常' : '失败' }}
</span>
</div>
<strong>{{ card.amount ?? '—' }} {{ card.currency }}</strong>
<span class="muted small" v-if="card.amountCny"> ¥{{ card.amountCny }}</span>
<p class="muted small" v-else-if="card.error">{{ card.error }}</p>
</div>
</div>
</section>
</div>
</template>
@ -287,9 +258,6 @@ const creating = ref(false);
const createForm = ref({ username: '', note: '' });
const createError = ref('');
const balanceData = ref<Record<string, any> | null>(null);
const balanceLoading = ref(false);
const overview = computed(() => snapshot.value?.overview || {});
const uploads = computed(() => snapshot.value?.uploads || {});
const containerItems = computed(() => {
@ -303,22 +271,6 @@ const totalRequests = computed(() =>
)
);
const balanceCards = computed(() => {
const keys = ['kimi', 'deepseek', 'qwen'];
return keys.map((k) => {
const data = (balanceData.value as any)?.[k] || {};
return {
key: k,
label: k.toUpperCase(),
success: data.success === true,
amount: data.available ?? data.total ?? null,
amountCny: data.amount_cny ?? data.amountCny ?? null,
currency: data.currency || '',
error: data.error
};
});
});
const formatNumber = (val: any) => {
const num = Number(val || 0);
return Number.isFinite(num) ? num.toLocaleString('zh-CN') : '0';
@ -501,21 +453,6 @@ const copyToken = async (username: string) => {
}
};
const fetchBalance = async () => {
if (!secondaryVerified.value) return;
balanceLoading.value = true;
try {
const resp = await fetch('/api/admin/balance', { credentials: 'same-origin' });
const data = await resp.json();
if (!resp.ok || !data.success) throw new Error(data.error || '查询失败');
balanceData.value = data.data;
} catch (err) {
console.error(err);
} finally {
balanceLoading.value = false;
}
};
const handleVerifySecondary = async () => {
await verifySecondary(secondaryPassword.value);
if (secondaryVerified.value) {
@ -754,37 +691,6 @@ td {
gap: 14px;
}
.balance-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-bottom: 12px;
}
.balance-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
}
.balance-card {
background: rgba(255, 255, 255, 0.92);
border: 1px solid rgba(44, 32, 19, 0.12);
border-radius: 14px;
padding: 12px;
}
.balance-card.error {
border-color: rgba(181, 71, 61, 0.35);
}
.balance-card-head {
display: flex;
align-items: center;
justify-content: space-between;
}
.error-text {
color: #b5473d;
margin-top: 8px;

View File

@ -62,17 +62,16 @@ function debugShowImageLog(event: string, payload: Record<string, any> = {}) {
}
function isShowHtmlDebugEnabled() {
if (typeof window === 'undefined') return true;
if (typeof window === 'undefined') return false;
try {
const explicitFlag = (window as any).__SHOW_HTML_DEBUG__;
if (explicitFlag === false || explicitFlag === '0') return false;
if (explicitFlag === true || explicitFlag === '1') return true;
if (explicitFlag === false || explicitFlag === '0') return false;
const localFlag = window.localStorage?.getItem('showHtmlDebug');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}
@ -1042,7 +1041,8 @@ function getShowTagContainer() {
}
function isLayoutDebugEnabled() {
if (typeof window === 'undefined') return true;
// 默认关闭:排障时通过 window.__LAYOUT_DEBUG__ = true 或 localStorage.layoutDebug = '1' 显式打开
if (typeof window === 'undefined') return false;
try {
const explicitFlag = (window as any).__LAYOUT_DEBUG__;
if (explicitFlag === false || explicitFlag === '0') return false;
@ -1050,9 +1050,9 @@ function isLayoutDebugEnabled() {
const localFlag = window.localStorage?.getItem('layoutDebug');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}

View File

@ -23,7 +23,6 @@ export function created() {
export async function mounted() {
debugLog('Vue应用已挂载');
console.log('[DEBUG_SYSTEM][boot] 前端调试版本已加载 2026-04-05');
if (window.ensureCsrfToken) {
window.ensureCsrfToken().catch((err) => {
console.warn('CSRF token 初始化失败:', err);

View File

@ -25,8 +25,6 @@ export const traceLog = (...args) => {
function isGoalModeDebugEnabled() {
if (typeof window === 'undefined') return false;
try {
// 临时强制开启,用于调试多智能体消息轮询问题
return true;
const explicit = (window as any).__GOAL_MODE_DEBUG__;
if (explicit === true || explicit === '1') return true;
if (explicit === false || explicit === '0') return false;

View File

@ -17,7 +17,6 @@ export const actionMethods = {
}
},
async createNewConversation() {
console.log('[DEBUG_AWAITING] ===== createNewConversation =====');
if (this.compressionInProgress || this.compressing) {
const confirmed = await this.confirmAction({
title: '压缩进行中',

View File

@ -7,7 +7,6 @@ import {
export const stateMethods = {
resetAllStates(reason = 'unspecified', options: { preserveMonitorWindows?: boolean } = {}) {
console.log('[DEBUG_AWAITING] ===== resetAllStates =====', { reason });
// 如果正在等待子智能体完成,不重置任务状态
if (this.waitingForSubAgent) {
@ -74,11 +73,6 @@ export const stateMethods = {
generatingLabel: m.generatingLabel
}));
console.log('[DEBUG_AWAITING] resetAllStates 清理完成', {
before: assistantMsgsBefore,
after: assistantMsgsAfter
});
// 清理Markdown缓存
if (this.markdownCache) {
this.markdownCache.clear();

View File

@ -2,7 +2,6 @@
import { debugLog } from './common';
import { useQuickDockStore } from '../../stores/quickDock';
const jsonDebug = (...args: any[]) => {
console.log('[JSONDEBUG]', ...args);
};
const RESTORE_DEBUG_PREFIX = '[RESTORE_DEBUG]';
const RESTORE_DEBUG_EVENTS = new Set([
@ -12,17 +11,16 @@ const RESTORE_DEBUG_EVENTS = new Set([
]);
function isRestoreDebugEnabled() {
if (typeof window === 'undefined') return true;
if (typeof window === 'undefined') return false;
try {
const explicit = (window as any).__RESTORE_DEBUG__;
if (explicit === false || explicit === '0') return false;
if (explicit === true || explicit === '1') return true;
if (explicit === false || explicit === '0') return false;
const localFlag = window.localStorage?.getItem('restoreDebug');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}
@ -459,10 +457,6 @@ export const historyMethods = {
if (message.role === 'system') {
const rawContent = message.content || '';
const label = parseSystemNoticeLabel(rawContent);
console.log('[DEBUG_SYSTEM][history] 命中 role=system 历史消息', {
rawContent,
matchedDoneNotice: !!label
});
if (label) {
// 历史中的 system 通知转换为 assistant system action避免被 role=system 过滤掉
this.messages.push({
@ -485,9 +479,6 @@ export const historyMethods = {
generatingLabel: ''
});
} else {
console.log('[DEBUG_SYSTEM][history] role=system 被历史加载拦截(非子智能体完成)', {
rawContent
});
}
return;
}

View File

@ -97,7 +97,6 @@ export const sendMethods = {
}
},
async sendMessage(options = {}) {
console.log('[DEBUG_AWAITING] ===== sendMessage =====');
const presetText = typeof options?.presetText === 'string' ? options.presetText : null;
const usePresetText = presetText !== null;
@ -417,7 +416,6 @@ export const sendMethods = {
return true;
},
async stopTask() {
console.log('[DEBUG_AWAITING] ===== stopTask =====');
if (this._stopTaskRunning) {
goalModeDebugLog('stopTask:debounce-rejected', { stopRequested: this.stopRequested });
return;

View File

@ -21,22 +21,8 @@ import {
export const aiStreamMethods = {
handleAiMessageStart(data: any, eventIdx: number) {
const lastMessage = this.messages[this.messages.length - 1];
console.log('[DEBUG_AWAITING] ===== handleAiMessageStart =====', {
eventIdx,
lastMessageRole: lastMessage?.role,
lastMessageAwaitingFirstContent: lastMessage?.awaitingFirstContent,
lastMessageGeneratingLabel: lastMessage?.generatingLabel
});
debugLog('[TaskPolling] AI消息开始, idx:', eventIdx);
console.log('[AiMessageStart] 开始处理', {
eventIdx,
messagesLength: this.messages.length,
lastMessageRole: this.messages[this.messages.length - 1]?.role,
streamingMessage: this.streamingMessage,
taskInProgress: this.taskInProgress,
currentConversationId: this.currentConversationId
});
if (this.waitingForSubAgent) {
this.waitingForSubAgent = false;
@ -45,13 +31,6 @@ export const aiStreamMethods = {
// 检查是否已经有 assistant 消息
const hasAssistantMessage = lastMessage && lastMessage.role === 'assistant';
console.log('[AiMessageStart] 最后一条消息状态', {
hasAssistantMessage,
lastMessageActionsLength: lastMessage?.actions?.length || 0,
lastMessageAwaitingFirstContent: lastMessage?.awaitingFirstContent,
lastMessageGeneratingLabel: lastMessage?.generatingLabel
});
// 判断是否是刷新恢复的情况:
// 1. 有assistant消息
// 2. 且最后一条 assistant 仍处于“未完成流式状态”(而不是普通已完成消息)
@ -83,16 +62,7 @@ export const aiStreamMethods = {
isRefreshRestore
});
console.log('[AiMessageStart] 场景判断', {
isRefreshRestore,
streamingMessage: this.streamingMessage,
hasActions: !!(lastMessage?.actions && lastMessage.actions.length > 0),
awaitingFirstContent: lastMessage?.awaitingFirstContent,
taskInProgress: this.taskInProgress
});
if (isRefreshRestore) {
console.log('[AiMessageStart] 场景=刷新恢复复用现有assistant消息');
debugLog('[TaskPolling] 刷新恢复场景,复用现有 assistant 消息');
// 只更新状态,不创建新消息
this.taskInProgress = true;
@ -105,25 +75,18 @@ export const aiStreamMethods = {
// 从头重建时restoreTaskState 已根据事件流分析hasAssistantContentEvent
// 正确设置了 awaitingFirstContent此处不覆盖。
// actions 被清空不代表没有内容,事件重放会恢复。
console.log('[AiMessageStart] 从头重建,保留 awaitingFirstContent:', lastMessage.awaitingFirstContent);
} else if (!hasContent) {
lastMessage.awaitingFirstContent = true;
lastMessage.generatingLabel = lastMessage.generatingLabel || '思考中...';
console.log('[AiMessageStart] 设置等待动画', {
awaitingFirstContent: true,
generatingLabel: lastMessage.generatingLabel
});
} else {
// 如果已有内容,确保等待动画不显示
lastMessage.awaitingFirstContent = false;
lastMessage.generatingLabel = '';
console.log('[AiMessageStart] 关闭等待动画(已有内容)');
}
return;
}
// 其他情况:创建新的 assistant 消息
console.log('[AiMessageStart] 场景=创建新消息');
debugLog('[TaskPolling] 创建新的 assistant 消息');
this.monitorResetSpeech();
this.cleanupStaleToolActions();
@ -133,13 +96,6 @@ export const aiStreamMethods = {
this.streamingMessage = true;
const newMessage = this.messages[this.messages.length - 1];
console.log('[AiMessageStart] 新消息创建完成', {
role: newMessage?.role,
awaitingFirstContent: newMessage?.awaitingFirstContent,
generatingLabel: newMessage?.generatingLabel,
actionsLength: newMessage?.actions?.length || 0,
messagesLength: this.messages.length
});
// 如果是从头重建,标记消息为静默恢复
if (this._rebuildingFromScratch) {
@ -147,33 +103,27 @@ export const aiStreamMethods = {
debugLog('[TaskPolling] 标记消息为静默恢复(从头重建)');
newMessage.awaitingFirstContent = false;
newMessage.generatingLabel = '';
console.log('[AiMessageStart] 从头重建,关闭等待动画');
}
}
// 强制触发Vue响应式更新
this.$forceUpdate();
console.log('[AiMessageStart] 已调用$forceUpdate');
this.$nextTick(() => {
console.log('[AiMessageStart] nextTick回调执行');
this.conditionalScrollToBottom();
});
},
handleThinkingStart(data: any, eventIdx: number) {
console.log('[ThinkingStart] 开始处理', { eventIdx });
debugLog('[TaskPolling] 思考开始, idx:', eventIdx);
const ignoreThinking = this.runMode === 'fast' || this.thinkingMode === false;
if (ignoreThinking) {
this.monitorEndModelOutput();
console.log('[ThinkingStart] 忽略思考fast模式或关闭思考');
return;
}
// 防御性检查如果没有assistant消息先创建一个
const lastMessage = this.messages[this.messages.length - 1];
if (!lastMessage || lastMessage.role !== 'assistant') {
console.log('[DEBUG_AWAITING] ThinkingStart 检测到缺少assistant消息自动创建');
this.chatStartAssistantMessage();
}
@ -188,10 +138,6 @@ export const aiStreamMethods = {
// 有内容了,关闭等待动画
if (lastMessage && lastMessage.role === 'assistant') {
console.log('[ThinkingStart] 关闭等待动画', {
beforeAwaitingFirstContent: lastMessage.awaitingFirstContent,
beforeGeneratingLabel: lastMessage.generatingLabel
});
lastMessage.awaitingFirstContent = false;
lastMessage.generatingLabel = '';
}
@ -267,13 +213,11 @@ export const aiStreamMethods = {
this.monitorEndModelOutput();
},
handleTextStart() {
console.log('[TextStart] 开始处理');
debugLog('[TaskPolling] 文本开始');
// 防御性检查如果没有assistant消息先创建一个
const lastMessage = this.messages[this.messages.length - 1];
if (!lastMessage || lastMessage.role !== 'assistant') {
console.log('[DEBUG_AWAITING] TextStart 检测到缺少assistant消息自动创建');
this.chatStartAssistantMessage();
}
@ -282,10 +226,6 @@ export const aiStreamMethods = {
// 有内容了,关闭等待动画
const currentMessage = this.messages[this.messages.length - 1];
if (currentMessage && currentMessage.role === 'assistant') {
console.log('[TextStart] 关闭等待动画', {
beforeAwaitingFirstContent: currentMessage.awaitingFirstContent,
beforeGeneratingLabel: currentMessage.generatingLabel
});
currentMessage.awaitingFirstContent = false;
currentMessage.generatingLabel = '';
}

View File

@ -94,12 +94,6 @@ export const lifecycleMethods = {
currentConversationId: this.currentConversationId
});
}
console.log(`[DEBUG_AWAITING] 忽略不匹配的事件`, {
eventType,
eventIdx,
eventConversationId: eventData.conversation_id,
currentConversationId: this.currentConversationId
});
debugLog(
`[TaskPolling] 忽略不匹配的事件 #${eventIdx}: ${eventType}, 事件对话=${eventData.conversation_id}, 当前对话=${this.currentConversationId}`
);
@ -176,13 +170,6 @@ export const lifecycleMethods = {
debugLog(`[TaskPolling] 处理事件 #${eventIdx}: ${eventType}`, eventData);
console.log(`[DEBUG_AWAITING] 处理事件`, {
eventType,
eventIdx,
eventConversationId: eventData.conversation_id,
currentConversationId: this.currentConversationId
});
// 根据事件类型调用对应的处理方法
switch (eventType) {
case 'ai_message_start':

View File

@ -8,13 +8,10 @@ export const debugNotifyLog = (...args: any[]) => {
void args;
};
export const keyNotifyLog = (...args: any[]) => {
console.log(...args);
};
export const jsonDebug = (...args: any[]) => {
console.log('[JSONDEBUG]', ...args);
};
export const userMDebug = (...args: any[]) => {
console.log('[USERMDEBUG]', ...args);
};
export const RESTORE_DEBUG_PREFIX = '[RESTORE_DEBUG]';
export let restoreDebugCount = 0;
@ -35,17 +32,16 @@ export const RESTORE_DEBUG_EVENTS = new Set([
]);
export function isRestoreDebugEnabled() {
if (typeof window === 'undefined') return true;
if (typeof window === 'undefined') return false;
try {
const explicit = (window as any).__RESTORE_DEBUG__;
if (explicit === false || explicit === '0') return false;
if (explicit === true || explicit === '1') return true;
if (explicit === false || explicit === '0') return false;
const localFlag = window.localStorage?.getItem('restoreDebug');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}

View File

@ -21,25 +21,18 @@ import {
export const toolMethods = {
handleToolPreparing(data: any) {
console.log('[ToolPreparing] 开始处理', { name: data.name, id: data.id });
debugLog('[TaskPolling] 工具准备中:', data.name);
if (this.dropToolEvents) {
console.log('[ToolPreparing] dropToolEvents=true跳过');
return;
}
const msg = this.chatEnsureAssistantMessage();
if (!msg) {
console.log('[ToolPreparing] 无法获取assistant消息');
return;
}
if (msg.awaitingFirstContent) {
console.log('[ToolPreparing] 关闭等待动画', {
beforeAwaitingFirstContent: msg.awaitingFirstContent,
beforeGeneratingLabel: msg.generatingLabel
});
msg.awaitingFirstContent = false;
msg.generatingLabel = '';
}
@ -105,10 +98,6 @@ export const toolMethods = {
// 但从头重建等场景可能跳过 tool_preparing 直接收到 tool_start
const msgForAwaiting = this.chatEnsureAssistantMessage();
if (msgForAwaiting && msgForAwaiting.awaitingFirstContent) {
console.log('[ToolStart] 关闭等待动画', {
beforeAwaitingFirstContent: msgForAwaiting.awaitingFirstContent,
toolName: data.name
});
msgForAwaiting.awaitingFirstContent = false;
msgForAwaiting.generatingLabel = '';
}
@ -294,7 +283,6 @@ export const toolMethods = {
await personalizationStore.fetchPersonalization();
} catch (e) {
// 静默处理,不影响主流程
console.debug('[TaskPolling] 刷新个人空间数据失败:', e);
}
})();
}

View File

@ -336,19 +336,10 @@ export const hostWorkspaceMethods = {
},
async handleSelectWorkspaceConversation(payload: { conversationId: string; workspaceId: string }) {
const { conversationId, workspaceId } = payload || {};
console.log('[sidebar-debug] handleSelectWorkspaceConversation', {
conversationId,
workspaceId,
currentHostWorkspaceId: this.currentHostWorkspaceId,
versioningHostMode: this.versioningHostMode,
dockerProjectMode: this.dockerProjectMode
});
if (!conversationId || !workspaceId) return;
if ((this.versioningHostMode || this.dockerProjectMode) && workspaceId !== this.currentHostWorkspaceId) {
console.log('[sidebar-debug] switching workspace', { from: this.currentHostWorkspaceId, to: workspaceId });
await this.handleHostWorkspaceSwitch(workspaceId);
}
console.log('[sidebar-debug] loading conversation', { conversationId, currentHostWorkspaceIdAfterSwitch: this.currentHostWorkspaceId });
await this.loadConversation(conversationId, { force: true, workspaceId });
},
async handleRenameWorkspaceFromSidebar(payload: { workspaceId: string; label: string }) {

View File

@ -67,23 +67,13 @@ export const mobileMethods = {
this.uiToggleMobileOverlayMenu();
},
openMobileOverlay(target) {
console.log(
'[UI_DEBUG] openMobileOverlay called, target:',
target,
'isMobileViewport:',
this.isMobileViewport,
'activeMobileOverlay:',
this.activeMobileOverlay
);
if (!this.isMobileViewport) {
console.log('[UI_DEBUG] openMobileOverlay: blocked - not mobile viewport');
return;
}
if (target === 'approval') {
this.fetchPendingToolApprovals();
}
if (this.activeMobileOverlay === target) {
console.log('[UI_DEBUG] openMobileOverlay: target already active, closing');
this.closeMobileOverlay('same-target-click');
return;
}
@ -93,17 +83,10 @@ export const mobileMethods = {
if (target === 'conversation') {
this.uiSetSidebarCollapsed(false);
}
console.log('[UI_DEBUG] openMobileOverlay: opening target:', target);
this.uiSetActiveMobileOverlay(target);
this.uiSetMobileOverlayMenuOpen(false);
},
closeMobileOverlay(source = 'unknown') {
console.log(
'[UI_DEBUG] closeMobileOverlay called from:',
source,
'activeMobileOverlay:',
this.activeMobileOverlay
);
if (!this.activeMobileOverlay) {
this.uiCloseMobileOverlay();
return;

View File

@ -38,12 +38,6 @@ export const panelMethods = {
}
},
toggleApprovalPanel() {
console.log(
'[UI_DEBUG] toggleApprovalPanel called, current rightCollapsed:',
this.rightCollapsed,
'new state:',
!this.rightCollapsed
);
this.rightCollapsed = !this.rightCollapsed;
if (!this.rightCollapsed && this.rightWidth < this.minPanelWidth) {
this.rightWidth = this.minPanelWidth;
@ -71,53 +65,28 @@ export const panelMethods = {
this.toggleFocusPanel();
},
handleApprovalPanelToggleClick() {
console.log(
'[UI_DEBUG] handleApprovalPanelToggleClick called, isMobileViewport:',
this.isMobileViewport,
'currentConversationId:',
this.currentConversationId,
'activeMobileOverlay:',
this.activeMobileOverlay
);
if (!this.currentConversationId) {
console.log('[UI_DEBUG] handleApprovalPanelToggleClick: blocked - no conversation');
return;
}
if (this.isMobileViewport) {
console.log('[UI_DEBUG] handleApprovalPanelToggleClick: mobile path, toggling overlay');
// 手机端:获取审批列表(不自动关闭),然后切换遮罩
this.fetchPendingToolApprovals();
this.openMobileOverlay('approval');
return;
}
console.log('[UI_DEBUG] handleApprovalPanelToggleClick: desktop path, toggling panel');
this.toggleApprovalPanel();
},
handleTokenPanelToggleClick(fromSettingsMenu = false) {
console.log(
'[UI_DEBUG] handleTokenPanelToggleClick called, fromSettingsMenu:',
fromSettingsMenu,
'isMobileViewport:',
this.isMobileViewport,
'tokenPanelCollapsed:',
this.tokenPanelCollapsed,
'currentConversationId:',
this.currentConversationId
);
if (!this.currentConversationId) {
console.log('[UI_DEBUG] handleTokenPanelToggleClick: blocked - no conversation');
return;
}
if (this.isPolicyBlocked('block_token_panel', '用量统计已被管理员禁用')) {
console.log('[UI_DEBUG] handleTokenPanelToggleClick: blocked - policy');
return;
}
// 移动端禁用“点击展开顶部用量面板”,仅允许在已展开时点击收起
if (this.isMobileViewport && this.tokenPanelCollapsed && !fromSettingsMenu) {
console.log('[UI_DEBUG] handleTokenPanelToggleClick: blocked - mobile viewport restriction');
return;
}
console.log('[UI_DEBUG] handleTokenPanelToggleClick: calling toggleTokenPanel');
this.toggleTokenPanel();
},
getMessagesAreaElement() {

View File

@ -20,14 +20,14 @@ import { debugLog } from '../common';
export const SUB_AGENT_DONE_PREFIX_RE = /^(?:✅\s*)?子智能体\s*#?\s*(\d+)\s*任务摘要[:]/;
export const BG_RUN_COMMAND_DONE_PREFIX_RE = /^\[后台\s*run_command\s*完成\]/;
export const userMDebug = (...args: any[]) => {
console.log('[USERMDEBUG]', ...args);
};
export let uiBounceTraceCount = 0;
export const UI_BOUNCE_TRACE_MAX = 140;
export const uiBounceTraceLastTsByKey = new Map<string, number>();
export function isUiBounceTraceEnabled() {
if (typeof window === 'undefined') return true;
// 默认关闭:排障时通过 window.__SCROLL_BOUNCE_TRACE__ = true 或 localStorage.scrollBounceTrace = '1' 显式打开
if (typeof window === 'undefined') return false;
try {
const explicit = (window as any).__SCROLL_BOUNCE_TRACE__;
if (explicit === false || explicit === '0') return false;
@ -35,9 +35,9 @@ export function isUiBounceTraceEnabled() {
const localFlag = window.localStorage?.getItem('scrollBounceTrace');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}
@ -62,7 +62,8 @@ export function uiBounceTrace(
}
export function isConnectionDiagEnabled() {
if (typeof window === 'undefined') return true;
// 默认关闭:排障时通过 window.__CONN_DIAG__ = true 或 localStorage.connDiag = '1' 显式打开
if (typeof window === 'undefined') return false;
try {
const explicit = (window as any).__CONN_DIAG__;
if (explicit === false || explicit === '0') return false;
@ -70,10 +71,9 @@ export function isConnectionDiagEnabled() {
const localFlag = window.localStorage?.getItem('connDiag');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
// 默认常开:无需手动启动
return true;
return false;
} catch {
return true;
return false;
}
}
@ -118,18 +118,10 @@ export function connectionDiag(
export function parseSubAgentDoneLabel(rawContent: any): string | null {
const content = (rawContent || '').toString().trim();
if (!content) {
console.log('[DEBUG_SYSTEM][ui] parseSubAgentDoneLabel: 空内容');
return null;
}
const match = content.match(SUB_AGENT_DONE_PREFIX_RE);
const isCompleted = /已完成/.test(content);
console.log('[DEBUG_SYSTEM][ui] parseSubAgentDoneLabel', {
content,
regex: SUB_AGENT_DONE_PREFIX_RE.toString(),
matched: !!match,
matchAgentId: match?.[1],
isCompleted
});
if (!match || !isCompleted) {
return null;
}

View File

@ -91,8 +91,7 @@ export const socketMethods = {
streamingMessage: !!this.streamingMessage,
visibility: document?.visibilityState || 'unknown',
online: typeof navigator !== 'undefined' ? navigator.onLine : null
},
{ force: true }
}
);
} else if (
isConnectionDiagEnabled() &&
@ -177,8 +176,7 @@ export const socketMethods = {
{
connectedIntervalMs: this.connectionHeartbeatIntervalMs,
disconnectedIntervalMs: this.connectionHeartbeatDisconnectedIntervalMs
},
{ force: true }
}
);
const runHeartbeat = async () => {
if (!this.connectionHeartbeatActive) {
@ -224,7 +222,7 @@ export const socketMethods = {
clearTimeout(this.connectionHeartbeatTimer);
this.connectionHeartbeatTimer = null;
}
connectionDiag('log', 'heartbeat-stop', {}, { force: true });
connectionDiag('log', 'heartbeat-stop', {});
},
async loadInitialData() {
try {

View File

@ -30,11 +30,6 @@ export const tutorialMethods = {
try {
const resp = await fetch('/api/tutorial-status', { credentials: 'same-origin' });
const data = await resp.json().catch(() => ({}));
console.info('[tutorial-prompt] status response:', {
ok: resp.ok,
status: resp.status,
data
});
if (!resp.ok || !data?.success) {
return;
}

View File

@ -159,17 +159,13 @@ export const versioningMethods = {
throw new Error(`详情响应解析失败: ${parseErr?.message || '未知错误'}`);
}
// eslint-disable-next-line no-console
console.log('[VersioningDetail] raw response:', data);
if (!resp.ok || !data?.success) {
throw new Error(data?.error || '加载详情失败');
}
this.versioningSelectedDetail = data.data || null;
// eslint-disable-next-line no-console
console.log('[VersioningDetail] detail set:', this.versioningSelectedDetail);
// eslint-disable-next-line no-console
console.log('[VersioningDetail] files:', this.versioningSelectedDetail?.files);
// eslint-disable-next-line no-console
console.log('[VersioningDetail] first file patch_lines:', this.versioningSelectedDetail?.files?.[0]?.patch_lines);
} catch (error: any) {
// eslint-disable-next-line no-console
console.error('[VersioningDetail] error:', error);

View File

@ -147,7 +147,6 @@ onMounted(async () => {
try {
const resp = await fetch('/api/session-status', { credentials: 'same-origin' });
const data = await resp.json();
console.info('[auth-debug] login page session-status:', data);
} catch (err) {
console.warn('[auth-debug] login page session-status failed:', err);
}

View File

@ -125,7 +125,6 @@ onMounted(async () => {
try {
const resp = await fetch('/api/session-status', { credentials: 'same-origin' });
const data = await resp.json();
console.info('[auth-debug] register page session-status:', data);
} catch (err) {
console.warn('[auth-debug] register page session-status failed:', err);
}

View File

@ -916,7 +916,6 @@ const copyUserMessage = async (msg: any, index: number) => {
const branchUserMessage = (_msg: any) => {
// TODO:
void _msg;
console.log('[ChatArea] 分支功能待实现');
};
const observeUserBubbles = () => {
@ -1083,10 +1082,6 @@ const filteredMessages = computed(() => {
const source = props.messages || [];
const droppedRoleSystem = source.filter((m) => m && m.role === 'system');
if (droppedRoleSystem.length > 0) {
console.log('[DEBUG_SYSTEM][render] filteredMessages 过滤了 role=system 消息', {
count: droppedRoleSystem.length,
samples: droppedRoleSystem.slice(0, 3)
});
}
const result = source.filter((m) => {
if (m && m.metadata && m.metadata.system_injected_image) {
@ -1762,7 +1757,6 @@ function getSubAgentSystemNoticeLabel(action: any): string | null {
const key = action?.id || `no-id-${content.slice(0, 32)}`;
if (!content) {
if (!debugLoggedSystemActionKeys.has(`${key}-empty`)) {
console.log('[DEBUG_SYSTEM][render] system action 内容为空', { action });
debugLoggedSystemActionKeys.add(`${key}-empty`);
}
return null;
@ -1773,7 +1767,6 @@ function getSubAgentSystemNoticeLabel(action: any): string | null {
BG_RUN_COMMAND_DONE_LABEL_RE.test(content))
) {
if (!debugLoggedSystemActionKeys.has(`${key}-variant-pass`)) {
console.log('[DEBUG_SYSTEM][render] 命中 variant 渲染', { action, label: content });
debugLoggedSystemActionKeys.add(`${key}-variant-pass`);
}
return content;
@ -1781,20 +1774,11 @@ function getSubAgentSystemNoticeLabel(action: any): string | null {
const m = content.match(SUB_AGENT_DONE_PREFIX_RE);
if (m && /已完成/.test(content)) {
if (!debugLoggedSystemActionKeys.has(`${key}-regex-pass`)) {
console.log('[DEBUG_SYSTEM][render] 命中 regex 渲染', {
action,
normalized: `子智能体${m[1]} 任务完成`
});
debugLoggedSystemActionKeys.add(`${key}-regex-pass`);
}
return `子智能体${m[1]} 任务完成`;
}
if (!debugLoggedSystemActionKeys.has(`${key}-blocked`)) {
console.log('[DEBUG_SYSTEM][render] system action 被渲染层拦截', {
action,
regex: SUB_AGENT_DONE_PREFIX_RE.toString(),
completed: /已完成/.test(content)
});
debugLoggedSystemActionKeys.add(`${key}-blocked`);
}
return null;
@ -1808,10 +1792,6 @@ function isActionVisible(action: any): boolean {
if (!RENDERABLE_ACTION_TYPES.has(actionType)) {
const key = action?.id || `unknown-${actionType || 'none'}`;
if (!debugLoggedUnknownActionKeys.has(key)) {
console.log('[DEBUG_SYSTEM][render] 未知 action.type已跳过渲染', {
actionType,
action
});
debugLoggedUnknownActionKeys.add(key);
}
return false;
@ -2099,11 +2079,6 @@ const splitActionGroups = (actions: any[] = [], messageIndex = 0) => {
//
if (CHAT_DEBUG_LOGS && actions.length > 0) {
console.log(`[splitActionGroups] 消息 ${messageIndex}:`, {
totalActions: actions.length,
actionTypes: actions.map((a) => a.type),
stackedBlocksEnabled: props.stackedBlocksEnabled
});
}
const flushBuffer = () => {
@ -2140,14 +2115,6 @@ const splitActionGroups = (actions: any[] = [], messageIndex = 0) => {
//
if (CHAT_DEBUG_LOGS && actions.length > 0) {
console.log(`[splitActionGroups] 消息 ${messageIndex} 结果:`, {
totalGroups: result.length,
groups: result.map((g) => ({
kind: g.kind,
actionsCount: g.kind === 'stack' ? g.actions.length : 1,
actionType: g.kind === 'stack' ? g.actions[0]?.type : g.action?.type
}))
});
}
return result;

View File

@ -98,7 +98,7 @@ const RENAME_TYPE_INTERVAL = 32;
const MONITOR_EDITOR_DEBUG = false;
const MONITOR_READER_DEBUG = false;
const MONITOR_RENAME_DEBUG = true;
const MONITOR_RENAME_DEBUG = false;
const readerDebug = (...args: any[]) => {
if (!MONITOR_READER_DEBUG) {
return;
@ -117,14 +117,14 @@ const editorDebug = (...args: any[]) => {
}
console.log('[MonitorEditor]', ...args);
};
const MONITOR_PROGRESS_DEBUG = true;
const MONITOR_PROGRESS_DEBUG = false;
const progressDebug = (...args: any[]) => {
if (!MONITOR_PROGRESS_DEBUG) {
return;
}
console.debug('[MonitorProgress]', ...args);
};
const MONITOR_LIFECYCLE_DEBUG = true;
const MONITOR_LIFECYCLE_DEBUG = false;
const monitorLifecycleDebug = (...args: any[]) => {
if (!MONITOR_LIFECYCLE_DEBUG) {
return;

View File

@ -62,7 +62,6 @@ const filePadding = computed(() => ({
function toggle() {
if (props.node.type === 'folder') {
console.log('[FileTree] click folder header', props.node.path);
fileStore.toggleFolder(props.node.path);
}
}

View File

@ -1911,7 +1911,6 @@ const voiceButtonTitle = computed(() => {
const setupVoiceBridgeCallbacks = () => {
if (typeof window === 'undefined') return;
(window as any).__onVoiceResult = (text: string) => {
console.log('[VoiceInput] Android 识别结果:', text);
const bridge = (window as any).AndroidVoiceBridge;
bridge?.debugLog('__onVoiceResult 被调用, text=' + JSON.stringify(text));
if (!text) {
@ -1959,7 +1958,6 @@ const setupVoiceBridgeCallbacks = () => {
}
};
(window as any).__onVoiceStatus = (status: string) => {
console.log('[VoiceInput] 状态:', status);
if (status === 'listening' || status === 'processing' || status === 'initializing') {
// initializing startListening
isRecording.value = true;
@ -2008,23 +2006,19 @@ const isWebSpeechSupported = computed(() => {
if (typeof window === 'undefined') return false;
const hasSR = 'SpeechRecognition' in window;
const hasWebkit = 'webkitSpeechRecognition' in window;
console.log('[VoiceInput] 检测支持:', { hasSR, hasWebkit, supported: hasSR || hasWebkit });
return hasSR || hasWebkit;
});
const getSpeechRecognitionConstructor = (): typeof SpeechRecognition | null => {
if (typeof window === 'undefined') return null;
const Ctor = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition || null;
console.log('[VoiceInput] 构造函数:', Ctor ? Ctor.name || 'webkitSpeechRecognition' : 'null');
return Ctor;
};
const stopVoiceRecording = () => {
console.log('[VoiceInput] stopVoiceRecording called, isRecording:', isRecording.value);
if (recognitionInstance.value) {
try {
recognitionInstance.value.stop();
console.log('[VoiceInput] recognition.stop() called');
} catch (e) {
console.warn('[VoiceInput] recognition.stop() error:', e);
}
@ -2053,27 +2047,15 @@ const initSpeechRecognition = () => {
voiceAnchorPos = 0;
}
lastVoiceTextLength = 0;
console.log('[VoiceInput] init: anchorPos=', voiceAnchorPos);
recognition.onresult = (event: SpeechRecognitionEvent) => {
console.log('[VoiceInput] onresult fired:', {
resultLength: event.results.length,
resultIndex: (event as any).resultIndex
});
let fullText = '';
for (let i = 0; i < event.results.length; i++) {
const r = event.results[i];
console.log(`[VoiceInput] result[${i}]:`, {
transcript: r[0]?.transcript,
isFinal: r.isFinal,
confidence: r[0]?.confidence
});
fullText += r[0].transcript;
}
console.log('[VoiceInput] fullText:', JSON.stringify(fullText));
if (!fullText) {
console.log('[VoiceInput] fullText empty, skip');
return;
}
@ -2102,7 +2084,6 @@ const initSpeechRecognition = () => {
view.focus();
lastVoiceTextLength = fullText.length;
console.log('[VoiceInput] inserted ok, lastVoiceTextLength=', lastVoiceTextLength);
emit('update:input-message', getEditorPlainText());
emit('input-change');
@ -2114,7 +2095,6 @@ const initSpeechRecognition = () => {
recognition.onerror = (event: SpeechRecognitionErrorEvent) => {
console.warn('[VoiceInput] onerror:', { error: event.error, message: (event as any).message });
if (event.error === 'aborted') {
console.log('[VoiceInput] aborted (user stop), ignore');
return;
}
// no-speech / network / not-allowed / service-not-allowed
@ -2123,35 +2103,27 @@ const initSpeechRecognition = () => {
};
recognition.onstart = () => {
console.log('[VoiceInput] onstart: 录音已开始');
};
recognition.onaudiostart = () => {
console.log('[VoiceInput] onaudiostart: 音频捕获开始');
};
recognition.onsoundstart = () => {
console.log('[VoiceInput] onsoundstart: 检测到声音');
};
recognition.onspeechstart = () => {
console.log('[VoiceInput] onspeechstart: 检测到语音');
};
recognition.onspeechend = () => {
console.log('[VoiceInput] onspeechend: 语音结束');
};
recognition.onsoundend = () => {
console.log('[VoiceInput] onsoundend: 声音结束');
};
recognition.onaudioend = () => {
console.log('[VoiceInput] onaudioend: 音频捕获结束');
};
recognition.onend = () => {
console.log('[VoiceInput] onend: 录音结束, isRecording=', isRecording.value);
isRecording.value = false;
recognitionInstance.value = null;
voiceAnchorPos = 0;
@ -2162,7 +2134,6 @@ const initSpeechRecognition = () => {
};
const toggleVoiceRecording = () => {
console.log('[VoiceInput] toggleVoiceRecording, isRecording=', isRecording.value);
// Android Bridge
const bridge = (window as any).AndroidVoiceBridge;
@ -2193,7 +2164,6 @@ const toggleVoiceRecording = () => {
try {
recognition.start();
console.log('[VoiceInput] recognition.start() called');
recognitionInstance.value = recognition;
isRecording.value = true;
} catch (error) {

View File

@ -208,7 +208,6 @@ function appendToTerm(data: string) {
function renderSessionLog() {
if (!term || !activeSession.value) return;
const log = sessionLogs.value[activeSession.value] || '';
console.log('[TerminalPanel] renderSessionLog:', activeSession.value, 'len:', log.length, 'ready:', _historyReady.value[activeSession.value], 'hydrated:', sessionHydrated.value[activeSession.value]);
term.clear();
if (log) {
term.write(log, () => {
@ -218,7 +217,6 @@ function renderSessionLog() {
}
function switchToSession(name: string) {
console.log('[TerminalPanel] switchToSession:', name);
if (!name) return;
activeSession.value = name;
if (!sessionHydrated.value[name]) {
@ -227,7 +225,6 @@ function switchToSession(name: string) {
delete updatedTimes[name];
_historyLastEventTime.value = updatedTimes;
if (socket?.connected) {
console.log('[TerminalPanel] requesting history for:', name);
socket.emit('get_terminal_output', { session: name, lines: 0, conversation_id: props.conversationId });
}
}
@ -236,12 +233,10 @@ function switchToSession(name: string) {
// ---- watchers ----
watch(activeSession, (val) => {
console.log('[TerminalPanel] activeSession:', val);
if (term) renderSessionLog();
});
watch(sessionKeys, (keys) => {
console.log('[TERMINAL_DEBUG] sessionKeys:', keys);
if (keys.length > 0 && term && !activeSession.value) {
switchToSession(keys[0]);
}
@ -250,7 +245,6 @@ watch(sessionKeys, (keys) => {
//
watch(() => props.workspaceId, (newId, oldId) => {
if (newId && oldId && newId !== oldId) {
console.log('[TerminalPanel] workspace changed:', oldId, '->', newId);
//
if (socket) {
socket.disconnect();
@ -270,7 +264,6 @@ watch(() => props.workspaceId, (newId, oldId) => {
// terminal shell
watch(() => props.conversationId, (newId, oldId) => {
if (newId !== oldId) {
console.log('[TerminalPanel] conversation changed:', oldId, '->', newId);
sessions.value = {};
activeSession.value = '';
sessionLogs.value = {};
@ -286,7 +279,6 @@ watch(() => props.conversationId, (newId, oldId) => {
// ---- socket ----
async function initSocket() {
console.log('[TerminalPanel] initSocket start');
socket = createSocketClient('/', {
transports: ['websocket', 'polling'],
@ -319,16 +311,13 @@ async function initSocket() {
}
socket.on('connect', () => {
console.log('[TerminalPanel] socket connected');
socket!.emit('terminal_subscribe', { all: true, conversation_id: props.conversationId });
});
socket.on('disconnect', () => {
console.log('[TerminalPanel] socket disconnected');
});
socket.on('terminal_subscribed', (data: any) => {
console.log('[TerminalPanel] terminal_subscribed:', data);
if (data?.terminals) {
const map: Record<string, { working_dir?: string; shell?: string }> = {};
for (const t of data.terminals) {
@ -343,7 +332,6 @@ async function initSocket() {
socket.on('terminal_started', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_started:', data);
sessions.value = {
...sessions.value,
[data.session]: { working_dir: data.working_dir, shell: 'bash' }
@ -353,7 +341,6 @@ async function initSocket() {
socket.on('terminal_list_update', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_list_update:', data);
if (data?.terminals) {
const map: Record<string, { working_dir?: string; shell?: string }> = {};
for (const t of data.terminals) {
@ -376,7 +363,6 @@ async function initSocket() {
const historyTime = _historyLastEventTime.value[s] || 0;
const eventTime = typeof data.timestamp === 'number' ? data.timestamp : 0;
if (historyTime > 0 && eventTime > 0 && eventTime <= historyTime) {
console.log('[TerminalPanel] terminal_output DEDUP skip:', s, 'eventTime:', eventTime, '<= historyTime:', historyTime);
return;
}
@ -384,17 +370,14 @@ async function initSocket() {
// _historyReady false
sessionLogs.value[s] = (sessionLogs.value[s] || '') + delta;
if (s === activeSession.value && term && _historyReady.value[s]) {
console.log('[TerminalPanel] terminal_output WRITE:', s, 'len:', delta.length);
term.write(delta);
} else {
console.log('[TerminalPanel] terminal_output SKIP:', s, 'len:', delta.length, 'isActive:', s === activeSession.value, 'ready:', _historyReady.value[s]);
}
if (!activeSession.value) switchToSession(s);
});
socket.on('terminal_input', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_input:', data.session);
//
//
if (!activeSession.value && data.session) switchToSession(data.session);
@ -402,7 +385,6 @@ async function initSocket() {
socket.on('terminal_closed', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_closed:', data);
const updated = { ...sessions.value };
delete updated[data.session];
sessions.value = updated;
@ -414,7 +396,6 @@ async function initSocket() {
socket.on('terminal_reset', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_reset:', data);
const target = data.session || activeSession.value;
if (target) {
sessionLogs.value = { ...sessionLogs.value, [target]: '' };
@ -428,12 +409,10 @@ async function initSocket() {
socket.on('terminal_switched', (data: any) => {
if (!acceptTerminalBroadcast(data)) return;
console.log('[TerminalPanel] terminal_switched:', data);
if (data.current) switchToSession(data.current);
});
const handleHistory = (data: any) => {
console.log('[TerminalPanel] handleHistory FIRED, event session:', data.session, 'data keys:', Object.keys(data).join(','));
const s = data.session || data.active;
if (!s) return;
const raw = data.output || data.data || '';
@ -443,7 +422,6 @@ async function initSocket() {
} else if (Array.isArray(raw)) {
payload = raw.join('\n');
}
console.log('[TerminalPanel] handleHistory:', s, 'rawLen:', raw.length, 'payloadLen:', payload.length, 'isActive:', s === activeSession.value);
if (payload) {
sessionLogs.value[s] = payload;
}
@ -454,7 +432,6 @@ async function initSocket() {
// terminal_output
const lastEventTime = typeof data.last_event_time === 'number' ? data.last_event_time : 0;
_historyLastEventTime.value = { ..._historyLastEventTime.value, [s]: lastEventTime };
console.log('[TerminalPanel] handleHistory SAVED:', s, 'finalLen:', payload.length, 'calling render:', s === activeSession.value);
if (s === activeSession.value) {
renderSessionLog();
}
@ -464,7 +441,6 @@ async function initSocket() {
socket.on('terminal_history', handleHistory);
socket.connect();
console.log('[TerminalPanel] socket connecting...');
}
// ---- ----

View File

@ -158,30 +158,22 @@ const emit = defineEmits<{
}>();
const handleCloseClick = () => {
console.log('[sidebarDEBUG] ToolApprovalPanel close button clicked');
emit('close');
};
// - 使
const isMobileViewport = computed(() => {
const isMobile = typeof window !== 'undefined' && window.innerWidth <= 768;
console.log('[sidebarDEBUG] isMobileViewport computed:', isMobile, 'windowWidth:', window?.innerWidth);
return isMobile;
});
onMounted(() => {
console.log('[sidebarDEBUG] ToolApprovalPanel mounted');
console.log('[sidebarDEBUG] window.innerWidth:', window.innerWidth);
console.log('[sidebarDEBUG] isMobileViewport:', isMobileViewport.value);
console.log('[sidebarDEBUG] body[data-theme]:', document.body.getAttribute('data-theme'));
//
const aside = document.querySelector('.tool-approval-panel');
const sidebarHeader = document.querySelector('.tool-approval-panel .sidebar-header');
if (sidebarHeader) {
const computedStyle = window.getComputedStyle(sidebarHeader);
console.log('[sidebarDEBUG] sidebar-header computed background:', computedStyle.backgroundColor);
console.log('[sidebarDEBUG] sidebar-header computed padding:', computedStyle.paddingTop, computedStyle.paddingBottom);
}
});

View File

@ -865,10 +865,6 @@ const persistPinnedWorkspaces = () => {
const next = Array.from(pinnedWorkspaceIds.value);
const current = personalizationStore.form.sidebar_pinned_workspaces || [];
if (JSON.stringify(next) === JSON.stringify(current)) return;
console.log('[sidebar-debug] persistPinnedWorkspaces', {
next: JSON.parse(JSON.stringify(next)),
current: JSON.parse(JSON.stringify(current))
});
personalizationStore.updateField({
key: 'sidebar_pinned_workspaces',
value: next
@ -880,10 +876,6 @@ const persistWorkspaceOrder = () => {
const next = Array.from(workspaceOrder.value);
const current = personalizationStore.form.sidebar_workspace_order || [];
if (JSON.stringify(next) === JSON.stringify(current)) return;
console.log('[sidebar-debug] persistWorkspaceOrder', {
next: JSON.parse(JSON.stringify(next)),
current: JSON.parse(JSON.stringify(current))
});
personalizationStore.updateField({
key: 'sidebar_workspace_order',
value: next
@ -893,19 +885,12 @@ const persistWorkspaceOrder = () => {
const bumpCurrentWorkspaceToTop = () => {
if (!sidebarSortLoaded.value) return;
const currentId = String(props.currentWorkspaceId || '');
console.log('[sidebar-debug] bumpCurrentWorkspaceToTop', {
currentId,
orderBefore: JSON.parse(JSON.stringify(workspaceOrder.value))
});
if (!currentId || pinnedWorkspaceIds.value.has(currentId)) return;
if (workspaceOrder.value[0] === currentId) return;
const order = workspaceOrder.value.filter((item) => item !== currentId);
order.unshift(currentId);
workspaceOrder.value = order;
persistWorkspaceOrder();
console.log('[sidebar-debug] bumpCurrentWorkspaceToTop after', {
orderAfter: JSON.parse(JSON.stringify(workspaceOrder.value))
});
};
const syncWorkspaceOrderWithWorkspaces = (workspaces: any[]) => {
@ -921,12 +906,6 @@ const syncWorkspaceOrderWithWorkspaces = (workspaces: any[]) => {
const removedIds = new Set(
workspaceOrder.value.filter((id) => !ids.includes(id))
);
console.log('[sidebar-debug] syncWorkspaceOrderWithWorkspaces', {
ids,
newIds,
removedIds: Array.from(removedIds),
orderBefore: JSON.parse(JSON.stringify(workspaceOrder.value))
});
if (newIds.length || removedIds.size) {
workspaceOrder.value = workspaceOrder.value
.filter((id) => !removedIds.has(id))
@ -937,10 +916,6 @@ const syncWorkspaceOrderWithWorkspaces = (workspaces: any[]) => {
const loadSidebarSortFromStore = () => {
if (!personalizationStore.loaded || sidebarSortLoaded.value) return;
console.log('[sidebar-debug] loadSidebarSortFromStore start', {
pinned: JSON.parse(JSON.stringify(personalizationStore.form.sidebar_pinned_workspaces)),
order: JSON.parse(JSON.stringify(personalizationStore.form.sidebar_workspace_order))
});
syncPinnedFromStore();
syncOrderFromStore();
sidebarSortLoaded.value = true;
@ -948,10 +923,6 @@ const loadSidebarSortFromStore = () => {
syncWorkspaceOrderWithWorkspaces(props.workspaces);
}
bumpCurrentWorkspaceToTop();
console.log('[sidebar-debug] loadSidebarSortFromStore end', {
pinned: Array.from(pinnedWorkspaceIds.value),
order: JSON.parse(JSON.stringify(workspaceOrder.value))
});
};
watch(
@ -1165,7 +1136,6 @@ watch(
);
const handleWorkspaceConversationClick = (conversationId: string, workspaceId: string) => {
console.log('[sidebar-debug] handleWorkspaceConversationClick', { conversationId, workspaceId });
openWorkspaceMenuId.value = null;
emit('select-workspace-conversation', { conversationId, workspaceId });
};

View File

@ -120,7 +120,6 @@ export function useEasterEgg() {
}, durationSeconds * 1000);
uiStore.setEasterEggState({ cleanupTimer: timer });
if (payload?.message) {
console.info(`[彩蛋] ${payload.display_name || effectName}: ${payload.message}`);
}
};

View File

@ -24,7 +24,7 @@ import { useQuickDockStore } from '../stores/quickDock';
export async function initializeLegacySocket(ctx: any) {
try {
const SOCKET_DEBUG_LOGS_ENABLED = true;
const SOCKET_DEBUG_LOGS_ENABLED = false;
const socketLog = (...args: any[]) => {
if (!SOCKET_DEBUG_LOGS_ENABLED) {
return;
@ -74,20 +74,10 @@ export async function initializeLegacySocket(ctx: any) {
}
if (action.tool.intent_full === text) {
if (console && console.debug) {
console.debug('[tool_intent] skip (same text)', {
id: action?.id || action?.tool?.id,
name: action?.tool?.name,
text
});
}
return;
}
if (typeof console !== 'undefined' && console.debug) {
console.debug('[tool_intent] typing start', {
id: action?.id || action?.tool?.id,
name: action?.tool?.name,
text
});
}
if (action.tool.intent_full === text && action.tool.intent_rendered === text) {
return;
@ -105,11 +95,6 @@ export async function initializeLegacySocket(ctx: any) {
action.tool.intent_typing_timer = window.setInterval(() => {
action.tool.intent_rendered = text.slice(0, index + 1);
if (index === 0 && console && console.debug) {
console.debug('[tool_intent] typing tick', {
id: action?.id || action?.tool?.id,
name: action?.tool?.name,
next: action.tool.intent_rendered
});
}
index += 1;
if (index >= text.length) {
@ -117,11 +102,6 @@ export async function initializeLegacySocket(ctx: any) {
action.tool.intent_typing_timer = null;
action.tool.intent_rendered = text;
if (console && console.debug) {
console.debug('[tool_intent] typing done', {
id: action?.id || action?.tool?.id,
name: action?.tool?.name,
full: text
});
}
}
if (typeof ctx?.$forceUpdate === 'function') {
@ -789,7 +769,6 @@ export async function initializeLegacySocket(ctx: any) {
// 监听对话变更事件
ctx.socket.on('conversation_changed', (data) => {
socketLog('对话已切换:', data);
console.log('[conv-trace] socket:conversation_changed', data);
// 初始化期间不修改 currentConversationId避免与 bootstrapRoute 冲突
if (ctx.initialRouteResolved) {
@ -1177,11 +1156,6 @@ export async function initializeLegacySocket(ctx: any) {
socketLog('文本开始 (轮询模式,跳过)');
return;
}
console.log('[DEBUG] 收到 text_start 事件:', {
currentConversationId: ctx.currentConversationId,
messagesCount: ctx.messages.length,
currentMessageIndex: ctx.currentMessageIndex
});
socketLog('文本开始');
logStreamingDebug('socket:text_start');
finalizeStreamingText({ force: true });
@ -1192,7 +1166,6 @@ export async function initializeLegacySocket(ctx: any) {
streamingState.activeTextAction = action || ensureActiveTextAction();
ensureActiveMessageBinding();
ctx.$forceUpdate();
console.log('[DEBUG] text_start 处理完成');
});
// 文本内容块
@ -1201,12 +1174,6 @@ export async function initializeLegacySocket(ctx: any) {
if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
return;
}
console.log('[DEBUG] 收到 text_chunk 事件:', {
conversation_id: data?.conversation_id,
currentConversationId: ctx.currentConversationId,
chunkLength: (data?.content || '').length,
index: data?.index
});
logStreamingDebug('socket:text_chunk', {
index: data?.index ?? null,
elapsed: data?.elapsed ?? null,
@ -1301,30 +1268,15 @@ export async function initializeLegacySocket(ctx: any) {
if (ctx.dropToolEvents) {
return;
}
console.log('[DEBUG] 收到 tool_preparing 事件:', {
name: data.name,
id: data.id,
conversation_id: data?.conversation_id,
currentConversationId: ctx.currentConversationId,
match: data?.conversation_id === ctx.currentConversationId
});
socketLog('工具准备中:', data.name);
if (typeof console !== 'undefined' && console.debug) {
console.debug('[tool_intent] preparing', {
id: data?.id,
name: data?.name,
intent: data?.intent,
convo: data?.conversation_id
});
}
if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
console.log('[DEBUG] 跳过 tool_preparing (对话不匹配)');
socketLog('跳过tool_preparing(对话不匹配)', data.conversation_id);
return;
}
const msg = ctx.chatEnsureAssistantMessage();
if (!msg) {
console.log('[DEBUG] tool_preparing: 无法获取assistant消息');
return;
}
if (msg.awaitingFirstContent) {
@ -1355,7 +1307,6 @@ export async function initializeLegacySocket(ctx: any) {
if (data.intent) {
startIntentTyping(action, data.intent);
}
console.log('[DEBUG] tool_preparing 处理完成action已添加');
ctx.$forceUpdate();
ctx.conditionalScrollToBottom();
if (ctx.monitorPreviewTool) {
@ -1376,12 +1327,6 @@ export async function initializeLegacySocket(ctx: any) {
return;
}
if (typeof console !== 'undefined' && console.debug) {
console.debug('[tool_intent] update', {
id: data?.id,
name: data?.name,
intent: data?.intent,
convo: data?.conversation_id
});
}
const target =
ctx.toolFindAction(data.id, data.preparing_id, data.execution_id) ||
@ -1689,35 +1634,21 @@ export async function initializeLegacySocket(ctx: any) {
// 任务完成重点更新Token统计
ctx.socket.on('task_complete', (data) => {
console.log('[DEBUG] 收到 task_complete 事件:', data);
console.log('[DEBUG] 当前状态 (before task_complete):', {
taskInProgress: ctx.taskInProgress,
streamingMessage: ctx.streamingMessage,
has_running_sub_agents: data.has_running_sub_agents
});
socketLog('任务完成', data);
const hasRunningMultiAgent = !!data?.has_running_multi_agent;
// 多智能体模式下,若仍有运行中的多智能体实例,保持对话运行态,继续接收后续消息;
// 但此时主智能体已空闲不应阻塞输入区waitingForSubAgent=false
if (hasRunningMultiAgent) {
console.log('[DEBUG] 多智能体实例仍在运行,保持任务状态但不阻塞输入');
} else if (ctx.multiAgentMode || !data.has_running_sub_agents) {
console.log('[DEBUG] 没有运行中的子智能体/多智能体,重置任务状态');
if (ctx.waitingForSubAgent) {
ctx.waitingForSubAgent = false;
}
ctx.taskInProgress = false;
ctx.scheduleResetAfterTask('socket:task_complete', { preserveMonitorWindows: true });
} else {
console.log('[DEBUG] 有运行中的子智能体,保持任务状态');
}
console.log('[DEBUG] 当前状态 (after task_complete):', {
taskInProgress: ctx.taskInProgress,
streamingMessage: ctx.streamingMessage
});
resetPendingToolEvents();
// 任务完成后立即更新Token统计关键修复
@ -1729,12 +1660,6 @@ export async function initializeLegacySocket(ctx: any) {
// 子智能体等待状态
ctx.socket.on('sub_agent_waiting', (data) => {
console.log('[DEBUG] 收到 sub_agent_waiting 事件:', data);
console.log('[DEBUG] 当前状态 (before sub_agent_waiting):', {
taskInProgress: ctx.taskInProgress,
streamingMessage: ctx.streamingMessage,
stopRequested: ctx.stopRequested
});
socketLog('等待子智能体完成:', data);
// 多智能体模式下,子智能体 idle/running 是常态,不阻塞主对话输入区
@ -1748,13 +1673,6 @@ export async function initializeLegacySocket(ctx: any) {
ctx.stopRequested = false;
}
console.log('[DEBUG] 当前状态 (after sub_agent_waiting):', {
taskInProgress: ctx.taskInProgress,
streamingMessage: ctx.streamingMessage,
stopRequested: ctx.stopRequested,
waitingForSubAgent: ctx.waitingForSubAgent
});
// 显示等待提示
if (typeof ctx.appendSystemAction === 'function') {
const taskList = data.tasks
@ -1764,7 +1682,6 @@ export async function initializeLegacySocket(ctx: any) {
}
ctx.$forceUpdate();
console.log('[DEBUG] sub_agent_waiting 处理完成');
});
// 聚焦文件更新
@ -1886,7 +1803,6 @@ export async function initializeLegacySocket(ctx: any) {
// === 实时终端事件 ===
ctx.socket.on('terminal_subscribed', (data) => {
console.log('[Socket] terminal_subscribed:', data);
if (data?.terminals) {
const sessions: Record<string, { working_dir?: string; shell?: string }> = {};
for (const t of data.terminals) {
@ -1903,7 +1819,6 @@ export async function initializeLegacySocket(ctx: any) {
});
ctx.socket.on('terminal_started', (data) => {
console.log('[Socket] terminal_started:', data);
if (data?.session) {
const sessions = { ...ctx.terminalSessions };
sessions[data.session] = {

View File

@ -17,17 +17,16 @@ let showHtmlDebugCount = 0;
const SHOW_HTML_DEBUG_MAX = 500;
function isShowHtmlDebugEnabled() {
if (typeof window === 'undefined') return true;
if (typeof window === 'undefined') return false;
try {
const flag = (window as any).__SHOW_HTML_DEBUG__;
if (flag === false || flag === '0') return false;
if (flag === true || flag === '1') return true;
if (flag === false || flag === '0') return false;
const localFlag = window.localStorage?.getItem('showHtmlDebug');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}

View File

@ -77,7 +77,8 @@ function isScrollDebugEnabled() {
}
function isShowHtmlScrollTraceEnabled() {
if (typeof window === 'undefined') return true;
// 默认关闭:排障时通过 window.__SHOW_HTML_SCROLL_TRACE__ = true 或 localStorage.showHtmlScrollTrace = '1' 显式打开
if (typeof window === 'undefined') return false;
try {
const explicit = (window as any).__SHOW_HTML_SCROLL_TRACE__;
if (explicit === false || explicit === '0') return false;
@ -85,9 +86,9 @@ function isShowHtmlScrollTraceEnabled() {
const localFlag = window.localStorage?.getItem('showHtmlScrollTrace');
if (localFlag === '0' || localFlag === 'false') return false;
if (localFlag === '1' || localFlag === 'true') return true;
return true;
return false;
} catch {
return true;
return false;
}
}

View File

@ -84,7 +84,6 @@ function clearAwaitingFirstContent(message: any) {
}
}
const userMDebug = (...args: any[]) => {
console.log('[USERMDEBUG]', ...args);
};
export const useChatStore = defineStore('chat', {
@ -222,11 +221,6 @@ export const useChatStore = defineStore('chat', {
this.streamingMessage = true;
message.awaitingFirstContent = true;
console.log('[DEBUG_AWAITING] ===== startAssistantMessage =====', {
awaitingFirstContent: message.awaitingFirstContent,
generatingLabel: message.generatingLabel
});
return message;
},
startThinkingAction() {

View File

@ -188,11 +188,6 @@ export const useConversationStore = defineStore('conversation', {
{ reset = false, refresh = false } = {}
) {
if (!workspaceId) return;
console.log('[sidebar-debug] loadWorkspaceConversations', {
workspaceId,
reset,
refresh
});
let index = this.workspaceGroups.findIndex((g) => g.workspaceId === workspaceId);
if (index === -1) {
this.ensureWorkspaceGroup(workspaceId);

View File

@ -1,7 +1,6 @@
import { defineStore } from 'pinia';
import { useModelStore } from './model';
export type BlockDisplayMode = 'traditional' | 'stacked' | 'minimal';
export type CompactMessageDisplay = 'full' | 'brief';
type RunMode = 'fast' | 'thinking';
@ -859,20 +858,17 @@ export const usePersonalizationStore = defineStore('personalization', {
},
async logout() {
try {
console.info('[auth-debug] logout clicked, sending POST /logout');
const resp = await fetch('/logout', {
method: 'POST',
credentials: 'same-origin',
cache: 'no-store'
});
console.info('[auth-debug] logout POST status:', resp.status);
let payload: any = null;
try {
payload = await resp.json();
} catch (_err) {
payload = null;
}
console.info('[auth-debug] logout POST payload:', payload);
if (resp.ok && (!payload || payload.success !== false)) {
window.location.replace(`/login?logged_out=1&ts=${Date.now()}`);
return;

View File

@ -103,7 +103,6 @@ export const useResourceStore = defineStore('resource', {
this.currentContextTokens = value || 0;
},
toggleTokenPanel() {
console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed);
this.tokenPanelCollapsed = !this.tokenPanelCollapsed;
if (this.tokenPanelCollapsed) {
this.stopContainerStatsPolling();

View File

@ -6,13 +6,24 @@ const debugNotifyLog = (...args: any[]) => {
void args;
};
const keyNotifyLog = (...args: any[]) => {
console.log(...args);
};
const jsonDebug = (...args: any[]) => {
console.log('[JSONDEBUG]', ...args);
};
const CONN_DIAG_PREFIX = '[CONN_DIAG]';
const TASK_POLL_DIAG_MAX = 2000;
// 默认关闭 console 输出(心跳类高频日志);排障时通过 window.__CONN_DIAG__ = true
// 或 localStorage.connDiag = '1' 显式打开。内存记录 __CONN_DIAG_LOGS__ 始终收集。
const isConnDiagConsoleEnabled = () => {
if (typeof window === 'undefined') return false;
try {
const w = window as any;
if (w.__CONN_DIAG__ === true || w.__CONN_DIAG__ === '1') return true;
const localFlag = window.localStorage?.getItem('connDiag');
return localFlag === '1' || localFlag === 'true';
} catch {
return false;
}
};
const taskPollDiag = (event: string, payload: Record<string, any> = {}) => {
const ts = new Date().toISOString();
const record = { ts, event, ...payload };
@ -30,7 +41,9 @@ const taskPollDiag = (event: string, payload: Record<string, any> = {}) => {
} catch {
// ignore
}
console.log(CONN_DIAG_PREFIX, event, record);
if (isConnDiagConsoleEnabled()) {
console.log(CONN_DIAG_PREFIX, event, record);
}
};
export const useTaskStore = defineStore('task', {

View File

@ -10,56 +10,43 @@ const applyTheme = (theme: ThemeKey) => {
document.body.setAttribute('data-theme', theme);
// 调试信息
console.log('=== Theme Applied ===');
console.log('Theme:', theme);
// 检查样式是否生效
setTimeout(() => {
console.log('=== Elements Check ===');
// 输入栏底色
const stadiumShell = document.querySelector('.stadium-shell');
console.log('.stadium-shell exists:', !!stadiumShell);
if (stadiumShell) {
const styles = window.getComputedStyle(stadiumShell);
console.log('.stadium-shell background-color:', styles.backgroundColor);
}
// 对话区域顶部的模型选择器
const ribbonSelector = document.querySelector('.conversation-ribbon__selector');
console.log('.conversation-ribbon__selector exists:', !!ribbonSelector);
if (ribbonSelector) {
const styles = window.getComputedStyle(ribbonSelector);
console.log('.conversation-ribbon__selector color:', styles.color);
}
const selectorModel = document.querySelector('.selector-model');
if (selectorModel) {
const styles = window.getComputedStyle(selectorModel);
console.log('.selector-model color:', styles.color);
}
const selectorMode = document.querySelector('.selector-mode');
if (selectorMode) {
const styles = window.getComputedStyle(selectorMode);
console.log('.selector-mode color:', styles.color);
}
// 下拉菜单
const dropdown = document.querySelector('.model-mode-dropdown');
console.log('.model-mode-dropdown exists:', !!dropdown);
if (dropdown) {
const styles = window.getComputedStyle(dropdown);
console.log('.model-mode-dropdown background-color:', styles.backgroundColor);
}
const dropdownItem = document.querySelector('.dropdown-item');
if (dropdownItem) {
const styles = window.getComputedStyle(dropdownItem);
console.log('.dropdown-item color:', styles.color);
}
console.log('=== End Elements Check ===');
}, 100);
};

View File

@ -3,6 +3,7 @@
import os
import json
import base64
import logging
import mimetypes
import io
import uuid
@ -13,6 +14,9 @@ from copy import deepcopy
from typing import Dict, List, Optional, Any
from pathlib import Path
from datetime import datetime
logger = logging.getLogger(__name__)
try:
from config import (
MAX_CONTEXT_SIZE,
@ -198,23 +202,16 @@ class TokenMixin:
def safe_broadcast_token_update(self):
"""安全的token更新广播只广播累计统计不重新计算"""
try:
print(f"[Debug] 尝试广播token更新")
# 检查是否有回调函数
if not hasattr(self, '_web_terminal_callback'):
print(f"[Debug] 没有_web_terminal_callback属性")
return
if not self._web_terminal_callback:
print(f"[Debug] _web_terminal_callback为None")
return
if not self.current_conversation_id:
print(f"[Debug] 没有当前对话ID")
return
print(f"[Debug] 广播token统计对话ID: {self.current_conversation_id}")
# 只获取已有的累计token统计不重新计算
cumulative_stats = self.get_conversation_token_statistics()
@ -228,14 +225,8 @@ class TokenMixin:
'updated_at': datetime.now().isoformat()
}
print(f"[Debug] Token统计: 累计输入={broadcast_data['cumulative_input_tokens']}, 累计输出={broadcast_data['cumulative_output_tokens']}")
# 广播到前端
self._web_terminal_callback('token_update', broadcast_data)
print(f"[Debug] token更新已广播")
except Exception as e:
print(f"[Debug] 广播token更新失败: {e}")
import traceback
traceback.print_exc()
logger.warning(f"[TokenStats] 广播token更新失败: {e}")