Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
5.6 KiB
JSON
1 line
5.6 KiB
JSON
{"repo": "churman1113/ai-output-guard", "files": {"src/agentguard/proxy/router.py": {"ad2752efbd26e4d1b47409d539dbb4806bd56845": {"t": 1786067732.3211582, "n": 5266, "h": "d5dccb0276e0afb3", "c": "\"\"\"LLM API route identification and response extraction.\n\nDefines URL patterns for known LLM providers and the JSONPath-like\nextraction rules to pull generated text from API responses.\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Any\n\n\n@dataclass\nclass LLMAPIRoute:\n \"\"\"A known LLM API route pattern with response extraction rules.\"\"\"\n name: str\n url_pattern: str # substring match against the request URL\n content_path: list[str] # dot-path to extract content from response JSON\n request_content_path: list[str] | None = None # dot-path to extract prompt from request\n method: str = \"POST\"\n\n\n# Known LLM API providers and their response structures\nBUILTIN_ROUTES: list[LLMAPIRoute] = [\n # OpenAI Chat Completions\n LLMAPIRoute(\n name=\"openai-chat\",\n url_pattern=\"api.openai.com/v1/chat/completions\",\n content_path=[\"choices\", \"0\", \"message\", \"content\"],\n request_content_path=[\"messages\", \"-1\", \"content\"],\n ),\n # OpenAI Completions (legacy)\n LLMAPIRoute(\n name=\"openai-completion\",\n url_pattern=\"api.openai.com/v1/completions\",\n content_path=[\"choices\", \"0\", \"text\"],\n ),\n # Anthropic Messages\n LLMAPIRoute(\n name=\"anthropic-messages\",\n url_pattern=\"api.anthropic.com/v1/messages\",\n content_path=[\"content\", \"0\", \"text\"],\n request_content_path=[\"messages\", \"-1\", \"content\"],\n ),\n # Google Gemini\n LLMAPIRoute(\n name=\"gemini\",\n url_pattern=\"generativelanguage.googleapis.com/v1\",\n content_path=[\"candidates\", \"0\", \"content\", \"parts\", \"0\", \"text\"],\n ),\n # Alibaba Tongyi Qianwen (通义千问)\n LLMAPIRoute(\n name=\"tongyi\",\n url_pattern=\"dashscope.aliyuncs.com/api/v1/services/aigc/text-generation\",\n content_path=[\"output\", \"text\"],\n ),\n # DeepSeek\n LLMAPIRoute(\n name=\"deepseek-chat\",\n url_pattern=\"api.deepseek.com/v1/chat/completions\",\n content_path=[\"choices\", \"0\", \"message\", \"content\"],\n ),\n]\n\n# Default route when no pattern matches — used as fallback\nDEFAULT_ROUTE = LLMAPIRoute(\n name=\"unknown\",\n url_pattern=\"\",\n content_path=[\"choices\", \"0\", \"message\", \"content\"],\n)\n\n\ndef match_route(url: str) -> LLMAPIRoute | None:\n \"\"\"Match a URL against known LLM API routes.\n\n Args:\n url: The full request URL (e.g., 'https://api.openai.com/v1/chat/completions').\n\n Returns:\n The matching LLMAPIRoute, or None if no pattern matches.\n \"\"\"\n # Strip port from URL for pattern matching\n # e.g., \"https://api.openai.com:8443/v1/...\" -> \"https://api.openai.com/v1/...\"\n from urllib.parse import urlparse, urlunparse\n try:\n parsed = urlparse(url)\n clean_url = urlunparse(parsed._replace(netloc=parsed.hostname or parsed.netloc))\n except Exception:\n clean_url = url\n\n for route in BUILTIN_ROUTES:\n if route.url_pattern in clean_url:\n return route\n return None\n\n\ndef extract_content(\n body: dict[str, Any] | None,\n content_path: list[str],\n) -> str | None:\n \"\"\"Extract text content from a JSON response body using a dot-notated path.\n\n Handles numeric indices in the path (e.g., 'choices.0.message.content').\n\n Args:\n body: The parsed JSON response body.\n content_path: List of keys/indices to traverse (e.g., ['choices', '0', 'message', 'content']).\n\n Returns:\n Extracted text string, or None if path doesn't exist.\n \"\"\"\n if body is None:\n return None\n\n current: Any = body\n for key in content_path:\n if current is None:\n return None\n if isinstance(current, dict):\n current = current.get(key)\n elif isinstance(current, (list, tuple)):\n try:\n idx = int(key)\n current = current[idx] if 0 <= idx < len(current) else None\n except (ValueError, IndexError):\n return None\n else:\n return None\n\n return str(current) if current is not None else None\n\n\ndef set_content(\n body: dict[str, Any],\n content_path: list[str],\n new_value: str,\n) -> dict[str, Any]:\n \"\"\"Set text content in a JSON response body at a given dot-notated path.\n\n Creates intermediate dicts/lists if they don't exist.\n\n Args:\n body: The parsed JSON response body.\n content_path: Path to set (e.g., ['choices', '0', 'message', 'content']).\n new_value: The new text value.\n\n Returns:\n The modified body.\n \"\"\"\n current = body\n for i, key in enumerate(content_path[:-1]):\n if isinstance(current, dict):\n if key not in current:\n current[key] = {} if not content_path[i + 1].isdigit() else []\n current = current[key]\n elif isinstance(current, list):\n idx = int(key)\n while len(current) <= idx:\n current.append({})\n current = current[idx]\n\n last_key = content_path[-1]\n if isinstance(current, dict):\n current[last_key] = new_value\n elif isinstance(current, list):\n idx = int(last_key)\n while len(current) <= idx:\n current.append(None)\n current[idx] = new_value\n\n return body\n"}}}} |