@evolve.labs/devflow 0.8.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/.claude/commands/agents/architect.md +1162 -0
- package/.claude/commands/agents/architect.meta.yaml +124 -0
- package/.claude/commands/agents/builder.md +1432 -0
- package/.claude/commands/agents/builder.meta.yaml +117 -0
- package/.claude/commands/agents/chronicler.md +633 -0
- package/.claude/commands/agents/chronicler.meta.yaml +217 -0
- package/.claude/commands/agents/guardian.md +456 -0
- package/.claude/commands/agents/guardian.meta.yaml +127 -0
- package/.claude/commands/agents/strategist.md +483 -0
- package/.claude/commands/agents/strategist.meta.yaml +158 -0
- package/.claude/commands/agents/system-designer.md +1137 -0
- package/.claude/commands/agents/system-designer.meta.yaml +156 -0
- package/.claude/commands/devflow-help.md +93 -0
- package/.claude/commands/devflow-status.md +60 -0
- package/.claude/commands/quick/create-adr.md +82 -0
- package/.claude/commands/quick/new-feature.md +57 -0
- package/.claude/commands/quick/security-check.md +54 -0
- package/.claude/commands/quick/system-design.md +58 -0
- package/.claude_project +52 -0
- package/.devflow/agents/architect.meta.yaml +122 -0
- package/.devflow/agents/builder.meta.yaml +116 -0
- package/.devflow/agents/chronicler.meta.yaml +222 -0
- package/.devflow/agents/guardian.meta.yaml +127 -0
- package/.devflow/agents/strategist.meta.yaml +158 -0
- package/.devflow/agents/system-designer.meta.yaml +265 -0
- package/.devflow/project.yaml +242 -0
- package/.gitignore-template +84 -0
- package/LICENSE +21 -0
- package/README.md +249 -0
- package/bin/devflow.js +54 -0
- package/lib/autopilot.js +235 -0
- package/lib/autopilotConstants.js +213 -0
- package/lib/constants.js +95 -0
- package/lib/init.js +200 -0
- package/lib/update.js +181 -0
- package/lib/utils.js +157 -0
- package/lib/web.js +119 -0
- package/package.json +57 -0
- package/web/CHANGELOG.md +192 -0
- package/web/README.md +156 -0
- package/web/app/api/autopilot/execute/route.ts +102 -0
- package/web/app/api/autopilot/terminal-execute/route.ts +124 -0
- package/web/app/api/files/route.ts +280 -0
- package/web/app/api/files/tree/route.ts +160 -0
- package/web/app/api/git/route.ts +201 -0
- package/web/app/api/health/route.ts +94 -0
- package/web/app/api/project/open/route.ts +134 -0
- package/web/app/api/search/route.ts +247 -0
- package/web/app/api/specs/route.ts +405 -0
- package/web/app/api/terminal/route.ts +222 -0
- package/web/app/globals.css +160 -0
- package/web/app/ide/layout.tsx +43 -0
- package/web/app/ide/page.tsx +216 -0
- package/web/app/layout.tsx +34 -0
- package/web/app/page.tsx +303 -0
- package/web/components/agents/AgentIcons.tsx +281 -0
- package/web/components/autopilot/AutopilotConfigModal.tsx +245 -0
- package/web/components/autopilot/AutopilotPanel.tsx +299 -0
- package/web/components/dashboard/DashboardPanel.tsx +393 -0
- package/web/components/editor/Breadcrumbs.tsx +134 -0
- package/web/components/editor/EditorPanel.tsx +120 -0
- package/web/components/editor/EditorTabs.tsx +229 -0
- package/web/components/editor/MarkdownPreview.tsx +154 -0
- package/web/components/editor/MermaidDiagram.tsx +113 -0
- package/web/components/editor/MonacoEditor.tsx +177 -0
- package/web/components/editor/TabContextMenu.tsx +207 -0
- package/web/components/git/GitPanel.tsx +534 -0
- package/web/components/layout/Shell.tsx +15 -0
- package/web/components/layout/StatusBar.tsx +100 -0
- package/web/components/modals/CommandPalette.tsx +393 -0
- package/web/components/modals/GlobalSearch.tsx +348 -0
- package/web/components/modals/QuickOpen.tsx +241 -0
- package/web/components/modals/RecentFiles.tsx +208 -0
- package/web/components/projects/ProjectSelector.tsx +147 -0
- package/web/components/settings/SettingItem.tsx +150 -0
- package/web/components/settings/SettingsPanel.tsx +323 -0
- package/web/components/specs/SpecsPanel.tsx +1091 -0
- package/web/components/terminal/TerminalPanel.tsx +683 -0
- package/web/components/ui/ContextMenu.tsx +182 -0
- package/web/components/ui/LoadingSpinner.tsx +66 -0
- package/web/components/ui/ResizeHandle.tsx +110 -0
- package/web/components/ui/Skeleton.tsx +108 -0
- package/web/components/ui/SkipLinks.tsx +37 -0
- package/web/components/ui/Toaster.tsx +57 -0
- package/web/hooks/useFocusTrap.ts +141 -0
- package/web/hooks/useKeyboardShortcuts.ts +169 -0
- package/web/hooks/useListNavigation.ts +237 -0
- package/web/lib/autopilotConstants.ts +213 -0
- package/web/lib/constants/agents.ts +67 -0
- package/web/lib/git.ts +339 -0
- package/web/lib/ptyManager.ts +191 -0
- package/web/lib/specsParser.ts +299 -0
- package/web/lib/stores/autopilotStore.ts +288 -0
- package/web/lib/stores/fileStore.ts +550 -0
- package/web/lib/stores/gitStore.ts +386 -0
- package/web/lib/stores/projectStore.ts +196 -0
- package/web/lib/stores/settingsStore.ts +126 -0
- package/web/lib/stores/specsStore.ts +297 -0
- package/web/lib/stores/uiStore.ts +175 -0
- package/web/lib/types/index.ts +177 -0
- package/web/lib/utils.ts +98 -0
- package/web/next.config.js +50 -0
- package/web/package.json +54 -0
- package/web/postcss.config.js +6 -0
- package/web/tailwind.config.ts +68 -0
- package/web/tsconfig.json +41 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--background: 0 0% 100%;
|
|
8
|
+
--foreground: 222.2 84% 4.9%;
|
|
9
|
+
--card: 0 0% 100%;
|
|
10
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
11
|
+
--popover: 0 0% 100%;
|
|
12
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
13
|
+
--primary: 221.2 83.2% 53.3%;
|
|
14
|
+
--primary-foreground: 210 40% 98%;
|
|
15
|
+
--secondary: 210 40% 96.1%;
|
|
16
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
17
|
+
--muted: 210 40% 96.1%;
|
|
18
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
19
|
+
--accent: 210 40% 96.1%;
|
|
20
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
21
|
+
--destructive: 0 84.2% 60.2%;
|
|
22
|
+
--destructive-foreground: 210 40% 98%;
|
|
23
|
+
--border: 214.3 31.8% 91.4%;
|
|
24
|
+
--input: 214.3 31.8% 91.4%;
|
|
25
|
+
--ring: 221.2 83.2% 53.3%;
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.dark {
|
|
30
|
+
--background: 222.2 84% 4.9%;
|
|
31
|
+
--foreground: 210 40% 98%;
|
|
32
|
+
--card: 222.2 84% 4.9%;
|
|
33
|
+
--card-foreground: 210 40% 98%;
|
|
34
|
+
--popover: 222.2 84% 4.9%;
|
|
35
|
+
--popover-foreground: 210 40% 98%;
|
|
36
|
+
--primary: 217.2 91.2% 59.8%;
|
|
37
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
38
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
39
|
+
--secondary-foreground: 210 40% 98%;
|
|
40
|
+
--muted: 217.2 32.6% 17.5%;
|
|
41
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
42
|
+
--accent: 217.2 32.6% 17.5%;
|
|
43
|
+
--accent-foreground: 210 40% 98%;
|
|
44
|
+
--destructive: 0 62.8% 30.6%;
|
|
45
|
+
--destructive-foreground: 210 40% 98%;
|
|
46
|
+
--border: 217.2 32.6% 17.5%;
|
|
47
|
+
--input: 217.2 32.6% 17.5%;
|
|
48
|
+
--ring: 224.3 76.3% 48%;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@layer base {
|
|
53
|
+
* {
|
|
54
|
+
@apply border-border;
|
|
55
|
+
}
|
|
56
|
+
body {
|
|
57
|
+
@apply bg-background text-foreground;
|
|
58
|
+
font-feature-settings: "rlig" 1, "calt" 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Custom scrollbar */
|
|
63
|
+
::-webkit-scrollbar {
|
|
64
|
+
width: 8px;
|
|
65
|
+
height: 8px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
::-webkit-scrollbar-track {
|
|
69
|
+
@apply bg-transparent;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
::-webkit-scrollbar-thumb {
|
|
73
|
+
@apply bg-muted-foreground/20 rounded-full;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
::-webkit-scrollbar-thumb:hover {
|
|
77
|
+
@apply bg-muted-foreground/40;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Monaco editor adjustments */
|
|
81
|
+
.monaco-editor {
|
|
82
|
+
@apply rounded-md;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Monaco editor line highlight animation */
|
|
86
|
+
.highlight-line-animation {
|
|
87
|
+
background-color: rgba(168, 85, 247, 0.3) !important;
|
|
88
|
+
animation: highlight-fade 2s ease-out forwards;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.highlight-line-margin {
|
|
92
|
+
background-color: rgba(168, 85, 247, 0.8) !important;
|
|
93
|
+
width: 3px !important;
|
|
94
|
+
margin-left: 3px;
|
|
95
|
+
animation: highlight-fade 2s ease-out forwards;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@keyframes highlight-fade {
|
|
99
|
+
0% {
|
|
100
|
+
background-color: rgba(168, 85, 247, 0.5);
|
|
101
|
+
}
|
|
102
|
+
100% {
|
|
103
|
+
background-color: transparent;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* File tree hover effects */
|
|
108
|
+
.file-node:hover {
|
|
109
|
+
@apply bg-accent;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.file-node.selected {
|
|
113
|
+
@apply bg-accent text-accent-foreground;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Chat message streaming cursor */
|
|
117
|
+
.streaming-cursor::after {
|
|
118
|
+
content: '▌';
|
|
119
|
+
@apply animate-pulse text-primary;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Terminal styles */
|
|
123
|
+
.xterm {
|
|
124
|
+
@apply p-2;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.xterm-screen canvas {
|
|
128
|
+
image-rendering: pixelated;
|
|
129
|
+
image-rendering: crisp-edges;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.xterm-viewport {
|
|
133
|
+
overflow-y: auto !important;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Resizable panels */
|
|
137
|
+
.resizable-handle {
|
|
138
|
+
@apply bg-transparent hover:bg-primary/20 transition-colors;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.resizable-handle:active {
|
|
142
|
+
@apply bg-primary/40;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Hide scrollbar utility */
|
|
146
|
+
.scrollbar-hide {
|
|
147
|
+
-ms-overflow-style: none;
|
|
148
|
+
scrollbar-width: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.scrollbar-hide::-webkit-scrollbar {
|
|
152
|
+
display: none;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Responsive text utilities */
|
|
156
|
+
@layer utilities {
|
|
157
|
+
.text-responsive {
|
|
158
|
+
font-size: clamp(0.75rem, 2vw, 0.875rem);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { useProjectStore } from '@/lib/stores/projectStore';
|
|
6
|
+
|
|
7
|
+
export default function IDELayout({ children }: { children: React.ReactNode }) {
|
|
8
|
+
const router = useRouter();
|
|
9
|
+
const { projects, restoreProjects } = useProjectStore();
|
|
10
|
+
const [restoring, setRestoring] = useState(true);
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (projects.length > 0) {
|
|
14
|
+
// Already have projects loaded
|
|
15
|
+
setRestoring(false);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Try to restore from persisted state
|
|
20
|
+
restoreProjects().then(() => {
|
|
21
|
+
const current = useProjectStore.getState();
|
|
22
|
+
if (current.projects.length === 0) {
|
|
23
|
+
// No projects could be restored, redirect to home
|
|
24
|
+
router.push('/');
|
|
25
|
+
} else {
|
|
26
|
+
setRestoring(false);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
30
|
+
|
|
31
|
+
if (restoring && projects.length === 0) {
|
|
32
|
+
return (
|
|
33
|
+
<div className="min-h-screen flex items-center justify-center bg-[#0a0a0f]">
|
|
34
|
+
<div className="text-center space-y-4">
|
|
35
|
+
<div className="animate-spin w-8 h-8 border-2 border-purple-500 border-t-transparent rounded-full mx-auto" />
|
|
36
|
+
<p className="text-gray-400">Loading projects...</p>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return <>{children}</>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useCallback } from 'react';
|
|
4
|
+
import { useProjectStore } from '@/lib/stores/projectStore';
|
|
5
|
+
import { useUIStore } from '@/lib/stores/uiStore';
|
|
6
|
+
import { useSettingsStore } from '@/lib/stores/settingsStore';
|
|
7
|
+
import { EditorPanel } from '@/components/editor/EditorPanel';
|
|
8
|
+
import { SpecsPanel } from '@/components/specs/SpecsPanel';
|
|
9
|
+
import { TerminalPanel } from '@/components/terminal/TerminalPanel';
|
|
10
|
+
import { GitPanel } from '@/components/git/GitPanel';
|
|
11
|
+
import { DashboardPanel } from '@/components/dashboard/DashboardPanel';
|
|
12
|
+
import { StatusBar } from '@/components/layout/StatusBar';
|
|
13
|
+
import { ResizeHandle } from '@/components/ui/ResizeHandle';
|
|
14
|
+
import { QuickOpen } from '@/components/modals/QuickOpen';
|
|
15
|
+
import { GlobalSearch } from '@/components/modals/GlobalSearch';
|
|
16
|
+
import { CommandPalette } from '@/components/modals/CommandPalette';
|
|
17
|
+
import { RecentFiles } from '@/components/modals/RecentFiles';
|
|
18
|
+
import { SettingsPanel } from '@/components/settings/SettingsPanel';
|
|
19
|
+
import { AutopilotPanel } from '@/components/autopilot/AutopilotPanel';
|
|
20
|
+
import { AutopilotConfigModal } from '@/components/autopilot/AutopilotConfigModal';
|
|
21
|
+
import { ProjectSelector } from '@/components/projects/ProjectSelector';
|
|
22
|
+
import { SkipLinks } from '@/components/ui/SkipLinks';
|
|
23
|
+
import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts';
|
|
24
|
+
import {
|
|
25
|
+
FileText,
|
|
26
|
+
Terminal,
|
|
27
|
+
LayoutDashboard,
|
|
28
|
+
Zap,
|
|
29
|
+
Settings,
|
|
30
|
+
GitBranch
|
|
31
|
+
} from 'lucide-react';
|
|
32
|
+
import { cn } from '@/lib/utils';
|
|
33
|
+
|
|
34
|
+
export default function IDEPage() {
|
|
35
|
+
const { currentProject, projects, activeProjectPath } = useProjectStore();
|
|
36
|
+
const { openSettings } = useSettingsStore();
|
|
37
|
+
const projectPaths = projects.map(p => p.path);
|
|
38
|
+
|
|
39
|
+
// Initialize keyboard shortcuts
|
|
40
|
+
useKeyboardShortcuts();
|
|
41
|
+
|
|
42
|
+
const {
|
|
43
|
+
sidebarVisible,
|
|
44
|
+
sidebarWidth,
|
|
45
|
+
activePanel,
|
|
46
|
+
setActivePanel,
|
|
47
|
+
terminalVisible,
|
|
48
|
+
terminalHeight,
|
|
49
|
+
terminalMaximized,
|
|
50
|
+
toggleSidebar,
|
|
51
|
+
toggleTerminal,
|
|
52
|
+
toggleTerminalMaximized,
|
|
53
|
+
setSidebarWidth,
|
|
54
|
+
setTerminalHeight,
|
|
55
|
+
} = useUIStore();
|
|
56
|
+
|
|
57
|
+
// Resize handlers
|
|
58
|
+
const handleSidebarResize = useCallback((delta: number) => {
|
|
59
|
+
setSidebarWidth(sidebarWidth + delta);
|
|
60
|
+
}, [sidebarWidth, setSidebarWidth]);
|
|
61
|
+
|
|
62
|
+
const sidebarItems = [
|
|
63
|
+
{ id: 'specs', icon: FileText, label: 'Specs' },
|
|
64
|
+
{ id: 'git', icon: GitBranch, label: 'Source Control' },
|
|
65
|
+
{ id: 'dashboard', icon: LayoutDashboard, label: 'Dashboard' },
|
|
66
|
+
] as const;
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<div className="h-screen flex flex-col bg-[#0a0a0f] text-white overflow-hidden">
|
|
70
|
+
{/* Skip Links for accessibility */}
|
|
71
|
+
<SkipLinks />
|
|
72
|
+
|
|
73
|
+
{/* Main Content */}
|
|
74
|
+
<div className="flex-1 flex overflow-hidden" role="main">
|
|
75
|
+
{/* Activity Bar */}
|
|
76
|
+
<div className="w-12 bg-[#08080c] border-r border-white/10 flex flex-col items-center py-2">
|
|
77
|
+
{/* Logo */}
|
|
78
|
+
<div className="w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-700 rounded-lg flex items-center justify-center mb-4">
|
|
79
|
+
<Zap className="w-4 h-4 text-white" />
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{/* Nav Items */}
|
|
83
|
+
<div className="flex-1 flex flex-col gap-1">
|
|
84
|
+
{sidebarItems.map((item) => (
|
|
85
|
+
<button
|
|
86
|
+
key={item.id}
|
|
87
|
+
onClick={() => {
|
|
88
|
+
if (activePanel === item.id && sidebarVisible) {
|
|
89
|
+
toggleSidebar();
|
|
90
|
+
} else {
|
|
91
|
+
setActivePanel(item.id);
|
|
92
|
+
if (!sidebarVisible) toggleSidebar();
|
|
93
|
+
}
|
|
94
|
+
}}
|
|
95
|
+
className={cn(
|
|
96
|
+
'w-10 h-10 flex items-center justify-center rounded-lg transition-colors',
|
|
97
|
+
activePanel === item.id && sidebarVisible
|
|
98
|
+
? 'bg-purple-500/20 text-purple-400'
|
|
99
|
+
: 'text-gray-500 hover:text-white hover:bg-white/5'
|
|
100
|
+
)}
|
|
101
|
+
title={item.label}
|
|
102
|
+
>
|
|
103
|
+
<item.icon className="w-5 h-5" />
|
|
104
|
+
</button>
|
|
105
|
+
))}
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* Bottom Actions */}
|
|
109
|
+
<div className="flex flex-col gap-1">
|
|
110
|
+
<button
|
|
111
|
+
onClick={toggleTerminal}
|
|
112
|
+
className={cn(
|
|
113
|
+
'w-10 h-10 flex items-center justify-center rounded-lg transition-colors',
|
|
114
|
+
terminalVisible
|
|
115
|
+
? 'bg-purple-500/20 text-purple-400'
|
|
116
|
+
: 'text-gray-500 hover:text-white hover:bg-white/5'
|
|
117
|
+
)}
|
|
118
|
+
title="Terminal"
|
|
119
|
+
>
|
|
120
|
+
<Terminal className="w-5 h-5" />
|
|
121
|
+
</button>
|
|
122
|
+
<button
|
|
123
|
+
onClick={openSettings}
|
|
124
|
+
className="w-10 h-10 flex items-center justify-center rounded-lg text-gray-500 hover:text-white hover:bg-white/5 transition-colors"
|
|
125
|
+
title="Settings (Cmd+,)"
|
|
126
|
+
>
|
|
127
|
+
<Settings className="w-5 h-5" />
|
|
128
|
+
</button>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
{/* Sidebar Panel */}
|
|
133
|
+
{sidebarVisible && (
|
|
134
|
+
<>
|
|
135
|
+
<aside
|
|
136
|
+
id="main-sidebar"
|
|
137
|
+
className="h-full bg-[#0a0a0f] flex-shrink-0 overflow-hidden flex flex-col"
|
|
138
|
+
style={{ width: sidebarWidth }}
|
|
139
|
+
aria-label="Sidebar"
|
|
140
|
+
>
|
|
141
|
+
{/* Project Selector */}
|
|
142
|
+
<div className="px-2 pt-2 pb-1 flex-shrink-0">
|
|
143
|
+
<ProjectSelector />
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
{/* Panel Content */}
|
|
147
|
+
<div className="flex-1 min-h-0 overflow-hidden">
|
|
148
|
+
{activePanel === 'git' && currentProject && (
|
|
149
|
+
<GitPanel projectPath={currentProject.path} />
|
|
150
|
+
)}
|
|
151
|
+
{activePanel === 'specs' && projectPaths.length > 0 && (
|
|
152
|
+
<SpecsPanel projectPaths={projectPaths} activeProjectPath={activeProjectPath} />
|
|
153
|
+
)}
|
|
154
|
+
{activePanel === 'dashboard' && currentProject && (
|
|
155
|
+
<DashboardPanel projectPath={currentProject.path} />
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
</aside>
|
|
159
|
+
{/* Sidebar Resize Handle */}
|
|
160
|
+
<ResizeHandle
|
|
161
|
+
direction="horizontal"
|
|
162
|
+
side="right"
|
|
163
|
+
onResize={handleSidebarResize}
|
|
164
|
+
className="bg-white/5 hover:bg-purple-500/30"
|
|
165
|
+
/>
|
|
166
|
+
</>
|
|
167
|
+
)}
|
|
168
|
+
|
|
169
|
+
{/* Editor + Terminal Area */}
|
|
170
|
+
<div className="flex-1 min-w-0 flex flex-col">
|
|
171
|
+
{/* Editor */}
|
|
172
|
+
<div
|
|
173
|
+
id="main-editor"
|
|
174
|
+
className={cn(
|
|
175
|
+
'flex-1 min-h-0',
|
|
176
|
+
terminalVisible && !terminalMaximized && 'pb-0'
|
|
177
|
+
)}
|
|
178
|
+
tabIndex={-1}
|
|
179
|
+
>
|
|
180
|
+
<EditorPanel />
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
{/* Terminal */}
|
|
184
|
+
{terminalVisible && currentProject && (
|
|
185
|
+
<TerminalPanel
|
|
186
|
+
projectPath={currentProject.path}
|
|
187
|
+
isMaximized={terminalMaximized}
|
|
188
|
+
onToggleMaximize={toggleTerminalMaximized}
|
|
189
|
+
onClose={toggleTerminal}
|
|
190
|
+
height={terminalHeight}
|
|
191
|
+
onHeightChange={setTerminalHeight}
|
|
192
|
+
/>
|
|
193
|
+
)}
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
{/* Status Bar */}
|
|
198
|
+
<StatusBar />
|
|
199
|
+
|
|
200
|
+
{/* Modals */}
|
|
201
|
+
<QuickOpen />
|
|
202
|
+
<GlobalSearch />
|
|
203
|
+
<CommandPalette />
|
|
204
|
+
<RecentFiles />
|
|
205
|
+
<SettingsPanel />
|
|
206
|
+
|
|
207
|
+
{/* Autopilot */}
|
|
208
|
+
{currentProject && (
|
|
209
|
+
<>
|
|
210
|
+
<AutopilotConfigModal projectPath={currentProject.path} />
|
|
211
|
+
<AutopilotPanel />
|
|
212
|
+
</>
|
|
213
|
+
)}
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import { Inter, JetBrains_Mono } from 'next/font/google';
|
|
3
|
+
import { Toaster } from '@/components/ui/Toaster';
|
|
4
|
+
import './globals.css';
|
|
5
|
+
|
|
6
|
+
const inter = Inter({
|
|
7
|
+
subsets: ['latin'],
|
|
8
|
+
variable: '--font-inter',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const jetbrainsMono = JetBrains_Mono({
|
|
12
|
+
subsets: ['latin'],
|
|
13
|
+
variable: '--font-mono',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const metadata: Metadata = {
|
|
17
|
+
title: 'DevFlow IDE',
|
|
18
|
+
description: 'Spec-driven development IDE powered by AI agents',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default function RootLayout({
|
|
22
|
+
children,
|
|
23
|
+
}: {
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
}) {
|
|
26
|
+
return (
|
|
27
|
+
<html lang="en" className="dark">
|
|
28
|
+
<body className={`${inter.variable} ${jetbrainsMono.variable} font-sans antialiased`}>
|
|
29
|
+
{children}
|
|
30
|
+
<Toaster />
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
);
|
|
34
|
+
}
|