import 'package:flutter/material.dart'; import '../i18n/app_language.dart'; enum WorkspaceDestination { assistant, tasks, skills, nodes, agents, mcpServer, clawHub, secrets, aiGateway, settings, account, } extension WorkspaceDestinationCopy on WorkspaceDestination { String get label => switch (this) { WorkspaceDestination.assistant => appText('助手', 'Assistant'), WorkspaceDestination.tasks => appText('任务', 'Tasks'), WorkspaceDestination.skills => appText('技能', 'Skills'), WorkspaceDestination.nodes => appText('节点', 'Nodes'), WorkspaceDestination.agents => appText('代理', 'Agents'), WorkspaceDestination.mcpServer => 'MCP Hub', WorkspaceDestination.clawHub => 'ClawHub', WorkspaceDestination.secrets => appText('密钥', 'Secrets'), WorkspaceDestination.aiGateway => 'LLM API', WorkspaceDestination.settings => appText('设置', 'Settings'), WorkspaceDestination.account => appText('账号', 'Account'), }; IconData get icon => switch (this) { WorkspaceDestination.assistant => Icons.chat_bubble_outline_rounded, WorkspaceDestination.tasks => Icons.layers_rounded, WorkspaceDestination.skills => Icons.auto_awesome_rounded, WorkspaceDestination.nodes => Icons.developer_board_rounded, WorkspaceDestination.agents => Icons.hub_rounded, WorkspaceDestination.mcpServer => Icons.dns_rounded, WorkspaceDestination.clawHub => Icons.extension_rounded, WorkspaceDestination.secrets => Icons.key_rounded, WorkspaceDestination.aiGateway => Icons.smart_toy_rounded, WorkspaceDestination.settings => Icons.tune_rounded, WorkspaceDestination.account => Icons.account_circle_rounded, }; String get description => switch (this) { WorkspaceDestination.assistant => appText( 'AI 主入口,优先承接自然输入和高频工作发起。', 'Primary AI entry point for natural input and frequent task starts.', ), WorkspaceDestination.tasks => appText( '任务队列、运行态、失败项和调度历史的统一视图。', 'Unified view for queue, running, failed, and history.', ), WorkspaceDestination.skills => appText( '管理技能包与能力扩展,浏览和安装 ClawHub 技能。', 'Manage skill packages and extensions, browse and install from ClawHub.', ), WorkspaceDestination.nodes => appText( '管理边缘节点与实例,监控运行状态与负载。', 'Manage edge nodes and instances, monitor status and load.', ), WorkspaceDestination.agents => appText( '管理代理实例,配置行为与能力。', 'Manage agent instances, configure behaviors and capabilities.', ), WorkspaceDestination.mcpServer => appText( '管理 MCP Hub 连接与工具配置。', 'Manage MCP Hub connections and tool configurations.', ), WorkspaceDestination.clawHub => appText( '浏览和安装技能包、代理模板与连接器。', 'Browse and install skill packages, agent templates and connectors.', ), WorkspaceDestination.secrets => appText( '密钥与 Vault 配置统一收口到设置中心。', 'Secrets and Vault configuration now live in the Settings center.', ), WorkspaceDestination.aiGateway => appText( 'LLM API 配置统一收口到设置中心。', 'LLM API configuration now lives in the Settings center.', ), WorkspaceDestination.settings => appText( '全局配置中心,只负责系统设置与诊断,不承担业务模块入口。', 'Global settings and diagnostics, separated from business modules.', ), WorkspaceDestination.account => appText( '用户身份、工作区切换与登录会话管理。', 'Identity, workspace switching, and session management.', ), }; static WorkspaceDestination? fromJsonValue(String? value) { if (value == null || value.trim().isEmpty) { return null; } for (final item in WorkspaceDestination.values) { if (item.name == value.trim()) { return item; } } return null; } } enum AssistantFocusEntry { tasks, skills, nodes, agents, mcpServer, clawHub, secrets, aiGateway, settings, language, theme, } extension AssistantFocusEntryCopy on AssistantFocusEntry { String get label => switch (this) { AssistantFocusEntry.tasks => appText('任务', 'Tasks'), AssistantFocusEntry.skills => appText('技能', 'Skills'), AssistantFocusEntry.nodes => appText('节点', 'Nodes'), AssistantFocusEntry.agents => appText('代理', 'Agents'), AssistantFocusEntry.mcpServer => 'MCP Hub', AssistantFocusEntry.clawHub => 'ClawHub', AssistantFocusEntry.secrets => appText('密钥', 'Secrets'), AssistantFocusEntry.aiGateway => 'LLM API', AssistantFocusEntry.settings => appText('设置', 'Settings'), AssistantFocusEntry.language => appText('语言', 'Language'), AssistantFocusEntry.theme => appText('主题/亮度', 'Theme / Brightness'), }; IconData get icon => switch (this) { AssistantFocusEntry.tasks => Icons.layers_rounded, AssistantFocusEntry.skills => Icons.auto_awesome_rounded, AssistantFocusEntry.nodes => Icons.developer_board_rounded, AssistantFocusEntry.agents => Icons.hub_rounded, AssistantFocusEntry.mcpServer => Icons.dns_rounded, AssistantFocusEntry.clawHub => Icons.extension_rounded, AssistantFocusEntry.secrets => Icons.key_rounded, AssistantFocusEntry.aiGateway => Icons.smart_toy_rounded, AssistantFocusEntry.settings => Icons.tune_rounded, AssistantFocusEntry.language => Icons.translate_rounded, AssistantFocusEntry.theme => Icons.brightness_6_rounded, }; String get description => switch (this) { AssistantFocusEntry.tasks => appText( '任务队列、运行态、失败项和调度历史的统一视图。', 'Unified view for queue, running, failed, and history.', ), AssistantFocusEntry.skills => appText( '管理技能包与能力扩展,浏览和安装 ClawHub 技能。', 'Manage skill packages and extensions, browse and install from ClawHub.', ), AssistantFocusEntry.nodes => appText( '管理边缘节点与实例,监控运行状态与负载。', 'Manage edge nodes and instances, monitor status and load.', ), AssistantFocusEntry.agents => appText( '管理代理实例,配置行为与能力。', 'Manage agent instances, configure behaviors and capabilities.', ), AssistantFocusEntry.mcpServer => appText( '管理 MCP Hub 连接与工具配置。', 'Manage MCP Hub connections and tool configurations.', ), AssistantFocusEntry.clawHub => appText( '浏览和安装技能包、代理模板与连接器。', 'Browse and install skill packages, agent templates and connectors.', ), AssistantFocusEntry.secrets => appText( '密钥与 Vault 配置统一收口到设置中心。', 'Secrets and Vault configuration now live in the Settings center.', ), AssistantFocusEntry.aiGateway => appText( 'LLM API 配置统一收口到设置中心。', 'LLM API configuration now lives in the Settings center.', ), AssistantFocusEntry.settings => appText( '全局配置中心,只负责系统设置与诊断,不承担业务模块入口。', 'Global settings and diagnostics, separated from business modules.', ), AssistantFocusEntry.language => appText( '快速切换中英文界面语言,无需先进入设置页。', 'Switch the interface language quickly without opening Settings first.', ), AssistantFocusEntry.theme => appText( '快速切换浅色/深色亮度模式,方便在当前上下文立即调整外观。', 'Switch light and dark appearance modes directly from the current context.', ), }; WorkspaceDestination? get destination => switch (this) { AssistantFocusEntry.tasks => WorkspaceDestination.tasks, AssistantFocusEntry.skills => WorkspaceDestination.skills, AssistantFocusEntry.nodes => WorkspaceDestination.nodes, AssistantFocusEntry.agents => WorkspaceDestination.agents, AssistantFocusEntry.mcpServer => WorkspaceDestination.mcpServer, AssistantFocusEntry.clawHub => WorkspaceDestination.clawHub, AssistantFocusEntry.secrets => WorkspaceDestination.secrets, AssistantFocusEntry.aiGateway => WorkspaceDestination.aiGateway, AssistantFocusEntry.settings => WorkspaceDestination.settings, AssistantFocusEntry.language => null, AssistantFocusEntry.theme => null, }; bool get opensSettingsPage => this == AssistantFocusEntry.language || this == AssistantFocusEntry.theme || this == AssistantFocusEntry.settings; static AssistantFocusEntry? fromJsonValue(String? value) { if (value == null || value.trim().isEmpty) { return null; } for (final item in AssistantFocusEntry.values) { if (item.name == value.trim()) { return item; } } return null; } static AssistantFocusEntry fromDestination(WorkspaceDestination destination) { return switch (destination) { WorkspaceDestination.tasks => AssistantFocusEntry.tasks, WorkspaceDestination.skills => AssistantFocusEntry.skills, WorkspaceDestination.nodes => AssistantFocusEntry.nodes, WorkspaceDestination.agents => AssistantFocusEntry.agents, WorkspaceDestination.mcpServer => AssistantFocusEntry.mcpServer, WorkspaceDestination.clawHub => AssistantFocusEntry.clawHub, WorkspaceDestination.secrets => AssistantFocusEntry.secrets, WorkspaceDestination.aiGateway => AssistantFocusEntry.aiGateway, WorkspaceDestination.settings => AssistantFocusEntry.settings, WorkspaceDestination.assistant || WorkspaceDestination.account => throw ArgumentError.value( destination, 'destination', 'Focused assistant entries only support pinnable workspace targets.', ), }; } } const List kAssistantNavigationDestinationDefaults = []; const List kAssistantNavigationDestinationCandidates = [ AssistantFocusEntry.tasks, AssistantFocusEntry.skills, AssistantFocusEntry.nodes, AssistantFocusEntry.agents, AssistantFocusEntry.mcpServer, AssistantFocusEntry.clawHub, AssistantFocusEntry.secrets, AssistantFocusEntry.aiGateway, AssistantFocusEntry.settings, AssistantFocusEntry.language, AssistantFocusEntry.theme, ]; List normalizeAssistantNavigationDestinations( Iterable destinations, ) { final allowed = kAssistantNavigationDestinationCandidates.toSet(); final seen = {}; final normalized = []; for (final destination in destinations) { if (!allowed.contains(destination) || !seen.add(destination)) { continue; } normalized.add(destination); } return normalized; } enum StatusTone { neutral, accent, success, warning, danger } class StatusInfo { const StatusInfo(this.label, this.tone); final String label; final StatusTone tone; } enum AppSidebarState { expanded, collapsed, hidden } enum AssistantMode { code, office } extension AssistantModeCopy on AssistantMode { String get label => switch (this) { AssistantMode.code => appText('代码开发', 'Code'), AssistantMode.office => appText('日常办公', 'Office'), }; } enum TasksTab { queue, running, history, failed, scheduled } extension TasksTabCopy on TasksTab { String get label => switch (this) { TasksTab.queue => appText('队列', 'Queue'), TasksTab.running => appText('运行中', 'Running'), TasksTab.history => appText('历史', 'History'), TasksTab.failed => appText('失败', 'Failed'), TasksTab.scheduled => appText('计划中', 'Scheduled'), }; } enum ModulesTab { gateway, nodes, agents, skills, clawHub, connectors } extension ModulesTabCopy on ModulesTab { String get label => switch (this) { ModulesTab.gateway => appText('网关', 'Gateway'), ModulesTab.nodes => appText('节点', 'Nodes'), ModulesTab.agents => appText('代理', 'Agents'), ModulesTab.skills => appText('技能', 'Skills'), ModulesTab.clawHub => 'ClawHub', ModulesTab.connectors => appText('连接器', 'Connectors'), }; } enum SecretsTab { vault, localStore, providers, audit } extension SecretsTabCopy on SecretsTab { String get label => switch (this) { SecretsTab.vault => 'Vault', SecretsTab.localStore => appText('本地存储', 'Local Store'), SecretsTab.providers => appText('提供方', 'Providers'), SecretsTab.audit => appText('审计', 'Audit'), }; } enum SettingsTab { general, workspace, gateway, agents, appearance, diagnostics, experimental, about, } extension SettingsTabCopy on SettingsTab { String get label => switch (this) { SettingsTab.general => appText('通用', 'General'), SettingsTab.workspace => appText('工作区', 'Workspace'), SettingsTab.gateway => appText('集成', 'Integrations'), SettingsTab.agents => appText('多 Agent', 'Multi-Agent'), SettingsTab.appearance => appText('外观', 'Appearance'), SettingsTab.diagnostics => appText('诊断', 'Diagnostics'), SettingsTab.experimental => appText('实验特性', 'Experimental'), SettingsTab.about => appText('关于', 'About'), }; } enum AiGatewayTab { models, agents, endpoints, tools } extension AiGatewayTabCopy on AiGatewayTab { String get label => switch (this) { AiGatewayTab.models => appText('模型', 'Models'), AiGatewayTab.agents => appText('代理', 'Agents'), AiGatewayTab.endpoints => appText('端点', 'Endpoints'), AiGatewayTab.tools => appText('工具', 'Tools'), }; } enum SettingsDetailPage { gatewayConnection, aiGatewayIntegration, vaultProvider, externalAgents, diagnosticsAdvanced, } extension SettingsDetailPageCopy on SettingsDetailPage { String get label => switch (this) { SettingsDetailPage.gatewayConnection => appText( 'Gateway 连接参数', 'Gateway Connection', ), SettingsDetailPage.aiGatewayIntegration => appText( 'LLM 接入点', 'LLM Endpoints', ), SettingsDetailPage.vaultProvider => appText( 'Vault 提供方参数', 'Vault Provider', ), SettingsDetailPage.externalAgents => appText( '多 Agent 协作参数', 'External Agents', ), SettingsDetailPage.diagnosticsAdvanced => appText( '高级诊断参数', 'Advanced Diagnostics', ), }; SettingsTab get tab => switch (this) { SettingsDetailPage.gatewayConnection || SettingsDetailPage.aiGatewayIntegration || SettingsDetailPage.vaultProvider => SettingsTab.gateway, SettingsDetailPage.externalAgents => SettingsTab.agents, SettingsDetailPage.diagnosticsAdvanced => SettingsTab.diagnostics, }; } @immutable class SettingsNavigationContext { const SettingsNavigationContext({ required this.rootLabel, required this.destination, this.sectionLabel, this.modulesTab, this.secretsTab, this.aiGatewayTab, this.settingsTab, this.gatewayProfileIndex, this.prefersGatewaySetupCode, }); final String rootLabel; final WorkspaceDestination destination; final String? sectionLabel; final ModulesTab? modulesTab; final SecretsTab? secretsTab; final AiGatewayTab? aiGatewayTab; final SettingsTab? settingsTab; final int? gatewayProfileIndex; final bool? prefersGatewaySetupCode; } enum AccountTab { profile, workspace, sessions } extension AccountTabCopy on AccountTab { String get label => switch (this) { AccountTab.profile => appText('资料', 'Profile'), AccountTab.workspace => appText('工作区', 'Workspace'), AccountTab.sessions => appText('会话', 'Sessions'), }; } class QuickAction { const QuickAction({ required this.title, required this.icon, required this.caption, }); final String title; final IconData icon; final String caption; } class RecentSession { const RecentSession({ required this.title, required this.timestamp, required this.summary, }); final String title; final String timestamp; final String summary; } class MetricSummary { const MetricSummary({ required this.label, required this.value, required this.caption, required this.icon, this.status, }); final String label; final String value; final String caption; final IconData icon; final StatusInfo? status; } class TaskSummary { const TaskSummary({ required this.name, required this.owner, required this.status, required this.startedAt, required this.duration, required this.surface, }); final String name; final String owner; final StatusInfo status; final String startedAt; final String duration; final String surface; } class ModuleSummary { const ModuleSummary({ required this.name, required this.description, required this.status, required this.meta, required this.icon, }); final String name; final String description; final StatusInfo status; final String meta; final IconData icon; } class NodeSummary { const NodeSummary({ required this.name, required this.type, required this.region, required this.heartbeat, required this.load, required this.status, }); final String name; final String type; final String region; final String heartbeat; final String load; final StatusInfo status; } class AgentSummary { const AgentSummary({ required this.name, required this.description, required this.status, required this.lastRun, required this.capabilities, }); final String name; final String description; final StatusInfo status; final String lastRun; final List capabilities; } class SkillSummary { const SkillSummary({ required this.name, required this.type, required this.source, required this.status, required this.version, required this.modules, }); final String name; final String type; final String source; final StatusInfo status; final String version; final String modules; } class ConnectorSummary { const ConnectorSummary({ required this.name, required this.description, required this.status, required this.lastSync, required this.permission, }); final String name; final String description; final StatusInfo status; final String lastSync; final String permission; } class SecretSummary { const SecretSummary({ required this.name, required this.scope, required this.status, required this.updatedAt, required this.provider, }); final String name; final String scope; final StatusInfo status; final String updatedAt; final String provider; } class SecretReference { const SecretReference({ required this.name, required this.provider, required this.module, required this.status, required this.maskedValue, }); final String name; final String provider; final String module; final StatusInfo status; final String maskedValue; } class ProviderSummary { const ProviderSummary({ required this.name, required this.description, required this.status, required this.capabilities, }); final String name; final String description; final StatusInfo status; final List capabilities; } class AuditSummary { const AuditSummary({ required this.time, required this.action, required this.provider, required this.target, required this.module, required this.status, }); final String time; final String action; final String provider; final String target; final String module; final StatusInfo status; } class SettingSummary { const SettingSummary({ required this.title, required this.description, required this.value, }); final String title; final String description; final String value; } class WorkspaceProfile { const WorkspaceProfile({ required this.name, required this.role, required this.members, required this.region, }); final String name; final String role; final String members; final String region; } class DetailPanelData { const DetailPanelData({ required this.title, required this.subtitle, required this.icon, required this.status, required this.description, required this.meta, required this.sections, required this.actions, }); final String title; final String subtitle; final IconData icon; final StatusInfo status; final String description; final List meta; final List sections; final List actions; } class DetailSection { const DetailSection({required this.title, required this.items}); final String title; final List items; } class DetailItem { const DetailItem({required this.label, required this.value}); final String label; final String value; } class CommandEntry { const CommandEntry({ required this.title, required this.subtitle, required this.icon, required this.keyword, this.shortcut, this.destination, this.detail, }); final String title; final String subtitle; final IconData icon; final String keyword; final String? shortcut; final WorkspaceDestination? destination; final DetailPanelData? detail; }