Initial release — APIClient - Agent v2.0.0

AI-first API testing desktop client built with Python + PyQt6.

Features:
- Multi-tab HTTP request editor with params/headers/body/auth/tests
- KeyValueTable with per-row enable/disable checkboxes and 36px rows
- Format JSON button, syntax highlighting, pre-request & test scripts
- Collections, environments, history, import/export (Postman v2.1, cURL)
- OpenAPI 3.x / Swagger 2.0 local parser (no AI tokens)
- EKIKA Odoo API Framework generator — JSON-API, REST JSON, GraphQL,
  Custom REST JSON with all auth types (instant, no AI tokens)
- Persistent AI chat sidebar (Claude-powered co-pilot) with streaming,
  context-aware suggestions, and one-click Apply to request editor
- AI collection generator from any docs URL or pasted spec
- WebSocket client, Mock server, Collection runner, Code generator
- Dark/light theme engine (global QSS, object-name selectors)
- SSL error detection with actionable hints
- MIT License

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-28 17:34:18 +05:30
parent 1dbbb4320b
commit 01662f7e0e
37 changed files with 7822 additions and 1 deletions

82
app/core/mock_server.py Normal file
View File

@@ -0,0 +1,82 @@
"""APIClient - Agent — Lightweight HTTP mock server."""
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from app.core import storage
_server_instance: HTTPServer | None = None
_server_thread: threading.Thread | None = None
_server_port: int = 8888
class _MockHandler(BaseHTTPRequestHandler):
"""Queries the DB on every request so new/edited endpoints are served immediately."""
def log_message(self, fmt, *args):
pass # suppress default console logging
def _handle(self):
endpoints = storage.get_mock_endpoints()
matched = None
for ep in endpoints:
method_match = ep.method == "*" or ep.method == self.command
if method_match and ep.path == self.path:
matched = ep
break
if matched:
self.send_response(matched.status_code)
for k, v in matched.response_headers.items():
self.send_header(k, v)
body = matched.response_body.encode("utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
else:
body = b'{"error": "No mock endpoint matched"}'
self.send_response(404)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
do_GET = _handle
do_POST = _handle
do_PUT = _handle
do_PATCH = _handle
do_DELETE = _handle
do_HEAD = _handle
do_OPTIONS = _handle
def start(port: int = 8888) -> str:
global _server_instance, _server_thread, _server_port
if _server_instance:
return f"Already running on port {_server_port}"
_server_port = port
try:
_server_instance = HTTPServer(("localhost", port), _MockHandler)
except OSError as e:
return f"Failed to start: {e}"
_server_thread = threading.Thread(target=_server_instance.serve_forever, daemon=True)
_server_thread.start()
return f"Mock server running on http://localhost:{port}"
def stop() -> str:
global _server_instance, _server_thread
if _server_instance:
_server_instance.shutdown()
_server_instance = None
_server_thread = None
return "Mock server stopped"
return "Not running"
def is_running() -> bool:
return _server_instance is not None
def get_port() -> int:
return _server_port