feat: add silent disable option and workspace prompt split
This commit is contained in:
parent
50b0dd9336
commit
55ef45e04d
@ -145,6 +145,7 @@ class MainTerminal:
|
||||
)
|
||||
self.easter_egg_manager = EasterEggManager()
|
||||
self._announced_sub_agent_tasks = set()
|
||||
self.silent_tool_disable = False # 是否静默工具禁用提示
|
||||
self.current_session_id = 0 # 用于标识不同的任务会话
|
||||
# 工具类别(可被管理员动态覆盖)
|
||||
self.tool_categories_map = dict(TOOL_CATEGORIES)
|
||||
@ -428,6 +429,9 @@ class MainTerminal:
|
||||
except ValueError:
|
||||
logger.warning("忽略无效默认运行模式: %s", preferred_mode)
|
||||
|
||||
# 静默禁用工具提示
|
||||
self.silent_tool_disable = bool(effective_config.get("silent_tool_disable"))
|
||||
|
||||
|
||||
def _handle_read_tool(self, arguments: Dict) -> Dict:
|
||||
"""集中处理 read_file 工具的三种模式。"""
|
||||
@ -664,6 +668,8 @@ class MainTerminal:
|
||||
|
||||
def _format_disabled_tool_notice(self) -> Optional[str]:
|
||||
"""生成禁用工具提示信息 / Format disabled tool notice."""
|
||||
if getattr(self, "silent_tool_disable", False):
|
||||
return None
|
||||
if not self.disabled_notice_tools:
|
||||
return None
|
||||
|
||||
@ -2508,6 +2514,10 @@ class MainTerminal:
|
||||
{"role": "system", "content": system_prompt}
|
||||
]
|
||||
|
||||
workspace_system = self.context_manager._build_workspace_system_message(context)
|
||||
if workspace_system:
|
||||
messages.append({"role": "system", "content": workspace_system})
|
||||
|
||||
if self.tool_category_states.get("todo", True):
|
||||
todo_prompt = self.load_prompt("todo_guidelines").strip()
|
||||
if todo_prompt:
|
||||
|
||||
@ -38,6 +38,7 @@ DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = {
|
||||
"tool_intent_enabled": True,
|
||||
"default_model": "kimi-k2.5",
|
||||
"image_compression": "original", # original / 1080p / 720p / 540p
|
||||
"silent_tool_disable": False, # 禁用工具时不向模型插入提示
|
||||
}
|
||||
|
||||
__all__ = [
|
||||
@ -164,6 +165,12 @@ def sanitize_personalization_payload(
|
||||
elif base.get("image_compression") not in allowed_image_modes:
|
||||
base["image_compression"] = "original"
|
||||
|
||||
# 静默禁用工具提示
|
||||
if "silent_tool_disable" in data:
|
||||
base["silent_tool_disable"] = bool(data.get("silent_tool_disable"))
|
||||
else:
|
||||
base["silent_tool_disable"] = bool(base.get("silent_tool_disable"))
|
||||
|
||||
return base
|
||||
|
||||
|
||||
|
||||
@ -136,22 +136,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 7. 工作区信息
|
||||
|
||||
- **运行环境**:隔离容器中(挂载目录 {container_path}),宿主机路径已隐藏
|
||||
- **资源限制**:CPU {container_cpus} 核,内存 {container_memory},磁盘配额 {project_storage}
|
||||
- **当前时间**:{current_time}
|
||||
- **项目结构**:
|
||||
|
||||
```
|
||||
{file_tree}
|
||||
```
|
||||
|
||||
- **长期记忆**:{memory}
|
||||
|
||||
---
|
||||
|
||||
## 8. 核心原则
|
||||
## 7. 核心原则
|
||||
|
||||
1. **安全第一**:只操作授权范围内的文件
|
||||
2. **沟通为主**:不确定时多问,不要自作主张
|
||||
@ -159,8 +144,6 @@
|
||||
4. **用户友好**:用简单的语言解释复杂的操作
|
||||
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
||||
|
||||
---
|
||||
|
||||
## 9. 个性化配置
|
||||
## 8. 个性化配置
|
||||
|
||||
当用户的个性化信息与上文冲突时,以用户的个性化信息为准。
|
||||
|
||||
@ -154,22 +154,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 7. 工作区信息
|
||||
|
||||
- **运行环境**:隔离容器中(挂载目录 {container_path}),宿主机路径已隐藏
|
||||
- **资源限制**:CPU {container_cpus} 核,内存 {container_memory},磁盘配额 {project_storage}
|
||||
- **当前时间**:{current_time}
|
||||
- **项目结构**:
|
||||
|
||||
```
|
||||
{file_tree}
|
||||
```
|
||||
|
||||
- **长期记忆**:{memory}
|
||||
|
||||
---
|
||||
|
||||
## 8. 核心原则
|
||||
## 7. 核心原则
|
||||
|
||||
1. **安全第一**:只操作授权范围内的文件
|
||||
2. **沟通为主**:不确定时多问,不要自作主张
|
||||
@ -177,8 +162,6 @@
|
||||
4. **用户友好**:用简单的语言解释复杂的操作
|
||||
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
||||
|
||||
---
|
||||
|
||||
## 9. 个性化配置
|
||||
## 8. 个性化配置
|
||||
|
||||
当用户的个性化信息与上文冲突时,以用户的个性化信息为准。
|
||||
|
||||
12
prompts/workspace_system.txt
Normal file
12
prompts/workspace_system.txt
Normal file
@ -0,0 +1,12 @@
|
||||
## 工作区信息
|
||||
|
||||
- **运行环境**:{runtime_environment}
|
||||
- **资源限制**:{resource_limit}
|
||||
- **当前时间**:{current_time}
|
||||
- **项目结构**:
|
||||
|
||||
```
|
||||
{file_tree}
|
||||
```
|
||||
|
||||
- **长期记忆**:{memory}
|
||||
@ -63,6 +63,7 @@
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="section-note">仅作用于当前工作区,可随时在左下角开关。</p>
|
||||
<div class="personalization-sections">
|
||||
<div class="personal-left-column">
|
||||
<div class="personal-section personal-info">
|
||||
@ -254,25 +255,6 @@
|
||||
Qwen-Max 仅支持快速模式;Qwen-VL 不支持深度思考模式,选择时会给出提示。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-actions-row">
|
||||
<div class="personal-form-actions card-aligned">
|
||||
<div class="personal-status-group">
|
||||
<transition name="personal-status-fade">
|
||||
<span class="status success" v-if="status">{{ status }}</span>
|
||||
</transition>
|
||||
<transition name="personal-status-fade">
|
||||
<span class="status error" v-if="error">{{ error }}</span>
|
||||
</transition>
|
||||
</div>
|
||||
<button type="submit" class="primary" :disabled="saving">
|
||||
{{ saving ? '保存中...' : '保存设置' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section v-else-if="activeTab === 'behavior'" key="behavior" class="personal-page behavior-page">
|
||||
<div class="behavior-section">
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">默认思考模型</span>
|
||||
@ -296,6 +278,61 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">思考频率</span>
|
||||
<p class="field-desc">控制连续快速模式运行多少轮后,系统会强制切换到思考模型。</p>
|
||||
</div>
|
||||
<div class="thinking-presets">
|
||||
<button
|
||||
v-for="preset in thinkingPresets"
|
||||
:key="preset.id"
|
||||
type="button"
|
||||
:class="{ active: isPresetActive(preset.value) }"
|
||||
@click.prevent="applyThinkingPreset(preset.value)"
|
||||
>
|
||||
{{ preset.label }}
|
||||
<small>{{ preset.value }} 轮</small>
|
||||
</button>
|
||||
</div>
|
||||
<div class="thinking-input-row">
|
||||
<label>
|
||||
<span>自定义轮数</span>
|
||||
<input
|
||||
type="number"
|
||||
:min="thinkingIntervalRange.min"
|
||||
:max="thinkingIntervalRange.max"
|
||||
:placeholder="`默认 ${thinkingIntervalDefault} 轮`"
|
||||
:value="form.thinking_interval ?? ''"
|
||||
@input="handleThinkingInput"
|
||||
@focus="personalization.clearFeedback()"
|
||||
/>
|
||||
</label>
|
||||
<span class="thinking-hint">范围 {{ thinkingIntervalRange.min }}~{{ thinkingIntervalRange.max }} 轮。</span>
|
||||
<button type="button" class="link-button" @click.prevent="restoreThinkingInterval">
|
||||
恢复默认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="personal-actions-row">
|
||||
<div class="personal-form-actions card-aligned">
|
||||
<div class="personal-status-group">
|
||||
<transition name="personal-status-fade">
|
||||
<span class="status success" v-if="status">{{ status }}</span>
|
||||
</transition>
|
||||
<transition name="personal-status-fade">
|
||||
<span class="status error" v-if="error">{{ error }}</span>
|
||||
</transition>
|
||||
</div>
|
||||
<button type="submit" class="primary" :disabled="saving">
|
||||
{{ saving ? '保存中...' : '保存设置' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section v-else-if="activeTab === 'behavior'" key="behavior" class="personal-page behavior-page">
|
||||
<div class="behavior-section">
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">堆叠块显示</span>
|
||||
@ -319,6 +356,29 @@
|
||||
<span>在对话区使用堆叠动画(可随时切换回传统列表)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">静默禁用</span>
|
||||
<p class="field-desc">禁用工具时不再注入提示消息,模型不会感知被禁用项。</p>
|
||||
</div>
|
||||
<label class="toggle-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="form.silent_tool_disable"
|
||||
@change="personalization.updateField({ key: 'silent_tool_disable', value: $event.target.checked })"
|
||||
/>
|
||||
<span class="fancy-check" aria-hidden="true">
|
||||
<svg viewBox="0 0 64 64">
|
||||
<path
|
||||
d="M 0 16 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 16 L 32 48 L 64 16 V 8 A 8 8 90 0 0 56 0 H 8 A 8 8 90 0 0 0 8 V 56 A 8 8 90 0 0 8 64 H 56 A 8 8 90 0 0 64 56 V 16"
|
||||
pathLength="575.0541381835938"
|
||||
class="fancy-path"
|
||||
></path>
|
||||
</svg>
|
||||
</span>
|
||||
<span>静默禁用工具(不向模型提示)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">自动生成对话标题</span>
|
||||
@ -365,42 +425,6 @@
|
||||
<span>在工具块显示“我要做什么”的简短提示</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">思考频率</span>
|
||||
<p class="field-desc">控制连续快速模式运行多少轮后,系统会强制切换到思考模型。</p>
|
||||
</div>
|
||||
<div class="thinking-presets">
|
||||
<button
|
||||
v-for="preset in thinkingPresets"
|
||||
:key="preset.id"
|
||||
type="button"
|
||||
:class="{ active: isPresetActive(preset.value) }"
|
||||
@click.prevent="applyThinkingPreset(preset.value)"
|
||||
>
|
||||
{{ preset.label }}
|
||||
<small>{{ preset.value }} 轮</small>
|
||||
</button>
|
||||
</div>
|
||||
<div class="thinking-input-row">
|
||||
<label>
|
||||
<span>自定义轮数</span>
|
||||
<input
|
||||
type="number"
|
||||
:min="thinkingIntervalRange.min"
|
||||
:max="thinkingIntervalRange.max"
|
||||
:placeholder="`默认 ${thinkingIntervalDefault} 轮`"
|
||||
:value="form.thinking_interval ?? ''"
|
||||
@input="handleThinkingInput"
|
||||
@focus="personalization.clearFeedback()"
|
||||
/>
|
||||
</label>
|
||||
<span class="thinking-hint">范围 {{ thinkingIntervalRange.min }}~{{ thinkingIntervalRange.max }} 轮。</span>
|
||||
<button type="button" class="link-button" @click.prevent="restoreThinkingInterval">
|
||||
恢复默认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="behavior-field">
|
||||
<div class="behavior-field-header">
|
||||
<span class="field-title">默认禁用工具类别</span>
|
||||
@ -617,9 +641,9 @@ const {
|
||||
} = storeToRefs(personalization);
|
||||
|
||||
const baseTabs = [
|
||||
{ id: 'preferences', label: '个性化设置' },
|
||||
{ id: 'preferences', label: '个性化设置', description: '称呼、语气与注意事项' },
|
||||
{ id: 'model', label: '模型偏好', description: '默认模型选择' },
|
||||
{ id: 'behavior', label: '模型行为' },
|
||||
{ id: 'behavior', label: '模型行为', description: '工具提示与界面表现' },
|
||||
{ id: 'image', label: '图片压缩', description: '发送图片的尺寸策略' },
|
||||
{ id: 'theme', label: '主题切换', description: '浅色 / 深色 / Claude' },
|
||||
{ id: 'experiments', label: '实验功能', description: 'Liquid Glass' }
|
||||
@ -935,6 +959,12 @@ const applyThemeOption = (theme: ThemeKey) => {
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
.section-note {
|
||||
margin: 6px 0 14px;
|
||||
font-size: 12px;
|
||||
color: var(--claude-text-secondary);
|
||||
}
|
||||
|
||||
.admin-monitor-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -6,6 +6,7 @@ interface PersonalForm {
|
||||
enabled: boolean;
|
||||
auto_generate_title: boolean;
|
||||
tool_intent_enabled: boolean;
|
||||
silent_tool_disable: boolean;
|
||||
self_identify: string;
|
||||
user_name: string;
|
||||
profession: string;
|
||||
@ -58,6 +59,7 @@ const defaultForm = (): PersonalForm => ({
|
||||
enabled: false,
|
||||
auto_generate_title: true,
|
||||
tool_intent_enabled: true,
|
||||
silent_tool_disable: false,
|
||||
self_identify: '',
|
||||
user_name: '',
|
||||
profession: '',
|
||||
@ -186,6 +188,7 @@ export const usePersonalizationStore = defineStore('personalization', {
|
||||
enabled: !!data.enabled,
|
||||
auto_generate_title: data.auto_generate_title !== false,
|
||||
tool_intent_enabled: !!data.tool_intent_enabled,
|
||||
silent_tool_disable: !!data.silent_tool_disable,
|
||||
self_identify: data.self_identify || '',
|
||||
user_name: data.user_name || '',
|
||||
profession: data.profession || '',
|
||||
|
||||
@ -265,9 +265,16 @@
|
||||
background: var(--theme-surface-soft);
|
||||
align-self: flex-start;
|
||||
height: auto;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
flex-wrap: wrap;
|
||||
max-height: 72vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
flex-wrap: nowrap;
|
||||
-ms-overflow-style: none; /* IE/Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
.personal-page-tabs::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.personal-tab-button {
|
||||
|
||||
@ -98,6 +98,7 @@ class MainTerminal:
|
||||
data_dir=str(self.data_dir)
|
||||
)
|
||||
self._announced_sub_agent_tasks = set()
|
||||
self.silent_tool_disable = False # 是否静默工具禁用提示
|
||||
|
||||
# 聚焦文件管理
|
||||
self.focused_files = {} # {path: content} 存储聚焦的文件内容
|
||||
@ -439,6 +440,8 @@ class MainTerminal:
|
||||
|
||||
def _format_disabled_tool_notice(self) -> Optional[str]:
|
||||
"""生成禁用工具提示信息 / Format disabled tool notice."""
|
||||
if getattr(self, "silent_tool_disable", False):
|
||||
return None
|
||||
if not self.disabled_notice_tools:
|
||||
return None
|
||||
|
||||
@ -2126,6 +2129,10 @@ class MainTerminal:
|
||||
{"role": "system", "content": system_prompt}
|
||||
]
|
||||
|
||||
workspace_system = self.context_manager._build_workspace_system_message(context)
|
||||
if workspace_system:
|
||||
messages.append({"role": "system", "content": workspace_system})
|
||||
|
||||
if self.tool_category_states.get("todo", True):
|
||||
todo_prompt = self.load_prompt("todo_guidelines").strip()
|
||||
if todo_prompt:
|
||||
|
||||
@ -16,6 +16,8 @@ try:
|
||||
TERMINAL_SANDBOX_CPUS,
|
||||
TERMINAL_SANDBOX_MEMORY,
|
||||
PROJECT_MAX_STORAGE_MB,
|
||||
TERMINAL_SANDBOX_MODE,
|
||||
LINUX_SAFETY,
|
||||
)
|
||||
except ImportError:
|
||||
import sys
|
||||
@ -31,6 +33,8 @@ except ImportError:
|
||||
TERMINAL_SANDBOX_CPUS,
|
||||
TERMINAL_SANDBOX_MEMORY,
|
||||
PROJECT_MAX_STORAGE_MB,
|
||||
TERMINAL_SANDBOX_MODE,
|
||||
LINUX_SAFETY,
|
||||
)
|
||||
from utils.conversation_manager import ConversationManager
|
||||
|
||||
@ -68,6 +72,10 @@ class ContextManager:
|
||||
|
||||
self.load_annotations()
|
||||
|
||||
def _is_host_mode_without_safety(self) -> bool:
|
||||
"""是否处于宿主机模式且未启用安全保护。"""
|
||||
return (TERMINAL_SANDBOX_MODE or "").lower() == "host" and not LINUX_SAFETY
|
||||
|
||||
def set_web_terminal_callback(self, callback):
|
||||
"""设置Web终端回调函数,用于广播事件"""
|
||||
self._web_terminal_callback = callback
|
||||
@ -954,6 +962,9 @@ class ContextManager:
|
||||
|
||||
lines = []
|
||||
project_name = Path(structure['path']).name
|
||||
if self._is_host_mode_without_safety():
|
||||
root_label = f"{structure['path']} (项目根)"
|
||||
else:
|
||||
container_root = (self.container_mount_path or "").strip() or "/workspace"
|
||||
container_root = container_root.rstrip("/") or "/"
|
||||
if container_root == "/":
|
||||
@ -1116,6 +1127,45 @@ class ContextManager:
|
||||
"is_overflow": sizes["total"] > MAX_CONTEXT_SIZE,
|
||||
"usage_percent": (sizes["total"] / MAX_CONTEXT_SIZE) * 100
|
||||
}
|
||||
|
||||
def _build_workspace_system_message(self, context: Dict) -> Optional[str]:
|
||||
"""构建独立的工作区系统消息,根据运行模式动态展示环境与资源信息。"""
|
||||
template = self.load_prompt("workspace_system")
|
||||
if not template:
|
||||
template = (
|
||||
"## 工作区信息\n"
|
||||
"- **运行环境**:{runtime_environment}\n"
|
||||
"- **资源限制**:{resource_limit}\n"
|
||||
"- **当前时间**:{current_time}\n"
|
||||
"- **项目结构**:\n\n{file_tree}\n\n"
|
||||
"- **长期记忆**:{memory}"
|
||||
)
|
||||
|
||||
is_host = self._is_host_mode_without_safety()
|
||||
runtime_environment = (
|
||||
"宿主机模式"
|
||||
if is_host
|
||||
else f"隔离容器中(挂载目录 {self.container_mount_path or '/workspace'}),宿主机路径已隐藏"
|
||||
)
|
||||
resource_limit = (
|
||||
"宿主机模式无限制"
|
||||
if is_host
|
||||
else f"CPU {self.container_cpu_limit} 核,内存 {self.container_memory_limit},磁盘配额 {self.project_storage_limit}"
|
||||
)
|
||||
|
||||
content = template.format(
|
||||
runtime_environment=runtime_environment,
|
||||
resource_limit=resource_limit,
|
||||
container_path=self.container_mount_path or "/workspace",
|
||||
container_cpus=self.container_cpu_limit,
|
||||
container_memory=self.container_memory_limit,
|
||||
project_storage=self.project_storage_limit,
|
||||
current_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
file_tree=context["project_info"]["file_tree"],
|
||||
memory=context["memory"],
|
||||
)
|
||||
|
||||
return content
|
||||
def build_messages(self, context: Dict, user_input: str) -> List[Dict]:
|
||||
"""构建消息列表(添加终端内容注入)"""
|
||||
# 加载系统提示
|
||||
@ -1141,6 +1191,10 @@ class ContextManager:
|
||||
{"role": "system", "content": system_prompt}
|
||||
]
|
||||
|
||||
workspace_system = self._build_workspace_system_message(context)
|
||||
if workspace_system:
|
||||
messages.append({"role": "system", "content": workspace_system})
|
||||
|
||||
# 添加对话历史
|
||||
for conv in context["conversation"]:
|
||||
if conv["role"] == "assistant":
|
||||
|
||||
@ -18,6 +18,8 @@ try:
|
||||
TERMINAL_SANDBOX_CPUS,
|
||||
TERMINAL_SANDBOX_MEMORY,
|
||||
PROJECT_MAX_STORAGE_MB,
|
||||
TERMINAL_SANDBOX_MODE,
|
||||
LINUX_SAFETY,
|
||||
)
|
||||
from config.model_profiles import get_model_prompt_replacements
|
||||
except ImportError:
|
||||
@ -34,6 +36,8 @@ except ImportError:
|
||||
TERMINAL_SANDBOX_CPUS,
|
||||
TERMINAL_SANDBOX_MEMORY,
|
||||
PROJECT_MAX_STORAGE_MB,
|
||||
TERMINAL_SANDBOX_MODE,
|
||||
LINUX_SAFETY,
|
||||
)
|
||||
from config.model_profiles import get_model_prompt_replacements
|
||||
from utils.conversation_manager import ConversationManager
|
||||
@ -70,6 +74,10 @@ class ContextManager:
|
||||
|
||||
self.load_annotations()
|
||||
|
||||
def _is_host_mode_without_safety(self) -> bool:
|
||||
"""是否处于宿主机模式且未启用安全保护。"""
|
||||
return (TERMINAL_SANDBOX_MODE or "").lower() == "host" and not LINUX_SAFETY
|
||||
|
||||
# ===========================================
|
||||
# Token 累计文件工具
|
||||
# ===========================================
|
||||
@ -1109,6 +1117,9 @@ class ContextManager:
|
||||
|
||||
lines = []
|
||||
project_name = Path(structure['path']).name
|
||||
if self._is_host_mode_without_safety():
|
||||
root_label = f"{structure['path']} (项目根)"
|
||||
else:
|
||||
container_root = (self.container_mount_path or "").strip() or "/workspace"
|
||||
container_root = container_root.rstrip("/") or "/"
|
||||
if container_root == "/":
|
||||
@ -1371,6 +1382,45 @@ class ContextManager:
|
||||
continue
|
||||
return parts if parts else text
|
||||
|
||||
def _build_workspace_system_message(self, context: Dict) -> Optional[str]:
|
||||
"""构建独立的工作区系统消息,根据运行模式动态展示环境与资源信息。"""
|
||||
template = self.load_prompt("workspace_system")
|
||||
if not template:
|
||||
template = (
|
||||
"## 工作区信息\n"
|
||||
"- **运行环境**:{runtime_environment}\n"
|
||||
"- **资源限制**:{resource_limit}\n"
|
||||
"- **当前时间**:{current_time}\n"
|
||||
"- **项目结构**:\n\n{file_tree}\n\n"
|
||||
"- **长期记忆**:{memory}"
|
||||
)
|
||||
|
||||
is_host = self._is_host_mode_without_safety()
|
||||
runtime_environment = (
|
||||
"宿主机模式"
|
||||
if is_host
|
||||
else f"隔离容器中(挂载目录 {self.container_mount_path or '/workspace'}),宿主机路径已隐藏"
|
||||
)
|
||||
resource_limit = (
|
||||
"宿主机模式无限制"
|
||||
if is_host
|
||||
else f"CPU {self.container_cpu_limit} 核,内存 {self.container_memory_limit},磁盘配额 {self.project_storage_limit}"
|
||||
)
|
||||
|
||||
content = template.format(
|
||||
runtime_environment=runtime_environment,
|
||||
resource_limit=resource_limit,
|
||||
container_path=self.container_mount_path or "/workspace",
|
||||
container_cpus=self.container_cpu_limit,
|
||||
container_memory=self.container_memory_limit,
|
||||
project_storage=self.project_storage_limit,
|
||||
current_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
file_tree=context["project_info"]["file_tree"],
|
||||
memory=context["memory"],
|
||||
)
|
||||
|
||||
return content
|
||||
|
||||
def build_messages(self, context: Dict, user_input: str) -> List[Dict]:
|
||||
"""构建消息列表(添加终端内容注入)"""
|
||||
# 加载系统提示(Qwen-VL 使用专用提示)
|
||||
@ -1400,6 +1450,10 @@ class ContextManager:
|
||||
{"role": "system", "content": system_prompt}
|
||||
]
|
||||
|
||||
workspace_system = self._build_workspace_system_message(context)
|
||||
if workspace_system:
|
||||
messages.append({"role": "system", "content": workspace_system})
|
||||
|
||||
# 添加对话历史
|
||||
for conv in context["conversation"]:
|
||||
if conv["role"] == "assistant":
|
||||
|
||||
Loading…
Reference in New Issue
Block a user