paqad-ai
Version:
Spec-driven development framework — AI agents that think before they type
93 lines (87 loc) • 2.77 kB
JavaScript
import process from 'node:process';
function quickFilter(input) {
try {
const payload = JSON.parse(input);
if (payload?.tool_name === 'Skill') return payload;
if (payload?.tool_name !== 'Read') return null;
const path = payload?.tool_input?.file_path;
return typeof path === 'string' && /(^|[\\/])SKILL\.md$/.test(path) ? payload : null;
} catch {
return null;
}
}
async function record(payload) {
const fs = await import('node:fs');
const { basename, dirname, join } = await import('node:path');
const core = await import('./lib/skill-activation-core.mjs');
const gate = await import('./lib/paqad-disabled.mjs');
const projectRoot = gate.resolveProjectRoot(process.env, payload);
if (gate.isPaqadDisabled(projectRoot) || !gate.isProjectOnboarded(projectRoot)) return;
const enabled = gate.readLayeredKey(
projectRoot,
'skill_orchestrator_enabled',
'PAQAD_SKILL_ORCHESTRATOR_ENABLED',
);
if (enabled !== undefined && ['false', '0', 'no', 'off'].includes(enabled.trim().toLowerCase()))
return;
const entry = core.activationFromPayload(payload);
const line = entry === null ? null : core.activationLine(entry);
if (line === null) return;
const file = join(projectRoot, core.ACTIVATIONS_REL);
const { seenInTail, withTailLock } = await import('./lib/ledger-tail-dedupe.mjs');
const wrote = withTailLock(file, (assertHeld) => {
if (
entry.request_id !== null &&
seenInTail(file, core.isSameActivation(entry), {
byValue: typeof payload.tool_use_id === 'string',
})
) {
return false;
}
assertHeld();
fs.appendFileSync(file, line, 'utf8');
return true;
});
if (!wrote) return;
const fd = fs.openSync(file, 'r');
let text;
try {
if (fs.fstatSync(fd).size <= core.PRUNE_THRESHOLD_BYTES) return;
text = fs.readFileSync(fd, 'utf8');
} finally {
fs.closeSync(fd);
}
const window = Number(
gate.readLayeredKey(
projectRoot,
'authoring_dark_window_days',
'PAQAD_AUTHORING_DARK_WINDOW_DAYS',
),
);
const pruned = core.pruneActivationText(
text,
new Date(),
Number.isInteger(window) && window > 0 ? window : core.DEFAULT_DARK_WINDOW_DAYS,
);
const tmp = join(dirname(file), `.${basename(file)}.${process.pid}.tmp`);
try {
fs.writeFileSync(tmp, pruned, 'utf8');
fs.renameSync(tmp, file);
} catch (error) {
fs.rmSync(tmp, { force: true });
throw error;
}
}
async function main() {
let input = '';
try {
for await (const chunk of process.stdin) input += chunk;
const payload = quickFilter(input);
if (payload !== null) await record(payload);
} catch {
process.exitCode = 0;
}
process.exitCode = 0;
}
await main();