@mrpatronz/nexusflow 0.2.18 → 0.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +37 -50
- package/dist/commands/sync.js.map +1 -1
- package/dist/core/sync.d.ts +44 -0
- package/dist/core/sync.d.ts.map +1 -0
- package/dist/core/sync.js +82 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/core/workspace-state.d.ts +51 -0
- package/dist/core/workspace-state.d.ts.map +1 -0
- package/dist/core/workspace-state.js +108 -0
- package/dist/core/workspace-state.js.map +1 -0
- package/dist/core/workspace-state.test.d.ts +2 -0
- package/dist/core/workspace-state.test.d.ts.map +1 -0
- package/dist/core/workspace-state.test.js +84 -0
- package/dist/core/workspace-state.test.js.map +1 -0
- package/dist/gui/assets/index-Bdbld6yY.css +1 -0
- package/dist/gui/assets/index-D8iJPvnk.js +26 -0
- package/dist/gui/index.html +2 -2
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +42 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +94 -13
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/multi-git.d.ts +33 -8
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +91 -19
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/multi-git.test.d.ts +2 -0
- package/dist/utils/multi-git.test.d.ts.map +1 -0
- package/dist/utils/multi-git.test.js +125 -0
- package/dist/utils/multi-git.test.js.map +1 -0
- package/gui/e2e/dashboard.spec.ts +61 -0
- package/gui/e2e/wizard.spec.ts +2 -2
- package/gui/package-lock.json +62 -4
- package/gui/package.json +2 -1
- package/gui/src/App.tsx +168 -227
- package/gui/src/app/AppSidebar.tsx +69 -0
- package/gui/src/components/AddRepoPicker.tsx +81 -0
- package/gui/src/components/ui/Button.tsx +40 -0
- package/gui/src/components/ui/Card.tsx +6 -0
- package/gui/src/components/ui/EmptyState.tsx +22 -0
- package/gui/src/components/ui/Input.tsx +21 -0
- package/gui/src/components/ui/Menu.tsx +71 -0
- package/gui/src/components/ui/Modal.tsx +39 -0
- package/gui/src/components/ui/PageHeader.tsx +21 -0
- package/gui/src/components/ui/RepoStatusStrip.tsx +33 -0
- package/gui/src/components/ui/Skeleton.tsx +5 -0
- package/gui/src/components/ui/StatusPill.tsx +36 -0
- package/gui/src/components/ui/Tabs.tsx +40 -0
- package/gui/src/components/ui/cn.ts +4 -0
- package/gui/src/components/ui/index.ts +16 -0
- package/gui/src/features/services/ServiceConsole.tsx +4 -39
- package/gui/src/index.css +140 -125
- package/gui/src/lib/status.ts +24 -0
- package/gui/src/pages/DashboardPage.tsx +129 -0
- package/gui/src/pages/WorkspacesPage.tsx +352 -0
- package/gui/src/types.ts +19 -0
- package/package.json +1 -1
- package/src/commands/sync.ts +36 -58
- package/src/core/sync.ts +121 -0
- package/src/core/workspace-state.test.ts +108 -0
- package/src/core/workspace-state.ts +130 -0
- package/src/mcp/server.ts +44 -0
- package/src/server.ts +103 -15
- package/src/types.ts +36 -0
- package/src/utils/multi-git.test.ts +158 -0
- package/src/utils/multi-git.ts +117 -25
- package/dist/gui/assets/index-CB-jWded.css +0 -1
- package/dist/gui/assets/index-DDXpZZu3.js +0 -25
- package/gui/src/features/workspace/WorkspaceList.tsx +0 -666
package/gui/src/App.tsx
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
PlusCircle,
|
|
4
|
-
FolderGit2,
|
|
5
4
|
Settings as SettingsIcon,
|
|
6
5
|
Terminal,
|
|
7
6
|
Play,
|
|
@@ -17,12 +16,14 @@ import {
|
|
|
17
16
|
Copy,
|
|
18
17
|
X,
|
|
19
18
|
Cpu,
|
|
20
|
-
Workflow,
|
|
21
19
|
Trash2,
|
|
22
20
|
CheckCircle,
|
|
23
21
|
} from 'lucide-react';
|
|
24
22
|
import './App.css';
|
|
25
|
-
import {
|
|
23
|
+
import { HashRouter, useLocation, useNavigate } from 'react-router-dom';
|
|
24
|
+
import { AppSidebar } from './app/AppSidebar.js';
|
|
25
|
+
import { DashboardPage } from './pages/DashboardPage.js';
|
|
26
|
+
import { WorkspacesPage } from './pages/WorkspacesPage.js';
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
// Types matched with src/types.ts
|
|
@@ -115,12 +116,26 @@ interface RunningService {
|
|
|
115
116
|
startedAt: string;
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
type SyncStatus = 'up-to-date' | 'rebased' | 'conflict' | 'stash-conflict' | 'error';
|
|
120
|
+
|
|
121
|
+
interface WorkspaceStatus {
|
|
122
|
+
id: string;
|
|
123
|
+
branchName: string;
|
|
124
|
+
changedFiles: number;
|
|
125
|
+
dirtyRepos: number;
|
|
126
|
+
runningServices: number;
|
|
127
|
+
syncStatus: SyncStatus | 'unknown';
|
|
128
|
+
pendingValidation: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
118
131
|
const API_BASE = (import.meta.env.DEV || (typeof window !== 'undefined' && (window as any).Neutralino)) ? 'http://localhost:3000' : '';
|
|
119
132
|
const isVsCode = new URLSearchParams(window.location.search).get('env') === 'vscode';
|
|
120
133
|
let toastIdCounter = 0;
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
const
|
|
135
|
+
function AppInner() {
|
|
136
|
+
const navigate = useNavigate();
|
|
137
|
+
const location = useLocation();
|
|
138
|
+
const [view, setView] = useState<'dashboard' | 'guide' | 'create' | 'workspaces' | 'settings' | 'workflows'>('dashboard');
|
|
124
139
|
|
|
125
140
|
// Toast State
|
|
126
141
|
interface Toast {
|
|
@@ -233,6 +248,9 @@ export default function App() {
|
|
|
233
248
|
// Workspaces List
|
|
234
249
|
const [workspaces, setWorkspaces] = useState<Feature[]>([]);
|
|
235
250
|
const [workspacesLoading, setWorkspacesLoading] = useState(false);
|
|
251
|
+
// At-a-glance status per workspace (keyed by branchName), for the listing overview.
|
|
252
|
+
const [workspaceStatuses, setWorkspaceStatuses] = useState<Record<string, WorkspaceStatus>>({});
|
|
253
|
+
const [statusesLoading, setStatusesLoading] = useState(false);
|
|
236
254
|
|
|
237
255
|
// Active Workspace Services / Orchestration Details
|
|
238
256
|
const [activeWsId, setActiveWsId] = useState<string | null>(null);
|
|
@@ -550,6 +568,8 @@ export default function App() {
|
|
|
550
568
|
const res = await fetch(`${API_BASE}/api/workspaces`);
|
|
551
569
|
const data = await res.json();
|
|
552
570
|
setWorkspaces(Array.isArray(data) ? data : []);
|
|
571
|
+
// Refresh at-a-glance status alongside the list (independent endpoint).
|
|
572
|
+
void fetchWorkspaceStatuses();
|
|
553
573
|
} catch (e) {
|
|
554
574
|
console.error(e);
|
|
555
575
|
} finally {
|
|
@@ -557,6 +577,19 @@ export default function App() {
|
|
|
557
577
|
}
|
|
558
578
|
};
|
|
559
579
|
|
|
580
|
+
const fetchWorkspaceStatuses = async () => {
|
|
581
|
+
setStatusesLoading(true);
|
|
582
|
+
try {
|
|
583
|
+
const res = await fetch(`${API_BASE}/api/workspaces/status`);
|
|
584
|
+
const data = await res.json();
|
|
585
|
+
setWorkspaceStatuses(data && typeof data === 'object' && !Array.isArray(data) ? data : {});
|
|
586
|
+
} catch (e) {
|
|
587
|
+
console.error(e);
|
|
588
|
+
} finally {
|
|
589
|
+
setStatusesLoading(false);
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
|
|
560
593
|
const fetchWorkflowTemplates = async () => {
|
|
561
594
|
try {
|
|
562
595
|
const res = await fetch(`${API_BASE}/api/workflows/templates`);
|
|
@@ -1093,11 +1126,27 @@ export default function App() {
|
|
|
1093
1126
|
const queryParams = new URLSearchParams(window.location.search);
|
|
1094
1127
|
const queryWsId = queryParams.get('workspaceId');
|
|
1095
1128
|
if (queryWsId) {
|
|
1096
|
-
|
|
1097
|
-
setView('workspaces');
|
|
1129
|
+
navigate(`/workspaces/${encodeURIComponent(queryWsId)}`);
|
|
1098
1130
|
}
|
|
1099
1131
|
}, []);
|
|
1100
1132
|
|
|
1133
|
+
// Keep the legacy `view` + workspace selection (and their data-loading effects) in sync with the route.
|
|
1134
|
+
useEffect(() => {
|
|
1135
|
+
const p = location.pathname;
|
|
1136
|
+
if (p.startsWith('/workspaces')) {
|
|
1137
|
+
setView('workspaces');
|
|
1138
|
+
const parts = p.split('/').filter(Boolean); // ['workspaces', id?, tab?]
|
|
1139
|
+
setActiveWsId(parts[1] ? decodeURIComponent(parts[1]) : null);
|
|
1140
|
+
const tab = parts[2];
|
|
1141
|
+
const valid = ['overview', 'sessions', 'services', 'changes', 'knowledge', 'plan'];
|
|
1142
|
+
setSubTab((tab && valid.includes(tab) ? tab : 'overview') as typeof subTab);
|
|
1143
|
+
} else if (p.startsWith('/new')) setView('create');
|
|
1144
|
+
else if (p.startsWith('/strategies')) setView('workflows');
|
|
1145
|
+
else if (p.startsWith('/settings')) setView('settings');
|
|
1146
|
+
else if (p.startsWith('/guide')) setView('guide');
|
|
1147
|
+
else setView('dashboard');
|
|
1148
|
+
}, [location.pathname]);
|
|
1149
|
+
|
|
1101
1150
|
// Load tool updates status and LLM recommendations when settings view is open
|
|
1102
1151
|
useEffect(() => {
|
|
1103
1152
|
if (view === 'settings') {
|
|
@@ -1120,9 +1169,9 @@ export default function App() {
|
|
|
1120
1169
|
};
|
|
1121
1170
|
}, [activeWsId]);
|
|
1122
1171
|
|
|
1123
|
-
// Load git changes
|
|
1172
|
+
// Load git changes for the Changes tab and the Overview (per-repo topology panel)
|
|
1124
1173
|
useEffect(() => {
|
|
1125
|
-
if (activeWsId && subTab === 'changes') {
|
|
1174
|
+
if (activeWsId && (subTab === 'changes' || subTab === 'overview')) {
|
|
1126
1175
|
fetchGitChanges(activeWsId);
|
|
1127
1176
|
}
|
|
1128
1177
|
}, [activeWsId, subTab]);
|
|
@@ -1180,12 +1229,12 @@ Workspace Metadata:
|
|
|
1180
1229
|
- Mapped Repositories: ${repoNames}
|
|
1181
1230
|
|
|
1182
1231
|
Core Instructions:
|
|
1183
|
-
1. Always
|
|
1232
|
+
1. Always read and append to "nexusflow-knowledge.md" (persistent workspace memory & decisions) as you progress, and follow the phased order in "nexusflow-plan.md".
|
|
1184
1233
|
2. Read "WORKSPACE.md" at the root for a detailed index of repository relationships, tech stacks, and listening ports.
|
|
1185
1234
|
3. Follow all project-specific rules in "CLAUDE.md", ".cursorrules", or "AGENTS.md" in sub-repositories.
|
|
1186
1235
|
`;
|
|
1187
1236
|
navigator.clipboard.writeText(prompt);
|
|
1188
|
-
showToast('
|
|
1237
|
+
showToast('AI context prompt copied to clipboard!', 'success');
|
|
1189
1238
|
};
|
|
1190
1239
|
|
|
1191
1240
|
const handleDeleteWorkspace = async (wsName: string) => {
|
|
@@ -1508,7 +1557,7 @@ Core Instructions:
|
|
|
1508
1557
|
return (
|
|
1509
1558
|
<div className="flex flex-col h-screen w-full bg-[#060813] text-[#d1d5db] font-mono text-[11px] overflow-hidden select-none border-t border-gray-800">
|
|
1510
1559
|
{/* Terminal Header */}
|
|
1511
|
-
<div className="flex items-center justify-between px-3 py-2 bg-
|
|
1560
|
+
<div className="flex items-center justify-between px-3 py-2 bg-surface border-b border-gray-800 shrink-0 text-[10px]">
|
|
1512
1561
|
<div className="flex items-center gap-2">
|
|
1513
1562
|
<span className="font-bold text-indigo-400">NEXUSFLOW_SHELL</span>
|
|
1514
1563
|
<span className="text-gray-700">|</span>
|
|
@@ -1707,122 +1756,24 @@ Core Instructions:
|
|
|
1707
1756
|
}
|
|
1708
1757
|
|
|
1709
1758
|
return (
|
|
1710
|
-
<div className="flex min-h-screen bg-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
<ul className="flex flex-col gap-2">
|
|
1726
|
-
<li>
|
|
1727
|
-
<button
|
|
1728
|
-
className={`w-full flex items-center gap-3 p-3 rounded-lg text-xs font-bold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1729
|
-
view === 'guide'
|
|
1730
|
-
? 'text-cyan-400 bg-cyan-950/30 border-cyan-900/60 shadow-[0_0_15px_rgba(6,182,212,0.15)]'
|
|
1731
|
-
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40'
|
|
1732
|
-
}`}
|
|
1733
|
-
onClick={() => {
|
|
1734
|
-
setView('guide');
|
|
1735
|
-
}}
|
|
1736
|
-
>
|
|
1737
|
-
<Sparkles size={16} className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
|
1738
|
-
Getting Started
|
|
1739
|
-
</button>
|
|
1740
|
-
</li>
|
|
1741
|
-
<li>
|
|
1742
|
-
<button
|
|
1743
|
-
className={`w-full flex items-center gap-3 p-3 rounded-lg text-xs font-bold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1744
|
-
view === 'create'
|
|
1745
|
-
? 'text-cyan-400 bg-cyan-950/30 border-cyan-900/60 shadow-[0_0_15px_rgba(6,182,212,0.15)]'
|
|
1746
|
-
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40'
|
|
1747
|
-
}`}
|
|
1748
|
-
onClick={() => {
|
|
1749
|
-
setView('create');
|
|
1750
|
-
setActiveStep(0);
|
|
1751
|
-
setCreatedWorkspace(null);
|
|
1752
|
-
setBranchName('');
|
|
1753
|
-
setDescription('');
|
|
1754
|
-
setSelectedRepos([]);
|
|
1755
|
-
setLocalLlmEnabled(config?.localLlm?.enabled || false);
|
|
1756
|
-
}}
|
|
1757
|
-
>
|
|
1758
|
-
<PlusCircle size={16} className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
|
1759
|
-
New Workspace
|
|
1760
|
-
</button>
|
|
1761
|
-
</li>
|
|
1762
|
-
<li>
|
|
1763
|
-
<button
|
|
1764
|
-
className={`w-full flex items-center gap-3 p-3 rounded-lg text-xs font-bold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1765
|
-
view === 'workspaces'
|
|
1766
|
-
? 'text-cyan-400 bg-cyan-950/30 border-cyan-900/60 shadow-[0_0_15px_rgba(6,182,212,0.15)]'
|
|
1767
|
-
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40'
|
|
1768
|
-
}`}
|
|
1769
|
-
onClick={() => {
|
|
1770
|
-
setView('workspaces');
|
|
1771
|
-
fetchWorkspaces();
|
|
1772
|
-
}}
|
|
1773
|
-
>
|
|
1774
|
-
<FolderGit2 size={16} className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
|
1775
|
-
Active Workspaces
|
|
1776
|
-
</button>
|
|
1777
|
-
</li>
|
|
1778
|
-
<li>
|
|
1779
|
-
<button
|
|
1780
|
-
className={`w-full flex items-center gap-3 p-3 rounded-lg text-xs font-bold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1781
|
-
view === 'workflows'
|
|
1782
|
-
? 'text-cyan-400 bg-cyan-950/30 border-cyan-900/60 shadow-[0_0_15px_rgba(6,182,212,0.15)]'
|
|
1783
|
-
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40'
|
|
1784
|
-
}`}
|
|
1785
|
-
onClick={() => {
|
|
1786
|
-
setView('workflows');
|
|
1787
|
-
fetchWorkflowTemplates();
|
|
1788
|
-
if (workflowTemplates.length > 0) {
|
|
1789
|
-
const first = workflowTemplates[0];
|
|
1790
|
-
setSelectedMgtTemplateId(first.id);
|
|
1791
|
-
setMgtTemplateName(first.name);
|
|
1792
|
-
setMgtTemplateContent(first.content);
|
|
1793
|
-
}
|
|
1794
|
-
setAnalysisResult(null);
|
|
1795
|
-
}}
|
|
1796
|
-
>
|
|
1797
|
-
<Workflow size={16} className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
|
1798
|
-
Team Strategies
|
|
1799
|
-
</button>
|
|
1800
|
-
</li>
|
|
1801
|
-
<li>
|
|
1802
|
-
<button
|
|
1803
|
-
className={`w-full flex items-center gap-3 p-3 rounded-lg text-xs font-bold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1804
|
-
view === 'settings'
|
|
1805
|
-
? 'text-cyan-400 bg-cyan-950/30 border-cyan-900/60 shadow-[0_0_15px_rgba(6,182,212,0.15)]'
|
|
1806
|
-
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40'
|
|
1807
|
-
}`}
|
|
1808
|
-
onClick={() => {
|
|
1809
|
-
setView('settings');
|
|
1810
|
-
fetchConfig();
|
|
1811
|
-
}}
|
|
1812
|
-
>
|
|
1813
|
-
<SettingsIcon size={16} className="text-cyan-400 group-hover:scale-110 transition-transform" />
|
|
1814
|
-
Settings
|
|
1815
|
-
</button>
|
|
1816
|
-
</li>
|
|
1817
|
-
</ul>
|
|
1818
|
-
</nav>
|
|
1819
|
-
<div className="pt-6 border-t border-slate-900 text-[10px] text-slate-500 text-center tracking-wider font-semibold uppercase">
|
|
1820
|
-
SYSTEM_UI: ONLINE v{appVersion}
|
|
1821
|
-
</div>
|
|
1822
|
-
</aside>
|
|
1759
|
+
<div className="flex min-h-screen bg-base text-content">
|
|
1760
|
+
<AppSidebar
|
|
1761
|
+
pathname={location.pathname}
|
|
1762
|
+
appVersion={appVersion}
|
|
1763
|
+
onNavigate={navigate}
|
|
1764
|
+
onNewWorkspace={() => {
|
|
1765
|
+
setActiveStep(0);
|
|
1766
|
+
setCreatedWorkspace(null);
|
|
1767
|
+
setBranchName('');
|
|
1768
|
+
setDescription('');
|
|
1769
|
+
setSelectedRepos([]);
|
|
1770
|
+
setLocalLlmEnabled(config?.localLlm?.enabled || false);
|
|
1771
|
+
navigate('/new');
|
|
1772
|
+
}}
|
|
1773
|
+
/>
|
|
1823
1774
|
|
|
1824
1775
|
{/* Main Content Area */}
|
|
1825
|
-
<main className="flex-1
|
|
1776
|
+
<main className="flex-1 overflow-y-auto p-6 sm:p-8">
|
|
1826
1777
|
{configLoading ? (
|
|
1827
1778
|
<div className="flex flex-col items-center justify-center py-40 gap-4 text-gray-400">
|
|
1828
1779
|
<RefreshCw className="animate-spin text-indigo-400" size={32} />
|
|
@@ -1882,6 +1833,26 @@ Core Instructions:
|
|
|
1882
1833
|
</div>
|
|
1883
1834
|
)}
|
|
1884
1835
|
|
|
1836
|
+
{/* View: Dashboard (Overview) */}
|
|
1837
|
+
{view === 'dashboard' && config && (
|
|
1838
|
+
<DashboardPage
|
|
1839
|
+
workspaces={workspaces}
|
|
1840
|
+
workspaceStatuses={workspaceStatuses}
|
|
1841
|
+
workspacesLoading={workspacesLoading}
|
|
1842
|
+
statusesLoading={statusesLoading}
|
|
1843
|
+
onOpenWorkspace={(id) => navigate(`/workspaces/${encodeURIComponent(id)}`)}
|
|
1844
|
+
onNewWorkspace={() => {
|
|
1845
|
+
setActiveStep(0);
|
|
1846
|
+
setCreatedWorkspace(null);
|
|
1847
|
+
setBranchName('');
|
|
1848
|
+
setDescription('');
|
|
1849
|
+
setSelectedRepos([]);
|
|
1850
|
+
setLocalLlmEnabled(config?.localLlm?.enabled || false);
|
|
1851
|
+
navigate('/new');
|
|
1852
|
+
}}
|
|
1853
|
+
/>
|
|
1854
|
+
)}
|
|
1855
|
+
|
|
1885
1856
|
{/* View 0: Getting Started Guide */}
|
|
1886
1857
|
{view === 'guide' && config && (
|
|
1887
1858
|
<div className="max-w-4xl mx-auto">
|
|
@@ -1899,7 +1870,7 @@ Core Instructions:
|
|
|
1899
1870
|
|
|
1900
1871
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-10">
|
|
1901
1872
|
{/* Left: Interactive Stepper */}
|
|
1902
|
-
<div className="bg-
|
|
1873
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-6 shadow-xl backdrop-blur-sm space-y-6">
|
|
1903
1874
|
<h2 className="text-lg font-bold text-white mb-4">NexusFlow Workflows</h2>
|
|
1904
1875
|
|
|
1905
1876
|
<div className="flex gap-4">
|
|
@@ -1943,7 +1914,7 @@ Core Instructions:
|
|
|
1943
1914
|
</div>
|
|
1944
1915
|
|
|
1945
1916
|
{/* Right: Quick actions and Telemetry info */}
|
|
1946
|
-
<div className="bg-
|
|
1917
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-6 shadow-xl backdrop-blur-sm flex flex-col justify-between">
|
|
1947
1918
|
<div>
|
|
1948
1919
|
<h2 className="text-lg font-bold text-white mb-4">Current Configuration</h2>
|
|
1949
1920
|
<div className="space-y-3 text-xs">
|
|
@@ -1969,13 +1940,13 @@ Core Instructions:
|
|
|
1969
1940
|
<div className="pt-6 border-t border-gray-800/60 flex flex-col gap-2">
|
|
1970
1941
|
<button
|
|
1971
1942
|
className="w-full inline-flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-xs font-semibold bg-gradient-to-r from-indigo-500 to-indigo-600 hover:from-indigo-600 hover:to-indigo-700 text-white shadow-md shadow-indigo-500/10 hover:-translate-y-0.5 active:translate-y-0 transition-all cursor-pointer"
|
|
1972
|
-
onClick={() =>
|
|
1943
|
+
onClick={() => navigate('/new')}
|
|
1973
1944
|
>
|
|
1974
1945
|
<PlusCircle size={14} /> Create a Workspace
|
|
1975
1946
|
</button>
|
|
1976
1947
|
<button
|
|
1977
1948
|
className="w-full inline-flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-xs font-semibold bg-gray-900 border border-gray-800 hover:bg-gray-800 hover:border-gray-700 text-white transition-all cursor-pointer"
|
|
1978
|
-
onClick={() =>
|
|
1949
|
+
onClick={() => navigate('/settings')}
|
|
1979
1950
|
>
|
|
1980
1951
|
<SettingsIcon size={14} className="text-gray-500" /> Modify Settings
|
|
1981
1952
|
</button>
|
|
@@ -1984,7 +1955,7 @@ Core Instructions:
|
|
|
1984
1955
|
</div>
|
|
1985
1956
|
|
|
1986
1957
|
{/* Compare dashboard at the bottom */}
|
|
1987
|
-
<div className="bg-
|
|
1958
|
+
<div className="bg-surface/20 border border-gray-800/80 rounded-xl p-6 shadow-md">
|
|
1988
1959
|
<h4 className="text-xs font-semibold uppercase tracking-wider text-gray-500 mb-3">Industry Comparison</h4>
|
|
1989
1960
|
<div className="overflow-x-auto">
|
|
1990
1961
|
<table className="w-full text-[10px] text-gray-400 text-left border-collapse">
|
|
@@ -2047,7 +2018,7 @@ Core Instructions:
|
|
|
2047
2018
|
></div>
|
|
2048
2019
|
<div className="flex flex-col items-center gap-2">
|
|
2049
2020
|
<div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center font-bold text-xs transition-all ${
|
|
2050
|
-
activeStep > 0 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 0 ? 'border-indigo-500 bg-
|
|
2021
|
+
activeStep > 0 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 0 ? 'border-indigo-500 bg-surface text-white shadow-lg shadow-indigo-500/20' : 'border-gray-800 bg-gray-900 text-gray-500'
|
|
2051
2022
|
}`}>
|
|
2052
2023
|
{activeStep > 0 ? <Check size={14} /> : '1'}
|
|
2053
2024
|
</div>
|
|
@@ -2055,7 +2026,7 @@ Core Instructions:
|
|
|
2055
2026
|
</div>
|
|
2056
2027
|
<div className="flex flex-col items-center gap-2">
|
|
2057
2028
|
<div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center font-bold text-xs transition-all ${
|
|
2058
|
-
activeStep > 1 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 1 ? 'border-indigo-500 bg-
|
|
2029
|
+
activeStep > 1 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 1 ? 'border-indigo-500 bg-surface text-white shadow-lg shadow-indigo-500/20' : 'border-gray-800 bg-gray-900 text-gray-500'
|
|
2059
2030
|
}`}>
|
|
2060
2031
|
{activeStep > 1 ? <Check size={14} /> : '2'}
|
|
2061
2032
|
</div>
|
|
@@ -2063,7 +2034,7 @@ Core Instructions:
|
|
|
2063
2034
|
</div>
|
|
2064
2035
|
<div className="flex flex-col items-center gap-2">
|
|
2065
2036
|
<div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center font-bold text-xs transition-all ${
|
|
2066
|
-
activeStep > 2 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 2 ? 'border-indigo-500 bg-
|
|
2037
|
+
activeStep > 2 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 2 ? 'border-indigo-500 bg-surface text-white shadow-lg shadow-indigo-500/20' : 'border-gray-800 bg-gray-900 text-gray-500'
|
|
2067
2038
|
}`}>
|
|
2068
2039
|
{activeStep > 2 ? <Check size={14} /> : '3'}
|
|
2069
2040
|
</div>
|
|
@@ -2071,7 +2042,7 @@ Core Instructions:
|
|
|
2071
2042
|
</div>
|
|
2072
2043
|
<div className="flex flex-col items-center gap-2">
|
|
2073
2044
|
<div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center font-bold text-xs transition-all ${
|
|
2074
|
-
activeStep > 3 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 3 ? 'border-indigo-500 bg-
|
|
2045
|
+
activeStep > 3 ? 'bg-emerald-500 border-emerald-500 text-white' : activeStep === 3 ? 'border-indigo-500 bg-surface text-white shadow-lg shadow-indigo-500/20' : 'border-gray-800 bg-gray-900 text-gray-500'
|
|
2075
2046
|
}`}>
|
|
2076
2047
|
{activeStep > 3 ? <Check size={14} /> : '4'}
|
|
2077
2048
|
</div>
|
|
@@ -2079,7 +2050,7 @@ Core Instructions:
|
|
|
2079
2050
|
</div>
|
|
2080
2051
|
<div className="flex flex-col items-center gap-2">
|
|
2081
2052
|
<div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center font-bold text-xs transition-all ${
|
|
2082
|
-
activeStep === 4 ? 'border-emerald-500 bg-
|
|
2053
|
+
activeStep === 4 ? 'border-emerald-500 bg-surface text-emerald-400 shadow-lg shadow-emerald-500/20' : 'border-gray-800 bg-gray-900 text-gray-500'
|
|
2083
2054
|
}`}>
|
|
2084
2055
|
5
|
|
2085
2056
|
</div>
|
|
@@ -2089,12 +2060,12 @@ Core Instructions:
|
|
|
2089
2060
|
|
|
2090
2061
|
{/* Step 0: Name & Description */}
|
|
2091
2062
|
{activeStep === 0 && (
|
|
2092
|
-
<div className="bg-
|
|
2063
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm">
|
|
2093
2064
|
<div className="mb-6">
|
|
2094
2065
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Feature Branch Name</label>
|
|
2095
2066
|
<input
|
|
2096
2067
|
type="text"
|
|
2097
|
-
className="w-full bg-
|
|
2068
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner"
|
|
2098
2069
|
placeholder="e.g., feature/oauth-authentication-flow"
|
|
2099
2070
|
value={branchName}
|
|
2100
2071
|
onChange={(e) => setBranchName(e.target.value)}
|
|
@@ -2103,7 +2074,7 @@ Core Instructions:
|
|
|
2103
2074
|
<div className="mb-8">
|
|
2104
2075
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Feature Purpose & Context</label>
|
|
2105
2076
|
<textarea
|
|
2106
|
-
className="w-full bg-
|
|
2077
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm min-h-[140px] resize-y shadow-inner"
|
|
2107
2078
|
placeholder="Describe what you want to build. This helps AI assistants analyze context and produce matching plans."
|
|
2108
2079
|
value={description}
|
|
2109
2080
|
onChange={(e) => setDescription(e.target.value)}
|
|
@@ -2123,14 +2094,14 @@ Core Instructions:
|
|
|
2123
2094
|
|
|
2124
2095
|
{/* Step 1: Repo Selector */}
|
|
2125
2096
|
{activeStep === 1 && (
|
|
2126
|
-
<div className="bg-
|
|
2097
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm">
|
|
2127
2098
|
<div className="flex justify-between items-center mb-6">
|
|
2128
2099
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider">Select Repositories</label>
|
|
2129
2100
|
<div className="relative w-64">
|
|
2130
2101
|
<Search size={14} className="absolute left-3 top-3 text-gray-500" />
|
|
2131
2102
|
<input
|
|
2132
2103
|
type="text"
|
|
2133
|
-
className="w-full bg-
|
|
2104
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg pl-9 pr-4 py-2 text-white placeholder-gray-600 transition-all outline-none text-xs"
|
|
2134
2105
|
placeholder="Search repo name..."
|
|
2135
2106
|
value={repoSearch}
|
|
2136
2107
|
onChange={(e) => setRepoSearch(e.target.value)}
|
|
@@ -2150,7 +2121,7 @@ Core Instructions:
|
|
|
2150
2121
|
return (
|
|
2151
2122
|
<div
|
|
2152
2123
|
key={repo.path}
|
|
2153
|
-
className={`bg-
|
|
2124
|
+
className={`bg-surface/60 border rounded-xl p-4 flex items-start gap-3 cursor-pointer hover:bg-gray-800/20 hover:border-gray-700 transition-all ${
|
|
2154
2125
|
isSelected ? 'border-indigo-500 bg-indigo-500/5' : 'border-gray-800/80'
|
|
2155
2126
|
}`}
|
|
2156
2127
|
onClick={() => handleToggleRepo(repo)}
|
|
@@ -2192,7 +2163,7 @@ Core Instructions:
|
|
|
2192
2163
|
|
|
2193
2164
|
{/* Step 2: AI & Editor Settings */}
|
|
2194
2165
|
{activeStep === 2 && (
|
|
2195
|
-
<div className="bg-
|
|
2166
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm">
|
|
2196
2167
|
{creating ? (
|
|
2197
2168
|
<div className="flex flex-col items-center py-6">
|
|
2198
2169
|
<h3 className="text-lg font-bold text-white mb-2 flex items-center gap-2.5">
|
|
@@ -2292,7 +2263,7 @@ Core Instructions:
|
|
|
2292
2263
|
return (
|
|
2293
2264
|
<div
|
|
2294
2265
|
key={ai.name}
|
|
2295
|
-
className={`bg-
|
|
2266
|
+
className={`bg-surface/60 border rounded-xl p-4 flex flex-col gap-3 cursor-pointer hover:border-gray-700 transition-all ${
|
|
2296
2267
|
isSelected ? 'border-indigo-500 bg-indigo-500/5' : 'border-gray-800/80'
|
|
2297
2268
|
}`}
|
|
2298
2269
|
onClick={() => handleToggleAI(ai.name)}
|
|
@@ -2326,7 +2297,7 @@ Core Instructions:
|
|
|
2326
2297
|
return (
|
|
2327
2298
|
<div
|
|
2328
2299
|
key={ed.command}
|
|
2329
|
-
className={`bg-
|
|
2300
|
+
className={`bg-surface/60 border rounded-xl p-4 flex flex-col cursor-pointer hover:border-gray-700 transition-all ${
|
|
2330
2301
|
isSelected ? 'border-indigo-500 bg-indigo-500/5' : 'border-gray-800/80'
|
|
2331
2302
|
}`}
|
|
2332
2303
|
onClick={() => {
|
|
@@ -2348,7 +2319,7 @@ Core Instructions:
|
|
|
2348
2319
|
);
|
|
2349
2320
|
})}
|
|
2350
2321
|
<div
|
|
2351
|
-
className={`bg-
|
|
2322
|
+
className={`bg-surface/60 border rounded-xl p-4 flex flex-col cursor-pointer hover:border-gray-700 transition-all ${
|
|
2352
2323
|
selectedEditor === null ? 'border-indigo-500 bg-indigo-500/5' : 'border-gray-800/80'
|
|
2353
2324
|
}`}
|
|
2354
2325
|
onClick={() => {
|
|
@@ -2459,7 +2430,7 @@ Core Instructions:
|
|
|
2459
2430
|
|
|
2460
2431
|
{/* Step 3: Team Strategy */}
|
|
2461
2432
|
{activeStep === 3 && (
|
|
2462
|
-
<div className="bg-
|
|
2433
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm">
|
|
2463
2434
|
{creating ? (
|
|
2464
2435
|
<div className="flex flex-col items-center py-6">
|
|
2465
2436
|
<h3 className="text-lg font-bold text-white mb-2 flex items-center gap-2.5">
|
|
@@ -2590,7 +2561,7 @@ Core Instructions:
|
|
|
2590
2561
|
return (
|
|
2591
2562
|
<div
|
|
2592
2563
|
key={template.id}
|
|
2593
|
-
className={`bg-
|
|
2564
|
+
className={`bg-surface/60 border rounded-xl p-4 flex flex-col gap-2 cursor-pointer hover:border-gray-700 transition-all ${
|
|
2594
2565
|
isSelected ? 'border-indigo-500 bg-indigo-500/5' : 'border-gray-800/80'
|
|
2595
2566
|
}`}
|
|
2596
2567
|
onClick={() => {
|
|
@@ -2614,7 +2585,7 @@ Core Instructions:
|
|
|
2614
2585
|
You can customize these instructions directly. They will be saved in the workspace context.
|
|
2615
2586
|
</p>
|
|
2616
2587
|
<textarea
|
|
2617
|
-
className="w-full bg-
|
|
2588
|
+
className="w-full bg-surface border border-gray-850 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-605 transition-all outline-none text-xs font-mono min-h-[220px] resize-y shadow-inner leading-relaxed"
|
|
2618
2589
|
value={customTeamworkInstructions}
|
|
2619
2590
|
onChange={(e) => setCustomTeamworkInstructions(e.target.value)}
|
|
2620
2591
|
placeholder="Enter custom instructions for how the AI agents should coordinate..."
|
|
@@ -2651,7 +2622,7 @@ Core Instructions:
|
|
|
2651
2622
|
|
|
2652
2623
|
{/* Step 4: Success Screen */}
|
|
2653
2624
|
{activeStep === 4 && createdWorkspace && (
|
|
2654
|
-
<div className="bg-
|
|
2625
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-10 text-center shadow-xl backdrop-blur-sm">
|
|
2655
2626
|
<div className="inline-flex items-center justify-center p-3 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 mb-6">
|
|
2656
2627
|
<Check size={36} />
|
|
2657
2628
|
</div>
|
|
@@ -2675,9 +2646,8 @@ Core Instructions:
|
|
|
2675
2646
|
<button
|
|
2676
2647
|
className="inline-flex items-center justify-center gap-2 px-5 py-3 rounded-lg text-sm font-semibold bg-gray-900 border border-gray-800 hover:bg-gray-800 hover:border-gray-700 text-white transition-all cursor-pointer"
|
|
2677
2648
|
onClick={() => {
|
|
2678
|
-
setView('workspaces');
|
|
2679
2649
|
fetchWorkspaces();
|
|
2680
|
-
|
|
2650
|
+
navigate(`/workspaces/${encodeURIComponent(branchName)}`);
|
|
2681
2651
|
}}
|
|
2682
2652
|
>
|
|
2683
2653
|
<Terminal size={14} className="text-cyan-400" /> Manage Services
|
|
@@ -2694,69 +2664,32 @@ Core Instructions:
|
|
|
2694
2664
|
</div>
|
|
2695
2665
|
)}
|
|
2696
2666
|
|
|
2697
|
-
{/* View 2: Active Workspaces
|
|
2667
|
+
{/* View 2: Active Workspaces (master-detail) */}
|
|
2698
2668
|
{view === 'workspaces' && (
|
|
2699
|
-
<
|
|
2700
|
-
workspacesLoading={workspacesLoading}
|
|
2669
|
+
<WorkspacesPage
|
|
2701
2670
|
workspaces={workspaces}
|
|
2702
|
-
|
|
2703
|
-
|
|
2671
|
+
workspaceStatuses={workspaceStatuses}
|
|
2672
|
+
statusesLoading={statusesLoading}
|
|
2673
|
+
workspacesLoading={workspacesLoading}
|
|
2674
|
+
fetchWorkspaces={fetchWorkspaces}
|
|
2675
|
+
selectedId={activeWsId}
|
|
2676
|
+
subTab={subTab}
|
|
2677
|
+
onSelect={(id) => navigate(`/workspaces/${encodeURIComponent(id)}`)}
|
|
2678
|
+
onSelectTab={(id, tab) => navigate(`/workspaces/${encodeURIComponent(id)}/${tab}`)}
|
|
2704
2679
|
resumingWs={resumingWs}
|
|
2705
2680
|
handleResumeSession={handleResumeSession}
|
|
2706
2681
|
handleCopyPrompt={handleCopyPrompt}
|
|
2707
2682
|
handleOpenInEditor={handleOpenInEditor}
|
|
2708
|
-
|
|
2709
|
-
aiAssistants={aiAssistants}
|
|
2710
|
-
repos={repos}
|
|
2683
|
+
handleDeleteWorkspace={handleDeleteWorkspace}
|
|
2711
2684
|
deleteWsLoading={deleteWsLoading}
|
|
2685
|
+
repos={repos}
|
|
2712
2686
|
addRepoLoading={addRepoLoading}
|
|
2713
|
-
handleDeleteWorkspace={handleDeleteWorkspace}
|
|
2714
2687
|
handleAddRepo={handleAddRepo}
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
setSelectedLogService={setSelectedLogService}
|
|
2721
|
-
handleStartServices={handleStartServices}
|
|
2722
|
-
handleStopServices={handleStopServices}
|
|
2723
|
-
orchTools={orchTools}
|
|
2724
|
-
servicesLoading={servicesLoading}
|
|
2725
|
-
gitChanges={gitChanges}
|
|
2726
|
-
gitChangesLoading={gitChangesLoading}
|
|
2727
|
-
syncLoading={syncLoading}
|
|
2728
|
-
syncResults={syncResults}
|
|
2729
|
-
commitMessage={commitMessage}
|
|
2730
|
-
showCommitModal={showCommitModal}
|
|
2731
|
-
commitLoading={commitLoading}
|
|
2732
|
-
commitResults={commitResults}
|
|
2733
|
-
setSyncResults={setSyncResults}
|
|
2734
|
-
setCommitResults={setCommitResults}
|
|
2735
|
-
setCommitMessage={setCommitMessage}
|
|
2736
|
-
setShowCommitModal={setShowCommitModal}
|
|
2737
|
-
fetchGitChanges={fetchGitChanges}
|
|
2738
|
-
handleSyncAll={handleSyncAll}
|
|
2739
|
-
handleCommitAll={handleCommitAll}
|
|
2740
|
-
knowledgeContent={knowledgeContent}
|
|
2741
|
-
knowledgeLoading={knowledgeLoading}
|
|
2742
|
-
isEditingKnowledge={isEditingKnowledge}
|
|
2743
|
-
editedKnowledge={editedKnowledge}
|
|
2744
|
-
saveKnowledgeLoading={saveKnowledgeLoading}
|
|
2745
|
-
setEditedKnowledge={setEditedKnowledge}
|
|
2746
|
-
setIsEditingKnowledge={setIsEditingKnowledge}
|
|
2747
|
-
handleSaveKnowledge={handleSaveKnowledge}
|
|
2748
|
-
planContent={planContent}
|
|
2749
|
-
planLoading={planLoading}
|
|
2750
|
-
sessions={sessions}
|
|
2751
|
-
sessionsLoading={sessionsLoading}
|
|
2752
|
-
activeSession={activeSession}
|
|
2753
|
-
transcript={transcript}
|
|
2754
|
-
transcriptLoading={transcriptLoading}
|
|
2755
|
-
setActiveSession={setActiveSession}
|
|
2756
|
-
setTranscript={setTranscript}
|
|
2757
|
-
fetchSessionTranscript={fetchSessionTranscript}
|
|
2758
|
-
subTab={subTab}
|
|
2759
|
-
setSubTab={setSubTab}
|
|
2688
|
+
sessionProps={{ sessions, sessionsLoading, activeSession, transcript, transcriptLoading, workspaces, setActiveSession, setTranscript, fetchSessionTranscript, handleResumeSession }}
|
|
2689
|
+
serviceProps={{ services, runningServices, selectedLogService, serviceLogs, logsEndRef, setSelectedLogService, handleStartServices, handleStopServices, orchTools, servicesLoading }}
|
|
2690
|
+
changesProps={{ gitChanges, gitChangesLoading, syncLoading, syncResults, commitMessage, showCommitModal, commitLoading, commitResults, setSyncResults, setCommitResults, setCommitMessage, setShowCommitModal, fetchGitChanges, handleSyncAll, handleCommitAll }}
|
|
2691
|
+
knowledgeProps={{ knowledgeContent, knowledgeLoading, isEditingKnowledge, editedKnowledge, saveKnowledgeLoading, setEditedKnowledge, setIsEditingKnowledge, handleSaveKnowledge }}
|
|
2692
|
+
planProps={{ planContent, planLoading }}
|
|
2760
2693
|
/>
|
|
2761
2694
|
)}
|
|
2762
2695
|
|
|
@@ -2771,7 +2704,7 @@ Core Instructions:
|
|
|
2771
2704
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 text-left">
|
|
2772
2705
|
{/* Left sidebar: Strategy List */}
|
|
2773
2706
|
<div className="lg:col-span-4 flex flex-col gap-4">
|
|
2774
|
-
<div className="bg-
|
|
2707
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-5 shadow-md flex flex-col gap-4">
|
|
2775
2708
|
<div className="flex justify-between items-center">
|
|
2776
2709
|
<h3 className="text-xs font-semibold uppercase tracking-wider text-gray-500">Strategies</h3>
|
|
2777
2710
|
<button
|
|
@@ -2834,7 +2767,7 @@ Core Instructions:
|
|
|
2834
2767
|
{/* Right side: Strategy Detail / Edit Panel */}
|
|
2835
2768
|
<div className="lg:col-span-8 flex flex-col gap-6">
|
|
2836
2769
|
{(selectedMgtTemplateId || isEditingTemplate) ? (
|
|
2837
|
-
<div className="bg-
|
|
2770
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-6 shadow-md flex flex-col gap-5">
|
|
2838
2771
|
<div className="flex justify-between items-start gap-4">
|
|
2839
2772
|
<div className="flex-1">
|
|
2840
2773
|
{isEditingTemplate ? (
|
|
@@ -2842,7 +2775,7 @@ Core Instructions:
|
|
|
2842
2775
|
<label className="text-xs font-semibold text-gray-400 uppercase tracking-wider">Strategy Name</label>
|
|
2843
2776
|
<input
|
|
2844
2777
|
type="text"
|
|
2845
|
-
className="w-full bg-
|
|
2778
|
+
className="w-full bg-surface border border-gray-850 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-2 text-white text-sm outline-none transition-all"
|
|
2846
2779
|
value={mgtTemplateName}
|
|
2847
2780
|
onChange={(e) => setMgtTemplateName(e.target.value)}
|
|
2848
2781
|
placeholder="e.g. Test-Driven Development"
|
|
@@ -2940,7 +2873,7 @@ Core Instructions:
|
|
|
2940
2873
|
<div className="flex flex-col gap-2">
|
|
2941
2874
|
<label className="text-xs font-semibold text-gray-400 uppercase tracking-wider">Guidelines Markdown</label>
|
|
2942
2875
|
<textarea
|
|
2943
|
-
className="w-full bg-
|
|
2876
|
+
className="w-full bg-surface border border-gray-850 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-xs font-mono min-h-[250px] resize-y shadow-inner leading-relaxed"
|
|
2944
2877
|
value={mgtTemplateContent}
|
|
2945
2878
|
onChange={(e) => setMgtTemplateContent(e.target.value)}
|
|
2946
2879
|
disabled={!isEditingTemplate}
|
|
@@ -3003,7 +2936,7 @@ Core Instructions:
|
|
|
3003
2936
|
<div className="flex flex-col gap-2">
|
|
3004
2937
|
<label className="text-[10px] font-semibold text-gray-400 uppercase tracking-wider text-left">Evaluation Focus / Instructions (Optional)</label>
|
|
3005
2938
|
<textarea
|
|
3006
|
-
className="w-full bg-
|
|
2939
|
+
className="w-full bg-surface/40 border border-gray-850 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-2 text-white placeholder-gray-600 transition-all outline-none text-xs min-h-[60px] resize-y leading-relaxed font-sans"
|
|
3007
2940
|
value={mgtAnalysisComment}
|
|
3008
2941
|
onChange={(e) => setMgtAnalysisComment(e.target.value)}
|
|
3009
2942
|
placeholder="e.g. Focus on checking if timeouts are handled well, check subagent roles coordination..."
|
|
@@ -3039,7 +2972,7 @@ Core Instructions:
|
|
|
3039
2972
|
)}
|
|
3040
2973
|
</div>
|
|
3041
2974
|
) : (
|
|
3042
|
-
<div className="h-[400px] bg-
|
|
2975
|
+
<div className="h-[400px] bg-surface/10 border border-gray-800/60 border-dashed rounded-xl flex flex-col items-center justify-center text-center p-6">
|
|
3043
2976
|
<FolderOpen size={36} className="text-gray-600 mb-3" />
|
|
3044
2977
|
<span className="text-sm font-semibold text-gray-400">No strategy template selected</span>
|
|
3045
2978
|
<p className="text-xs text-gray-500 mt-1 max-w-sm font-sans">
|
|
@@ -3071,12 +3004,12 @@ Core Instructions:
|
|
|
3071
3004
|
</div>
|
|
3072
3005
|
)}
|
|
3073
3006
|
|
|
3074
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 bg-
|
|
3007
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm mb-6">
|
|
3075
3008
|
<div className="flex flex-col">
|
|
3076
3009
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Development Directory</label>
|
|
3077
3010
|
<input
|
|
3078
3011
|
type="text"
|
|
3079
|
-
className="w-full bg-
|
|
3012
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner"
|
|
3080
3013
|
value={config.devDir}
|
|
3081
3014
|
onChange={(e) => setConfig({ ...config, devDir: e.target.value })}
|
|
3082
3015
|
/>
|
|
@@ -3087,7 +3020,7 @@ Core Instructions:
|
|
|
3087
3020
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Workspaces Directory</label>
|
|
3088
3021
|
<input
|
|
3089
3022
|
type="text"
|
|
3090
|
-
className="w-full bg-
|
|
3023
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner"
|
|
3091
3024
|
value={config.workspacesDir}
|
|
3092
3025
|
onChange={(e) => setConfig({ ...config, workspacesDir: e.target.value })}
|
|
3093
3026
|
/>
|
|
@@ -3098,7 +3031,7 @@ Core Instructions:
|
|
|
3098
3031
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Repo Search Depth</label>
|
|
3099
3032
|
<input
|
|
3100
3033
|
type="number"
|
|
3101
|
-
className="w-full bg-
|
|
3034
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner"
|
|
3102
3035
|
min={1}
|
|
3103
3036
|
max={5}
|
|
3104
3037
|
value={config.scanDepth}
|
|
@@ -3110,7 +3043,7 @@ Core Instructions:
|
|
|
3110
3043
|
<div className="flex flex-col">
|
|
3111
3044
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Default Assistant</label>
|
|
3112
3045
|
<select
|
|
3113
|
-
className="w-full bg-
|
|
3046
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white transition-all outline-none text-sm shadow-inner cursor-pointer"
|
|
3114
3047
|
value={config.defaultAssistant || ''}
|
|
3115
3048
|
onChange={(e) => setConfig({ ...config, defaultAssistant: e.target.value || null })}
|
|
3116
3049
|
>
|
|
@@ -3127,7 +3060,7 @@ Core Instructions:
|
|
|
3127
3060
|
<div className="flex flex-col">
|
|
3128
3061
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Default Editor</label>
|
|
3129
3062
|
<select
|
|
3130
|
-
className="w-full bg-
|
|
3063
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white transition-all outline-none text-sm shadow-inner cursor-pointer"
|
|
3131
3064
|
value={config.defaultEditor || ''}
|
|
3132
3065
|
onChange={(e) => setConfig({ ...config, defaultEditor: e.target.value || null })}
|
|
3133
3066
|
>
|
|
@@ -3149,7 +3082,7 @@ Core Instructions:
|
|
|
3149
3082
|
</label>
|
|
3150
3083
|
<select
|
|
3151
3084
|
id="storageProvider"
|
|
3152
|
-
className="w-full max-w-md text-xs bg-
|
|
3085
|
+
className="w-full max-w-md text-xs bg-surface border border-gray-800 rounded-lg p-2 text-white focus:outline-none focus:border-indigo-500"
|
|
3153
3086
|
value={config.storageProvider || 'local'}
|
|
3154
3087
|
onChange={(e) => {
|
|
3155
3088
|
const val = e.target.value;
|
|
@@ -3255,7 +3188,7 @@ Core Instructions:
|
|
|
3255
3188
|
</div>
|
|
3256
3189
|
|
|
3257
3190
|
{/* Local AI Co-Processor Settings */}
|
|
3258
|
-
<div className="bg-
|
|
3191
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm mb-6 mt-6">
|
|
3259
3192
|
<h3 className="text-lg font-bold text-white mb-2">Local AI Co-Processor Settings</h3>
|
|
3260
3193
|
<p className="text-xs text-gray-450 mb-6 font-semibold">Enable a local LLM to handle simple tasks like log analysis, git diff summaries, and boilerplate code generation without using remote tokens.</p>
|
|
3261
3194
|
|
|
@@ -3274,7 +3207,7 @@ Core Instructions:
|
|
|
3274
3207
|
<input
|
|
3275
3208
|
type="checkbox"
|
|
3276
3209
|
id="localLlmEnabled"
|
|
3277
|
-
className="w-4 h-4 rounded border-gray-800 bg-
|
|
3210
|
+
className="w-4 h-4 rounded border-gray-800 bg-surface text-indigo-600 focus:ring-indigo-500 cursor-pointer"
|
|
3278
3211
|
checked={config.localLlm?.enabled || false}
|
|
3279
3212
|
onChange={(e) => {
|
|
3280
3213
|
const defaultLlm = { enabled: e.target.checked, provider: 'ollama' as const, endpoint: 'http://localhost:11434', model: recommendation?.recommendedModel || 'qwen2.5-coder:1.5b' };
|
|
@@ -3295,7 +3228,7 @@ Core Instructions:
|
|
|
3295
3228
|
<div className="flex flex-col">
|
|
3296
3229
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Local Provider</label>
|
|
3297
3230
|
<select
|
|
3298
|
-
className="w-full bg-
|
|
3231
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white transition-all outline-none text-sm shadow-inner cursor-pointer"
|
|
3299
3232
|
value={config.localLlm.provider}
|
|
3300
3233
|
onChange={(e) => setConfig({
|
|
3301
3234
|
...config,
|
|
@@ -3312,7 +3245,7 @@ Core Instructions:
|
|
|
3312
3245
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Endpoint URL</label>
|
|
3313
3246
|
<input
|
|
3314
3247
|
type="text"
|
|
3315
|
-
className={`w-full bg-
|
|
3248
|
+
className={`w-full bg-surface border focus:ring-1 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner ${
|
|
3316
3249
|
config.localLlm.endpoint && !config.localLlm.endpoint.trim().startsWith('http://') && !config.localLlm.endpoint.trim().startsWith('https://')
|
|
3317
3250
|
? 'border-rose-500/60 focus:border-rose-500 focus:ring-rose-500'
|
|
3318
3251
|
: 'border-gray-800 focus:border-indigo-500 focus:ring-indigo-500'
|
|
@@ -3333,7 +3266,7 @@ Core Instructions:
|
|
|
3333
3266
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Model Name</label>
|
|
3334
3267
|
<input
|
|
3335
3268
|
type="text"
|
|
3336
|
-
className="w-full bg-
|
|
3269
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-600 transition-all outline-none text-sm shadow-inner"
|
|
3337
3270
|
value={config.localLlm.model}
|
|
3338
3271
|
onChange={(e) => setConfig({
|
|
3339
3272
|
...config,
|
|
@@ -3348,7 +3281,7 @@ Core Instructions:
|
|
|
3348
3281
|
<label className="block text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">API Key (Optional)</label>
|
|
3349
3282
|
<input
|
|
3350
3283
|
type="password"
|
|
3351
|
-
className="w-full bg-
|
|
3284
|
+
className="w-full bg-surface border border-gray-800 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 rounded-lg px-4 py-3 text-white placeholder-gray-605 transition-all outline-none text-sm shadow-inner"
|
|
3352
3285
|
value={config.localLlm.apiKey || ''}
|
|
3353
3286
|
placeholder="sk-..."
|
|
3354
3287
|
onChange={(e) => setConfig({
|
|
@@ -3396,7 +3329,7 @@ Core Instructions:
|
|
|
3396
3329
|
</div>
|
|
3397
3330
|
|
|
3398
3331
|
{/* Toolchain Updates Section */}
|
|
3399
|
-
<div className="bg-
|
|
3332
|
+
<div className="bg-surface/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm mt-6">
|
|
3400
3333
|
<div className="flex justify-between items-center mb-6">
|
|
3401
3334
|
<div>
|
|
3402
3335
|
<h3 className="text-lg font-bold text-white mb-1">AI Toolchain Updates</h3>
|
|
@@ -3505,7 +3438,7 @@ Core Instructions:
|
|
|
3505
3438
|
{/* Transcript Modal Overlay */}
|
|
3506
3439
|
{activeSession && (
|
|
3507
3440
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/75 backdrop-blur-sm p-4">
|
|
3508
|
-
<div className="bg-
|
|
3441
|
+
<div className="bg-surface border border-gray-800 rounded-2xl w-full max-w-4xl h-[80vh] flex flex-col shadow-2xl overflow-hidden animate-fadeIn">
|
|
3509
3442
|
{/* Modal Header */}
|
|
3510
3443
|
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-800 bg-gray-950/40">
|
|
3511
3444
|
<div>
|
|
@@ -3630,3 +3563,11 @@ Core Instructions:
|
|
|
3630
3563
|
</div>
|
|
3631
3564
|
);
|
|
3632
3565
|
}
|
|
3566
|
+
|
|
3567
|
+
export default function App() {
|
|
3568
|
+
return (
|
|
3569
|
+
<HashRouter>
|
|
3570
|
+
<AppInner />
|
|
3571
|
+
</HashRouter>
|
|
3572
|
+
);
|
|
3573
|
+
}
|