feat: add --yes flag for auto-confirmation across multiple workflows

- Enhanced lite-execute, lite-fix, lite-lite-lite, lite-plan, multi-cli-plan, plan, replan, session complete, session solidify, and various UI design commands to support a --yes or -y flag for skipping user confirmations and auto-selecting defaults.
- Updated argument hints and examples to reflect new auto mode functionality.
- Implemented auto mode defaults for confirmation, execution methods, and code review options.
- Improved error handling and validation in command parsing and execution processes.
This commit is contained in:
catlog22
2026-01-24 09:23:24 +08:00
parent fd50adf581
commit a293a01d85
36 changed files with 693 additions and 250 deletions

View File

@@ -45,6 +45,7 @@ allowed-tools: Task, AskUserQuestion, Read, Write, Bash, Glob, Grep
5. **执行透明性**: 展示执行进度、结果和可能的错误
6. **会话持久化**: 保存编排会话,支持中途暂停和恢复
7. **智能提示词生成**: 根据任务上下文和前序产物自动生成 ccw cli 提示词
8. **自动确认**: 所有命令自动添加 `-y` 参数,跳过交互式确认,实现无人值守执行
## Intelligent Prompt Generation

View File

@@ -66,8 +66,8 @@ for (let i = current_command_index; i < command_chain.length; i++) {
const prompt = generatePrompt(cmd, state, commandMeta);
try {
// 使用 ccw cli 执行
const result = Bash(`ccw cli -p "${prompt.replace(/"/g, '\\"')}" ${cmd.command}`, {
// 使用 ccw cli 执行(添加 -y 参数跳过确认)
const result = Bash(`ccw cli -p "${prompt.replace(/"/g, '\\"')}" ${cmd.command} -y`, {
run_in_background: true
});

View File

@@ -254,8 +254,30 @@ function main() {
chain = args[1].split(',').map(s => s.trim());
} else if (args[0] === '--file') {
const filePath = args[1];
const fileContent = JSON.parse(fs.readFileSync(filePath, 'utf8'));
chain = fileContent.chain || fileContent.steps.map(s => s.command);
// SEC-001: 路径遍历验证 - 只允许访问工作目录下的文件
const resolvedPath = path.resolve(filePath);
const workDir = path.resolve('.');
if (!resolvedPath.startsWith(workDir)) {
console.error('Error: File path must be within current working directory');
process.exit(1);
}
// CORR-001: JSON 解析错误处理
let fileContent;
try {
fileContent = JSON.parse(fs.readFileSync(resolvedPath, 'utf8'));
} catch (error) {
console.error(`Error: Failed to parse JSON file ${filePath}: ${error.message}`);
process.exit(1);
}
// CORR-002: 嵌套属性 null 检查
chain = fileContent.chain || fileContent.steps?.map(s => s.command) || [];
if (chain.length === 0) {
console.error('Error: No valid chain found in file (expected "chain" array or "steps" with "command" fields)');
process.exit(1);
}
} else {
chain = args;
}

View File

@@ -48,7 +48,19 @@ class CommandRegistry {
}
/**
* 解析 YAML 头
* 解析 YAML 头 (简化版本)
*
* 限制:
* - 只支持简单的 key: value 对 (单行值)
* - 不支持多行值、嵌套对象、复杂列表
* - allowed-tools 字段支持逗号分隔的字符串,自动转为数组
*
* 示例:
* ---
* name: lite-plan
* description: "Lightweight planning workflow"
* allowed-tools: Read, Write, Bash
* ---
*/
parseYamlHeader(content) {
// 处理 Windows 行结尾 (\r\n)
@@ -58,23 +70,36 @@ class CommandRegistry {
const yamlContent = match[1];
const result = {};
const lines = yamlContent.split(/[\r\n]+/);
for (const line of lines) {
if (!line.trim()) continue;
try {
const lines = yamlContent.split(/[\r\n]+/);
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue; // 跳过空行和注释
const colonIndex = line.indexOf(':');
if (colonIndex === -1) continue;
const colonIndex = trimmed.indexOf(':');
if (colonIndex === -1) continue;
const key = line.substring(0, colonIndex).trim();
const value = line.substring(colonIndex + 1).trim();
const key = trimmed.substring(0, colonIndex).trim();
const value = trimmed.substring(colonIndex + 1).trim();
let cleanValue = value.replace(/^["']|["']$/g, '');
if (!key) continue; // 跳过无效行
if (key === 'allowed-tools') {
cleanValue = cleanValue.split(',').map(t => t.trim());
// 去除引号 (单引号或双引号)
let cleanValue = value.replace(/^["']|["']$/g, '');
// allowed-tools 字段特殊处理:转为数组
// 支持格式: "Read, Write, Bash" 或 "Read,Write,Bash"
if (key === 'allowed-tools') {
cleanValue = Array.isArray(cleanValue)
? cleanValue
: cleanValue.split(',').map(t => t.trim()).filter(t => t);
}
result[key] = cleanValue;
}
result[key] = cleanValue;
} catch (error) {
console.error('YAML parsing error:', error.message);
return null;
}
return result;