mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 03:30:40 +00:00
feat(cli): add timestamped filenames for insight reports
- Generate date-stamped filenames (insight-YYYY-MM-DD.html) - Append timestamp for multiple runs same day (insight-YYYY-MM-DD-HHMMSS.html) - Create insight.html alias pointing to latest report - Use symlink when possible, fallback to copy for cross-platform compatibility Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
eea5daae74
commit
509260ddfc
1 changed files with 65 additions and 2 deletions
|
|
@ -14,7 +14,9 @@ import type {
|
|||
InsightProgressCallback,
|
||||
} from '../types/StaticInsightTypes.js';
|
||||
|
||||
import type { Config } from '@qwen-code/qwen-code-core';
|
||||
import { createDebugLogger, type Config } from '@qwen-code/qwen-code-core';
|
||||
|
||||
const logger = createDebugLogger('StaticInsightGenerator');
|
||||
|
||||
export class StaticInsightGenerator {
|
||||
private dataProcessor: DataProcessor;
|
||||
|
|
@ -32,6 +34,62 @@ export class StaticInsightGenerator {
|
|||
return outputDir;
|
||||
}
|
||||
|
||||
// Generate timestamped filename with collision detection
|
||||
private async generateOutputPath(outputDir: string): Promise<string> {
|
||||
const now = new Date();
|
||||
const date = now.toISOString().split('T')[0]; // YYYY-MM-DD
|
||||
const time = now.toTimeString().slice(0, 8).replace(/:/g, ''); // HHMMSS
|
||||
|
||||
let outputPath = path.join(outputDir, `insight-${date}.html`);
|
||||
|
||||
// Check if date-only file exists, if so, add timestamp
|
||||
try {
|
||||
await fs.access(outputPath);
|
||||
// File exists, use timestamped version
|
||||
outputPath = path.join(outputDir, `insight-${date}-${time}.html`);
|
||||
} catch {
|
||||
// File doesn't exist, use date-only name
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
// Create or update the "latest" alias (symlink preferred, copy as fallback)
|
||||
private async updateLatestAlias(
|
||||
outputDir: string,
|
||||
targetPath: string,
|
||||
): Promise<void> {
|
||||
const latestPath = path.join(outputDir, 'insight.html');
|
||||
const relativeTarget = path.relative(outputDir, targetPath);
|
||||
|
||||
// Remove existing file/symlink if it exists
|
||||
try {
|
||||
await fs.unlink(latestPath);
|
||||
} catch {
|
||||
// File doesn't exist, ignore
|
||||
}
|
||||
|
||||
// Try symlink first (preferred - lightweight, always points to latest)
|
||||
try {
|
||||
await fs.symlink(relativeTarget, latestPath);
|
||||
logger.debug('Created insight symlink:', relativeTarget);
|
||||
return;
|
||||
} catch (error) {
|
||||
logger.debug(
|
||||
'Failed to create insight symlink, falling back to copy:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback: copy file (works everywhere, uses more disk space)
|
||||
try {
|
||||
await fs.copyFile(targetPath, latestPath);
|
||||
logger.debug('Created insight copy:', targetPath);
|
||||
} catch (error) {
|
||||
logger.debug('Failed to create insight latest alias:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the static insight HTML file
|
||||
async generateStaticInsight(
|
||||
baseDir: string,
|
||||
|
|
@ -52,10 +110,15 @@ export class StaticInsightGenerator {
|
|||
// Render HTML
|
||||
const html = await this.templateRenderer.renderInsightHTML(insights);
|
||||
|
||||
const outputPath = path.join(outputDir, 'insight.html');
|
||||
// Generate timestamped output path
|
||||
const outputPath = await this.generateOutputPath(outputDir);
|
||||
|
||||
// Write the HTML file
|
||||
await fs.writeFile(outputPath, html, 'utf-8');
|
||||
|
||||
// Update latest alias (symlink preferred, copy as fallback)
|
||||
await this.updateLatestAlias(outputDir, outputPath);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue