@mrpatronz/nexusflow 0.2.11 → 0.2.13
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/add-repo.d.ts.map +1 -1
- package/dist/commands/add-repo.js +24 -14
- package/dist/commands/add-repo.js.map +1 -1
- package/dist/commands/commit.js +1 -1
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +9 -2
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/diff.js +1 -1
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff.js +1 -1
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/logs.js +1 -1
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +21 -9
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/pack.js +1 -1
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/refresh.js +13 -8
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +12 -7
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/start.js +1 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.js +1 -1
- package/dist/commands/stop.js.map +1 -1
- package/dist/commands/sync.js +13 -8
- package/dist/commands/sync.js.map +1 -1
- package/dist/core/workspace.d.ts +7 -0
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +45 -1
- package/dist/core/workspace.js.map +1 -1
- package/dist/generators/antigravity.d.ts +15 -0
- package/dist/generators/antigravity.d.ts.map +1 -0
- package/dist/generators/antigravity.js +27 -0
- package/dist/generators/antigravity.js.map +1 -0
- package/dist/generators/index.d.ts +1 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +17 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/skills-generator.d.ts.map +1 -1
- package/dist/generators/skills-generator.js +6 -1
- package/dist/generators/skills-generator.js.map +1 -1
- package/dist/gui/assets/index-CFWwqFux.js +23 -0
- package/dist/gui/assets/index-Dvc9QMvl.css +2 -0
- package/dist/gui/index.html +2 -2
- package/dist/orchestration/runner.d.ts +5 -6
- package/dist/orchestration/runner.d.ts.map +1 -1
- package/dist/orchestration/runner.js +105 -102
- package/dist/orchestration/runner.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +57 -2
- package/dist/server.js.map +1 -1
- package/dist/utils/detect-ai.d.ts.map +1 -1
- package/dist/utils/detect-ai.js +4 -1
- package/dist/utils/detect-ai.js.map +1 -1
- package/dist/utils/detect-editors.d.ts.map +1 -1
- package/dist/utils/detect-editors.js +5 -2
- package/dist/utils/detect-editors.js.map +1 -1
- package/dist/utils/detect-editors.test.js +7 -6
- package/dist/utils/detect-editors.test.js.map +1 -1
- package/dist/utils/prompts.d.ts +1 -0
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +77 -15
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/update-check.d.ts.map +1 -1
- package/dist/utils/update-check.js +16 -4
- package/dist/utils/update-check.js.map +1 -1
- package/extension/package.json +9 -0
- package/extension/src/extension.ts +37 -1
- package/gui/eslint.config.js +4 -0
- package/gui/src/App.tsx +375 -151
- package/gui/src/features/changes/ChangesViewer.tsx +246 -70
- package/gui/src/features/services/ServiceConsole.tsx +162 -71
- package/gui/src/features/workspace/WorkspaceList.tsx +184 -32
- package/gui/src/index.css +95 -2
- package/package.json +3 -2
- package/src/commands/add-repo.ts +30 -14
- package/src/commands/commit.ts +1 -1
- package/src/commands/create.ts +9 -2
- package/src/commands/diff.ts +1 -1
- package/src/commands/doctor.ts +1 -1
- package/src/commands/handoff.ts +1 -1
- package/src/commands/logs.ts +1 -1
- package/src/commands/open.ts +24 -9
- package/src/commands/pack.ts +1 -1
- package/src/commands/refresh.ts +16 -8
- package/src/commands/remove.ts +15 -7
- package/src/commands/start.ts +1 -1
- package/src/commands/status.ts +1 -1
- package/src/commands/stop.ts +1 -1
- package/src/commands/sync.ts +16 -8
- package/src/core/workspace.ts +48 -1
- package/src/generators/antigravity.ts +32 -0
- package/src/generators/index.ts +23 -1
- package/src/generators/skills-generator.ts +5 -1
- package/src/orchestration/runner.ts +112 -108
- package/src/server.ts +62 -2
- package/src/utils/detect-ai.ts +4 -1
- package/src/utils/detect-editors.test.ts +7 -6
- package/src/utils/detect-editors.ts +5 -2
- package/src/utils/prompts.ts +88 -14
- package/src/utils/update-check.ts +16 -4
- package/dist/gui/assets/index-Ca2VRMrQ.js +0 -22
- package/dist/gui/assets/index-fj0RJiOb.css +0 -2
package/gui/src/App.tsx
CHANGED
|
@@ -95,6 +95,7 @@ interface RunningService {
|
|
|
95
95
|
|
|
96
96
|
const API_BASE = import.meta.env.DEV ? 'http://localhost:3000' : '';
|
|
97
97
|
const isVsCode = new URLSearchParams(window.location.search).get('env') === 'vscode';
|
|
98
|
+
let toastIdCounter = 0;
|
|
98
99
|
|
|
99
100
|
export default function App() {
|
|
100
101
|
const [view, setView] = useState<'guide' | 'create' | 'workspaces' | 'settings'>('guide');
|
|
@@ -108,7 +109,7 @@ export default function App() {
|
|
|
108
109
|
}
|
|
109
110
|
const [toasts, setToasts] = useState<Toast[]>([]);
|
|
110
111
|
const showToast = (message: string, type: 'success' | 'error' | 'info' = 'info', duration = 5000) => {
|
|
111
|
-
const id =
|
|
112
|
+
const id = `toast-${++toastIdCounter}`;
|
|
112
113
|
setToasts((prev) => [...prev, { id, message, type, duration }]);
|
|
113
114
|
setTimeout(() => {
|
|
114
115
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
@@ -190,7 +191,7 @@ export default function App() {
|
|
|
190
191
|
const [orchTools, setOrchTools] = useState<OrchestrationDetection[]>([]);
|
|
191
192
|
const [runningServices, setRunningServices] = useState<RunningService[]>([]);
|
|
192
193
|
const [servicesLoading, setServicesLoading] = useState(false);
|
|
193
|
-
const [subTab, setSubTab] = useState<'services' | 'changes' | 'sessions' | 'knowledge' | 'plan'>('
|
|
194
|
+
const [subTab, setSubTab] = useState<'overview' | 'services' | 'changes' | 'sessions' | 'knowledge' | 'plan'>('overview');
|
|
194
195
|
const [sessions, setSessions] = useState<any[]>([]);
|
|
195
196
|
const [sessionsLoading, setSessionsLoading] = useState(false);
|
|
196
197
|
const [activeSession, setActiveSession] = useState<any | null>(null);
|
|
@@ -237,86 +238,7 @@ export default function App() {
|
|
|
237
238
|
return true;
|
|
238
239
|
})();
|
|
239
240
|
|
|
240
|
-
//
|
|
241
|
-
useEffect(() => {
|
|
242
|
-
fetchConfig();
|
|
243
|
-
fetchAIAssistants();
|
|
244
|
-
fetchWorkspaces();
|
|
245
|
-
fetchUpdateStatus();
|
|
246
|
-
}, []);
|
|
247
|
-
|
|
248
|
-
// Load tool updates status and LLM recommendations when settings view is open
|
|
249
|
-
useEffect(() => {
|
|
250
|
-
if (view === 'settings') {
|
|
251
|
-
fetchToolsStatus();
|
|
252
|
-
fetchLlmRecommendation();
|
|
253
|
-
}
|
|
254
|
-
}, [view]);
|
|
255
|
-
|
|
256
|
-
// Poll logs and services status when active workspace is open
|
|
257
|
-
useEffect(() => {
|
|
258
|
-
let interval: any = null;
|
|
259
|
-
if (activeWsId) {
|
|
260
|
-
fetchWorkspaceServices(activeWsId);
|
|
261
|
-
interval = setInterval(() => {
|
|
262
|
-
fetchWorkspaceServices(activeWsId, true);
|
|
263
|
-
}, 3000);
|
|
264
|
-
}
|
|
265
|
-
return () => {
|
|
266
|
-
if (interval) clearInterval(interval);
|
|
267
|
-
};
|
|
268
|
-
}, [activeWsId]);
|
|
269
|
-
|
|
270
|
-
// Load git changes when tab switches to 'changes' or active workspace changes
|
|
271
|
-
useEffect(() => {
|
|
272
|
-
if (activeWsId && subTab === 'changes') {
|
|
273
|
-
fetchGitChanges(activeWsId);
|
|
274
|
-
}
|
|
275
|
-
}, [activeWsId, subTab]);
|
|
276
|
-
|
|
277
|
-
// Load sessions when active workspace changes or subTab switches to 'sessions'
|
|
278
|
-
useEffect(() => {
|
|
279
|
-
if (activeWsId && subTab === 'sessions') {
|
|
280
|
-
fetchWorkspaceSessions(activeWsId);
|
|
281
|
-
}
|
|
282
|
-
}, [activeWsId, subTab]);
|
|
283
|
-
|
|
284
|
-
// Load knowledge when subTab switches to 'knowledge' or active workspace changes
|
|
285
|
-
useEffect(() => {
|
|
286
|
-
if (activeWsId && subTab === 'knowledge') {
|
|
287
|
-
fetchKnowledge(activeWsId);
|
|
288
|
-
}
|
|
289
|
-
}, [activeWsId, subTab]);
|
|
290
|
-
|
|
291
|
-
// Load plan when subTab switches to 'plan' or active workspace changes
|
|
292
|
-
useEffect(() => {
|
|
293
|
-
if (activeWsId && subTab === 'plan') {
|
|
294
|
-
fetchPlan(activeWsId);
|
|
295
|
-
}
|
|
296
|
-
}, [activeWsId, subTab]);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
// Poll logs for active service logs
|
|
301
|
-
useEffect(() => {
|
|
302
|
-
let interval: any = null;
|
|
303
|
-
if (activeWsId && selectedLogService) {
|
|
304
|
-
fetchLogs(activeWsId, selectedLogService);
|
|
305
|
-
interval = setInterval(() => {
|
|
306
|
-
fetchLogs(activeWsId, selectedLogService);
|
|
307
|
-
}, 2000);
|
|
308
|
-
}
|
|
309
|
-
return () => {
|
|
310
|
-
if (interval) clearInterval(interval);
|
|
311
|
-
};
|
|
312
|
-
}, [activeWsId, selectedLogService]);
|
|
313
|
-
|
|
314
|
-
// Scroll to bottom of logs when log content changes
|
|
315
|
-
useEffect(() => {
|
|
316
|
-
if (logsEndRef.current) {
|
|
317
|
-
logsEndRef.current.scrollIntoView({ behavior: 'smooth' });
|
|
318
|
-
}
|
|
319
|
-
}, [serviceLogs]);
|
|
241
|
+
// Effects moved below helper functions to resolve lexical declaration order
|
|
320
242
|
|
|
321
243
|
// ─── API Fetches ────────────────────────────────────────────────────────
|
|
322
244
|
|
|
@@ -892,7 +814,106 @@ export default function App() {
|
|
|
892
814
|
}
|
|
893
815
|
};
|
|
894
816
|
|
|
817
|
+
const executeTerminal = (command: string) => {
|
|
818
|
+
if (!activeWsId) return;
|
|
819
|
+
const ws = workspaces.find(w => w.branchName === activeWsId);
|
|
820
|
+
if (ws) {
|
|
821
|
+
window.parent.postMessage({
|
|
822
|
+
type: 'executeTerminalCommand',
|
|
823
|
+
command,
|
|
824
|
+
cwd: ws.workspacePath
|
|
825
|
+
}, '*');
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
|
|
895
830
|
|
|
831
|
+
// Initial loads
|
|
832
|
+
useEffect(() => {
|
|
833
|
+
fetchConfig();
|
|
834
|
+
fetchAIAssistants();
|
|
835
|
+
fetchWorkspaces();
|
|
836
|
+
fetchUpdateStatus();
|
|
837
|
+
|
|
838
|
+
// Support auto-loading workspace from VS Code or URL params
|
|
839
|
+
const queryParams = new URLSearchParams(window.location.search);
|
|
840
|
+
const queryWsId = queryParams.get('workspaceId');
|
|
841
|
+
if (queryWsId) {
|
|
842
|
+
setActiveWsId(queryWsId);
|
|
843
|
+
setView('workspaces');
|
|
844
|
+
}
|
|
845
|
+
}, []);
|
|
846
|
+
|
|
847
|
+
// Load tool updates status and LLM recommendations when settings view is open
|
|
848
|
+
useEffect(() => {
|
|
849
|
+
if (view === 'settings') {
|
|
850
|
+
fetchToolsStatus();
|
|
851
|
+
fetchLlmRecommendation();
|
|
852
|
+
}
|
|
853
|
+
}, [view]);
|
|
854
|
+
|
|
855
|
+
// Poll logs and services status when active workspace is open
|
|
856
|
+
useEffect(() => {
|
|
857
|
+
let interval: any = null;
|
|
858
|
+
if (activeWsId) {
|
|
859
|
+
fetchWorkspaceServices(activeWsId);
|
|
860
|
+
interval = setInterval(() => {
|
|
861
|
+
fetchWorkspaceServices(activeWsId, true);
|
|
862
|
+
}, 3000);
|
|
863
|
+
}
|
|
864
|
+
return () => {
|
|
865
|
+
if (interval) clearInterval(interval);
|
|
866
|
+
};
|
|
867
|
+
}, [activeWsId]);
|
|
868
|
+
|
|
869
|
+
// Load git changes when tab switches to 'changes' or active workspace changes
|
|
870
|
+
useEffect(() => {
|
|
871
|
+
if (activeWsId && subTab === 'changes') {
|
|
872
|
+
fetchGitChanges(activeWsId);
|
|
873
|
+
}
|
|
874
|
+
}, [activeWsId, subTab]);
|
|
875
|
+
|
|
876
|
+
// Load sessions when active workspace changes or subTab switches to 'sessions'
|
|
877
|
+
useEffect(() => {
|
|
878
|
+
if (activeWsId && subTab === 'sessions') {
|
|
879
|
+
fetchWorkspaceSessions(activeWsId);
|
|
880
|
+
}
|
|
881
|
+
}, [activeWsId, subTab]);
|
|
882
|
+
|
|
883
|
+
// Load knowledge when subTab switches to 'knowledge' or active workspace changes
|
|
884
|
+
useEffect(() => {
|
|
885
|
+
if (activeWsId && subTab === 'knowledge') {
|
|
886
|
+
fetchKnowledge(activeWsId);
|
|
887
|
+
}
|
|
888
|
+
}, [activeWsId, subTab]);
|
|
889
|
+
|
|
890
|
+
// Load plan when subTab switches to 'plan' or active workspace changes
|
|
891
|
+
useEffect(() => {
|
|
892
|
+
if (activeWsId && subTab === 'plan') {
|
|
893
|
+
fetchPlan(activeWsId);
|
|
894
|
+
}
|
|
895
|
+
}, [activeWsId, subTab]);
|
|
896
|
+
|
|
897
|
+
// Poll logs for active service logs
|
|
898
|
+
useEffect(() => {
|
|
899
|
+
let interval: any = null;
|
|
900
|
+
if (activeWsId && selectedLogService) {
|
|
901
|
+
fetchLogs(activeWsId, selectedLogService);
|
|
902
|
+
interval = setInterval(() => {
|
|
903
|
+
fetchLogs(activeWsId, selectedLogService);
|
|
904
|
+
}, 2000);
|
|
905
|
+
}
|
|
906
|
+
return () => {
|
|
907
|
+
if (interval) clearInterval(interval);
|
|
908
|
+
};
|
|
909
|
+
}, [activeWsId, selectedLogService]);
|
|
910
|
+
|
|
911
|
+
// Scroll to bottom of logs when log content changes
|
|
912
|
+
useEffect(() => {
|
|
913
|
+
if (logsEndRef.current) {
|
|
914
|
+
logsEndRef.current.scrollIntoView({ behavior: 'smooth' });
|
|
915
|
+
}
|
|
916
|
+
}, [serviceLogs]);
|
|
896
917
|
|
|
897
918
|
const handleCopyPrompt = (ws: Feature) => {
|
|
898
919
|
const repoNames = ws.repos.map((r) => r.split(/[\\/]/).pop()).join(', ');
|
|
@@ -978,68 +999,68 @@ Core Instructions:
|
|
|
978
999
|
const isFormValid = config.devDir.trim() !== '' && config.workspacesDir.trim() !== '';
|
|
979
1000
|
|
|
980
1001
|
return (
|
|
981
|
-
<div className="flex min-h-screen bg-[#
|
|
1002
|
+
<div className="flex min-h-screen bg-[#060813] text-gray-100 font-sans items-center justify-center p-6 bg-gradient-to-br from-[#0b0e24] via-[#060813] to-[#030409]">
|
|
982
1003
|
{/* Onboarding Box */}
|
|
983
|
-
<div className="max-w-6xl w-full
|
|
1004
|
+
<div className="max-w-6xl w-full glass-card border border-slate-800/60 rounded-3xl p-10 shadow-2xl glass-card-glow grid grid-cols-1 lg:grid-cols-12 gap-12 animate-slide-in">
|
|
984
1005
|
|
|
985
1006
|
{/* Left Column: Onboarding Guide & Concepts */}
|
|
986
1007
|
<div className="lg:col-span-7 flex flex-col justify-between">
|
|
987
1008
|
<div>
|
|
988
|
-
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 text-xs font-semibold uppercase tracking-wider mb-
|
|
1009
|
+
<div className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-indigo-500/10 text-indigo-400 border border-indigo-500/20 text-xs font-semibold uppercase tracking-wider mb-5">
|
|
989
1010
|
<Sparkles size={12} className="text-cyan-400 animate-pulse" /> Onboarding Guide
|
|
990
1011
|
</div>
|
|
991
|
-
<h1 className="text-3xl font-extrabold tracking-tight text-white mb-2 bg-gradient-to-r from-white via-
|
|
1012
|
+
<h1 className="text-3xl font-extrabold tracking-tight text-white mb-2 bg-gradient-to-r from-white via-slate-200 to-indigo-300 bg-clip-text text-transparent">
|
|
992
1013
|
Welcome to NexusFlow
|
|
993
1014
|
</h1>
|
|
994
|
-
<p className="text-sm text-
|
|
1015
|
+
<p className="text-sm text-slate-400 mb-8 max-w-xl leading-relaxed">
|
|
995
1016
|
NexusFlow orchestrates multi-repository developer environments. It combines isolated Git worktrees, automatic code analyzer sweeps, and background process running into a single dashboard.
|
|
996
1017
|
</p>
|
|
997
1018
|
|
|
998
1019
|
{/* Onboarding Steps */}
|
|
999
1020
|
<div className="space-y-6">
|
|
1000
|
-
<div className="flex gap-4">
|
|
1001
|
-
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0">
|
|
1021
|
+
<div className="flex gap-4 group">
|
|
1022
|
+
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0 group-hover:bg-indigo-500/20 group-hover:text-indigo-300 transition-colors">
|
|
1002
1023
|
1
|
|
1003
1024
|
</div>
|
|
1004
1025
|
<div>
|
|
1005
|
-
<h3 className="text-sm font-semibold text-white">Configure Development Folders</h3>
|
|
1006
|
-
<p className="text-xs text-
|
|
1026
|
+
<h3 className="text-sm font-semibold text-white group-hover:text-indigo-300 transition-colors">Configure Development Folders</h3>
|
|
1027
|
+
<p className="text-xs text-slate-400 mt-1 leading-relaxed">
|
|
1007
1028
|
Specify your local code path and target workspaces path. For the first setup, these paths start empty so you can explicitly configure them.
|
|
1008
1029
|
</p>
|
|
1009
1030
|
</div>
|
|
1010
1031
|
</div>
|
|
1011
1032
|
|
|
1012
|
-
<div className="flex gap-4">
|
|
1013
|
-
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0">
|
|
1033
|
+
<div className="flex gap-4 group">
|
|
1034
|
+
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0 group-hover:bg-indigo-500/20 group-hover:text-indigo-300 transition-colors">
|
|
1014
1035
|
2
|
|
1015
1036
|
</div>
|
|
1016
1037
|
<div>
|
|
1017
|
-
<h3 className="text-sm font-semibold text-white">Build Isolated Branch Workspaces</h3>
|
|
1018
|
-
<p className="text-xs text-
|
|
1038
|
+
<h3 className="text-sm font-semibold text-white group-hover:text-indigo-300 transition-colors">Build Isolated Branch Workspaces</h3>
|
|
1039
|
+
<p className="text-xs text-slate-400 mt-1 leading-relaxed">
|
|
1019
1040
|
Choose repositories and input your feature branch. NexusFlow runs <code>git worktree</code> to checkout dependencies under a unified folder structure, leaving your primary repository directories clean.
|
|
1020
1041
|
</p>
|
|
1021
1042
|
</div>
|
|
1022
1043
|
</div>
|
|
1023
1044
|
|
|
1024
|
-
<div className="flex gap-4">
|
|
1025
|
-
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0">
|
|
1045
|
+
<div className="flex gap-4 group">
|
|
1046
|
+
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0 group-hover:bg-indigo-500/20 group-hover:text-indigo-300 transition-colors">
|
|
1026
1047
|
3
|
|
1027
1048
|
</div>
|
|
1028
1049
|
<div>
|
|
1029
|
-
<h3 className="text-sm font-semibold text-white">Align AI Coding Contexts</h3>
|
|
1030
|
-
<p className="text-xs text-
|
|
1050
|
+
<h3 className="text-sm font-semibold text-white group-hover:text-indigo-300 transition-colors">Align AI Coding Contexts</h3>
|
|
1051
|
+
<p className="text-xs text-slate-400 mt-1 leading-relaxed">
|
|
1031
1052
|
NexusFlow automatically generates configuration files (<code>CLAUDE.md</code>, <code>.cursorrules</code>, <code>AGENTS.md</code>) that instruct the AI assistant to analyze project inter-dependencies, document its assumptions in <code>nexusflow-overview.md</code>, and highlight clarifying questions.
|
|
1032
1053
|
</p>
|
|
1033
1054
|
</div>
|
|
1034
1055
|
</div>
|
|
1035
1056
|
|
|
1036
|
-
<div className="flex gap-4">
|
|
1037
|
-
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0">
|
|
1057
|
+
<div className="flex gap-4 group">
|
|
1058
|
+
<div className="w-8 h-8 rounded-full bg-indigo-500/10 border border-indigo-500/20 text-indigo-400 flex items-center justify-center font-bold text-sm shrink-0 group-hover:bg-indigo-500/20 group-hover:text-indigo-300 transition-colors">
|
|
1038
1059
|
4
|
|
1039
1060
|
</div>
|
|
1040
1061
|
<div>
|
|
1041
|
-
<h3 className="text-sm font-semibold text-white">Orchestrate Background Services</h3>
|
|
1042
|
-
<p className="text-xs text-
|
|
1062
|
+
<h3 className="text-sm font-semibold text-white group-hover:text-indigo-300 transition-colors">Orchestrate Background Services</h3>
|
|
1063
|
+
<p className="text-xs text-slate-400 mt-1 leading-relaxed">
|
|
1043
1064
|
Run APIs, database scripts, and frontend watch tasks concurrently from the web portal. Monitor real-time logs inside a unified terminal pane.
|
|
1044
1065
|
</p>
|
|
1045
1066
|
</div>
|
|
@@ -1048,12 +1069,12 @@ Core Instructions:
|
|
|
1048
1069
|
</div>
|
|
1049
1070
|
|
|
1050
1071
|
{/* Comparison Dashboard */}
|
|
1051
|
-
<div className="mt-8 pt-6 border-t border-
|
|
1052
|
-
<h4 className="text-xs font-semibold uppercase tracking-wider text-
|
|
1072
|
+
<div className="mt-8 pt-6 border-t border-slate-800/80">
|
|
1073
|
+
<h4 className="text-xs font-semibold uppercase tracking-wider text-slate-500 mb-3">Industry Comparison</h4>
|
|
1053
1074
|
<div className="overflow-x-auto font-sans">
|
|
1054
|
-
<table className="w-full text-[10px] text-
|
|
1075
|
+
<table className="w-full text-[10px] text-slate-400 text-left border-collapse">
|
|
1055
1076
|
<thead>
|
|
1056
|
-
<tr className="border-b border-
|
|
1077
|
+
<tr className="border-b border-slate-800 text-slate-500">
|
|
1057
1078
|
<th className="py-2 pr-4 font-semibold">Orchestrator</th>
|
|
1058
1079
|
<th className="py-2 px-4 font-semibold">Multi-Repo</th>
|
|
1059
1080
|
<th className="py-2 px-4 font-semibold">AI Rules Integration</th>
|
|
@@ -1061,29 +1082,29 @@ Core Instructions:
|
|
|
1061
1082
|
</tr>
|
|
1062
1083
|
</thead>
|
|
1063
1084
|
<tbody>
|
|
1064
|
-
<tr className="border-b border-
|
|
1085
|
+
<tr className="border-b border-slate-850">
|
|
1065
1086
|
<td className="py-2 pr-4 font-semibold text-white">Docker Compose</td>
|
|
1066
1087
|
<td className="py-2 px-4">Yes (Containers only)</td>
|
|
1067
1088
|
<td className="py-2 px-4">No</td>
|
|
1068
1089
|
<td className="py-2 pl-4">Medium (VM overhead)</td>
|
|
1069
1090
|
</tr>
|
|
1070
|
-
<tr className="border-b border-
|
|
1091
|
+
<tr className="border-b border-slate-850">
|
|
1071
1092
|
<td className="py-2 pr-4 font-semibold text-white">Lerna / Turborepo</td>
|
|
1072
1093
|
<td className="py-2 px-4">Monorepo only</td>
|
|
1073
1094
|
<td className="py-2 px-4">No</td>
|
|
1074
1095
|
<td className="py-2 pl-4">Light</td>
|
|
1075
1096
|
</tr>
|
|
1076
|
-
<tr className="border-b border-
|
|
1097
|
+
<tr className="border-b border-slate-850">
|
|
1077
1098
|
<td className="py-2 pr-4 font-semibold text-white">DevPod / Gitpod</td>
|
|
1078
1099
|
<td className="py-2 px-4">Yes (Complex config)</td>
|
|
1079
1100
|
<td className="py-2 px-4">No</td>
|
|
1080
1101
|
<td className="py-2 pl-4">Heavy (Full virtual VM)</td>
|
|
1081
1102
|
</tr>
|
|
1082
1103
|
<tr>
|
|
1083
|
-
<td className="py-2 pr-4 font-semibold text-indigo-400">NexusFlow</td>
|
|
1084
|
-
<td className="py-2 px-4 text-indigo-300">Yes (Native Worktrees)</td>
|
|
1085
|
-
<td className="py-2 px-4 text-indigo-300">Yes (CLAUDE.md/MDC rules)</td>
|
|
1086
|
-
<td className="py-2 pl-4 text-indigo-300">Extremely Light (Native processes)</td>
|
|
1104
|
+
<td className="py-2 pr-4 font-semibold text-indigo-400 text-glow-indigo">NexusFlow</td>
|
|
1105
|
+
<td className="py-2 px-4 text-indigo-300 font-medium">Yes (Native Worktrees)</td>
|
|
1106
|
+
<td className="py-2 px-4 text-indigo-300 font-medium">Yes (CLAUDE.md/MDC rules)</td>
|
|
1107
|
+
<td className="py-2 pl-4 text-indigo-300 font-medium">Extremely Light (Native processes)</td>
|
|
1087
1108
|
</tr>
|
|
1088
1109
|
</tbody>
|
|
1089
1110
|
</table>
|
|
@@ -1093,44 +1114,44 @@ Core Instructions:
|
|
|
1093
1114
|
|
|
1094
1115
|
{/* Right Column: Configuration Form */}
|
|
1095
1116
|
<div className="lg:col-span-5 flex flex-col justify-center">
|
|
1096
|
-
<div className="bg-
|
|
1117
|
+
<div className="bg-slate-950/50 border border-slate-850 rounded-2xl p-8 shadow-xl relative overflow-hidden before:absolute before:inset-0 before:bg-gradient-to-b before:from-indigo-500/5 before:to-transparent before:pointer-events-none">
|
|
1097
1118
|
<h2 className="text-xl font-bold text-white mb-1 flex items-center gap-2">
|
|
1098
1119
|
<SettingsIcon className="text-indigo-400 animate-spin-slow" size={20} /> Initialize Config
|
|
1099
1120
|
</h2>
|
|
1100
|
-
<p className="text-xs text-
|
|
1121
|
+
<p className="text-xs text-slate-500 mb-6">
|
|
1101
1122
|
Define the directories on your machine. The fields are empty so you can provide your paths.
|
|
1102
1123
|
</p>
|
|
1103
1124
|
|
|
1104
1125
|
{/* Form Input fields */}
|
|
1105
1126
|
<div className="space-y-5">
|
|
1106
1127
|
<div>
|
|
1107
|
-
<label className="block text-[
|
|
1128
|
+
<label className="block text-[10px] font-semibold text-slate-400 uppercase tracking-wider mb-2">Development Directory</label>
|
|
1108
1129
|
<input
|
|
1109
1130
|
type="text"
|
|
1110
|
-
className="w-full bg-
|
|
1131
|
+
className="w-full bg-slate-950/60 border border-slate-800 focus:border-indigo-500/80 focus:ring-1 focus:ring-indigo-500/35 rounded-xl px-4 py-3 text-white placeholder-slate-600 transition-all outline-none text-xs shadow-inner"
|
|
1111
1132
|
placeholder="e.g. C:\Users\username\dev"
|
|
1112
1133
|
value={config.devDir}
|
|
1113
1134
|
onChange={(e) => setConfig({ ...config, devDir: e.target.value })}
|
|
1114
1135
|
/>
|
|
1115
1136
|
{defaultPaths && (
|
|
1116
|
-
<div className="text-[10px] text-
|
|
1117
|
-
<span>Suggested: <code>{defaultPaths.devDir}</code></span>
|
|
1137
|
+
<div className="text-[10px] text-slate-500 mt-1.5 flex justify-between items-center">
|
|
1138
|
+
<span>Suggested: <code className="text-indigo-300">{defaultPaths.devDir}</code></span>
|
|
1118
1139
|
</div>
|
|
1119
1140
|
)}
|
|
1120
1141
|
</div>
|
|
1121
1142
|
|
|
1122
1143
|
<div>
|
|
1123
|
-
<label className="block text-[
|
|
1144
|
+
<label className="block text-[10px] font-semibold text-slate-400 uppercase tracking-wider mb-2">Workspaces Directory</label>
|
|
1124
1145
|
<input
|
|
1125
1146
|
type="text"
|
|
1126
|
-
className="w-full bg-
|
|
1147
|
+
className="w-full bg-slate-950/60 border border-slate-800 focus:border-indigo-500/80 focus:ring-1 focus:ring-indigo-500/35 rounded-xl px-4 py-3 text-white placeholder-slate-600 transition-all outline-none text-xs shadow-inner"
|
|
1127
1148
|
placeholder="e.g. C:\Users\username\dev\workspaces"
|
|
1128
1149
|
value={config.workspacesDir}
|
|
1129
1150
|
onChange={(e) => setConfig({ ...config, workspacesDir: e.target.value })}
|
|
1130
1151
|
/>
|
|
1131
1152
|
{defaultPaths && (
|
|
1132
|
-
<div className="text-[10px] text-
|
|
1133
|
-
<span>Suggested: <code>{defaultPaths.workspacesDir}</code></span>
|
|
1153
|
+
<div className="text-[10px] text-slate-500 mt-1.5 flex justify-between items-center">
|
|
1154
|
+
<span>Suggested: <code className="text-indigo-300">{defaultPaths.workspacesDir}</code></span>
|
|
1134
1155
|
</div>
|
|
1135
1156
|
)}
|
|
1136
1157
|
</div>
|
|
@@ -1140,15 +1161,15 @@ Core Instructions:
|
|
|
1140
1161
|
<input
|
|
1141
1162
|
type="checkbox"
|
|
1142
1163
|
id="onboardingPackContextXml"
|
|
1143
|
-
className="w-4 h-4 rounded border-
|
|
1164
|
+
className="w-4 h-4 rounded border-slate-800 bg-slate-950/60 text-indigo-650 focus:ring-indigo-500/50 cursor-pointer"
|
|
1144
1165
|
checked={config.packContextXml || false}
|
|
1145
1166
|
onChange={(e) => setConfig({ ...config, packContextXml: e.target.checked })}
|
|
1146
1167
|
/>
|
|
1147
|
-
<label htmlFor="onboardingPackContextXml" className="text-xs font-semibold text-
|
|
1168
|
+
<label htmlFor="onboardingPackContextXml" className="text-xs font-semibold text-slate-200 cursor-pointer select-none">
|
|
1148
1169
|
Pack Codebase Context with Repomix (XML)
|
|
1149
1170
|
</label>
|
|
1150
1171
|
</div>
|
|
1151
|
-
<span className="text-[10px] text-
|
|
1172
|
+
<span className="text-[10px] text-slate-500 mt-1.5 block leading-normal">
|
|
1152
1173
|
Aggregates all repository files into a single token-efficient XML file (<code>nexusflow-context.xml</code>) at the workspace root, giving AI assistants immediate access to the full codebase state.
|
|
1153
1174
|
</span>
|
|
1154
1175
|
</div>
|
|
@@ -1157,7 +1178,7 @@ Core Instructions:
|
|
|
1157
1178
|
<div className="flex gap-2 pt-2">
|
|
1158
1179
|
<button
|
|
1159
1180
|
type="button"
|
|
1160
|
-
className="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-
|
|
1181
|
+
className="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-2.5 bg-slate-900 border border-slate-800/80 hover:bg-indigo-500/5 hover:border-indigo-500/30 rounded-xl text-xs font-semibold transition-all cursor-pointer text-slate-300 hover:text-white"
|
|
1161
1182
|
onClick={() => {
|
|
1162
1183
|
if (defaultPaths) {
|
|
1163
1184
|
setConfig({
|
|
@@ -1172,7 +1193,7 @@ Core Instructions:
|
|
|
1172
1193
|
</button>
|
|
1173
1194
|
<button
|
|
1174
1195
|
type="button"
|
|
1175
|
-
className="px-3 py-2 bg-
|
|
1196
|
+
className="px-3 py-2.5 bg-slate-900 border border-slate-800/80 hover:bg-rose-500/5 hover:border-rose-500/30 hover:text-rose-400 rounded-xl text-xs font-semibold transition-all cursor-pointer text-slate-400"
|
|
1176
1197
|
onClick={() => {
|
|
1177
1198
|
setConfig({
|
|
1178
1199
|
...config,
|
|
@@ -1189,7 +1210,7 @@ Core Instructions:
|
|
|
1189
1210
|
<div className="pt-4">
|
|
1190
1211
|
<button
|
|
1191
1212
|
type="button"
|
|
1192
|
-
className="w-full inline-flex items-center justify-center gap-2 px-5 py-3 rounded-
|
|
1213
|
+
className="w-full inline-flex items-center justify-center gap-2 px-5 py-3.5 rounded-xl text-sm font-bold bg-gradient-to-r from-indigo-500 via-indigo-600 to-purple-650 hover:from-indigo-600 hover:to-purple-700 text-white shadow-lg shadow-indigo-500/20 hover:-translate-y-0.5 active:translate-y-0 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:translate-y-0 transition-all cursor-pointer"
|
|
1193
1214
|
disabled={!isFormValid}
|
|
1194
1215
|
onClick={() => saveAppConfig(config)}
|
|
1195
1216
|
>
|
|
@@ -1204,41 +1225,243 @@ Core Instructions:
|
|
|
1204
1225
|
);
|
|
1205
1226
|
}
|
|
1206
1227
|
|
|
1228
|
+
if (isVsCode) {
|
|
1229
|
+
return (
|
|
1230
|
+
<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">
|
|
1231
|
+
{/* Terminal Header */}
|
|
1232
|
+
<div className="flex items-center justify-between px-3 py-2 bg-[#0b0f19] border-b border-gray-800 shrink-0 text-[10px]">
|
|
1233
|
+
<div className="flex items-center gap-2">
|
|
1234
|
+
<span className="font-bold text-indigo-400">NEXUSFLOW_SHELL</span>
|
|
1235
|
+
<span className="text-gray-700">|</span>
|
|
1236
|
+
<span className="text-gray-300">ws: {activeWsId || 'none'}</span>
|
|
1237
|
+
</div>
|
|
1238
|
+
<div className="flex items-center gap-2">
|
|
1239
|
+
{activeWsId && (
|
|
1240
|
+
<button
|
|
1241
|
+
onClick={() => {
|
|
1242
|
+
setActiveWsId(null);
|
|
1243
|
+
setSelectedLogService(null);
|
|
1244
|
+
setServiceLogs('');
|
|
1245
|
+
}}
|
|
1246
|
+
className="text-indigo-400 hover:text-indigo-350 hover:underline transition-colors cursor-pointer bg-transparent border-none p-0 outline-none"
|
|
1247
|
+
>
|
|
1248
|
+
[Change WS]
|
|
1249
|
+
</button>
|
|
1250
|
+
)}
|
|
1251
|
+
<span className="text-[10px] text-gray-500">v{appVersion}</span>
|
|
1252
|
+
</div>
|
|
1253
|
+
</div>
|
|
1254
|
+
|
|
1255
|
+
{!activeWsId ? (
|
|
1256
|
+
/* CLI Workspace Selection Menu */
|
|
1257
|
+
<div className="flex-1 flex flex-col items-center justify-center p-6 text-center overflow-y-auto">
|
|
1258
|
+
<div className="text-indigo-400 font-bold mb-4 text-[12px] uppercase">
|
|
1259
|
+
=== Select Active Workspace ===
|
|
1260
|
+
</div>
|
|
1261
|
+
<div className="flex flex-col gap-2 w-full max-w-xs">
|
|
1262
|
+
{workspaces.map((ws) => (
|
|
1263
|
+
<button
|
|
1264
|
+
key={ws.branchName}
|
|
1265
|
+
onClick={() => {
|
|
1266
|
+
setActiveWsId(ws.branchName);
|
|
1267
|
+
fetchWorkspaceServices(ws.branchName);
|
|
1268
|
+
}}
|
|
1269
|
+
className="w-full text-left p-2.5 bg-gray-950 border border-gray-800 hover:border-indigo-500 rounded hover:bg-indigo-500/5 text-gray-300 hover:text-white transition-all text-[11px] cursor-pointer"
|
|
1270
|
+
>
|
|
1271
|
+
> {ws.branchName}
|
|
1272
|
+
</button>
|
|
1273
|
+
))}
|
|
1274
|
+
{workspaces.length === 0 && (
|
|
1275
|
+
<div className="text-gray-550 italic">No workspaces found. Initialize one via the CLI.</div>
|
|
1276
|
+
)}
|
|
1277
|
+
</div>
|
|
1278
|
+
</div>
|
|
1279
|
+
) : (
|
|
1280
|
+
/* Active Workspace Panel */
|
|
1281
|
+
<div className="flex-1 flex flex-col min-h-0">
|
|
1282
|
+
{/* Top Config / Control Panel */}
|
|
1283
|
+
<div className="p-3 border-b border-gray-800 shrink-0 bg-gray-950/30">
|
|
1284
|
+
{/* Service Control Buttons */}
|
|
1285
|
+
<div className="flex gap-2 mb-3">
|
|
1286
|
+
<button
|
|
1287
|
+
onClick={() => handleStartServices(activeWsId)}
|
|
1288
|
+
className="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-1.5 rounded border border-emerald-500/20 bg-emerald-500/5 hover:bg-emerald-500/10 text-emerald-400 font-bold transition-all cursor-pointer text-[10px]"
|
|
1289
|
+
>
|
|
1290
|
+
<Play size={10} /> [START SERVICES]
|
|
1291
|
+
</button>
|
|
1292
|
+
<button
|
|
1293
|
+
onClick={() => handleStopServices(activeWsId)}
|
|
1294
|
+
className="flex-1 inline-flex items-center justify-center gap-1.5 px-3 py-1.5 rounded border border-rose-500/20 bg-rose-500/5 hover:bg-rose-500/10 text-rose-400 font-bold transition-all cursor-pointer text-[10px]"
|
|
1295
|
+
>
|
|
1296
|
+
<X size={10} /> [STOP SERVICES]
|
|
1297
|
+
</button>
|
|
1298
|
+
</div>
|
|
1299
|
+
|
|
1300
|
+
{/* Service List */}
|
|
1301
|
+
<div className="mb-3">
|
|
1302
|
+
<div className="text-[10px] text-gray-400 uppercase font-bold tracking-wider mb-1 px-1">
|
|
1303
|
+
Background Services ({runningServices.filter(rs => rs.pid > 0).length}/{services.length})
|
|
1304
|
+
</div>
|
|
1305
|
+
{services.length === 0 ? (
|
|
1306
|
+
<div className="text-gray-600 italic px-1 text-[10px]">No services detected in workspace.</div>
|
|
1307
|
+
) : (
|
|
1308
|
+
<div className="flex flex-col gap-1 max-h-[120px] overflow-y-auto pr-1">
|
|
1309
|
+
{services.map((service) => {
|
|
1310
|
+
const isRunning = runningServices.some((rs) => rs.name === service.name && rs.pid > 0);
|
|
1311
|
+
const isSelected = selectedLogService === service.name;
|
|
1312
|
+
return (
|
|
1313
|
+
<div
|
|
1314
|
+
key={service.name}
|
|
1315
|
+
onClick={() => setSelectedLogService(service.name)}
|
|
1316
|
+
className={`flex items-center justify-between p-1.5 border rounded cursor-pointer transition-all ${
|
|
1317
|
+
isSelected
|
|
1318
|
+
? 'bg-indigo-950/40 border-indigo-500/50 text-white'
|
|
1319
|
+
: 'bg-gray-950/20 border-gray-800 hover:border-gray-700 text-gray-300'
|
|
1320
|
+
}`}
|
|
1321
|
+
>
|
|
1322
|
+
<div className="flex items-center gap-2 truncate">
|
|
1323
|
+
<span className={`h-1.5 w-1.5 rounded-full ${isRunning ? 'bg-emerald-400 animate-pulse' : 'bg-rose-500'}`}></span>
|
|
1324
|
+
<span className="font-bold truncate">{service.name}</span>
|
|
1325
|
+
</div>
|
|
1326
|
+
<span className="text-[10px] font-mono shrink-0">
|
|
1327
|
+
{isRunning ? (
|
|
1328
|
+
<span className="text-emerald-400 bg-emerald-500/10 px-1 py-0.2 rounded border border-emerald-500/20 text-[8px] font-bold uppercase">on</span>
|
|
1329
|
+
) : (
|
|
1330
|
+
<span className="text-gray-500 bg-gray-900 px-1 py-0.2 rounded border border-gray-800 text-[8px] font-bold uppercase">off</span>
|
|
1331
|
+
)}
|
|
1332
|
+
</span>
|
|
1333
|
+
</div>
|
|
1334
|
+
);
|
|
1335
|
+
})}
|
|
1336
|
+
</div>
|
|
1337
|
+
)}
|
|
1338
|
+
</div>
|
|
1339
|
+
|
|
1340
|
+
{/* MCP Status Check */}
|
|
1341
|
+
<div className="mb-3 border-t border-gray-800 pt-2.5">
|
|
1342
|
+
<div className="text-[10px] text-gray-400 font-bold uppercase mb-1 px-1">
|
|
1343
|
+
Active Local MCP Tools
|
|
1344
|
+
</div>
|
|
1345
|
+
<div className="flex flex-col gap-1 px-1 text-[10px] text-gray-450 font-mono">
|
|
1346
|
+
<div className="flex justify-between">
|
|
1347
|
+
<span>• search_workspace</span>
|
|
1348
|
+
<span className="text-indigo-400 font-bold">READY</span>
|
|
1349
|
+
</div>
|
|
1350
|
+
<div className="flex justify-between">
|
|
1351
|
+
<span>• get_service_logs</span>
|
|
1352
|
+
<span className="text-indigo-400 font-bold">READY</span>
|
|
1353
|
+
</div>
|
|
1354
|
+
<div className="flex justify-between">
|
|
1355
|
+
<span>• delegate_to_local_agent</span>
|
|
1356
|
+
<span className={config?.localLlm?.enabled ? "text-indigo-400 font-bold" : "text-gray-600 font-bold"}>
|
|
1357
|
+
{config?.localLlm?.enabled ? 'READY' : 'DISABLED'}
|
|
1358
|
+
</span>
|
|
1359
|
+
</div>
|
|
1360
|
+
</div>
|
|
1361
|
+
</div>
|
|
1362
|
+
|
|
1363
|
+
{/* Interactive CLI Buttons */}
|
|
1364
|
+
<div className="border-t border-gray-800 pt-2.5">
|
|
1365
|
+
<div className="text-[10px] text-gray-400 font-bold uppercase mb-1.5 px-1">
|
|
1366
|
+
Terminal Commands (Click to Run)
|
|
1367
|
+
</div>
|
|
1368
|
+
<div className="grid grid-cols-2 gap-1.5">
|
|
1369
|
+
<button
|
|
1370
|
+
onClick={() => executeTerminal('nexusflow sync')}
|
|
1371
|
+
className="px-2 py-1.5 text-left border border-gray-850 hover:border-indigo-500 bg-gray-950/40 rounded text-gray-300 hover:text-white hover:bg-indigo-950/20 transition-all font-mono text-[9px] cursor-pointer"
|
|
1372
|
+
>
|
|
1373
|
+
$ nexusflow sync
|
|
1374
|
+
</button>
|
|
1375
|
+
<button
|
|
1376
|
+
onClick={() => executeTerminal('nexusflow diff')}
|
|
1377
|
+
className="px-2 py-1.5 text-left border border-gray-850 hover:border-indigo-500 bg-gray-950/40 rounded text-gray-300 hover:text-white hover:bg-indigo-950/20 transition-all font-mono text-[9px] cursor-pointer"
|
|
1378
|
+
>
|
|
1379
|
+
$ nexusflow diff
|
|
1380
|
+
</button>
|
|
1381
|
+
<button
|
|
1382
|
+
onClick={() => executeTerminal('nexusflow handoff')}
|
|
1383
|
+
className="px-2 py-1.5 text-left border border-gray-850 hover:border-indigo-500 bg-gray-950/40 rounded text-gray-300 hover:text-white hover:bg-indigo-950/20 transition-all font-mono text-[9px] cursor-pointer"
|
|
1384
|
+
>
|
|
1385
|
+
$ nexusflow handoff
|
|
1386
|
+
</button>
|
|
1387
|
+
<button
|
|
1388
|
+
onClick={() => executeTerminal('nexusflow status')}
|
|
1389
|
+
className="px-2 py-1.5 text-left border border-gray-850 hover:border-indigo-500 bg-gray-950/40 rounded text-gray-300 hover:text-white hover:bg-indigo-950/20 transition-all font-mono text-[9px] cursor-pointer"
|
|
1390
|
+
>
|
|
1391
|
+
$ nexusflow status
|
|
1392
|
+
</button>
|
|
1393
|
+
</div>
|
|
1394
|
+
</div>
|
|
1395
|
+
</div>
|
|
1396
|
+
|
|
1397
|
+
{/* Bottom Log Pane */}
|
|
1398
|
+
<div className="flex-1 flex flex-col min-h-0 bg-[#04060d]">
|
|
1399
|
+
<div className="flex items-center justify-between px-3 py-1.5 bg-[#090d1a] border-b border-gray-800/80 shrink-0 text-[9px] text-gray-400 uppercase tracking-wider font-bold">
|
|
1400
|
+
<div className="flex items-center gap-1.5">
|
|
1401
|
+
<span className="h-1.5 w-1.5 rounded-full bg-indigo-500 animate-pulse"></span>
|
|
1402
|
+
<span>log_stream: {selectedLogService || 'none'}</span>
|
|
1403
|
+
</div>
|
|
1404
|
+
<button
|
|
1405
|
+
onClick={() => {
|
|
1406
|
+
if (activeWsId && selectedLogService) {
|
|
1407
|
+
fetchLogs(activeWsId, selectedLogService);
|
|
1408
|
+
}
|
|
1409
|
+
}}
|
|
1410
|
+
className="text-gray-500 hover:text-white font-mono hover:underline cursor-pointer bg-transparent border-none p-0 outline-none"
|
|
1411
|
+
>
|
|
1412
|
+
[refresh]
|
|
1413
|
+
</button>
|
|
1414
|
+
</div>
|
|
1415
|
+
<div className="flex-1 p-3 overflow-y-auto font-mono text-[10px] leading-relaxed whitespace-pre-wrap select-text selection:bg-indigo-500/30 text-gray-300">
|
|
1416
|
+
{serviceLogs.trim() ? (
|
|
1417
|
+
serviceLogs
|
|
1418
|
+
) : (
|
|
1419
|
+
<span className="text-gray-600 italic font-mono">(no logs recorded yet)</span>
|
|
1420
|
+
)}
|
|
1421
|
+
<div ref={logsEndRef} />
|
|
1422
|
+
</div>
|
|
1423
|
+
</div>
|
|
1424
|
+
</div>
|
|
1425
|
+
)}
|
|
1426
|
+
</div>
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1207
1430
|
return (
|
|
1208
1431
|
<div className="flex min-h-screen bg-[#060813] bg-gradient-to-br from-[#0c0f24] via-[#060813] to-[#04050a] text-gray-100 font-sans">
|
|
1209
1432
|
{/* Sidebar Navigation */}
|
|
1210
|
-
<aside className="w-64 bg-
|
|
1433
|
+
<aside className="w-64 bg-slate-950/40 border-r border-slate-900 flex flex-col p-6 shrink-0 shadow-[0_0_50px_rgba(0,0,0,0.8)] backdrop-blur-xl relative z-10">
|
|
1211
1434
|
<div className="flex items-center gap-3 mb-10 px-2">
|
|
1212
|
-
<div className="w-9 h-9 bg-gradient-to-tr from-cyan-400 via-indigo-500 to-purple-
|
|
1435
|
+
<div className="w-9 h-9 bg-gradient-to-tr from-cyan-400 via-indigo-500 to-purple-650 rounded-lg flex items-center justify-center font-extrabold text-white shadow-lg shadow-indigo-500/25 text-lg select-none">
|
|
1213
1436
|
N
|
|
1214
1437
|
</div>
|
|
1215
|
-
<span className="text-xl font-bold tracking-tight bg-gradient-to-r from-white via-
|
|
1438
|
+
<span className="text-xl font-bold tracking-tight bg-gradient-to-r from-white via-slate-200 to-slate-400 bg-clip-text text-transparent">
|
|
1216
1439
|
NexusFlow
|
|
1217
1440
|
</span>
|
|
1218
1441
|
</div>
|
|
1219
1442
|
<nav className="flex-1">
|
|
1220
|
-
<ul className="flex flex-col gap-2">
|
|
1443
|
+
<ul className="flex flex-col gap-2.5">
|
|
1221
1444
|
<li>
|
|
1222
1445
|
<button
|
|
1223
|
-
className={`w-full flex items-center gap-3 p-3 rounded-
|
|
1446
|
+
className={`w-full flex items-center gap-3 p-3 rounded-xl text-sm font-semibold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1224
1447
|
view === 'guide'
|
|
1225
|
-
? 'text-white bg-indigo-500/10 border-indigo-500/
|
|
1226
|
-
: 'text-
|
|
1448
|
+
? 'text-white bg-indigo-500/10 border-indigo-500/25 shadow-[0_0_20px_rgba(99,102,241,0.08)] before:absolute before:left-0 before:top-2 before:bottom-2 before:w-[3.5px] before:bg-indigo-500 before:rounded-r'
|
|
1449
|
+
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40 hover:-translate-x-0.5'
|
|
1227
1450
|
}`}
|
|
1228
1451
|
onClick={() => {
|
|
1229
1452
|
setView('guide');
|
|
1230
1453
|
}}
|
|
1231
1454
|
>
|
|
1232
|
-
<Sparkles size={18} className="text-indigo-400" />
|
|
1455
|
+
<Sparkles size={18} className="text-indigo-400 group-hover:scale-110 transition-transform" />
|
|
1233
1456
|
Getting Started
|
|
1234
1457
|
</button>
|
|
1235
1458
|
</li>
|
|
1236
1459
|
<li>
|
|
1237
1460
|
<button
|
|
1238
|
-
className={`w-full flex items-center gap-3 p-3 rounded-
|
|
1461
|
+
className={`w-full flex items-center gap-3 p-3 rounded-xl text-sm font-semibold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1239
1462
|
view === 'create'
|
|
1240
|
-
? 'text-white bg-indigo-500/10 border-indigo-500/
|
|
1241
|
-
: 'text-
|
|
1463
|
+
? 'text-white bg-indigo-500/10 border-indigo-500/25 shadow-[0_0_20px_rgba(99,102,241,0.08)] before:absolute before:left-0 before:top-2 before:bottom-2 before:w-[3.5px] before:bg-indigo-500 before:rounded-r'
|
|
1464
|
+
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40 hover:-translate-x-0.5'
|
|
1242
1465
|
}`}
|
|
1243
1466
|
onClick={() => {
|
|
1244
1467
|
setView('create');
|
|
@@ -1250,45 +1473,45 @@ Core Instructions:
|
|
|
1250
1473
|
setLocalLlmEnabled(config?.localLlm?.enabled || false);
|
|
1251
1474
|
}}
|
|
1252
1475
|
>
|
|
1253
|
-
<PlusCircle size={18} className="text-indigo-400" />
|
|
1476
|
+
<PlusCircle size={18} className="text-indigo-400 group-hover:scale-110 transition-transform" />
|
|
1254
1477
|
New Workspace
|
|
1255
1478
|
</button>
|
|
1256
1479
|
</li>
|
|
1257
1480
|
<li>
|
|
1258
1481
|
<button
|
|
1259
|
-
className={`w-full flex items-center gap-3 p-3 rounded-
|
|
1482
|
+
className={`w-full flex items-center gap-3 p-3 rounded-xl text-sm font-semibold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1260
1483
|
view === 'workspaces'
|
|
1261
|
-
? 'text-white bg-indigo-500/10 border-indigo-500/
|
|
1262
|
-
: 'text-
|
|
1484
|
+
? 'text-white bg-indigo-500/10 border-indigo-500/25 shadow-[0_0_20px_rgba(99,102,241,0.08)] before:absolute before:left-0 before:top-2 before:bottom-2 before:w-[3.5px] before:bg-indigo-500 before:rounded-r'
|
|
1485
|
+
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40 hover:-translate-x-0.5'
|
|
1263
1486
|
}`}
|
|
1264
1487
|
onClick={() => {
|
|
1265
1488
|
setView('workspaces');
|
|
1266
1489
|
fetchWorkspaces();
|
|
1267
1490
|
}}
|
|
1268
1491
|
>
|
|
1269
|
-
<FolderGit2 size={18} className="text-indigo-400" />
|
|
1492
|
+
<FolderGit2 size={18} className="text-indigo-400 group-hover:scale-110 transition-transform" />
|
|
1270
1493
|
Active Workspaces
|
|
1271
1494
|
</button>
|
|
1272
1495
|
</li>
|
|
1273
1496
|
<li>
|
|
1274
1497
|
<button
|
|
1275
|
-
className={`w-full flex items-center gap-3 p-3 rounded-
|
|
1498
|
+
className={`w-full flex items-center gap-3 p-3 rounded-xl text-sm font-semibold transition-all cursor-pointer border relative overflow-hidden group ${
|
|
1276
1499
|
view === 'settings'
|
|
1277
|
-
? 'text-white bg-indigo-500/10 border-indigo-500/
|
|
1278
|
-
: 'text-
|
|
1500
|
+
? 'text-white bg-indigo-500/10 border-indigo-500/25 shadow-[0_0_20px_rgba(99,102,241,0.08)] before:absolute before:left-0 before:top-2 before:bottom-2 before:w-[3.5px] before:bg-indigo-500 before:rounded-r'
|
|
1501
|
+
: 'text-slate-400 border-transparent hover:text-white hover:bg-slate-900/40 hover:-translate-x-0.5'
|
|
1279
1502
|
}`}
|
|
1280
1503
|
onClick={() => {
|
|
1281
1504
|
setView('settings');
|
|
1282
1505
|
fetchConfig();
|
|
1283
1506
|
}}
|
|
1284
1507
|
>
|
|
1285
|
-
<SettingsIcon size={18} className="text-indigo-400" />
|
|
1508
|
+
<SettingsIcon size={18} className="text-indigo-400 group-hover:scale-110 transition-transform" />
|
|
1286
1509
|
Settings
|
|
1287
1510
|
</button>
|
|
1288
1511
|
</li>
|
|
1289
1512
|
</ul>
|
|
1290
1513
|
</nav>
|
|
1291
|
-
<div className="pt-6 border-t border-
|
|
1514
|
+
<div className="pt-6 border-t border-slate-900 text-[10px] text-slate-500 text-center tracking-wider font-semibold uppercase">
|
|
1292
1515
|
NexusFlow Engine v{appVersion}
|
|
1293
1516
|
</div>
|
|
1294
1517
|
</aside>
|
|
@@ -1975,6 +2198,7 @@ Core Instructions:
|
|
|
1975
2198
|
handleCopyPrompt={handleCopyPrompt}
|
|
1976
2199
|
handleOpenInEditor={handleOpenInEditor}
|
|
1977
2200
|
fetchWorkspaces={fetchWorkspaces}
|
|
2201
|
+
aiAssistants={aiAssistants}
|
|
1978
2202
|
repos={repos}
|
|
1979
2203
|
deleteWsLoading={deleteWsLoading}
|
|
1980
2204
|
addRepoLoading={addRepoLoading}
|