From d1463d4d1e0d8bbad845afd7e233d7cde627d976 Mon Sep 17 00:00:00 2001 From: Hibryda Date: Wed, 18 Mar 2026 02:01:18 +0100 Subject: [PATCH] feat(pro): wire all 7 Pro components into app - ProjectBox: 5 Pro tabs (Analytics, Budget, Export, Symbols, Agent Mem) with PERSISTED-LAZY mount, proStatus() feature gate, peach accent color - SettingsPanel: Pro tab (Accounts + Marketplace) conditionally shown - ProSettings.svelte: wrapper with sub-tabs for AccountSwitcher + PluginMarketplace - Feature detection via dynamic import of pro-bridge + proStatus() call - All tabs hidden when agor-pro plugin not loaded (community edition) --- .../components/Workspace/ProjectBox.svelte | 53 ++++++++++++++++++- src/lib/settings/SettingsPanel.svelte | 15 +++++- .../settings/categories/ProSettings.svelte | 35 ++++++++++++ src/lib/settings/settings-registry.ts | 3 +- 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 src/lib/settings/categories/ProSettings.svelte diff --git a/src/lib/components/Workspace/ProjectBox.svelte b/src/lib/components/Workspace/ProjectBox.svelte index 2afb602..7a8ea5b 100644 --- a/src/lib/components/Workspace/ProjectBox.svelte +++ b/src/lib/components/Workspace/ProjectBox.svelte @@ -16,6 +16,11 @@ import TestingTab from './TestingTab.svelte'; import MetricsPanel from './MetricsPanel.svelte'; import AuditLogTab from './AuditLogTab.svelte'; + import AnalyticsDashboard from '../../commercial/AnalyticsDashboard.svelte'; + import SessionExporter from '../../commercial/SessionExporter.svelte'; + import BudgetManager from '../../commercial/BudgetManager.svelte'; + import ProjectMemory from '../../commercial/ProjectMemory.svelte'; + import CodeIntelligence from '../../commercial/CodeIntelligence.svelte'; import { getTerminalTabs, getActiveGroup, getFocusFlashProjectId, onProjectTabSwitch, onTerminalToggle, @@ -43,8 +48,14 @@ let mainSessionId = $state(null); let terminalExpanded = $state(false); - type ProjectTab = 'model' | 'docs' | 'context' | 'files' | 'ssh' | 'memories' | 'metrics' | 'tasks' | 'architecture' | 'selenium' | 'tests' | 'audit'; + type ProjectTab = 'model' | 'docs' | 'context' | 'files' | 'ssh' | 'memories' | 'metrics' | 'tasks' | 'architecture' | 'selenium' | 'tests' | 'audit' | 'analytics' | 'export' | 'budget' | 'promemory' | 'symbols'; let activeTab = $state('model'); + let proAvailable = $state(false); + + // Detect Pro edition availability + $effect(() => { + import('../../commercial/pro-bridge').then(m => m.proStatus()).then(() => { proAvailable = true; }).catch(() => {}); + }); let activeGroup = $derived(getActiveGroup()); let agentRole = $derived(project.agentRole); @@ -299,6 +310,13 @@ {#if isAgent && agentRole === 'manager'} {/if} + {#if proAvailable} + + + + + + {/if}
@@ -362,6 +380,31 @@
{/if} + {#if proAvailable && everActivated['analytics']} +
+ +
+ {/if} + {#if proAvailable && everActivated['budget']} +
+ +
+ {/if} + {#if proAvailable && everActivated['export']} +
+ +
+ {/if} + {#if proAvailable && everActivated['symbols']} +
+ +
+ {/if} + {#if proAvailable && everActivated['promemory']} +
+ +
+ {/if}
@@ -470,6 +513,14 @@ color: var(--ctp-text); } + .ptab-pro { + color: var(--ctp-peach); + } + + .ptab-pro:hover { + color: var(--ctp-text); + } + .project-content-area { overflow: hidden; position: relative; diff --git a/src/lib/settings/SettingsPanel.svelte b/src/lib/settings/SettingsPanel.svelte index b64a923..012c14b 100644 --- a/src/lib/settings/SettingsPanel.svelte +++ b/src/lib/settings/SettingsPanel.svelte @@ -9,13 +9,14 @@ import ProjectSettings from './categories/ProjectSettings.svelte'; import OrchestrationSettings from './categories/OrchestrationSettings.svelte'; import AdvancedSettings from './categories/AdvancedSettings.svelte'; + import ProSettings from './categories/ProSettings.svelte'; interface Props { onClose?: () => void; } let { onClose }: Props = $props(); - const CATEGORIES: { id: SettingsCategory; label: string; icon: string }[] = [ + const BASE_CATEGORIES: { id: SettingsCategory; label: string; icon: string }[] = [ { id: 'appearance', label: 'Appearance', icon: '🎨' }, { id: 'agents', label: 'Agents', icon: '🤖' }, { id: 'security', label: 'Security', icon: '🛡' }, @@ -24,6 +25,11 @@ { id: 'advanced', label: 'Advanced', icon: '⚡' }, ]; + let proAvailable = $state(false); + let CATEGORIES = $derived(proAvailable + ? [...BASE_CATEGORIES, { id: 'pro' as SettingsCategory, label: 'Pro', icon: '💎' }] + : BASE_CATEGORIES); + let activeCategory = $state('appearance'); let searchQuery = $state(''); let searchResults = $derived(searchQuery.length >= 2 @@ -78,7 +84,10 @@ } let searchInput: HTMLInputElement | undefined = $state(); - onMount(() => { searchInput?.focus(); }); + onMount(() => { + searchInput?.focus(); + import('../commercial/pro-bridge').then(m => m.proStatus()).then(() => { proAvailable = true; }).catch(() => {}); + });
@@ -142,6 +151,8 @@ {:else if activeCategory === 'advanced'} + {:else if activeCategory === 'pro'} + {/if}
diff --git a/src/lib/settings/categories/ProSettings.svelte b/src/lib/settings/categories/ProSettings.svelte new file mode 100644 index 0000000..6885778 --- /dev/null +++ b/src/lib/settings/categories/ProSettings.svelte @@ -0,0 +1,35 @@ + + +
+
+ + +
+ +
+ {#if activeSection === 'accounts'} + + {:else} + + {/if} +
+
+ + diff --git a/src/lib/settings/settings-registry.ts b/src/lib/settings/settings-registry.ts index 3bf1fee..c18e6a3 100644 --- a/src/lib/settings/settings-registry.ts +++ b/src/lib/settings/settings-registry.ts @@ -9,7 +9,8 @@ export type SettingsCategory = | 'security' | 'projects' | 'orchestration' - | 'advanced'; + | 'advanced' + | 'pro'; export interface SettingEntry { key: string;