@mrpatronz/nexusflow 0.1.9 → 0.1.10

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.
Files changed (46) hide show
  1. package/dist/commands/add-repo.d.ts +12 -0
  2. package/dist/commands/add-repo.d.ts.map +1 -0
  3. package/dist/commands/add-repo.js +126 -0
  4. package/dist/commands/add-repo.js.map +1 -0
  5. package/dist/commands/remove.d.ts +11 -0
  6. package/dist/commands/remove.d.ts.map +1 -0
  7. package/dist/commands/remove.js +82 -0
  8. package/dist/commands/remove.js.map +1 -0
  9. package/dist/core/workspace.d.ts +20 -0
  10. package/dist/core/workspace.d.ts.map +1 -1
  11. package/dist/core/workspace.js +127 -1
  12. package/dist/core/workspace.js.map +1 -1
  13. package/dist/core/worktree.d.ts +3 -2
  14. package/dist/core/worktree.d.ts.map +1 -1
  15. package/dist/core/worktree.js +9 -3
  16. package/dist/core/worktree.js.map +1 -1
  17. package/dist/generators/base.d.ts.map +1 -1
  18. package/dist/generators/base.js +9 -0
  19. package/dist/generators/base.js.map +1 -1
  20. package/dist/gui/assets/index-C8W6FoPa.js +21 -0
  21. package/dist/gui/assets/index-CJn2LW8K.css +2 -0
  22. package/dist/gui/index.html +2 -2
  23. package/dist/index.js +39 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/server.d.ts.map +1 -1
  26. package/dist/server.js +70 -2
  27. package/dist/server.js.map +1 -1
  28. package/dist/utils/update-check.d.ts +11 -0
  29. package/dist/utils/update-check.d.ts.map +1 -1
  30. package/dist/utils/update-check.js +105 -0
  31. package/dist/utils/update-check.js.map +1 -1
  32. package/extension/package-lock.json +8 -8
  33. package/extension/package.json +1 -1
  34. package/gui/src/App.tsx +268 -6
  35. package/gui/src/features/workspace/WorkspaceList.tsx +58 -8
  36. package/package.json +1 -1
  37. package/src/commands/add-repo.ts +141 -0
  38. package/src/commands/remove.ts +90 -0
  39. package/src/core/workspace.ts +142 -2
  40. package/src/core/worktree.ts +10 -2
  41. package/src/generators/base.ts +9 -0
  42. package/src/index.ts +39 -0
  43. package/src/server.ts +73 -2
  44. package/src/utils/update-check.ts +116 -0
  45. package/dist/gui/assets/index-7IR7ZrSG.css +0 -2
  46. package/dist/gui/assets/index-BfNp4LNj.js +0 -21
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/utils/update-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../../src/utils/update-check.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  "devDependencies": {
11
11
  "@types/glob": "^8.1.0",
12
12
  "@types/mocha": "^10.0.1",
13
- "@types/node": "18.x",
13
+ "@types/node": "25.x",
14
14
  "@types/vscode": "^1.80.0",
15
15
  "@typescript-eslint/eslint-plugin": "^5.59.8",
16
16
  "@typescript-eslint/parser": "^5.59.8",
@@ -196,13 +196,13 @@
196
196
  "license": "MIT"
197
197
  },
198
198
  "node_modules/@types/node": {
199
- "version": "18.19.130",
200
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
201
- "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
199
+ "version": "25.9.1",
200
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz",
201
+ "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==",
202
202
  "dev": true,
203
203
  "license": "MIT",
204
204
  "dependencies": {
205
- "undici-types": "~5.26.4"
205
+ "undici-types": ">=7.24.0 <7.24.7"
206
206
  }
207
207
  },
208
208
  "node_modules/@types/semver": {
@@ -2614,9 +2614,9 @@
2614
2614
  }
2615
2615
  },
