mirror of
https://github.com/bendtherules/opencode-multi-model.git
synced 2026-08-18 13:42:21 +00:00
build: color-code open and close outputs
This commit is contained in:
+47
-32
@@ -1,6 +1,7 @@
|
||||
import * as readline from "node:readline";
|
||||
import chalk from 'chalk'; // removed console usage
|
||||
import type { CloseSessionOptions, CloseSessionResult } from "../types";
|
||||
import { runCommand, getSessionPath, getWorktreesForSession } from "./utils";
|
||||
import { runCommand, getSessionPath, getWorktreesForSession, sanitizeName } from "./utils";
|
||||
|
||||
/**
|
||||
* Prompts the user for input on the terminal.
|
||||
@@ -45,33 +46,42 @@ async function promptUser(question: string): Promise<string> {
|
||||
*/
|
||||
export async function closeMultiModel(options: CloseSessionOptions): Promise<CloseSessionResult> {
|
||||
const worktreesRemoved: string[] = [];
|
||||
const instructionsArr: string[] = [];
|
||||
const branchesDeleted: string[] = [];
|
||||
const tagsCreated: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
|
||||
const safeSessionName = sanitizeName(options.sessionName);
|
||||
try {
|
||||
// Check if session exists
|
||||
const { ok: sessionExists } = await runCommand(["tmux", "has-session", "-t", options.sessionName]);
|
||||
const { ok: sessionExists } = await runCommand(["tmux", "has-session", "-t", safeSessionName]);
|
||||
|
||||
// Kill tmux session if it exists
|
||||
if (sessionExists) {
|
||||
await runCommand(["tmux", "kill-session", "-t", options.sessionName]);
|
||||
await runCommand(["tmux", "kill-session", "-t", safeSessionName]);
|
||||
instructionsArr.push(chalk.green(`Closed session '${safeSessionName}'`));
|
||||
} else {
|
||||
instructionsArr.push(chalk.yellow(`Session '${safeSessionName}' does not exist`));
|
||||
}
|
||||
|
||||
// Get list of worktrees for this session before killing tmux
|
||||
const worktrees = await getWorktreesForSession(options.sessionName);
|
||||
const worktrees = await getWorktreesForSession(safeSessionName);
|
||||
|
||||
// If cleanup requested and not forced, ask for confirmation
|
||||
if (options.cleanupWorktrees && !options.force && worktrees.length > 0) {
|
||||
console.log(`\nThe following worktrees and branches will be removed:`);
|
||||
worktrees.forEach((wt) => console.log(` - ${wt.path} (branch: ${wt.branch})`));
|
||||
instructionsArr.push(chalk.red('The following worktrees and branches will be removed:'));
|
||||
worktrees.forEach((wt) => {
|
||||
const msg = ` - ${wt.path} (branch: ${wt.branch})`;
|
||||
instructionsArr.push(msg.trim());
|
||||
});
|
||||
|
||||
const answer = await promptUser("\nDo you want to proceed? (y/N): ");
|
||||
const answer = await promptUser(chalk.bold("\nDo you want to proceed? (y/N): "));
|
||||
if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
|
||||
return {
|
||||
success: false,
|
||||
sessionName: options.sessionName,
|
||||
sessionName: safeSessionName,
|
||||
error: "Cleanup cancelled by user",
|
||||
instructions: instructionsArr.join("\n"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -94,20 +104,19 @@ export async function closeMultiModel(options: CloseSessionOptions): Promise<Clo
|
||||
if (tagResult.ok) {
|
||||
tagsCreated.push(archiveTag);
|
||||
} else {
|
||||
const warningMsg = `Failed to create tag ${archiveTag} for branch ${worktree.branch}.`;
|
||||
warnings.push(warningMsg);
|
||||
console.warn(`Warning: ${warningMsg}`);
|
||||
const warningMsg = chalk.red(`Warning: Failed to create tag ${archiveTag} for branch ${worktree.branch}.`);
|
||||
instructionsArr.push(warningMsg);
|
||||
}
|
||||
|
||||
await runCommand(["git", "branch", "-D", worktree.branch]);
|
||||
branchesDeleted.push(worktree.branch);
|
||||
} catch (err) {
|
||||
console.warn(`Warning: Failed to cleanup worktree ${worktree.path}: ${err}`);
|
||||
instructionsArr.push(chalk.red(`Failed to cleanup worktree ${worktree.path}: ${err}`));
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove the base directory
|
||||
const worktreeBase = getSessionPath(options.sessionName);
|
||||
const worktreeBase = getSessionPath(safeSessionName);
|
||||
try {
|
||||
await runCommand(["rm", "-rf", worktreeBase]);
|
||||
} catch {
|
||||
@@ -115,26 +124,32 @@ export async function closeMultiModel(options: CloseSessionOptions): Promise<Clo
|
||||
}
|
||||
|
||||
cleanupPerformed = worktreesRemoved.length > 0;
|
||||
if (cleanupPerformed) {
|
||||
instructionsArr.push(chalk.dim(`Removed ${worktreesRemoved.length} worktrees, alongwith their branches.`));
|
||||
if (tagsCreated.length > 0) {
|
||||
instructionsArr.push(chalk.dim(`Created archive tags: ${tagsCreated.join(", ")}.`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
sessionName: options.sessionName,
|
||||
cleanupPerformed,
|
||||
worktreesRemoved,
|
||||
branchesDeleted,
|
||||
tagsCreated,
|
||||
warnings,
|
||||
};
|
||||
return {
|
||||
success: true,
|
||||
sessionName: safeSessionName,
|
||||
cleanupPerformed,
|
||||
worktreesRemoved,
|
||||
branchesDeleted,
|
||||
tagsCreated,
|
||||
instructions: instructionsArr.join("\n"),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
sessionName: options.sessionName,
|
||||
error: String(error),
|
||||
worktreesRemoved,
|
||||
branchesDeleted,
|
||||
tagsCreated,
|
||||
warnings,
|
||||
};
|
||||
return {
|
||||
success: false,
|
||||
sessionName: safeSessionName,
|
||||
error: String(error),
|
||||
worktreesRemoved,
|
||||
branchesDeleted,
|
||||
tagsCreated,
|
||||
instructions: instructionsArr.join("\n"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -154,7 +154,9 @@ export async function openMultiModel(options: MultiModelOptions): Promise<MultiM
|
||||
if (!sessionCreateResult.ok) {
|
||||
const undoErrors = await undoWorktree(worktreePath, branchName);
|
||||
let errorMsg = `Error: Failed to create tmux session '${sessionName}'.${sessionCreateResult.stderr ? ` ${sessionCreateResult.stderr}` : ""}`;
|
||||
if (undoErrors.length > 0) errorMsg += ` Cleanup errors: ${undoErrors.join(", ")}`;
|
||||
if (undoErrors.length > 0) {
|
||||
errorMsg += ` Cleanup errors: ${undoErrors.join(", ")}`;
|
||||
}
|
||||
return { success: false, sessionName, error: errorMsg };
|
||||
}
|
||||
} else {
|
||||
@@ -173,7 +175,9 @@ export async function openMultiModel(options: MultiModelOptions): Promise<MultiM
|
||||
if (!windowCreateResult.ok) {
|
||||
failedModels.push(`${plan.model} (${windowCreateResult.stderr || "failed to create window"})`);
|
||||
const undoErrors = await undoWorktree(worktreePath, branchName);
|
||||
if (undoErrors.length > 0) failedModels.push(`cleanup failed for ${plan.model}: ${undoErrors.join(", ")}`);
|
||||
if (undoErrors.length > 0) {
|
||||
failedModels.push(`cleanup failed for ${plan.model}: ${undoErrors.join(", ")}`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user