mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 15:03:57 +08:00
feat(cli-tools): add effort level configuration for Claude CLI
- Introduced effort level options (low, medium, high) in the CLI tool settings. - Updated the SettingsPage and CliToolCard components to handle effort level updates. - Enhanced CLI command options to accept effort level via --effort parameter. - Modified backend routes to support effort level updates in tool configurations. - Created a new CliViewerToolbar component for improved CLI viewer interactions. - Implemented logic to manage and display execution statuses and layouts in the CLI viewer.
This commit is contained in:
@@ -21,6 +21,7 @@ import { remoteNotificationService } from '../core/services/remote-notification-
|
||||
import {
|
||||
addPendingQuestion,
|
||||
getPendingQuestion,
|
||||
updatePendingQuestion,
|
||||
removePendingQuestion,
|
||||
getAllPendingQuestions,
|
||||
clearAllPendingQuestions,
|
||||
@@ -451,19 +452,30 @@ export async function execute(params: AskQuestionParams): Promise<ToolResult<Ask
|
||||
// Generate surface ID
|
||||
const surfaceId = params.surfaceId || `question-${question.id}-${Date.now()}`;
|
||||
|
||||
// Check if this question was restored from disk (e.g., after MCP restart)
|
||||
const existingPending = getPendingQuestion(question.id);
|
||||
|
||||
// Create promise for answer
|
||||
const resultPromise = new Promise<AskQuestionResult>((resolve, reject) => {
|
||||
// Store pending question
|
||||
// Store pending question with real resolve/reject
|
||||
const pendingQuestion: PendingQuestion = {
|
||||
id: question.id,
|
||||
surfaceId,
|
||||
question,
|
||||
timestamp: Date.now(),
|
||||
timestamp: existingPending?.timestamp || Date.now(),
|
||||
timeout: params.timeout || DEFAULT_TIMEOUT_MS,
|
||||
resolve,
|
||||
reject,
|
||||
};
|
||||
addPendingQuestion(pendingQuestion);
|
||||
|
||||
// If question exists (restored from disk), update it with real resolve/reject
|
||||
// This fixes the "no promise attached" issue when MCP restarts
|
||||
if (existingPending) {
|
||||
updatePendingQuestion(question.id, pendingQuestion);
|
||||
console.log(`[AskQuestion] Updated restored question "${question.id}" with real resolve/reject`);
|
||||
} else {
|
||||
addPendingQuestion(pendingQuestion);
|
||||
}
|
||||
|
||||
// Set timeout
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -62,6 +62,12 @@ export interface ClaudeCliTool {
|
||||
* Supports ~, absolute, relative, and Windows paths
|
||||
*/
|
||||
settingsFile?: string;
|
||||
/**
|
||||
* Default effort level for Claude CLI (builtin claude only)
|
||||
* Passed to Claude CLI via --effort parameter
|
||||
* Valid values: 'low', 'medium', 'high'
|
||||
*/
|
||||
effort?: string;
|
||||
}
|
||||
|
||||
export type CliToolName = 'gemini' | 'qwen' | 'codex' | 'claude' | 'opencode' | string;
|
||||
@@ -1030,6 +1036,7 @@ export function getToolConfig(projectDir: string, tool: string): {
|
||||
tags?: string[];
|
||||
envFile?: string;
|
||||
settingsFile?: string;
|
||||
effort?: string;
|
||||
} {
|
||||
const config = loadClaudeCliTools(projectDir);
|
||||
const toolConfig = config.tools[tool];
|
||||
@@ -1050,7 +1057,8 @@ export function getToolConfig(projectDir: string, tool: string): {
|
||||
secondaryModel: toolConfig.secondaryModel ?? '',
|
||||
tags: toolConfig.tags,
|
||||
envFile: toolConfig.envFile,
|
||||
settingsFile: toolConfig.settingsFile
|
||||
settingsFile: toolConfig.settingsFile,
|
||||
effort: toolConfig.effort
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1068,6 +1076,7 @@ export function updateToolConfig(
|
||||
tags: string[];
|
||||
envFile: string | null;
|
||||
settingsFile: string | null;
|
||||
effort: string | null;
|
||||
}>
|
||||
): ClaudeCliToolsConfig {
|
||||
const config = loadClaudeCliTools(projectDir);
|
||||
@@ -1104,6 +1113,14 @@ export function updateToolConfig(
|
||||
config.tools[tool].settingsFile = updates.settingsFile;
|
||||
}
|
||||
}
|
||||
// Handle effort: set to undefined if null/empty, otherwise set value
|
||||
if (updates.effort !== undefined) {
|
||||
if (updates.effort === null || updates.effort === '') {
|
||||
delete config.tools[tool].effort;
|
||||
} else {
|
||||
config.tools[tool].effort = updates.effort;
|
||||
}
|
||||
}
|
||||
saveClaudeCliTools(projectDir, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ export interface CliToolConfig {
|
||||
envFile?: string | null;
|
||||
type?: 'builtin' | 'cli-wrapper' | 'api-endpoint'; // Tool type for frontend routing
|
||||
settingsFile?: string | null; // Claude CLI settings file path
|
||||
effort?: string | null; // Effort level for Claude CLI (low, medium, high)
|
||||
}
|
||||
|
||||
export interface CliConfig {
|
||||
@@ -160,7 +161,8 @@ export function getFullConfigResponse(baseDir: string): {
|
||||
tags: tool.tags,
|
||||
envFile: tool.envFile,
|
||||
type: tool.type, // Preserve type field for frontend routing
|
||||
settingsFile: tool.settingsFile // Preserve settingsFile for Claude CLI
|
||||
settingsFile: tool.settingsFile, // Preserve settingsFile for Claude CLI
|
||||
effort: tool.effort // Preserve effort level for Claude CLI
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -429,6 +429,8 @@ const ParamsSchema = z.object({
|
||||
base: z.string().optional(), // Review changes against base branch
|
||||
commit: z.string().optional(), // Review changes from specific commit
|
||||
title: z.string().optional(), // Optional title for review summary
|
||||
// Claude-specific options
|
||||
effort: z.enum(['low', 'medium', 'high']).optional(), // Effort level for claude
|
||||
// Rules env vars (PROTO, TMPL) - will be passed to subprocess environment
|
||||
rulesEnv: z.object({
|
||||
PROTO: z.string().optional(),
|
||||
@@ -458,7 +460,7 @@ async function executeCliTool(
|
||||
throw new Error(`Invalid params: ${parsed.error.message}`);
|
||||
}
|
||||
|
||||
const { tool, prompt, mode, format, model, cd, includeDirs, resume, id: customId, noNative, category, parentExecutionId, outputFormat, uncommitted, base, commit, title, rulesEnv } = parsed.data;
|
||||
const { tool, prompt, mode, format, model, cd, includeDirs, resume, id: customId, noNative, category, parentExecutionId, outputFormat, uncommitted, base, commit, title, effort, rulesEnv } = parsed.data;
|
||||
|
||||
// Validate and determine working directory early (needed for conversation lookup)
|
||||
let workingDir: string;
|
||||
@@ -881,6 +883,7 @@ async function executeCliTool(
|
||||
|
||||
// Load and validate settings file for Claude tool (builtin only)
|
||||
let settingsFilePath: string | undefined;
|
||||
let effectiveEffort = effort;
|
||||
if (tool === 'claude') {
|
||||
const toolConfig = getToolConfig(workingDir, tool);
|
||||
if (toolConfig.settingsFile) {
|
||||
@@ -896,6 +899,11 @@ async function executeCliTool(
|
||||
errorLog('SETTINGS_FILE', `Failed to resolve Claude settings file`, { configured: toolConfig.settingsFile, error: (err as Error).message });
|
||||
}
|
||||
}
|
||||
// Use default effort from config if not explicitly provided, fallback to 'high'
|
||||
if (!effectiveEffort) {
|
||||
effectiveEffort = toolConfig.effort || 'high';
|
||||
debugLog('EFFORT', `Using effort level`, { effort: effectiveEffort, source: toolConfig.effort ? 'config' : 'default' });
|
||||
}
|
||||
}
|
||||
|
||||
// Build command
|
||||
@@ -908,7 +916,8 @@ async function executeCliTool(
|
||||
include: includeDirs,
|
||||
nativeResume: nativeResumeConfig,
|
||||
settingsFile: settingsFilePath,
|
||||
reviewOptions: mode === 'review' ? { uncommitted, base, commit, title } : undefined
|
||||
reviewOptions: mode === 'review' ? { uncommitted, base, commit, title } : undefined,
|
||||
effort: effectiveEffort
|
||||
});
|
||||
|
||||
// Use auto-detected format (from buildCommand) if available, otherwise use passed outputFormat
|
||||
|
||||
@@ -166,8 +166,10 @@ export function buildCommand(params: {
|
||||
commit?: string;
|
||||
title?: string;
|
||||
};
|
||||
/** Effort level for claude (low, medium, high) */
|
||||
effort?: string;
|
||||
}): { command: string; args: string[]; useStdin: boolean; outputFormat?: 'text' | 'json-lines' } {
|
||||
const { tool, prompt, mode = 'analysis', model, dir, include, nativeResume, settingsFile, reviewOptions } = params;
|
||||
const { tool, prompt, mode = 'analysis', model, dir, include, nativeResume, settingsFile, reviewOptions, effort } = params;
|
||||
|
||||
debugLog('BUILD_CMD', `Building command for tool: ${tool}`, {
|
||||
mode,
|
||||
@@ -331,6 +333,10 @@ export function buildCommand(params: {
|
||||
if (model) {
|
||||
args.push('--model', model);
|
||||
}
|
||||
// Effort level: claude --effort <low|medium|high>
|
||||
if (effort) {
|
||||
args.push('--effort', effort);
|
||||
}
|
||||
// Permission modes: write/auto → bypassPermissions, analysis → default
|
||||
if (mode === 'write' || mode === 'auto') {
|
||||
args.push('--permission-mode', 'bypassPermissions');
|
||||
|
||||
Reference in New Issue
Block a user