@mrpatronz/nexusflow 0.2.19 → 1.3.0
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/README.md +27 -3
- package/dist/analyzers/index.d.ts +23 -0
- package/dist/analyzers/index.d.ts.map +1 -1
- package/dist/analyzers/index.js +62 -0
- package/dist/analyzers/index.js.map +1 -1
- package/dist/commands/commands.test.js +20 -6
- package/dist/commands/commands.test.js.map +1 -1
- package/dist/commands/commit.d.ts +2 -0
- package/dist/commands/commit.d.ts.map +1 -1
- package/dist/commands/commit.js +27 -5
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/diff.d.ts +9 -2
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +36 -12
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff.js +2 -2
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/refresh.d.ts +4 -2
- package/dist/commands/refresh.d.ts.map +1 -1
- package/dist/commands/refresh.js +20 -36
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/schedule.d.ts +35 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +151 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +28 -7
- package/dist/commands/sync.js.map +1 -1
- package/dist/core/analysis-cache.d.ts +58 -0
- package/dist/core/analysis-cache.d.ts.map +1 -0
- package/dist/core/analysis-cache.js +116 -0
- package/dist/core/analysis-cache.js.map +1 -0
- package/dist/core/analysis-cache.test.d.ts +2 -0
- package/dist/core/analysis-cache.test.d.ts.map +1 -0
- package/dist/core/analysis-cache.test.js +108 -0
- package/dist/core/analysis-cache.test.js.map +1 -0
- package/dist/core/refresh.d.ts +41 -0
- package/dist/core/refresh.d.ts.map +1 -0
- package/dist/core/refresh.js +60 -0
- package/dist/core/refresh.js.map +1 -0
- package/dist/core/scheduler.d.ts +117 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +247 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/scheduler.test.d.ts +2 -0
- package/dist/core/scheduler.test.d.ts.map +1 -0
- package/dist/core/scheduler.test.js +111 -0
- package/dist/core/scheduler.test.js.map +1 -0
- package/dist/core/sync.d.ts +6 -0
- package/dist/core/sync.d.ts.map +1 -1
- package/dist/core/sync.js +15 -5
- package/dist/core/sync.js.map +1 -1
- package/dist/generators/index.d.ts +7 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +14 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/index.js +107 -4
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +81 -0
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +66 -0
- package/dist/server.test.js.map +1 -1
- package/dist/utils/multi-git.d.ts +21 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +40 -4
- package/dist/utils/multi-git.js.map +1 -1
- package/package.json +13 -1
- package/.agents/skills/ccc/SKILL.md +0 -71
- package/.agents/skills/ccc/references/management.md +0 -110
- package/.agents/skills/ccc/references/settings.md +0 -126
- package/.github/dependabot.yml +0 -52
- package/.github/workflows/ci.yml +0 -44
- package/.github/workflows/dependabot-merge.yml +0 -53
- package/.github/workflows/release-desktop.yml +0 -67
- package/.github/workflows/release-npm.yml +0 -65
- package/.github/workflows/release-vscode.yml +0 -61
- package/.vscode/launch.json +0 -17
- package/.vscode/tasks.json +0 -17
- package/GETTING_STARTED.md +0 -114
- package/desktop/build-installer.js +0 -228
- package/desktop/build.js +0 -118
- package/desktop/installer/nexusflow.iss +0 -35
- package/desktop/neutralino.config.json +0 -39
- package/desktop/package-lock.json +0 -1060
- package/desktop/package.json +0 -14
- package/extension/media/icon.svg +0 -1
- package/extension/package-lock.json +0 -6044
- package/extension/package.json +0 -117
- package/extension/src/extension.ts +0 -653
- package/extension/tsconfig.json +0 -21
- package/gui/README.md +0 -73
- package/gui/e2e/dashboard.spec.ts +0 -61
- package/gui/e2e/wizard.spec.ts +0 -346
- package/gui/eslint.config.js +0 -26
- package/gui/index.html +0 -17
- package/gui/package-lock.json +0 -3137
- package/gui/package.json +0 -37
- package/gui/playwright.config.ts +0 -41
- package/gui/public/app_logo.png +0 -0
- package/gui/public/favicon.svg +0 -1
- package/gui/public/icons.svg +0 -24
- package/gui/src/App.css +0 -1
- package/gui/src/App.tsx +0 -3573
- package/gui/src/app/AppSidebar.tsx +0 -69
- package/gui/src/assets/hero.png +0 -0
- package/gui/src/assets/react.svg +0 -1
- package/gui/src/assets/vite.svg +0 -1
- package/gui/src/components/AddRepoPicker.tsx +0 -81
- package/gui/src/components/ui/Button.tsx +0 -40
- package/gui/src/components/ui/Card.tsx +0 -6
- package/gui/src/components/ui/EmptyState.tsx +0 -22
- package/gui/src/components/ui/Input.tsx +0 -21
- package/gui/src/components/ui/Menu.tsx +0 -71
- package/gui/src/components/ui/Modal.tsx +0 -39
- package/gui/src/components/ui/PageHeader.tsx +0 -21
- package/gui/src/components/ui/RepoStatusStrip.tsx +0 -33
- package/gui/src/components/ui/Skeleton.tsx +0 -5
- package/gui/src/components/ui/StatusPill.tsx +0 -36
- package/gui/src/components/ui/Tabs.tsx +0 -40
- package/gui/src/components/ui/cn.ts +0 -4
- package/gui/src/components/ui/index.ts +0 -16
- package/gui/src/features/changes/ChangesViewer.tsx +0 -388
- package/gui/src/features/knowledge/KnowledgeBase.tsx +0 -84
- package/gui/src/features/onboarding/OnboardingWizard.tsx +0 -230
- package/gui/src/features/plan/ImplementationPlan.tsx +0 -32
- package/gui/src/features/services/ServiceConsole.tsx +0 -215
- package/gui/src/features/sessions/SessionHistory.tsx +0 -195
- package/gui/src/index.css +0 -167
- package/gui/src/lib/status.ts +0 -24
- package/gui/src/main.tsx +0 -94
- package/gui/src/pages/DashboardPage.tsx +0 -129
- package/gui/src/pages/WorkspacesPage.tsx +0 -352
- package/gui/src/types.ts +0 -81
- package/gui/tsconfig.app.json +0 -25
- package/gui/tsconfig.json +0 -7
- package/gui/tsconfig.node.json +0 -24
- package/gui/vite.config.ts +0 -12
- package/resources/workflows/plan-implement-review.md +0 -8
- package/resources/workflows/research-verify.md +0 -6
- package/resources/workflows/solo-developer.md +0 -3
- package/scripts/simulate-workspaces.ts +0 -55
- package/skills-lock.json +0 -11
- package/src/analyzers/detect-apis.ts +0 -290
- package/src/analyzers/detect-deps.ts +0 -315
- package/src/analyzers/detect-existing.ts +0 -74
- package/src/analyzers/detect-ports.ts +0 -110
- package/src/analyzers/index.ts +0 -97
- package/src/analyzers/messaging-analyzer.ts +0 -254
- package/src/analyzers/readme-summarizer.ts +0 -102
- package/src/analyzers/run-analyzer.ts +0 -269
- package/src/analyzers/tech-stack.ts +0 -283
- package/src/commands/adapter.ts +0 -348
- package/src/commands/add-repo.ts +0 -156
- package/src/commands/commands.test.ts +0 -156
- package/src/commands/commit.ts +0 -131
- package/src/commands/config.ts +0 -52
- package/src/commands/create.ts +0 -204
- package/src/commands/desktop.ts +0 -128
- package/src/commands/diff.ts +0 -125
- package/src/commands/doctor.ts +0 -370
- package/src/commands/handoff.ts +0 -266
- package/src/commands/init.ts +0 -134
- package/src/commands/list.ts +0 -46
- package/src/commands/logs.ts +0 -63
- package/src/commands/mcp.ts +0 -94
- package/src/commands/open.ts +0 -129
- package/src/commands/refresh.ts +0 -137
- package/src/commands/remove.ts +0 -98
- package/src/commands/start.ts +0 -117
- package/src/commands/status.ts +0 -54
- package/src/commands/stop.ts +0 -55
- package/src/commands/sync.ts +0 -125
- package/src/commands/tui.ts +0 -484
- package/src/commands/ui.ts +0 -111
- package/src/core/adapters/local-storage.ts +0 -66
- package/src/core/adapters/obsidian-storage.ts +0 -151
- package/src/core/adapters/registry.ts +0 -44
- package/src/core/adapters/storage.test.ts +0 -174
- package/src/core/adapters/vault-storage.ts +0 -86
- package/src/core/config.test.ts +0 -96
- package/src/core/config.ts +0 -140
- package/src/core/graph.ts +0 -344
- package/src/core/plugins/index.ts +0 -17
- package/src/core/plugins/loader.ts +0 -36
- package/src/core/ports/storage.ts +0 -71
- package/src/core/scanner.test.ts +0 -61
- package/src/core/scanner.ts +0 -91
- package/src/core/storage.ts +0 -37
- package/src/core/sync.ts +0 -121
- package/src/core/workspace-state.test.ts +0 -108
- package/src/core/workspace-state.ts +0 -130
- package/src/core/workspace.ts +0 -487
- package/src/core/worktree.ts +0 -120
- package/src/generators/antigravity.ts +0 -32
- package/src/generators/base.ts +0 -243
- package/src/generators/claude.ts +0 -34
- package/src/generators/codex.ts +0 -48
- package/src/generators/copilot.ts +0 -56
- package/src/generators/cursor.ts +0 -44
- package/src/generators/diff-context.ts +0 -75
- package/src/generators/index.ts +0 -322
- package/src/generators/map-generator.test.ts +0 -159
- package/src/generators/map-generator.ts +0 -539
- package/src/generators/plan-generator.ts +0 -483
- package/src/generators/skills-generator.ts +0 -259
- package/src/index.ts +0 -539
- package/src/mcp/server.ts +0 -338
- package/src/orchestration/detect.ts +0 -313
- package/src/orchestration/index.ts +0 -7
- package/src/orchestration/runner.ts +0 -283
- package/src/server.test.ts +0 -618
- package/src/server.ts +0 -1402
- package/src/types.ts +0 -451
- package/src/utils/detect-ai.test.ts +0 -44
- package/src/utils/detect-ai.ts +0 -84
- package/src/utils/detect-editors.test.ts +0 -48
- package/src/utils/detect-editors.ts +0 -57
- package/src/utils/git.test.ts +0 -74
- package/src/utils/git.ts +0 -117
- package/src/utils/local-ai.test.ts +0 -130
- package/src/utils/local-ai.ts +0 -116
- package/src/utils/multi-git.test.ts +0 -158
- package/src/utils/multi-git.ts +0 -405
- package/src/utils/prompts.ts +0 -209
- package/src/utils/session-finder.ts +0 -483
- package/src/utils/system-scanner.test.ts +0 -89
- package/src/utils/system-scanner.ts +0 -96
- package/src/utils/update-check.ts +0 -286
- package/src/utils/workflow-advisor.ts +0 -118
- package/src/utils/workflows.test.ts +0 -114
- package/src/utils/workflows.ts +0 -178
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -14
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
import { useMemo, useState, type ComponentProps } from 'react';
|
|
2
|
-
import { RefreshCw, Play, MoreVertical, ExternalLink, Sparkles, Trash2, Search, FolderGit2 } from 'lucide-react';
|
|
3
|
-
import type { Feature, WorkspaceStatus, RepoInfo } from '../types.js';
|
|
4
|
-
import { Button, Card, EmptyState, Menu, PageHeader, StatusPill, Tabs, Input, Skeleton, cn } from '../components/ui/index.js';
|
|
5
|
-
import type { TabItem } from '../components/ui/index.js';
|
|
6
|
-
import { AddRepoPicker } from '../components/AddRepoPicker.js';
|
|
7
|
-
import { syncMeta, repoName } from '../lib/status.js';
|
|
8
|
-
import { SessionHistory } from '../features/sessions/SessionHistory.js';
|
|
9
|
-
import { ServiceConsole } from '../features/services/ServiceConsole.js';
|
|
10
|
-
import { ChangesViewer } from '../features/changes/ChangesViewer.js';
|
|
11
|
-
import { KnowledgeBase } from '../features/knowledge/KnowledgeBase.js';
|
|
12
|
-
import { ImplementationPlan } from '../features/plan/ImplementationPlan.js';
|
|
13
|
-
|
|
14
|
-
type SubTab = 'overview' | 'sessions' | 'services' | 'changes' | 'knowledge' | 'plan';
|
|
15
|
-
|
|
16
|
-
const TABS: TabItem[] = [
|
|
17
|
-
{ value: 'overview', label: 'Overview' },
|
|
18
|
-
{ value: 'changes', label: 'Changes' },
|
|
19
|
-
{ value: 'services', label: 'Services' },
|
|
20
|
-
{ value: 'sessions', label: 'Sessions' },
|
|
21
|
-
{ value: 'knowledge', label: 'Knowledge' },
|
|
22
|
-
{ value: 'plan', label: 'Plan' },
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
const FILTERS = ['all', 'changes', 'running'] as const;
|
|
26
|
-
type Filter = (typeof FILTERS)[number];
|
|
27
|
-
|
|
28
|
-
interface WorkspacesPageProps {
|
|
29
|
-
workspaces: Feature[];
|
|
30
|
-
workspaceStatuses: Record<string, WorkspaceStatus>;
|
|
31
|
-
statusesLoading: boolean;
|
|
32
|
-
workspacesLoading: boolean;
|
|
33
|
-
fetchWorkspaces: () => Promise<void>;
|
|
34
|
-
selectedId: string | null;
|
|
35
|
-
subTab: SubTab;
|
|
36
|
-
onSelect: (id: string) => void;
|
|
37
|
-
onSelectTab: (id: string, tab: SubTab) => void;
|
|
38
|
-
resumingWs: string | null;
|
|
39
|
-
handleResumeSession: (ws: Feature, sessionId?: string, assistant?: string) => Promise<void>;
|
|
40
|
-
handleCopyPrompt: (ws: Feature) => void;
|
|
41
|
-
handleOpenInEditor: (workspacePath: string) => Promise<void>;
|
|
42
|
-
handleDeleteWorkspace: (wsName: string) => Promise<void>;
|
|
43
|
-
deleteWsLoading: string | null;
|
|
44
|
-
repos: RepoInfo[];
|
|
45
|
-
addRepoLoading: boolean;
|
|
46
|
-
handleAddRepo: (wsName: string, repoPath: string) => Promise<void>;
|
|
47
|
-
sessionProps: Omit<ComponentProps<typeof SessionHistory>, 'ws'>;
|
|
48
|
-
serviceProps: Omit<ComponentProps<typeof ServiceConsole>, 'ws'>;
|
|
49
|
-
changesProps: Omit<ComponentProps<typeof ChangesViewer>, 'ws'>;
|
|
50
|
-
knowledgeProps: Omit<ComponentProps<typeof KnowledgeBase>, 'ws'>;
|
|
51
|
-
planProps: ComponentProps<typeof ImplementationPlan>;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function WorkspacesPage(props: WorkspacesPageProps) {
|
|
55
|
-
const {
|
|
56
|
-
workspaces,
|
|
57
|
-
workspaceStatuses,
|
|
58
|
-
workspacesLoading,
|
|
59
|
-
fetchWorkspaces,
|
|
60
|
-
selectedId,
|
|
61
|
-
subTab,
|
|
62
|
-
onSelect,
|
|
63
|
-
onSelectTab,
|
|
64
|
-
resumingWs,
|
|
65
|
-
handleResumeSession,
|
|
66
|
-
handleCopyPrompt,
|
|
67
|
-
handleOpenInEditor,
|
|
68
|
-
handleDeleteWorkspace,
|
|
69
|
-
deleteWsLoading,
|
|
70
|
-
repos,
|
|
71
|
-
addRepoLoading,
|
|
72
|
-
handleAddRepo,
|
|
73
|
-
sessionProps,
|
|
74
|
-
serviceProps,
|
|
75
|
-
changesProps,
|
|
76
|
-
knowledgeProps,
|
|
77
|
-
planProps,
|
|
78
|
-
} = props;
|
|
79
|
-
|
|
80
|
-
const [query, setQuery] = useState('');
|
|
81
|
-
const [filter, setFilter] = useState<Filter>('all');
|
|
82
|
-
|
|
83
|
-
const selected = workspaces.find((w) => w.branchName === selectedId) ?? null;
|
|
84
|
-
|
|
85
|
-
const filtered = useMemo(() => {
|
|
86
|
-
const q = query.trim().toLowerCase();
|
|
87
|
-
return workspaces.filter((w) => {
|
|
88
|
-
const st = workspaceStatuses[w.branchName];
|
|
89
|
-
if (q && !`${w.branchName} ${w.description}`.toLowerCase().includes(q)) return false;
|
|
90
|
-
if (filter === 'changes' && !(st && st.changedFiles > 0)) return false;
|
|
91
|
-
if (filter === 'running' && !(st && st.runningServices > 0)) return false;
|
|
92
|
-
return true;
|
|
93
|
-
});
|
|
94
|
-
}, [workspaces, workspaceStatuses, query, filter]);
|
|
95
|
-
|
|
96
|
-
const repoRows = selected
|
|
97
|
-
? selected.repos.map((rp) => {
|
|
98
|
-
const name = repoName(rp);
|
|
99
|
-
const change = changesProps.gitChanges?.find((c: { repoName: string; files?: unknown[] }) => c.repoName === name);
|
|
100
|
-
const changedCount: number | null = change ? change.files?.length ?? 0 : null;
|
|
101
|
-
const svcs = (serviceProps.services ?? []).filter((s) => (s.cwd ?? '').split(/[\\/]/).includes(name));
|
|
102
|
-
const ports = Array.from(new Set(svcs.map((s) => s.port).filter((p): p is number => typeof p === 'number')));
|
|
103
|
-
return { name, changedCount, ports, serviceCount: svcs.length };
|
|
104
|
-
})
|
|
105
|
-
: [];
|
|
106
|
-
|
|
107
|
-
const availableRepos = selected ? repos.filter((r) => !selected.repos.includes(r.path)) : [];
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<div className="mx-auto max-w-7xl animate-fade-in">
|
|
111
|
-
<PageHeader
|
|
112
|
-
title="Workspaces"
|
|
113
|
-
subtitle="Select a workspace to inspect its changes, services, sessions and context."
|
|
114
|
-
actions={
|
|
115
|
-
<Button
|
|
116
|
-
variant="secondary"
|
|
117
|
-
icon={<RefreshCw size={14} className={workspacesLoading ? 'animate-spin text-accent' : ''} />}
|
|
118
|
-
onClick={fetchWorkspaces}
|
|
119
|
-
disabled={workspacesLoading}
|
|
120
|
-
>
|
|
121
|
-
Refresh
|
|
122
|
-
</Button>
|
|
123
|
-
}
|
|
124
|
-
/>
|
|
125
|
-
|
|
126
|
-
<div className="flex flex-col gap-5 lg:flex-row">
|
|
127
|
-
{/* ── List pane ─────────────────────────────────────────── */}
|
|
128
|
-
<div className="lg:w-80 lg:shrink-0">
|
|
129
|
-
<div className="relative mb-3">
|
|
130
|
-
<Search size={14} className="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-content-faint" />
|
|
131
|
-
<Input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search workspaces" className="pl-8" />
|
|
132
|
-
</div>
|
|
133
|
-
<div className="mb-3 flex items-center gap-1">
|
|
134
|
-
{FILTERS.map((f) => (
|
|
135
|
-
<button
|
|
136
|
-
key={f}
|
|
137
|
-
onClick={() => setFilter(f)}
|
|
138
|
-
className={cn(
|
|
139
|
-
'rounded-md px-2.5 py-1 text-xs font-medium capitalize transition-colors cursor-pointer',
|
|
140
|
-
filter === f ? 'bg-accent-soft text-accent' : 'text-content-faint hover:text-content',
|
|
141
|
-
)}
|
|
142
|
-
>
|
|
143
|
-
{f}
|
|
144
|
-
</button>
|
|
145
|
-
))}
|
|
146
|
-
</div>
|
|
147
|
-
|
|
148
|
-
{workspacesLoading ? (
|
|
149
|
-
<div className="flex flex-col gap-1.5">
|
|
150
|
-
{[0, 1, 2, 3].map((i) => (
|
|
151
|
-
<Skeleton key={i} className="h-14" />
|
|
152
|
-
))}
|
|
153
|
-
</div>
|
|
154
|
-
) : filtered.length === 0 ? (
|
|
155
|
-
<Card className="p-6 text-center text-sm text-content-muted">No workspaces match.</Card>
|
|
156
|
-
) : (
|
|
157
|
-
<div className="flex flex-col gap-1.5">
|
|
158
|
-
{filtered.map((w) => {
|
|
159
|
-
const st = workspaceStatuses[w.branchName];
|
|
160
|
-
const active = w.branchName === selectedId;
|
|
161
|
-
const sync = st ? syncMeta(st.syncStatus) : null;
|
|
162
|
-
return (
|
|
163
|
-
<button
|
|
164
|
-
key={w.id}
|
|
165
|
-
onClick={() => onSelect(w.branchName)}
|
|
166
|
-
className={cn(
|
|
167
|
-
'rounded-lg border p-3 text-left transition-colors cursor-pointer',
|
|
168
|
-
active ? 'border-accent/50 bg-accent-soft' : 'border-hairline bg-surface hover:border-hairline-strong hover:bg-raised',
|
|
169
|
-
)}
|
|
170
|
-
>
|
|
171
|
-
<div className="flex items-center justify-between gap-2">
|
|
172
|
-
<span className="truncate font-mono text-sm font-semibold text-content">{w.branchName}</span>
|
|
173
|
-
<span className="shrink-0 text-[11px] text-content-faint">{w.repos.length} repos</span>
|
|
174
|
-
</div>
|
|
175
|
-
<div className="mt-1.5 flex items-center gap-2">
|
|
176
|
-
<span
|
|
177
|
-
className={cn('h-1.5 w-1.5 rounded-full', st?.changedFiles ? 'bg-warning' : 'bg-success')}
|
|
178
|
-
title={st?.changedFiles ? `${st.changedFiles} uncommitted` : 'Clean'}
|
|
179
|
-
/>
|
|
180
|
-
{st?.runningServices ? <span className="h-1.5 w-1.5 rounded-full bg-running" title="Running services" /> : null}
|
|
181
|
-
{sync && <span className="text-[11px] text-content-faint">{sync.label}</span>}
|
|
182
|
-
</div>
|
|
183
|
-
</button>
|
|
184
|
-
);
|
|
185
|
-
})}
|
|
186
|
-
</div>
|
|
187
|
-
)}
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
{/* ── Detail pane ───────────────────────────────────────── */}
|
|
191
|
-
<div className="min-w-0 flex-1">
|
|
192
|
-
{!selected ? (
|
|
193
|
-
<Card>
|
|
194
|
-
<EmptyState
|
|
195
|
-
icon={<FolderGit2 size={40} />}
|
|
196
|
-
title="No workspace selected"
|
|
197
|
-
description="Pick a workspace from the list to see its status, repositories, changes, services and sessions."
|
|
198
|
-
/>
|
|
199
|
-
</Card>
|
|
200
|
-
) : (
|
|
201
|
-
<div>
|
|
202
|
-
<Card className="mb-4 p-5">
|
|
203
|
-
<div className="flex items-start justify-between gap-4">
|
|
204
|
-
<div className="min-w-0">
|
|
205
|
-
<h2 className="font-display text-xl font-bold text-content">{selected.branchName}</h2>
|
|
206
|
-
<div className="mt-1 flex items-center gap-2 text-xs text-content-faint">
|
|
207
|
-
<span>Created {new Date(selected.createdAt).toLocaleDateString()}</span>
|
|
208
|
-
<span>·</span>
|
|
209
|
-
<span>{selected.repos.length} repos</span>
|
|
210
|
-
</div>
|
|
211
|
-
</div>
|
|
212
|
-
<div className="flex shrink-0 items-center gap-2">
|
|
213
|
-
<Button
|
|
214
|
-
variant="primary"
|
|
215
|
-
icon={<Play size={13} className={resumingWs === selected.branchName ? 'animate-spin' : ''} />}
|
|
216
|
-
disabled={resumingWs === selected.branchName}
|
|
217
|
-
onClick={() => handleResumeSession(selected)}
|
|
218
|
-
>
|
|
219
|
-
{resumingWs === selected.branchName ? 'Resuming…' : 'Resume in Editor'}
|
|
220
|
-
</Button>
|
|
221
|
-
<Menu
|
|
222
|
-
label="More actions"
|
|
223
|
-
trigger={
|
|
224
|
-
<span className="grid h-9 w-9 place-items-center rounded-md border border-hairline bg-surface text-content-muted hover:bg-raised hover:text-content">
|
|
225
|
-
<MoreVertical size={16} />
|
|
226
|
-
</span>
|
|
227
|
-
}
|
|
228
|
-
items={[
|
|
229
|
-
{ label: 'Open Folder', icon: <ExternalLink size={14} />, onClick: () => void handleOpenInEditor(selected.workspacePath) },
|
|
230
|
-
{ label: 'Copy AI Context', icon: <Sparkles size={14} className="text-accent" />, onClick: () => handleCopyPrompt(selected) },
|
|
231
|
-
{
|
|
232
|
-
label: deleteWsLoading === selected.branchName ? 'Deleting…' : 'Delete Workspace',
|
|
233
|
-
icon: <Trash2 size={14} />,
|
|
234
|
-
danger: true,
|
|
235
|
-
disabled: deleteWsLoading === selected.branchName,
|
|
236
|
-
onClick: () => void handleDeleteWorkspace(selected.branchName),
|
|
237
|
-
},
|
|
238
|
-
]}
|
|
239
|
-
/>
|
|
240
|
-
</div>
|
|
241
|
-
</div>
|
|
242
|
-
|
|
243
|
-
<div className="mt-3 flex flex-wrap items-center gap-2">
|
|
244
|
-
{(() => {
|
|
245
|
-
const st = workspaceStatuses[selected.branchName];
|
|
246
|
-
if (!st) return null;
|
|
247
|
-
const sync = syncMeta(st.syncStatus);
|
|
248
|
-
return (
|
|
249
|
-
<>
|
|
250
|
-
{st.changedFiles > 0 ? (
|
|
251
|
-
<StatusPill tone="warning" dot>
|
|
252
|
-
{st.changedFiles} uncommitted
|
|
253
|
-
</StatusPill>
|
|
254
|
-
) : (
|
|
255
|
-
<StatusPill tone="idle" dot>
|
|
256
|
-
Clean
|
|
257
|
-
</StatusPill>
|
|
258
|
-
)}
|
|
259
|
-
{st.runningServices > 0 ? (
|
|
260
|
-
<StatusPill tone="running" dot>
|
|
261
|
-
{st.runningServices} running
|
|
262
|
-
</StatusPill>
|
|
263
|
-
) : (
|
|
264
|
-
<StatusPill tone="idle" dot>
|
|
265
|
-
No services
|
|
266
|
-
</StatusPill>
|
|
267
|
-
)}
|
|
268
|
-
<StatusPill tone={sync.tone}>
|
|
269
|
-
<RefreshCw size={11} /> {sync.label}
|
|
270
|
-
</StatusPill>
|
|
271
|
-
{st.pendingValidation && <StatusPill tone="warning">Needs validation</StatusPill>}
|
|
272
|
-
</>
|
|
273
|
-
);
|
|
274
|
-
})()}
|
|
275
|
-
</div>
|
|
276
|
-
</Card>
|
|
277
|
-
|
|
278
|
-
<Tabs items={TABS} value={subTab} onChange={(v) => onSelectTab(selected.branchName, v as SubTab)} className="mb-4" />
|
|
279
|
-
|
|
280
|
-
<div className="animate-fade-in">
|
|
281
|
-
{subTab === 'overview' && (
|
|
282
|
-
<div className="flex flex-col gap-4">
|
|
283
|
-
<Card className="p-5">
|
|
284
|
-
<h3 className="mb-2 font-display text-sm font-semibold text-content">Description</h3>
|
|
285
|
-
{selected.description ? (
|
|
286
|
-
<p className="whitespace-pre-line text-sm leading-relaxed text-content-muted">{selected.description}</p>
|
|
287
|
-
) : (
|
|
288
|
-
<p className="text-sm text-content-faint">No description provided.</p>
|
|
289
|
-
)}
|
|
290
|
-
</Card>
|
|
291
|
-
<Card className="p-5">
|
|
292
|
-
<div className="mb-4 flex items-center justify-between gap-3">
|
|
293
|
-
<h3 className="font-display text-sm font-semibold text-content">
|
|
294
|
-
Repositories <span className="text-content-faint">({selected.repos.length})</span>
|
|
295
|
-
</h3>
|
|
296
|
-
{availableRepos.length > 0 && (
|
|
297
|
-
<AddRepoPicker
|
|
298
|
-
repos={availableRepos}
|
|
299
|
-
disabled={addRepoLoading}
|
|
300
|
-
onAdd={(path) => {
|
|
301
|
-
if (
|
|
302
|
-
window.confirm(
|
|
303
|
-
`Add repository "${repoName(path)}" to this workspace?\nThis creates a new git worktree and re-runs analysis.`,
|
|
304
|
-
)
|
|
305
|
-
) {
|
|
306
|
-
void handleAddRepo(selected.branchName, path);
|
|
307
|
-
}
|
|
308
|
-
}}
|
|
309
|
-
/>
|
|
310
|
-
)}
|
|
311
|
-
</div>
|
|
312
|
-
<div className="divide-y divide-hairline">
|
|
313
|
-
{repoRows.map((r) => (
|
|
314
|
-
<div key={r.name} className="flex items-center gap-3 py-2.5 first:pt-0 last:pb-0">
|
|
315
|
-
<span
|
|
316
|
-
className={cn(
|
|
317
|
-
'h-2 w-2 shrink-0 rounded-full',
|
|
318
|
-
r.changedCount === null ? 'bg-idle' : r.changedCount > 0 ? 'bg-warning' : 'bg-success',
|
|
319
|
-
)}
|
|
320
|
-
title={r.changedCount === null ? 'Status unknown' : r.changedCount > 0 ? 'Uncommitted changes' : 'Clean'}
|
|
321
|
-
/>
|
|
322
|
-
<span className="min-w-0 flex-1 truncate font-mono text-sm text-content">{r.name}</span>
|
|
323
|
-
<div className="flex shrink-0 items-center gap-2">
|
|
324
|
-
{r.ports.map((p) => (
|
|
325
|
-
<span key={p} className="rounded border border-hairline bg-base px-1.5 py-0.5 font-mono text-[11px] text-running">
|
|
326
|
-
:{p}
|
|
327
|
-
</span>
|
|
328
|
-
))}
|
|
329
|
-
<span className="w-24 text-right text-xs text-content-faint">
|
|
330
|
-
{r.changedCount === null ? '—' : r.changedCount > 0 ? `${r.changedCount} changed` : 'clean'}
|
|
331
|
-
</span>
|
|
332
|
-
</div>
|
|
333
|
-
</div>
|
|
334
|
-
))}
|
|
335
|
-
</div>
|
|
336
|
-
<p className="mt-3 text-[11px] text-content-faint">Per-repo git state and detected service ports.</p>
|
|
337
|
-
</Card>
|
|
338
|
-
</div>
|
|
339
|
-
)}
|
|
340
|
-
{subTab === 'sessions' && <SessionHistory ws={selected} {...sessionProps} />}
|
|
341
|
-
{subTab === 'services' && <ServiceConsole ws={selected} {...serviceProps} />}
|
|
342
|
-
{subTab === 'changes' && <ChangesViewer ws={selected} {...changesProps} />}
|
|
343
|
-
{subTab === 'knowledge' && <KnowledgeBase ws={selected} {...knowledgeProps} />}
|
|
344
|
-
{subTab === 'plan' && <ImplementationPlan {...planProps} />}
|
|
345
|
-
</div>
|
|
346
|
-
</div>
|
|
347
|
-
)}
|
|
348
|
-
</div>
|
|
349
|
-
</div>
|
|
350
|
-
</div>
|
|
351
|
-
);
|
|
352
|
-
}
|
package/gui/src/types.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// Types matched with src/types.ts
|
|
2
|
-
|
|
3
|
-
export interface NexusFlowConfig {
|
|
4
|
-
version: string;
|
|
5
|
-
devDir: string;
|
|
6
|
-
workspacesDir: string;
|
|
7
|
-
defaultAssistant: string | null;
|
|
8
|
-
defaultEditor?: string | null;
|
|
9
|
-
scanDepth: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface DetectedAI {
|
|
13
|
-
name: string;
|
|
14
|
-
displayName: string;
|
|
15
|
-
detected: boolean;
|
|
16
|
-
command?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface DetectedEditor {
|
|
20
|
-
name: string;
|
|
21
|
-
command: string;
|
|
22
|
-
detected: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface RepoInfo {
|
|
26
|
-
name: string;
|
|
27
|
-
path: string;
|
|
28
|
-
defaultBranch: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface Feature {
|
|
32
|
-
id: string;
|
|
33
|
-
branchName: string;
|
|
34
|
-
description: string;
|
|
35
|
-
repos: string[];
|
|
36
|
-
assistants: string[];
|
|
37
|
-
workspacePath: string;
|
|
38
|
-
createdAt: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Classified outcome of a sync/rebase attempt for a repo (mirrors src/types.ts). */
|
|
42
|
-
export type SyncStatus = 'up-to-date' | 'rebased' | 'conflict' | 'stash-conflict' | 'error';
|
|
43
|
-
|
|
44
|
-
/** At-a-glance status for one workspace, from GET /api/workspaces/status. */
|
|
45
|
-
export interface WorkspaceStatus {
|
|
46
|
-
id: string;
|
|
47
|
-
branchName: string;
|
|
48
|
-
/** Total uncommitted files across all repo worktrees. */
|
|
49
|
-
changedFiles: number;
|
|
50
|
-
/** Number of repos with uncommitted changes. */
|
|
51
|
-
dirtyRepos: number;
|
|
52
|
-
/** Number of currently running orchestrated services. */
|
|
53
|
-
runningServices: number;
|
|
54
|
-
/** Worst-case sync classification across repos, or 'unknown' if never synced. */
|
|
55
|
-
syncStatus: SyncStatus | 'unknown';
|
|
56
|
-
/** True when any repo pulled in new commits and awaits re-validation. */
|
|
57
|
-
pendingValidation: boolean;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface ServiceConfig {
|
|
61
|
-
name: string;
|
|
62
|
-
cwd: string;
|
|
63
|
-
command: string;
|
|
64
|
-
args: string[];
|
|
65
|
-
port?: number;
|
|
66
|
-
source: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface OrchestrationDetection {
|
|
70
|
-
tool: string;
|
|
71
|
-
configPath: string;
|
|
72
|
-
startCommand: string;
|
|
73
|
-
stopCommand: string;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface RunningService {
|
|
77
|
-
name: string;
|
|
78
|
-
pid: number;
|
|
79
|
-
config: ServiceConfig;
|
|
80
|
-
startedAt: string;
|
|
81
|
-
}
|
package/gui/tsconfig.app.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "es2023",
|
|
5
|
-
"lib": ["ES2023", "DOM"],
|
|
6
|
-
"module": "esnext",
|
|
7
|
-
"types": ["vite/client"],
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
/* Bundler mode */
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
"jsx": "react-jsx",
|
|
17
|
-
|
|
18
|
-
/* Linting */
|
|
19
|
-
"noUnusedLocals": true,
|
|
20
|
-
"noUnusedParameters": true,
|
|
21
|
-
"erasableSyntaxOnly": true,
|
|
22
|
-
"noFallthroughCasesInSwitch": true
|
|
23
|
-
},
|
|
24
|
-
"include": ["src"]
|
|
25
|
-
}
|
package/gui/tsconfig.json
DELETED
package/gui/tsconfig.node.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
-
"target": "es2023",
|
|
5
|
-
"lib": ["ES2023"],
|
|
6
|
-
"module": "esnext",
|
|
7
|
-
"types": ["node"],
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
/* Bundler mode */
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
|
|
17
|
-
/* Linting */
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"erasableSyntaxOnly": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true
|
|
22
|
-
},
|
|
23
|
-
"include": ["vite.config.ts"]
|
|
24
|
-
}
|
package/gui/vite.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import react from '@vitejs/plugin-react'
|
|
3
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
4
|
-
|
|
5
|
-
// https://vite.dev/config/
|
|
6
|
-
export default defineConfig({
|
|
7
|
-
plugins: [react(), tailwindcss()],
|
|
8
|
-
build: {
|
|
9
|
-
outDir: '../dist/gui',
|
|
10
|
-
emptyOutDir: true,
|
|
11
|
-
},
|
|
12
|
-
})
|
|
@@ -1,8 +0,0 @@
|
|
|
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.
|
|
@@ -1,6 +0,0 @@
|
|
|
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.
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import * as os from 'node:os';
|
|
3
|
-
import { loadConfig } from '../src/core/config.js';
|
|
4
|
-
import { createWorkspace } from '../src/core/workspace.js';
|
|
5
|
-
import { analyzeAllRepos } from '../src/analyzers/index.js';
|
|
6
|
-
import { generateContextFiles } from '../src/generators/index.js';
|
|
7
|
-
|
|
8
|
-
async function main() {
|
|
9
|
-
const config = await loadConfig();
|
|
10
|
-
const repoPath = 'C:\\Users\\patro\\dev\\easyagent_container';
|
|
11
|
-
|
|
12
|
-
console.log('Creating Workspace 1: feat/rate-limiting-standard (Local LLM DISABLED)');
|
|
13
|
-
const ws1Path = path.join(config.workspacesDir, 'feat/rate-limiting-standard');
|
|
14
|
-
const feature1 = {
|
|
15
|
-
id: 'feat/rate-limiting-standard',
|
|
16
|
-
branchName: 'feat/rate-limiting-standard',
|
|
17
|
-
description: 'Implement rate limiting and connection pooling',
|
|
18
|
-
repos: [repoPath],
|
|
19
|
-
assistants: ['claude'],
|
|
20
|
-
workspacePath: ws1Path,
|
|
21
|
-
createdAt: new Date().toISOString(),
|
|
22
|
-
localLlmEnabled: false,
|
|
23
|
-
};
|
|
24
|
-
const repos1 = [{ name: 'easyagent_container', path: path.join(ws1Path, 'easyagent_container'), isGitRepo: true, defaultBranch: 'master' }];
|
|
25
|
-
|
|
26
|
-
await createWorkspace(feature1, [{ name: 'easyagent_container', path: repoPath, isGitRepo: true, defaultBranch: 'master' }]);
|
|
27
|
-
const analysis1 = await analyzeAllRepos(repos1);
|
|
28
|
-
const ctx1 = { feature: feature1, repos: repos1, analysis: analysis1 };
|
|
29
|
-
await generateContextFiles(ctx1, ['claude'], ws1Path);
|
|
30
|
-
console.log('✅ Workspace 1 created at:', ws1Path);
|
|
31
|
-
|
|
32
|
-
console.log('\nCreating Workspace 2: feat/rate-limiting-local-llm (Local LLM ENABLED)');
|
|
33
|
-
const ws2Path = path.join(config.workspacesDir, 'feat/rate-limiting-local-llm');
|
|
34
|
-
const feature2 = {
|
|
35
|
-
id: 'feat/rate-limiting-local-llm',
|
|
36
|
-
branchName: 'feat/rate-limiting-local-llm',
|
|
37
|
-
description: 'Implement rate limiting and connection pooling',
|
|
38
|
-
repos: [repoPath],
|
|
39
|
-
assistants: ['claude'],
|
|
40
|
-
workspacePath: ws2Path,
|
|
41
|
-
createdAt: new Date().toISOString(),
|
|
42
|
-
localLlmEnabled: true,
|
|
43
|
-
};
|
|
44
|
-
const repos2 = [{ name: 'easyagent_container', path: path.join(ws2Path, 'easyagent_container'), isGitRepo: true, defaultBranch: 'master' }];
|
|
45
|
-
|
|
46
|
-
await createWorkspace(feature2, [{ name: 'easyagent_container', path: repoPath, isGitRepo: true, defaultBranch: 'master' }]);
|
|
47
|
-
const analysis2 = await analyzeAllRepos(repos2);
|
|
48
|
-
const ctx2 = { feature: feature2, repos: repos2, analysis: analysis2, localLlm: config.localLlm };
|
|
49
|
-
await generateContextFiles(ctx2, ['claude'], ws2Path);
|
|
50
|
-
console.log('✅ Workspace 2 created at:', ws2Path);
|
|
51
|
-
|
|
52
|
-
console.log('\nBoth test workspaces are ready!');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
main().catch(console.error);
|
package/skills-lock.json
DELETED