UNPKG

paqad-ai

Version:

Spec-driven development framework — AI agents that think before they type

125 lines (114 loc) • 3.43 kB
#!/usr/bin/env node import process from 'node:process'; import { appendHooksLog, isPaqadDisabled, isProjectOnboarded, parseHookPayload, resolveProjectRoot, standDownReason, } from './lib/paqad-disabled.mjs'; import { stampAgentEntryMarker } from './lib/agent-entry-sentinel.mjs'; const LOG_PREFIX = 'stage-agent-start'; function logKey(value) { return typeof value === 'string' && value.trim() !== '' ? value .trim() .replace(/[^A-Za-z0-9_-]/g, '_') .slice(0, 128) : 'none'; } function errorMessage(error) { return (error instanceof Error ? error.message : String(error)) .replace(/\s+/g, ' ') .slice(0, 300); } async function importDist(relative) { return import(new URL(`../../dist/${relative}`, import.meta.url).href); } async function recordStart(projectRoot, payload) { try { const { recordStageAgentStart } = await importDist('stage-isolation/subagent-completion.js'); recordStageAgentStart({ projectRoot, payload }); } catch {} } async function seed(projectRoot, payload) { const agent = logKey(payload.agent_id); let stage = 'unknown'; try { const { recordRecipeInjected, seedStageAgentDetailed, stageHelperStage } = await importDist( 'stage-isolation/stage-brief.js', ); const resolved = stageHelperStage(payload.agent_type); if (!resolved) { appendHooksLog(projectRoot, `${LOG_PREFIX}: skipped agent=${agent} stage=none`); return; } stage = resolved; const seeded = seedStageAgentDetailed(stage, projectRoot, payload); process.stdout.write(seeded.output); stampAgentEntryMarker(projectRoot, payload.agent_id); await recordStart(projectRoot, payload); for (const note of seeded.notes) { appendHooksLog(projectRoot, `${LOG_PREFIX}: agent=${agent} stage=${stage}: ${note}`); } if (seeded.injected) { try { recordRecipeInjected(projectRoot, stage, payload, seeded.injected); } catch (error) { appendHooksLog( projectRoot, `${LOG_PREFIX}: recipe row not written agent=${agent}: ${errorMessage(error)}`, ); } } appendHooksLog(projectRoot, `${LOG_PREFIX}: seeded agent=${agent} stage=${stage}`); } catch (error) { appendHooksLog( projectRoot, `${LOG_PREFIX}: failed agent=${agent} stage=${stage}: ${errorMessage(error)}`, ); } } async function main(input) { const hookPayload = parseHookPayload(input); const projectRoot = resolveProjectRoot(process.env, hookPayload); try { if (isPaqadDisabled(projectRoot) || !isProjectOnboarded(projectRoot)) { return; } const reason = standDownReason(hookPayload); if (reason !== null) { appendHooksLog( projectRoot, `${LOG_PREFIX}: stood-down agent=${logKey(hookPayload?.agent_id)} reason=${reason}`, ); return; } let payload; try { payload = JSON.parse(input); } catch { return; } if (!payload || typeof payload !== 'object') { return; } await seed(projectRoot, payload); } catch (error) { appendHooksLog( projectRoot, `${LOG_PREFIX}: failed agent=none stage=none: ${errorMessage(error)}`, ); } } let input = ''; process.stdin.on('data', (chunk) => { input += chunk; }); process.stdin.on('end', () => { main(input).finally(() => { process.exitCode = 0; }); }); process.stdin.resume();