<template>
	<el-drawer
		:model-value="visible"
		:title="agentId ? '编辑 Agent' : '新建 Agent'"
		size="860px"
		class="agent-edit-drawer"
		@close="$emit('update:visible', false)"
	>
		<el-tabs v-model="activeTab" type="border-card" class="agent-edit-tabs">
			<el-tab-pane label="基本信息" name="info">
				<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
					<el-form-item v-if="agentId" label="内部名称">
						<el-input :model-value="form.name" disabled />
					</el-form-item>
					<el-form-item label="显示名称" prop="label">
						<el-input v-model="form.label" placeholder="例如：视频划痕检测助手" />
					</el-form-item>
					<el-form-item label="图标">
						<cl-menu-icon v-model="form.icon" :show-icon="true" />
					</el-form-item>
					<el-form-item label="描述">
						<el-input v-model="form.description" type="textarea" :rows="3" placeholder="说明这个 Agent 的用途" />
					</el-form-item>
				</el-form>
			</el-tab-pane>

			<el-tab-pane label="Skill 配置" name="skills">
				<p class="tab-desc">从 Skill 库中选择该 Agent 可用的技能。</p>
				<div class="dual-col">
					<div class="col-panel">
						<div class="col-header">
							<span class="col-title">可选 Skill</span>
							<el-input v-model="skillSearch" placeholder="搜索 Skill" size="small" clearable style="width: 180px" />
						</div>
						<div class="col-body">
							<div v-for="sk in availableSkills" :key="sk.name" class="item item--available" @click="addSkill(sk.name)">
								<span class="item-main">{{ sk.label || sk.name }}</span>
								<el-tag v-if="sk.skillType" size="small" :type="skillTagType(sk.skillType)">
									{{ skillTagLabel(sk.skillType) }}
								</el-tag>
								<el-tag v-if="sk.classification" size="small"
									:type="sk.classification === 'compute-entry' ? 'success' : sk.classification === 'compute-toolkit' ? 'primary' : 'info'"
									style="margin-left: 4px">
									{{ sk.classification }}
								</el-tag>
							</div>
							<el-empty v-if="availableSkills.length === 0" description="暂无可选 Skill" :image-size="48" />
						</div>
					</div>
					<div class="col-panel">
						<div class="col-header">
							<span class="col-title">已选择 Skill（{{ form.skills.length }}）</span>
						</div>
						<div class="col-body">
							<div v-for="name in form.skills" :key="name" class="item item--selected">
								<span class="item-main">{{ getSkillLabel(name) }}</span>
								<el-button type="danger" size="small" text @click="removeSkill(name)">移除</el-button>
							</div>
							<el-empty v-if="form.skills.length === 0" description="暂未选择 Skill" :image-size="48" />
						</div>
					</div>
				</div>
			</el-tab-pane>

			<el-tab-pane label="工具配置" name="tools">
				<p class="tab-desc">这里配置当前 Agent 的工具可见性、局部覆盖、子代理授权和 Worker 路由。全局停用的工具只读展示，需要到工具管理页恢复。</p>
				<div class="tools-layout">
					<section class="tools-summary">
						<div class="summary-card">
							<div class="summary-label">最终启用</div>
							<div class="summary-value">{{ enabledToolCount }}</div>
							<div class="summary-sub">包含核心默认工具和当前 Agent 局部启用工具。</div>
						</div>
						<div class="summary-card">
							<div class="summary-label">核心工具</div>
							<div class="summary-value">{{ coreToolCount }}</div>
							<div class="summary-sub">核心工具默认继承，可在当前 Agent 中单独关闭。</div>
						</div>
						<div class="summary-card summary-card--hint">
							<div class="summary-label">配置说明</div>
							<div class="summary-note">局部配置会覆盖工具治理默认值，包括是否启用、Prompt Hint、子代理权限和 Worker 路由。</div>
						</div>
					</section>

					<section class="tools-toolbar">
						<el-input v-model="toolSearch" placeholder="搜索工具名称、描述或工具集" clearable />
						<el-segmented v-model="toolStatusFilter" :options="toolStatusOptions" />
						<el-switch v-model="showCoreOnly" inline-prompt active-text="仅核心" inactive-text="全部" />
						<el-select v-model="toolRuntimeFilter" placeholder="运行路由" clearable>
							<el-option label="Worker 本地" value="local" />
							<el-option label="主进程代理" value="main-process-proxy" />
							<el-option label="Worker 禁用" value="disabled" />
							<el-option label="需要 Shell" value="shell" />
							<el-option label="需要写权限" value="write" />
						</el-select>
						<el-select v-model="toolGovernanceFilter" placeholder="治理条件" clearable>
							<el-option label="允许子代理" value="subagent-allowed" />
							<el-option label="禁止子代理" value="subagent-blocked" />
							<el-option label="自定义渲染器" value="custom-renderer" />
						</el-select>
						<el-button text @click="resetToolOverrides">重置工具配置</el-button>
						<el-button text @click="clearEnabledOverrides">清空启用覆盖</el-button>
						<el-button text @click="clearDisabledOverrides">清空关闭覆盖</el-button>
					</section>

					<section class="enabled-strip">
						<div class="section-header">
							<div>
								<div class="section-title">当前最终启用工具</div>
								<div class="section-subtitle">先核对最终工具集，再逐个调整单个工具。</div>
							</div>
							<el-tag size="small" type="success">{{ enabledToolCount }} 个</el-tag>
						</div>
						<div v-if="enabledTools.length" class="enabled-chips">
							<div v-for="tool in enabledTools" :key="tool.name" class="enabled-chip">
								<span>{{ tool.label || tool.name }}</span>
								<el-tag size="small" effect="plain">{{ tool.toolset }}</el-tag>
								<el-tag size="small" :type="statusToneMap[tool.statusMeta.state]">{{ tool.statusMeta.label }}</el-tag>
							</div>
						</div>
						<el-empty v-else description="当前 Agent 没有启用工具" :image-size="48" />
					</section>

					<section class="tool-groups">
						<div v-for="group in groupedTools" :key="group.toolset" class="group-card">
							<div class="group-head">
								<div>
									<div class="group-title">{{ group.toolset }}</div>
									<div class="group-subtitle">{{ group.enabledCount }}/{{ group.tools.length }} 已启用</div>
								</div>
							</div>
							<div v-if="group.tools.length" class="tool-grid">
								<div
									v-for="tool in group.tools"
									:key="tool.name"
									class="tool-card"
									:class="[`tool-card--${tool.statusMeta.state}`, { 'tool-card--disabled': tool.status === 0 }]"
								>
									<div class="tool-card__top">
										<div class="tool-card__title">
											<span class="tool-name">{{ tool.label || tool.name }}</span>
											<div class="tool-tags">
												<el-tag v-if="tool.isCore === 1" size="small" effect="plain">核心</el-tag>
												<el-tag size="small" effect="plain">{{ tool.capability || 'text' }}</el-tag>
												<el-tag v-if="tool.visibility" size="small" effect="plain">{{ tool.visibility }}</el-tag>
												<el-tag size="small" effect="plain" :type="runtimeRouteTagType(tool.effectiveRuntimeProfile.workerRoutingHint)">
													{{ runtimeRouteDisplayLabel(tool.runtimeRoute) }}
												</el-tag>
												<el-tag v-if="!tool.effectiveSubagentAllowed" size="small" type="warning" effect="plain">禁止子代理</el-tag>
												<el-tag v-if="tool.rendererCapability?.custom" size="small" type="success" effect="plain">自定义渲染器</el-tag>
											</div>
										</div>
										<el-switch :model-value="tool.statusMeta.enabled" :disabled="tool.status === 0" @change="toggleTool(tool, $event)" />
									</div>
									<div class="tool-card__desc">{{ tool.description || '暂无描述' }}</div>
									<div class="tool-card__meta">
										<span v-if="tool.effectiveRuntimeProfile.requiresShell">需要 Shell</span>
										<span v-if="tool.effectiveRuntimeProfile.requiresWrite">需要写权限</span>
										<span v-if="tool.effectiveRuntimeProfile.requiresSkillScope">需要 Skill 作用域</span>
										<span v-if="!tool.effectiveRuntimeProfile.requiresShell && !tool.effectiveRuntimeProfile.requiresWrite && !tool.effectiveRuntimeProfile.requiresSkillScope">无特殊权限</span>
									</div>
									<div v-if="toolCapabilitySummary(tool)" class="tool-card__capability">{{ toolCapabilitySummary(tool) }}</div>
									<div class="tool-card__runtime-summary">{{ toolManifestSummary(tool) }}</div>
									<div v-if="tool.overrideMeta.hasOverride" class="tool-card__override">
										<div class="tool-card__override-tags">
											<el-tag v-for="tag in tool.overrideMeta.tags" :key="`${tool.name}-${tag.label}`" size="small" effect="plain" :type="tag.type">{{ tag.label }}</el-tag>
										</div>
										<div class="tool-card__override-summary">{{ tool.overrideMeta.summary }}</div>
									</div>
									<div class="tool-card__policy">
										<div class="tool-card__policy-title">策略来源</div>
										<div class="tool-card__policy-tags">
											<el-tag v-for="source in tool.policyMeta.sources" :key="`${tool.name}-${source.label}`" size="small" effect="plain" :type="source.type">{{ source.label }}</el-tag>
										</div>
										<div class="tool-card__policy-summary">最终生效：{{ tool.statusMeta.label }} / {{ runtimeRouteDisplayLabel(tool.runtimeRoute) }}</div>
										<div class="tool-card__policy-summary">{{ tool.effectiveSubagentReason }}</div>
									</div>
									<div class="tool-card__footer">
										<el-tag size="small" :type="statusToneMap[tool.statusMeta.state]">{{ tool.statusMeta.label }}</el-tag>
										<div class="tool-card__actions">
											<span class="tool-card__hint">{{ tool.statusMeta.hint }}</span>
											<el-button text size="small" @click="openToolSettings(tool)">局部配置</el-button>
										</div>
									</div>
								</div>
							</div>
							<el-empty v-else description="当前筛选条件下没有工具" :image-size="40" />
						</div>
					</section>
				</div>
			</el-tab-pane>

			<el-tab-pane label="系统提示词" name="prompt">
				<p class="tab-desc">定义 Agent 的身份和行为规则。预览会展示最终注入给模型的提示词分层结果。</p>
				<el-input v-model="form.systemPrompt" type="textarea" :rows="18" placeholder="系统提示词" />
				<el-collapse style="margin-top: 16px">
					<el-collapse-item>
						<template #title>
							<span>预览最终提示词</span>
						</template>
						<el-button size="small" :loading="previewLoading" style="margin-bottom: 12px" @click="loadPreview">加载预览</el-button>
						<div v-if="previewLayers.length" class="prompt-preview">
							<div v-for="layer in previewLayers" :key="layer.name" class="layer-block">
								<div class="layer-label">{{ layer.name }}</div>
								<pre class="layer-content">{{ layer.content }}</pre>
							</div>
						</div>
						<div v-if="previewToolNames.length" class="preview-meta">
							<div class="preview-title">可用工具</div>
							<div class="preview-tags">
								<el-tag v-for="name in previewToolNames" :key="name" size="small">{{ name }}</el-tag>
							</div>
						</div>
						<div v-if="previewDisabledReasons.length" class="preview-meta">
							<div class="preview-title">禁用原因</div>
							<div v-for="item in previewDisabledReasons" :key="`${item.name}-${item.reason}`" class="preview-reason">{{ item.name }}：{{ item.reason }}</div>
						</div>
					</el-collapse-item>
				</el-collapse>
			</el-tab-pane>

			<el-tab-pane label="子代理" name="subagent">
				<p class="tab-desc">配置当前 Agent 是否允许在普通对话中委派子代理。这里影响 delegate_task / delegate_parallel 的可见性和运行约束。</p>
				<el-form label-width="150px" class="subagent-form">
					<section class="subagent-hero">
						<div>
							<div class="subagent-hero__title">会话内 Subagent</div>
							<div class="subagent-hero__desc">Agent 可以把局部目标交给预设 Agent 或临时 Agent 执行，结果会回写到当前 assistant 消息下的子代理卡片。</div>
						</div>
						<el-switch v-model="subagentConfig.enabled" inline-prompt active-text="启用" inactive-text="关闭" />
					</section>
					<el-form-item label="最大并发子代理">
						<el-input-number v-model="subagentConfig.maxConcurrent" :min="1" :max="10" :disabled="!subagentConfig.enabled" controls-position="right" />
						<span class="form-tip">建议 1-5，过高会增加模型和工具调用压力。</span>
					</el-form-item>
					<el-form-item label="允许预设 Agent">
						<el-select v-model="subagentConfig.allowedPresetAgentIds" multiple filterable clearable :disabled="!subagentConfig.enabled" placeholder="留空表示允许选择全部已发布 Agent" style="width: 100%">
							<el-option v-for="agent in publishedAgentOptions" :key="agent.id" :label="agent.label || agent.name" :value="agent.id">
								<span>{{ agent.label || agent.name }}</span>
								<span class="option-meta">{{ agent.name }}</span>
							</el-option>
						</el-select>
						<div class="field-hint">限制委派时可选择的预设 Agent，避免普通用户把任务交给不合适的 Agent。</div>
					</el-form-item>
					<el-form-item label="子代理可用工具">
						<el-select v-model="subagentConfig.allowedToolNames" multiple filterable clearable :disabled="!subagentConfig.enabled" placeholder="留空表示继承 Agent/全局默认工具范围" style="width: 100%">
							<el-option v-for="tool in subagentToolOptions" :key="tool.name" :label="tool.label || tool.name" :value="tool.name" :disabled="tool.status === 0">
								<span>{{ tool.label || tool.name }}</span>
								<span class="option-meta">{{ tool.toolset }} / {{ tool.name }}</span>
							</el-option>
						</el-select>
						<div class="field-hint">delegate_task / delegate_parallel / clarify 等内部委派工具会被自动排除。</div>
					</el-form-item>
				</el-form>
			</el-tab-pane>

			<el-tab-pane label="模型配置" name="model">
				<p class="tab-desc">未配置时使用系统默认模型。</p>
				<model-channel-selector v-model="modelConfig" />
				<el-form label-width="120px" style="margin-top: 12px">
					<el-form-item label="上下文窗口">
						<el-input-number v-model="modelConfig.contextWindow" :min="1" :max="2048" controls-position="right" />
						<span class="form-tip">单位：千 tokens</span>
					</el-form-item>
					<el-form-item>
						<el-button size="small" @click="clearModelConfig">清空模型配置</el-button>
					</el-form-item>
					<el-divider content-position="left">上下文压缩</el-divider>
					<el-form-item label="压缩阈值">
						<el-slider v-model="form.compactionThreshold" :min="0" :max="100" :step="5" :marks="{ 0: '关闭', 60: '60%', 80: '80%', 95: '95%' }" style="max-width: 420px" />
					</el-form-item>
					<el-form-item label="保留最近消息">
						<el-input-number v-model="form.compactionKeepRecent" :min="2" :max="20" :step="1" />
					</el-form-item>
					<el-form-item label="辅助模型渠道">
						<el-select v-model="form.auxiliaryModelChannelId" placeholder="跟随系统默认" clearable style="width: 260px">
							<el-option v-for="ch in auxiliaryChannels" :key="ch.channelId" :label="ch.channelName" :value="ch.channelId" />
						</el-select>
					</el-form-item>
					<el-form-item v-if="form.auxiliaryModelChannelId" label="辅助模型 ID">
						<el-select v-model="form.auxiliaryModelId" placeholder="选择模型" style="width: 260px">
							<el-option v-for="m in auxiliaryModels" :key="m.name" :label="m.name" :value="m.name" />
						</el-select>
					</el-form-item>
				</el-form>
			</el-tab-pane>

			<el-tab-pane label="高级配置" name="advanced">
				<p class="tab-desc">欢迎语、Middleware、会话目录和长期记忆设置。会话后端默认使用本地文件存储；留空根目录时使用后端默认目录。</p>
				<el-form label-width="150px">
					<el-form-item label="欢迎语">
						<el-input v-model="agentConfig.welcomeMessage" type="textarea" :rows="3" placeholder="用户进入对话时展示的欢迎语" />
					</el-form-item>
					<el-divider content-position="left">Middleware</el-divider>
					<el-form-item label="Tool 重试次数">
						<el-input-number v-model="agentConfig.middleware.toolRetryMaxRetries" :min="0" :max="10" controls-position="right" />
					</el-form-item>
					<el-form-item label="Tool 调用上限">
						<el-input-number v-model="agentConfig.middleware.maxToolCalls" :min="1" :max="100" controls-position="right" />
					</el-form-item>
					<el-form-item label="模型重试次数">
						<el-input-number v-model="agentConfig.middleware.modelRetryMaxRetries" :min="0" :max="10" controls-position="right" />
					</el-form-item>
					<el-divider content-position="left">会话存储</el-divider>
					<el-form-item label="会话后端">
						<el-select v-model="agentConfig.session.backend" style="width: 220px">
							<el-option label="本地文件" value="file" />
							<el-option label="MySQL" value="mysql" />
						</el-select>
					</el-form-item>
					<el-form-item label="工作目录">
						<el-input v-model="agentConfig.session.cwd" placeholder="例如：C:/workspace/project" />
						<div class="field-hint">用于文件工具、命令工具和会话上下文解析相对路径。</div>
					</el-form-item>
					<el-form-item label="恢复上次会话">
						<el-switch v-model="agentConfig.session.restoreLastSession" />
					</el-form-item>
					<el-form-item v-if="agentConfig.session.backend === 'file'" label="本地根目录">
						<el-input v-model="agentConfig.session.file.rootDir" placeholder="留空表示使用后端默认路径" />
						<div class="field-hint">这是后端文件存储目录，不是浏览器 localStorage。</div>
					</el-form-item>
					<el-divider content-position="left">长期记忆</el-divider>
					<el-form-item label="启用长期记忆">
						<el-switch v-model="agentConfig.memory.enabled" />
					</el-form-item>
					<template v-if="agentConfig.memory.enabled">
						<el-form-item label="存储后端">
							<el-select v-model="agentConfig.memory.backend" style="width: 220px">
								<el-option label="MySQL" value="mysql" />
								<el-option label="SQLite" value="sqlite" />
							</el-select>
						</el-form-item>
						<el-form-item label="预取条数">
							<el-input-number v-model="agentConfig.memory.prefetchLimit" :min="1" :max="20" controls-position="right" />
						</el-form-item>
					</template>
				</el-form>
			</el-tab-pane>

			<el-tab-pane label="接口配置" name="api">
				<p class="tab-desc">保存后可通过开放接口调用该 Agent。</p>
				<div v-if="agentId" class="api-preview">
					<h4>调用地址</h4>
					<code>POST /open/agent/run/invoke</code>
					<h4 style="margin-top: 16px">请求示例</h4>
					<pre class="api-code">{{ apiExample }}</pre>
					<el-button size="small" @click="copyApiExample">复制请求示例</el-button>
				</div>
				<el-empty v-else description="保存 Agent 后可查看接口信息" :image-size="60" />
			</el-tab-pane>
		</el-tabs>

		<template #footer>
			<el-button @click="$emit('update:visible', false)">取消</el-button>
			<el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
		</template>
	</el-drawer>

	<el-drawer :model-value="toolSettingsVisible" title="工具局部配置" size="540px" @close="toolSettingsVisible = false">
		<el-form :model="toolSettingsForm" label-width="130px">
			<el-form-item label="工具">
				<el-input :model-value="toolSettingsForm.label || toolSettingsForm.name" disabled />
			</el-form-item>
			<el-form-item label="局部启用">
				<el-select v-model="toolSettingsForm.enabledMode" style="width: 240px">
					<el-option label="跟随全局/默认" value="inherit" />
					<el-option label="当前 Agent 强制启用" value="enabled" />
					<el-option label="当前 Agent 强制关闭" value="disabled" />
				</el-select>
			</el-form-item>
			<el-form-item label="Prompt Hint">
				<el-input v-model="toolSettingsForm.promptHint" type="textarea" :rows="4" :placeholder="toolSettingsPromptPlaceholder" />
			</el-form-item>
			<el-form-item label="允许子代理">
				<el-select v-model="toolSettingsForm.allowInSubagentMode" style="width: 240px">
					<el-option label="跟随工具治理" value="inherit" />
					<el-option label="当前 Agent 允许" value="allowed" />
					<el-option label="当前 Agent 禁止" value="blocked" />
				</el-select>
			</el-form-item>
			<el-form-item label="Worker 路由">
				<el-select v-model="toolSettingsForm.workerRoutingStrategy" style="width: 260px">
					<el-option label="自动" value="auto" />
					<el-option label="强制 Worker 本地" value="force-local" />
					<el-option label="强制主进程代理" value="force-main-process-proxy" />
					<el-option label="强制禁用 Worker" value="force-disabled" />
				</el-select>
			</el-form-item>
			<el-form-item label="运行影响">
				<div class="runtime-impact-preview">
					<div class="runtime-impact-preview__note">{{ toolSettingsImpactNote }}</div>
					<div v-for="item in toolSettingsImpactRows" :key="item.key" class="runtime-impact-preview__row">
						<div>
							<div class="runtime-impact-preview__title">{{ item.label }}</div>
							<div class="runtime-impact-preview__reason">{{ item.reason }}</div>
						</div>
						<el-tag size="small" :type="item.type">{{ item.status }}</el-tag>
					</div>
				</div>
			</el-form-item>
		</el-form>
		<template #footer>
			<el-button @click="toolSettingsVisible = false">取消</el-button>
			<el-button @click="clearToolSettings">清空局部配置</el-button>
			<el-button type="primary" @click="applyToolSettings">应用</el-button>
		</template>
	</el-drawer>
