feat(WP-0012): IHF Phase 11 — Advanced AI Federation
Some checks failed
Test / test (push) Has been cancelled

- Schema: AgentRegistration, ModelRoutingPolicy, AgentDelegation,
  CollectiveProposal, CollectiveProposalContribution, AiGovernancePolicy,
  AgentPerformanceRecord + ALTER TABLE agent_proposals
  (migration 1744156800; CHECK constraints on trust_level, status,
  consensus_status — GAAF compliant)

- Bridge: scripts/llm_bridge.py (llm-connect subprocess seam) +
  Application/Helper/AgentBridge.hs (callBridge, callAgent,
  checkGovernancePolicy, jsonArrayTexts)

- Routing: Application/Helper/ModelRouter.hs (resolveAgent,
  resolveAllAgents) + ModelRoutingPolicies CRUD

- Registry: AgentRegistrations CRUD (Index/Show/New/Edit/Performance),
  DeactivateAgentAction, ComputeAgentPerformanceAction

- Delegation: AgentDelegations controller + views, DelegateSubtaskAction
  with token budget enforcement at bridge call time

- Collective: CollectiveProposals controller + views,
  CreateCollectiveProposalAction (fan-out → synthesis → consensus detection)

- Governance: AiGovernancePolicies CRUD + ToggleAiGovernancePolicyAction;
  checkGovernancePolicy enforced at all 4 Phase 5 invocation points

- Phase 5 wiring: replaced callClaudeApi in Widgets, DecisionRecords,
  RequirementCandidates with resolveAgent + callAgent + token tracking

- llm-connect feature requests: ~/llm-connect/FEATURE_REQUESTS.md
  (FR-1 HTTP serve, FR-2 RoutingPolicy, FR-3 async, FR-4 BudgetTracker)

- GAAF scorecard: 3.61 (up from 3.56); Functional 3.4→3.6, Extensions 3.8→3.9

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-01 20:57:17 +00:00
parent 4e4e994659
commit 133dae3d23
32 changed files with 1959 additions and 102 deletions

67
scripts/llm_bridge.py Executable file
View File

@@ -0,0 +1,67 @@
#!/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()