feat: 优化 CLI 历史记录输出格式,增加使用提示并规范化 sourceDir 处理

This commit is contained in:
catlog22
2025-12-26 12:18:52 +08:00
parent 0c0301d811
commit e79e33773f
5 changed files with 41 additions and 20 deletions

View File

@@ -86,11 +86,17 @@ Generate CPCC-compliant software design specification documents (软件设计说
## Directory Setup
```bash
timestamp=$(date +%Y%m%d-%H%M%S)
dir=".workflow/.scratchpad/copyright-$timestamp"
mkdir -p "$dir/sections" "$dir/iterations"
echo "$dir"
```javascript
// 跨平台目录创建
const timestamp = new Date().toISOString().replace(/[-:]/g, '').slice(0, 15);
const dir = `.workflow/.scratchpad/copyright-${timestamp}`;
// Windows
Bash(`if not exist "${dir}\\sections" mkdir "${dir}\\sections"`);
Bash(`if not exist "${dir}\\iterations" mkdir "${dir}\\iterations"`);
// Unix/macOS
// Bash(`mkdir -p "${dir}/sections" "${dir}/iterations"`);
```
## Output Structure

View File

@@ -116,11 +116,17 @@ Generate comprehensive project analysis reports through multi-phase iterative wo
## Directory Setup
```bash
timestamp=$(date +%Y%m%d-%H%M%S)
dir=".workflow/.scratchpad/analyze-$timestamp"
mkdir -p "$dir/sections" "$dir/iterations"
echo "$dir"
```javascript
// 跨平台目录创建
const timestamp = new Date().toISOString().replace(/[-:]/g, '').slice(0, 15);
const dir = `.workflow/.scratchpad/analyze-${timestamp}`;
// Windows
Bash(`if not exist "${dir}\\sections" mkdir "${dir}\\sections"`);
Bash(`if not exist "${dir}\\iterations" mkdir "${dir}\\iterations"`);
// Unix/macOS
// Bash(`mkdir -p "${dir}/sections" "${dir}/iterations"`);
```
## Output Structure

View File

@@ -788,7 +788,10 @@ async function historyAction(options: HistoryOptions): Promise<void> {
return;
}
console.log(chalk.gray(` Total executions: ${history.total}\n`));
// Compact table header
console.log(chalk.gray(` Total: ${history.total} | Showing: ${history.executions.length}\n`));
console.log(chalk.gray(' Status Tool Time Duration ID'));
console.log(chalk.gray(' ' + '─'.repeat(70)));
for (const exec of history.executions) {
const statusIcon = exec.status === 'success' ? chalk.green('●') :
@@ -798,13 +801,18 @@ async function historyAction(options: HistoryOptions): Promise<void> {
: `${exec.duration_ms}ms`;
const timeAgo = getTimeAgo(new Date(exec.updated_at || exec.timestamp));
const turnInfo = exec.turn_count && exec.turn_count > 1 ? chalk.cyan(` [${exec.turn_count} turns]`) : '';
const turnInfo = exec.turn_count && exec.turn_count > 1 ? chalk.cyan(`[${exec.turn_count}t]`) : ' ';
console.log(` ${statusIcon} ${chalk.bold.white(exec.tool.padEnd(8))} ${chalk.gray(timeAgo.padEnd(12))} ${chalk.gray(duration.padEnd(8))}${turnInfo}`);
console.log(chalk.gray(` ${exec.prompt_preview}`));
console.log(chalk.dim(` ID: ${exec.id}`));
console.log();
// Compact single-line format: status tool time duration [turns] id
const shortId = exec.id.length > 25 ? exec.id.substring(0, 22) + '...' : exec.id;
console.log(` ${statusIcon} ${chalk.bold.white(exec.tool.padEnd(8))} ${chalk.gray(timeAgo.padEnd(11))} ${chalk.gray(duration.padEnd(8))} ${turnInfo} ${chalk.dim(shortId)}`);
}
// Usage hint
console.log();
console.log(chalk.gray(' ' + '─'.repeat(70)));
console.log(chalk.dim(' View output: ccw cli output <id> --final'));
console.log();
}
/**

View File

@@ -145,8 +145,9 @@ function renderCliHistory() {
</span>`
: '';
// Escape sourceDir for use in onclick
const sourceDirEscaped = exec.sourceDir ? exec.sourceDir.replace(/'/g, "\\'") : '';
// Normalize and escape sourceDir for use in onclick
// Convert backslashes to forward slashes to prevent JS escape issues in onclick
const sourceDirEscaped = exec.sourceDir ? exec.sourceDir.replace(/\\/g, '/').replace(/'/g, "\\'") : '';
return `
<div class="cli-history-item ${hasNative ? 'has-native' : ''}">

View File

@@ -96,10 +96,10 @@ async function renderCliHistoryView() {
'<button class="btn-icon" onclick="event.stopPropagation(); copyExecutionId(\'' + exec.id + '\')" title="Copy ID">' +
'<i data-lucide="copy" class="w-4 h-4"></i>' +
'</button>' +
'<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail(\'' + exec.id + '\', \'' + (exec.sourceDir || '').replace(/'/g, "\\'") + '\')" title="View Details">' +
'<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail(\'' + exec.id + '\', \'' + normalizedSourceDir.replace(/'/g, "\\'") + '\')" title="View Details">' +
'<i data-lucide="eye" class="w-4 h-4"></i>' +
'</button>' +
'<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution(\'' + exec.id + '\', \'' + (exec.sourceDir || '').replace(/'/g, "\\'") + '\')" title="Delete">' +
'<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution(\'' + exec.id + '\', \'' + normalizedSourceDir.replace(/'/g, "\\'") + '\')" title="Delete">' +
'<i data-lucide="trash-2" class="w-4 h-4"></i>' +
'</button>' +
'</div>' +