2616
2616
  "node_modules/undici-types": {
2617
- "version": "5.26.5",
2618
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
2619
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
2617
+ "version": "7.24.6",
2618
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
2619
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
2620
2620
  "dev": true,
2621
2621
  "license": "MIT"
2622
2622
  },
@@ -49,7 +49,7 @@
49
49
  "@types/vscode": "^1.80.0",
50
50
  "@types/glob": "^8.1.0",
51
51
  "@types/mocha": "^10.0.1",
52
- "@types/node": "18.x",
52
+ "@types/node": "25.x",
53
53
  "@typescript-eslint/eslint-plugin": "^5.59.8",
54
54
  "@typescript-eslint/parser": "^5.59.8",
55
55
  "eslint": "^8.41.0",
package/gui/src/App.tsx CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  Save,
26
26
  Edit,
27
27
  Download,
28
+ Trash2,
28
29
  } from 'lucide-react';
29
30
  import './App.css';
30
31
 
@@ -135,6 +136,10 @@ export default function App() {
135
136
  { id: 'pack', name: 'Pack Codebase Context', status: 'pending', message: 'Waiting...' },
136
137
  ]);
137
138
 
139
+ const [toolsStatus, setToolsStatus] = useState<any[]>([]);
140
+ const [toolsLoading, setToolsLoading] = useState(false);
141
+ const [updatingToolId, setUpdatingToolId] = useState<string | null>(null);
142
+
138
143
  // Resumption Commands State
139
144
  const [testCommand, setTestCommand] = useState('npm run test');
140
145
  const [mockCommand, setMockCommand] = useState('');
@@ -187,6 +192,8 @@ export default function App() {
187
192
  const [showCommitModal, setShowCommitModal] = useState<boolean>(false);
188
193
  const [commitLoading, setCommitLoading] = useState<boolean>(false);
189
194
  const [commitResults, setCommitResults] = useState<any[] | null>(null);
195
+ const [deleteWsLoading, setDeleteWsLoading] = useState<string | null>(null);
196
+ const [addRepoLoading, setAddRepoLoading] = useState<boolean>(false);
190
197
 
191
198
 
192
199
  // Log Viewer
@@ -203,6 +210,13 @@ export default function App() {
203
210
  fetchUpdateStatus();
204
211
  }, []);
205
212
 
213
+ // Load tool updates status when settings view is open
214
+ useEffect(() => {
215
+ if (view === 'settings') {
216
+ fetchToolsStatus();
217
+ }
218
+ }, [view]);
219
+
206
220
  // Poll logs and services status when active workspace is open
