bobs-workshop 0.3.3 → 3.1.1
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 +2 -2
- package/README.md +199 -210
- package/bin/bobs-workshop.js +109 -0
- package/config/agents.json +27 -0
- package/dist/plugins/bobs-workshop.js +34 -0
- package/dist/tools/background-agent/cancel.d.ts +3 -0
- package/dist/tools/background-agent/cancel.d.ts.map +1 -0
- package/dist/tools/background-agent/cancel.js +52 -0
- package/dist/tools/background-agent/concurrency.d.ts +15 -0
- package/dist/tools/background-agent/concurrency.d.ts.map +1 -0
- package/dist/tools/background-agent/concurrency.js +61 -0
- package/dist/tools/background-agent/index.d.ts +8 -0
- package/dist/tools/background-agent/index.d.ts.map +1 -0
- package/dist/tools/background-agent/index.js +7 -0
- package/dist/tools/background-agent/launch.d.ts +6 -0
- package/dist/tools/background-agent/launch.d.ts.map +1 -0
- package/dist/tools/background-agent/launch.js +33 -0
- package/dist/tools/background-agent/list.d.ts +7 -0
- package/dist/tools/background-agent/list.d.ts.map +1 -0
- package/dist/tools/background-agent/list.js +40 -0
- package/dist/tools/background-agent/manager.d.ts +29 -0
- package/dist/tools/background-agent/manager.d.ts.map +1 -0
- package/dist/tools/background-agent/manager.js +388 -0
- package/dist/tools/background-agent/output.d.ts +3 -0
- package/dist/tools/background-agent/output.d.ts.map +1 -0
- package/dist/tools/background-agent/output.js +41 -0
- package/dist/tools/background-agent/types.d.ts +46 -0
- package/dist/tools/background-agent/types.d.ts.map +1 -0
- package/dist/tools/background-agent/types.js +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/manual/index.d.ts +3 -0
- package/dist/tools/manual/index.d.ts.map +1 -0
- package/dist/tools/manual/index.js +2 -0
- package/dist/tools/manual/manual-update.d.ts +4 -0
- package/dist/tools/manual/manual-update.d.ts.map +1 -0
- package/dist/tools/manual/manual-update.js +190 -0
- package/dist/tools/manual/verify-manual.d.ts +4 -0
- package/dist/tools/manual/verify-manual.d.ts.map +1 -0
- package/dist/tools/manual/verify-manual.js +51 -0
- package/package.json +34 -66
- package/postinstall.js +193 -0
- package/src/agents/alice.md +466 -0
- package/src/agents/bob-rev.md +493 -0
- package/src/agents/bob-send.md +277 -0
- package/src/agents/bob.md +442 -0
- package/src/agents/trace.md +451 -0
- package/src/plugins/bobs-workshop.ts +45 -0
- package/src/skills/api-patterns/SKILL.md +376 -0
- package/src/skills/architecture/SKILL.md +271 -0
- package/src/skills/bobs-workshop/performance/icon.svg +3 -0
- package/src/skills/brainstorming/SKILL.md +210 -0
- package/src/skills/clean-code/SKILL.md +151 -0
- package/src/skills/code-review-checklist/SKILL.md +220 -0
- package/src/skills/database-design/SKILL.md +271 -0
- package/src/skills/exploration/SKILL.md +257 -0
- package/src/skills/frontend-ui-ux/SKILL.md +78 -0
- package/src/skills/git-master/SKILL.md +1105 -0
- package/src/skills/performance/SKILL.md +144 -0
- package/src/skills/performance/icon.svg +3 -0
- package/src/skills/plan-writing/SKILL.md +225 -0
- package/src/skills/security/SKILL.md +410 -0
- package/src/skills/simplification/SKILL.md +238 -0
- package/src/skills/systematic-debugging/SKILL.md +175 -0
- package/src/skills/testing-patterns/SKILL.md +305 -0
- package/src/skills/verification/SKILL.md +286 -0
- package/src/tools/background-agent/cancel.ts +67 -0
- package/src/tools/background-agent/concurrency.ts +71 -0
- package/src/tools/background-agent/index.ts +7 -0
- package/src/tools/background-agent/launch.ts +39 -0
- package/src/tools/background-agent/list.ts +50 -0
- package/src/tools/background-agent/manager.ts +466 -0
- package/src/tools/background-agent/output.ts +57 -0
- package/src/tools/background-agent/types.ts +55 -0
- package/src/tools/index.ts +8 -0
- package/src/tools/manual/index.ts +2 -0
- package/src/tools/manual/manual-update.ts +197 -0
- package/src/tools/manual/verify-manual.ts +60 -0
- package/uninstall.js +64 -0
- package/Claude.md +0 -162
- package/bin/bobs-mcp-server.js +0 -11
- package/bin/bobs-mcp.js +0 -130
- package/dist/api/taskLogger.js +0 -106
- package/dist/api/taskLogger.js.map +0 -1
- package/dist/cli/checker.js +0 -401
- package/dist/cli/checker.js.map +0 -1
- package/dist/cli/cleanup.js +0 -131
- package/dist/cli/cleanup.js.map +0 -1
- package/dist/cli/debug.js +0 -157
- package/dist/cli/debug.js.map +0 -1
- package/dist/cli/health.js +0 -97
- package/dist/cli/health.js.map +0 -1
- package/dist/cli/setup.js +0 -81
- package/dist/cli/setup.js.map +0 -1
- package/dist/cli/workshop.js +0 -42
- package/dist/cli/workshop.js.map +0 -1
- package/dist/dashboard/server.js +0 -1203
- package/dist/dashboard/server.js.map +0 -1
- package/dist/index.js +0 -960
- package/dist/index.js.map +0 -1
- package/dist/prompts/architect.js +0 -221
- package/dist/prompts/architect.js.map +0 -1
- package/dist/prompts/debugger.js +0 -257
- package/dist/prompts/debugger.js.map +0 -1
- package/dist/prompts/engineer.js +0 -249
- package/dist/prompts/engineer.js.map +0 -1
- package/dist/prompts/orchestrator.js +0 -304
- package/dist/prompts/orchestrator.js.map +0 -1
- package/dist/prompts/reviewer.js +0 -289
- package/dist/prompts/reviewer.js.map +0 -1
- package/dist/services/activitySummarizer.js +0 -388
- package/dist/services/activitySummarizer.js.map +0 -1
- package/dist/services/changeValidator.js +0 -396
- package/dist/services/changeValidator.js.map +0 -1
- package/dist/services/claudeOrchestrator.js +0 -343
- package/dist/services/claudeOrchestrator.js.map +0 -1
- package/dist/services/fileMonitor.js +0 -250
- package/dist/services/fileMonitor.js.map +0 -1
- package/dist/services/implementationSummarizer.js +0 -306
- package/dist/services/implementationSummarizer.js.map +0 -1
- package/dist/services/liveMonitor.js +0 -315
- package/dist/services/liveMonitor.js.map +0 -1
- package/dist/services/mcpAuditLogger.js +0 -104
- package/dist/services/mcpAuditLogger.js.map +0 -1
- package/dist/services/mcpLogger.js +0 -223
- package/dist/services/mcpLogger.js.map +0 -1
- package/dist/services/tmuxManager.js +0 -541
- package/dist/services/tmuxManager.js.map +0 -1
- package/dist/tools/approvalTools.js +0 -244
- package/dist/tools/approvalTools.js.map +0 -1
- package/dist/tools/autoDebugger.js +0 -147
- package/dist/tools/autoDebugger.js.map +0 -1
- package/dist/tools/cleanupService.js +0 -221
- package/dist/tools/cleanupService.js.map +0 -1
- package/dist/tools/dashboardTools.js +0 -342
- package/dist/tools/dashboardTools.js.map +0 -1
- package/dist/tools/developmentNudges.js +0 -336
- package/dist/tools/developmentNudges.js.map +0 -1
- package/dist/tools/gitTools.js +0 -741
- package/dist/tools/gitTools.js.map +0 -1
- package/dist/tools/orchestratorTools.js +0 -832
- package/dist/tools/orchestratorTools.js.map +0 -1
- package/dist/tools/searchCache.js +0 -64
- package/dist/tools/searchCache.js.map +0 -1
- package/dist/tools/searchTools.js +0 -1107
- package/dist/tools/searchTools.js.map +0 -1
- package/dist/tools/semgrep-patterns.js +0 -296
- package/dist/tools/semgrep-patterns.js.map +0 -1
- package/dist/tools/specTools.js +0 -332
- package/dist/tools/specTools.js.map +0 -1
- package/dist/tools/structural/__tests__/orchestrator.test.js +0 -61
- package/dist/tools/structural/__tests__/orchestrator.test.js.map +0 -1
- package/dist/tools/structural/cache.js +0 -226
- package/dist/tools/structural/cache.js.map +0 -1
- package/dist/tools/structural/engines/python/index.js +0 -118
- package/dist/tools/structural/engines/python/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +0 -97
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +0 -1
- package/dist/tools/structural/engines/typescript/analyzer.js +0 -433
- package/dist/tools/structural/engines/typescript/analyzer.js.map +0 -1
- package/dist/tools/structural/engines/typescript/index.js +0 -381
- package/dist/tools/structural/engines/typescript/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/utils.js +0 -279
- package/dist/tools/structural/engines/typescript/utils.js.map +0 -1
- package/dist/tools/structural/index.js +0 -248
- package/dist/tools/structural/index.js.map +0 -1
- package/dist/tools/structural/types.js +0 -18
- package/dist/tools/structural/types.js.map +0 -1
- package/dist/tools/tmuxTools.js +0 -100
- package/dist/tools/tmuxTools.js.map +0 -1
- package/dist/tools/workRecorder.js +0 -215
- package/dist/tools/workRecorder.js.map +0 -1
- package/dist/tools/worktreeTools.js +0 -705
- package/dist/tools/worktreeTools.js.map +0 -1
- package/dist/utils/__tests__/integration.test.js +0 -57
- package/dist/utils/__tests__/integration.test.js.map +0 -1
- package/dist/utils/__tests__/serverDetection.test.js +0 -151
- package/dist/utils/__tests__/serverDetection.test.js.map +0 -1
- package/dist/utils/errorHandling.js +0 -336
- package/dist/utils/errorHandling.js.map +0 -1
- package/dist/utils/processManager.js +0 -172
- package/dist/utils/processManager.js.map +0 -1
- package/dist/utils/reliability.js +0 -263
- package/dist/utils/reliability.js.map +0 -1
- package/dist/utils/responseFormatter.js +0 -250
- package/dist/utils/responseFormatter.js.map +0 -1
- package/dist/utils/serverDetection.js +0 -133
- package/dist/utils/serverDetection.js.map +0 -1
- package/dist/utils/specMigration.js +0 -105
- package/dist/utils/specMigration.js.map +0 -1
- package/dist/validation/schemas.js +0 -299
- package/dist/validation/schemas.js.map +0 -1
- package/public/.well-known/mcp/manifest.json +0 -473
- package/public/index.html +0 -3157
- package/public/index.html.backup +0 -2805
- package/public/index.html.backup2 +0 -1292
- package/scripts/cleanup-system-logs.ts +0 -121
- package/scripts/init-workspace.js +0 -63
- package/scripts/install-search-tools.js +0 -116
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
// src/services/claudeOrchestrator.ts
|
|
2
|
-
import { exec } from "child_process";
|
|
3
|
-
import { promisify } from "util";
|
|
4
|
-
import { EventEmitter } from "events";
|
|
5
|
-
import fs from "fs-extra";
|
|
6
|
-
const execAsync = promisify(exec);
|
|
7
|
-
/**
|
|
8
|
-
* Claude Orchestrator Service
|
|
9
|
-
* Manages Claude CLI processes within tmux sessions with lifecycle management
|
|
10
|
-
*/
|
|
11
|
-
export class ClaudeOrchestrator extends EventEmitter {
|
|
12
|
-
constructor() {
|
|
13
|
-
super();
|
|
14
|
-
this.processes = new Map();
|
|
15
|
-
this.monitoringIntervals = new Map();
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Spawn Claude process in existing tmux session
|
|
19
|
-
*/
|
|
20
|
-
async spawnClaudeInSession(sessionName, prompt, workingDir) {
|
|
21
|
-
try {
|
|
22
|
-
// Verify tmux session exists
|
|
23
|
-
await this.verifySessionExists(sessionName);
|
|
24
|
-
// Start Claude in interactive mode
|
|
25
|
-
await execAsync(`tmux send-keys -t "${sessionName}" "claude --dangerously-skip-permissions" C-m`);
|
|
26
|
-
// Wait for Claude to be ready by monitoring output
|
|
27
|
-
await this.waitForClaudeReady(sessionName);
|
|
28
|
-
// Write prompt to temp file and use tmux paste to preserve formatting
|
|
29
|
-
const tempFile = `/tmp/claude-prompt-${Date.now()}.txt`;
|
|
30
|
-
await fs.writeFile(tempFile, prompt);
|
|
31
|
-
// Load the prompt into tmux buffer and paste it
|
|
32
|
-
await execAsync(`tmux load-buffer "${tempFile}"`);
|
|
33
|
-
await execAsync(`tmux paste-buffer -t "${sessionName}"`);
|
|
34
|
-
// Send enter to submit the prompt
|
|
35
|
-
await execAsync(`tmux send-keys -t "${sessionName}" C-m`);
|
|
36
|
-
// Clean up temp file
|
|
37
|
-
await fs.unlink(tempFile).catch(() => { });
|
|
38
|
-
// Create process record
|
|
39
|
-
const claudeProcess = {
|
|
40
|
-
sessionName,
|
|
41
|
-
status: 'initializing',
|
|
42
|
-
startTime: new Date().toISOString(),
|
|
43
|
-
lastActivity: new Date().toISOString(),
|
|
44
|
-
workingDirectory: workingDir,
|
|
45
|
-
prompt
|
|
46
|
-
};
|
|
47
|
-
this.processes.set(sessionName, claudeProcess);
|
|
48
|
-
// Start monitoring this process
|
|
49
|
-
this.startProcessMonitoring(sessionName);
|
|
50
|
-
// Emit process started event
|
|
51
|
-
this.emit('processStarted', claudeProcess);
|
|
52
|
-
return claudeProcess;
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
56
|
-
throw new Error(`Failed to spawn Claude in session ${sessionName}: ${errorMessage}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Stop Claude process in session (send Ctrl-C)
|
|
61
|
-
*/
|
|
62
|
-
async stopClaudeProcess(sessionName) {
|
|
63
|
-
try {
|
|
64
|
-
await this.verifySessionExists(sessionName);
|
|
65
|
-
// Send Ctrl-C to interrupt Claude
|
|
66
|
-
await execAsync(`tmux send-keys -t "${sessionName}" C-c`);
|
|
67
|
-
// Update process status
|
|
68
|
-
const process = this.processes.get(sessionName);
|
|
69
|
-
if (process) {
|
|
70
|
-
process.status = 'terminated';
|
|
71
|
-
process.lastActivity = new Date().toISOString();
|
|
72
|
-
this.processes.set(sessionName, process);
|
|
73
|
-
// Stop monitoring
|
|
74
|
-
this.stopProcessMonitoring(sessionName);
|
|
75
|
-
// Emit process stopped event
|
|
76
|
-
this.emit('processStopped', process);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
throw new Error(`Failed to stop Claude process in session ${sessionName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Send message/command to interactive Claude session
|
|
85
|
-
*/
|
|
86
|
-
async sendCommand(sessionName, command) {
|
|
87
|
-
try {
|
|
88
|
-
await this.verifySessionExists(sessionName);
|
|
89
|
-
// Send message directly to Claude (interactive mode)
|
|
90
|
-
// Just escape quotes for the tmux command itself
|
|
91
|
-
const escapedCommand = command.replace(/"/g, '\\"');
|
|
92
|
-
await execAsync(`tmux send-keys -t "${sessionName}" "${escapedCommand}" C-m`);
|
|
93
|
-
// Update last activity
|
|
94
|
-
const process = this.processes.get(sessionName);
|
|
95
|
-
if (process) {
|
|
96
|
-
process.lastActivity = new Date().toISOString();
|
|
97
|
-
this.processes.set(sessionName, process);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
throw new Error(`Failed to send command to session ${sessionName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Get process status
|
|
106
|
-
*/
|
|
107
|
-
async getProcessStatus(sessionName) {
|
|
108
|
-
return this.processes.get(sessionName) || null;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Restart Claude process with same or new prompt
|
|
112
|
-
*/
|
|
113
|
-
async restartProcess(sessionName, newPrompt) {
|
|
114
|
-
const existingProcess = this.processes.get(sessionName);
|
|
115
|
-
if (!existingProcess) {
|
|
116
|
-
throw new Error(`No process found for session ${sessionName}`);
|
|
117
|
-
}
|
|
118
|
-
// Stop current process if running
|
|
119
|
-
if (existingProcess.status === 'running') {
|
|
120
|
-
await this.stopClaudeProcess(sessionName);
|
|
121
|
-
// Wait a moment for cleanup
|
|
122
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
123
|
-
}
|
|
124
|
-
// Restart with new or existing prompt
|
|
125
|
-
const prompt = newPrompt || existingProcess.prompt;
|
|
126
|
-
return await this.spawnClaudeInSession(sessionName, prompt, existingProcess.workingDirectory);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Get all managed processes
|
|
130
|
-
*/
|
|
131
|
-
getAllProcesses() {
|
|
132
|
-
return Array.from(this.processes.values());
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Clean up terminated or orphaned processes
|
|
136
|
-
*/
|
|
137
|
-
async cleanup() {
|
|
138
|
-
let cleanedCount = 0;
|
|
139
|
-
for (const [sessionName, process] of this.processes) {
|
|
140
|
-
try {
|
|
141
|
-
// Check if tmux session still exists
|
|
142
|
-
const sessionExists = await this.sessionExists(sessionName);
|
|
143
|
-
if (!sessionExists || process.status === 'terminated') {
|
|
144
|
-
this.stopProcessMonitoring(sessionName);
|
|
145
|
-
this.processes.delete(sessionName);
|
|
146
|
-
cleanedCount++;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
console.warn(`Cleanup error for session ${sessionName}:`, error);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return cleanedCount;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Start monitoring a Claude process for status changes
|
|
157
|
-
*/
|
|
158
|
-
startProcessMonitoring(sessionName) {
|
|
159
|
-
// Clear existing monitoring if any
|
|
160
|
-
this.stopProcessMonitoring(sessionName);
|
|
161
|
-
const monitorInterval = setInterval(async () => {
|
|
162
|
-
try {
|
|
163
|
-
await this.checkProcessStatus(sessionName);
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
166
|
-
console.error(`Monitoring error for session ${sessionName}:`, error);
|
|
167
|
-
}
|
|
168
|
-
}, 2000); // Check every 2 seconds
|
|
169
|
-
this.monitoringIntervals.set(sessionName, monitorInterval);
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Stop monitoring a process
|
|
173
|
-
*/
|
|
174
|
-
stopProcessMonitoring(sessionName) {
|
|
175
|
-
const interval = this.monitoringIntervals.get(sessionName);
|
|
176
|
-
if (interval) {
|
|
177
|
-
clearInterval(interval);
|
|
178
|
-
this.monitoringIntervals.delete(sessionName);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Check process status by capturing tmux output
|
|
183
|
-
*/
|
|
184
|
-
async checkProcessStatus(sessionName) {
|
|
185
|
-
const process = this.processes.get(sessionName);
|
|
186
|
-
if (!process)
|
|
187
|
-
return;
|
|
188
|
-
try {
|
|
189
|
-
// Capture recent output from tmux session
|
|
190
|
-
const { stdout } = await execAsync(`tmux capture-pane -t "${sessionName}" -p -S -50`);
|
|
191
|
-
// Detect status from output
|
|
192
|
-
const newStatus = this.detectStatusFromOutput(stdout);
|
|
193
|
-
const previousStatus = process.status;
|
|
194
|
-
// Update process if status changed
|
|
195
|
-
if (newStatus !== previousStatus) {
|
|
196
|
-
process.status = newStatus;
|
|
197
|
-
process.lastActivity = new Date().toISOString();
|
|
198
|
-
// Detect error messages
|
|
199
|
-
if (newStatus === 'error') {
|
|
200
|
-
const errorMatch = stdout.match(/(?:Error|Failed|Exception):\s*(.+)/i);
|
|
201
|
-
if (errorMatch) {
|
|
202
|
-
process.errorMessage = errorMatch[1].trim();
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
this.processes.set(sessionName, process);
|
|
206
|
-
// Emit status change event
|
|
207
|
-
const statusUpdate = {
|
|
208
|
-
sessionName,
|
|
209
|
-
status: newStatus,
|
|
210
|
-
lastOutput: stdout.split('\n').slice(-3).join('\n').trim(),
|
|
211
|
-
timestamp: new Date().toISOString(),
|
|
212
|
-
errorMessage: process.errorMessage
|
|
213
|
-
};
|
|
214
|
-
this.emit('statusChange', statusUpdate);
|
|
215
|
-
// Stop monitoring if process completed or terminated
|
|
216
|
-
if (newStatus === 'completed' || newStatus === 'terminated') {
|
|
217
|
-
this.stopProcessMonitoring(sessionName);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
// Session might have been terminated
|
|
223
|
-
if (error instanceof Error && error.message.includes('no session found')) {
|
|
224
|
-
process.status = 'terminated';
|
|
225
|
-
this.processes.set(sessionName, process);
|
|
226
|
-
this.stopProcessMonitoring(sessionName);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Detect Claude process status from output patterns
|
|
232
|
-
*/
|
|
233
|
-
detectStatusFromOutput(output) {
|
|
234
|
-
const lowerOutput = output.toLowerCase();
|
|
235
|
-
// Error patterns
|
|
236
|
-
if (/(?:error|failed|exception|crashed)/i.test(output)) {
|
|
237
|
-
return 'error';
|
|
238
|
-
}
|
|
239
|
-
// Completion patterns
|
|
240
|
-
if (/(?:done|complete|finished|success)[\s\S]*$/i.test(output) ||
|
|
241
|
-
/✓|✅|🎉/i.test(output)) {
|
|
242
|
-
return 'completed';
|
|
243
|
-
}
|
|
244
|
-
// Waiting for input patterns
|
|
245
|
-
if (/(?:waiting|please|enter|input|continue|\?)[\s\S]*$/i.test(output)) {
|
|
246
|
-
return 'waiting_input';
|
|
247
|
-
}
|
|
248
|
-
// Running patterns (Claude is processing)
|
|
249
|
-
if (/(?:processing|running|executing|thinking|working)/i.test(output)) {
|
|
250
|
-
return 'running';
|
|
251
|
-
}
|
|
252
|
-
// If we see Claude's typical output, assume it's running
|
|
253
|
-
if (output.includes('Claude') || output.includes('claude') ||
|
|
254
|
-
/I'll|I'm|Let me/i.test(output)) {
|
|
255
|
-
return 'running';
|
|
256
|
-
}
|
|
257
|
-
// Default to running if we can't determine
|
|
258
|
-
return 'running';
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Verify tmux session exists
|
|
262
|
-
*/
|
|
263
|
-
async verifySessionExists(sessionName) {
|
|
264
|
-
const exists = await this.sessionExists(sessionName);
|
|
265
|
-
if (!exists) {
|
|
266
|
-
throw new Error(`tmux session '${sessionName}' does not exist`);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Check if tmux session exists
|
|
271
|
-
*/
|
|
272
|
-
async sessionExists(sessionName) {
|
|
273
|
-
try {
|
|
274
|
-
await execAsync(`tmux has-session -t "${sessionName}"`);
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Escape string for shell command using printf approach to avoid quote nesting
|
|
283
|
-
*/
|
|
284
|
-
escapeForShell(str) {
|
|
285
|
-
// Use printf approach to completely avoid quote escaping issues
|
|
286
|
-
// Replace newlines with \n and escape single quotes for printf
|
|
287
|
-
return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '\\r');
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Wait for Claude to be ready by monitoring output
|
|
291
|
-
*/
|
|
292
|
-
async waitForClaudeReady(sessionName) {
|
|
293
|
-
const maxWaitTime = 30000; // 30 seconds max
|
|
294
|
-
const checkInterval = 1000; // Check every 1 second
|
|
295
|
-
const startTime = Date.now();
|
|
296
|
-
while (Date.now() - startTime < maxWaitTime) {
|
|
297
|
-
try {
|
|
298
|
-
const { stdout } = await execAsync(`tmux capture-pane -t "${sessionName}" -p -S -50`);
|
|
299
|
-
// Check if Claude is ready for input (shows login, theme selection or ready prompt)
|
|
300
|
-
if (stdout.includes('Choose the text style') ||
|
|
301
|
-
stdout.includes('Select login method') ||
|
|
302
|
-
stdout.includes('How can I help you today?') ||
|
|
303
|
-
stdout.includes('I\'m Claude') ||
|
|
304
|
-
stdout.toLowerCase().includes('claude:')) {
|
|
305
|
-
// If it's showing login selection, auto-select option 1
|
|
306
|
-
if (stdout.includes('Select login method') && stdout.includes('Claude account with subscription')) {
|
|
307
|
-
await execAsync(`tmux send-keys -t "${sessionName}" "1" C-m`);
|
|
308
|
-
// Wait a bit more for login to complete
|
|
309
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
310
|
-
}
|
|
311
|
-
// If it's showing theme selection, auto-select dark mode
|
|
312
|
-
if (stdout.includes('Choose the text style') && stdout.includes('Dark mode ✔')) {
|
|
313
|
-
await execAsync(`tmux send-keys -t "${sessionName}" "1" C-m`);
|
|
314
|
-
// Wait a bit more for theme selection to complete
|
|
315
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
316
|
-
}
|
|
317
|
-
return; // Claude is ready
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
// Session might not exist yet, continue waiting
|
|
322
|
-
}
|
|
323
|
-
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
324
|
-
}
|
|
325
|
-
// If we get here, we timed out - just proceed anyway
|
|
326
|
-
console.warn(`Timed out waiting for Claude to be ready in session ${sessionName}`);
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Graceful shutdown - stop all monitoring
|
|
330
|
-
*/
|
|
331
|
-
async shutdown() {
|
|
332
|
-
// Stop all monitoring intervals
|
|
333
|
-
for (const interval of this.monitoringIntervals.values()) {
|
|
334
|
-
clearInterval(interval);
|
|
335
|
-
}
|
|
336
|
-
this.monitoringIntervals.clear();
|
|
337
|
-
// Emit shutdown event
|
|
338
|
-
this.emit('shutdown');
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
// Export singleton instance
|
|
342
|
-
export const claudeOrchestrator = new ClaudeOrchestrator();
|
|
343
|
-
//# sourceMappingURL=claudeOrchestrator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claudeOrchestrator.js","sourceRoot":"","sources":["../../src/services/claudeOrchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
// src/services/fileMonitor.ts
|
|
2
|
-
import * as chokidar from 'chokidar';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
import simpleGit from 'simple-git';
|
|
6
|
-
import { mcpLogger } from './mcpLogger.js';
|
|
7
|
-
const git = simpleGit();
|
|
8
|
-
class FileMonitor {
|
|
9
|
-
constructor(projectRoot = process.cwd()) {
|
|
10
|
-
this.watcher = null;
|
|
11
|
-
this.changeBuffer = [];
|
|
12
|
-
this.untracked = [];
|
|
13
|
-
this.projectRoot = projectRoot;
|
|
14
|
-
}
|
|
15
|
-
start() {
|
|
16
|
-
if (this.watcher) {
|
|
17
|
-
console.log('File monitor already running');
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
console.log('Starting file monitor...');
|
|
21
|
-
// Watch entire repo except node_modules, .git, and dist
|
|
22
|
-
this.watcher = chokidar.watch(this.projectRoot, {
|
|
23
|
-
ignored: [
|
|
24
|
-
'**/node_modules/**',
|
|
25
|
-
'**/.git/**',
|
|
26
|
-
'**/dist/**',
|
|
27
|
-
'**/.bob/specs/**', // Don't watch our own spec files
|
|
28
|
-
'**/build/**',
|
|
29
|
-
'**/coverage/**'
|
|
30
|
-
],
|
|
31
|
-
persistent: true,
|
|
32
|
-
ignoreInitial: true
|
|
33
|
-
});
|
|
34
|
-
this.watcher
|
|
35
|
-
.on('add', (filePath) => this.handleFileChange('added', filePath))
|
|
36
|
-
.on('change', (filePath) => this.handleFileChange('changed', filePath))
|
|
37
|
-
.on('unlink', (filePath) => this.handleFileChange('unlinked', filePath))
|
|
38
|
-
.on('error', (error) => console.error('File watcher error:', error));
|
|
39
|
-
console.log('File monitor started successfully');
|
|
40
|
-
}
|
|
41
|
-
stop() {
|
|
42
|
-
if (this.watcher) {
|
|
43
|
-
this.watcher.close();
|
|
44
|
-
this.watcher = null;
|
|
45
|
-
console.log('File monitor stopped');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
async handleFileChange(type, filePath) {
|
|
49
|
-
try {
|
|
50
|
-
const relativePath = path.relative(this.projectRoot, filePath);
|
|
51
|
-
const timestamp = new Date().toISOString();
|
|
52
|
-
// Get current branch and latest commit
|
|
53
|
-
const branch = await git.revparse(['--abbrev-ref', 'HEAD']);
|
|
54
|
-
let commit_hash = 'pending';
|
|
55
|
-
try {
|
|
56
|
-
const latestCommit = await git.log(['--max-count=1']);
|
|
57
|
-
if (latestCommit.latest) {
|
|
58
|
-
commit_hash = latestCommit.latest.hash.substring(0, 8);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
// Ignore commit errors for now
|
|
63
|
-
}
|
|
64
|
-
const changeEvent = {
|
|
65
|
-
type,
|
|
66
|
-
path: relativePath,
|
|
67
|
-
timestamp,
|
|
68
|
-
branch,
|
|
69
|
-
commit_hash
|
|
70
|
-
};
|
|
71
|
-
// Try to map to a manual
|
|
72
|
-
const spec_id = await this.mapFileToSpec(relativePath, branch);
|
|
73
|
-
if (spec_id) {
|
|
74
|
-
changeEvent.spec_id = spec_id;
|
|
75
|
-
await this.attachToSpecFeed(spec_id, changeEvent);
|
|
76
|
-
// Check for active operations for this manual and add file change as sub-event
|
|
77
|
-
const activeOps = mcpLogger.getActiveOperationsForSpec(spec_id);
|
|
78
|
-
for (const operationId of activeOps) {
|
|
79
|
-
await mcpLogger.addSubEvent(operationId, {
|
|
80
|
-
timestamp: changeEvent.timestamp,
|
|
81
|
-
event: `📄 File ${type}: ${path.basename(relativePath)}`,
|
|
82
|
-
details: {
|
|
83
|
-
file: changeEvent.path,
|
|
84
|
-
change_type: changeEvent.type,
|
|
85
|
-
branch: changeEvent.branch
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// Add to untracked bucket
|
|
92
|
-
this.addToUntracked(changeEvent);
|
|
93
|
-
}
|
|
94
|
-
this.changeBuffer.push(changeEvent);
|
|
95
|
-
// Keep buffer size manageable
|
|
96
|
-
if (this.changeBuffer.length > 1000) {
|
|
97
|
-
this.changeBuffer = this.changeBuffer.slice(-500);
|
|
98
|
-
}
|
|
99
|
-
console.log(`File ${type}: ${relativePath} ${spec_id ? `→ ${spec_id}` : '→ untracked'}`);
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
console.error('Error handling file change:', error);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async mapFileToSpec(filePath, branch) {
|
|
106
|
-
try {
|
|
107
|
-
// Strategy 1: Check if branch name contains manual ID
|
|
108
|
-
const specIdMatch = branch.match(/SPEC-\d{8}-[^\/]+/);
|
|
109
|
-
if (specIdMatch) {
|
|
110
|
-
return specIdMatch[0];
|
|
111
|
-
}
|
|
112
|
-
// Strategy 2: Look for manual files that reference this file
|
|
113
|
-
const specsDir = path.join(this.projectRoot, '.bob/specs');
|
|
114
|
-
if (await fs.pathExists(specsDir)) {
|
|
115
|
-
const specFiles = await fs.readdir(specsDir);
|
|
116
|
-
for (const specFile of specFiles) {
|
|
117
|
-
if (specFile.endsWith('.json')) {
|
|
118
|
-
try {
|
|
119
|
-
const specData = await fs.readJson(path.join(specsDir, specFile));
|
|
120
|
-
// Check execution logs for file references
|
|
121
|
-
const executionLogs = specData.execution_logs || specData.execution_log || [];
|
|
122
|
-
for (const log of executionLogs) {
|
|
123
|
-
if (log.files_changed && log.files_changed.includes(filePath)) {
|
|
124
|
-
return specData.spec_id;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Check implementation plan for file references
|
|
128
|
-
const implPlan = specData.implementation_plan || [];
|
|
129
|
-
for (const task of implPlan) {
|
|
130
|
-
if (task.description && task.description.includes(filePath)) {
|
|
131
|
-
return specData.spec_id;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
// Skip invalid spec files
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
console.error('Error mapping file to manual:', error);
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
async attachToSpecFeed(spec_id, changeEvent) {
|
|
150
|
-
try {
|
|
151
|
-
const specsDir = path.join(this.projectRoot, '.bob/specs');
|
|
152
|
-
const specFile = path.join(specsDir, `${spec_id}.json`);
|
|
153
|
-
if (await fs.pathExists(specFile)) {
|
|
154
|
-
const specData = await fs.readJson(specFile);
|
|
155
|
-
// Add to file_changes feed
|
|
156
|
-
if (!specData.file_changes) {
|
|
157
|
-
specData.file_changes = [];
|
|
158
|
-
}
|
|
159
|
-
specData.file_changes.push({
|
|
160
|
-
timestamp: changeEvent.timestamp,
|
|
161
|
-
type: changeEvent.type,
|
|
162
|
-
file: changeEvent.path,
|
|
163
|
-
branch: changeEvent.branch,
|
|
164
|
-
commit_hash: changeEvent.commit_hash
|
|
165
|
-
});
|
|
166
|
-
// Keep only last 100 file changes per manual
|
|
167
|
-
if (specData.file_changes.length > 100) {
|
|
168
|
-
specData.file_changes = specData.file_changes.slice(-100);
|
|
169
|
-
}
|
|
170
|
-
specData.updated_at = changeEvent.timestamp;
|
|
171
|
-
await fs.writeJson(specFile, specData, { spaces: 2 });
|
|
172
|
-
// Notify dashboard if it's running
|
|
173
|
-
try {
|
|
174
|
-
await this.notifyDashboard(spec_id, 'file_changed', {
|
|
175
|
-
file: changeEvent.path,
|
|
176
|
-
type: changeEvent.type,
|
|
177
|
-
timestamp: changeEvent.timestamp
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
catch (error) {
|
|
181
|
-
// Dashboard not running, ignore
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
catch (error) {
|
|
186
|
-
console.error('Error attaching to manual feed:', error);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
addToUntracked(changeEvent) {
|
|
190
|
-
const existing = this.untracked.find(u => u.branch === changeEvent.branch &&
|
|
191
|
-
Math.abs(new Date(u.timestamp).getTime() - new Date(changeEvent.timestamp).getTime()) < 60000 // within 1 minute
|
|
192
|
-
);
|
|
193
|
-
if (existing) {
|
|
194
|
-
existing.files.push(changeEvent.path);
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
this.untracked.push({
|
|
198
|
-
files: [changeEvent.path],
|
|
199
|
-
timestamp: changeEvent.timestamp,
|
|
200
|
-
branch: changeEvent.branch || 'unknown',
|
|
201
|
-
commit_hash: changeEvent.commit_hash
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
// Keep only last 50 untracked entries
|
|
205
|
-
if (this.untracked.length > 50) {
|
|
206
|
-
this.untracked = this.untracked.slice(-50);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
async notifyDashboard(spec_id, event, data) {
|
|
210
|
-
try {
|
|
211
|
-
const response = await fetch('http://localhost:4577/api/updates', {
|
|
212
|
-
method: 'POST',
|
|
213
|
-
headers: { 'Content-Type': 'application/json' },
|
|
214
|
-
body: JSON.stringify({
|
|
215
|
-
spec_id,
|
|
216
|
-
event,
|
|
217
|
-
data,
|
|
218
|
-
timestamp: new Date().toISOString()
|
|
219
|
-
})
|
|
220
|
-
});
|
|
221
|
-
return response.ok;
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
// Dashboard not running
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
getRecentChanges(limit = 50) {
|
|
229
|
-
return this.changeBuffer.slice(-limit);
|
|
230
|
-
}
|
|
231
|
-
getUntrackedChanges() {
|
|
232
|
-
return this.untracked;
|
|
233
|
-
}
|
|
234
|
-
async manuallyAssignToSpec(files, spec_id) {
|
|
235
|
-
for (const file of files) {
|
|
236
|
-
const changeEvent = {
|
|
237
|
-
type: 'changed',
|
|
238
|
-
path: file,
|
|
239
|
-
timestamp: new Date().toISOString(),
|
|
240
|
-
spec_id
|
|
241
|
-
};
|
|
242
|
-
await this.attachToSpecFeed(spec_id, changeEvent);
|
|
243
|
-
}
|
|
244
|
-
// Remove from untracked
|
|
245
|
-
this.untracked = this.untracked.filter(u => !u.files.some(f => files.includes(f)));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
// Singleton instance
|
|
249
|
-
export const fileMonitor = new FileMonitor();
|
|
250
|
-
//# sourceMappingURL=fileMonitor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fileMonitor.js","sourceRoot":"","sources":["../../src/services/fileMonitor.ts"],"names":[],"mappings":"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"}
|