@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,323 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useCallback } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
X,
|
|
6
|
+
Settings,
|
|
7
|
+
Type,
|
|
8
|
+
Terminal,
|
|
9
|
+
MessageSquare,
|
|
10
|
+
Keyboard,
|
|
11
|
+
RotateCcw,
|
|
12
|
+
} from 'lucide-react';
|
|
13
|
+
import { cn } from '@/lib/utils';
|
|
14
|
+
import { useSettingsStore, type TabSize, type ChatModel } from '@/lib/stores/settingsStore';
|
|
15
|
+
import { SettingItem, SettingSection } from './SettingItem';
|
|
16
|
+
import { AGENTS } from '@/lib/constants/agents';
|
|
17
|
+
|
|
18
|
+
type SettingsTab = 'general' | 'editor' | 'terminal' | 'chat' | 'keyboard';
|
|
19
|
+
|
|
20
|
+
const TABS: { id: SettingsTab; label: string; icon: React.ReactNode }[] = [
|
|
21
|
+
{ id: 'general', label: 'General', icon: <Settings className="w-4 h-4" /> },
|
|
22
|
+
{ id: 'editor', label: 'Editor', icon: <Type className="w-4 h-4" /> },
|
|
23
|
+
{ id: 'terminal', label: 'Terminal', icon: <Terminal className="w-4 h-4" /> },
|
|
24
|
+
{ id: 'chat', label: 'Chat/AI', icon: <MessageSquare className="w-4 h-4" /> },
|
|
25
|
+
{ id: 'keyboard', label: 'Keyboard', icon: <Keyboard className="w-4 h-4" /> },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export function SettingsPanel() {
|
|
29
|
+
const {
|
|
30
|
+
isSettingsOpen,
|
|
31
|
+
closeSettings,
|
|
32
|
+
activeSettingsTab,
|
|
33
|
+
setActiveSettingsTab,
|
|
34
|
+
resetToDefaults,
|
|
35
|
+
} = useSettingsStore();
|
|
36
|
+
|
|
37
|
+
// Close on Escape
|
|
38
|
+
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
|
39
|
+
if (e.key === 'Escape') {
|
|
40
|
+
closeSettings();
|
|
41
|
+
}
|
|
42
|
+
}, [closeSettings]);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (isSettingsOpen) {
|
|
46
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
47
|
+
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
48
|
+
}
|
|
49
|
+
}, [isSettingsOpen, handleKeyDown]);
|
|
50
|
+
|
|
51
|
+
if (!isSettingsOpen) return null;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
55
|
+
{/* Backdrop */}
|
|
56
|
+
<div
|
|
57
|
+
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
|
|
58
|
+
onClick={closeSettings}
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
{/* Modal */}
|
|
62
|
+
<div className="relative w-full max-w-3xl max-h-[80vh] bg-[#0a0a0f] border border-white/10 rounded-xl shadow-2xl overflow-hidden flex flex-col">
|
|
63
|
+
{/* Header */}
|
|
64
|
+
<div className="flex items-center justify-between px-6 py-4 border-b border-white/10">
|
|
65
|
+
<div className="flex items-center gap-2">
|
|
66
|
+
<Settings className="w-5 h-5 text-purple-400" />
|
|
67
|
+
<h2 className="text-lg font-semibold text-white">Settings</h2>
|
|
68
|
+
</div>
|
|
69
|
+
<button
|
|
70
|
+
onClick={closeSettings}
|
|
71
|
+
className="p-1.5 text-gray-400 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
72
|
+
>
|
|
73
|
+
<X className="w-5 h-5" />
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
{/* Content */}
|
|
78
|
+
<div className="flex flex-1 overflow-hidden">
|
|
79
|
+
{/* Sidebar */}
|
|
80
|
+
<nav className="w-48 border-r border-white/10 p-2 flex-shrink-0">
|
|
81
|
+
{TABS.map((tab) => (
|
|
82
|
+
<button
|
|
83
|
+
key={tab.id}
|
|
84
|
+
onClick={() => setActiveSettingsTab(tab.id)}
|
|
85
|
+
className={cn(
|
|
86
|
+
'w-full flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors',
|
|
87
|
+
activeSettingsTab === tab.id
|
|
88
|
+
? 'bg-purple-500/20 text-purple-400'
|
|
89
|
+
: 'text-gray-400 hover:text-white hover:bg-white/5'
|
|
90
|
+
)}
|
|
91
|
+
>
|
|
92
|
+
{tab.icon}
|
|
93
|
+
{tab.label}
|
|
94
|
+
</button>
|
|
95
|
+
))}
|
|
96
|
+
</nav>
|
|
97
|
+
|
|
98
|
+
{/* Settings Content */}
|
|
99
|
+
<div className="flex-1 overflow-y-auto p-6">
|
|
100
|
+
{activeSettingsTab === 'general' && <GeneralSettings />}
|
|
101
|
+
{activeSettingsTab === 'editor' && <EditorSettings />}
|
|
102
|
+
{activeSettingsTab === 'terminal' && <TerminalSettings />}
|
|
103
|
+
{activeSettingsTab === 'chat' && <ChatSettings />}
|
|
104
|
+
{activeSettingsTab === 'keyboard' && <KeyboardSettings />}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* Footer */}
|
|
109
|
+
<div className="flex items-center justify-between px-6 py-3 border-t border-white/10 bg-[#12121a]">
|
|
110
|
+
<button
|
|
111
|
+
onClick={resetToDefaults}
|
|
112
|
+
className="flex items-center gap-2 px-3 py-1.5 text-sm text-gray-400 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
|
|
113
|
+
>
|
|
114
|
+
<RotateCcw className="w-4 h-4" />
|
|
115
|
+
Reset to Defaults
|
|
116
|
+
</button>
|
|
117
|
+
<span className="text-xs text-gray-500">
|
|
118
|
+
Press <kbd className="px-1.5 py-0.5 bg-white/10 rounded text-gray-400">Esc</kbd> to close
|
|
119
|
+
</span>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function GeneralSettings() {
|
|
127
|
+
const { autoSave, autoSaveDelay, setSetting } = useSettingsStore();
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<div>
|
|
131
|
+
<SettingSection title="Auto Save">
|
|
132
|
+
<SettingItem
|
|
133
|
+
type="toggle"
|
|
134
|
+
label="Enable Auto Save"
|
|
135
|
+
description="Automatically save files after changes"
|
|
136
|
+
value={autoSave}
|
|
137
|
+
onChange={(value) => setSetting('autoSave', value)}
|
|
138
|
+
/>
|
|
139
|
+
<SettingItem
|
|
140
|
+
type="slider"
|
|
141
|
+
label="Auto Save Delay"
|
|
142
|
+
description="Delay in milliseconds before auto saving"
|
|
143
|
+
value={autoSaveDelay}
|
|
144
|
+
onChange={(value) => setSetting('autoSaveDelay', value)}
|
|
145
|
+
min={500}
|
|
146
|
+
max={5000}
|
|
147
|
+
step={100}
|
|
148
|
+
unit="ms"
|
|
149
|
+
/>
|
|
150
|
+
</SettingSection>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function EditorSettings() {
|
|
156
|
+
const {
|
|
157
|
+
editorFontSize,
|
|
158
|
+
editorTabSize,
|
|
159
|
+
editorWordWrap,
|
|
160
|
+
editorMinimap,
|
|
161
|
+
editorLineNumbers,
|
|
162
|
+
setSetting,
|
|
163
|
+
} = useSettingsStore();
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<div>
|
|
167
|
+
<SettingSection title="Font">
|
|
168
|
+
<SettingItem
|
|
169
|
+
type="slider"
|
|
170
|
+
label="Font Size"
|
|
171
|
+
description="Editor font size in pixels"
|
|
172
|
+
value={editorFontSize}
|
|
173
|
+
onChange={(value) => setSetting('editorFontSize', value)}
|
|
174
|
+
min={10}
|
|
175
|
+
max={24}
|
|
176
|
+
unit="px"
|
|
177
|
+
/>
|
|
178
|
+
</SettingSection>
|
|
179
|
+
|
|
180
|
+
<SettingSection title="Indentation">
|
|
181
|
+
<SettingItem
|
|
182
|
+
type="select"
|
|
183
|
+
label="Tab Size"
|
|
184
|
+
description="Number of spaces for indentation"
|
|
185
|
+
value={editorTabSize}
|
|
186
|
+
onChange={(value) => setSetting('editorTabSize', value as TabSize)}
|
|
187
|
+
options={[
|
|
188
|
+
{ label: '2 spaces', value: 2 },
|
|
189
|
+
{ label: '4 spaces', value: 4 },
|
|
190
|
+
{ label: '8 spaces', value: 8 },
|
|
191
|
+
]}
|
|
192
|
+
/>
|
|
193
|
+
</SettingSection>
|
|
194
|
+
|
|
195
|
+
<SettingSection title="Display">
|
|
196
|
+
<SettingItem
|
|
197
|
+
type="toggle"
|
|
198
|
+
label="Word Wrap"
|
|
199
|
+
description="Wrap long lines to fit the editor width"
|
|
200
|
+
value={editorWordWrap}
|
|
201
|
+
onChange={(value) => setSetting('editorWordWrap', value)}
|
|
202
|
+
/>
|
|
203
|
+
<SettingItem
|
|
204
|
+
type="toggle"
|
|
205
|
+
label="Minimap"
|
|
206
|
+
description="Show code minimap on the right side"
|
|
207
|
+
value={editorMinimap}
|
|
208
|
+
onChange={(value) => setSetting('editorMinimap', value)}
|
|
209
|
+
/>
|
|
210
|
+
<SettingItem
|
|
211
|
+
type="toggle"
|
|
212
|
+
label="Line Numbers"
|
|
213
|
+
description="Show line numbers in the gutter"
|
|
214
|
+
value={editorLineNumbers}
|
|
215
|
+
onChange={(value) => setSetting('editorLineNumbers', value)}
|
|
216
|
+
/>
|
|
217
|
+
</SettingSection>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function TerminalSettings() {
|
|
223
|
+
const { terminalFontSize, setSetting } = useSettingsStore();
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<div>
|
|
227
|
+
<SettingSection title="Font">
|
|
228
|
+
<SettingItem
|
|
229
|
+
type="slider"
|
|
230
|
+
label="Font Size"
|
|
231
|
+
description="Terminal font size in pixels"
|
|
232
|
+
value={terminalFontSize}
|
|
233
|
+
onChange={(value) => setSetting('terminalFontSize', value)}
|
|
234
|
+
min={10}
|
|
235
|
+
max={20}
|
|
236
|
+
unit="px"
|
|
237
|
+
/>
|
|
238
|
+
</SettingSection>
|
|
239
|
+
</div>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function ChatSettings() {
|
|
244
|
+
const { chatDefaultModel, chatDefaultAgent, setSetting } = useSettingsStore();
|
|
245
|
+
|
|
246
|
+
const agentOptions = [
|
|
247
|
+
{ label: 'None (General)', value: '' },
|
|
248
|
+
...AGENTS.map((agent) => ({
|
|
249
|
+
label: `${agent.icon} ${agent.displayName}`,
|
|
250
|
+
value: agent.id,
|
|
251
|
+
})),
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<div>
|
|
256
|
+
<SettingSection title="AI Model">
|
|
257
|
+
<SettingItem
|
|
258
|
+
type="select"
|
|
259
|
+
label="Default Model"
|
|
260
|
+
description="Claude model to use for chat"
|
|
261
|
+
value={chatDefaultModel}
|
|
262
|
+
onChange={(value) => setSetting('chatDefaultModel', value as ChatModel)}
|
|
263
|
+
options={[
|
|
264
|
+
{ label: 'Sonnet (Recommended)', value: 'sonnet' },
|
|
265
|
+
{ label: 'Opus (Most capable)', value: 'opus' },
|
|
266
|
+
{ label: 'Auto (Let Claude decide)', value: 'auto' },
|
|
267
|
+
]}
|
|
268
|
+
/>
|
|
269
|
+
</SettingSection>
|
|
270
|
+
|
|
271
|
+
<SettingSection title="Agents">
|
|
272
|
+
<SettingItem
|
|
273
|
+
type="select"
|
|
274
|
+
label="Default Agent"
|
|
275
|
+
description="Agent to use when starting a new conversation"
|
|
276
|
+
value={chatDefaultAgent || ''}
|
|
277
|
+
onChange={(value) => setSetting('chatDefaultAgent', (value as string) || null)}
|
|
278
|
+
options={agentOptions}
|
|
279
|
+
/>
|
|
280
|
+
</SettingSection>
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function KeyboardSettings() {
|
|
286
|
+
const shortcuts = [
|
|
287
|
+
{ key: 'Cmd + ,', action: 'Open Settings' },
|
|
288
|
+
{ key: 'Cmd + S', action: 'Save File' },
|
|
289
|
+
{ key: 'Cmd + P', action: 'Quick Open' },
|
|
290
|
+
{ key: 'Cmd + Shift + F', action: 'Global Search' },
|
|
291
|
+
{ key: 'Cmd + Shift + P', action: 'Command Palette' },
|
|
292
|
+
{ key: 'Cmd + B', action: 'Toggle Sidebar' },
|
|
293
|
+
{ key: 'Cmd + J', action: 'Toggle Terminal' },
|
|
294
|
+
{ key: 'Cmd + /', action: 'Toggle Comment' },
|
|
295
|
+
{ key: 'Cmd + Z', action: 'Undo' },
|
|
296
|
+
{ key: 'Cmd + Shift + Z', action: 'Redo' },
|
|
297
|
+
{ key: 'Escape', action: 'Close Panel/Modal' },
|
|
298
|
+
];
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<div>
|
|
302
|
+
<SettingSection title="Keyboard Shortcuts">
|
|
303
|
+
<div className="space-y-2">
|
|
304
|
+
{shortcuts.map((shortcut) => (
|
|
305
|
+
<div
|
|
306
|
+
key={shortcut.key}
|
|
307
|
+
className="flex items-center justify-between py-2 border-b border-white/5 last:border-0"
|
|
308
|
+
>
|
|
309
|
+
<span className="text-sm text-gray-400">{shortcut.action}</span>
|
|
310
|
+
<kbd className="px-2 py-1 bg-white/5 border border-white/10 rounded text-xs text-gray-300 font-mono">
|
|
311
|
+
{shortcut.key}
|
|
312
|
+
</kbd>
|
|
313
|
+
</div>
|
|
314
|
+
))}
|
|
315
|
+
</div>
|
|
316
|
+
</SettingSection>
|
|
317
|
+
|
|
318
|
+
<p className="text-xs text-gray-500 mt-4">
|
|
319
|
+
* On Windows/Linux, replace Cmd with Ctrl
|
|
320
|
+
</p>
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
}
|