@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.
Files changed (106) hide show
  1. package/.claude/commands/agents/architect.md +1162 -0
  2. package/.claude/commands/agents/architect.meta.yaml +124 -0
  3. package/.claude/commands/agents/builder.md +1432 -0
  4. package/.claude/commands/agents/builder.meta.yaml +117 -0
  5. package/.claude/commands/agents/chronicler.md +633 -0
  6. package/.claude/commands/agents/chronicler.meta.yaml +217 -0
  7. package/.claude/commands/agents/guardian.md +456 -0
  8. package/.claude/commands/agents/guardian.meta.yaml +127 -0
  9. package/.claude/commands/agents/strategist.md +483 -0
  10. package/.claude/commands/agents/strategist.meta.yaml +158 -0
  11. package/.claude/commands/agents/system-designer.md +1137 -0
  12. package/.claude/commands/agents/system-designer.meta.yaml +156 -0
  13. package/.claude/commands/devflow-help.md +93 -0
  14. package/.claude/commands/devflow-status.md +60 -0
  15. package/.claude/commands/quick/create-adr.md +82 -0
  16. package/.claude/commands/quick/new-feature.md +57 -0
  17. package/.claude/commands/quick/security-check.md +54 -0
  18. package/.claude/commands/quick/system-design.md +58 -0
  19. package/.claude_project +52 -0
  20. package/.devflow/agents/architect.meta.yaml +122 -0
  21. package/.devflow/agents/builder.meta.yaml +116 -0
  22. package/.devflow/agents/chronicler.meta.yaml +222 -0
  23. package/.devflow/agents/guardian.meta.yaml +127 -0
  24. package/.devflow/agents/strategist.meta.yaml +158 -0
  25. package/.devflow/agents/system-designer.meta.yaml +265 -0
  26. package/.devflow/project.yaml +242 -0
  27. package/.gitignore-template +84 -0
  28. package/LICENSE +21 -0
  29. package/README.md +249 -0
  30. package/bin/devflow.js +54 -0
  31. package/lib/autopilot.js +235 -0
  32. package/lib/autopilotConstants.js +213 -0
  33. package/lib/constants.js +95 -0
  34. package/lib/init.js +200 -0
  35. package/lib/update.js +181 -0
  36. package/lib/utils.js +157 -0
  37. package/lib/web.js +119 -0
  38. package/package.json +57 -0
  39. package/web/CHANGELOG.md +192 -0
  40. package/web/README.md +156 -0
  41. package/web/app/api/autopilot/execute/route.ts +102 -0
  42. package/web/app/api/autopilot/terminal-execute/route.ts +124 -0
  43. package/web/app/api/files/route.ts +280 -0
  44. package/web/app/api/files/tree/route.ts +160 -0
  45. package/web/app/api/git/route.ts +201 -0
  46. package/web/app/api/health/route.ts +94 -0
  47. package/web/app/api/project/open/route.ts +134 -0
  48. package/web/app/api/search/route.ts +247 -0
  49. package/web/app/api/specs/route.ts +405 -0
  50. package/web/app/api/terminal/route.ts +222 -0
  51. package/web/app/globals.css +160 -0
  52. package/web/app/ide/layout.tsx +43 -0
  53. package/web/app/ide/page.tsx +216 -0
  54. package/web/app/layout.tsx +34 -0
  55. package/web/app/page.tsx +303 -0
  56. package/web/components/agents/AgentIcons.tsx +281 -0
  57. package/web/components/autopilot/AutopilotConfigModal.tsx +245 -0
  58. package/web/components/autopilot/AutopilotPanel.tsx +299 -0
  59. package/web/components/dashboard/DashboardPanel.tsx +393 -0
  60. package/web/components/editor/Breadcrumbs.tsx +134 -0
  61. package/web/components/editor/EditorPanel.tsx +120 -0
  62. package/web/components/editor/EditorTabs.tsx +229 -0
  63. package/web/components/editor/MarkdownPreview.tsx +154 -0
  64. package/web/components/editor/MermaidDiagram.tsx +113 -0
  65. package/web/components/editor/MonacoEditor.tsx +177 -0
  66. package/web/components/editor/TabContextMenu.tsx +207 -0
  67. package/web/components/git/GitPanel.tsx +534 -0
  68. package/web/components/layout/Shell.tsx +15 -0
  69. package/web/components/layout/StatusBar.tsx +100 -0
  70. package/web/components/modals/CommandPalette.tsx +393 -0
  71. package/web/components/modals/GlobalSearch.tsx +348 -0
  72. package/web/components/modals/QuickOpen.tsx +241 -0
  73. package/web/components/modals/RecentFiles.tsx +208 -0
  74. package/web/components/projects/ProjectSelector.tsx +147 -0
  75. package/web/components/settings/SettingItem.tsx +150 -0
  76. package/web/components/settings/SettingsPanel.tsx +323 -0
  77. package/web/components/specs/SpecsPanel.tsx +1091 -0
  78. package/web/components/terminal/TerminalPanel.tsx +683 -0
  79. package/web/components/ui/ContextMenu.tsx +182 -0
  80. package/web/components/ui/LoadingSpinner.tsx +66 -0
  81. package/web/components/ui/ResizeHandle.tsx +110 -0
  82. package/web/components/ui/Skeleton.tsx +108 -0
  83. package/web/components/ui/SkipLinks.tsx +37 -0
  84. package/web/components/ui/Toaster.tsx +57 -0
  85. package/web/hooks/useFocusTrap.ts +141 -0
  86. package/web/hooks/useKeyboardShortcuts.ts +169 -0
  87. package/web/hooks/useListNavigation.ts +237 -0
  88. package/web/lib/autopilotConstants.ts +213 -0
  89. package/web/lib/constants/agents.ts +67 -0
  90. package/web/lib/git.ts +339 -0
  91. package/web/lib/ptyManager.ts +191 -0
  92. package/web/lib/specsParser.ts +299 -0
  93. package/web/lib/stores/autopilotStore.ts +288 -0
  94. package/web/lib/stores/fileStore.ts +550 -0
  95. package/web/lib/stores/gitStore.ts +386 -0
  96. package/web/lib/stores/projectStore.ts +196 -0
  97. package/web/lib/stores/settingsStore.ts +126 -0
  98. package/web/lib/stores/specsStore.ts +297 -0
  99. package/web/lib/stores/uiStore.ts +175 -0
  100. package/web/lib/types/index.ts +177 -0
  101. package/web/lib/utils.ts +98 -0
  102. package/web/next.config.js +50 -0
  103. package/web/package.json +54 -0
  104. package/web/postcss.config.js +6 -0
  105. package/web/tailwind.config.ts +68 -0
  106. 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
+ }