</template>

<script lang="ts" setup>
defineOptions({ name: 'agent-edit' });

import { computed, onMounted, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { useCool } from '/@/cool';
import type { AgentSubagentConfig, AgentToolConfig, SkillMeta } from '../types/index.d';
import ModelChannelSelector from '../components/model-channel-selector.vue';
import { getToolRendererCapability } from '../tools/renderer-registry';
import { toolBlockedReasonLabel } from '../tools/runtime-policy';

type ToolStatusState = 'default_enabled' | 'enabled_for_agent' | 'disabled_for_agent' | 'globally_disabled';
type ToolStatusFilter = 'all' | 'enabled' | 'disabled' | 'global_disabled';
type WorkerRoutingHint = 'local' | 'main-process-proxy' | 'disabled';
type RuntimeRoute = 'worker-local' | 'main-process-proxy' | 'disabled';
type RuntimeProfile = {
	kind?: string;
	executionMode?: 'parallel' | 'sequential';
	supportedInWorker?: boolean;
	workerRoutingHint?: WorkerRoutingHint;
	requiresShell?: boolean;
	requiresWrite?: boolean;
	requiresSkillScope?: boolean;
};
type PerToolConfig = NonNullable<AgentToolConfig['perTool']>[string];
type TagType = 'primary' | 'success' | 'warning' | 'info' | 'danger';

interface ToolCatalogItem {
	name: string;
	label?: string;
	description?: string;
	toolset: string;
	capability?: string;
	visibility?: string;
	status: number;
	isCore: number;
	canDisable?: number;
	governancePolicy?: {
		allowInSubagent?: boolean;
		workerRoutingStrategy?: 'auto' | 'force-local' | 'force-main-process-proxy' | 'force-disabled';
	};
	runtimeProfile?: RuntimeProfile;
	presentation?: {
		rendererCapability?: ReturnType<typeof getToolRendererCapability>;
	};
}

interface ToolViewItem extends ToolCatalogItem {
	rendererCapability: ReturnType<typeof getToolRendererCapability>;
	effectiveRuntimeProfile: Required<Pick<RuntimeProfile, 'executionMode' | 'supportedInWorker' | 'workerRoutingHint'>> & RuntimeProfile;
	runtimeRoute: RuntimeRoute;
	effectiveSubagentAllowed: boolean;
	effectiveSubagentReason: string;
	statusMeta: {
		state: ToolStatusState;
		label: string;
		hint: string;
		enabled: boolean;
	};
	policyMeta: {
		sources: Array<{ label: string; type: TagType }>;
	};
	overrideMeta: {
		hasOverride: boolean;
		tags: Array<{ label: string; type: TagType }>;
		summary: string;
	};
}

interface AgentOption {
	id: number;
	name: string;
	label?: string;
	status?: number;
}

const LEGACY_DEFAULT_TOOLSETS = ['base', 'planning', 'interaction'];
const DEFAULT_TOOL_CONFIG: AgentToolConfig = {
	inheritCoreTools: true,
	enabled: [],
	disabled: [],
	perTool: {}
};
const DEFAULT_SUBAGENT_CONFIG: Required<AgentSubagentConfig> = {
	enabled: true,
	maxConcurrent: 3,
	allowedPresetAgentIds: [],
	allowedToolNames: []
};
const SUBAGENT_BLOCKED_TOOL_NAMES = new Set([
	'delegate_task',
	'delegate_parallel',
	'clarify',
	'memory_save',
	'memory_recall'
]);

const props = defineProps<{
	visible: boolean;
	agentId: number | null;
}>();

const emit = defineEmits<{
	'update:visible': [value: boolean];
	saved: [];
}>();

const { service } = useCool();

const activeTab = ref('info');
const saving = ref(false);
const formRef = ref();
const skillMetas = ref<SkillMeta[]>([]);
const toolCatalog = ref<ToolCatalogItem[]>([]);
const agentOptions = ref<AgentOption[]>([]);
const skillSearch = ref('');
const toolSearch = ref('');
const toolStatusFilter = ref<ToolStatusFilter>('all');
const showCoreOnly = ref(false);
const toolRuntimeFilter = ref('');
const toolGovernanceFilter = ref('');
const toolSettingsVisible = ref(false);
const toolSettingsDiagnostic = ref<any>(null);
const toolSettingsDiagnosticLoading = ref(false);
let toolSettingsDiagnosticToken = 0;
const agentToolDiagnostic = ref<any>(null);
const agentToolDiagnosticLoading = ref(false);
let agentToolDiagnosticToken = 0;
const toolSettingsForm = ref({
	name: '',
	label: '',
	enabledMode: 'inherit' as 'inherit' | 'enabled' | 'disabled',
	promptHint: '',
	allowInSubagentMode: 'inherit' as 'inherit' | 'allowed' | 'blocked',
	workerRoutingStrategy: 'auto' as 'auto' | 'force-local' | 'force-main-process-proxy' | 'force-disabled'
});

const toolStatusOptions = [
	{ label: '全部', value: 'all' },
	{ label: '已启用', value: 'enabled' },
	{ label: '已关闭', value: 'disabled' },
	{ label: '全局停用', value: 'global_disabled' }
];

const statusToneMap: Record<ToolStatusState, TagType> = {
	default_enabled: 'success',
	enabled_for_agent: 'primary',
	disabled_for_agent: 'warning',
	globally_disabled: 'danger'
};

const form = ref({
	name: '',
	label: '',
	description: '',
	icon: '',
	systemPrompt: '',
	skills: [] as string[],
	toolsets: null as string[] | null,
	tools: { ...DEFAULT_TOOL_CONFIG } as AgentToolConfig,
	compactionThreshold: 0,
	compactionKeepRecent: 4,
	auxiliaryModelChannelId: null as number | null,
	auxiliaryModelId: ''
});

const modelConfig = ref({
	channelId: null as number | null,
	modelId: '',
	apiKey: '',
	apiUrl: '',
	contextWindow: null as number | null
});

const agentConfig = ref({
	welcomeMessage: '',
	middleware: {
		toolRetryMaxRetries: 2,
		maxToolCalls: 20,
		modelRetryMaxRetries: 2
	},
	session: {
		backend: 'file' as 'file' | 'mysql',
		cwd: '',
		restoreLastSession: true,
		file: {
			rootDir: ''
		}
	},
	memory: {
		enabled: false,
		backend: 'mysql' as 'mysql' | 'sqlite',
		prefetchLimit: 5
	}
});

const subagentConfig = ref<Required<AgentSubagentConfig>>({ ...DEFAULT_SUBAGENT_CONFIG });
const auxiliaryChannels = ref<any[]>([]);
const auxiliaryModels = ref<any[]>([]);
const previewLoading = ref(false);
const previewLayers = ref<Array<{ name: string; content: string }>>([]);
const previewToolNames = ref<string[]>([]);
const previewDisabledReasons = ref<Array<{ name: string; reason: string }>>([]);

const rules = {
	label: [{ required: true, message: '请输入显示名称', trigger: 'blur' }]
};

const apiExample = computed(() =>
	JSON.stringify(
		{
			agentId: props.agentId,
			input: { message: '请分析这个任务' },
			stream: false,
			timeout: 300000
		},
		null,
		2
	)
);

const availableSkills = computed(() => {
	const selected = new Set(form.value.skills || []);
	const kw = skillSearch.value.trim().toLowerCase();
	return skillMetas.value.filter((s) => {
		if (selected.has(s.name)) return false;
		if (!kw) return true;
		return s.name.toLowerCase().includes(kw) || (s.label || '').toLowerCase().includes(kw);
	});
});

const enabledNameSet = computed(() => new Set(form.value.tools.enabled || []));
const disabledNameSet = computed(() => new Set(form.value.tools.disabled || []));
const perToolConfig = computed(() => form.value.tools.perTool || {});
const toolSettingsPromptPlaceholder = computed(() => '可选：补充这个工具在当前 Agent 下的使用提示。');
const currentToolSettingsTarget = computed(() => toolViews.value.find((item) => item.name === toolSettingsForm.value.name) || null);
const agentToolDiagnosticItems = computed(() => agentToolDiagnostic.value?.items || []);
const agentToolDiagnosticItemMap = computed(() => new Map(agentToolDiagnosticItems.value.map((item: any) => [item.name, item])));
const agentToolRuntimeRouteMap = computed(() => new Map(((agentToolDiagnostic.value as any)?.toolRuntimeRoutes || []).map((item: any) => [item.name, item])));

const toolViews = computed<ToolViewItem[]>(() => {
	return toolCatalog.value.map((tool) => {
		const globalDisabled = tool.status === 0;
		const perTool = perToolConfig.value[tool.name];
		const isExplicitEnabled = perTool?.enabled === true || enabledNameSet.value.has(tool.name);
		const isExplicitDisabled = perTool?.enabled === false || disabledNameSet.value.has(tool.name);
		const isDefaultEnabled = form.value.tools.inheritCoreTools !== false && tool.isCore === 1;
		const diagnosticItem = agentToolDiagnosticItemMap.value.get(tool.name);
		const diagnosticRuntimeRoute = agentToolRuntimeRouteMap.value.get(tool.name);

		let localState: ToolStatusState;
		if (globalDisabled) {
			localState = 'globally_disabled';
		} else if (isExplicitDisabled) {
			localState = 'disabled_for_agent';
		} else if (isExplicitEnabled) {
			localState = 'enabled_for_agent';
		} else if (isDefaultEnabled) {
			localState = 'default_enabled';
		} else {
			localState = 'disabled_for_agent';
		}

		const localEnabled = !globalDisabled && localState !== 'disabled_for_agent';
		const labelMap: Record<ToolStatusState, string> = {
			default_enabled: '默认启用',
			enabled_for_agent: '当前 Agent 启用',
			disabled_for_agent: '当前 Agent 关闭',
			globally_disabled: '全局停用'
		};
		const hintMap: Record<ToolStatusState, string> = {
			default_enabled: '继承核心工具默认配置。',
			enabled_for_agent: '当前 Agent 明确启用。',
			disabled_for_agent: '当前 Agent 明确关闭。',
			globally_disabled: '工具管理中已全局停用。'
		};

		const overrideTags: ToolViewItem['overrideMeta']['tags'] = [];
		const overrideSummary: string[] = [];
		if (typeof perTool?.enabled === 'boolean') {
			overrideTags.push({
				label: perTool.enabled ? '当前 Agent 强制启用' : '当前 Agent 强制关闭',
				type: perTool.enabled ? 'primary' : 'warning'
			});
			overrideSummary.push(perTool.enabled ? '覆盖为启用' : '覆盖为关闭');
		}
		if (typeof perTool?.allowInSubagent === 'boolean') {
			overrideTags.push({
				label: perTool.allowInSubagent ? '当前 Agent 允许子代理' : '当前 Agent 禁止子代理',
				type: perTool.allowInSubagent ? 'success' : 'warning'
			});
			overrideSummary.push(perTool.allowInSubagent ? '允许子代理' : '禁止子代理');
		}
		if (perTool?.workerRoutingStrategy && perTool.workerRoutingStrategy !== 'auto') {
			const routingMeta = workerRoutingOverrideMeta(perTool.workerRoutingStrategy);
			overrideTags.push({ label: routingMeta.label, type: routingMeta.type });
			overrideSummary.push(routingMeta.summary);
		}
		if (perTool?.promptHint?.trim()) {
			overrideTags.push({ label: '自定义 Prompt Hint', type: 'info' });
			overrideSummary.push('自定义 Prompt Hint');
		}

		const effectiveRuntimeProfile = diagnosticItem?.manifest
			? {
				...tool.runtimeProfile,
				kind: diagnosticItem.manifest.kind,
				executionMode: diagnosticItem.manifest.executionMode,
				supportedInWorker: diagnosticItem.manifest.supportedInWorker,
				workerRoutingHint: diagnosticItem.manifest.workerRoutingHint,
				requiresShell: diagnosticItem.manifest.requiresShell,
				requiresWrite: diagnosticItem.manifest.requiresWrite,
				requiresSkillScope: diagnosticItem.manifest.requiresSkillScope
			}
			: buildEffectiveRuntimeProfile(tool, perTool);
		const effectiveSubagentAllowed = diagnosticItem
			? diagnosticItem.runtime?.subagentInProcess?.enabled === true
			: buildEffectiveSubagentAllowed(tool, perTool);
		const effectiveEnabled = typeof diagnosticItem?.runtime?.supervisorInProcess?.enabled === 'boolean'
			? diagnosticItem.runtime.supervisorInProcess.enabled === true
			: localEnabled;
		const effectiveState: ToolStatusState = globalDisabled
			? 'globally_disabled'
			: effectiveEnabled
				? (isExplicitEnabled ? 'enabled_for_agent' : 'default_enabled')
				: 'disabled_for_agent';

		const policySources: ToolViewItem['policyMeta']['sources'] = [
			{ label: '工具目录', type: 'info' },
			{ label: '运行诊断', type: 'info' }
		];
		if (globalDisabled) policySources.push({ label: '全局停用', type: 'danger' });
		if (tool.isCore === 1 && form.value.tools.inheritCoreTools !== false) policySources.push({ label: '核心工具继承', type: 'success' });
		if (enabledNameSet.value.has(tool.name) || disabledNameSet.value.has(tool.name) || overrideTags.length > 0) {
			policySources.push({ label: '当前 Agent 局部配置', type: 'primary' });
		}
		if (tool.governancePolicy?.allowInSubagent === false) policySources.push({ label: '子代理受限', type: 'warning' });
		const rendererCapability = tool.presentation?.rendererCapability || getToolRendererCapability(tool.name);
		if (rendererCapability?.custom) policySources.push({ label: '自定义渲染器', type: 'success' });
		if (diagnosticItem?.runtime?.supervisorInProcess?.blockedReason) {
			policySources.push({ label: '后端运行限制', type: 'warning' });
		}

		return {
			...tool,
			rendererCapability,
			effectiveRuntimeProfile,
			runtimeRoute: diagnosticRuntimeRoute?.runtimeRoute || normalizeRuntimeRoute(effectiveRuntimeProfile.workerRoutingHint),
			effectiveSubagentAllowed,
			effectiveSubagentReason: effectiveSubagentAllowed ? '当前 Agent 允许子代理使用' : '当前 Agent 或工具治理禁止子代理使用',
			statusMeta: {
				state: effectiveState,
				label: labelMap[effectiveState],
				hint: hintMap[effectiveState],
				enabled: effectiveEnabled
			},
			policyMeta: {
				sources: policySources
			},
			overrideMeta: {
				hasOverride: overrideTags.length > 0,
				tags: overrideTags,
				summary: overrideSummary.join(' / ')
			}
		};
	});
});

const filteredTools = computed(() => {
	const keyword = toolSearch.value.trim().toLowerCase();
	return toolViews.value.filter((tool) => {
		if (showCoreOnly.value && tool.isCore !== 1) return false;
		if (toolStatusFilter.value === 'enabled' && !tool.statusMeta.enabled) return false;
		if (toolStatusFilter.value === 'disabled' && tool.statusMeta.state !== 'disabled_for_agent') return false;
		if (toolStatusFilter.value === 'global_disabled' && tool.statusMeta.state !== 'globally_disabled') return false;
		if (toolRuntimeFilter.value === 'local' && tool.effectiveRuntimeProfile.workerRoutingHint !== 'local') return false;
		if (toolRuntimeFilter.value === 'main-process-proxy' && tool.effectiveRuntimeProfile.workerRoutingHint !== 'main-process-proxy') return false;
		if (toolRuntimeFilter.value === 'disabled' && tool.effectiveRuntimeProfile.workerRoutingHint !== 'disabled') return false;
		if (toolRuntimeFilter.value === 'shell' && !tool.effectiveRuntimeProfile.requiresShell) return false;
		if (toolRuntimeFilter.value === 'write' && !tool.effectiveRuntimeProfile.requiresWrite) return false;
		if (toolGovernanceFilter.value === 'subagent-allowed' && !tool.effectiveSubagentAllowed) return false;
		if (toolGovernanceFilter.value === 'subagent-blocked' && tool.effectiveSubagentAllowed) return false;
		if (toolGovernanceFilter.value === 'custom-renderer' && !tool.rendererCapability?.custom) return false;
		if (!keyword) return true;
		return [tool.name, tool.label, tool.description, tool.toolset, tool.capability]
			.filter(Boolean)
			.join(' ')
			.toLowerCase()
			.includes(keyword);
	});
});

const groupedTools = computed(() => {
	const map = new Map<string, ToolViewItem[]>();
	for (const tool of filteredTools.value) {
		if (!map.has(tool.toolset)) map.set(tool.toolset, []);
		map.get(tool.toolset)!.push(tool);
	}
	return [...map.entries()].map(([toolset, tools]) => ({
		toolset,
		tools: tools.sort((a, b) => {
			if (a.statusMeta.enabled !== b.statusMeta.enabled) return a.statusMeta.enabled ? -1 : 1;
			if (a.isCore !== b.isCore) return b.isCore - a.isCore;
			return (a.label || a.name).localeCompare(b.label || b.name, 'zh-CN');
		}),
		enabledCount: tools.filter((tool) => tool.statusMeta.enabled).length
	}));
});

const enabledTools = computed(() =>
	toolViews.value
		.filter((tool) => tool.statusMeta.enabled)
		.sort((a, b) => {
			if (a.isCore !== b.isCore) return b.isCore - a.isCore;
			return (a.label || a.name).localeCompare(b.label || b.name, 'zh-CN');
		})
);
const enabledToolCount = computed(() => enabledTools.value.length);
const coreToolCount = computed(() => toolCatalog.value.filter((tool) => tool.isCore === 1).length);
const publishedAgentOptions = computed(() => agentOptions.value.filter((agent) => agent.status === 1 && agent.id !== props.agentId));
const subagentToolOptions = computed(() =>
	toolCatalog.value
		.filter((tool) => {
			if (SUBAGENT_BLOCKED_TOOL_NAMES.has(tool.name)) return false;
			if (tool.status === 0) return false;
			const diagnosticItem = agentToolDiagnosticItemMap.value.get(tool.name);
			return diagnosticItem
				? diagnosticItem.runtime?.subagentInProcess?.enabled === true
				: buildEffectiveSubagentAllowed(tool, perToolConfig.value[tool.name]);
		})
		.sort((a, b) => (a.label || a.name).localeCompare(b.label || b.name, 'zh-CN'))
);

const toolSettingsImpactNote = computed(() => {
	const tool = currentToolSettingsTarget.value;
	if (!tool) return '选择一个工具后查看局部配置会如何影响当前 Agent。';
	if (isFileOrShellTool(tool.name)) {
		return '文件和命令类工具会受到工作目录、Worker 策略、Shell/写权限和子代理治理共同约束。';
	}
	return '局部配置会覆盖当前 Agent 对该工具的启用状态、子代理权限和 Worker 路由。';
});

const toolSettingsImpactRows = computed(() => {
	const tool = currentToolSettingsTarget.value;
	if (!tool) return [];
	const diagnosticRow = toolSettingsDiagnostic.value?.items?.find((item: any) => item.name === tool.name);
	const routeMap = new Map(
		((toolSettingsDiagnostic.value as any)?.toolRuntimeRoutes || []).map((item: any) => [item.name, item])
	);
	const runtimeRoute = routeMap.get(tool.name);
	if (!diagnosticRow) {
		return [{
			key: 'diagnostic',
			label: '后端诊断',
			status: toolSettingsDiagnosticLoading.value ? '计算中' : '待刷新',
			type: 'info',
			reason: toolSettingsDiagnosticLoading.value ? '正在根据局部配置草稿计算影响。' : '打开或修改配置后会自动刷新。'
		}];
	}
	const enabledMode = toolSettingsForm.value.enabledMode;
	const allowInSubagentMode = toolSettingsForm.value.allowInSubagentMode;
	return [
		{
			key: 'agent',
			label: '当前 Agent',
			status: diagnosticRow.runtime?.supervisorInProcess?.enabled ? '可用' : '受限',
			type: diagnosticRow.runtime?.supervisorInProcess?.enabled ? 'success' : 'warning',
			reason: diagnosticRow.runtime?.supervisorInProcess?.blockedReason
				? blockedReasonLabel(diagnosticRow.runtime.supervisorInProcess.blockedReason)
				: enabledMode === 'inherit'
					? '沿用核心工具默认和工具管理配置。'
					: enabledMode === 'enabled'
						? '当前 Agent 草稿会启用该工具。'
						: '当前 Agent 草稿会关闭该工具。'
		},
		{
			key: 'subagent',
			label: '子代理使用',
			status: diagnosticRow.runtime?.subagentInProcess?.enabled ? '允许' : '禁止',
			type: diagnosticRow.runtime?.subagentInProcess?.enabled ? 'success' : 'warning',
			reason: diagnosticRow.runtime?.subagentInProcess?.blockedReason
				? blockedReasonLabel(diagnosticRow.runtime.subagentInProcess.blockedReason)
				: allowInSubagentMode === 'inherit'
					? '沿用工具治理和内置委派保护规则。'
					: allowInSubagentMode === 'allowed'
						? '当前 Agent 明确允许子代理使用该工具。'
						: '当前 Agent 明确禁止子代理使用该工具。'
		},
		{
			key: 'worker',
			label: 'Worker 路由',
			status: runtimeRouteDisplayLabel(runtimeRoute?.runtimeRoute),
			type: runtimeRoute?.runtimeRoute === 'worker-local' ? 'success' : runtimeRoute?.runtimeRoute === 'main-process-proxy' ? 'warning' : 'danger',
			reason: runtimeRoute?.blockedReason ? blockedReasonLabel(runtimeRoute.blockedReason) : '由后端 manifest、Agent 覆盖和 Worker 策略共同推导。'
		}
	] as Array<{ key: string; label: string; status: string; type: TagType; reason: string }>;
});

watch(
	() => form.value.auxiliaryModelChannelId,
	(id) => {
		const ch = auxiliaryChannels.value.find((c: any) => c.channelId === id);
		auxiliaryModels.value = ch?.models ?? [];
		if (form.value.auxiliaryModelId && !auxiliaryModels.value.find((m: any) => m.name === form.value.auxiliaryModelId)) {
			form.value.auxiliaryModelId = '';
		}
	}
);

watch(
	() => props.visible,
	async (val) => {
		if (!val) return;
		activeTab.value = 'info';
		await Promise.all([loadSkillMetas(), loadToolCatalog(), loadAuxiliaryChannels(), loadAgentOptions()]);
		if (props.agentId) {
			await loadAgent();
		} else {
			resetForm();
		}
		await refreshAgentToolDiagnostic();
	}
);

watch(
	() => [
		props.visible,
		form.value.tools.inheritCoreTools,
		JSON.stringify(form.value.tools.enabled || []),
		JSON.stringify(form.value.tools.disabled || []),
		JSON.stringify(form.value.tools.perTool || {}),
		agentConfig.value.session.cwd,
		agentConfig.value.session.file.rootDir
	],
	() => {
		if (!props.visible) return;
		void refreshAgentToolDiagnostic();
	}
);

watch(
	() => [
		toolSettingsVisible.value,
		toolSettingsForm.value.name,
		toolSettingsForm.value.enabledMode,
		toolSettingsForm.value.promptHint,
		toolSettingsForm.value.allowInSubagentMode,
		toolSettingsForm.value.workerRoutingStrategy,
		agentConfig.value.session.cwd,
		agentConfig.value.session.file.rootDir
	],
	() => {
		if (!toolSettingsVisible.value || !toolSettingsForm.value.name) return;
		void refreshToolSettingsDiagnostic();
	}
);

onMounted(() => {
	loadSkillMetas();
	loadToolCatalog();
	loadAuxiliaryChannels();
	loadAgentOptions();
});

function parseJson(val: any, fallback: any = null) {
	if (val == null) return fallback;
	if (typeof val === 'string') {
		try {
			return JSON.parse(val);
		} catch {
			return fallback;
		}
	}
	return val;
}

function generateAgentName(): string {
	const hex = Array.from(crypto.getRandomValues(new Uint8Array(4)))
		.map((b) => b.toString(16).padStart(2, '0'))
		.join('');
	return `agent_${hex}`;
}

function resetToolUiState() {
	toolSearch.value = '';
	toolStatusFilter.value = 'all';
	showCoreOnly.value = false;
	toolRuntimeFilter.value = '';
	toolGovernanceFilter.value = '';
}

function resetForm() {
	form.value = {
		name: generateAgentName(),
		label: '',
		description: '',
		icon: '',
		systemPrompt: '',
		skills: [],
		toolsets: null,
		tools: { inheritCoreTools: true, enabled: [], disabled: [], perTool: {} },
		compactionThreshold: 0,
		compactionKeepRecent: 4,
		auxiliaryModelChannelId: null,
		auxiliaryModelId: ''
	};
	modelConfig.value = { channelId: null, modelId: '', apiKey: '', apiUrl: '', contextWindow: null };
	agentConfig.value = {
		welcomeMessage: '',
		middleware: { toolRetryMaxRetries: 2, maxToolCalls: 20, modelRetryMaxRetries: 2 },
		session: { backend: 'file', cwd: '', restoreLastSession: true, file: { rootDir: '' } },
		memory: { enabled: false, backend: 'mysql', prefetchLimit: 5 }
	};
	subagentConfig.value = { ...DEFAULT_SUBAGENT_CONFIG };
	previewLayers.value = [];
	previewToolNames.value = [];
	previewDisabledReasons.value = [];
	resetToolUiState();
}

function toStringArray(value: unknown): string[] {
	if (!Array.isArray(value)) return [];
	return Array.from(new Set(value.filter((name): name is string => typeof name === 'string' && !!name)));
}

function toPositiveIntArray(value: unknown): number[] {
	if (!Array.isArray(value)) return [];
	return Array.from(new Set(value.map((id) => Number(id)).filter((id): id is number => Number.isInteger(id) && id > 0)));
}

function normalizeToolConfig(raw: any): AgentToolConfig {
	return {
		inheritCoreTools: raw?.inheritCoreTools !== false,
		enabled: toStringArray(raw?.enabled),
		disabled: toStringArray(raw?.disabled),
		perTool: normalizePerToolConfig(raw?.perTool)
	};
}

function normalizePerToolConfig(value: unknown): NonNullable<AgentToolConfig['perTool']> {
	if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
	return Object.fromEntries(
		Object.entries(value as Record<string, any>).map(([name, config]) => {
			if (!config || typeof config !== 'object' || Array.isArray(config)) return [name, {}];
			return [
				name,
				{
					enabled: typeof config.enabled === 'boolean' ? config.enabled : undefined,
					promptHint: typeof config.promptHint === 'string' ? config.promptHint : '',
					allowInSubagent: typeof config.allowInSubagent === 'boolean' ? config.allowInSubagent : undefined,
					workerRoutingStrategy: ['auto', 'force-local', 'force-main-process-proxy', 'force-disabled'].includes(config.workerRoutingStrategy)
						? config.workerRoutingStrategy
						: 'auto'
				}
			];
		})
	);
}

function normalizeSubagentConfig(raw: any): Required<AgentSubagentConfig> {
	const parsed = parseJson(raw, {});
	const maxConcurrent = Number(parsed?.maxConcurrent);
	return {
		enabled: parsed?.enabled !== false,
		maxConcurrent: Number.isFinite(maxConcurrent) ? Math.min(10, Math.max(1, Math.floor(maxConcurrent))) : 3,
		allowedPresetAgentIds: toPositiveIntArray(parsed?.allowedPresetAgentIds),
		allowedToolNames: toStringArray(parsed?.allowedToolNames)
	};
}

function deriveToolConfigFromLegacy(toolsets: string[] | null, rawTools: any): AgentToolConfig {
	const legacyToolsets = Array.isArray(toolsets) ? toolsets.filter((name): name is string => typeof name === 'string' && !!name) : LEGACY_DEFAULT_TOOLSETS;
	const enabled = toolCatalog.value.filter((tool) => tool.isCore !== 1 && legacyToolsets.includes(tool.toolset)).map((tool) => tool.name);
	return {
		inheritCoreTools: true,
		enabled,
		disabled: toStringArray(rawTools?.disabled),
		perTool: normalizePerToolConfig(rawTools?.perTool)
	};
}

function clearModelConfig() {
	modelConfig.value = { channelId: null, modelId: '', apiKey: '', apiUrl: '', contextWindow: null };
}

async function loadSkillMetas() {
	try {
		const res = await service.request({ url: '/admin/netaclaw/skill/metas' });
		skillMetas.value = (res || []).filter((s: any) => s.status === 1);
	} catch {
		skillMetas.value = [];
	}
}

async function loadToolCatalog() {
	try {
		const res = await service.request({ url: '/admin/netaclaw/tool/forAgent' });
		toolCatalog.value = Array.isArray(res?.tools) ? res.tools : [];
	} catch {
		toolCatalog.value = [];
	}
}

async function loadAuxiliaryChannels() {
	try {
		const res = await service.request({ url: '/admin/netaclaw/model_channel/allModels' });
		auxiliaryChannels.value = Array.isArray(res) ? res : [];
	} catch {
		auxiliaryChannels.value = [];
	}
}

async function loadAgentOptions() {
	try {
		const res = await service.request({ url: '/admin/netaclaw/agent/options', method: 'POST' });
		agentOptions.value = Array.isArray(res) ? res : [];
	} catch {
		agentOptions.value = [];
	}
}

async function loadAgent() {
	try {
		const agent = await service.netaclaw.agent.info({ id: props.agentId });
		if (!agent) return;
		const skills = parseJson(agent.skills, []);
		const toolsets = parseJson(agent.toolsets, null);
		const tools = parseJson(agent.tools, null);
		const useNewShape = typeof tools?.inheritCoreTools === 'boolean' || Array.isArray(tools?.enabled);
		const normalizedTools = useNewShape ? normalizeToolConfig(tools) : deriveToolConfigFromLegacy(toolsets, tools);
		form.value = {
			name: agent.name || '',
			label: agent.label || '',
			description: agent.description || '',
			icon: agent.icon || '',
			systemPrompt: agent.systemPrompt || '',
			skills: Array.isArray(skills) ? skills : [],
			toolsets: Array.isArray(toolsets) ? toolsets : null,
			tools: normalizedTools,
			compactionThreshold: agent.compactionThreshold ?? 0,
			compactionKeepRecent: agent.compactionKeepRecent ?? 4,
			auxiliaryModelChannelId: agent.auxiliaryModelChannelId ?? null,
			auxiliaryModelId: agent.auxiliaryModelId ?? ''
		};
		const mc = parseJson(agent.modelConfig, {});
		modelConfig.value = {
			channelId: mc.channelId || null,
			modelId: mc.modelId || '',
			apiKey: mc.apiKey || '',
			apiUrl: mc.apiUrl || '',
			contextWindow: mc.contextWindow || null
		};
		const cfg = parseJson(agent.config, {});
		const mw = cfg.middleware || {};
		const session = cfg.session || {};
		const mem = cfg.memory || {};
		agentConfig.value = {
			welcomeMessage: cfg.welcomeMessage || '',
			middleware: {
				toolRetryMaxRetries: mw.toolRetryMaxRetries ?? 2,
				maxToolCalls: mw.maxToolCalls ?? 20,
				modelRetryMaxRetries: mw.modelRetryMaxRetries ?? 2
			},
			session: {
				backend: session.backend === 'mysql' ? 'mysql' : 'file',
				cwd: session.cwd || '',
				restoreLastSession: session.restoreLastSession !== false,
				file: { rootDir: session.file?.rootDir || '' }
			},
			memory: {
				enabled: !!mem.enabled,
				backend: mem.backend || 'mysql',
				prefetchLimit: mem.prefetchLimit ?? 5
			}
		};
		subagentConfig.value = normalizeSubagentConfig(agent.subagentConfig);
		resetToolUiState();
	} catch {
		ElMessage.error('加载 Agent 详情失败');
	}
}

function buildPersistedToolConfig(): AgentToolConfig {
	const perTool = Object.fromEntries(
		Object.entries(form.value.tools.perTool || {})
			.map(([name, config]) => [
				name,
				{
					enabled: typeof config?.enabled === 'boolean' ? config.enabled : undefined,
					promptHint: typeof config?.promptHint === 'string' ? config.promptHint.trim() : '',
					allowInSubagent: typeof config?.allowInSubagent === 'boolean' ? config.allowInSubagent : undefined,
					workerRoutingStrategy: config?.workerRoutingStrategy || 'auto'
				}
			])
			.filter(([, config]) => typeof config.enabled === 'boolean' || !!config.promptHint || typeof config.allowInSubagent === 'boolean' || config.workerRoutingStrategy !== 'auto')
	);
	return {
		inheritCoreTools: form.value.tools.inheritCoreTools !== false,
		enabled: [...new Set(form.value.tools.enabled || [])],
		disabled: [...new Set(form.value.tools.disabled || [])],
		perTool
	};
}

function buildPersistedSubagentConfig(): Required<AgentSubagentConfig> {
	const normalized = normalizeSubagentConfig(subagentConfig.value);
	return {
		...normalized,
		allowedPresetAgentIds: normalized.allowedPresetAgentIds.filter((id) => id !== props.agentId),
		allowedToolNames: normalized.allowedToolNames.filter((name) => !SUBAGENT_BLOCKED_TOOL_NAMES.has(name))
	};
}

async function handleSave() {
	if (formRef.value) {
		try {
			await formRef.value.validate();
		} catch {
			activeTab.value = 'info';
			return;
		}
	}
	saving.value = true;
	try {
		const mc = modelConfig.value.channelId || modelConfig.value.modelId || modelConfig.value.contextWindow ? modelConfig.value : null;
		const body: any = {
			name: form.value.name,
			label: form.value.label,
			description: form.value.description,
			icon: form.value.icon,
			systemPrompt: form.value.systemPrompt,
			skills: form.value.skills,
			toolsets: form.value.toolsets ?? null,
			tools: buildPersistedToolConfig(),
			subagentConfig: buildPersistedSubagentConfig(),
			modelConfig: mc,
			config: agentConfig.value,
			compactionThreshold: form.value.compactionThreshold,
			compactionKeepRecent: form.value.compactionKeepRecent,
			auxiliaryModelChannelId: form.value.auxiliaryModelChannelId,
			auxiliaryModelId: form.value.auxiliaryModelId
		};
		if (props.agentId) {
			body.id = props.agentId;
			await service.netaclaw.agent.update(body);
		} else {
			await service.netaclaw.agent.add(body);
		}
		ElMessage.success('保存成功');
		emit('saved');
		emit('update:visible', false);
	} catch {
		ElMessage.error('保存失败');
	} finally {
		saving.value = false;
	}
}

function addSkill(name: string) {
	if (!form.value.skills.includes(name)) {
		form.value.skills.push(name);
		const classification = getSkillClassification(name);
		if (classification === 'compute-entry') {
			ElMessage.warning(`"${name}" 是 compute-entry 类型，请确保该 Agent 已启用 execute_skill 工具`);
		} else if (classification === 'compute-toolkit') {
			ElMessage.warning(`"${name}" 是 compute-toolkit 类型，请确保该 Agent 已启用 bash 工具`);
		}
	}
}

function getSkillClassification(name: string): string {
	const meta = skillMetas.value?.find((s: any) => s.name === name);
	return meta?.classification || 'prompt';
}

function removeSkill(name: string) {
	form.value.skills = form.value.skills.filter((n) => n !== name);
}

function getSkillLabel(name: string) {
	const meta = skillMetas.value.find((s) => s.name === name);
	return meta ? `${meta.label || meta.name}` : name;
}

function ensureToolArrays() {
	if (!Array.isArray(form.value.tools.enabled)) form.value.tools.enabled = [];
	if (!Array.isArray(form.value.tools.disabled)) form.value.tools.disabled = [];
}

function toggleTool(tool: ToolCatalogItem, checked: string | number | boolean) {
	if (tool.status === 0) return;
	ensureToolArrays();
	const enabledSet = new Set(form.value.tools.enabled);
	const disabledSet = new Set(form.value.tools.disabled);
	if (checked === true) {
		disabledSet.delete(tool.name);
		if (tool.isCore === 1) enabledSet.delete(tool.name);
		else enabledSet.add(tool.name);
	} else {
		enabledSet.delete(tool.name);
		disabledSet.add(tool.name);
	}
	form.value.tools.enabled = [...enabledSet];
	form.value.tools.disabled = [...disabledSet];
}

function resetToolOverrides() {
	form.value.tools = { inheritCoreTools: true, enabled: [], disabled: [], perTool: {} };
	toolRuntimeFilter.value = '';
	toolGovernanceFilter.value = '';
}

function clearEnabledOverrides() {
	form.value.tools.enabled = [];
}

function clearDisabledOverrides() {
	form.value.tools.disabled = [];
}

function ensurePerToolConfig() {
	if (!form.value.tools.perTool || typeof form.value.tools.perTool !== 'object') form.value.tools.perTool = {};
}

function openToolSettings(tool: ToolViewItem) {
	const config = perToolConfig.value[tool.name] || {};
	toolSettingsForm.value = {
		name: tool.name,
		label: tool.label || tool.name,
		enabledMode: config.enabled === true ? 'enabled' : config.enabled === false ? 'disabled' : 'inherit',
		promptHint: config.promptHint || '',
		allowInSubagentMode: config.allowInSubagent === true ? 'allowed' : config.allowInSubagent === false ? 'blocked' : 'inherit',
		workerRoutingStrategy: config.workerRoutingStrategy || 'auto'
	};
	toolSettingsDiagnostic.value = null;
	toolSettingsVisible.value = true;
	void refreshToolSettingsDiagnostic();
}

async function refreshToolSettingsDiagnostic() {
	const tool = currentToolSettingsTarget.value;
	if (!toolSettingsVisible.value || !tool) return;
	const token = ++toolSettingsDiagnosticToken;
	toolSettingsDiagnosticLoading.value = true;
	try {
		const enabledMode = toolSettingsForm.value.enabledMode;
		const allowInSubagentMode = toolSettingsForm.value.allowInSubagentMode;
		const res = await service.request({
			url: '/admin/netaclaw/tool/runtimeDiagnostic',
			method: 'POST',
			data: {
				agentId: props.agentId || undefined,
				capability: 'text',
				sessionCwd: agentConfig.value.session.cwd || undefined,
				workspaceRoots: agentConfig.value.session.file.rootDir ? [agentConfig.value.session.file.rootDir] : [],
				allowShell: false,
				readonly: true,
				draftAgentTools: buildPersistedToolConfig(),
				draftToolOverride: {
					name: tool.name,
					status: tool.status,
					promptHint: toolSettingsForm.value.promptHint || null,
					enabled: enabledMode === 'enabled' ? true : enabledMode === 'disabled' ? false : undefined,
					allowInSubagent: allowInSubagentMode === 'allowed' ? true : allowInSubagentMode === 'blocked' ? false : undefined,
					workerRoutingStrategy: toolSettingsForm.value.workerRoutingStrategy || 'auto'
				}
			}
		});
		if (token === toolSettingsDiagnosticToken) {
			toolSettingsDiagnostic.value = res || null;
		}
	} catch {
		if (token === toolSettingsDiagnosticToken) {
			toolSettingsDiagnostic.value = null;
		}
	} finally {
		if (token === toolSettingsDiagnosticToken) {
			toolSettingsDiagnosticLoading.value = false;
		}
	}
}

async function refreshAgentToolDiagnostic() {
	if (!props.visible) return;
	const token = ++agentToolDiagnosticToken;
	agentToolDiagnosticLoading.value = true;
	try {
		const res = await service.request({
			url: '/admin/netaclaw/tool/runtimeDiagnostic',
			method: 'POST',
			data: {
				agentId: props.agentId || undefined,
				capability: 'text',
				sessionCwd: agentConfig.value.session.cwd || undefined,
				workspaceRoots: agentConfig.value.session.file.rootDir ? [agentConfig.value.session.file.rootDir] : [],
				allowShell: false,
				readonly: true,
				draftAgentTools: buildPersistedToolConfig()
			}
		});
		if (token === agentToolDiagnosticToken) {
			agentToolDiagnostic.value = res || null;
		}
	} catch {
		if (token === agentToolDiagnosticToken) {
			agentToolDiagnostic.value = null;
		}
	} finally {
		if (token === agentToolDiagnosticToken) {
			agentToolDiagnosticLoading.value = false;
		}
	}
}

function applyToolSettings() {
	ensurePerToolConfig();
	const name = toolSettingsForm.value.name;
	form.value.tools.perTool![name] = {
		enabled: toolSettingsForm.value.enabledMode === 'inherit' ? undefined : toolSettingsForm.value.enabledMode === 'enabled',
		promptHint: toolSettingsForm.value.promptHint,
		allowInSubagent: toolSettingsForm.value.allowInSubagentMode === 'inherit' ? undefined : toolSettingsForm.value.allowInSubagentMode === 'allowed',
		workerRoutingStrategy: toolSettingsForm.value.workerRoutingStrategy
	};
	toolSettingsVisible.value = false;
}

function clearToolSettings() {
	ensurePerToolConfig();
	delete form.value.tools.perTool![toolSettingsForm.value.name];
	toolSettingsVisible.value = false;
}

function buildEffectiveRuntimeProfile(tool: ToolCatalogItem, perTool: PerToolConfig | undefined) {
	let workerRoutingHint: WorkerRoutingHint = tool.runtimeProfile?.workerRoutingHint || 'disabled';
	if (perTool?.workerRoutingStrategy === 'force-local') workerRoutingHint = 'local';
	if (perTool?.workerRoutingStrategy === 'force-main-process-proxy') workerRoutingHint = 'main-process-proxy';
	if (perTool?.workerRoutingStrategy === 'force-disabled') workerRoutingHint = 'disabled';
	return {
		kind: tool.runtimeProfile?.kind || 'custom',
		executionMode: tool.runtimeProfile?.executionMode || 'parallel',
		supportedInWorker: workerRoutingHint === 'local',
		workerRoutingHint,
		requiresShell: !!tool.runtimeProfile?.requiresShell,
		requiresWrite: !!tool.runtimeProfile?.requiresWrite,
		requiresSkillScope: !!tool.runtimeProfile?.requiresSkillScope
	};
}

function buildEffectiveSubagentAllowed(tool: ToolCatalogItem, perTool: PerToolConfig | undefined) {
	if (SUBAGENT_BLOCKED_TOOL_NAMES.has(tool.name)) return false;
	if (perTool?.allowInSubagent === false) return false;
	if (perTool?.allowInSubagent === true) return true;
	return tool.governancePolicy?.allowInSubagent !== false;
}

function normalizeRuntimeRoute(value?: WorkerRoutingHint): RuntimeRoute {
	if (value === 'local') return 'worker-local';
	if (value === 'main-process-proxy') return 'main-process-proxy';
	return 'disabled';
}

function normalizedRuntimeRouteLabel(value?: WorkerRoutingHint) {
	return runtimeRouteDisplayLabel(normalizeRuntimeRoute(value));
}

function runtimeRouteDisplayLabel(value?: RuntimeRoute) {
	if (value === 'worker-local') return 'Worker 本地';
	if (value === 'main-process-proxy') return '主进程代理';
	return 'Worker 禁用';
}

function blockedReasonLabel(value?: string | null) {
	return toolBlockedReasonLabel(value) || value || '';
}

function runtimeRouteTagType(value?: WorkerRoutingHint): TagType {
	if (value === 'local') return 'success';
	if (value === 'main-process-proxy') return 'warning';
	return 'info';
}

function skillTagType(type: string): TagType {
	if (type === 'compute') return 'success';
	if (type === 'multimodal') return 'warning';
	return 'primary';
}

function skillTagLabel(type: string) {
	if (type === 'compute') return '计算';
	if (type === 'multimodal') return '多模态';
	return 'LLM';
}

function toolCapabilitySummary(tool: ToolCatalogItem) {
	const map: Record<string, string> = {
		read_file: '读取文件内容，支持按 offset 分段读取。',
		write_file: '写入或覆盖文件内容，需要写权限。',
		list_dir: '列出目录内容，用于探索工作区。',
		find_files: '按 glob 模式查找文件。',
		grep: '按文本或正则搜索文件内容。',
		bash: '执行 Shell 命令，受到 cwd 和权限策略约束。'
	};
	return map[tool.name] || '';
}

function toolManifestSummary(tool: ToolViewItem) {
	const parts = [
		normalizedRuntimeRouteLabel(tool.effectiveRuntimeProfile.workerRoutingHint),
		tool.effectiveRuntimeProfile.executionMode === 'sequential' ? '串行' : '可并行'
	];
	if (tool.effectiveRuntimeProfile.requiresShell) parts.push('需要 Shell');
	if (tool.effectiveRuntimeProfile.requiresWrite) parts.push('需要写权限');
	if (tool.effectiveRuntimeProfile.requiresSkillScope) parts.push('需要 Skill 作用域');
	return parts.join(' / ');
}

function workerRoutingOverrideMeta(strategy: NonNullable<PerToolConfig['workerRoutingStrategy']>) {
	const map = {
		'force-local': { label: '当前 Agent 强制 Worker 本地', type: 'success' as TagType, summary: '强制 Worker 本地' },
		'force-main-process-proxy': { label: '当前 Agent 强制主进程代理', type: 'warning' as TagType, summary: '强制主进程代理' },
		'force-disabled': { label: '当前 Agent 禁用 Worker', type: 'danger' as TagType, summary: '禁用 Worker' },
		auto: { label: '跟随 Worker 策略', type: 'info' as TagType, summary: '自动 Worker 路由' }
	};
	return map[strategy];
}

function workerRoutingReason(strategy: string) {
	if (strategy === 'force-local') return '强制在 Worker 本地执行，适合支持 Worker 的纯计算工具。';
	if (strategy === 'force-main-process-proxy') return '强制通过主进程代理执行，适合需要宿主权限的工具。';
	if (strategy === 'force-disabled') return '禁止 Worker 路由，仅在主流程中按策略处理。';
	return '跟随工具 manifest 和全局 Worker 策略自动推导。';
}

function isFileOrShellTool(name: string) {
	return ['read_file', 'write_file', 'list_dir', 'find_files', 'grep', 'bash'].includes(name);
}

function copyApiExample() {
	navigator.clipboard.writeText(apiExample.value).then(() => {
		ElMessage.success('已复制');
	});
}

async function loadPreview() {
	previewLoading.value = true;
	try {
		const res = await service.request({
			url: '/admin/netaclaw/agent/previewPrompt',
			method: 'POST',
			data: {
				id: props.agentId,
				name: form.value.name,
				label: form.value.label,
				description: form.value.description,
				systemPrompt: form.value.systemPrompt,
				skills: form.value.skills,
				toolsets: form.value.toolsets,
				tools: buildPersistedToolConfig(),
				subagentConfig: buildPersistedSubagentConfig(),
				config: agentConfig.value,
				modelConfig: {
					channelId: modelConfig.value.channelId,
					modelId: modelConfig.value.modelId
				}
			}
		});
		previewLayers.value = res?.layers || [];
		previewToolNames.value = res?.toolNames || [];
		previewDisabledReasons.value = res?.disabledReasons || [];
	} catch {
		previewLayers.value = [];
		previewToolNames.value = [];
		previewDisabledReasons.value = [];
		ElMessage.error('加载预览失败');
	} finally {
		previewLoading.value = false;
	}
}
</script>

<style lang="scss" scoped>
.agent-edit-tabs {
	display: flex;
	flex-direction: column;
	height: 100%;
	max-height: calc(100vh - 160px);
	min-height: 0;
}

.agent-edit-drawer {
	:deep(.el-drawer__body) {
		overflow-y: auto;
	}
}

.agent-edit-tabs :deep(.el-tabs__content) {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	padding-right: 4px;
}

.agent-edit-tabs :deep(.el-tab-pane) {
	padding-bottom: 20px;
}

.tab-desc {
	font-size: 13px;
	color: var(--el-text-color-secondary);
	margin: 0 0 14px 0;
	padding: 10px 12px;
	background: linear-gradient(135deg, var(--el-color-primary-light-9), var(--el-fill-color-light));
	border-radius: 10px;
	border-left: 3px solid var(--el-color-primary);
	line-height: 1.6;
}

.dual-col {
	display: flex;
	gap: 12px;
	height: 380px;
}

.col-panel {
	flex: 1;
	display: flex;
	flex-direction: column;
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 8px;
	overflow: hidden;
}

.col-header,
.section-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 10px 12px;
	background: var(--el-fill-color-light);
	border-bottom: 1px solid var(--el-border-color-lighter);
	flex-shrink: 0;
}

