1 line
6.2 KiB
JSON
1 line
6.2 KiB
JSON
{"repo": "blackeagle686/phoenix-llm", "files": {"smart_git.py": {"9b6cb0ce4285ab8c23dcf9eff24d842efe9f5f1a": {"t": 1785604682.9059427, "n": 5726, "h": "0a947701d44c833b", "c": "import os\nimport time\nimport subprocess\nfrom datetime import datetime\nfrom openai import OpenAI\nfrom dotenv import load_dotenv\n\n# Configuration\nload_dotenv()\nAPI_KEY = os.getenv(\"OPENAI_API_KEY\", \"ak_2yp3Xw1Ny7ky2pF7er9x93ZO9jj6G\")\nBASE_URL = os.getenv(\"OPENAI_BASE_URL\", \"https://api.longcat.chat/openai\")\nMODEL = os.getenv(\"OPENAI_LLM_MODEL\", \"LongCat-Flash-Lite\")\nINTERVAL = 5 # Seconds\nMAX_DIFF_BYTES = int(os.getenv(\"SMART_GIT_MAX_DIFF_BYTES\", \"12000\"))\nMAX_DIFF_FILES = int(os.getenv(\"SMART_GIT_MAX_DIFF_FILES\", \"30\"))\nLLM_TIMEOUT = float(os.getenv(\"SMART_GIT_LLM_TIMEOUT\", \"12.0\"))\n\nclient = OpenAI(api_key=API_KEY, base_url=BASE_URL, timeout=LLM_TIMEOUT) if API_KEY else None\n\ndef run_command(command):\n \"\"\"Runs a shell command and returns stdout.\"\"\"\n try:\n result = subprocess.run(\n command,\n capture_output=True,\n text=True,\n check=True,\n encoding=\"utf-8\",\n errors=\"replace\",\n )\n return (result.stdout or \"\").strip()\n except Exception as e:\n stderr = getattr(e, \"stderr\", str(e))\n print(f\"Error running command {' '.join(command)}: {stderr}\")\n return \"\"\n\n\ndef run_command_ok(command):\n \"\"\"Runs a shell command and returns True on success.\"\"\"\n try:\n subprocess.run(\n command,\n capture_output=True,\n text=True,\n check=True,\n encoding=\"utf-8\",\n errors=\"replace\",\n )\n return True\n except Exception as e:\n stderr = getattr(e, \"stderr\", str(e))\n print(f\"Error: {e}\")\n print(f\"Error running command {' '.join(command)}: {stderr}\")\n return False\n\n\ndef get_current_branch():\n return run_command([\"git\", \"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n\ndef get_status_porcelain():\n return run_command([\"git\", \"status\", \"--porcelain=v1\"])\n\ndef has_changes(status_text):\n return bool(status_text.strip())\n\ndef stage_all():\n return run_command_ok([\"git\", \"add\", \".\"])\n\ndef build_fast_diff_payload():\n \"\"\"\n Build a compact, high-signal payload for faster commit generation:\n - name/status list (cheap, structured)\n - shortstat summary\n - patch with zero context and file cap\n \"\"\"\n names = run_command([\"git\", \"diff\", \"--cached\", \"--name-status\"])\n shortstat = run_command([\"git\", \"diff\", \"--cached\", \"--shortstat\"])\n patch = run_command(\n [\"git\", \"diff\", \"--cached\", \"--unified=0\", \"--\", \".\"]\n )\n\n if not names and not patch:\n return \"\"\n\n # Cap number of files considered for speed and token control\n lines = names.splitlines()[:MAX_DIFF_FILES] if names else []\n names = \"\\n\".join(lines)\n\n if len(patch) > MAX_DIFF_BYTES:\n patch = patch[:MAX_DIFF_BYTES] + \"\\n...[truncated for speed]\"\n\n return f\"Changed files:\\n{names}\\n\\nSummary:\\n{shortstat}\\n\\nPatch:\\n{patch}\"\n\nimport sys\n\ndef generate_commit_message(payload):\n if not payload:\n return None\n if client is None:\n return None\n\n try:\n response = client.chat.completions.create(\n model=MODEL,\n messages=[\n {\"role\": \"system\", \"content\": \"Write a 1-line git commit message (<50 chars). No quotes, no markdown, plain text only.\"},\n {\"role\": \"user\", \"content\": payload},\n ],\n max_tokens=30,\n temperature=0,\n stream=True,\n )\n \n full_message = \"\"\n for chunk in response:\n content = chunk.choices[0].delta.content\n if content:\n sys.stdout.write(content)\n sys.stdout.flush()\n full_message += content\n sys.stdout.write(\"\\n\")\n sys.stdout.flush()\n return full_message.strip()\n except Exception as e:\n print(f\"\\nLLM Error: {e}\")\n return None\n\ndef commit_with_message(message):\n return run_command_ok([\"git\", \"commit\", \"-m\", message])\n\ndef smart_sync():\n print(f\"[*] Checking for changes at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}...\")\n\n status = get_status_porcelain()\n if not has_changes(status):\n print(\"[ ] No changes detected.\")\n return\n\n print(\"[+] Changes detected. Staging files...\")\n if not stage_all():\n print(\"[!] Staging failed. Skipping this cycle.\")\n return\n\n payload = build_fast_diff_payload()\n print(\"[*] Generating commit message...\")\n message = generate_commit_message(payload)\n\n if not message:\n message = f\"Auto-commit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\"\n print(f\"[!] LLM failed or no message generated. Using fallback: {message}\")\n else:\n print(f\"[v] Generated message: {message.splitlines()[0]}\")\n\n print(\"[*] Committing...\")\n if not commit_with_message(message):\n print(\"[!] Commit failed (or nothing staged). Skipping push.\")\n return\n\n branch = get_current_branch()\n if branch:\n print(f\"[*] Pushing to origin {branch}...\")\n if run_command_ok([\"git\", \"push\", \"origin\", branch]):\n print(\"[v] Done.\")\n else:\n print(\"[!] Push failed.\")\n else:\n print(\"[!] Could not determine current branch. Skipping push.\")\n\ndef main():\n print(\"=== Smart Git Automator Started ===\")\n print(f\"Interval: {INTERVAL} seconds\")\n print(f\"Target: {os.getcwd()}\")\n \n # Check if this is a git repo\n if not os.path.exists(\".git\"):\n print(\"[!] Error: Not a Git repository. Please run in a git project root.\")\n return\n\n try:\n while True:\n smart_sync()\n time.sleep(INTERVAL)\n except KeyboardInterrupt:\n print(\"\\n[!] Stopped by user.\")\n\nif __name__ == \"__main__\":\n main()"}}}} |