Improve IK-style artifact scanner pipeline

This commit is contained in:
AzuTear
2026-07-07 22:02:24 +02:00
parent 8ebbe91c39
commit f791d1464c
70 changed files with 7408 additions and 445 deletions
@@ -3,6 +3,9 @@ import path from "node:path";
import type { ReviewSampleListResult, ReviewSamplesRepositoryPort, ReviewSamplePayload } from "./contracts.js";
import type { ReviewSampleRecord, SaveResultWithPath } from "../../src/types/global.js";
const SMALL_FILE_LIMIT_BYTES = 8 * 1024 * 1024;
const TAIL_READ_LIMIT_BYTES = 32 * 1024 * 1024;
export class ReviewSamplesRepository implements ReviewSamplesRepositoryPort {
private readonly filePath: string;
@@ -12,9 +15,12 @@ export class ReviewSamplesRepository implements ReviewSamplesRepositoryPort {
async list(limit = 50): Promise<ReviewSampleListResult> {
try {
const raw = await fs.readFile(this.filePath, "utf8");
const lines = raw.split(/\r?\n/).filter(Boolean);
const safeLimit = Math.max(1, Math.min(200, Number(limit) || 50));
const stats = await fs.stat(this.filePath);
const raw = stats.size <= SMALL_FILE_LIMIT_BYTES
? await fs.readFile(this.filePath, "utf8")
: await readTailText(this.filePath, stats.size, TAIL_READ_LIMIT_BYTES);
const lines = raw.split(/\r?\n/).filter(Boolean);
const samples = lines
.slice(-safeLimit)
.map((line) => {
@@ -25,7 +31,8 @@ export class ReviewSamplesRepository implements ReviewSamplesRepositoryPort {
}
})
.filter(Boolean) as ReviewSampleRecord[];
return { ok: true, samples: samples.reverse(), total: lines.length, path: this.filePath };
const total = stats.size <= SMALL_FILE_LIMIT_BYTES ? lines.length : Math.max(samples.length, lines.length);
return { ok: true, samples: samples.reverse(), total, path: this.filePath };
} catch {
return { ok: true, samples: [], total: 0, path: this.filePath };
}
@@ -37,3 +44,17 @@ export class ReviewSamplesRepository implements ReviewSamplesRepositoryPort {
return { ok: true, path: this.filePath };
}
}
async function readTailText(filePath: string, fileSize: number, maxBytes: number) {
const bytesToRead = Math.min(fileSize, maxBytes);
const handle = await fs.open(filePath, "r");
try {
const buffer = Buffer.alloc(bytesToRead);
await handle.read(buffer, 0, bytesToRead, fileSize - bytesToRead);
const text = buffer.toString("utf8");
const firstNewline = text.indexOf("\n");
return fileSize > bytesToRead && firstNewline >= 0 ? text.slice(firstNewline + 1) : text;
} finally {
await handle.close();
}
}