bobs-workshop 0.1.4
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/LICENSE +21 -0
- package/README.md +252 -0
- package/bin/bobs-mcp.js +130 -0
- package/dist/api/taskLogger.js +106 -0
- package/dist/api/taskLogger.js.map +1 -0
- package/dist/cli/checker.js +401 -0
- package/dist/cli/checker.js.map +1 -0
- package/dist/cli/cleanup.js +131 -0
- package/dist/cli/cleanup.js.map +1 -0
- package/dist/cli/debug.js +157 -0
- package/dist/cli/debug.js.map +1 -0
- package/dist/cli/health.js +97 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/setup.js +81 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/workshop.js +42 -0
- package/dist/cli/workshop.js.map +1 -0
- package/dist/dashboard/server.js +1206 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/index.js +757 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/architect.js +157 -0
- package/dist/prompts/architect.js.map +1 -0
- package/dist/prompts/debugger.js +201 -0
- package/dist/prompts/debugger.js.map +1 -0
- package/dist/prompts/engineer.js +171 -0
- package/dist/prompts/engineer.js.map +1 -0
- package/dist/prompts/orchestrator.js +225 -0
- package/dist/prompts/orchestrator.js.map +1 -0
- package/dist/prompts/reviewer.js +199 -0
- package/dist/prompts/reviewer.js.map +1 -0
- package/dist/services/activitySummarizer.js +353 -0
- package/dist/services/activitySummarizer.js.map +1 -0
- package/dist/services/changeValidator.js +396 -0
- package/dist/services/changeValidator.js.map +1 -0
- package/dist/services/claudeOrchestrator.js +343 -0
- package/dist/services/claudeOrchestrator.js.map +1 -0
- package/dist/services/fileMonitor.js +250 -0
- package/dist/services/fileMonitor.js.map +1 -0
- package/dist/services/implementationSummarizer.js +306 -0
- package/dist/services/implementationSummarizer.js.map +1 -0
- package/dist/services/liveMonitor.js +315 -0
- package/dist/services/liveMonitor.js.map +1 -0
- package/dist/services/mcpAuditLogger.js +104 -0
- package/dist/services/mcpAuditLogger.js.map +1 -0
- package/dist/services/mcpLogger.js +223 -0
- package/dist/services/mcpLogger.js.map +1 -0
- package/dist/services/tmuxManager.js +541 -0
- package/dist/services/tmuxManager.js.map +1 -0
- package/dist/tools/approvalTools.js +244 -0
- package/dist/tools/approvalTools.js.map +1 -0
- package/dist/tools/autoDebugger.js +147 -0
- package/dist/tools/autoDebugger.js.map +1 -0
- package/dist/tools/cleanupService.js +221 -0
- package/dist/tools/cleanupService.js.map +1 -0
- package/dist/tools/dashboardTools.js +359 -0
- package/dist/tools/dashboardTools.js.map +1 -0
- package/dist/tools/developmentNudges.js +336 -0
- package/dist/tools/developmentNudges.js.map +1 -0
- package/dist/tools/gitTools.js +741 -0
- package/dist/tools/gitTools.js.map +1 -0
- package/dist/tools/orchestratorTools.js +765 -0
- package/dist/tools/orchestratorTools.js.map +1 -0
- package/dist/tools/searchTools.js +788 -0
- package/dist/tools/searchTools.js.map +1 -0
- package/dist/tools/specTools.js +350 -0
- package/dist/tools/specTools.js.map +1 -0
- package/dist/tools/tmuxTools.js +100 -0
- package/dist/tools/tmuxTools.js.map +1 -0
- package/dist/tools/workRecorder.js +215 -0
- package/dist/tools/workRecorder.js.map +1 -0
- package/dist/tools/worktreeTools.js +705 -0
- package/dist/tools/worktreeTools.js.map +1 -0
- package/dist/utils/__tests__/integration.test.js +57 -0
- package/dist/utils/__tests__/integration.test.js.map +1 -0
- package/dist/utils/__tests__/serverDetection.test.js +151 -0
- package/dist/utils/__tests__/serverDetection.test.js.map +1 -0
- package/dist/utils/errorHandling.js +336 -0
- package/dist/utils/errorHandling.js.map +1 -0
- package/dist/utils/processManager.js +172 -0
- package/dist/utils/processManager.js.map +1 -0
- package/dist/utils/reliability.js +263 -0
- package/dist/utils/reliability.js.map +1 -0
- package/dist/utils/responseFormatter.js +250 -0
- package/dist/utils/responseFormatter.js.map +1 -0
- package/dist/utils/serverDetection.js +133 -0
- package/dist/utils/serverDetection.js.map +1 -0
- package/dist/utils/specMigration.js +105 -0
- package/dist/utils/specMigration.js.map +1 -0
- package/dist/validation/schemas.js +299 -0
- package/dist/validation/schemas.js.map +1 -0
- package/package.json +79 -0
- package/scripts/init-workspace.js +63 -0
- package/scripts/install-search-tools.js +116 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
// Enhanced icons for different states and modes
|
|
4
|
+
const MODE_ICONS = {
|
|
5
|
+
orchestrator: 'šÆ',
|
|
6
|
+
architect: 'š',
|
|
7
|
+
engineer: 'āļø',
|
|
8
|
+
debugger: 'š',
|
|
9
|
+
reviewer: 'š',
|
|
10
|
+
unknown: 'š§'
|
|
11
|
+
};
|
|
12
|
+
const STATUS_ICONS = {
|
|
13
|
+
// Main spec states
|
|
14
|
+
draft: 'š',
|
|
15
|
+
ready: 'ā
',
|
|
16
|
+
engineered: 'š',
|
|
17
|
+
done: 'š',
|
|
18
|
+
// Debug resolution states
|
|
19
|
+
fixed: 'ā
',
|
|
20
|
+
escalated: 'ā¬ļø',
|
|
21
|
+
pending: 'ā³',
|
|
22
|
+
// Workflow step states
|
|
23
|
+
questioning: 'ā',
|
|
24
|
+
spec_review: 'š',
|
|
25
|
+
approved: 'ā
',
|
|
26
|
+
implementation: 'āļø',
|
|
27
|
+
user_review: 'šØāš»',
|
|
28
|
+
completed: 'š',
|
|
29
|
+
routed_to_architect: 'š',
|
|
30
|
+
routed_to_engineer: 'āļø',
|
|
31
|
+
routed_to_debugger: 'š',
|
|
32
|
+
routed_to_reviewer: 'š',
|
|
33
|
+
// Action states
|
|
34
|
+
clarify: 'ā',
|
|
35
|
+
route: 'ā”ļø',
|
|
36
|
+
continue: 'ā¶ļø',
|
|
37
|
+
await_approval: 'āøļø',
|
|
38
|
+
proceed: 'ā¶ļø',
|
|
39
|
+
complete: 'š',
|
|
40
|
+
// Additional states
|
|
41
|
+
debug: 'š§',
|
|
42
|
+
error: 'ā',
|
|
43
|
+
failed: 'š„',
|
|
44
|
+
success: 'ā
',
|
|
45
|
+
healthy: 'š',
|
|
46
|
+
degraded: 'ā ļø',
|
|
47
|
+
unknown: 'ā'
|
|
48
|
+
};
|
|
49
|
+
const TOOL_ICONS = {
|
|
50
|
+
'manual.create': 'š',
|
|
51
|
+
'manual.update': 'āļø',
|
|
52
|
+
'manual.get': 'š',
|
|
53
|
+
'search.hybrid': 'š',
|
|
54
|
+
'workflow.start': 'š',
|
|
55
|
+
'workflow.deploy': 'šÆ',
|
|
56
|
+
'health': 'š',
|
|
57
|
+
'validate': 'ā
',
|
|
58
|
+
'cleanup': 'š§¹',
|
|
59
|
+
'dashboard': 'š»'
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Detects the current mode based on context clues
|
|
63
|
+
*/
|
|
64
|
+
function detectMode(toolName, result) {
|
|
65
|
+
// Try to detect from tool context
|
|
66
|
+
if (toolName?.includes('workflow.start'))
|
|
67
|
+
return 'architect';
|
|
68
|
+
if (toolName?.includes('workflow.deploy'))
|
|
69
|
+
return 'engineer';
|
|
70
|
+
if (toolName?.includes('search') && result?.phase)
|
|
71
|
+
return result.phase;
|
|
72
|
+
if (toolName?.includes('manual.create'))
|
|
73
|
+
return 'architect';
|
|
74
|
+
if (toolName?.includes('debug') || toolName?.includes('validate'))
|
|
75
|
+
return 'debugger';
|
|
76
|
+
if (toolName?.includes('health') || toolName?.includes('cleanup'))
|
|
77
|
+
return 'engineer';
|
|
78
|
+
// Check for activity logs that might indicate mode
|
|
79
|
+
if (result?.activity) {
|
|
80
|
+
const recentActivity = result.activity[result.activity.length - 1];
|
|
81
|
+
if (recentActivity?.role === 'engineer')
|
|
82
|
+
return 'engineer';
|
|
83
|
+
if (recentActivity?.role === 'debugger')
|
|
84
|
+
return 'debugger';
|
|
85
|
+
if (recentActivity?.role === 'architect')
|
|
86
|
+
return 'architect';
|
|
87
|
+
if (recentActivity?.role === 'reviewer')
|
|
88
|
+
return 'reviewer';
|
|
89
|
+
}
|
|
90
|
+
// Check process environment or arguments for mode hints
|
|
91
|
+
try {
|
|
92
|
+
const args = process.argv.join(' ').toLowerCase();
|
|
93
|
+
if (args.includes('architect'))
|
|
94
|
+
return 'architect';
|
|
95
|
+
if (args.includes('engineer'))
|
|
96
|
+
return 'engineer';
|
|
97
|
+
if (args.includes('debugger'))
|
|
98
|
+
return 'debugger';
|
|
99
|
+
if (args.includes('reviewer'))
|
|
100
|
+
return 'reviewer';
|
|
101
|
+
if (args.includes('orchestrator'))
|
|
102
|
+
return 'orchestrator';
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
// Ignore errors in process inspection
|
|
106
|
+
}
|
|
107
|
+
return 'unknown';
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Gets manual status for a given spec_id
|
|
111
|
+
*/
|
|
112
|
+
async function getManualStatus(specId) {
|
|
113
|
+
try {
|
|
114
|
+
const specsDir = path.resolve(process.cwd(), ".bob/specs");
|
|
115
|
+
const filePath = path.join(specsDir, `${specId}.json`);
|
|
116
|
+
if (await fs.pathExists(filePath)) {
|
|
117
|
+
const specData = await fs.readJson(filePath);
|
|
118
|
+
return specData.state || 'unknown';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
// Silently fail and return unknown
|
|
123
|
+
}
|
|
124
|
+
return 'unknown';
|
|
125
|
+
}
|
|
126
|
+
export async function formatConciseResponse(toolName, result, options = {}) {
|
|
127
|
+
const { includeTimestamp = true, maxContentLength = 100, showMetadata = true, mode = options.mode || detectMode(toolName, result), specId = result.spec_id } = options;
|
|
128
|
+
// Get tool icon
|
|
129
|
+
const toolKey = Object.keys(TOOL_ICONS).find(key => toolName.includes(key)) || 'unknown';
|
|
130
|
+
const toolIcon = TOOL_ICONS[toolKey] || 'š§';
|
|
131
|
+
// Get mode and status information
|
|
132
|
+
const modeIcon = MODE_ICONS[mode] || MODE_ICONS.unknown;
|
|
133
|
+
let statusInfo = '';
|
|
134
|
+
if (specId) {
|
|
135
|
+
try {
|
|
136
|
+
const status = await getManualStatus(specId);
|
|
137
|
+
const statusIcon = STATUS_ICONS[status] || STATUS_ICONS.unknown;
|
|
138
|
+
statusInfo = ` ${statusIcon} ${status}`;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// Silently handle error
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Default to just the summary if available
|
|
145
|
+
if (result._meta?.summary) {
|
|
146
|
+
return `${toolIcon} ${result._meta.summary}${statusInfo}`;
|
|
147
|
+
}
|
|
148
|
+
// Handle different tool types with enhanced formatting
|
|
149
|
+
let baseMessage = '';
|
|
150
|
+
switch (true) {
|
|
151
|
+
case toolName.includes('manual.update'):
|
|
152
|
+
baseMessage = formatManualUpdateResponse(result, maxContentLength);
|
|
153
|
+
break;
|
|
154
|
+
case toolName.includes('manual.create'):
|
|
155
|
+
baseMessage = formatManualCreateResponse(result);
|
|
156
|
+
break;
|
|
157
|
+
case toolName.includes('search'):
|
|
158
|
+
baseMessage = formatSearchResponse(result);
|
|
159
|
+
break;
|
|
160
|
+
case toolName.includes('workflow'):
|
|
161
|
+
baseMessage = formatWorkflowResponse(result);
|
|
162
|
+
break;
|
|
163
|
+
case toolName.includes('health'):
|
|
164
|
+
baseMessage = formatHealthResponse(result);
|
|
165
|
+
break;
|
|
166
|
+
default:
|
|
167
|
+
baseMessage = formatGenericResponse(result, maxContentLength);
|
|
168
|
+
}
|
|
169
|
+
// Add mode indicator if metadata is requested
|
|
170
|
+
const modeIndicator = showMetadata ? `${modeIcon} ` : '';
|
|
171
|
+
return `${toolIcon} ${modeIndicator}${baseMessage}${statusInfo}`;
|
|
172
|
+
}
|
|
173
|
+
function formatManualUpdateResponse(result, maxLength) {
|
|
174
|
+
const specId = result.spec_id || 'unknown';
|
|
175
|
+
const shortId = specId.split('-').pop() || specId;
|
|
176
|
+
const state = result.state || 'draft';
|
|
177
|
+
const timestamp = result.updated_at ? new Date(result.updated_at).toLocaleTimeString() : '';
|
|
178
|
+
return `Manual ${shortId} updated ā ${state}${timestamp ? ` (${timestamp})` : ''}`;
|
|
179
|
+
}
|
|
180
|
+
function formatManualCreateResponse(result) {
|
|
181
|
+
const specId = result.spec_id || 'unknown';
|
|
182
|
+
const shortId = specId.split('-').pop() || specId;
|
|
183
|
+
const state = result.state || 'draft';
|
|
184
|
+
return `Manual created: ${shortId} ā ${state}`;
|
|
185
|
+
}
|
|
186
|
+
function formatSearchResponse(result) {
|
|
187
|
+
if (result.stats?.totalResults !== undefined) {
|
|
188
|
+
const count = result.stats.totalResults;
|
|
189
|
+
const mode = result.stats.searchMode || 'hybrid';
|
|
190
|
+
return `Search (${mode}): ${count} result${count !== 1 ? 's' : ''} found`;
|
|
191
|
+
}
|
|
192
|
+
if (result.lexicalHits && result.semanticHits) {
|
|
193
|
+
const lexical = result.lexicalHits.length;
|
|
194
|
+
const semantic = result.semanticHits.length;
|
|
195
|
+
const total = lexical + semantic;
|
|
196
|
+
return `Search: ${total} results (${lexical} lexical, ${semantic} semantic)`;
|
|
197
|
+
}
|
|
198
|
+
return 'Search completed';
|
|
199
|
+
}
|
|
200
|
+
function formatWorkflowResponse(result) {
|
|
201
|
+
const workflowStatus = result.workflow_status;
|
|
202
|
+
if (workflowStatus === 'started' && result.manual?.spec_id) {
|
|
203
|
+
const shortId = result.manual.spec_id.split('-').pop() || 'manual';
|
|
204
|
+
return `Workflow started for ${shortId}`;
|
|
205
|
+
}
|
|
206
|
+
if (workflowStatus === 'deployed') {
|
|
207
|
+
return 'Workflow deployed successfully';
|
|
208
|
+
}
|
|
209
|
+
return `Workflow ${workflowStatus || 'completed'}`;
|
|
210
|
+
}
|
|
211
|
+
function formatHealthResponse(result) {
|
|
212
|
+
const status = result.status || (result.overall_healthy ? 'healthy' : 'degraded');
|
|
213
|
+
const componentCount = result.component_health ? Object.keys(result.component_health).length : 0;
|
|
214
|
+
return `System ${status}${componentCount > 0 ? ` (${componentCount} components checked)` : ''}`;
|
|
215
|
+
}
|
|
216
|
+
function formatGenericResponse(result, maxLength) {
|
|
217
|
+
if (typeof result === 'string') {
|
|
218
|
+
return result.length > maxLength ? result.substring(0, maxLength) + '...' : result;
|
|
219
|
+
}
|
|
220
|
+
if (result.message) {
|
|
221
|
+
return result.message.length > maxLength ? result.message.substring(0, maxLength) + '...' : result.message;
|
|
222
|
+
}
|
|
223
|
+
return 'Operation completed';
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creates activity log entries with different verbosity levels:
|
|
227
|
+
* - Terminal: Concise for clean command line output
|
|
228
|
+
* - Dashboard: Enhanced with specific task details and context
|
|
229
|
+
*/
|
|
230
|
+
export function formatConciseActivityLog(action, details, maxLength = 80) {
|
|
231
|
+
switch (action) {
|
|
232
|
+
case 'section_updated':
|
|
233
|
+
const section = details.section?.replace(/_/g, ' ') || 'section';
|
|
234
|
+
const wordCount = details.wordCount || 0;
|
|
235
|
+
return `Updated ${section} (${wordCount} words)`;
|
|
236
|
+
case 'execution_log':
|
|
237
|
+
const filesCount = details.filesCount || 0;
|
|
238
|
+
const taskId = details.taskId || 'task';
|
|
239
|
+
return `š ļø ${taskId}: ${filesCount} files modified`;
|
|
240
|
+
case 'debug_log':
|
|
241
|
+
const confidence = details.confidence || 'medium';
|
|
242
|
+
return `š Debug issue resolved (confidence: ${confidence})`;
|
|
243
|
+
case 'state_change':
|
|
244
|
+
return `State: ${details.oldState} ā ${details.newState}`;
|
|
245
|
+
default:
|
|
246
|
+
const summary = typeof details === 'string' ? details : details.summary || 'Activity logged';
|
|
247
|
+
return summary.length > maxLength ? summary.substring(0, maxLength) + '...' : summary;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=responseFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseFormatter.js","sourceRoot":"","sources":["../../src/utils/responseFormatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/utils/serverDetection.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
/**
|
|
5
|
+
* Detects the project type based on files in the directory
|
|
6
|
+
*/
|
|
7
|
+
export function detectProjectType(projectPath) {
|
|
8
|
+
try {
|
|
9
|
+
// Check for Node.js project
|
|
10
|
+
if (fs.existsSync(path.join(projectPath, 'package.json'))) {
|
|
11
|
+
return 'node';
|
|
12
|
+
}
|
|
13
|
+
// Check for Go project
|
|
14
|
+
if (fs.existsSync(path.join(projectPath, 'go.mod'))) {
|
|
15
|
+
return 'go';
|
|
16
|
+
}
|
|
17
|
+
// Check for Python project
|
|
18
|
+
if (fs.existsSync(path.join(projectPath, 'requirements.txt'))) {
|
|
19
|
+
return 'python';
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.warn(`Error detecting project type in ${projectPath}:`, error);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Gets server configuration based on project type and detected settings
|
|
30
|
+
*/
|
|
31
|
+
export async function getServerConfig(projectPath, projectType) {
|
|
32
|
+
if (!projectType) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
switch (projectType) {
|
|
37
|
+
case 'node':
|
|
38
|
+
return await getNodeServerConfig(projectPath);
|
|
39
|
+
case 'go':
|
|
40
|
+
return getGoServerConfig(projectPath);
|
|
41
|
+
case 'python':
|
|
42
|
+
return getPythonServerConfig(projectPath);
|
|
43
|
+
default:
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.warn(`Error getting server config for ${projectType}:`, error);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Gets Node.js server configuration by reading package.json
|
|
54
|
+
*/
|
|
55
|
+
async function getNodeServerConfig(projectPath) {
|
|
56
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
57
|
+
try {
|
|
58
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
59
|
+
const scripts = packageJson.scripts || {};
|
|
60
|
+
// Determine dev command
|
|
61
|
+
let devCommand = 'npm start';
|
|
62
|
+
if (scripts.dev) {
|
|
63
|
+
devCommand = 'npm run dev';
|
|
64
|
+
}
|
|
65
|
+
else if (scripts.start) {
|
|
66
|
+
devCommand = 'npm start';
|
|
67
|
+
}
|
|
68
|
+
else if (scripts.serve) {
|
|
69
|
+
devCommand = 'npm run serve';
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
startupScript: 'npm install',
|
|
73
|
+
devCommand,
|
|
74
|
+
port: 3000, // Common default for Node.js apps
|
|
75
|
+
healthCheckUrl: 'http://localhost:3000'
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
// Fallback configuration
|
|
80
|
+
return {
|
|
81
|
+
startupScript: 'npm install',
|
|
82
|
+
devCommand: 'npm start',
|
|
83
|
+
port: 3000
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Gets Go server configuration
|
|
89
|
+
*/
|
|
90
|
+
function getGoServerConfig(projectPath) {
|
|
91
|
+
// Check if main.go exists
|
|
92
|
+
const hasMainGo = fs.existsSync(path.join(projectPath, 'main.go'));
|
|
93
|
+
return {
|
|
94
|
+
devCommand: hasMainGo ? 'go run main.go' : 'go run .',
|
|
95
|
+
port: 8080, // Common default for Go apps
|
|
96
|
+
healthCheckUrl: 'http://localhost:8080'
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Gets Python server configuration
|
|
101
|
+
*/
|
|
102
|
+
function getPythonServerConfig(projectPath) {
|
|
103
|
+
// Check for common Python entry points
|
|
104
|
+
const hasAppPy = fs.existsSync(path.join(projectPath, 'app.py'));
|
|
105
|
+
const hasMainPy = fs.existsSync(path.join(projectPath, 'main.py'));
|
|
106
|
+
const hasManagePy = fs.existsSync(path.join(projectPath, 'manage.py'));
|
|
107
|
+
let devCommand = 'python app.py';
|
|
108
|
+
if (hasManagePy) {
|
|
109
|
+
// Django project
|
|
110
|
+
devCommand = 'python manage.py runserver';
|
|
111
|
+
}
|
|
112
|
+
else if (hasMainPy) {
|
|
113
|
+
devCommand = 'python main.py';
|
|
114
|
+
}
|
|
115
|
+
else if (hasAppPy) {
|
|
116
|
+
devCommand = 'python app.py';
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
startupScript: 'pip install -r requirements.txt',
|
|
120
|
+
devCommand,
|
|
121
|
+
port: 5000, // Common default for Python apps
|
|
122
|
+
healthCheckUrl: 'http://localhost:5000'
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Validates if a server configuration is valid
|
|
127
|
+
*/
|
|
128
|
+
export function validateServerConfig(config) {
|
|
129
|
+
if (!config)
|
|
130
|
+
return false;
|
|
131
|
+
return Boolean(config.devCommand && config.devCommand.trim().length > 0);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=serverDetection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverDetection.js","sourceRoot":"","sources":["../../src/utils/serverDetection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// src/utils/specMigration.ts
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "path";
|
|
4
|
+
const DEFAULT_WORKTREE_METADATA = {
|
|
5
|
+
path: null,
|
|
6
|
+
branch: null,
|
|
7
|
+
status: "pending",
|
|
8
|
+
createdAt: null,
|
|
9
|
+
lastActivity: null,
|
|
10
|
+
specPath: null,
|
|
11
|
+
validation: {
|
|
12
|
+
isClean: false,
|
|
13
|
+
hasChanges: false,
|
|
14
|
+
lastChecked: null
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Migrate a single SPEC file to include worktree metadata
|
|
19
|
+
*/
|
|
20
|
+
export async function migrateSpecFile(specFilePath) {
|
|
21
|
+
try {
|
|
22
|
+
if (!await fs.pathExists(specFilePath)) {
|
|
23
|
+
console.warn(`SPEC file not found: ${specFilePath}`);
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const specData = await fs.readJson(specFilePath);
|
|
27
|
+
// Check if migration is needed
|
|
28
|
+
if (specData.worktree) {
|
|
29
|
+
console.log(`SPEC ${specData.spec_id} already has worktree metadata, skipping migration`);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
// Add worktree metadata
|
|
33
|
+
specData.worktree = DEFAULT_WORKTREE_METADATA;
|
|
34
|
+
specData.updated_at = new Date().toISOString();
|
|
35
|
+
// Write back to file
|
|
36
|
+
await fs.writeFile(specFilePath, JSON.stringify(specData, null, 2), "utf8");
|
|
37
|
+
console.log(`ā
Migrated SPEC ${specData.spec_id} to include worktree metadata`);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error(`ā Failed to migrate SPEC file ${specFilePath}:`, error);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Migrate all SPEC files in the .bob/specs directory
|
|
47
|
+
*/
|
|
48
|
+
export async function migrateAllSpecs() {
|
|
49
|
+
const specsDir = path.resolve(process.cwd(), ".bob/specs");
|
|
50
|
+
if (!await fs.pathExists(specsDir)) {
|
|
51
|
+
console.warn("Specs directory not found, no migration needed");
|
|
52
|
+
return { total: 0, migrated: 0, skipped: 0, failed: 0 };
|
|
53
|
+
}
|
|
54
|
+
const files = await fs.readdir(specsDir);
|
|
55
|
+
const specFiles = files.filter(file => file.startsWith("SPEC-") && file.endsWith(".json"));
|
|
56
|
+
let migrated = 0;
|
|
57
|
+
let skipped = 0;
|
|
58
|
+
let failed = 0;
|
|
59
|
+
console.log(`\nš Starting migration of ${specFiles.length} SPEC files...\n`);
|
|
60
|
+
for (const specFile of specFiles) {
|
|
61
|
+
const specFilePath = path.join(specsDir, specFile);
|
|
62
|
+
try {
|
|
63
|
+
const wasMigrated = await migrateSpecFile(specFilePath);
|
|
64
|
+
if (wasMigrated) {
|
|
65
|
+
migrated++;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
skipped++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error(`Failed to migrate ${specFile}:`, error);
|
|
73
|
+
failed++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const results = {
|
|
77
|
+
total: specFiles.length,
|
|
78
|
+
migrated,
|
|
79
|
+
skipped,
|
|
80
|
+
failed
|
|
81
|
+
};
|
|
82
|
+
console.log(`\nš Migration Summary:`);
|
|
83
|
+
console.log(` Total SPEC files: ${results.total}`);
|
|
84
|
+
console.log(` ā
Migrated: ${results.migrated}`);
|
|
85
|
+
console.log(` āļø Skipped (already migrated): ${results.skipped}`);
|
|
86
|
+
console.log(` ā Failed: ${results.failed}\n`);
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if a SPEC file needs migration
|
|
91
|
+
*/
|
|
92
|
+
export async function needsMigration(specFilePath) {
|
|
93
|
+
try {
|
|
94
|
+
if (!await fs.pathExists(specFilePath)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const specData = await fs.readJson(specFilePath);
|
|
98
|
+
return !specData.worktree;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(`Error checking migration status for ${specFilePath}:`, error);
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=specMigration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specMigration.js","sourceRoot":"","sources":["../../src/utils/specMigration.ts"],"names":[],"mappings":"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"}
|