chore: auto-commit from dashboard

This commit is contained in:
MoltBot Service
2026-02-15 23:23:29 +00:00
parent 8ce7ea3bd6
commit fd9d962ad2
3 changed files with 408 additions and 26 deletions

View File

@@ -15,6 +15,7 @@ from src.claude_session import (
PROJECT_ROOT,
VALID_MODELS,
)
from src.fast_commands import dispatch as fast_dispatch
from src.router import route_message
logger = logging.getLogger("echo-core.discord")
@@ -114,26 +115,47 @@ def create_bot(config: Config) -> discord.Client:
"**Echo Commands**",
"`/ping` — Check bot latency",
"`/help` — Show this help message",
"`/setup` — Claim ownership of the bot (first run only)",
"`/channel add <alias>` — Register current channel (owner only)",
"`/channels` — List registered channels",
"`/admin add <user_id>` — Add an admin (owner only)",
"`/clear` — Clear the session for this channel",
"`/status` — Show session status for this channel",
"`/model` — View current model and available models",
"`/model <choice>` — Change model for this channel's session",
"`/logs [n]` — Show last N log lines (default 10)",
"`/restart` — Restart the bot process (owner only)",
"`/heartbeat` — Run heartbeat health checks",
"`/search <query>` — Search Echo's memory",
"`/status` — Show session status",
"`/model [choice]` — View/change AI model",
"",
"**Cron Jobs**",
"`/cron list` — List all scheduled jobs",
"`/cron run <name>` — Force-run a job now",
"`/cron add <name> <expr> [model]` — Create a scheduled job (admin)",
"`/cron remove <name>` — Remove a job (admin)",
"`/cron enable <name>` — Enable a job (admin)",
"`/cron disable <name>` — Disable a job (admin)",
"**Email**",
"`/email check` — Check unread emails",
"`/email send <to> <subject> <body>` — Send an email",
"`/email save` — Save unread emails to KB",
"",
"**Calendar**",
"`/calendar today` — Today + tomorrow events",
"`/calendar week` — This week's schedule",
"`/calendar busy` — Am I in a meeting?",
"",
"**Notes**",
"`/note <text>` — Quick note in daily file",
"`/jurnal <text>` — Journal entry in daily file",
"`/search <query>` — Search Echo's memory",
"`/kb [category]` — Recent KB notes",
"",
"**Reminders**",
"`/remind <time> <text> [date]` — Create reminder",
"",
"**Git**",
"`/commit [message]` — Commit all changes",
"`/push` — Push to remote",
"`/pull` — Pull with rebase",
"`/test [pattern]` — Run tests",
"",
"**Ops**",
"`/logs [n]` — Last N log lines",
"`/doctor` — System diagnostics",
"`/heartbeat` — Health checks",
"`/restart` — Restart bot (owner)",
"",
"**Admin**",
"`/setup` — Claim ownership",
"`/channel add <alias>` — Register channel",
"`/channels` — List channels",
"`/admin add <user_id>` — Add admin",
"`/cron list|run|add|remove|enable|disable` — Cron jobs",
]
await interaction.response.send_message(
"\n".join(lines), ephemeral=True
@@ -409,6 +431,158 @@ def create_bot(config: Config) -> discord.Client:
tree.add_command(cron_group)
# --- Email commands ---
email_group = app_commands.Group(
name="email", description="Email operations"
)
@email_group.command(name="check", description="Check unread emails")
async def email_check(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "email", [])
await interaction.followup.send(result)
@email_group.command(name="send", description="Send an email")
@app_commands.describe(
to="Recipient email address",
subject="Email subject",
body="Email body text",
)
async def email_send(
interaction: discord.Interaction, to: str, subject: str, body: str
) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(
fast_dispatch, "email", ["send", f"{to} {subject} :: {body}"]
)
await interaction.followup.send(result)
@email_group.command(name="save", description="Save unread emails to knowledge base")
async def email_save(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "email", ["save"])
await interaction.followup.send(result)
tree.add_command(email_group)
# --- Calendar commands ---
calendar_group = app_commands.Group(
name="calendar", description="Calendar operations"
)
@calendar_group.command(name="today", description="Today and tomorrow events")
async def calendar_today(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "calendar", [])
await interaction.followup.send(result)
@calendar_group.command(name="week", description="This week's schedule")
async def calendar_week(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "calendar", ["week"])
await interaction.followup.send(result)
@calendar_group.command(name="busy", description="Am I in a meeting right now?")
async def calendar_busy(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "calendar", ["busy"])
await interaction.followup.send(result)
tree.add_command(calendar_group)
# --- Note & journal commands ---
@tree.command(name="note", description="Add a quick note to today's daily file")
@app_commands.describe(text="Note text")
async def note_cmd(interaction: discord.Interaction, text: str) -> None:
await interaction.response.defer(ephemeral=True)
result = await asyncio.to_thread(fast_dispatch, "note", text.split())
await interaction.followup.send(result, ephemeral=True)
@tree.command(name="jurnal", description="Add a journal entry to today's daily file")
@app_commands.describe(text="Journal entry text")
async def jurnal_cmd(interaction: discord.Interaction, text: str) -> None:
await interaction.response.defer(ephemeral=True)
result = await asyncio.to_thread(fast_dispatch, "jurnal", text.split())
await interaction.followup.send(result, ephemeral=True)
# --- KB command ---
@tree.command(name="kb", description="List recent knowledge base notes")
@app_commands.describe(category="Filter by category (optional)")
async def kb_cmd(
interaction: discord.Interaction, category: str | None = None
) -> None:
await interaction.response.defer()
args = [category] if category else []
result = await asyncio.to_thread(fast_dispatch, "kb", args)
await interaction.followup.send(result)
# --- Remind command ---
@tree.command(name="remind", description="Create a calendar reminder")
@app_commands.describe(
time="Time in HH:MM format",
text="Reminder text",
date="Date in YYYY-MM-DD format (default: today)",
)
async def remind_cmd(
interaction: discord.Interaction, time: str, text: str, date: str | None = None
) -> None:
await interaction.response.defer(ephemeral=True)
args = [date, time, text] if date else [time, text]
result = await asyncio.to_thread(fast_dispatch, "remind", args)
await interaction.followup.send(result, ephemeral=True)
# --- Git commands ---
@tree.command(name="commit", description="Git commit all changes")
@app_commands.describe(message="Commit message (auto-generated if empty)")
async def commit_cmd(
interaction: discord.Interaction, message: str | None = None
) -> None:
await interaction.response.defer()
args = message.split() if message else []
result = await asyncio.to_thread(fast_dispatch, "commit", args)
await interaction.followup.send(result)
@tree.command(name="push", description="Git push to remote")
async def push_cmd(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "push", [])
await interaction.followup.send(result)
@tree.command(name="pull", description="Git pull with rebase")
async def pull_cmd(interaction: discord.Interaction) -> None:
await interaction.response.defer()
result = await asyncio.to_thread(fast_dispatch, "pull", [])
await interaction.followup.send(result)
# --- Test command ---
@tree.command(name="test", description="Run pytest tests")
@app_commands.describe(pattern="Test filter pattern (optional)")
async def test_cmd(
interaction: discord.Interaction, pattern: str | None = None
) -> None:
await interaction.response.defer()
args = [pattern] if pattern else []
result = await asyncio.to_thread(fast_dispatch, "test", args)
# Truncate for Discord limit
if len(result) > 1900:
result = result[-1900:]
await interaction.followup.send(f"```\n{result}\n```")
# --- Doctor command ---
@tree.command(name="doctor", description="System diagnostics")
async def doctor_cmd(interaction: discord.Interaction) -> None:
await interaction.response.defer(ephemeral=True)
result = await asyncio.to_thread(fast_dispatch, "doctor", [])
await interaction.followup.send(result, ephemeral=True)
@tree.command(name="heartbeat", description="Run heartbeat health checks")
async def heartbeat_cmd(interaction: discord.Interaction) -> None:
from src.heartbeat import run_heartbeat