Compare commits
1 Commits
main
...
claude/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c58093dccc |
@@ -18,9 +18,17 @@ jobs:
|
||||
- name: Lint (ruff via tox)
|
||||
run: tox -e lint
|
||||
|
||||
test:
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Type-check (mypy via tox)
|
||||
run: tox -e typecheck
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: typecheck
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run tests (via tox)
|
||||
|
||||
@@ -164,3 +164,7 @@ directory = "htmlcov"
|
||||
|
||||
[tool.coverage.xml]
|
||||
output = "coverage.xml"
|
||||
|
||||
[tool.mypy]
|
||||
ignore_missing_imports = true
|
||||
no_error_summary = true
|
||||
|
||||
@@ -6,6 +6,8 @@ import sqlite3
|
||||
from contextlib import closing
|
||||
from pathlib import Path
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
|
||||
@@ -36,9 +38,9 @@ def _discover_databases() -> list[dict]:
|
||||
return dbs
|
||||
|
||||
|
||||
def _query_database(db_path: str) -> dict:
|
||||
def _query_database(db_path: str) -> dict[str, Any]:
|
||||
"""Open a database read-only and return all tables with their rows."""
|
||||
result = {"tables": {}, "error": None}
|
||||
result: dict[str, Any] = {"tables": {}, "error": None}
|
||||
try:
|
||||
with closing(sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
@@ -137,7 +137,7 @@ class HermesMonitor:
|
||||
message=f"Check error: {r}",
|
||||
)
|
||||
)
|
||||
else:
|
||||
elif isinstance(r, CheckResult):
|
||||
checks.append(r)
|
||||
|
||||
# Compute overall level
|
||||
|
||||
@@ -203,7 +203,7 @@ async def reload_config(
|
||||
@router.get("/history")
|
||||
async def get_history(
|
||||
hours: int = 24,
|
||||
store: Annotated[HealthHistoryStore, Depends(get_history_store)] = None,
|
||||
store: Annotated[HealthHistoryStore | None, Depends(get_history_store)] = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Get provider health history for the last N hours."""
|
||||
if store is None:
|
||||
|
||||
@@ -744,19 +744,20 @@ class CascadeRouter:
|
||||
self,
|
||||
provider: Provider,
|
||||
messages: list[dict],
|
||||
model: str,
|
||||
model: str | None,
|
||||
temperature: float,
|
||||
max_tokens: int | None,
|
||||
content_type: ContentType = ContentType.TEXT,
|
||||
) -> dict:
|
||||
"""Try a single provider request."""
|
||||
start_time = time.time()
|
||||
effective_model: str = model or provider.get_default_model() or ""
|
||||
|
||||
if provider.type == "ollama":
|
||||
result = await self._call_ollama(
|
||||
provider=provider,
|
||||
messages=messages,
|
||||
model=model or provider.get_default_model(),
|
||||
model=effective_model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
content_type=content_type,
|
||||
@@ -765,7 +766,7 @@ class CascadeRouter:
|
||||
result = await self._call_openai(
|
||||
provider=provider,
|
||||
messages=messages,
|
||||
model=model or provider.get_default_model(),
|
||||
model=effective_model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
)
|
||||
@@ -773,7 +774,7 @@ class CascadeRouter:
|
||||
result = await self._call_anthropic(
|
||||
provider=provider,
|
||||
messages=messages,
|
||||
model=model or provider.get_default_model(),
|
||||
model=effective_model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
)
|
||||
@@ -781,7 +782,7 @@ class CascadeRouter:
|
||||
result = await self._call_grok(
|
||||
provider=provider,
|
||||
messages=messages,
|
||||
model=model or provider.get_default_model(),
|
||||
model=effective_model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
)
|
||||
@@ -789,7 +790,7 @@ class CascadeRouter:
|
||||
result = await self._call_vllm_mlx(
|
||||
provider=provider,
|
||||
messages=messages,
|
||||
model=model or provider.get_default_model(),
|
||||
model=effective_model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
)
|
||||
|
||||
20
src/integrations/chat_bridge/vendors/discord.py
vendored
20
src/integrations/chat_bridge/vendors/discord.py
vendored
@@ -474,7 +474,7 @@ class DiscordVendor(ChatPlatform):
|
||||
async def _run_client(self, token: str) -> None:
|
||||
"""Run the discord.py client (blocking call in a task)."""
|
||||
try:
|
||||
await self._client.start(token)
|
||||
await self._client.start(token) # type: ignore[union-attr]
|
||||
except Exception as exc:
|
||||
logger.error("Discord client error: %s", exc)
|
||||
self._state = PlatformState.ERROR
|
||||
@@ -482,32 +482,32 @@ class DiscordVendor(ChatPlatform):
|
||||
def _register_handlers(self) -> None:
|
||||
"""Register Discord event handlers on the client."""
|
||||
|
||||
@self._client.event
|
||||
@self._client.event # type: ignore[union-attr]
|
||||
async def on_ready():
|
||||
self._guild_count = len(self._client.guilds)
|
||||
self._guild_count = len(self._client.guilds) # type: ignore[union-attr]
|
||||
self._state = PlatformState.CONNECTED
|
||||
logger.info(
|
||||
"Discord ready: %s in %d guild(s)",
|
||||
self._client.user,
|
||||
self._client.user, # type: ignore[union-attr]
|
||||
self._guild_count,
|
||||
)
|
||||
|
||||
@self._client.event
|
||||
@self._client.event # type: ignore[union-attr]
|
||||
async def on_message(message):
|
||||
# Ignore our own messages
|
||||
if message.author == self._client.user:
|
||||
if message.author == self._client.user: # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
# Only respond to mentions or DMs
|
||||
is_dm = not hasattr(message.channel, "guild") or message.channel.guild is None
|
||||
is_mention = self._client.user in message.mentions
|
||||
is_mention = self._client.user in message.mentions # type: ignore[union-attr]
|
||||
|
||||
if not is_dm and not is_mention:
|
||||
return
|
||||
|
||||
await self._handle_message(message)
|
||||
|
||||
@self._client.event
|
||||
@self._client.event # type: ignore[union-attr]
|
||||
async def on_disconnect():
|
||||
if self._state != PlatformState.DISCONNECTED:
|
||||
self._state = PlatformState.CONNECTING
|
||||
@@ -535,8 +535,8 @@ class DiscordVendor(ChatPlatform):
|
||||
def _extract_content(self, message) -> str:
|
||||
"""Strip the bot mention and return clean message text."""
|
||||
content = message.content
|
||||
if self._client.user:
|
||||
content = content.replace(f"<@{self._client.user.id}>", "").strip()
|
||||
if self._client.user: # type: ignore[union-attr]
|
||||
content = content.replace(f"<@{self._client.user.id}>", "").strip() # type: ignore[union-attr]
|
||||
return content
|
||||
|
||||
async def _invoke_agent(self, content: str, session_id: str, target):
|
||||
|
||||
@@ -102,14 +102,14 @@ class TelegramBot:
|
||||
self._token = tok
|
||||
self._app = Application.builder().token(tok).build()
|
||||
|
||||
self._app.add_handler(CommandHandler("start", self._cmd_start))
|
||||
self._app.add_handler(
|
||||
self._app.add_handler(CommandHandler("start", self._cmd_start)) # type: ignore[union-attr]
|
||||
self._app.add_handler( # type: ignore[union-attr]
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND, self._handle_message)
|
||||
)
|
||||
|
||||
await self._app.initialize()
|
||||
await self._app.start()
|
||||
await self._app.updater.start_polling(allowed_updates=Update.ALL_TYPES)
|
||||
await self._app.initialize() # type: ignore[union-attr]
|
||||
await self._app.start() # type: ignore[union-attr]
|
||||
await self._app.updater.start_polling(allowed_updates=Update.ALL_TYPES) # type: ignore[union-attr]
|
||||
|
||||
self._running = True
|
||||
logger.info("Telegram bot started.")
|
||||
|
||||
@@ -245,6 +245,7 @@ class VoiceLoop:
|
||||
def _transcribe(self, audio: np.ndarray) -> str:
|
||||
"""Transcribe audio using local Whisper model."""
|
||||
self._load_whisper()
|
||||
assert self._whisper_model is not None, "Whisper model failed to load"
|
||||
|
||||
sys.stdout.write(" 🧠 Transcribing...\r")
|
||||
sys.stdout.flush()
|
||||
|
||||
10
tox.ini
10
tox.ini
@@ -41,8 +41,10 @@ description = Static type checking with mypy
|
||||
commands_pre =
|
||||
deps =
|
||||
mypy>=1.0.0
|
||||
types-PyYAML
|
||||
types-requests
|
||||
commands =
|
||||
mypy src --ignore-missing-imports --no-error-summary
|
||||
mypy src
|
||||
|
||||
# ── Test Environments ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -130,13 +132,17 @@ commands =
|
||||
# ── Pre-push (mirrors CI exactly) ────────────────────────────────────────────
|
||||
|
||||
[testenv:pre-push]
|
||||
description = Local gate — lint + full CI suite (same as Gitea Actions)
|
||||
description = Local gate — lint + typecheck + full CI suite (same as Gitea Actions)
|
||||
deps =
|
||||
ruff>=0.8.0
|
||||
mypy>=1.0.0
|
||||
types-PyYAML
|
||||
types-requests
|
||||
commands =
|
||||
ruff check src/ tests/
|
||||
ruff format --check src/ tests/
|
||||
bash -c 'files=$(grep -rl "<style" src/dashboard/templates/ --include="*.html" 2>/dev/null); if [ -n "$files" ]; then echo "ERROR: inline <style> blocks found — move CSS to static/css/mission-control.css:"; echo "$files"; exit 1; fi; echo "No inline CSS — OK"'
|
||||
mypy src
|
||||
mkdir -p reports
|
||||
pytest tests/ \
|
||||
--cov=src \
|
||||
|
||||
Reference in New Issue
Block a user