.col-title,
.section-title {
	font-size: 13px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}

.section-subtitle,
.group-subtitle,
.summary-sub,
.summary-note {
	font-size: 12px;
	color: var(--el-text-color-secondary);
	line-height: 1.5;
}

.col-body {
	flex: 1;
	overflow-y: auto;
	padding: 8px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.item {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px;
	border-radius: 6px;
	border: 1px solid var(--el-border-color-lighter);
	font-size: 13px;

	&--available {
		background: var(--el-bg-color);
		cursor: pointer;
	}

	&--selected {
		background: var(--el-color-success-light-9);
		border-color: var(--el-color-success-light-7);
		justify-content: space-between;
	}
}

.item-main {
	font-weight: 500;
}

.form-tip {
	margin-left: 10px;
	font-size: 12px;
	color: var(--el-text-color-placeholder);
}

.field-hint {
	margin-top: 6px;
	font-size: 12px;
	line-height: 1.6;
	color: var(--el-text-color-secondary);
}

.option-meta {
	float: right;
	margin-left: 16px;
	font-size: 12px;
	color: var(--el-text-color-placeholder);
}

.subagent-form {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.subagent-hero {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	padding: 18px;
	margin-bottom: 18px;
	border: 1px solid rgba(64, 158, 255, 0.22);
	border-radius: 16px;
	background:
		radial-gradient(circle at top right, rgba(64, 158, 255, 0.16), transparent 40%),
		linear-gradient(135deg, var(--el-bg-color), var(--el-fill-color-light));
}

.subagent-hero__title {
	font-size: 16px;
	font-weight: 700;
	color: var(--el-text-color-primary);
	margin-bottom: 6px;
}

.subagent-hero__desc {
	font-size: 13px;
	line-height: 1.7;
	color: var(--el-text-color-regular);
}

.tools-layout {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.tools-summary {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 12px;
}

.summary-card {
	padding: 16px;
	border-radius: 14px;
	border: 1px solid var(--el-border-color-lighter);
	background:
		radial-gradient(circle at top right, rgba(64, 158, 255, 0.14), transparent 45%),
		var(--el-bg-color);
}

.summary-card--hint {
	background:
		radial-gradient(circle at top right, rgba(230, 162, 60, 0.14), transparent 45%),
		var(--el-bg-color);
}

.summary-label {
	font-size: 12px;
	color: var(--el-text-color-secondary);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.summary-value {
	font-size: 28px;
	font-weight: 700;
	color: var(--el-text-color-primary);
	margin: 8px 0 6px;
}

.tools-toolbar {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) auto auto auto auto auto auto auto;
	gap: 10px;
	align-items: center;
}

.enabled-strip,
.group-card {
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 12px;
	background: var(--el-bg-color);
	overflow: hidden;
}

.enabled-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	padding: 12px;
}

.enabled-chip {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px;
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 999px;
	background: var(--el-fill-color-light);
	font-size: 12px;
}

.tool-groups {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding-bottom: 8px;
}

.group-head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 12px 14px;
	background: linear-gradient(135deg, var(--el-fill-color-light), var(--el-bg-color-page));
	border-bottom: 1px solid var(--el-border-color-lighter);
}

.group-title {
	font-size: 14px;
	font-weight: 700;
	color: var(--el-text-color-primary);
	text-transform: capitalize;
}

.tool-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: 12px;
	padding: 14px;
}

