Revert "feat: add --llm mode for LLM-friendly stdout filtering"

This reverts commit ea6f07914e.
This commit is contained in:
user
2026-02-19 20:39:36 +01:00
parent ea6f07914e
commit 6f1f4b2fc8
4 changed files with 12 additions and 147 deletions

View File

@@ -7,7 +7,6 @@ import base64
import fnmatch
import logging
import random
import sys
import time
from datetime import datetime, timezone
from pathlib import Path
@@ -78,10 +77,9 @@ class _TokenBucket:
class Bot:
"""IRC bot: ties connection, config, and plugins together."""
def __init__(self, config: dict, registry: PluginRegistry, *, llm: bool = False) -> None:
def __init__(self, config: dict, registry: PluginRegistry) -> None:
self.config = config
self.registry = registry
self._llm = llm
self.conn = IRCConnection(
host=config["server"]["host"],
port=config["server"]["port"],
@@ -94,7 +92,6 @@ class Bot:
self._started: float = time.monotonic()
self._tasks: set[asyncio.Task] = set()
self._reconnect_delay: float = 5.0
self._owner: list[str] = config.get("bot", {}).get("owner", [])
self._admins: list[str] = config.get("bot", {}).get("admins", [])
self._opers: set[str] = set() # hostmasks of known IRC operators
self._caps: set[str] = set() # negotiated IRCv3 caps
@@ -120,18 +117,10 @@ class Bot:
self._reconnect_delay = 5.0 # reset on clean run
except (OSError, ConnectionError) as exc:
log.error("connection lost: %s", exc)
if self._llm:
ts = time.strftime("%H:%M")
sys.stdout.write(f"{ts} --- disconnected: {exc}\n")
sys.stdout.flush()
if self._running:
jitter = self._reconnect_delay * 0.25 * (2 * random.random() - 1)
delay = self._reconnect_delay + jitter
log.info("reconnecting in %.0fs...", delay)
if self._llm:
ts = time.strftime("%H:%M")
sys.stdout.write(f"{ts} --- reconnecting in {delay:.0f}s\n")
sys.stdout.flush()
await asyncio.sleep(delay)
self._reconnect_delay = min(self._reconnect_delay * 2, 300.0)
@@ -270,19 +259,11 @@ class Bot:
# Protocol-level PING/PONG
if msg.command == "PING":
await self.conn.send(format_msg("PONG", msg.params[0] if msg.params else ""))
if self._llm:
ts = time.strftime("%H:%M")
sys.stdout.write(f"{ts} --- ping\n")
sys.stdout.flush()
return
# RPL_WELCOME (001) — join channels and WHO for oper detection
if msg.command == "001":
self.nick = msg.params[0] if msg.params else self.nick
if self._llm:
ts = time.strftime("%H:%M")
sys.stdout.write(f"{ts} --- connected as {self.nick}\n")
sys.stdout.flush()
for channel in self.config["bot"]["channels"]:
await self.join(channel)
await self.conn.send(format_msg("WHO", channel))
@@ -319,16 +300,6 @@ class Bot:
self._spawn(self._handle_ctcp(msg), name="ctcp")
return
# LLM mode: route PRIVMSG to stdout or info.log
if self._llm and msg.command == "PRIVMSG" and msg.text:
ts = time.strftime("%H:%M")
if self._is_addressed(msg) and self._is_owner(msg):
prefix = f"{msg.target} " if msg.is_channel else ""
sys.stdout.write(f"{ts} {prefix}<{msg.nick}> {msg.text}\n")
sys.stdout.flush()
else:
log.info("%s <%s> %s", msg.target, msg.nick, msg.text)
# Dispatch to event handlers (fire-and-forget)
channel = msg.target if msg.is_channel else None
event_type = msg.command
@@ -388,25 +359,14 @@ class Bot:
return True
return plugin_name in allowed
def _is_owner(self, msg: Message) -> bool:
"""Check if the sender matches a configured owner hostmask pattern."""
if not msg.prefix:
return False
for pattern in self._owner:
if fnmatch.fnmatch(msg.prefix, pattern):
return True
return False
def _is_admin(self, msg: Message) -> bool:
"""Check if the message sender is a bot admin.
Returns True if the sender is an owner, a known IRC operator,
or matches a configured admin hostmask pattern (fnmatch-style).
Returns True if the sender is a known IRC operator or matches
a configured hostmask pattern (fnmatch-style).
"""
if not msg.prefix:
return False
if self._is_owner(msg):
return True
if msg.prefix in self._opers:
return True
for pattern in self._admins:
@@ -414,18 +374,6 @@ class Bot:
return True
return False
def _is_addressed(self, msg: Message) -> bool:
"""Check if a message is addressed to the bot (DM or nick-prefixed)."""
if not msg.is_channel:
return True
text = (msg.text or "").lstrip()
nick_lower = self.nick.lower()
if text.lower().startswith(nick_lower):
rest = text[len(nick_lower):]
if rest and rest[0] in ":, ":
return True
return False
def _dispatch_command(self, msg: Message) -> None:
"""Check if a PRIVMSG is a bot command and spawn it."""
text = msg.text
@@ -505,16 +453,6 @@ class Bot:
for chunk in _split_utf8(line, max_text):
await self._bucket.acquire()
await self.conn.send(format_msg("PRIVMSG", target, chunk))
if self._llm:
ts = time.strftime("%H:%M")
display = chunk
if display.startswith("\x01ACTION ") and display.endswith("\x01"):
display = display[8:-1]
out = f"{ts} {target} * {self.nick} {display}"
else:
out = f"{ts} {target} <{self.nick}> {display}"
sys.stdout.write(out + "\n")
sys.stdout.flush()
async def reply(self, msg: Message, text: str) -> None:
"""Reply to the source of a message (channel or PM)."""

View File

@@ -33,11 +33,6 @@ def build_parser() -> argparse.ArgumentParser:
action="store_true",
help="enable debug logging",
)
p.add_argument(
"--llm",
action="store_true",
help="LLM mode: addressed messages to stdout, rest to info.log",
)
p.add_argument(
"--cprofile",
metavar="PATH",
@@ -116,14 +111,7 @@ def main(argv: list[str] | None = None) -> int:
level = logging.DEBUG if args.verbose else logging.INFO
log_fmt = config.get("logging", {}).get("format", "text")
if args.llm:
handler = logging.FileHandler("info.log")
if log_fmt == "json":
handler.setFormatter(JsonFormatter())
else:
handler.setFormatter(logging.Formatter(LOG_FORMAT, datefmt=LOG_DATE))
logging.basicConfig(handlers=[handler], level=level)
elif log_fmt == "json":
if log_fmt == "json":
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logging.basicConfig(handlers=[handler], level=level)
@@ -134,7 +122,7 @@ def main(argv: list[str] | None = None) -> int:
log.info("derp %s starting", __version__)
registry = PluginRegistry()
bot = Bot(config, registry, llm=args.llm)
bot = Bot(config, registry)
bot.load_plugins()
if args.tracemalloc: