xworkmate-app/lib/models/app_models.dart

737 lines
21 KiB
Dart

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('在线账户', 'Online 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(
'在线账户、工作区切换、登录会话与 ACP Bridge Server 同步管理。',
'Online account, workspace switching, login sessions, and ACP Bridge Server sync.',
),
};
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<AssistantFocusEntry> kAssistantNavigationDestinationDefaults =
<AssistantFocusEntry>[];
const List<AssistantFocusEntry> kAssistantNavigationDestinationCandidates =
<AssistantFocusEntry>[
AssistantFocusEntry.tasks,
AssistantFocusEntry.skills,
AssistantFocusEntry.nodes,
AssistantFocusEntry.agents,
AssistantFocusEntry.mcpServer,
AssistantFocusEntry.clawHub,
AssistantFocusEntry.secrets,
AssistantFocusEntry.aiGateway,
AssistantFocusEntry.settings,
AssistantFocusEntry.language,
AssistantFocusEntry.theme,
];
List<AssistantFocusEntry> normalizeAssistantNavigationDestinations(
Iterable<AssistantFocusEntry> destinations,
) {
final allowed = kAssistantNavigationDestinationCandidates.toSet();
final seen = <AssistantFocusEntry>{};
final normalized = <AssistantFocusEntry>[];
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<String> 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<String> 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<String> meta;
final List<DetailSection> sections;
final List<String> actions;
}
class DetailSection {
const DetailSection({required this.title, required this.items});
final String title;
final List<DetailItem> 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;
}