.tool-card {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 14px;
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 12px;
	background: var(--el-bg-color-page);
	transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;

	&:hover {
		transform: translateY(-1px);
		box-shadow: 0 10px 22px rgba(0, 0, 0, 0.04);
	}

	&--default_enabled {
		border-color: rgba(103, 194, 58, 0.32);
	}

	&--enabled_for_agent {
		border-color: rgba(64, 158, 255, 0.32);
	}

	&--disabled_for_agent {
		border-color: rgba(230, 162, 60, 0.32);
	}

	&--globally_disabled {
		border-color: rgba(245, 108, 108, 0.32);
		background: linear-gradient(180deg, rgba(245, 108, 108, 0.06), var(--el-bg-color-page));
	}

	&--disabled {
		opacity: 0.8;
	}
}

.tool-card__top,
.tool-card__footer {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.tool-card__title {
	display: flex;
	flex-direction: column;
	gap: 8px;
	min-width: 0;
}

.tool-name {
	font-size: 14px;
	font-weight: 700;
	color: var(--el-text-color-primary);
	word-break: break-word;
}

.tool-tags,
.tool-card__override-tags,
.tool-card__policy-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.tool-card__desc {
	font-size: 12px;
	line-height: 1.7;
	color: var(--el-text-color-regular);
	min-height: 40px;
}

.tool-card__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	font-size: 12px;
	line-height: 1.6;
	color: var(--el-text-color-secondary);
}

