From d23bd2708c6ce5a1bf26efe8e2d5d554f8bda2db Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Fri, 12 Jun 2026 14:52:23 +0800 Subject: [PATCH] chore: remove stale Flutter code --- .gitignore | 1 + lib/app/task_thread_repositories.dart | 45 +- lib/data/mock_data.dart | 773 ------------------ lib/runtime/opencode_config_bridge.dart | 118 --- lib/widgets/app_brand_logo.dart | 164 ---- lib/widgets/metric_card.dart | 48 -- lib/widgets/section_header.dart | 35 - ...troller_thread_workspace_binding_test.dart | 1 - 8 files changed, 4 insertions(+), 1181 deletions(-) delete mode 100644 lib/data/mock_data.dart delete mode 100644 lib/runtime/opencode_config_bridge.dart delete mode 100644 lib/widgets/app_brand_logo.dart delete mode 100644 lib/widgets/metric_card.dart delete mode 100644 lib/widgets/section_header.dart diff --git a/.gitignore b/.gitignore index 6c5bf4e0..cd04c7cb 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ migrate_working_dir/ tmp/* !tmp/.gitkeep .worktrees/ +_codex_worktrees/ # IntelliJ related *.iml diff --git a/lib/app/task_thread_repositories.dart b/lib/app/task_thread_repositories.dart index 8f5ced5f..b855fdcb 100644 --- a/lib/app/task_thread_repositories.dart +++ b/lib/app/task_thread_repositories.dart @@ -38,7 +38,9 @@ class DesktopTaskThreadRepository { _records ..clear() ..addEntries( - records.map((record) => MapEntry(record.threadId, record)), + records.map( + (record) => MapEntry(record.threadId, record), + ), ); if (persist) { _schedulePersist(); @@ -74,44 +76,3 @@ class DesktopTaskThreadRepository { unawaited(_persistQueue); } } - -class WebTaskThreadRepository { - final Map _records = {}; - - Map get recordsView => UnmodifiableMapView(_records); - Iterable get values => _records.values; - - bool containsKey(String sessionKey) => _records.containsKey(sessionKey); - - TaskThread? taskThreadForSession(String sessionKey) => _records[sessionKey]; - - TaskThread requireTaskThreadForSession(String sessionKey) { - final record = taskThreadForSession(sessionKey); - if (record == null) { - throw StateError('Missing TaskThread for session $sessionKey.'); - } - return record; - } - - void replace(TaskThread record) { - _records[record.threadId] = record; - } - - void replaceAll(Iterable records) { - _records - ..clear() - ..addEntries( - records.map((record) => MapEntry(record.threadId, record)), - ); - } - - void clear() { - _records.clear(); - } - - void removeWhere(bool Function(String sessionKey, TaskThread record) predicate) { - _records.removeWhere(predicate); - } - - List snapshot() => values.toList(growable: false); -} diff --git a/lib/data/mock_data.dart b/lib/data/mock_data.dart deleted file mode 100644 index 62a65645..00000000 --- a/lib/data/mock_data.dart +++ /dev/null @@ -1,773 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../app/app_metadata.dart'; -import '../models/app_models.dart'; - -class MockData { - static const quickActions = [ - QuickAction( - title: '写代码', - icon: Icons.code_rounded, - caption: '生成组件、修复 bug、搭建原型', - ), - QuickAction( - title: '分析文档', - icon: Icons.description_rounded, - caption: '长文总结、要点抽取、风险提示', - ), - QuickAction( - title: '生成 PPT', - icon: Icons.slideshow_rounded, - caption: '提纲生成、页面结构、讲述逻辑', - ), - QuickAction( - title: '数据分析', - icon: Icons.analytics_rounded, - caption: '表格解读、趋势拆解、指标洞察', - ), - QuickAction( - title: '设计方案', - icon: Icons.draw_rounded, - caption: '产品方案、交互思路、界面方向', - ), - QuickAction( - title: '邮件处理', - icon: Icons.mail_outline_rounded, - caption: '总结线程、起草回复、提炼行动项', - ), - QuickAction( - title: '自动化任务', - icon: Icons.auto_mode_rounded, - caption: '定时执行、跨工具协同、持续追踪', - ), - ]; - - static const recentSessions = [ - RecentSession( - title: '设计新的桌面 IA', - timestamp: '12 分钟前', - summary: '重排主导航,压平二级结构,保持 Assistant 为首页。', - ), - RecentSession( - title: '梳理任务执行历史', - timestamp: '今天 14:20', - summary: '合并 Queue / Running / Failed 的追踪口径。', - ), - RecentSession( - title: '检查 Gateway 轻量控制面', - timestamp: '昨天', - summary: '减少运维感,更多强调 AI 控制平面状态。', - ), - ]; - - static const taskMetrics = [ - MetricSummary( - label: 'Total', - value: '128', - caption: '总任务数', - icon: Icons.layers_rounded, - ), - MetricSummary( - label: 'Running', - value: '12', - caption: '当前运行中', - icon: Icons.play_circle_outline_rounded, - status: StatusInfo('Stable', StatusTone.success), - ), - MetricSummary( - label: 'Failed', - value: '3', - caption: '需要人工介入', - icon: Icons.error_outline_rounded, - status: StatusInfo('Watch', StatusTone.warning), - ), - MetricSummary( - label: 'Scheduled', - value: '18', - caption: '已排程任务', - icon: Icons.event_repeat_rounded, - ), - ]; - - static const queueTasks = [ - TaskSummary( - name: 'Design Desktop IA Shell', - owner: 'Coding Agent', - status: StatusInfo('Queued', StatusTone.neutral), - startedAt: '预计 16:50', - duration: 'ETA 4m', - surface: 'Assistant', - ), - TaskSummary( - name: 'Daily Report Draft', - owner: 'Job Autopilot', - status: StatusInfo('Queued', StatusTone.neutral), - startedAt: '预计 17:00', - duration: 'ETA 2m', - surface: 'Scheduled', - ), - ]; - - static const runningTasks = [ - TaskSummary( - name: 'XWorkmate Workspace Prototype', - owner: 'Coding Agent', - status: StatusInfo('Running', StatusTone.accent), - startedAt: '刚刚', - duration: '8m 12s', - surface: 'Assistant', - ), - TaskSummary( - name: 'Market Monitor Rollup', - owner: 'Research Agent', - status: StatusInfo('Streaming', StatusTone.success), - startedAt: '16:12', - duration: '2m 43s', - surface: 'Tasks', - ), - ]; - - static const historyTasks = [ - TaskSummary( - name: 'Slack Thread Summarization', - owner: 'Research Agent', - status: StatusInfo('Completed', StatusTone.success), - startedAt: '今天 15:10', - duration: '3m 42s', - surface: 'CoreSetup', - ), - TaskSummary( - name: 'Resume Scan Batch', - owner: 'Job Autopilot', - status: StatusInfo('Completed', StatusTone.success), - startedAt: '今天 13:25', - duration: '6m 03s', - surface: 'Tasks', - ), - ]; - - static const failedTasks = [ - TaskSummary( - name: 'Connector Credential Refresh', - owner: 'Browser Agent', - status: StatusInfo('Failed', StatusTone.danger), - startedAt: '今天 14:03', - duration: '58s', - surface: 'Secrets', - ), - ]; - - static const scheduledTasks = [ - TaskSummary( - name: 'Morning Standup Digest', - owner: 'Job Autopilot', - status: StatusInfo('Scheduled', StatusTone.accent), - startedAt: '明天 08:40', - duration: 'Daily', - surface: 'Tasks', - ), - TaskSummary( - name: 'Inbox Triage', - owner: 'Research Agent', - status: StatusInfo('Scheduled', StatusTone.accent), - startedAt: '18:00', - duration: 'Every 3h', - surface: 'Tasks', - ), - ]; - - static const workspaceModules = [ - ModuleSummary( - name: 'Workspace Overview', - description: '统一管理默认模型、默认 Agent、团队策略与入口偏好。', - status: StatusInfo('Ready', StatusTone.success), - meta: '3 workspaces · 12 members', - icon: Icons.apartment_rounded, - ), - ]; - - static const gatewayModules = [ - ModuleSummary( - name: 'LLM API', - description: - 'Healthy · version $kAppVersion · 3 nodes · 12 active sessions', - status: StatusInfo('Healthy', StatusTone.success), - meta: '87 runs today', - icon: Icons.wifi_tethering_rounded, - ), - ModuleSummary( - name: 'Edge Relay', - description: 'Tokyo relay handling cross-region session routing.', - status: StatusInfo('Healthy', StatusTone.success), - meta: '3 active sessions', - icon: Icons.hub_rounded, - ), - ]; - - static const nodeModules = [ - ModuleSummary( - name: 'Mac mini studio-01', - description: 'Desktop automation node with screenshot + shell access.', - status: StatusInfo('Healthy', StatusTone.success), - meta: 'CPU 42% · RAM 61%', - icon: Icons.desktop_mac_rounded, - ), - ModuleSummary( - name: 'Cloud sandbox', - description: 'Ephemeral workload node for heavy research tasks.', - status: StatusInfo('Warning', StatusTone.warning), - meta: 'Retry queue elevated', - icon: Icons.cloud_queue_rounded, - ), - ]; - - static const nodes = [ - NodeSummary( - name: 'Mac mini studio-01', - type: 'local', - region: 'Shanghai', - heartbeat: '12s ago', - load: '42%', - status: StatusInfo('Healthy', StatusTone.success), - ), - NodeSummary( - name: 'Edge relay tokyo', - type: 'edge', - region: 'Tokyo', - heartbeat: '28s ago', - load: '31%', - status: StatusInfo('Healthy', StatusTone.success), - ), - NodeSummary( - name: 'Sandbox remote-03', - type: 'remote', - region: 'Frankfurt', - heartbeat: '2m ago', - load: '76%', - status: StatusInfo('Warning', StatusTone.warning), - ), - ]; - - static const agents = [ - AgentSummary( - name: 'Browser Agent', - description: '网页探索、采集、表单操作与流程验证。', - status: StatusInfo('Idle', StatusTone.neutral), - lastRun: '18 分钟前', - capabilities: ['Browse', 'Capture', 'Validate'], - ), - AgentSummary( - name: 'Coding Agent', - description: '读写代码、生成补丁、解释实现与验证构建。', - status: StatusInfo('Running', StatusTone.accent), - lastRun: '刚刚', - capabilities: ['Code', 'Patch', 'Tests'], - ), - AgentSummary( - name: 'Research Agent', - description: '检索资料、比对来源、收敛结论。', - status: StatusInfo('Idle', StatusTone.neutral), - lastRun: '43 分钟前', - capabilities: ['Search', 'Compare', 'Synthesis'], - ), - AgentSummary( - name: 'Job Autopilot', - description: '持续接单、编排子任务、回收输出物。', - status: StatusInfo('Running', StatusTone.success), - lastRun: '2 分钟前', - capabilities: ['Delegation', 'Scheduling', 'Reports'], - ), - AgentSummary( - name: 'Custom Agent', - description: '面向团队流程定制的草稿 Agent。', - status: StatusInfo('Draft', StatusTone.warning), - lastRun: '未运行', - capabilities: ['Custom Prompt', 'Tools', 'Context'], - ), - ]; - - static const skills = [ - SkillSummary( - name: 'db-migration-runbook', - type: 'Runbook', - source: 'Local skill', - status: StatusInfo('Enabled', StatusTone.success), - version: '1.4.0', - modules: 'Tasks · Modules', - ), - SkillSummary( - name: 'playwright', - type: 'Automation', - source: 'Shared skill', - status: StatusInfo('Enabled', StatusTone.success), - version: '2.1.3', - modules: 'Modules · Secrets', - ), - SkillSummary( - name: 'vercel-deploy', - type: 'Deployment', - source: 'Hub', - status: StatusInfo('Preview', StatusTone.accent), - version: '0.9.2', - modules: 'Modules', - ), - ]; - - static const agentModules = [ - ModuleSummary( - name: 'Job Autopilot', - description: '持续接单、自动整理输出物、分发下一步行动。', - status: StatusInfo('Running', StatusTone.success), - meta: 'Queue depth 4', - icon: Icons.auto_awesome_motion_rounded, - ), - ModuleSummary( - name: 'Coding Agent', - description: '负责读写代码、补丁生成、编译检查与解释。', - status: StatusInfo('Running', StatusTone.accent), - meta: 'GPT-5 Code', - icon: Icons.terminal_rounded, - ), - ]; - - static const skillModules = [ - ModuleSummary( - name: 'db-migration-runbook', - description: '面向数据库迁移和演练的工作指引 skill。', - status: StatusInfo('Installed', StatusTone.success), - meta: 'Last updated 2d ago', - icon: Icons.menu_book_rounded, - ), - ModuleSummary( - name: 'playwright', - description: '桌面与浏览器自动化能力封装。', - status: StatusInfo('Installed', StatusTone.success), - meta: 'Used in 18 runs', - icon: Icons.web_asset_rounded, - ), - ]; - - static const clawHubModules = [ - ModuleSummary( - name: 'Hub Registry', - description: '统一查看共享模块、预设 Agent 与团队模板。', - status: StatusInfo('Connected', StatusTone.accent), - meta: '24 shared assets', - icon: Icons.grid_view_rounded, - ), - ]; - - static const connectorModules = [ - ModuleSummary( - name: 'Slack Connector', - description: '线程总结、消息派发与任务回写。', - status: StatusInfo('Warning', StatusTone.warning), - meta: '480 events / day', - icon: Icons.forum_rounded, - ), - ModuleSummary( - name: 'Email Relay', - description: '日报投递、邮件摘要与草稿生成。', - status: StatusInfo('Healthy', StatusTone.success), - meta: '126 messages / day', - icon: Icons.mail_rounded, - ), - ]; - - static const connectors = [ - ConnectorSummary( - name: 'Vault', - description: '管理远程 secret reference 与轮换策略。', - status: StatusInfo('Connected', StatusTone.success), - lastSync: '2 分钟前', - permission: 'Read / Write', - ), - ConnectorSummary( - name: 'GitHub', - description: '用于 issue、PR 和仓库自动化。', - status: StatusInfo('Connected', StatusTone.success), - lastSync: '5 分钟前', - permission: 'Repo scoped', - ), - ConnectorSummary( - name: 'Google Drive', - description: '读取文档、表格与共享目录。', - status: StatusInfo('Pending', StatusTone.warning), - lastSync: '未同步', - permission: 'Awaiting OAuth', - ), - ConnectorSummary( - name: 'Slack', - description: '消息接入、线程总结、任务回写。', - status: StatusInfo('Warning', StatusTone.warning), - lastSync: '12 分钟前', - permission: 'Messages', - ), - ConnectorSummary( - name: 'MCP', - description: '连接本地或远程 MCP 服务器。', - status: StatusInfo('Connected', StatusTone.success), - lastSync: '刚刚', - permission: 'Tool access', - ), - ConnectorSummary( - name: 'Local FS', - description: '本地文件系统读写与目录索引。', - status: StatusInfo('Connected', StatusTone.success), - lastSync: '实时', - permission: 'Workspace only', - ), - ]; - - static const vaultSecrets = [ - SecretSummary( - name: 'OPENAI_API_KEY', - scope: 'Workspace', - status: StatusInfo('Healthy', StatusTone.success), - updatedAt: '2 小时前', - provider: 'Vault', - ), - SecretSummary( - name: 'SLACK_BOT_TOKEN', - scope: 'Connector', - status: StatusInfo('Rotating', StatusTone.warning), - updatedAt: '昨天', - provider: 'Vault', - ), - ]; - - static const localSecrets = [ - SecretSummary( - name: 'LOCAL_AGENT_CACHE', - scope: 'Desktop', - status: StatusInfo('Local', StatusTone.neutral), - updatedAt: '今天', - provider: 'Keychain', - ), - ]; - - static const providerSecrets = [ - SecretSummary( - name: '1Password', - scope: 'Provider', - status: StatusInfo('Connected', StatusTone.success), - updatedAt: '刚刚', - provider: 'Provider', - ), - SecretSummary( - name: 'AWS Secrets Manager', - scope: 'Provider', - status: StatusInfo('Draft', StatusTone.warning), - updatedAt: '未配置', - provider: 'Provider', - ), - ]; - - static const secretReferences = [ - SecretReference( - name: 'indeed_cookie', - provider: 'Vault', - module: 'Job Autopilot', - status: StatusInfo('In use', StatusTone.success), - maskedValue: '••••••••4ae7', - ), - SecretReference( - name: 'github_token', - provider: 'Vault', - module: 'Coding Agent', - status: StatusInfo('In use', StatusTone.success), - maskedValue: 'ghp_••••••8k2m', - ), - SecretReference( - name: 'openai_key', - provider: 'Local', - module: 'Gateway', - status: StatusInfo('Warning', StatusTone.warning), - maskedValue: 'sk-••••••••••', - ), - ]; - - static const providers = [ - ProviderSummary( - name: 'HashiCorp Vault', - description: '远程 secret provider,支持 namespace、TTL 和审计。', - status: StatusInfo('Connected', StatusTone.success), - capabilities: ['KV', 'TTL', 'Audit'], - ), - ProviderSummary( - name: 'Environment Variables', - description: '适合本地开发与 CI 运行时注入。', - status: StatusInfo('Available', StatusTone.neutral), - capabilities: ['Runtime', 'Process', 'Masking'], - ), - ProviderSummary( - name: 'Local File', - description: '为离线桌面环境提供本地加密存储。', - status: StatusInfo('Enabled', StatusTone.success), - capabilities: ['Encrypted', 'Local', 'Backup'], - ), - ProviderSummary( - name: 'External Secret Manager', - description: '预留给企业第三方 secret manager 的接入位。', - status: StatusInfo('Draft', StatusTone.warning), - capabilities: ['Enterprise', 'Sync', 'Policy'], - ), - ]; - - static const auditSecrets = [ - AuditSummary( - time: '16:12', - action: 'Rotate token', - provider: 'Vault', - target: 'github_token', - module: 'Coding Agent', - status: StatusInfo('Success', StatusTone.success), - ), - AuditSummary( - time: '15:40', - action: 'Read secret', - provider: 'Vault', - target: 'indeed_cookie', - module: 'Job Autopilot', - status: StatusInfo('Success', StatusTone.success), - ), - AuditSummary( - time: '14:52', - action: 'Resolve reference', - provider: 'Local', - target: 'openai_key', - module: 'Gateway', - status: StatusInfo('Warning', StatusTone.warning), - ), - ]; - - static const generalSettings = [ - SettingSummary( - title: 'Default launch surface', - description: '始终保持 Assistant 为默认首页。', - value: 'Assistant', - ), - SettingSummary( - title: 'Command palette shortcut', - description: '桌面全局入口,Cmd/Ctrl + K。', - value: 'Enabled', - ), - ]; - - static const workspaceSettings = [ - SettingSummary( - title: 'Data path', - description: '本地运行数据与缓存目录。', - value: '/opt/data', - ), - SettingSummary( - title: 'Repo path', - description: '默认代码工作区根目录。', - value: '/opt/data/workspace', - ), - SettingSummary( - title: 'Default agent', - description: '新建任务时默认挂载的 Agent。', - value: 'Coding Agent', - ), - ]; - - static const gatewaySettings = [ - SettingSummary( - title: 'Gateway default route', - description: '控制面启动后默认挂载的主路由。', - value: 'LLM API', - ), - SettingSummary( - title: 'Session retention', - description: '会话日志保留策略。', - value: '14 days', - ), - ]; - - static const appearanceSettings = [ - SettingSummary( - title: 'Theme', - description: '桌面浅色优先,同时支持暗色主题。', - value: 'Auto / Manual', - ), - SettingSummary( - title: 'Dense tables', - description: '关闭后保持更轻的桌面留白。', - value: 'Off', - ), - ]; - - static const providerSettings = [ - SettingSummary( - title: 'Module provider source', - description: '决定 Skills / Agents / Connectors 的拉取来源。', - value: 'ClawHub', - ), - SettingSummary( - title: 'Connector sync policy', - description: '共享模块更新时的同步行为。', - value: 'Manual review', - ), - ]; - - static const diagnosticSettings = [ - SettingSummary( - title: 'Gateway health snapshot', - description: '最近一次诊断汇总。', - value: 'Healthy', - ), - SettingSummary( - title: 'Local data directory', - description: '本地运行数据与缓存入口。', - value: '/opt/data/', - ), - ]; - - static const experimentalSettings = [ - SettingSummary( - title: 'Floating detail drawer', - description: '在宽屏下保留右侧抽屉式详情。', - value: 'Enabled', - ), - SettingSummary( - title: 'Desktop inline previews', - description: '在 Tasks 和 Secrets 中显示更多 hover 预览。', - value: 'Preview', - ), - ]; - - static const aboutSettings = [ - SettingSummary( - title: kSystemAppName, - description: 'Flutter Material 3 UI shell for macOS and Windows.', - value: kAppVersionLabel, - ), - SettingSummary( - title: 'Build channel', - description: 'Prototype only, mock data mode.', - value: 'Desktop alpha', - ), - ]; - - static const workspaces = [ - WorkspaceProfile( - name: 'XWorkmate Design Lab', - role: 'Owner', - members: '12 members', - region: 'Asia Pacific', - ), - WorkspaceProfile( - name: 'Client Operations', - role: 'Editor', - members: '8 members', - region: 'Global', - ), - ]; - - static const accountSessions = [ - TaskSummary( - name: 'MacBook Pro · Desktop App', - owner: 'This device', - status: StatusInfo('Active', StatusTone.success), - startedAt: '今天 16:00', - duration: 'Current', - surface: 'Desktop', - ), - TaskSummary( - name: 'Windows workstation', - owner: 'Remote sign-in', - status: StatusInfo('Idle', StatusTone.neutral), - startedAt: '昨天', - duration: '23h ago', - surface: 'Desktop', - ), - ]; - - static DetailPanelData taskDetail(TaskSummary task) { - return DetailPanelData( - title: task.name, - subtitle: 'Task Detail', - icon: Icons.bolt_rounded, - status: task.status, - description: '任务来自 ${task.surface},当前由 ${task.owner} 持有。', - meta: [task.surface, task.owner, task.duration], - actions: const ['打开', '重试', '复制链接'], - sections: [ - DetailSection( - title: 'Execution', - items: [ - DetailItem(label: '开始时间', value: task.startedAt), - DetailItem(label: '耗时', value: task.duration), - DetailItem(label: '状态', value: task.status.label), - ], - ), - ], - ); - } - - static DetailPanelData moduleDetail(ModuleSummary module) { - return DetailPanelData( - title: module.name, - subtitle: 'Module Detail', - icon: module.icon, - status: module.status, - description: module.description, - meta: [module.meta, module.status.label], - actions: const ['打开', '配置', '查看状态'], - sections: [ - DetailSection( - title: 'Overview', - items: [ - DetailItem(label: '状态', value: module.status.label), - DetailItem(label: '摘要', value: module.meta), - ], - ), - ], - ); - } - - static DetailPanelData secretDetail(SecretSummary secret) { - return DetailPanelData( - title: secret.name, - subtitle: 'Secret Detail', - icon: Icons.key_rounded, - status: secret.status, - description: '该密钥当前归属 ${secret.scope},由 ${secret.provider} 管理。', - meta: [secret.scope, secret.provider, secret.updatedAt], - actions: const ['查看审计', '轮换', '复制引用'], - sections: [ - DetailSection( - title: 'Metadata', - items: [ - DetailItem(label: 'Scope', value: secret.scope), - DetailItem(label: 'Provider', value: secret.provider), - DetailItem(label: 'Updated', value: secret.updatedAt), - ], - ), - ], - ); - } - - static DetailPanelData workspaceDetail(WorkspaceProfile workspace) { - return DetailPanelData( - title: workspace.name, - subtitle: 'Workspace Detail', - icon: Icons.apartment_rounded, - status: const StatusInfo('Healthy', StatusTone.success), - description: '工作区用于组织共享模块、成员权限和默认执行策略。', - meta: [workspace.role, workspace.members, workspace.region], - actions: const ['切换', '管理成员', '查看策略'], - sections: [ - DetailSection( - title: 'Profile', - items: [ - DetailItem(label: 'Role', value: workspace.role), - DetailItem(label: 'Members', value: workspace.members), - DetailItem(label: 'Region', value: workspace.region), - ], - ), - ], - ); - } -} diff --git a/lib/runtime/opencode_config_bridge.dart b/lib/runtime/opencode_config_bridge.dart deleted file mode 100644 index 4f02ab6b..00000000 --- a/lib/runtime/opencode_config_bridge.dart +++ /dev/null @@ -1,118 +0,0 @@ -import 'dart:io'; - -class OpencodeConfigBridge { - OpencodeConfigBridge({String? opencodeHome}) - : opencodeHome = - opencodeHome ?? '${Platform.environment['HOME'] ?? ''}/.opencode'; - - static const String _managedMcpBlockStart = - '# BEGIN XWORKMATE MANAGED MCP BLOCK'; - static const String _managedMcpBlockEnd = '# END XWORKMATE MANAGED MCP BLOCK'; - - final String opencodeHome; - - Future configureManagedMcpServers({ - required List servers, - }) async { - final configDir = Directory(opencodeHome); - if (!await configDir.exists()) { - await configDir.create(recursive: true); - } - - final configFile = File('$opencodeHome/config.toml'); - final existingConfig = await configFile.exists() - ? await configFile.readAsString() - : ''; - final preserved = _stripManagedMcpBlock(existingConfig).trimRight(); - final managedBlock = _buildManagedMcpBlock(servers); - final merged = preserved.isEmpty - ? '$managedBlock\n' - : '$preserved\n\n$managedBlock\n'; - await configFile.writeAsString(merged); - } - - Future readConfig() async { - final configFile = File('$opencodeHome/config.toml'); - if (!await configFile.exists()) { - return ''; - } - return configFile.readAsString(); - } - - String _stripManagedMcpBlock(String content) { - if (content.isEmpty) { - return content; - } - - var remaining = content; - while (true) { - final start = remaining.indexOf(_managedMcpBlockStart); - if (start < 0) { - break; - } - final end = remaining.indexOf(_managedMcpBlockEnd, start); - if (end < 0) { - remaining = remaining.substring(0, start); - break; - } - remaining = - remaining.substring(0, start) + - remaining.substring(end + _managedMcpBlockEnd.length); - } - return remaining; - } - - String _buildManagedMcpBlock(List servers) { - final buffer = StringBuffer() - ..writeln(_managedMcpBlockStart) - ..writeln('# Generated by XWorkmate - Managed MCP Server Configuration') - ..writeln('# Last updated: ${DateTime.now().toIso8601String()}') - ..writeln(); - - for (final server in servers) { - buffer.writeln('[mcp_servers.${server.name}]'); - if (server.url.trim().isNotEmpty) { - buffer.writeln('url = "${server.url.trim()}"'); - } else { - buffer.writeln('type = "stdio"'); - buffer.writeln('command = "${server.command}"'); - if (server.args.isNotEmpty) { - buffer.writeln('args = ${_formatTomlArray(server.args)}'); - } - } - if (server.env.isNotEmpty) { - final entries = server.env.entries - .map((entry) => '${entry.key} = "${entry.value}"') - .join(', '); - buffer.writeln('env = { $entries }'); - } - buffer.writeln(); - } - - buffer.writeln(_managedMcpBlockEnd); - return buffer.toString().trimRight(); - } - - String _formatTomlArray(List items) { - if (items.isEmpty) { - return '[]'; - } - return '[${items.map((item) => '"$item"').join(', ')}]'; - } -} - -class OpencodeMcpServer { - const OpencodeMcpServer({ - required this.name, - this.command = '', - this.url = '', - this.args = const [], - this.env = const {}, - }); - - final String name; - final String command; - final String url; - final List args; - final Map env; -} diff --git a/lib/widgets/app_brand_logo.dart b/lib/widgets/app_brand_logo.dart deleted file mode 100644 index 98309e18..00000000 --- a/lib/widgets/app_brand_logo.dart +++ /dev/null @@ -1,164 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../theme/app_palette.dart'; - -enum DoorLogoSide { left, right, doubleDoor } - -class AppBrandLogo extends StatelessWidget { - const AppBrandLogo({ - super.key, - this.size = 32, - this.borderRadius = 10, - this.showShadow = true, - }); - - final double size; - final double borderRadius; - final bool showShadow; - - @override - Widget build(BuildContext context) { - final palette = context.palette; - final iconColor = palette.textPrimary; - - return Container( - width: size, - height: size, - clipBehavior: Clip.antiAlias, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(borderRadius), - border: Border.all(color: palette.chromeStroke), - boxShadow: showShadow ? [palette.chromeShadowLift] : const [], - ), - child: Padding( - padding: EdgeInsets.all(size * 0.16), - child: CustomPaint( - painter: _DoorLogoPainter( - color: iconColor, - side: DoorLogoSide.doubleDoor, - ), - ), - ), - ); - } -} - -class DoorLogoIcon extends StatelessWidget { - const DoorLogoIcon({ - super.key, - required this.side, - required this.color, - this.size = 22, - }); - - final DoorLogoSide side; - final Color color; - final double size; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: size, - height: size, - child: CustomPaint( - painter: _DoorLogoPainter(color: color, side: side), - ), - ); - } -} - -class _DoorLogoPainter extends CustomPainter { - const _DoorLogoPainter({required this.color, required this.side}); - - final Color color; - final DoorLogoSide side; - - @override - void paint(Canvas canvas, Size size) { - final stroke = size.width * 0.085; - final outline = Paint() - ..color = color - ..style = PaintingStyle.stroke - ..strokeWidth = stroke - ..strokeCap = StrokeCap.round - ..strokeJoin = StrokeJoin.round; - - final panel = Paint() - ..color = color - ..style = PaintingStyle.stroke - ..strokeWidth = stroke * 0.82 - ..strokeCap = StrokeCap.round; - - final shell = RRect.fromRectAndRadius( - Rect.fromLTWH( - size.width * 0.14, - size.height * 0.16, - size.width * 0.72, - size.height * 0.68, - ), - Radius.circular(size.width * 0.16), - ); - canvas.drawRRect(shell, outline); - - final centerX = size.width * 0.5; - canvas.drawLine( - Offset(centerX, size.height * 0.2), - Offset(centerX, size.height * 0.8), - outline, - ); - - switch (side) { - case DoorLogoSide.left: - _paintLeftDoor(canvas, size, panel); - case DoorLogoSide.right: - _paintRightDoor(canvas, size, panel); - case DoorLogoSide.doubleDoor: - _paintLeftDoor(canvas, size, panel); - _paintRightDoor(canvas, size, panel); - _paintHandles(canvas, size); - } - } - - @override - bool shouldRepaint(covariant _DoorLogoPainter oldDelegate) { - return oldDelegate.color != color || oldDelegate.side != side; - } - - void _paintLeftDoor(Canvas canvas, Size size, Paint panel) { - final insetTop = size.height * 0.25; - final insetBottom = size.height * 0.75; - final leftDoorInset = size.width * 0.3; - canvas.drawLine( - Offset(leftDoorInset, insetTop), - Offset(leftDoorInset, insetBottom), - panel, - ); - _paintHandle(canvas, Offset(size.width * 0.435, size.height * 0.5), size); - } - - void _paintRightDoor(Canvas canvas, Size size, Paint panel) { - final insetTop = size.height * 0.25; - final insetBottom = size.height * 0.75; - final rightDoorInset = size.width * 0.7; - canvas.drawLine( - Offset(rightDoorInset, insetTop), - Offset(rightDoorInset, insetBottom), - panel, - ); - _paintHandle(canvas, Offset(size.width * 0.565, size.height * 0.5), size); - } - - void _paintHandles(Canvas canvas, Size size) { - _paintHandle(canvas, Offset(size.width * 0.435, size.height * 0.5), size); - _paintHandle(canvas, Offset(size.width * 0.565, size.height * 0.5), size); - } - - void _paintHandle(Canvas canvas, Offset center, Size size) { - final handlePaint = Paint() - ..color = color - ..style = PaintingStyle.fill; - final handleRadius = size.width * 0.035; - canvas.drawCircle(center, handleRadius, handlePaint); - } -} diff --git a/lib/widgets/metric_card.dart b/lib/widgets/metric_card.dart deleted file mode 100644 index 1e4e6c2c..00000000 --- a/lib/widgets/metric_card.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../models/app_models.dart'; -import '../theme/app_palette.dart'; -import '../theme/app_theme.dart'; -import 'status_badge.dart'; -import 'surface_card.dart'; - -class MetricCard extends StatelessWidget { - const MetricCard({super.key, required this.metric}); - - final MetricSummary metric; - - @override - Widget build(BuildContext context) { - final palette = context.palette; - - return SurfaceCard( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: palette.surfaceSecondary, - borderRadius: BorderRadius.circular(AppRadius.card), - ), - child: Icon(metric.icon, color: palette.textPrimary, size: 20), - ), - const Spacer(), - if (metric.status != null) - StatusBadge(status: metric.status!, compact: true), - ], - ), - const SizedBox(height: AppSpacing.lg), - Text(metric.label, style: Theme.of(context).textTheme.bodyMedium), - const SizedBox(height: AppSpacing.xxs), - Text(metric.value, style: Theme.of(context).textTheme.headlineSmall), - const SizedBox(height: AppSpacing.xxs), - Text(metric.caption, style: Theme.of(context).textTheme.bodySmall), - ], - ), - ); - } -} diff --git a/lib/widgets/section_header.dart b/lib/widgets/section_header.dart deleted file mode 100644 index 2aedc034..00000000 --- a/lib/widgets/section_header.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flutter/material.dart'; -import '../theme/app_theme.dart'; - -class SectionHeader extends StatelessWidget { - const SectionHeader({ - super.key, - required this.title, - required this.subtitle, - this.trailing, - }); - - final String title; - final String subtitle; - final Widget? trailing; - - @override - Widget build(BuildContext context) { - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(title, style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: AppSpacing.xs), - Text(subtitle, style: Theme.of(context).textTheme.bodySmall), - ], - ), - ), - ...[trailing].nonNulls, - ], - ); - } -} diff --git a/test/runtime/app_controller_thread_workspace_binding_test.dart b/test/runtime/app_controller_thread_workspace_binding_test.dart index 683cf902..30c4bf0f 100644 --- a/test/runtime/app_controller_thread_workspace_binding_test.dart +++ b/test/runtime/app_controller_thread_workspace_binding_test.dart @@ -5,7 +5,6 @@ import 'package:crypto/crypto.dart' as crypto; import 'package:flutter_test/flutter_test.dart'; import 'package:xworkmate/app/app_controller.dart'; import 'package:xworkmate/app/app_controller_desktop_runtime_coordination_impl.dart'; -import 'package:xworkmate/app/app_controller_desktop_runtime_helpers.dart'; import 'package:xworkmate/app/app_controller_desktop_thread_binding.dart'; import 'package:xworkmate/runtime/assistant_artifacts.dart'; import 'package:xworkmate/runtime/go_task_service_client.dart';