UNPKG

aiwg

Version:

Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo

88 lines (82 loc) 3.14 kB
/** * Hermes hook translator — emits a Python plugin stub at * ~/.hermes/plugins/<id>.py that registers itself with Hermes' Python * plugin system and shells out to the AIWG hook command. * * Hermes' hook surface per the parity assessment is Python-plugin-based; * shelling out from Python is a common pattern, so the emitted plugin is * a thin wrapper that subprocess.run()s the canonical AIWG command. */ import { promises as fs } from 'node:fs'; import * as path from 'node:path'; import { homedir } from 'node:os'; import { substituteEnvVars } from './shim.js'; const HERMES_EVENT_MAP = { PreToolUse: 'pre_tool', PostToolUse: 'post_tool', UserPromptSubmit: 'pre_prompt', SessionStart: 'session_start', SessionEnd: 'session_end', Stop: 'session_end', }; function renderHermesPlugin(source) { const events = source.events .map((e) => HERMES_EVENT_MAP[e]) .filter((e) => Boolean(e)); const subCommand = substituteEnvVars(source.command, 'hermes'); const subArgs = (source.args || []).map((a) => substituteEnvVars(a, 'hermes')); return `# AIWG-managed hook plugin (ADR-3 / PUW-018) # Hook id: ${source.id} # Description: ${source.description} # Generated by AIWG; do not edit manually. from hermes.plugin import register_hook import os import subprocess EVENTS = ${JSON.stringify(events)} COMMAND = ${JSON.stringify(subCommand)} ARGS = ${JSON.stringify(subArgs)} AIWG_ID = ${JSON.stringify(source.id)} SAFETY_CRITICAL = ${source.safetyCritical ? 'True' : 'False'} def _run(payload=None): env = dict(os.environ) env.setdefault('AIWG_PROJECT_DIR', os.environ.get('HERMES_PROJECT_DIR', os.getcwd())) env['AIWG_HOOK_EVENT'] = payload.get('event', 'unknown') if payload else 'unknown' cmd = [COMMAND] + ARGS if not COMMAND.startswith('#!') else [COMMAND, *ARGS] return subprocess.run(cmd, env=env, check=False).returncode for _event in EVENTS: register_hook(_event, _run, aiwg_managed=True, aiwg_id=AIWG_ID, safety_critical=SAFETY_CRITICAL) `; } export async function translateForHermes(source, options) { const result = { provider: 'hermes', emittedPaths: [], warnings: [], skipped: false, }; if (source.degradeOn?.includes('hermes')) { result.skipped = true; result.skipReason = 'degrade-on declared hermes'; return result; } const events = source.events .map((e) => HERMES_EVENT_MAP[e]) .filter((e) => Boolean(e)); if (events.length === 0) { result.skipped = true; result.skipReason = 'no Hermes-mapped events'; return result; } const pluginDir = path.join(homedir(), '.hermes', 'plugins'); const pluginPath = path.join(pluginDir, `${source.id}.py`); if (options.dryRun) { result.emittedPaths.push(pluginPath + ' (dry-run)'); return result; } await fs.mkdir(pluginDir, { recursive: true }); await fs.writeFile(pluginPath, renderHermesPlugin(source), 'utf8'); result.emittedPaths.push(pluginPath); return result; } //# sourceMappingURL=hermes-translator.js.map