#!/usr/bin/env python3 """ IHF llm-connect bridge — Phase 11 AI Federation (IHUB-WP-0012) Usage: echo '{"provider":"openrouter","model":"...","prompt":"..."}' | python3 scripts/llm_bridge.py Input JSON fields: provider — openrouter | gemini | openai | claude-code (default: openrouter) model — model name string (provider-specific) prompt — the user prompt systemPrompt — optional system prompt api_key — optional; falls back to llm-connect env-var resolution maxTokens — max completion tokens (default: 2000) temperature — sampling temperature (default: 0.7) Output JSON (stdout, exit 0 on success): content — generated text model — model name actually used tokensIn — prompt token count tokensOut — completion token count finishReason — stop reason string Error JSON (stdout, exit 1 on LLMError): error — error message errorType — exception class name """ import sys import json import os sys.path.insert(0, os.path.expanduser("~/llm-connect")) from llm_connect import create_adapter, RunConfig from llm_connect.exceptions import LLMError def main() -> None: req = json.load(sys.stdin) try: adapter = create_adapter( provider=req.get("provider", "openrouter"), model=req.get("model"), api_key=req.get("api_key"), system_prompt=req.get("systemPrompt"), ) config = RunConfig( model_name=req.get("model", ""), temperature=req.get("temperature", 0.7), max_tokens=req.get("maxTokens", 2000), ) resp = adapter.execute_prompt(req["prompt"], config) print(json.dumps({ "content": resp.content, "model": resp.model, "tokensIn": resp.usage.get("prompt_tokens", 0), "tokensOut": resp.usage.get("completion_tokens", 0), "finishReason": resp.finish_reason, })) except LLMError as e: json.dump({"error": str(e), "errorType": type(e).__name__}, sys.stdout) sys.exit(1) if __name__ == "__main__": main()