@mrpatronz/nexusflow 0.2.13 → 0.2.18
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/.agents/skills/ccc/SKILL.md +71 -0
- package/.agents/skills/ccc/references/management.md +110 -0
- package/.agents/skills/ccc/references/settings.md +126 -0
- package/.github/workflows/ci.yml +44 -0
- package/.github/workflows/dependabot-merge.yml +53 -0
- package/.github/workflows/release-desktop.yml +67 -0
- package/.github/workflows/release-npm.yml +65 -0
- package/.github/workflows/release-vscode.yml +61 -0
- package/GETTING_STARTED.md +5 -0
- package/README.md +53 -0
- package/desktop/build-installer.js +228 -0
- package/desktop/build.js +118 -0
- package/desktop/installer/nexusflow.iss +35 -0
- package/desktop/neutralino.config.json +39 -0
- package/desktop/package-lock.json +1060 -0
- package/desktop/package.json +14 -0
- package/dist/commands/adapter.d.ts +27 -0
- package/dist/commands/adapter.d.ts.map +1 -0
- package/dist/commands/adapter.js +318 -0
- package/dist/commands/adapter.js.map +1 -0
- package/dist/commands/add-repo.d.ts.map +1 -1
- package/dist/commands/add-repo.js +0 -1
- package/dist/commands/add-repo.js.map +1 -1
- package/dist/commands/commands.test.js +2 -2
- package/dist/commands/commands.test.js.map +1 -1
- package/dist/commands/config.d.ts +22 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +50 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +14 -17
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/desktop.d.ts +12 -0
- package/dist/commands/desktop.d.ts.map +1 -0
- package/dist/commands/desktop.js +119 -0
- package/dist/commands/desktop.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +11 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/refresh.d.ts +1 -0
- package/dist/commands/refresh.d.ts.map +1 -1
- package/dist/commands/refresh.js +2 -14
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +1 -8
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/tui.d.ts +8 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +439 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/commands/ui.d.ts +3 -1
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +76 -19
- package/dist/commands/ui.js.map +1 -1
- package/dist/core/adapters/local-storage.d.ts +14 -0
- package/dist/core/adapters/local-storage.d.ts.map +1 -0
- package/dist/core/adapters/local-storage.js +58 -0
- package/dist/core/adapters/local-storage.js.map +1 -0
- package/dist/core/adapters/obsidian-storage.d.ts +28 -0
- package/dist/core/adapters/obsidian-storage.d.ts.map +1 -0
- package/dist/core/adapters/obsidian-storage.js +135 -0
- package/dist/core/adapters/obsidian-storage.js.map +1 -0
- package/dist/core/adapters/registry.d.ts +8 -0
- package/dist/core/adapters/registry.d.ts.map +1 -0
- package/dist/core/adapters/registry.js +37 -0
- package/dist/core/adapters/registry.js.map +1 -0
- package/dist/core/adapters/storage.test.d.ts +2 -0
- package/dist/core/adapters/storage.test.d.ts.map +1 -0
- package/dist/core/adapters/storage.test.js +106 -0
- package/dist/core/adapters/storage.test.js.map +1 -0
- package/dist/core/adapters/vault-storage.d.ts +16 -0
- package/dist/core/adapters/vault-storage.d.ts.map +1 -0
- package/dist/core/adapters/vault-storage.js +77 -0
- package/dist/core/adapters/vault-storage.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +28 -4
- package/dist/core/config.js.map +1 -1
- package/dist/core/plugins/index.d.ts +14 -0
- package/dist/core/plugins/index.d.ts.map +1 -0
- package/dist/core/plugins/index.js +2 -0
- package/dist/core/plugins/index.js.map +1 -0
- package/dist/core/plugins/loader.d.ts +2 -0
- package/dist/core/plugins/loader.d.ts.map +1 -0
- package/dist/core/plugins/loader.js +34 -0
- package/dist/core/plugins/loader.js.map +1 -0
- package/dist/core/ports/storage.d.ts +59 -0
- package/dist/core/ports/storage.d.ts.map +1 -0
- package/dist/core/ports/storage.js +10 -0
- package/dist/core/ports/storage.js.map +1 -0
- package/dist/core/storage.d.ts +10 -0
- package/dist/core/storage.d.ts.map +1 -0
- package/dist/core/storage.js +29 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +110 -16
- package/dist/core/workspace.js.map +1 -1
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/base.js +19 -6
- package/dist/generators/base.js.map +1 -1
- package/dist/generators/diff-context.d.ts +6 -0
- package/dist/generators/diff-context.d.ts.map +1 -0
- package/dist/generators/diff-context.js +68 -0
- package/dist/generators/diff-context.js.map +1 -0
- package/dist/generators/index.d.ts +1 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +75 -18
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/map-generator.d.ts.map +1 -1
- package/dist/generators/map-generator.js +7 -11
- package/dist/generators/map-generator.js.map +1 -1
- package/dist/generators/plan-generator.d.ts.map +1 -1
- package/dist/generators/plan-generator.js +3 -5
- package/dist/generators/plan-generator.js.map +1 -1
- package/dist/gui/app_logo.png +0 -0
- package/dist/gui/assets/index-CB-jWded.css +1 -0
- package/dist/gui/assets/index-DDXpZZu3.js +25 -0
- package/dist/gui/index.html +2 -2
- package/dist/index.js +174 -20
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +212 -28
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +173 -38
- package/dist/server.test.js.map +1 -1
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/git.d.ts +16 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +52 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/local-ai.d.ts.map +1 -1
- package/dist/utils/local-ai.js +7 -3
- package/dist/utils/local-ai.js.map +1 -1
- package/dist/utils/multi-git.d.ts +2 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +5 -2
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/update-check.d.ts +3 -1
- package/dist/utils/update-check.d.ts.map +1 -1
- package/dist/utils/update-check.js +23 -34
- package/dist/utils/update-check.js.map +1 -1
- package/dist/utils/workflow-advisor.d.ts +16 -0
- package/dist/utils/workflow-advisor.d.ts.map +1 -0
- package/dist/utils/workflow-advisor.js +100 -0
- package/dist/utils/workflow-advisor.js.map +1 -0
- package/dist/utils/workflows.d.ts +11 -0
- package/dist/utils/workflows.d.ts.map +1 -0
- package/dist/utils/workflows.js +156 -0
- package/dist/utils/workflows.js.map +1 -0
- package/dist/utils/workflows.test.d.ts +2 -0
- package/dist/utils/workflows.test.d.ts.map +1 -0
- package/dist/utils/workflows.test.js +86 -0
- package/dist/utils/workflows.test.js.map +1 -0
- package/extension/media/icon.svg +1 -0
- package/extension/package-lock.json +4893 -1660
- package/extension/package.json +58 -11
- package/extension/src/extension.ts +476 -27
- package/extension/tsconfig.json +4 -2
- package/gui/e2e/wizard.spec.ts +19 -0
- package/gui/package-lock.json +342 -381
- package/gui/package.json +12 -12
- package/gui/public/app_logo.png +0 -0
- package/gui/src/App.tsx +991 -81
- package/gui/src/features/workspace/WorkspaceList.tsx +30 -30
- package/gui/src/index.css +64 -22
- package/gui/src/main.tsx +89 -5
- package/package.json +11 -12
- package/resources/workflows/plan-implement-review.md +8 -0
- package/resources/workflows/research-verify.md +6 -0
- package/resources/workflows/solo-developer.md +3 -0
- package/skills-lock.json +11 -0
- package/src/commands/adapter.ts +348 -0
- package/src/commands/add-repo.ts +0 -1
- package/src/commands/commands.test.ts +3 -2
- package/src/commands/config.ts +52 -0
- package/src/commands/create.ts +14 -17
- package/src/commands/desktop.ts +128 -0
- package/src/commands/doctor.ts +13 -0
- package/src/commands/mcp.ts +2 -0
- package/src/commands/refresh.ts +4 -14
- package/src/commands/sync.ts +2 -8
- package/src/commands/tui.ts +484 -0
- package/src/commands/ui.ts +83 -19
- package/src/core/adapters/local-storage.ts +66 -0
- package/src/core/adapters/obsidian-storage.ts +151 -0
- package/src/core/adapters/registry.ts +44 -0
- package/src/core/adapters/storage.test.ts +174 -0
- package/src/core/adapters/vault-storage.ts +86 -0
- package/src/core/config.ts +29 -4
- package/src/core/plugins/index.ts +17 -0
- package/src/core/plugins/loader.ts +36 -0
- package/src/core/ports/storage.ts +71 -0
- package/src/core/storage.ts +37 -0
- package/src/core/workspace.ts +122 -15
- package/src/generators/base.ts +21 -5
- package/src/generators/diff-context.ts +75 -0
- package/src/generators/index.ts +93 -21
- package/src/generators/map-generator.ts +7 -10
- package/src/generators/plan-generator.ts +6 -4
- package/src/index.ts +178 -21
- package/src/server.test.ts +193 -39
- package/src/server.ts +238 -28
- package/src/types.ts +14 -2
- package/src/utils/git.ts +56 -0
- package/src/utils/local-ai.ts +8 -3
- package/src/utils/multi-git.ts +16 -9
- package/src/utils/update-check.ts +42 -31
- package/src/utils/workflow-advisor.ts +118 -0
- package/src/utils/workflows.test.ts +114 -0
- package/src/utils/workflows.ts +178 -0
- package/.github/workflows/release.yml +0 -100
- package/dist/commands/pack.d.ts +0 -7
- package/dist/commands/pack.d.ts.map +0 -1
- package/dist/commands/pack.js +0 -64
- package/dist/commands/pack.js.map +0 -1
- package/dist/core/packer.d.ts +0 -14
- package/dist/core/packer.d.ts.map +0 -1
- package/dist/core/packer.js +0 -87
- package/dist/core/packer.js.map +0 -1
- package/dist/core/packer.test.d.ts +0 -2
- package/dist/core/packer.test.d.ts.map +0 -1
- package/dist/core/packer.test.js +0 -82
- package/dist/core/packer.test.js.map +0 -1
- package/dist/gui/assets/index-CFWwqFux.js +0 -23
- package/dist/gui/assets/index-Dvc9QMvl.css +0 -2
- package/src/commands/pack.ts +0 -73
- package/src/core/packer.test.ts +0 -99
- package/src/core/packer.ts +0 -107
|
@@ -96,7 +96,7 @@ const parseInlineStyles = (text: string): React.ReactNode => {
|
|
|
96
96
|
return <strong key={index} className="font-bold text-gray-200">{part.slice(2, -2)}</strong>;
|
|
97
97
|
}
|
|
98
98
|
if (part.startsWith('`') && part.endsWith('`')) {
|
|
99
|
-
return <code key={index} className="px-1.5 py-0.5 bg-gray-900 border border-gray-800 text-
|
|
99
|
+
return <code key={index} className="px-1.5 py-0.5 bg-gray-900 border border-gray-800 text-cyan-400 rounded font-mono text-[10px]">{part.slice(1, -1)}</code>;
|
|
100
100
|
}
|
|
101
101
|
if (part.startsWith('*') && part.endsWith('*')) {
|
|
102
102
|
return <em key={index} className="italic text-gray-300">{part.slice(1, -1)}</em>;
|
|
@@ -263,13 +263,13 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
263
263
|
onClick={fetchWorkspaces}
|
|
264
264
|
disabled={workspacesLoading}
|
|
265
265
|
>
|
|
266
|
-
<RefreshCw size={14} className={workspacesLoading ? 'animate-spin text-
|
|
266
|
+
<RefreshCw size={14} className={workspacesLoading ? 'animate-spin text-cyan-400' : ''} /> Refresh
|
|
267
267
|
</button>
|
|
268
268
|
</header>
|
|
269
269
|
|
|
270
270
|
{workspacesLoading ? (
|
|
271
271
|
<div className="flex flex-col items-center py-40 gap-4 text-gray-400">
|
|
272
|
-
<RefreshCw className="animate-spin text-
|
|
272
|
+
<RefreshCw className="animate-spin text-cyan-400" size={32} />
|
|
273
273
|
<span className="text-sm">Fetching workspace details...</span>
|
|
274
274
|
</div>
|
|
275
275
|
) : workspaces.length === 0 ? (
|
|
@@ -285,10 +285,10 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
285
285
|
{workspaces.map((ws) => {
|
|
286
286
|
const isExpanded = activeWsId === ws.branchName;
|
|
287
287
|
return (
|
|
288
|
-
<div key={ws.id} className="glass-card p-8 rounded-2xl shadow-xl hover:shadow-2xl border border-slate-800/40 relative overflow-hidden transition-all duration-300 before:absolute before:inset-x-0 before:top-0 before:h-[1px] before:bg-gradient-to-r before:from-
|
|
288
|
+
<div key={ws.id} className="glass-card p-8 rounded-2xl shadow-xl hover:shadow-2xl border border-slate-800/40 relative overflow-hidden transition-all duration-300 before:absolute before:inset-x-0 before:top-0 before:h-[1px] before:bg-gradient-to-r before:from-cyan-500/10 via-violet-500/10 to-transparent">
|
|
289
289
|
<div className="flex justify-between items-start gap-4 mb-4">
|
|
290
290
|
<div>
|
|
291
|
-
<h3 className="text-lg font-bold text-white hover:text-
|
|
291
|
+
<h3 className="text-lg font-bold text-white hover:text-cyan-400 transition-colors">{ws.branchName}</h3>
|
|
292
292
|
<div className="flex items-center gap-3 text-xs text-slate-500 mt-1">
|
|
293
293
|
<span>Created: {new Date(ws.createdAt).toLocaleDateString()}</span>
|
|
294
294
|
<span className="h-1 w-1 rounded-full bg-slate-850"></span>
|
|
@@ -317,7 +317,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
317
317
|
<ExternalLink size={12} /> Open
|
|
318
318
|
</button>
|
|
319
319
|
<button
|
|
320
|
-
className="inline-flex items-center justify-center gap-1.5 px-3.5 py-2.5 bg-
|
|
320
|
+
className="inline-flex items-center justify-center gap-1.5 px-3.5 py-2.5 bg-cyan-600 hover:bg-cyan-500 text-white rounded-xl text-xs font-semibold transition-all cursor-pointer shadow-md shadow-cyan-650/10"
|
|
321
321
|
onClick={() => {
|
|
322
322
|
if (isExpanded) {
|
|
323
323
|
setActiveWsId(null);
|
|
@@ -339,7 +339,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
339
339
|
</div>
|
|
340
340
|
</div>
|
|
341
341
|
|
|
342
|
-
<div className="text-xs text-slate-350 bg-slate-950/60 border-l-2 border-
|
|
342
|
+
<div className="text-xs text-slate-350 bg-slate-950/60 border-l-2 border-cyan-500/80 rounded-r-xl px-5 py-3.5 mb-5 font-normal leading-relaxed relative overflow-hidden before:absolute before:inset-y-0 before:right-0 before:w-12 before:bg-gradient-to-r before:from-transparent before:to-cyan-500/2">
|
|
343
343
|
{renderFormattedDescription(ws.description)}
|
|
344
344
|
</div>
|
|
345
345
|
|
|
@@ -356,7 +356,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
356
356
|
<div className="flex items-center gap-1.5 ml-auto">
|
|
357
357
|
<select
|
|
358
358
|
id={`add-repo-select-feature-${ws.branchName}`}
|
|
359
|
-
className="bg-slate-905 border border-slate-800 text-slate-300 rounded-lg text-[10px] px-3 py-1.5 font-semibold outline-none focus:border-
|
|
359
|
+
className="bg-slate-905 border border-slate-800 text-slate-300 rounded-lg text-[10px] px-3 py-1.5 font-semibold outline-none focus:border-cyan-500 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer transition-all hover:border-slate-700"
|
|
360
360
|
defaultValue=""
|
|
361
361
|
onChange={async (e) => {
|
|
362
362
|
const val = e.target.value;
|
|
@@ -389,8 +389,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
389
389
|
<button
|
|
390
390
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
391
391
|
subTab === 'overview'
|
|
392
|
-
? 'bg-
|
|
393
|
-
: 'text-slate-500 hover:text-slate-
|
|
392
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
393
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
394
394
|
}`}
|
|
395
395
|
onClick={() => setSubTab('overview')}
|
|
396
396
|
>
|
|
@@ -399,8 +399,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
399
399
|
<button
|
|
400
400
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
401
401
|
subTab === 'sessions'
|
|
402
|
-
? 'bg-
|
|
403
|
-
: 'text-slate-500 hover:text-slate-
|
|
402
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
403
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
404
404
|
}`}
|
|
405
405
|
onClick={() => setSubTab('sessions')}
|
|
406
406
|
>
|
|
@@ -409,8 +409,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
409
409
|
<button
|
|
410
410
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
411
411
|
subTab === 'services'
|
|
412
|
-
? 'bg-
|
|
413
|
-
: 'text-slate-500 hover:text-slate-
|
|
412
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
413
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
414
414
|
}`}
|
|
415
415
|
onClick={() => setSubTab('services')}
|
|
416
416
|
>
|
|
@@ -419,8 +419,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
419
419
|
<button
|
|
420
420
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
421
421
|
subTab === 'changes'
|
|
422
|
-
? 'bg-
|
|
423
|
-
: 'text-slate-500 hover:text-slate-
|
|
422
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
423
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
424
424
|
}`}
|
|
425
425
|
onClick={() => setSubTab('changes')}
|
|
426
426
|
>
|
|
@@ -429,8 +429,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
429
429
|
<button
|
|
430
430
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
431
431
|
subTab === 'knowledge'
|
|
432
|
-
? 'bg-
|
|
433
|
-
: 'text-slate-500 hover:text-slate-
|
|
432
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
433
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
434
434
|
}`}
|
|
435
435
|
onClick={() => setSubTab('knowledge')}
|
|
436
436
|
>
|
|
@@ -439,8 +439,8 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
439
439
|
<button
|
|
440
440
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all cursor-pointer select-none ${
|
|
441
441
|
subTab === 'plan'
|
|
442
|
-
? 'bg-
|
|
443
|
-
: 'text-slate-500 hover:text-slate-
|
|
442
|
+
? 'bg-cyan-950/30 border border-cyan-900/60 text-cyan-400 shadow-[0_0_15px_rgba(6,182,212,0.1)]'
|
|
443
|
+
: 'text-slate-500 hover:text-slate-300 hover:bg-slate-900/40 border border-transparent'
|
|
444
444
|
}`}
|
|
445
445
|
onClick={() => setSubTab('plan')}
|
|
446
446
|
>
|
|
@@ -453,7 +453,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
453
453
|
{/* Section 1: AI Assistant Harnesses */}
|
|
454
454
|
<div className="bg-gray-950/20 border border-gray-800/80 rounded-xl p-5">
|
|
455
455
|
<div className="flex items-center gap-2 mb-4 border-b border-gray-800/80 pb-3">
|
|
456
|
-
<Cpu size={18} className="text-
|
|
456
|
+
<Cpu size={18} className="text-cyan-400" />
|
|
457
457
|
<h4 className="font-bold text-white">AI Assistant Harnesses</h4>
|
|
458
458
|
</div>
|
|
459
459
|
<p className="text-xs text-gray-400 mb-4">
|
|
@@ -479,11 +479,11 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
479
479
|
<div key={name} className="flex flex-col p-3 bg-gray-900/40 border border-gray-800/60 rounded-lg">
|
|
480
480
|
<div className="flex items-center justify-between gap-2">
|
|
481
481
|
<div className="flex items-center gap-2">
|
|
482
|
-
<span className={`h-2 w-2 rounded-full ${isConfigured ? 'bg-
|
|
482
|
+
<span className={`h-2 w-2 rounded-full ${isConfigured ? 'bg-cyan-500 shadow-sm' : 'bg-gray-700'}`}></span>
|
|
483
483
|
<span className="font-semibold text-xs text-gray-200">{displayName}</span>
|
|
484
484
|
</div>
|
|
485
485
|
<div className="flex items-center gap-1.5 text-[10px] font-medium">
|
|
486
|
-
{isConfigured && <span className="text-
|
|
486
|
+
{isConfigured && <span className="text-cyan-400 bg-cyan-950/20 px-2 py-0.5 rounded border border-cyan-900/40 text-[9px] font-bold uppercase tracking-wider">Active</span>}
|
|
487
487
|
{isDetected ? (
|
|
488
488
|
<span className="text-emerald-400 bg-emerald-500/10 px-2 py-0.5 rounded border border-emerald-500/20 text-[9px] font-bold uppercase tracking-wider">Installed</span>
|
|
489
489
|
) : (
|
|
@@ -493,7 +493,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
493
493
|
</div>
|
|
494
494
|
{isConfigured && resumeCmd && (
|
|
495
495
|
<div className="mt-2.5 flex items-center justify-between gap-2 bg-gray-950/80 px-2.5 py-1.5 rounded border border-gray-800/60 font-mono text-[10px]">
|
|
496
|
-
<span className="text-
|
|
496
|
+
<span className="text-cyan-400 truncate">{resumeCmd}</span>
|
|
497
497
|
<button
|
|
498
498
|
onClick={() => handleCopy(resumeCmd)}
|
|
499
499
|
className="text-gray-400 hover:text-white transition-colors cursor-pointer"
|
|
@@ -513,7 +513,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
513
513
|
<div className="flex flex-col gap-6">
|
|
514
514
|
<div className="bg-gray-950/20 border border-gray-800/80 rounded-xl p-5">
|
|
515
515
|
<div className="flex items-center gap-2 mb-4 border-b border-gray-800/80 pb-3">
|
|
516
|
-
<Layers size={18} className="text-
|
|
516
|
+
<Layers size={18} className="text-cyan-400" />
|
|
517
517
|
<h4 className="font-bold text-white">Local MCP Server (Tools)</h4>
|
|
518
518
|
</div>
|
|
519
519
|
<p className="text-xs text-gray-400 mb-4">
|
|
@@ -521,7 +521,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
521
521
|
</p>
|
|
522
522
|
<div className="flex flex-col gap-3.5">
|
|
523
523
|
<div className="flex flex-col gap-1">
|
|
524
|
-
<div className="flex items-center gap-2 text-xs font-semibold text-
|
|
524
|
+
<div className="flex items-center gap-2 text-xs font-semibold text-cyan-455">
|
|
525
525
|
<code>search_workspace</code>
|
|
526
526
|
</div>
|
|
527
527
|
<span className="text-[11px] text-gray-400">
|
|
@@ -529,7 +529,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
529
529
|
</span>
|
|
530
530
|
</div>
|
|
531
531
|
<div className="flex flex-col gap-1 border-t border-gray-800/40 pt-2.5">
|
|
532
|
-
<div className="flex items-center gap-2 text-xs font-semibold text-
|
|
532
|
+
<div className="flex items-center gap-2 text-xs font-semibold text-cyan-455">
|
|
533
533
|
<code>get_service_logs</code>
|
|
534
534
|
</div>
|
|
535
535
|
<span className="text-[11px] text-gray-400">
|
|
@@ -537,7 +537,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
537
537
|
</span>
|
|
538
538
|
</div>
|
|
539
539
|
<div className="flex flex-col gap-1 border-t border-gray-800/40 pt-2.5">
|
|
540
|
-
<div className="flex items-center gap-2 text-xs font-semibold text-
|
|
540
|
+
<div className="flex items-center gap-2 text-xs font-semibold text-cyan-455">
|
|
541
541
|
<code>delegate_to_local_agent</code>
|
|
542
542
|
</div>
|
|
543
543
|
<span className="text-[11px] text-gray-400">
|
|
@@ -550,7 +550,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
550
550
|
{/* CLI shortcuts */}
|
|
551
551
|
<div className="bg-gray-950/20 border border-gray-800/80 rounded-xl p-5">
|
|
552
552
|
<div className="flex items-center gap-2 mb-4 border-b border-gray-800/80 pb-3">
|
|
553
|
-
<Terminal size={18} className="text-
|
|
553
|
+
<Terminal size={18} className="text-cyan-400" />
|
|
554
554
|
<h4 className="font-bold text-white">Workspace CLI Shortcuts</h4>
|
|
555
555
|
</div>
|
|
556
556
|
<div className="flex flex-col gap-2.5">
|
|
@@ -563,7 +563,7 @@ export const WorkspaceList: React.FC<WorkspaceListProps> = ({
|
|
|
563
563
|
].map(({ cmd, desc }) => (
|
|
564
564
|
<div key={cmd} className="flex flex-col gap-1">
|
|
565
565
|
<div className="flex items-center justify-between gap-2">
|
|
566
|
-
<code className="text-xs text-
|
|
566
|
+
<code className="text-xs text-cyan-400">{cmd}</code>
|
|
567
567
|
<button
|
|
568
568
|
onClick={() => handleCopy(cmd)}
|
|
569
569
|
className="text-gray-400 hover:text-white transition-colors cursor-pointer"
|
package/gui/src/index.css
CHANGED
|
@@ -1,37 +1,80 @@
|
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Space+Grotesk:wght@300..700&display=swap');
|
|
1
2
|
@import "tailwindcss";
|
|
2
3
|
|
|
4
|
+
/* Global Font Overrides to Monospace */
|
|
5
|
+
body {
|
|
6
|
+
font-family: 'JetBrains Mono', monospace !important;
|
|
7
|
+
background-color: #030408 !important;
|
|
8
|
+
background-image:
|
|
9
|
+
radial-gradient(at 50% 0%, rgba(139, 92, 246, 0.06) 0px, transparent 50%),
|
|
10
|
+
radial-gradient(at 0% 100%, rgba(6, 182, 212, 0.04) 0px, transparent 50%) !important;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
h1, h2, h3, h4, h5, h6, button, input, select, textarea, code, pre {
|
|
14
|
+
font-family: 'JetBrains Mono', monospace !important;
|
|
15
|
+
}
|
|
16
|
+
|
|
3
17
|
/* Custom Sleek Scrollbars */
|
|
4
18
|
::-webkit-scrollbar {
|
|
5
19
|
width: 6px;
|
|
6
20
|
height: 6px;
|
|
7
21
|
}
|
|
8
22
|
::-webkit-scrollbar-track {
|
|
9
|
-
background:
|
|
23
|
+
background: #05070c;
|
|
10
24
|
}
|
|
11
25
|
::-webkit-scrollbar-thumb {
|
|
12
|
-
background:
|
|
13
|
-
border-radius:
|
|
26
|
+
background: #1f2937;
|
|
27
|
+
border-radius: 3px;
|
|
14
28
|
border: 1px solid rgba(255, 255, 255, 0.03);
|
|
15
29
|
}
|
|
16
30
|
::-webkit-scrollbar-thumb:hover {
|
|
17
|
-
background:
|
|
31
|
+
background: #374151;
|
|
18
32
|
}
|
|
19
33
|
|
|
20
|
-
/* Glassmorphism and
|
|
34
|
+
/* Glassmorphism and Terminal UI Helpers */
|
|
21
35
|
@utility glass-card {
|
|
22
|
-
background: rgba(
|
|
23
|
-
backdrop-filter: blur(
|
|
24
|
-
-webkit-backdrop-filter: blur(
|
|
25
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
26
|
-
box-shadow: 0
|
|
36
|
+
background: rgba(5, 7, 12, 0.6) !important;
|
|
37
|
+
backdrop-filter: blur(12px);
|
|
38
|
+
-webkit-backdrop-filter: blur(12px);
|
|
39
|
+
border: 1px solid rgba(255, 255, 255, 0.04) !important;
|
|
40
|
+
box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.5) !important;
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
@utility glass-card-glow {
|
|
30
|
-
box-shadow: 0 0 15px rgba(
|
|
44
|
+
box-shadow: 0 0 15px rgba(6, 182, 212, 0.05), inset 0 0 1px 1px rgba(255, 255, 255, 0.03);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@utility text-glow-cyan {
|
|
48
|
+
text-shadow: 0 0 8px rgba(6, 182, 212, 0.4);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@utility text-glow-green {
|
|
52
|
+
text-shadow: 0 0 8px rgba(16, 185, 129, 0.4);
|
|
31
53
|
}
|
|
32
54
|
|
|
33
|
-
@utility
|
|
34
|
-
|
|
55
|
+
@utility neon-border {
|
|
56
|
+
box-shadow: 0 0 10px rgba(6, 182, 212, 0.1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@utility neon-border-green {
|
|
60
|
+
box-shadow: 0 0 10px rgba(16, 185, 129, 0.1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* CRT Scanline effect */
|
|
64
|
+
.crt-screen {
|
|
65
|
+
position: relative;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.crt-screen::after {
|
|
69
|
+
content: " ";
|
|
70
|
+
display: block;
|
|
71
|
+
position: absolute;
|
|
72
|
+
top: 0; left: 0; bottom: 0; right: 0;
|
|
73
|
+
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.2) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.04), rgba(0, 255, 0, 0.01), rgba(0, 255, 0, 0.04));
|
|
74
|
+
z-index: 10;
|
|
75
|
+
background-size: 100% 4px, 6px 100%;
|
|
76
|
+
pointer-events: none;
|
|
77
|
+
opacity: 0.35;
|
|
35
78
|
}
|
|
36
79
|
|
|
37
80
|
@utility animate-slide-in {
|
|
@@ -50,13 +93,13 @@
|
|
|
50
93
|
animation: pulse-glow-green 2s infinite ease-in-out;
|
|
51
94
|
}
|
|
52
95
|
|
|
53
|
-
@utility animate-pulse-glow-
|
|
54
|
-
animation: pulse-glow-
|
|
96
|
+
@utility animate-pulse-glow-cyan {
|
|
97
|
+
animation: pulse-glow-cyan 2.5s infinite ease-in-out;
|
|
55
98
|
}
|
|
56
99
|
|
|
57
100
|
@keyframes slide-in {
|
|
58
101
|
from {
|
|
59
|
-
transform: translateY(0.
|
|
102
|
+
transform: translateY(0.5rem);
|
|
60
103
|
opacity: 0;
|
|
61
104
|
}
|
|
62
105
|
to {
|
|
@@ -76,21 +119,21 @@
|
|
|
76
119
|
|
|
77
120
|
@keyframes pulse-glow-green {
|
|
78
121
|
0%, 100% {
|
|
79
|
-
box-shadow: 0 0 4px rgba(52, 211, 153, 0.
|
|
122
|
+
box-shadow: 0 0 4px rgba(52, 211, 153, 0.15);
|
|
80
123
|
opacity: 0.8;
|
|
81
124
|
}
|
|
82
125
|
50% {
|
|
83
|
-
box-shadow: 0 0
|
|
126
|
+
box-shadow: 0 0 10px rgba(52, 211, 153, 0.4);
|
|
84
127
|
opacity: 1;
|
|
85
128
|
}
|
|
86
129
|
}
|
|
87
130
|
|
|
88
|
-
@keyframes pulse-glow-
|
|
131
|
+
@keyframes pulse-glow-cyan {
|
|
89
132
|
0%, 100% {
|
|
90
|
-
box-shadow: 0 0 4px rgba(
|
|
133
|
+
box-shadow: 0 0 4px rgba(6, 182, 212, 0.15);
|
|
91
134
|
}
|
|
92
135
|
50% {
|
|
93
|
-
box-shadow: 0 0
|
|
136
|
+
box-shadow: 0 0 12px rgba(6, 182, 212, 0.4);
|
|
94
137
|
}
|
|
95
138
|
}
|
|
96
139
|
|
|
@@ -107,4 +150,3 @@
|
|
|
107
150
|
color: #e5e7eb;
|
|
108
151
|
background-color: #0b0f19;
|
|
109
152
|
}
|
|
110
|
-
|
package/gui/src/main.tsx
CHANGED
|
@@ -3,8 +3,92 @@ import { createRoot } from 'react-dom/client'
|
|
|
3
3
|
import './index.css'
|
|
4
4
|
import App from './App.tsx'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
Neutralino?: any;
|
|
9
|
+
NL_PATH?: string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function waitForBackend(url: string, maxRetries = 25, delay = 200): Promise<boolean> {
|
|
14
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
15
|
+
try {
|
|
16
|
+
const res = await fetch(url);
|
|
17
|
+
if (res.ok) {
|
|
18
|
+
console.log(`Backend connection established on attempt ${i + 1}`);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// Ignored, retry
|
|
23
|
+
}
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
25
|
+
}
|
|
26
|
+
console.warn(`Backend connection timed out after ${maxRetries} attempts`);
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function renderApp() {
|
|
31
|
+
createRoot(document.getElementById('root')!).render(
|
|
32
|
+
<StrictMode>
|
|
33
|
+
<App />
|
|
34
|
+
</StrictMode>,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (typeof window !== 'undefined' && window.Neutralino) {
|
|
39
|
+
window.Neutralino.init();
|
|
40
|
+
window.Neutralino.events.on('windowClose', () => {
|
|
41
|
+
window.Neutralino.app.exit();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
(async () => {
|
|
45
|
+
const backendUrl = 'http://localhost:3000/api/config';
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(backendUrl);
|
|
48
|
+
if (res.ok) {
|
|
49
|
+
console.log('NexusFlow Hono backend is already running.');
|
|
50
|
+
renderApp();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
console.log('NexusFlow Hono backend not detected. Launching...');
|
|
55
|
+
try {
|
|
56
|
+
const isWin = navigator.platform.includes('Win') || navigator.userAgent.includes('Windows');
|
|
57
|
+
const nlPath = window.NL_PATH || '.';
|
|
58
|
+
|
|
59
|
+
// Construct paths for packaged mode
|
|
60
|
+
const nodeBinary = isWin ? `${nlPath}/node/node.exe` : `${nlPath}/node/bin/node`;
|
|
61
|
+
const serverScript = `${nlPath}/server/dist/index.js`;
|
|
62
|
+
|
|
63
|
+
// Check if we are running in packaged mode by testing if the embedded node exists
|
|
64
|
+
let isPackaged = false;
|
|
65
|
+
try {
|
|
66
|
+
await window.Neutralino.filesystem.getStats(nodeBinary);
|
|
67
|
+
isPackaged = true;
|
|
68
|
+
} catch {
|
|
69
|
+
// File doesn't exist or filesystem API failed, meaning dev mode
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let cmd: string;
|
|
73
|
+
if (isPackaged) {
|
|
74
|
+
console.log('Running in packaged mode, using embedded node and server...');
|
|
75
|
+
cmd = `"${nodeBinary}" "${serverScript}" ui --server-only --port 3000`;
|
|
76
|
+
} else {
|
|
77
|
+
console.log('Running in development mode, using global node and relative path...');
|
|
78
|
+
cmd = 'node ../NexusFlow/dist/index.js ui --server-only --port 3000';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log('Spawning backend command:', cmd);
|
|
82
|
+
await window.Neutralino.os.execCommand(cmd, { background: true });
|
|
83
|
+
console.log('Hono backend successfully spawned. Waiting for port 3000...');
|
|
84
|
+
await waitForBackend(backendUrl);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error('Failed to spawn Hono backend:', err);
|
|
87
|
+
} finally {
|
|
88
|
+
renderApp();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
} else {
|
|
93
|
+
renderApp();
|
|
94
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrpatronz/nexusflow",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "Combine multiple repos into a workspace with rich AI assistant context",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"nexusflow": "dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc && npm run build --prefix gui
|
|
11
|
+
"build": "tsc && npm run build --prefix gui",
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "node dist/index.js",
|
|
14
14
|
"ui": "node dist/index.js ui",
|
|
@@ -34,23 +34,22 @@
|
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@hono/node-server": "^2.0.4",
|
|
37
|
-
"@inquirer/prompts": "^
|
|
37
|
+
"@inquirer/prompts": "^8.5.2",
|
|
38
38
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
39
39
|
"chalk": "^5.3.0",
|
|
40
|
-
"commander": "^
|
|
40
|
+
"commander": "^15.0.0",
|
|
41
41
|
"execa": "^9.5.0",
|
|
42
42
|
"fs-extra": "^11.2.0",
|
|
43
|
-
"globby": "^
|
|
44
|
-
"hono": "^4.12.
|
|
45
|
-
"ora": "^
|
|
46
|
-
"pm2": "^7.0.1"
|
|
47
|
-
"repomix": "^1.14.1"
|
|
43
|
+
"globby": "^16.2.0",
|
|
44
|
+
"hono": "^4.12.25",
|
|
45
|
+
"ora": "^9.4.0",
|
|
46
|
+
"pm2": "^7.0.1"
|
|
48
47
|
},
|
|
49
48
|
"devDependencies": {
|
|
50
49
|
"@types/fs-extra": "^11.0.4",
|
|
51
|
-
"@types/node": "^
|
|
50
|
+
"@types/node": "^25.9.3",
|
|
52
51
|
"rimraf": "^6.0.0",
|
|
53
|
-
"typescript": "^
|
|
54
|
-
"vitest": "^
|
|
52
|
+
"typescript": "^6.0.3",
|
|
53
|
+
"vitest": "^4.1.8"
|
|
55
54
|
}
|
|
56
55
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Team Cooperation Guidelines
|
|
2
|
+
|
|
3
|
+
You are the lead developer. You must coordinate a Plan-Implement-Review loop to complete the task:
|
|
4
|
+
|
|
5
|
+
1. **Research & Plan**: Research the requirements and codebase first. Create a plan (`implementation_plan.md`) describing the proposed changes.
|
|
6
|
+
2. **Implement**: Define a `Code_Implementer` subagent equipped with code editing and terminal tools. Send them the plan and instruct them to write the changes.
|
|
7
|
+
3. **Review**: Once implemented, define a `Code_Reviewer` subagent to run verification tests and review the changes for correctness.
|
|
8
|
+
4. **Loop**: If the reviewer finds bugs or test failures, send the feedback back to the implementer and repeat the cycle until the changes are approved.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Team Cooperation Guidelines
|
|
2
|
+
|
|
3
|
+
You are the lead investigator. You must coordinate a research-heavy cycle:
|
|
4
|
+
|
|
5
|
+
1. **Deep Research**: Define a `Research_Specialist` subagent to scan the codebase, find dependencies, and write a thorough context guide outlining how the system works.
|
|
6
|
+
2. **Test-Driven Implement**: Write test suites first based on the research findings, then spawn a developer subagent to code until all tests pass successfully.
|
package/skills-lock.json
ADDED