pomljs
Version:
Prompt Orchestration Markup Language
137 lines (133 loc) • 4.24 kB
JavaScript
var fs = require('./fs.cjs');
var path = require('path');
function replaceBuffers(value) {
if (Buffer.isBuffer(value)) {
const wrapper = { __base64__: value.toString('base64') };
return wrapper;
}
else if (Array.isArray(value)) {
return value.map(replaceBuffers);
}
else if (value && typeof value === 'object') {
const result = {};
for (const k of Object.keys(value)) {
result[k] = replaceBuffers(value[k]);
}
return result;
}
return value;
}
function parseJsonWithBuffers(text) {
return JSON.parse(text, (_key, value) => {
if (value && typeof value === 'object' && value.__base64__) {
return Buffer.from(value.__base64__, 'base64');
}
return value;
});
}
let traceEnabled = false;
let traceDir;
function setTrace(enabled = true, dir) {
traceEnabled = enabled;
if (!enabled) {
traceDir = undefined;
return undefined;
}
const envDir = process.env.POML_TRACE;
if (dir) {
const base = path.resolve(dir);
fs.mkdirSync(base, { recursive: true });
traceDir = base;
}
else if (envDir) {
fs.mkdirSync(envDir, { recursive: true });
traceDir = envDir;
}
else {
traceDir = undefined;
}
return traceDir;
}
function clearTrace() {
traceEnabled = false;
traceDir = undefined;
}
function isTracing() {
return traceEnabled && !!traceDir;
}
function nextIndex(sourcePath) {
if (!traceDir) {
return [0, '', -1];
}
const fileName = sourcePath ? path.basename(sourcePath, '.poml') : '';
for (let i = 1;; i++) {
const idxStr = i.toString().padStart(4, '0');
// 1) If ANY file in traceDir starts with this index, skip it.
// This makes the sequence independent of fileName.
const entries = fs.readdirSync(traceDir);
const indexTaken = entries.some((entry) => entry.startsWith(idxStr));
if (indexTaken) {
continue;
}
// 2) Build our own target using the (possibly present) fileName.
const prefix = path.join(traceDir, idxStr) + (fileName ? `.${fileName}` : '');
const filePath = `${prefix}.poml`;
try {
// 3) Atomically create our file. If it races and now exists, loop again.
const fd = fs.openSync(filePath, 'wx');
return [i, prefix, fd];
}
catch (err) {
if (err.code === 'EEXIST') {
// Someone created a file with this index between steps (1) and (3); try next i.
continue;
}
throw err;
}
}
}
function dumpTrace(markup, context, stylesheet, result, sourcePath, prettyResult) {
if (!isTracing()) {
return;
}
const [_idx, prefix, fd] = nextIndex(sourcePath);
try {
fs.writeSync(fd, markup);
}
finally {
fs.closeSync(fd);
}
if (sourcePath) {
const envFile = `${prefix}.env`;
fs.writeFileSync(envFile, `SOURCE_PATH=${sourcePath}\n`);
const linkPath = `${prefix}.source.poml`;
try {
fs.symlinkSync(sourcePath, linkPath);
}
catch {
console.warn(`Failed to create symlink for source path: ${sourcePath}`);
}
}
if (context && Object.keys(context).length > 0) {
fs.writeFileSync(`${prefix}.context.json`, JSON.stringify(replaceBuffers(context), null, 2));
}
if (stylesheet && Object.keys(stylesheet).length > 0) {
fs.writeFileSync(`${prefix}.stylesheet.json`, JSON.stringify(replaceBuffers(stylesheet), null, 2));
}
if (result !== undefined) {
fs.writeFileSync(`${prefix}.result.json`, JSON.stringify(replaceBuffers(result), null, 2));
if (prettyResult !== undefined) {
fs.writeFileSync(`${prefix}.result.txt`, prettyResult);
}
}
}
if (process.env.POML_TRACE) {
setTrace(true, process.env.POML_TRACE);
}
exports.clearTrace = clearTrace;
exports.dumpTrace = dumpTrace;
exports.isTracing = isTracing;
exports.parseJsonWithBuffers = parseJsonWithBuffers;
exports.setTrace = setTrace;
//# sourceMappingURL=trace.cjs.map
;