Update documentation.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — AI chat sidebar panel (persistent, context-aware)."""
|
||||
"""APIClient - Agent - AI chat sidebar panel (persistent, context-aware)."""
|
||||
import re
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
@@ -124,7 +124,7 @@ class MessageBubble(QFrame):
|
||||
self._text_lbl.setText(self._full_text)
|
||||
|
||||
def finalize(self):
|
||||
"""Called when streaming ends — strip apply blocks and render them."""
|
||||
"""Called when streaming ends - strip apply blocks and render them."""
|
||||
if self._finalized:
|
||||
return
|
||||
self._finalized = True
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — AI Assistant Dialog."""
|
||||
"""APIClient - Agent - AI Assistant Dialog."""
|
||||
import json
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
@@ -43,7 +43,7 @@ class AnalysisWorker(QThread):
|
||||
self.progress.emit("Checking for OpenAPI/Swagger spec…")
|
||||
spec = openapi_parser.detect_spec(content)
|
||||
if spec:
|
||||
self.progress.emit("OpenAPI spec detected — parsing directly…")
|
||||
self.progress.emit("OpenAPI spec detected - parsing directly…")
|
||||
result = openapi_parser.parse_spec(spec)
|
||||
if self.base_url:
|
||||
result["base_url"] = self.base_url
|
||||
@@ -136,7 +136,7 @@ class AIAssistantDialog(QDialog):
|
||||
layout.addWidget(footer)
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
# Tab 1 — EKIKA Odoo API Framework (dedicated, no AI tokens needed)
|
||||
# Tab 1 - EKIKA Odoo API Framework (dedicated, no AI tokens needed)
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def _build_ekika_tab(self) -> QWidget:
|
||||
@@ -303,7 +303,7 @@ class AIAssistantDialog(QDialog):
|
||||
self.ek_preview.setFont(QFont("JetBrains Mono, Fira Code, Consolas", 10))
|
||||
self.ek_preview.setPlaceholderText(
|
||||
"Fill in the form above and click Generate Collection to preview.\n\n"
|
||||
"No API key required — collection is generated instantly from the\n"
|
||||
"No API key required - collection is generated instantly from the\n"
|
||||
"EKIKA Odoo API Framework documentation."
|
||||
)
|
||||
self.ek_preview.setMaximumHeight(180)
|
||||
@@ -380,7 +380,7 @@ class AIAssistantDialog(QDialog):
|
||||
self.ek_import_btn.setEnabled(True)
|
||||
self.ek_env_btn.setEnabled(True)
|
||||
self.ek_both_btn.setEnabled(True)
|
||||
self.status_label.setText(f"✓ {len(eps)} endpoint(s) ready — click Import to save")
|
||||
self.status_label.setText(f"✓ {len(eps)} endpoint(s) ready - click Import to save")
|
||||
|
||||
def _ekika_import(self):
|
||||
if not self._result:
|
||||
@@ -399,7 +399,7 @@ class AIAssistantDialog(QDialog):
|
||||
self._do_create_env(self._result)
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
# Tab 2 — Generic AI analysis (OpenAPI / any docs URL)
|
||||
# Tab 2 - Generic AI analysis (OpenAPI / any docs URL)
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def _build_generic_tab(self) -> QWidget:
|
||||
@@ -543,10 +543,10 @@ class AIAssistantDialog(QDialog):
|
||||
lines = [
|
||||
f"✓ Parsed via: {src_label}",
|
||||
f"✓ Collection: {result.get('collection_name', 'Unnamed')}",
|
||||
f"✓ Base URL: {result.get('base_url', '—')}",
|
||||
f"✓ Base URL: {result.get('base_url', '-')}",
|
||||
f"✓ Auth type: {result.get('auth_type', 'none')}",
|
||||
f"✓ Endpoints: {len(endpoints)} found",
|
||||
f"✓ Env vars: {list(env_vars.keys()) or '—'}",
|
||||
f"✓ Env vars: {list(env_vars.keys()) or '-'}",
|
||||
]
|
||||
if notes:
|
||||
lines += ["", "── Notes ─────────────────", notes]
|
||||
@@ -565,7 +565,7 @@ class AIAssistantDialog(QDialog):
|
||||
self.analyze_btn.setEnabled(True)
|
||||
self.progress_bar.setVisible(False)
|
||||
self.result_view.setPlainText(f"✗ Error:\n\n{msg}")
|
||||
self.status_label.setText("Error — see results panel")
|
||||
self.status_label.setText("Error - see results panel")
|
||||
|
||||
def _set_generic_action_buttons(self, enabled: bool):
|
||||
self.import_btn.setEnabled(enabled)
|
||||
@@ -586,7 +586,7 @@ class AIAssistantDialog(QDialog):
|
||||
self._do_create_env(self._generic_result)
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
# Tab 3 — Settings
|
||||
# Tab 3 - Settings
|
||||
# ══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def _build_settings_tab(self) -> QWidget:
|
||||
@@ -598,7 +598,7 @@ class AIAssistantDialog(QDialog):
|
||||
|
||||
hint = QLabel(
|
||||
"EKIKA AI Assistant uses Claude by Anthropic to analyze plain-text API documentation.\n"
|
||||
"OpenAPI/Swagger specs and EKIKA Odoo Framework collections are generated locally — "
|
||||
"OpenAPI/Swagger specs and EKIKA Odoo Framework collections are generated locally - "
|
||||
"no API key required for those."
|
||||
)
|
||||
hint.setObjectName("hintText")
|
||||
@@ -683,7 +683,7 @@ class AIAssistantDialog(QDialog):
|
||||
def _do_create_env(self, result: dict):
|
||||
env_vars = result.get("environment_variables", {})
|
||||
col_name = result.get("collection_name", "AI Import")
|
||||
env_name = f"{col_name} — Environment"
|
||||
env_name = f"{col_name} - Environment"
|
||||
|
||||
if not env_vars:
|
||||
QMessageBox.information(self, "No Variables", "No environment variables detected.")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Code Generation Dialog."""
|
||||
"""APIClient - Agent - Code Generation Dialog."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QComboBox,
|
||||
QTextEdit, QPushButton, QLabel, QApplication, QWidget
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Collection Runner dialog."""
|
||||
"""APIClient - Agent - Collection Runner dialog."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
|
||||
QTreeWidget, QTreeWidgetItem, QComboBox, QHeaderView, QProgressBar, QWidget
|
||||
@@ -168,7 +168,7 @@ class CollectionRunnerDialog(QDialog):
|
||||
status_str = str(result.status)
|
||||
row_color = Colors.SUCCESS if result.status < 400 else Colors.ERROR
|
||||
|
||||
test_str = f"{passed}/{total}" if total > 0 else "—"
|
||||
test_str = f"{passed}/{total}" if total > 0 else "-"
|
||||
item = QTreeWidgetItem([
|
||||
f"{result.method} {result.request_name}",
|
||||
status_str,
|
||||
@@ -189,6 +189,6 @@ class CollectionRunnerDialog(QDialog):
|
||||
def _on_finished(self):
|
||||
self.run_btn.setEnabled(True)
|
||||
self.summary_label.setText(
|
||||
f"Completed: {self._done} request(s) — "
|
||||
f"Completed: {self._done} request(s) - "
|
||||
f"Tests: {self._passed_tests}/{self._total_tests} passed"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Environment Manager Dialog."""
|
||||
"""APIClient - Agent - Environment Manager Dialog."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QListWidget, QListWidgetItem,
|
||||
QPushButton, QTableWidget, QTableWidgetItem, QHeaderView,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Import Dialog."""
|
||||
"""APIClient - Agent - Import Dialog."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QTabWidget, QWidget,
|
||||
QTextEdit, QPushButton, QLabel, QFileDialog, QMessageBox
|
||||
@@ -76,7 +76,7 @@ class ImportDialog(QDialog):
|
||||
layout.setContentsMargins(16, 12, 16, 12)
|
||||
layout.setSpacing(8)
|
||||
|
||||
hint = QLabel("Paste a cURL command — it will open as a new request tab:")
|
||||
hint = QLabel("Paste a cURL command - it will open as a new request tab:")
|
||||
hint.setObjectName("hintText")
|
||||
layout.addWidget(hint)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Main Window."""
|
||||
"""APIClient - Agent - Main Window."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QMainWindow, QSplitter, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QComboBox, QPushButton, QStatusBar, QTabWidget,
|
||||
@@ -147,7 +147,7 @@ class MainWindow(QMainWindow):
|
||||
self.chat_panel = AIChatPanel()
|
||||
splitter.addWidget(self.chat_panel)
|
||||
splitter.setSizes([260, 940, 360]) # give chat panel real size first
|
||||
self.chat_panel.hide() # THEN hide — splitter remembers 360
|
||||
self.chat_panel.hide() # THEN hide - splitter remembers 360
|
||||
self._main_splitter = splitter
|
||||
|
||||
# Wire apply signals
|
||||
@@ -163,7 +163,7 @@ class MainWindow(QMainWindow):
|
||||
self._status_bar = QStatusBar()
|
||||
self._status_bar.setFixedHeight(26)
|
||||
self.setStatusBar(self._status_bar)
|
||||
self._status_bar.showMessage(f"Ready — {APP_NAME} v{APP_VERSION}")
|
||||
self._status_bar.showMessage(f"Ready - {APP_NAME} v{APP_VERSION}")
|
||||
|
||||
def _build_http_workspace(self) -> QWidget:
|
||||
w = QWidget()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Mock Server Panel."""
|
||||
"""APIClient - Agent - Mock Server Panel."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel,
|
||||
QTableWidget, QTableWidgetItem, QHeaderView, QDialog,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Request Panel."""
|
||||
"""APIClient - Agent - Request Panel."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QComboBox, QLineEdit,
|
||||
QPushButton, QTabWidget, QTableWidget, QTableWidgetItem,
|
||||
@@ -227,7 +227,7 @@ class RequestPanel(QWidget):
|
||||
|
||||
self.url_input = QLineEdit()
|
||||
self.url_input.setObjectName("urlBar")
|
||||
self.url_input.setPlaceholderText("Enter URL — e.g. https://api.example.com/v1/users")
|
||||
self.url_input.setPlaceholderText("Enter URL - e.g. https://api.example.com/v1/users")
|
||||
self.url_input.returnPressed.connect(self._send)
|
||||
|
||||
self.send_btn = QPushButton("Send")
|
||||
@@ -359,7 +359,7 @@ class RequestPanel(QWidget):
|
||||
# ── Slots ────────────────────────────────────────────────────────────────
|
||||
|
||||
def _on_method_changed(self, method: str):
|
||||
# Inline style is intentional here — color is dynamic per method value
|
||||
# Inline style is intentional here - color is dynamic per method value
|
||||
color = method_color(method)
|
||||
self.method_combo.setStyleSheet(f"QComboBox#methodCombo {{ color: {color}; }}")
|
||||
|
||||
@@ -377,7 +377,7 @@ class RequestPanel(QWidget):
|
||||
parsed = json.loads(text)
|
||||
self.body_editor.setPlainText(json.dumps(parsed, indent=2, ensure_ascii=False))
|
||||
except json.JSONDecodeError:
|
||||
pass # not valid JSON — leave as-is
|
||||
pass # not valid JSON - leave as-is
|
||||
|
||||
def _send(self):
|
||||
self.send_requested.emit(self._build_request())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Response Panel."""
|
||||
"""APIClient - Agent - Response Panel."""
|
||||
import json
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
@@ -25,13 +25,13 @@ def _fmt_size(n: int) -> str:
|
||||
|
||||
class StatusBadge(QLabel):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__("—", parent)
|
||||
super().__init__("-", parent)
|
||||
self.setFixedHeight(26)
|
||||
self._apply_style(Colors.TEXT_MUTED)
|
||||
self.setFont(QFont("Segoe UI", 11, QFont.Weight.Bold))
|
||||
|
||||
def _apply_style(self, color: str):
|
||||
# Inline style intentional — badge color is dynamic per status code
|
||||
# Inline style intentional - badge color is dynamic per status code
|
||||
self.setStyleSheet(f"""
|
||||
QLabel {{
|
||||
color: {color};
|
||||
@@ -53,7 +53,7 @@ class StatusBadge(QLabel):
|
||||
self._apply_style(Colors.ERROR)
|
||||
|
||||
def clear(self):
|
||||
self.setText("—")
|
||||
self.setText("-")
|
||||
self._apply_style(Colors.TEXT_MUTED)
|
||||
|
||||
|
||||
@@ -174,8 +174,8 @@ class ResponsePanel(QWidget):
|
||||
self._loading_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
ll.addWidget(self._loading_label)
|
||||
|
||||
self._stack.addWidget(self.tabs) # index 0 — normal view
|
||||
self._stack.addWidget(loading_widget) # index 1 — loading
|
||||
self._stack.addWidget(self.tabs) # index 0 - normal view
|
||||
self._stack.addWidget(loading_widget) # index 1 - loading
|
||||
|
||||
layout.addWidget(self._stack, 1)
|
||||
|
||||
@@ -203,7 +203,7 @@ class ResponsePanel(QWidget):
|
||||
size = resp.size_bytes or len(resp.body.encode())
|
||||
self.size_label.setText(_fmt_size(size))
|
||||
|
||||
# Body — pretty-print JSON if possible
|
||||
# Body - pretty-print JSON if possible
|
||||
try:
|
||||
parsed = json.loads(resp.body)
|
||||
self.body_view.setPlainText(json.dumps(parsed, indent=2, ensure_ascii=False))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Request Search Dialog."""
|
||||
"""APIClient - Agent - Request Search Dialog."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QLineEdit,
|
||||
QPushButton, QListWidget, QListWidgetItem, QLabel, QWidget
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Collections Sidebar."""
|
||||
"""APIClient - Agent - Collections Sidebar."""
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QTreeWidget, QTreeWidgetItem,
|
||||
QPushButton, QInputDialog, QMenu, QLineEdit, QLabel, QMessageBox
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — Multi-tab request manager."""
|
||||
"""APIClient - Agent - Multi-tab request manager."""
|
||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QTabWidget, QPushButton, QTabBar
|
||||
from PyQt6.QtCore import pyqtSignal, Qt
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
APIClient - Agent — Central Theme Engine
|
||||
APIClient - Agent - Central Theme Engine
|
||||
All styling lives here in the global QSS.
|
||||
UI widgets use setObjectName() selectors — never inline setStyleSheet() for static colors.
|
||||
UI widgets use setObjectName() selectors - never inline setStyleSheet() for static colors.
|
||||
Only truly dynamic values (per-request method color, status badge) stay inline.
|
||||
"""
|
||||
from PyQt6.QtGui import QColor, QPalette
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""APIClient - Agent — WebSocket client panel."""
|
||||
"""APIClient - Agent - WebSocket client panel."""
|
||||
import asyncio
|
||||
import queue
|
||||
import time
|
||||
|
||||
Reference in New Issue
Block a user