feat(ui): 极简摘要行补全工具文案、工作流图标统一新设计、只读模式放行调研工具
- MinimalBlocks: 摘要行分类覆盖全部原生工具,新增 MCP(mcp__前缀)/工作流三分/待办两分等文案;counts 改由 CATEGORY_ORDER 生成,根治新增分类漏初始化导致摘要空白的 bug - workflow.svg 换新设计(圆+扁菱形+圆弧弯+圆角方块),侧边栏/快捷菜单窗口内联图标同步,侧边栏图标尺寸修正为 18px - TOOL_ICON_MAP 增加 7 个工作流工具映射,补 submit_plan/terminate_sub_agent - tools_execution: 只读模式放行 terminal_session/snapshot、子智能体全家、list_mcp_servers、list/get_workflow_status 及全部 mcp__ 前缀工具 - EditSummaryCard: 桌面端 diff 弹窗最大高度改为 min(可用空间, 70vh, 640px) - 工作流编辑器:移除阶段块「单出线/终点」文字与顶栏激活按钮;提醒/报错改为按钮下方固定高度浮层(内部滚动+点外部关闭),不再挤占页面布局
This commit is contained in:
parent
8c1dd407df
commit
9602875391
@ -206,6 +206,20 @@ class MainTerminalToolsExecutionMixin:
|
||||
"todo_get",
|
||||
"sleep",
|
||||
"ask_user",
|
||||
# 以下为只读/调研性质或会话状态管理类工具,只读模式(含计划模式)放行:
|
||||
# 终端会话管理与快照(terminal_input 仍禁止,防止经持久终端执行写命令)
|
||||
"terminal_session",
|
||||
"terminal_snapshot",
|
||||
# 子智能体全生命周期(只读权限会传播给子智能体,计划模式调研主力)
|
||||
"create_sub_agent",
|
||||
"close_sub_agent",
|
||||
"terminate_sub_agent",
|
||||
"get_sub_agent_status",
|
||||
# MCP 服务列举(mcp__* 工具在 evaluate_tool_permission 中按前缀放行)
|
||||
"list_mcp_servers",
|
||||
# 工作流只读查询(激活/推进/停用/保存等状态写操作仍禁止)
|
||||
"list_workflows",
|
||||
"get_workflow_status",
|
||||
}
|
||||
_APPROVAL_REQUIRED_TOOLS = {
|
||||
"run_command",
|
||||
@ -383,6 +397,10 @@ class MainTerminalToolsExecutionMixin:
|
||||
# 计划模式下允许提交计划求批准
|
||||
if tool_name == "submit_plan" and self._is_plan_work_mode():
|
||||
return {"allowed": True, "mode": mode}
|
||||
# MCP 工具(mcp__<服务>__<工具>)在只读模式下放行:
|
||||
# 工具名动态生成无法静态区分读写,经用户确认全部允许(副作用风险由提示词约束)
|
||||
if tool_name.startswith("mcp__"):
|
||||
return {"allowed": True, "mode": mode}
|
||||
if tool_name not in self._READONLY_ALLOWED_TOOLS:
|
||||
return {
|
||||
"allowed": False,
|
||||
|
||||
@ -5,12 +5,20 @@
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-width="1.8"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="8" height="8" x="3" y="3" rx="2" />
|
||||
<path d="M7 11v4a2 2 0 0 0 2 2h4" />
|
||||
<rect width="8" height="8" x="13" y="13" rx="2" />
|
||||
<path d="M17 9V7a2 2 0 0 0-2-2h-4" />
|
||||
<!-- 顶部圆节点 -->
|
||||
<circle cx="12" cy="4.6" r="2.6" />
|
||||
<!-- 圆 → 菱形 竖直连线 -->
|
||||
<path d="M12 7.2 V10.1" />
|
||||
<!-- 中部菱形(扁平:半宽3.5 / 半高2.2) -->
|
||||
<path d="M8.5 12.3 L12 10.1 L15.5 12.3 L12 14.5 Z" stroke-linejoin="miter" />
|
||||
<!-- 左右连接线(圆弧弯) -->
|
||||
<path d="M8.5 12.3 H6.1 Q4.5 12.3 4.5 13.9 V16.3" />
|
||||
<path d="M15.5 12.3 H17.9 Q19.5 12.3 19.5 13.9 V16.3" />
|
||||
<!-- 底部圆角方块 -->
|
||||
<rect x="2.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
<rect x="17.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 794 B |
@ -66,6 +66,10 @@ const activeFile = computed<SummaryFile | null>(() => {
|
||||
const PANEL_MAX_WIDTH = 720;
|
||||
const VIEWPORT_MARGIN = 16;
|
||||
const MIN_PANEL_HEIGHT = 140;
|
||||
// 桌面端弹窗最大高度上限(2026-08-22 恢复):与 CSS 基础值 min(70vh, 640px) 对齐,
|
||||
// 在动态可用空间之上再取一次 min,避免高视口下弹窗占满半屏以上
|
||||
const PANEL_MAX_HEIGHT_VH_RATIO = 0.7;
|
||||
const PANEL_MAX_HEIGHT_PX = 640;
|
||||
// 条目上方至少要有这么多可用空间才放上面,否则优先考虑下方
|
||||
const PREFER_ABOVE_MIN_HEIGHT = 260;
|
||||
|
||||
@ -89,7 +93,8 @@ function computePanelStyle() {
|
||||
|
||||
// 垂直:优先放条目上方(底边 = 条目上边缘 - 半个条目高,向上生长);
|
||||
// 上方空间不足且下方更宽裕时改放下方(顶边 = 条目下边缘 + 半个条目高,向下生长)。
|
||||
// 两个方向的高度都吃满该方向的可用空间,无固定上限。
|
||||
// 高度上限 = min(该方向可用空间, 70vh, 640px),保底 MIN_PANEL_HEIGHT。
|
||||
const maxCapHeight = Math.min(vh * PANEL_MAX_HEIGHT_VH_RATIO, PANEL_MAX_HEIGHT_PX);
|
||||
const rowRect = anchorEl.value.getBoundingClientRect();
|
||||
const anchorAbove = rowRect.top - rowRect.height / 2;
|
||||
const anchorBelow = rowRect.bottom + rowRect.height / 2;
|
||||
@ -111,7 +116,7 @@ function computePanelStyle() {
|
||||
...base,
|
||||
top: 'auto',
|
||||
bottom: `${Math.round(vh - bottomEdge)}px`,
|
||||
maxHeight: `${Math.round(bottomEdge - VIEWPORT_MARGIN)}px`
|
||||
maxHeight: `${Math.round(Math.min(bottomEdge - VIEWPORT_MARGIN, maxCapHeight))}px`
|
||||
};
|
||||
} else {
|
||||
const topEdge = Math.min(
|
||||
@ -122,7 +127,7 @@ function computePanelStyle() {
|
||||
...base,
|
||||
top: `${Math.round(topEdge)}px`,
|
||||
bottom: 'auto',
|
||||
maxHeight: `${Math.round(vh - VIEWPORT_MARGIN - topEdge)}px`
|
||||
maxHeight: `${Math.round(Math.min(vh - VIEWPORT_MARGIN - topEdge, maxCapHeight))}px`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,10 +598,23 @@ type ToolCategory =
|
||||
| 'edit'
|
||||
| 'search'
|
||||
| 'webpage'
|
||||
| 'mcp'
|
||||
| 'workflow_activate'
|
||||
| 'workflow_advance'
|
||||
| 'workflow'
|
||||
| 'todo_create'
|
||||
| 'todo_update'
|
||||
| 'memory_update'
|
||||
| 'memory_read'
|
||||
| 'conversation'
|
||||
| 'sub_agent'
|
||||
| 'sub_agent_manage'
|
||||
| 'wait'
|
||||
| 'ask'
|
||||
| 'plan'
|
||||
| 'skill'
|
||||
| 'settings'
|
||||
| 'easter_egg'
|
||||
| 'other';
|
||||
|
||||
const TOOL_CATEGORY_MAP: Record<string, ToolCategory> = {
|
||||
@ -633,6 +646,22 @@ const TOOL_CATEGORY_MAP: Record<string, ToolCategory> = {
|
||||
extract_webpage: 'webpage',
|
||||
save_webpage: 'webpage',
|
||||
|
||||
// MCP(list_mcp_servers 归入此类;mcp__ 前缀由 getToolCategory 动态判定)
|
||||
list_mcp_servers: 'mcp',
|
||||
|
||||
// 工作流:激活 / 推进 / 其余操作
|
||||
activate_workflow: 'workflow_activate',
|
||||
report_workflow_stage: 'workflow_advance',
|
||||
choose_workflow_branch: 'workflow_advance',
|
||||
get_workflow_status: 'workflow',
|
||||
deactivate_workflow: 'workflow',
|
||||
list_workflows: 'workflow',
|
||||
save_workflow: 'workflow',
|
||||
|
||||
// 待办:创建 / 更新
|
||||
todo_create: 'todo_create',
|
||||
todo_update_task: 'todo_update',
|
||||
|
||||
// 更新记忆
|
||||
update_memory: 'memory_update',
|
||||
update_project_memory: 'memory_update',
|
||||
@ -645,8 +674,19 @@ const TOOL_CATEGORY_MAP: Record<string, ToolCategory> = {
|
||||
conversation_search: 'conversation',
|
||||
conversation_review: 'conversation',
|
||||
|
||||
// 子智能体
|
||||
create_sub_agent: 'sub_agent'
|
||||
// 子智能体:创建 / 管理
|
||||
create_sub_agent: 'sub_agent',
|
||||
close_sub_agent: 'sub_agent_manage',
|
||||
terminate_sub_agent: 'sub_agent_manage',
|
||||
get_sub_agent_status: 'sub_agent_manage',
|
||||
|
||||
// 其他原生工具
|
||||
sleep: 'wait',
|
||||
ask_user: 'ask',
|
||||
submit_plan: 'plan',
|
||||
create_skill: 'skill',
|
||||
manage_personalization: 'settings',
|
||||
trigger_easter_egg: 'easter_egg'
|
||||
};
|
||||
|
||||
const CATEGORY_LABELS: Record<ToolCategory, (count: number) => string> = {
|
||||
@ -655,10 +695,23 @@ const CATEGORY_LABELS: Record<ToolCategory, (count: number) => string> = {
|
||||
edit: (n) => `编辑了 ${n} 次文件`,
|
||||
search: (n) => `搜索了 ${n} 次`,
|
||||
webpage: (n) => `查看了 ${n} 次网页`,
|
||||
mcp: (n) => `执行了 ${n} 次 MCP 工具`,
|
||||
workflow_activate: (n) => `激活了 ${n} 个工作流`,
|
||||
workflow_advance: (n) => `推进了 ${n} 次工作流进度`,
|
||||
workflow: (n) => `执行了 ${n} 次工作流操作`,
|
||||
todo_create: (n) => `创建了 ${n} 次待办`,
|
||||
todo_update: (n) => `更新了 ${n} 次待办`,
|
||||
memory_update: (n) => `更新了 ${n} 次记忆`,
|
||||
memory_read: (n) => `查看了 ${n} 次记忆`,
|
||||
conversation: (n) => `回顾了 ${n} 次对话`,
|
||||
sub_agent: (n) => `创建了 ${n} 个子智能体`,
|
||||
sub_agent_manage: (n) => `管理了 ${n} 次子智能体`,
|
||||
wait: (n) => `等待了 ${n} 次`,
|
||||
ask: (n) => `询问了 ${n} 次`,
|
||||
plan: (n) => `提交了 ${n} 次计划`,
|
||||
skill: (n) => `归档了 ${n} 次技能`,
|
||||
settings: (n) => `更新了 ${n} 次个性化设置`,
|
||||
easter_egg: (n) => `触发了 ${n} 次彩蛋`,
|
||||
other: (n) => `执行了 ${n} 次其他操作`
|
||||
};
|
||||
|
||||
@ -668,16 +721,31 @@ const CATEGORY_ORDER: ToolCategory[] = [
|
||||
'edit',
|
||||
'search',
|
||||
'webpage',
|
||||
'mcp',
|
||||
'workflow_activate',
|
||||
'workflow_advance',
|
||||
'workflow',
|
||||
'todo_create',
|
||||
'todo_update',
|
||||
'memory_update',
|
||||
'memory_read',
|
||||
'conversation',
|
||||
'sub_agent',
|
||||
'sub_agent_manage',
|
||||
'wait',
|
||||
'ask',
|
||||
'plan',
|
||||
'skill',
|
||||
'settings',
|
||||
'easter_egg',
|
||||
'other'
|
||||
];
|
||||
|
||||
const getToolCategory = (action: Action): ToolCategory => {
|
||||
const name = action.tool?.name;
|
||||
if (typeof name !== 'string') return 'other';
|
||||
// MCP 工具名动态生成(mcp__<服务>__<工具>),无法穷举,按前缀归类
|
||||
if (name.startsWith('mcp__')) return 'mcp';
|
||||
return TOOL_CATEGORY_MAP[name] || 'other';
|
||||
};
|
||||
|
||||
@ -748,18 +816,11 @@ const getCompletedSummaryText = (actions: Action[]): string => {
|
||||
return getToolSummaryText(toolActions[0]);
|
||||
}
|
||||
|
||||
const counts: Record<ToolCategory, number> = {
|
||||
read: 0,
|
||||
command: 0,
|
||||
edit: 0,
|
||||
search: 0,
|
||||
webpage: 0,
|
||||
memory_update: 0,
|
||||
memory_read: 0,
|
||||
conversation: 0,
|
||||
sub_agent: 0,
|
||||
other: 0
|
||||
};
|
||||
// counts 必须由 CATEGORY_ORDER 生成:手写初始化清单曾在新增分类时漏同步,
|
||||
// 导致新分类计数从 undefined 累加成 NaN、被 count > 0 过滤掉,摘要行整行空白
|
||||
const counts = Object.fromEntries(
|
||||
CATEGORY_ORDER.map((category) => [category, 0])
|
||||
) as Record<ToolCategory, number>;
|
||||
|
||||
toolActions.forEach((action) => {
|
||||
counts[getToolCategory(action)]++;
|
||||
|
||||
@ -5,22 +5,23 @@
|
||||
:class="{ 'qd-window-enter': windowEntering, 'qd-window-exit': windowExiting }"
|
||||
>
|
||||
<header class="qd-window__header">
|
||||
<svg class="qd-window__icon" viewBox="0 0 16 16" fill="none">
|
||||
<circle cx="3" cy="3.5" r="1.8" stroke="currentColor" stroke-width="1.3" />
|
||||
<circle cx="13" cy="8" r="1.8" stroke="currentColor" stroke-width="1.3" />
|
||||
<circle cx="3" cy="12.5" r="1.8" stroke="currentColor" stroke-width="1.3" />
|
||||
<path
|
||||
d="M4.8 3.5h4.4a2 2 0 0 1 2 2v.7"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.3"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M4.8 12.5h4.4a2 2 0 0 0 2-2v-.7"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.3"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<!-- 图形与 /static/icons/workflow.svg 保持一致 -->
|
||||
<svg
|
||||
class="qd-window__icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.8"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="12" cy="4.6" r="2.6" />
|
||||
<path d="M12 7.2 V10.1" />
|
||||
<path d="M8.5 12.3 L12 10.1 L15.5 12.3 L12 14.5 Z" stroke-linejoin="miter" />
|
||||
<path d="M8.5 12.3 H6.1 Q4.5 12.3 4.5 13.9 V16.3" />
|
||||
<path d="M15.5 12.3 H17.9 Q19.5 12.3 19.5 13.9 V16.3" />
|
||||
<rect x="2.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
<rect x="17.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
</svg>
|
||||
<span class="qd-window__title">{{ snapshot.name }}</span>
|
||||
</header>
|
||||
|
||||
@ -102,7 +102,8 @@
|
||||
@click="$emit('open-workflows')"
|
||||
>
|
||||
<span class="sidebar-nav-icon workflow-icon" aria-hidden="true">
|
||||
<!-- 与其他导航按钮统一:内联 workflow 图标,避免 mask 图标异步加载闪烁 -->
|
||||
<!-- 与其他导航按钮统一:内联 workflow 图标,避免 mask 图标异步加载闪烁;
|
||||
图形与 /static/icons/workflow.svg 保持一致 -->
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
@ -110,14 +111,17 @@
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.6"
|
||||
stroke-width="1.8"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect width="8" height="8" x="3" y="3" rx="2" />
|
||||
<path d="M7 11v4a2 2 0 0 0 2 2h4" />
|
||||
<rect width="8" height="8" x="13" y="13" rx="2" />
|
||||
<path d="M17 9V7a2 2 0 0 0-2-2h-4" />
|
||||
<circle cx="12" cy="4.6" r="2.6" />
|
||||
<path d="M12 7.2 V10.1" />
|
||||
<path d="M8.5 12.3 L12 10.1 L15.5 12.3 L12 14.5 Z" stroke-linejoin="miter" />
|
||||
<path d="M8.5 12.3 H6.1 Q4.5 12.3 4.5 13.9 V16.3" />
|
||||
<path d="M15.5 12.3 H17.9 Q19.5 12.3 19.5 13.9 V16.3" />
|
||||
<rect x="2.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
<rect x="17.4" y="16.3" width="4.2" height="4.2" rx="1.1" />
|
||||
</svg>
|
||||
</span>
|
||||
<span class="sidebar-nav-label">工作流</span>
|
||||
|
||||
@ -11,15 +11,25 @@
|
||||
<span v-if="dirty" class="wf-editor__dirty">未保存</span>
|
||||
</div>
|
||||
<div class="wf-editor__topbar-right">
|
||||
<button
|
||||
type="button"
|
||||
class="wf-btn wf-btn--ghost"
|
||||
:class="{ 'wf-btn--issue': errorCount > 0 }"
|
||||
@click="issuesOpen = !issuesOpen"
|
||||
>
|
||||
<span class="icon" :style="iconSrc(errorCount > 0 ? ICONS.circleAlert : ICONS.check)" aria-hidden="true"></span>
|
||||
<span>{{ issueLabel }}</span>
|
||||
</button>
|
||||
<div class="wf-editor__issues-anchor" ref="issuesAnchorRef">
|
||||
<button
|
||||
type="button"
|
||||
class="wf-btn wf-btn--ghost"
|
||||
:class="{ 'wf-btn--issue': errorCount > 0 }"
|
||||
title="查看结构提醒与错误"
|
||||
@click.stop="issuesOpen = !issuesOpen"
|
||||
>
|
||||
<span class="icon" :style="iconSrc(errorCount > 0 ? ICONS.circleAlert : ICONS.check)" aria-hidden="true"></span>
|
||||
<span>{{ issueLabel }}</span>
|
||||
</button>
|
||||
<!-- 提醒/报错弹层:不占页面布局,固定高度 + 内部滚动,点外部关闭 -->
|
||||
<div v-if="issuesOpen && issues.length" class="wf-editor__issues-pop">
|
||||
<div v-for="(issue, i) in issues" :key="i" class="wf-issue" :class="`wf-issue--${issue.level}`">
|
||||
<span class="icon" :style="iconSrc(issue.level === 'error' ? ICONS.circleAlert : ICONS.triangleAlert)" aria-hidden="true"></span>
|
||||
<span>{{ issue.message }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="wf-btn wf-btn--ghost" title="自动排版" @click="onAutoLayout">
|
||||
<span class="icon" :style="iconSrc(ICONS.layoutGrid)" aria-hidden="true"></span>
|
||||
<span>自动排版</span>
|
||||
@ -62,19 +72,9 @@
|
||||
<span class="icon" :style="iconSrc(ICONS.save)" aria-hidden="true"></span>
|
||||
<span>{{ saving ? '保存中…' : '保存' }}</span>
|
||||
</button>
|
||||
<button type="button" class="wf-btn wf-btn--ghost" title="在对话中激活此工作流" @click="onActivate">
|
||||
<span class="icon" :style="iconSrc(ICONS.play)" aria-hidden="true"></span>
|
||||
<span>激活</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div v-if="issuesOpen && issues.length" class="wf-editor__issues">
|
||||
<div v-for="(issue, i) in issues" :key="i" class="wf-issue" :class="`wf-issue--${issue.level}`">
|
||||
<span class="icon" :style="iconSrc(issue.level === 'error' ? ICONS.circleAlert : ICONS.triangleAlert)" aria-hidden="true"></span>
|
||||
<span>{{ issue.message }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="flashMessage" class="wf-editor__flash">{{ flashMessage }}</div>
|
||||
|
||||
<div class="wf-editor__body">
|
||||
@ -487,6 +487,7 @@ const dirty = ref(false);
|
||||
const saving = ref(false);
|
||||
const addNodeMenuOpen = ref(false);
|
||||
const addNodeSelectRef = ref<HTMLElement | null>(null);
|
||||
const issuesAnchorRef = ref<HTMLElement | null>(null);
|
||||
const confirmingStageDelete = ref(false);
|
||||
let flashTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
@ -750,14 +751,13 @@ async function onSave() {
|
||||
}
|
||||
}
|
||||
|
||||
function onActivate() {
|
||||
flash('正式版将在对话 / 菜单中激活此工作流');
|
||||
}
|
||||
|
||||
function onDocumentClick(event: MouseEvent) {
|
||||
if (addNodeMenuOpen.value && addNodeSelectRef.value && !addNodeSelectRef.value.contains(event.target as HTMLElement)) {
|
||||
addNodeMenuOpen.value = false;
|
||||
}
|
||||
if (issuesOpen.value && issuesAnchorRef.value && !issuesAnchorRef.value.contains(event.target as HTMLElement)) {
|
||||
issuesOpen.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function iconSrc(url: string) {
|
||||
@ -837,13 +837,27 @@ onBeforeUnmount(() => {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&__issues {
|
||||
max-height: 160px;
|
||||
/* 提醒/报错弹层:锚固在按钮下方,不占页面布局,固定高度 + 内部滚动 */
|
||||
&__issues-anchor {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__issues-pop {
|
||||
position: absolute;
|
||||
top: calc(100% + 6px);
|
||||
right: 0;
|
||||
width: 320px;
|
||||
max-width: calc(100vw - 32px);
|
||||
height: 240px;
|
||||
overflow-y: auto;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--border-default);
|
||||
background: var(--surface-soft);
|
||||
flex-shrink: 0;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 10px;
|
||||
background: var(--surface-raised);
|
||||
box-shadow: var(--shadow-mid);
|
||||
z-index: 30;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: color-mix(in srgb, var(--text-secondary) 55%, transparent) transparent;
|
||||
}
|
||||
|
||||
&__flash {
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
</div>
|
||||
<div class="stage-node__foot">
|
||||
<span class="stage-node__id">{{ data.node.id }}</span>
|
||||
<span class="stage-node__routes">{{ data.isTerminal ? '终点' : '单出线' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -166,9 +165,5 @@ function iconSrc(url: string) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&__routes {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -180,8 +180,8 @@
|
||||
}
|
||||
|
||||
.workflow-icon svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.monitor-mode-btn.blocked {
|
||||
|
||||
@ -99,7 +99,18 @@ export const TOOL_ICON_MAP = Object.freeze({
|
||||
trigger_easter_egg: 'sparkles',
|
||||
list_mcp_servers: 'mcpLogo',
|
||||
view_image: 'camera',
|
||||
view_video: 'eye'
|
||||
view_video: 'eye',
|
||||
// 工作流工具统一使用 workflow 专用图标
|
||||
activate_workflow: 'workflow',
|
||||
report_workflow_stage: 'workflow',
|
||||
choose_workflow_branch: 'workflow',
|
||||
get_workflow_status: 'workflow',
|
||||
deactivate_workflow: 'workflow',
|
||||
list_workflows: 'workflow',
|
||||
save_workflow: 'workflow',
|
||||
// 补齐原先回落到默认齿轮的原生工具
|
||||
submit_plan: 'clipboard',
|
||||
terminate_sub_agent: 'bot'
|
||||
});
|
||||
|
||||
export const TOOL_CATEGORY_ICON_MAP = Object.freeze({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user