UNPKG

aios-core

Version:

Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework

100 lines (86 loc) 3.03 kB
#!/usr/bin/env node // SYN-14: Boot time captured before ANY require — measures hook cold start const _BOOT_TIME = process.hrtime.bigint(); 'use strict'; /** * SYNAPSE Hook Entry Point — UserPromptSubmit * * Thin wrapper that reads JSON from stdin, delegates to SynapseEngine, * and writes <synapse-rules> context to stdout. * * - Silent exit on missing .synapse/ directory * - Silent exit on any error (never blocks the user prompt) * - All errors logged to stderr with [synapse-hook] prefix * - 5s safety timeout as defense-in-depth * * @module synapse-engine-hook */ const path = require('path'); const { resolveHookRuntime, buildHookOutput } = require( path.join(__dirname, '..', '..', '.aios-core', 'core', 'synapse', 'runtime', 'hook-runtime.js'), ); /** Safety timeout (ms) — defense-in-depth; Claude Code also manages hook timeout. */ const HOOK_TIMEOUT_MS = 5000; /** * Read all data from stdin as a JSON object. * @returns {Promise<object>} Parsed JSON input */ function readStdin() { return new Promise((resolve, reject) => { let data = ''; process.stdin.setEncoding('utf8'); process.stdin.on('error', (e) => reject(e)); process.stdin.on('data', (chunk) => { data += chunk; }); process.stdin.on('end', () => { try { resolve(JSON.parse(data)); } catch (e) { reject(e); } }); }); } /** Main hook execution pipeline. */ async function main() { const input = await readStdin(); const runtime = resolveHookRuntime(input); if (!runtime) return; const result = await runtime.engine.process(input.prompt, runtime.session); // QW-1: Wire updateSession() — persist bracket transitions after each prompt if (runtime.sessionId && runtime.sessionsDir) { try { const { updateSession } = require( path.join(runtime.cwd, '.aios-core', 'core', 'synapse', 'session', 'session-manager.js'), ); updateSession(runtime.sessionId, runtime.sessionsDir, { context: { last_bracket: result.bracket || 'FRESH' }, }); } catch (_err) { // Fire-and-forget — never block the prompt } } const output = JSON.stringify(buildHookOutput(result.xml)); // Write and flush stdout (callback may not exist in mocked environments) const flushed = process.stdout.write(output); if (!flushed) { await new Promise((resolve) => process.stdout.once('drain', resolve)); } } /** * Safely exit the process — no-op inside Jest workers to prevent worker crashes. * @param {number} code - Exit code */ function safeExit(code) { if (process.env.JEST_WORKER_ID) return; process.exit(code); } /** Entry point runner — sets safety timeout and executes main(). */ function run() { const timer = setTimeout(() => safeExit(0), HOOK_TIMEOUT_MS); timer.unref(); main() .then(() => safeExit(0)) .catch((err) => { console.error(`[synapse-hook] ${err.message}`); safeExit(0); }); } if (require.main === module) run(); module.exports = { readStdin, main, run, HOOK_TIMEOUT_MS };