various fixes

This commit is contained in:
Cody Seibert
2025-12-12 20:51:01 -05:00
parent 5544031164
commit ca4809ca06
13 changed files with 496 additions and 126 deletions

View File

@@ -500,6 +500,86 @@ export function createFsRoutes(_events: EventEmitter): Router {
}
});
// Save board background image to .automaker/board directory
router.post("/save-board-background", async (req: Request, res: Response) => {
try {
const { data, filename, mimeType, projectPath } = req.body as {
data: string;
filename: string;
mimeType: string;
projectPath: string;
};
if (!data || !filename || !projectPath) {
res.status(400).json({
success: false,
error: "data, filename, and projectPath are required",
});
return;
}
// Create .automaker/board directory if it doesn't exist
const boardDir = path.join(projectPath, ".automaker", "board");
await fs.mkdir(boardDir, { recursive: true });
// Decode base64 data (remove data URL prefix if present)
const base64Data = data.replace(/^data:image\/\w+;base64,/, "");
const buffer = Buffer.from(base64Data, "base64");
// Use a fixed filename for the board background (overwrite previous)
const ext = path.extname(filename) || ".png";
const uniqueFilename = `background${ext}`;
const filePath = path.join(boardDir, uniqueFilename);
// Write file
await fs.writeFile(filePath, buffer);
// Add project path to allowed paths if not already
addAllowedPath(projectPath);
// Return the relative path for storage
const relativePath = `.automaker/board/${uniqueFilename}`;
res.json({ success: true, path: relativePath });
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
res.status(500).json({ success: false, error: message });
}
});
// Delete board background image
router.post("/delete-board-background", async (req: Request, res: Response) => {
try {
const { projectPath } = req.body as { projectPath: string };
if (!projectPath) {
res.status(400).json({
success: false,
error: "projectPath is required",
});
return;
}
const boardDir = path.join(projectPath, ".automaker", "board");
try {
// Try to remove all files in the board directory
const files = await fs.readdir(boardDir);
for (const file of files) {
if (file.startsWith("background")) {
await fs.unlink(path.join(boardDir, file));
}
}
} catch {
// Directory may not exist, that's fine
}
res.json({ success: true });
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
res.status(500).json({ success: false, error: message });
}
});
// Browse directories for file picker
// SECURITY: Restricted to home directory, allowed paths, and drive roots on Windows
router.post("/browse", async (req: Request, res: Response) => {

View File

@@ -3,32 +3,22 @@
*/
import { Router, type Request, type Response } from "express";
import path from "path";
import type { AutoModeService } from "../services/auto-mode-service.js";
interface RunningAgent {
featureId: string;
projectPath: string;
projectName: string;
isAutoMode: boolean;
}
// In-memory tracking of running agents (shared with auto-mode service via reference)
const runningAgentsMap = new Map<string, RunningAgent>();
let autoLoopRunning = false;
export function createRunningAgentsRoutes(): Router {
export function createRunningAgentsRoutes(autoModeService: AutoModeService): Router {
const router = Router();
// Get all running agents
router.get("/", async (_req: Request, res: Response) => {
try {
const runningAgents = Array.from(runningAgentsMap.values());
const runningAgents = autoModeService.getRunningAgents();
const status = autoModeService.getStatus();
res.json({
success: true,
runningAgents,
totalCount: runningAgents.length,
autoLoopRunning,
autoLoopRunning: status.autoLoopRunning,
});
} catch (error) {
const message = error instanceof Error ? error.message : "Unknown error";
@@ -38,33 +28,3 @@ export function createRunningAgentsRoutes(): Router {
return router;
}
// Export functions to update running agents from other services
export function registerRunningAgent(
featureId: string,
projectPath: string,
isAutoMode: boolean
): void {
runningAgentsMap.set(featureId, {
featureId,
projectPath,
projectName: path.basename(projectPath),
isAutoMode,
});
}
export function unregisterRunningAgent(featureId: string): void {
runningAgentsMap.delete(featureId);
}
export function setAutoLoopRunning(running: boolean): void {
autoLoopRunning = running;
}
export function getRunningAgentsCount(): number {
return runningAgentsMap.size;
}
export function isAgentRunning(featureId: string): boolean {
return runningAgentsMap.has(featureId);
}

View File

@@ -563,6 +563,23 @@ Format your response as a structured markdown document.`;
};
}
/**
* Get detailed info about all running agents
*/
getRunningAgents(): Array<{
featureId: string;
projectPath: string;
projectName: string;
isAutoMode: boolean;
}> {
return Array.from(this.runningFeatures.values()).map((rf) => ({
featureId: rf.featureId,
projectPath: rf.projectPath,
projectName: path.basename(rf.projectPath),
isAutoMode: rf.isAutoMode,
}));
}
// Private helpers
private async setupWorktree(
@@ -639,6 +656,13 @@ Format your response as a structured markdown document.`;
const feature = JSON.parse(data);
feature.status = status;
feature.updatedAt = new Date().toISOString();
// Set justFinished flag when moving to waiting_approval (agent just completed)
if (status === "waiting_approval") {
feature.justFinished = true;
} else {
// Clear the flag when moving to other statuses
feature.justFinished = false;
}
await fs.writeFile(featurePath, JSON.stringify(feature, null, 2));
} catch {
// Feature file may not exist