Capture kat-coder + qwen3-coder-30b outputs (5 prompts each, API-run, NOT graded yet)
Via tools/grade_run.py against LM Studio (load -> all prompts -> unload -> verify).
kat-coder: lfu/tts/webhook/automation/rust (lfu has a real SyntaxError: 'self._ bump_freq')
qwen3-coder-30b: lfu/tts/webhook/automation/rust (all 4 py parse clean; terse ~2k tok outputs)
Grading deferred to a later session (capture-only mode).
Script hardening:
- --resident / --unload-all commands (read loaded_instances, POST unload, verify)
- MEMORY GUARD: aborts if a different model is resident (never stack 30GB models)
- TTFT self-discovery dump (LM Studio returns empty stats non-streaming;
fix next session: switch to /api/v1/chat stream:true -> chat.end result.stats)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
import asyncio
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from collections import defaultdict, deque
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from urllib.parse import urlparse
|
||||
import threading
|
||||
|
||||
# Configuration
|
||||
SHARED_SECRET = b"my_secret_key"
|
||||
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/1234567890/test"
|
||||
MAX_DISCORD_RATE = 5 # events per second
|
||||
RATE_LIMIT_WINDOW = 1.0 # seconds
|
||||
|
||||
# In-memory stores
|
||||
idempotency_store = {} # event_id -> timestamp
|
||||
discord_forward_count = 0
|
||||
discord_forward_times = deque(maxlen=MAX_DISCORD_RATE) # timestamps of forwards
|
||||
|
||||
# Token bucket for rate limiting
|
||||
bucket_tokens = MAX_DISCORD_RATE
|
||||
last_refill = time.time()
|
||||
bucket_lock = threading.Lock()
|
||||
|
||||
def verify_signature(body, signature):
|
||||
"""Verify HMAC signature of the request body."""
|
||||
expected = hmac.new(SHARED_SECRET, body, hashlib.sha256).hexdigest()
|
||||
return hmac.compare_digest(signature, expected)
|
||||
|
||||
def is_idempotent(event_id):
|
||||
"""Check if event has been seen recently."""
|
||||
now = time.time()
|
||||
if event_id in idempotency_store:
|
||||
if now - idempotency_store[event_id] < 300: # 5 minutes
|
||||
return True
|
||||
idempotency_store[event_id] = now
|
||||
return False
|
||||
|
||||
def rate_limit():
|
||||
"""Check if we can make a Discord forward."""
|
||||
global bucket_tokens, last_refill
|
||||
with bucket_lock:
|
||||
now = time.time()
|
||||
# Refill tokens based on time passed
|
||||
elapsed = now - last_refill
|
||||
if elapsed > RATE_LIMIT_WINDOW:
|
||||
bucket_tokens = min(MAX_DISCORD_RATE, bucket_tokens + elapsed / RATE_LIMIT_WINDOW * MAX_DISCORD_RATE)
|
||||
last_refill = now
|
||||
if bucket_tokens >= 1:
|
||||
bucket_tokens -= 1
|
||||
return True
|
||||
return False
|
||||
|
||||
async def discord_send(payload):
|
||||
"""Simulate sending to Discord webhook."""
|
||||
# Simulate occasional 429
|
||||
import random
|
||||
if random.random() < 0.05: # 5% chance of 429
|
||||
retry_after = random.randint(1, 3)
|
||||
raise Exception(f"HTTP 429: Retry-After {retry_after}")
|
||||
# Simulate success
|
||||
return True
|
||||
|
||||
class WebhookHandler(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
if self.path != "/webhook":
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
# Read body
|
||||
content_length = int(self.headers.get('Content-Length', 0))
|
||||
if not content_length:
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
body = self.rfile.read(content_length)
|
||||
signature = self.headers.get('X-Signature')
|
||||
if not signature:
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
# Verify signature
|
||||
if not verify_signature(body, signature):
|
||||
self.send_response(401)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
try:
|
||||
data = json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
event_id = data.get("event_id")
|
||||
if not event_id:
|
||||
self.send_response(400)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
# Check idempotency
|
||||
if is_idempotent(event_id):
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
# Forward to Discord
|
||||
asyncio.run(self.forward_to_discord(data))
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
|
||||
async def forward_to_discord(self, data):
|
||||
"""Forward event to Discord with rate limiting and retries."""
|
||||
# Rate limit check
|
||||
while not rate_limit():
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
# Prepare payload for Discord
|
||||
summary = {
|
||||
"content": f"Event {data['type']}: {data.get('data', {}).get('message', 'No message')}"
|
||||
}
|
||||
|
||||
retry_after = 0
|
||||
while True:
|
||||
try:
|
||||
await discord_send(summary)
|
||||
break
|
||||
except Exception as e:
|
||||
if "HTTP 429" in str(e):
|
||||
# Extract retry-after
|
||||
import re
|
||||
match = re.search(r"Retry-After (\d+)", str(e))
|
||||
if match:
|
||||
retry_after = int(match.group(1))
|
||||
else:
|
||||
retry_after = 1
|
||||
await asyncio.sleep(retry_after)
|
||||
else:
|
||||
# Log error but don't fail silently
|
||||
print(f"Discord send failed: {e}")
|
||||
break
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run tests
|
||||
import unittest
|
||||
import threading
|
||||
import time
|
||||
|
||||
class TestWebhookBridge(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.handler = WebhookHandler.__new__(WebhookHandler)
|
||||
self.handler.path = "/webhook"
|
||||
self.handler.headers = {}
|
||||
self.handler.rfile = None
|
||||
self.handler.wfile = None
|
||||
|
||||
def test_signature_verification(self):
|
||||
body = b'{"event_id": "123", "type": "chat", "data": {}}'
|
||||
signature = hmac.new(SHARED_SECRET, body, hashlib.sha256).hexdigest()
|
||||
self.assertTrue(verify_signature(body, signature))
|
||||
# Tampered signature
|
||||
self.assertFalse(verify_signature(body, "wrong_signature"))
|
||||
|
||||
def test_idempotency(self):
|
||||
event_id = "test_event"
|
||||
# First time - should not be idempotent
|
||||
self.assertFalse(is_idempotent(event_id))
|
||||
# Second time - should be idempotent
|
||||
self.assertTrue(is_idempotent(event_id))
|
||||
|
||||
def test_rate_limiting(self):
|
||||
# Fill bucket
|
||||
for _ in range(MAX_DISCORD_RATE):
|
||||
self.assertTrue(rate_limit())
|
||||
# Next should fail
|
||||
self.assertFalse(rate_limit())
|
||||
|
||||
# Run tests
|
||||
unittest.main(argv=[''], exit=False, verbosity=2)
|
||||
|
||||
# Start HTTP server
|
||||
server = HTTPServer(('localhost', 8080), WebhookHandler)
|
||||
print("Starting server on http://localhost:8080")
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\nShutting down...")
|
||||
Reference in New Issue
Block a user