.tool-card__runtime-summary,
.tool-card__override,
.tool-card__policy {
	font-size: 12px;
	line-height: 1.7;
	padding: 10px 12px;
	border-radius: 10px;
	background: var(--el-fill-color-light);
	border: 1px solid var(--el-border-color-lighter);
}

.tool-card__capability {
	font-size: 12px;
	line-height: 1.7;
	color: var(--el-color-primary);
	padding: 10px 12px;
	border-radius: 10px;
	background: var(--el-color-primary-light-9);
	border: 1px solid var(--el-color-primary-light-7);
}

.tool-card__override,
.tool-card__policy {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.tool-card__policy-title {
	font-size: 12px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}

.tool-card__override-summary,
.tool-card__policy-summary,
.tool-card__hint {
	font-size: 12px;
	line-height: 1.6;
	color: var(--el-text-color-secondary);
}

.tool-card__actions {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 4px;
}

.runtime-impact-preview {
	display: flex;
	flex-direction: column;
	gap: 10px;
	width: 100%;
	padding: 12px;
	border-radius: 12px;
	background: var(--el-fill-color-light);
	border: 1px solid var(--el-border-color-lighter);
}

.runtime-impact-preview__note {
	font-size: 12px;
	line-height: 1.7;
	color: var(--el-text-color-secondary);
}

.runtime-impact-preview__row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
	padding: 10px 12px;
	border-radius: 10px;
	background: var(--el-bg-color);
	border: 1px solid var(--el-border-color-lighter);
}

