Files
EJClaw/src/paired-turn-output-attachments.ts

80 lines
2.2 KiB
TypeScript

import fs from 'fs';
import path from 'path';
import { DATA_DIR } from './config.js';
import type { OutboundAttachment, PairedRoomRole } from './types.js';
function sanitizePathSegment(value: string, fallback: string): string {
const sanitized = value.replace(/[^a-zA-Z0-9._-]+/g, '-').slice(0, 96);
return sanitized.replace(/^[.-]+|[.-]+$/g, '') || fallback;
}
function storedAttachmentName(
attachment: OutboundAttachment,
sourcePath: string,
index: number,
): string {
const sourceBasename = path.basename(sourcePath);
const displayBasename = attachment.name
? path.basename(attachment.name)
: sourceBasename;
const ext = path.extname(displayBasename) || path.extname(sourceBasename);
const stem =
path.basename(displayBasename, path.extname(displayBasename)) ||
`attachment-${index + 1}`;
return `${String(index + 1).padStart(2, '0')}-${sanitizePathSegment(
stem,
`attachment-${index + 1}`,
)}${ext}`;
}
export function persistPairedTurnOutputAttachments(args: {
taskId: string;
turnNumber: number;
role: PairedRoomRole;
attachments: OutboundAttachment[];
}): OutboundAttachment[] {
if (args.attachments.length === 0) return [];
const safeTaskId = sanitizePathSegment(args.taskId, 'task');
const targetDir = path.join(
DATA_DIR,
'attachments',
'paired-turn-outputs',
safeTaskId,
String(args.turnNumber),
args.role,
);
return args.attachments.map((attachment, index) => {
try {
if (
!path.isAbsolute(attachment.path) ||
!fs.existsSync(attachment.path)
) {
return attachment;
}
const sourcePath = fs.realpathSync(attachment.path);
if (!fs.statSync(sourcePath).isFile()) return attachment;
fs.mkdirSync(targetDir, { recursive: true });
const targetPath = path.join(
targetDir,
storedAttachmentName(attachment, sourcePath, index),
);
if (sourcePath !== path.resolve(targetPath)) {
fs.copyFileSync(sourcePath, targetPath);
}
return {
...attachment,
path: targetPath,
name: attachment.name
? path.basename(attachment.name)
: path.basename(targetPath),
};
} catch {
return attachment;
}
});
}