207
221
  useEffect(() => {
208
222
  let interval: any = null;
@@ -285,6 +299,45 @@ export default function App() {
285
299
  }
286
300
  };
287
301
 
302
+ const fetchToolsStatus = async (force = false) => {
303
+ setToolsLoading(true);
304
+ try {
305
+ const res = await fetch(`${API_BASE}/api/updates/tools${force ? '?force=true' : ''}`);
306
+ if (res.ok) {
307
+ const data = await res.json();
308
+ setToolsStatus(data);
309
+ }
310
+ } catch (e) {
311
+ console.error('Failed to fetch tools status:', e);
312
+ } finally {
313
+ setToolsLoading(false);
314
+ }
315
+ };
316
+
317
+ const handleUpdateTool = async (toolId: string) => {
318
+ setUpdatingToolId(toolId);
319
+ try {
320
+ const res = await fetch(`${API_BASE}/api/updates/install`, {
321
+ method: 'POST',
322
+ headers: { 'Content-Type': 'application/json' },
323
+ body: JSON.stringify({ toolId }),
324
+ });
325
+ const data = await res.json();
326
+ if (res.ok && data.success) {
327
+ alert(`${toolId} updated successfully!\n\nOutput:\n${data.output}`);
328
+ fetchToolsStatus(true);
329
+ fetchUpdateStatus();
330
+ } else {
331
+ alert(`Error: ${data.error || 'Failed to update tool'}`);
332
+ }
333
+ } catch (e) {
334
+ console.error(e);
335
+ alert('Network error when updating tool.');
336
+ } finally {
337
+ setUpdatingToolId(null);
338
+ }
339
+ };
340
+
288
341
  const fetchConfig = async () => {
289
342
  try {
290
343
  const res = await fetch(`${API_BASE}/api/config`);
@@ -778,6 +831,63 @@ Core Instructions:
778
831
  alert('Universal AI briefing prompt copied to clipboard!');
779
832
  };
780
833
 
834
+ const handleDeleteWorkspace = async (wsName: string) => {
835
+ if (!window.confirm(`Are you sure you want to delete the workspace "${wsName}"?\nThis will force remove all git worktrees inside it and delete all files in the folder.`)) {
836
+ return;
837
+ }
838
+ setDeleteWsLoading(wsName);
839
+ try {
840
+ const encodedId = encodeURIComponent(wsName);
841
+ const res = await fetch(`${API_BASE}/api/workspace/${encodedId}`, {
842
+ method: 'DELETE',
843
+ });
844
+ const data = await res.json();
845
+ if (res.ok && data.success) {
846
+ if (activeWsId === wsName) {
847
+ setActiveWsId(null);
848
+ }
849
+ await fetchWorkspaces();
850
+ alert(`Workspace ${wsName} successfully deleted.`);
851
+ } else {
852
+ alert(`Failed to delete workspace: ${data.error || 'Unknown error'}`);
853
+ }
854
+ } catch (e) {
855
+ console.error(e);
856
+ alert('Network error while deleting workspace.');
857
+ } finally {
858
+ setDeleteWsLoading(null);
859
+ }
860
+ };
861
+
862
+ const handleAddRepo = async (wsName: string, repoPath: string) => {
863
+ setAddRepoLoading(true);
864
+ try {
865
+ const encodedId = encodeURIComponent(wsName);
866
+ const res = await fetch(`${API_BASE}/api/workspace/${encodedId}/repo`, {
867
+ method: 'POST',
868
+ headers: { 'Content-Type': 'application/json' },
869
+ body: JSON.stringify({ repoPath }),
870
+ });
871
+ const data = await res.json();
872
+ if (res.ok && data.success) {
873
+ await fetchWorkspaces();
874
+ if (activeWsId === wsName) {
875
+ fetchWorkspaceServices(wsName, true);
876
+ fetchGitChanges(wsName);
877
+ fetchWorkspaceSessions(wsName);
878
+ }
879
+ alert('Repository successfully added. Configurations and Repomix packing updated.');
880
+ } else {
881
+ alert(`Failed to add repository: ${data.error || 'Unknown error'}`);
882
+ }
883
+ } catch (e) {
884
+ console.error(e);
885
+ alert('Network error while adding repository.');
886
+ } finally {
887
+ setAddRepoLoading(false);
888
+ }
889
+ };
890
+
781
891
  const filteredRepos = repos.filter((r) =>
782
892
  r.name.toLowerCase().includes(repoSearch.toLowerCase())
783
893
  );
@@ -1177,6 +1287,18 @@ Core Instructions:
1177
1287
  </p>
1178
1288
  </div>
1179
1289
  </div>
1290
+
1291
+ <div className="flex gap-4">
1292
+ <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">
1293
+ 4
1294
+ </div>
1295
+ <div>
1296
+ <h3 className="text-sm font-semibold text-white">Repomix Packing</h3>
1297
+ <p className="text-xs text-gray-400 mt-1">
1298
+ NexusFlow aggregates the entire multi-repo codebase using <code>Repomix</code> into a token-efficient XML file <code>nexusflow-context.xml</code>, giving AI immediate access to the full codebase state.
1299
+ </p>
1300
+ </div>
1301
+ </div>
1180
1302
  </div>
1181
1303
 
1182
1304
  {/* Right: Quick actions and Telemetry info */}
@@ -1783,6 +1905,14 @@ Core Instructions:
1783
1905
  >
1784
1906
  {isExpanded ? 'Hide Runner' : 'Orchestrate'}
1785
1907
  </button>
1908
+ <button
1909
+ className="inline-flex items-center justify-center gap-1.5 px-3.5 py-2 bg-red-950/40 border border-red-900/60 hover:bg-red-900/60 hover:border-red-800 rounded-lg text-xs font-semibold text-red-200 transition-all cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed animate-fade-in"
1910
+ onClick={() => handleDeleteWorkspace(ws.branchName)}
1911
+ disabled={deleteWsLoading === ws.branchName}
1912
+ >
1913
+ <Trash2 size={12} className={deleteWsLoading === ws.branchName ? 'animate-spin' : ''} />
1914
+ {deleteWsLoading === ws.branchName ? 'Deleting...' : 'Delete'}
1915
+ </button>
1786
1916
  </div>
1787
1917
  </div>
1788
1918
 
@@ -1790,12 +1920,42 @@ Core Instructions:
1790
1920
  {ws.description}
1791
1921
  </p>
1792
1922
 
1793
- <div className="flex flex-wrap gap-2 mb-4">
1794
- {ws.repos.map((repoPath) => (
1795
- <span key={repoPath} className="text-[10px] px-2.5 py-1 bg-gray-900 border border-gray-800 text-gray-300 rounded-md font-semibold">
1796
- {repoPath.split(/[\\/]/).pop()}
1797
- </span>
1798
- ))}
1923
+ <div className="flex items-center gap-3 mb-4">
1924
+ <div className="flex flex-wrap gap-2">
1925
+ {ws.repos.map((repoPath) => (
1926
+ <span key={repoPath} className="text-[10px] px-2.5 py-1 bg-gray-900 border border-gray-800 text-gray-300 rounded-md font-semibold">
1927
+ {repoPath.split(/[\\/]/).pop()}
1928
+ </span>
1929
+ ))}
1930
+ </div>
1931
+
1932
+ {repos.filter((r) => !ws.repos.includes(r.path)).length > 0 && (
1933
+ <div className="flex items-center gap-1.5 ml-auto">
1934
+ <select
1935
+ id={`add-repo-select-${ws.branchName}`}
1936
+ className="bg-gray-900 border border-gray-800 text-gray-300 rounded-md text-[10px] px-2 py-1 font-semibold outline-none focus:border-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
1937
+ defaultValue=""
1938
+ onChange={async (e) => {
1939
+ const val = e.target.value;
1940
+ if (val) {
1941
+ if (window.confirm(`Are you sure you want to add repository "${val.split(/[\\/]/).pop()}" to this workspace?\nThis will create a new git worktree and re-run analysis.`)) {
1942
+ await handleAddRepo(ws.branchName, val);
1943
+ }
1944
+ e.target.value = "";
1945
+ }
1946
+ }}
1947
+ disabled={addRepoLoading}
1948
+ >
1949
+ <option value="" disabled>+ Add Repository</option>
1950
+ {repos
1951
+ .filter((r) => !ws.repos.includes(r.path))
1952
+ .map((r) => (
1953
+ <option key={r.path} value={r.path}>{r.name}</option>
1954
+ ))
1955
+ }
1956
+ </select>
1957
+ </div>
1958
+ )}
1799
1959
  </div>
1800
1960
 
1801
1961
  {/* Expansion: Process management console */}
@@ -2407,6 +2567,108 @@ Core Instructions:
2407
2567
  Save Configuration
2408
2568
  </button>
2409
2569
  </div>
2570
+
2571
+ {/* Toolchain Updates Section */}
2572
+ <div className="bg-[#111827]/40 border border-gray-800/80 rounded-xl p-8 shadow-xl backdrop-blur-sm mt-6">
2573
+ <div className="flex justify-between items-center mb-6">
2574
+ <div>
2575
+ <h3 className="text-lg font-bold text-white mb-1">AI Toolchain Updates</h3>
2576
+ <p className="text-xs text-gray-555">Monitor and update CLI packages and assistants in your workflow.</p>
2577
+ </div>
2578
+ <button
2579
+ onClick={() => fetchToolsStatus(true)}
2580
+ disabled={toolsLoading}
2581
+ className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-gray-800 hover:border-gray-700 bg-gray-950/20 text-xs font-semibold text-white transition-all cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
2582
+ >
2583
+ <RefreshCw size={13} className={toolsLoading ? 'animate-spin' : ''} />
2584
+ {toolsLoading ? 'Checking...' : 'Check Now'}
2585
+ </button>
2586
+ </div>
2587
+
2588
+ {toolsLoading && toolsStatus.length === 0 ? (
2589
+ <div className="flex flex-col items-center justify-center py-8 gap-2 text-gray-400">
2590
+ <RefreshCw className="animate-spin text-indigo-400" size={24} />
2591
+ <span className="text-xs">Fetching registry version details...</span>
2592
+ </div>
2593
+ ) : (
2594
+ <div className="space-y-4">
2595
+ {toolsStatus.map((tool) => (
2596
+ <div key={tool.id} className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 p-4 border border-gray-800/60 rounded-xl bg-gray-950/10">
2597
+ <div className="min-w-0">
2598
+ <h4 className="text-sm font-bold text-white flex items-center gap-2">
2599
+ {tool.name}
2600
+ <span className={`text-[9px] px-2 py-0.5 rounded font-semibold uppercase ${
2601
+ tool.installed ? 'bg-emerald-500/10 text-emerald-400' : 'bg-gray-800 text-gray-500'
2602
+ }`}>
2603
+ {tool.installed ? 'Installed' : 'Not Installed'}
2604
+ </span>
2605
+ </h4>
2606
+ <div className="flex items-center gap-4 mt-1.5 text-xs text-gray-500">
2607
+ <span>Installed version: <code className="text-gray-300 font-mono text-[10px]">{tool.currentVersion}</code></span>
2608
+ {tool.installed && (
2609
+ <span>Latest: <code className="text-gray-300 font-mono text-[10px]">{tool.latestVersion}</code></span>
2610
+ )}
2611
+ </div>
2612
+ <p className="text-[10px] text-gray-600 mt-1 font-mono">{tool.updateCmd}</p>
2613
+ </div>
2614
+
2615
+ <div className="shrink-0 flex items-center gap-3">
2616
+ {tool.updateAvailable ? (
2617
+ <button
2618
+ onClick={() => handleUpdateTool(tool.id)}
2619
+ disabled={updatingToolId !== null}
2620
+ className="px-3.5 py-2 bg-gradient-to-r from-amber-500 to-amber-600 hover:from-amber-600 hover:to-amber-700 text-[#060813] font-bold text-xs rounded-lg transition-all shadow-md shadow-amber-500/10 cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed flex items-center gap-1.5"
2621
+ >
2622
+ {updatingToolId === tool.id ? (
2623
+ <>
2624
+ <RefreshCw className="animate-spin" size={12} /> Updating...
2625
+ </>
2626
+ ) : (
2627
+ <>
2628
+ <Sparkles size={12} /> Update Tool
2629
+ </>
2630
+ )}
2631
+ </button>
2632
+ ) : tool.installed ? (
2633
+ <div className="flex items-center gap-2">
2634
+ <span className="text-xs font-semibold text-emerald-400 flex items-center gap-1.5 bg-emerald-500/5 px-2.5 py-1.5 rounded-lg border border-emerald-500/10">
2635
+ <Check size={12} /> Up to Date
2636
+ </span>
2637
+ <button
2638
+ onClick={() => handleUpdateTool(tool.id)}
2639
+ disabled={updatingToolId !== null}
2640
+ className="px-3.5 py-2 bg-gray-900 border border-gray-800 hover:bg-gray-800 hover:border-gray-750 text-gray-300 font-bold text-xs rounded-lg transition-all cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed flex items-center gap-1.5"
2641
+ >
2642
+ {updatingToolId === tool.id ? (
2643
+ <>
2644
+ <RefreshCw className="animate-spin" size={12} /> Reinstalling...
2645
+ </>
2646
+ ) : (
2647
+ 'Reinstall'
2648
+ )}
2649
+ </button>
2650
+ </div>
2651
+ ) : (
2652
+ <button
2653
+ onClick={() => handleUpdateTool(tool.id)}
2654
+ disabled={updatingToolId !== null}
2655
+ className="px-3.5 py-2 bg-gray-900 border border-gray-800 hover:bg-gray-800 hover:border-gray-700 text-white font-bold text-xs rounded-lg transition-all cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
2656
+ >
2657
+ {updatingToolId === tool.id ? (
2658
+ <>
2659
+ <RefreshCw className="animate-spin" size={12} /> Installing...
2660
+ </>
2661
+ ) : (
2662
+ 'Install CLI'
2663
+ )}
2664
+ </button>
2665
+ )}
2666
+ </div>
2667
+ </div>
2668
+ ))}
2669
+ </div>
2670
+ )}
2671
+ </div>
2410
2672
  </div>
2411
2673
  )}
