UNPKG

@essentialai/cogent-bridge

Version:

Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.

73 lines • 3.75 kB
import { execFile } from "node:child_process"; import { promisify } from "node:util"; import { logger } from "../logger.js"; const execFileAsync = promisify(execFile); /** * Claude CLI flag preflight (mock-hidden-gap audit, 2026-05-27, gap 5 — cc-cli * counterpart of codex-preflight.ts). * * Why this exists: `execClaude` (cc-cli.ts) drives auto-relay by spawning * `claude --resume <id> --dangerously-skip-permissions --no-session-persistence * --strict-mcp-config -p <msg>`. The unit tests mock `child_process`, so they * only prove the args we *intend* — NOT that the installed `claude` accepts them. * Startup previously ran only `claude --version`, which does not validate flag * parsing. This preflight runs `claude --help` and warns loudly if the installed * CLI drops/renames a flag we depend on, instead of failing on the first * auto-relay. Mirrors codex-preflight.ts exactly. */ /** * The long-form flags `execClaude` emits. Keep in sync with `execClaude` in * cc-cli.ts. We assert long forms (`--print` documents the `-p` we pass; the * short form always co-documents with its long form in claude --help). */ export const EXPECTED_CLAUDE_FLAGS = [ { flag: "--resume", usedFor: "resume the target CC session" }, { flag: "--print", usedFor: "-p non-interactive single-shot reply" }, { flag: "--dangerously-skip-permissions", usedFor: "unattended auto-relay execution" }, { flag: "--no-session-persistence", usedFor: "don't pollute the resumed session transcript" }, { flag: "--strict-mcp-config", usedFor: "isolate MCP config of the resumed process" }, { flag: "--output-format", usedFor: "structured JSON reply envelope (Slice 3 capture)" }, ]; /** * Pure decision logic: given the text of `claude --help`, return which expected * flags are absent. Unit-testable with no spawning. */ export function analyzeClaudeHelp(helpText) { const checked = EXPECTED_CLAUDE_FLAGS.map((f) => f.flag); const missing = EXPECTED_CLAUDE_FLAGS.filter((f) => !helpText.includes(f.flag)).map((f) => f.flag); return { missing, checked }; } /** * Verify the claude binary exists and that `claude --help` documents the flags * auto-relay emits. Never throws — a preflight failure must not stop startup; we * only want visibility. Returns the analysis, or null if help could not be * obtained (binary missing / call failed). */ export async function preflightClaude(claudePath) { let helpText; try { const { stdout, stderr } = await execFileAsync(claudePath, ["--help"], { timeout: 10000, }); helpText = `${stdout}\n${stderr}`; } catch (err) { logger.warn(`Claude preflight: could not run '${claudePath} --help' (${err instanceof Error ? err.message : String(err)}). The claude CLI may be missing — auto-relay to CC peers will fail until ` + `it is installed. Set COGENT_CLAUDE_PATH if it lives in a non-standard location.`); return null; } const analysis = analyzeClaudeHelp(helpText); if (analysis.missing.length > 0) { const detail = EXPECTED_CLAUDE_FLAGS.filter((f) => analysis.missing.includes(f.flag)) .map((f) => `${f.flag} (${f.usedFor})`) .join(", "); logger.error(`Claude preflight: the installed 'claude' does NOT document these flags that ` + `auto-relay emits: ${detail}. Auto-relay to CC peers will likely fail. Update ` + `cc-cli.ts to match the installed CLI, or install a compatible claude version.`); } else { logger.info(`Claude preflight OK: 'claude --help' documents all ${analysis.checked.length} flags auto-relay emits.`); } return analysis; } //# sourceMappingURL=claude-preflight.js.map