agent-Specialization/utils/api_client/base_mixin.py
JOJO e3c897947f refactor(paths): 统一迁移运行态数据路径到 Astrion 命名空间
- 工作区内部路径 .agents/ -> .astrion/
- 默认运行态数据根 ~/.agents/agents/ -> ~/.astrion/astrion/
- 环境变量 AGENTS_DATA_ROOT -> ASTRION_DATA_ROOT(无兼容)
- 同步更新代码、测试、文档与脚本中的路径引用
- 新增 .gitignore 忽略 .astrion/ 与 .agents/ 运行态目录
2026-07-10 00:35:15 +08:00

96 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ========== api_client.py ==========
# utils/api_client.py - OpenAI-compatible API 客户端支持Web模式
import httpx
import json
import asyncio
import base64
import mimetypes
import os
from typing import List, Dict, Optional, AsyncGenerator, Any
from pathlib import Path
from datetime import datetime
from pathlib import Path
from typing import Tuple
try:
from config import (
OUTPUT_FORMATS,
DEFAULT_RESPONSE_MAX_TOKENS,
LOGS_DIR,
)
except ImportError:
import sys
from pathlib import Path
project_root = Path(__file__).resolve().parents[1]
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
from config import (
OUTPUT_FORMATS,
DEFAULT_RESPONSE_MAX_TOKENS,
LOGS_DIR,
)
from utils.log_rotation import append_line, prune_dir
from utils.api_client.utils import _api_dump_enabled
class DeepSeekClientBaseMixin:
def __init__(self, thinking_mode: bool = True, web_mode: bool = False):
# 模型 API 配置(端点 / 密钥 / 模型 ID由 apply_profile 从 custom_models 注入;
# 这里仅初始化为空,未应用任何模型档案前不可直接发请求。
self.fast_api_config = {
"base_url": "",
"api_key": "",
"model_id": ""
}
self.thinking_api_config = {
"base_url": "",
"api_key": "",
"model_id": ""
}
self.fast_max_tokens = None
self.thinking_max_tokens = None
self.fast_extra_params: Dict = {}
self.thinking_extra_params: Dict = {}
# 上下文预算(由上层在每次请求前设置)
self.current_context_tokens: int = 0
self.max_context_tokens: Optional[int] = None
self.default_context_window: Optional[int] = None
self.thinking_mode = thinking_mode # True=智能思考模式, False=快速模式
self.deep_thinking_mode = False # 深度思考模式:整轮都使用思考模型
self.deep_thinking_session = False # 当前任务是否处于深度思考会话
self.web_mode = web_mode # Web模式标志用于禁用print输出
# 兼容旧代码路径
self.api_base_url = self.fast_api_config["base_url"]
self.api_key = self.fast_api_config["api_key"]
self.model_id = self.fast_api_config["model_id"]
self.model_key = None # 由宿主终端注入,便于做模型兼容处理
self.model_multimodal = "none" # 由模型 profile 注入model_key 不可用时用于能力兜底
self.project_path: Optional[str] = None
# 每个任务的独立状态
self.current_task_first_call = True # 当前任务是否是第一次调用
self.current_task_thinking = "" # 当前任务的思考内容
self.force_thinking_next_call = False # 单次强制思考
self.skip_thinking_next_call = False # 单次强制快速
self.last_call_used_thinking = False # 最近一次调用是否使用思考模型
# 最近一次API错误详情
self.last_error_info: Optional[Dict[str, Any]] = None
# 请求体落盘目录(跟随 LOGS_DIR默认 ~/.astrion/<mode>/logs/api_requests
self.request_dump_dir = Path(LOGS_DIR) / "api_requests"
self.debug_log_path = Path(LOGS_DIR) / "api_debug.log"
def _resolve_env_value(self, name: str) -> Optional[str]:
"""从环境变量获取配置(已由 config/__init__.py 统一注入)。"""
value = os.environ.get(name)
if value is None:
return None
value = value.strip()
return value or None
def _print(self, message: str, end: str = "\n", flush: bool = False):
"""安全的打印函数在Web模式下不输出"""
if not self.web_mode:
print(message, end=end, flush=flush)