2412
2674
  </>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { Play, RefreshCw, FolderGit2, Sparkles, ExternalLink } from 'lucide-react';
3
- import type { Feature, RunningService, ServiceConfig, OrchestrationDetection } from '../../types.js';
2
+ import { Play, RefreshCw, FolderGit2, Sparkles, ExternalLink, Trash2 } from 'lucide-react';
3
+ import type { Feature, RunningService, ServiceConfig, OrchestrationDetection, RepoInfo } from '../../types.js';
4
4
 
5
5
  // Feature subcomponents
6
6
  import { SessionHistory } from '../sessions/SessionHistory.js';
@@ -20,6 +20,13 @@ interface WorkspaceListProps {
20
20
  handleOpenInEditor: (workspacePath: string) => Promise<void>;
21
21
  fetchWorkspaces: () => Promise<void>;
22
22
 
23
+ // Deletion and repo addition props
24
+ repos: RepoInfo[];
25
+ deleteWsLoading: string | null;
26
+ addRepoLoading: boolean;
27
+ handleDeleteWorkspace: (wsName: string) => Promise<void>;
28
+ handleAddRepo: (wsName: string, repoPath: string) => Promise<void>;
29
+
23
30
  // ServiceConsole props
24
31
  services: ServiceConfig[];
25
32
  runningServices: RunningService[];
@@ -89,6 +96,11 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
89
96
  handleCopyPrompt,
90
97
  handleOpenInEditor,
91
98
  fetchWorkspaces,
99
+ repos,
100
+ deleteWsLoading,
101
+ addRepoLoading,
102
+ handleDeleteWorkspace,
103
+ handleAddRepo,
92
104
 
93
105
  // ServiceConsole
94
106
  services,
@@ -225,6 +237,14 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
225
237
  >
226
238
  {isExpanded ? 'Hide Runner' : 'Orchestrate'}
227
239
  </button>
240
+ <button
241
+ className="inline-flex items-center justify-center gap-1.5 px-3.5 py-2 bg-red-950/40 border border-red-900/60 hover:bg-red-900/60 hover:border-red-800 rounded-lg text-xs font-semibold text-red-200 transition-all cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed animate-fade-in"
242
+ onClick={() => handleDeleteWorkspace(ws.branchName)}
243
+ disabled={deleteWsLoading === ws.branchName}
244
+ >
245
+ <Trash2 size={12} className={deleteWsLoading === ws.branchName ? 'animate-spin' : ''} />
246
+ {deleteWsLoading === ws.branchName ? 'Deleting...' : 'Delete'}
247
+ </button>
228
248
  </div>
229
249
  </div>
230
250
 
@@ -232,12 +252,42 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
232
252
  {ws.description}
233
253
  </p>
234
254
 
235
- <div className="flex flex-wrap gap-2 mb-4">
236
- {ws.repos.map((repoPath) => (
237
- <span key={repoPath} className="text-[10px] px-2.5 py-1 bg-gray-900 border border-gray-800 text-gray-300 rounded-md font-semibold">
238
- {repoPath.split(/[\\/]/).pop()}
239
- </span>
240
- ))}
255
+ <div className="flex items-center gap-3 mb-4">
256
+ <div className="flex flex-wrap gap-2">
257
+ {ws.repos.map((repoPath) => (
258
+ <span key={repoPath} className="text-[10px] px-2.5 py-1 bg-gray-900 border border-gray-800 text-gray-300 rounded-md font-semibold">
259
+ {repoPath.split(/[\\/]/).pop()}
260
+ </span>
261
+ ))}
262
+ </div>
263
+
264
+ {repos.filter((r) => !ws.repos.includes(r.path)).length > 0 && (
265
+ <div className="flex items-center gap-1.5 ml-auto">
266
+ <select
267
+ id={`add-repo-select-feature-${ws.branchName}`}
268
+ className="bg-gray-900 border border-gray-800 text-gray-300 rounded-md text-[10px] px-2 py-1 font-semibold outline-none focus:border-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
269
+ defaultValue=""
270
+ onChange={async (e) => {
271
+ const val = e.target.value;
272
+ if (val) {
273
+ if (window.confirm(`Are you sure you want to add repository "${val.split(/[\\/]/).pop()}" to this workspace?\nThis will create a new git worktree and re-run analysis.`)) {
274
+ await handleAddRepo(ws.branchName, val);
275
+ }
276
+ e.target.value = "";
277
+ }
278
+ }}
279
+ disabled={addRepoLoading}
280
+ >
281
+ <option value="" disabled>+ Add Repository</option>
282
+ {repos
283
+ .filter((r) => !ws.repos.includes(r.path))
284
+ .map((r) => (
285
+ <option key={r.path} value={r.path}>{r.name}</option>
286
+ ))
287
+ }
288
+ </select>
289
+ </div>
290
+ )}
241
291
  </div>
242
292
 
243
293
  {/* Expansion: Process management console */}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrpatronz/nexusflow",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Combine multiple repos into a workspace with rich AI assistant context",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @module commands/add-repo
3
+ * Adds a repository to an existing NexusFlow workspace.
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import ora from 'ora';
8
+ import { select } from '@inquirer/prompts';
9
+ import * as path from 'node:path';
10
+
11
+ import { loadConfig } from '../core/config.js';
12
+ import { scanForRepos } from '../core/scanner.js';
13
+ import { listWorkspaces, loadFeatureConfig, addRepoToWorkspace } from '../core/workspace.js';
14
+
15
+ /**
16
+ * Executes the add-repo command.
17
+ *
18
+ * @param repoPathArg - Optional repository path to add.
19
+ * @param workspaceArg - Optional workspace path or name.
20
+ */
21
+ export async function addRepoCommand(
22
+ repoPathArg?: string,
23
+ workspaceArg?: string,
24
+ ): Promise<void> {
25
+ console.log(chalk.bold.cyan('\n➕ NexusFlow — Adding Repository to Workspace\n'));
26
+
27
+ const config = await loadConfig();
28
+
29
+ // 1. Resolve workspace
30
+ let workspacePath: string | null = null;
31
+ let workspaceName = '';
32
+
33
+ if (workspaceArg) {
34
+ const resolvedPath = path.isAbsolute(workspaceArg)
35
+ ? workspaceArg
36
+ : path.resolve(config.workspacesDir, workspaceArg);
37
+
38
+ try {
39
+ const manifest = await loadFeatureConfig(resolvedPath);
40
+ if (manifest) {
41
+ workspacePath = resolvedPath;
42
+ workspaceName = manifest.branchName;
43
+ }
44
+ } catch {}
45
+
46
+ if (!workspacePath) {
47
+ const directPath = path.join(config.workspacesDir, workspaceArg);
48
+ const manifest = await loadFeatureConfig(directPath);
49
+ if (manifest) {
50
+ workspacePath = directPath;
51
+ workspaceName = manifest.branchName;
52
+ } else {
53
+ console.error(chalk.red(`✖ Invalid workspace: No nexusflow.json found at ${workspaceArg}`));
54
+ return;
55
+ }
56
+ }
57
+ } else {
58
+ const cwdFeature = await loadFeatureConfig(process.cwd());
59
+ if (cwdFeature) {
60
+ workspacePath = process.cwd();
61
+ workspaceName = cwdFeature.branchName;
62
+ } else {
63
+ const workspaces = await listWorkspaces(config.workspacesDir);
64
+ if (workspaces.length === 0) {
65
+ console.log(chalk.yellow('No workspaces found.\n'));
66
+ return;
67
+ }
68
+
69
+ const selected = await select({
70
+ message: 'Select a workspace to add a repository to:',
71
+ choices: workspaces.map((ws) => ({
72
+ name: `${ws.branchName} ${chalk.dim(`(${ws.repos.length} repos)`)}`,
73
+ value: ws,
74
+ })),
75
+ });
76
+
77
+ workspacePath = selected.workspacePath;
78
+ workspaceName = selected.branchName;
79
+ }
80
+ }
81
+
82
+ if (!workspacePath) return;
83
+
84
+ const feature = await loadFeatureConfig(workspacePath);
85
+ if (!feature) {
86
+ console.error(chalk.red('✖ Failed to load workspace configuration.'));
87
+ return;
88
+ }
89
+
90
+ // 2. Resolve repository to add
91
+ let repoPathToAdd = '';
92
+
93
+ if (repoPathArg) {
94
+ repoPathToAdd = path.resolve(repoPathArg);
95
+ } else {
96
+ const scanSpinner = ora('Scanning for projects...').start();
97
+ let repos = [];
98
+ try {
99
+ repos = await scanForRepos(config.devDir, config.scanDepth);
100
+ scanSpinner.succeed(`Found ${chalk.bold(repos.length)} projects in ${config.devDir}`);
101
+ } catch (error) {
102
+ scanSpinner.fail('Failed to scan for projects');
103
+ console.error(error);
104
+ return;
105
+ }
106
+
107
+ const availableRepos = repos.filter(
108
+ (r) => !feature.repos.includes(r.path)
109
+ );
110
+
111
+ if (availableRepos.length === 0) {
112
+ console.log(chalk.yellow('All scanned repositories are already in the workspace.\n'));
113
+ return;
114
+ }
115
+
116
+ repoPathToAdd = await select({
117
+ message: 'Select a repository to add:',
118
+ choices: availableRepos.map((r) => ({
119
+ name: `${r.name} ${chalk.dim(`(${r.path})`)}`,
120
+ value: r.path,
121
+ })),
122
+ });
123
+ }
124
+
125
+ const repoName = path.basename(repoPathToAdd);
126
+ const spinner = ora(`Adding ${repoName} to workspace ${workspaceName}...`).start();
127
+
128
+ try {
129
+ await addRepoToWorkspace(workspacePath, repoPathToAdd);
130
+ spinner.succeed(`Successfully added ${chalk.bold(repoName)} to workspace ${chalk.bold(workspaceName)}`);
131
+ console.log(chalk.dim(' - Checked out git worktree'));
132
+ console.log(chalk.dim(' - Updated nexusflow.json and .gitignore'));
133
+ console.log(chalk.dim(' - Re-analyzed workspace codebases'));
134
+ console.log(chalk.dim(' - Regenerated LLM instruction context files'));
135
+ console.log(chalk.dim(' - Repacked codebase context using Repomix'));
136
+ console.log();
137
+ } catch (error) {
138
+ spinner.fail(`Failed to add repository: ${error instanceof Error ? error.message : String(error)}`);
139
+ console.log();
140
+ }
141
+ }