Compare commits
5 Commits
55e0dcfb4f
...
70d2bceb45
| Author | SHA1 | Date | |
|---|---|---|---|
| 70d2bceb45 | |||
| dd08845bbc | |||
| 4b78fd6d40 | |||
| 011f9e14bc | |||
| 8da4a596eb |
@ -259,6 +259,8 @@ class MainTerminal(MainTerminalCommandMixin, MainTerminalContextMixin, MainTermi
|
|||||||
self.terminal_manager.set_host_execution_mode(mode)
|
self.terminal_manager.set_host_execution_mode(mode)
|
||||||
if getattr(self, "sub_agent_manager", None):
|
if getattr(self, "sub_agent_manager", None):
|
||||||
self.sub_agent_manager.set_host_execution_mode(mode)
|
self.sub_agent_manager.set_host_execution_mode(mode)
|
||||||
|
if getattr(self, "file_manager", None):
|
||||||
|
self.file_manager.set_host_execution_mode(mode)
|
||||||
|
|
||||||
def _init_host_network_permission(self):
|
def _init_host_network_permission(self):
|
||||||
default_permission = str(HOST_SANDBOX_NETWORK_PERMISSION or "restricted").strip().lower()
|
default_permission = str(HOST_SANDBOX_NETWORK_PERMISSION or "restricted").strip().lower()
|
||||||
|
|||||||
@ -54,8 +54,15 @@ class FileManagerBase:
|
|||||||
self.container_session: Optional["ContainerHandle"] = None
|
self.container_session: Optional["ContainerHandle"] = None
|
||||||
self._container_proxy: Optional[ContainerFileProxy] = None
|
self._container_proxy: Optional[ContainerFileProxy] = None
|
||||||
self._data_dir: Optional[str] = data_dir
|
self._data_dir: Optional[str] = data_dir
|
||||||
|
# 宿主机执行环境(sandbox / direct),由主终端同步;
|
||||||
|
# direct 时与 run_command 对齐:不走路径授权检查(不套沙箱语义)。
|
||||||
|
self.host_execution_mode: str = "sandbox"
|
||||||
self.set_container_session(container_session)
|
self.set_container_session(container_session)
|
||||||
|
|
||||||
|
def set_host_execution_mode(self, mode: str) -> None:
|
||||||
|
normalized = str(mode or "").strip().lower()
|
||||||
|
self.host_execution_mode = "direct" if normalized == "direct" else "sandbox"
|
||||||
|
|
||||||
def _load_personalization_config(self) -> Optional[Dict]:
|
def _load_personalization_config(self) -> Optional[Dict]:
|
||||||
"""加载个性化配置"""
|
"""加载个性化配置"""
|
||||||
if not self._data_dir:
|
if not self._data_dir:
|
||||||
|
|||||||
@ -175,6 +175,11 @@ class PathMixin:
|
|||||||
def _ensure_host_access(self, full_path: Path, access: str) -> Tuple[bool, str]:
|
def _ensure_host_access(self, full_path: Path, access: str) -> Tuple[bool, str]:
|
||||||
if not self._is_host_mode():
|
if not self._is_host_mode():
|
||||||
return True, ""
|
return True, ""
|
||||||
|
# 执行环境为 direct(完全访问权限)时,run_command 不套沙箱、可读写任意路径;
|
||||||
|
# read_file/write_file/edit_file 为进程内文件操作,本就不走 OS 沙箱,此处与
|
||||||
|
# run_command 语义对齐,直接放行。sandbox 模式下保持授权范围检查不变。
|
||||||
|
if getattr(self, "host_execution_mode", "sandbox") == "direct":
|
||||||
|
return True, ""
|
||||||
check_target = full_path
|
check_target = full_path
|
||||||
if access == "write" and not full_path.exists():
|
if access == "write" and not full_path.exists():
|
||||||
check_target = full_path.parent.resolve()
|
check_target = full_path.parent.resolve()
|
||||||
|
|||||||
@ -107,6 +107,7 @@ export const stateMethods = {
|
|||||||
this.imageEntries = [];
|
this.imageEntries = [];
|
||||||
this.imageLoading = false;
|
this.imageLoading = false;
|
||||||
this.conversationHasImages = false;
|
this.conversationHasImages = false;
|
||||||
|
this.conversationHasVideos = false;
|
||||||
this.toolSetSettingsLoading(false);
|
this.toolSetSettingsLoading(false);
|
||||||
this.toolSetSettings([]);
|
this.toolSetSettings([]);
|
||||||
this.pendingToolApprovals = [];
|
this.pendingToolApprovals = [];
|
||||||
|
|||||||
@ -189,11 +189,20 @@ export const resourceMethods = {
|
|||||||
} else {
|
} else {
|
||||||
this.pendingExecutionMode = '';
|
this.pendingExecutionMode = '';
|
||||||
}
|
}
|
||||||
if (status && typeof status.has_images !== 'undefined') {
|
// has_images/has_videos 遵循与上面模型/运行模式相同的权威规则:
|
||||||
this.conversationHasImages = !!status.has_images;
|
// 有打开对话时才从 status 同步;空对话/显式新建路由(/new)上 status 里的值
|
||||||
}
|
// 是 terminal 残留的旧对话上下文,不能应用——空对话语义上无图片/视频,
|
||||||
if (status && typeof status.has_videos !== 'undefined') {
|
// 直接置 false,否则会误拦 handleModelSelect 的图片/视频能力检查。
|
||||||
this.conversationHasVideos = !!status.has_videos;
|
if (hasConversation && !onExplicitNewRoute) {
|
||||||
|
if (status && typeof status.has_images !== 'undefined') {
|
||||||
|
this.conversationHasImages = !!status.has_images;
|
||||||
|
}
|
||||||
|
if (status && typeof status.has_videos !== 'undefined') {
|
||||||
|
this.conversationHasVideos = !!status.has_videos;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.conversationHasImages = false;
|
||||||
|
this.conversationHasVideos = false;
|
||||||
}
|
}
|
||||||
const compression = status?.conversation?.compression;
|
const compression = status?.conversation?.compression;
|
||||||
if (compression && typeof compression === 'object') {
|
if (compression && typeof compression === 'object') {
|
||||||
|
|||||||
@ -389,6 +389,18 @@ function lineNumber(line: any): string {
|
|||||||
color: var(--state-danger);
|
color: var(--state-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 列表最多显示 5 行(32px/行),超出内部滚动;滚动条隐藏(同 QuickDock 惯例) */
|
||||||
|
.edit-summary-card__list {
|
||||||
|
max-height: 160px;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-summary-card__list::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.edit-summary-card__row {
|
.edit-summary-card__row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -311,7 +311,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.qd-run-item.is-active {
|
.qd-run-item.is-active {
|
||||||
background: var(--surface-soft);
|
background: var(--hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.qd-run-status {
|
.qd-run-status {
|
||||||
@ -418,7 +418,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.qd-file-item.is-active {
|
.qd-file-item.is-active {
|
||||||
background: var(--surface-soft);
|
background: var(--hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.qd-file-name {
|
.qd-file-name {
|
||||||
|
|||||||
@ -308,8 +308,22 @@
|
|||||||
data-tutorial="quick-menu-open"
|
data-tutorial="quick-menu-open"
|
||||||
@click.stop="$emit('toggle-quick-menu')"
|
@click.stop="$emit('toggle-quick-menu')"
|
||||||
:disabled="!isConnected"
|
:disabled="!isConnected"
|
||||||
|
aria-label="快捷菜单"
|
||||||
>
|
>
|
||||||
+
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path d="M5 12h14" /><path d="M12 5v14" />
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div class="agent-type-switcher" :class="{ 'is-disabled': agentTypeLocked }">
|
<div class="agent-type-switcher" :class="{ 'is-disabled': agentTypeLocked }">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -886,10 +886,6 @@ body[data-theme='light'] {
|
|||||||
background: var(--hover-bg);
|
background: var(--hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stadium-btn.send-btn {
|
.stadium-btn.send-btn {
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: var(--on-accent);
|
color: var(--on-accent);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user