.runtime-impact-preview__title {
	font-size: 13px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}

.runtime-impact-preview__reason {
	margin-top: 4px;
	font-size: 12px;
	line-height: 1.6;
	color: var(--el-text-color-secondary);
}

.prompt-preview {
	max-height: 500px;
	overflow-y: auto;
}

.layer-block {
	margin-bottom: 12px;
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 4px;
}

.layer-label {
	padding: 6px 12px;
	background: var(--el-fill-color-light);
	font-weight: 600;
	font-size: 13px;
	border-bottom: 1px solid var(--el-border-color-lighter);
}

.layer-content {
	padding: 12px;
	margin: 0;
	white-space: pre-wrap;
	word-break: break-word;
	font-size: 12px;
	line-height: 1.6;
	max-height: 300px;
	overflow-y: auto;
}

.preview-meta {
	margin-top: 12px;
	padding: 10px 12px;
	border: 1px solid var(--el-border-color-lighter);
	border-radius: 8px;
}

.preview-title {
	font-size: 12px;
	font-weight: 600;
	margin-bottom: 8px;
}

.preview-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.preview-reason {
	font-size: 12px;
	line-height: 1.6;
	color: var(--el-text-color-secondary);
}

.api-preview {
	h4 {
		margin: 0 0 8px 0;
		font-size: 14px;
		font-weight: 600;
		color: var(--el-text-color-primary);
	}

	code {
		display: inline-block;
		padding: 5px 12px;
		background: var(--el-color-primary-light-9);
		border: 1px solid var(--el-color-primary-light-7);
		border-radius: 6px;
		color: var(--el-color-primary);
		font-size: 13px;
		font-family: 'SF Mono', 'Fira Code', monospace;
	}
}

.api-code {
	background: var(--el-fill-color-light);
	border: 1px solid var(--el-border-color-lighter);
	padding: 14px;
	border-radius: 8px;
	font-size: 12px;
	line-height: 1.6;
	overflow-x: auto;
	margin: 8px 0;
	font-family: 'SF Mono', 'Fira Code', monospace;
}

@media (max-width: 960px) {
	.tools-summary,
	.tools-toolbar {
		grid-template-columns: 1fr;
	}

	.tool-grid,
	.dual-col {
		grid-template-columns: 1fr;
	}

	.dual-col {
		display: flex;
		flex-direction: column;
		height: auto;
	}
}
</style>
