Skip to content

fyang93/the-defect-bot

Repository files navigation

The Defect Bot

中文说明

A local-first Telegram bot for personal memory, files, events, reminders, and lightweight relay workflows.

It runs through a local OpenCode server, keeps canonical state in the repository, and treats Telegram as a platform adapter rather than the center of the architecture.

What it does

  • remember and retrieve personal facts
  • organize uploaded files and materials
  • create and manage events and automations
  • send messages or scheduled deliveries to authorized users or known group chats
  • save Telegram-uploaded files into tmp/ for processing; the latest same-name upload replaces the earlier local copy
  • let the admin manage durable user roles through the bot

Architecture

The bot is organized as a small layered system: bot runtime, platform adapters, AI, repository CLI, domain operations, and records, with the repository CLI used as the preferred deterministic execution boundary.

Interaction
  receive and deliver user messages
  |
  v
Scheduling
  coordinate loops, sessions, and timing
  |
  +-- Assistant
  |     one main agent for interpretation + execution
  |     |
  |     +--> Repository CLI + Skills
  |     |      |
  |     |      +--> Operations / Records
  |     |             domain logic and canonical state
  |
  +-- Maintainer
         cleanup and repair
         |
         +--> Operations

The current conversation path is centered on a single assistant lane:

  • bot-side code and repo-CLI code are kept as separate surfaces in src/bot/** and src/cli/**

  • the assistant interprets the request and performs needed work directly

  • the current direction is to let runtime code own current-turn reply publication orchestration while actual Telegram delivery stays on shared deterministic CLI-backed paths the assistant mainly uses via repository-local CLI and skills

  • runtime code keeps waiting-state UI, interruption, short startup coalescing / follow-up merge, and duplicate-publication safeguards

  • fixed UI text stays in i18n; natural conversational wording is generated by the model

  • user-facing assistant replies follow the user's natural conversation language, while fixed UI text follows the configured default UI locale

Conversation scoping

Short-term conversational context is kept in OpenCode sessions by scope:

  • private chat -> one session per user
  • group / supergroup -> one session per chat

Long-term facts, access roles, events, automations, and structured state do not rely on model session history. They live in repository state such as system/users.json, system/chats.json, system/state.json, and system/events.json. These stores should be managed through deterministic code paths and the repository CLI instead of prompt-defined persistence protocols. The project-wide engineering rules now live in docs/principles.md.

Skill map

The repository keeps the skill set intentionally small. Repository-specific work should go through CLI + skills:

  • cli-shared: shared/base guidance for the repository CLI surface
  • cli-events: events, reminders, and automation workflows
  • cli-telegram: Telegram outbound delivery workflows
  • cli-access: users and authorization workflows
  • memory: repository-local durable notes and preferences

Quick start

cp config.toml.example config.toml
cp .env.example .env
just install
# uses the project-local OpenCode binary via npm, no global install required
just serve

Configuration

Fill in at least:

  • telegram.bot_token
  • telegram.admin_user_id

Typical setup:

[telegram]
bot_token = "YOUR_TELEGRAM_BOT_TOKEN"
admin_user_id = 333333333
waiting_message = "Thinking..."
input_merge_window_seconds = 3
menu_page_size = 8

[bot]
language = "zh-CN"
persona_style = "Speak like the Defect from Slay the Spire."
default_timezone = "Asia/Tokyo"

[maintenance]
enabled = true
idle_after_minutes = 15

[opencode]
base_url = "http://127.0.0.1:4096"

Useful optional settings:

  • telegram.menu_page_size: Telegram inline menu page size
  • telegram.input_merge_window_seconds: short window for merging follow-up text/files into the same in-flight turn
  • telegram.waiting_message: initial waiting UI text shown immediately; if empty, no initial waiting message is shown
  • bot.language: default UI locale for fixed UI text; choose zh-CN or en
  • bot.default_timezone: fallback timezone used when the user has not explicitly provided one
  • maintenance.idle_after_minutes: run maintenance after this many idle minutes
  • opencode.base_url: local OpenCode server address

Telegram prerequisites

  • Every user who should receive direct bot messages must have started a private chat with the bot at least once.
  • If you want to use the bot in group chats, open BotFather and turn Group Privacy off for the bot.

Access levels

  • allowed user: may chat with the bot and use only basic low-risk features within their own / linked conversation context; they may upload/process temporary files in tmp/, but must not access private information outside that scoped context or write durable memory
  • trusted user: may read and modify memory, upload/process files, create events/automations, and use other persistent workflows
  • admin user: trusted user plus admin-only operations such as durable role management and temporary authorization grants

The code currently enforces the allowed-user privacy boundary in the assistant lane: allowed users are constrained to allowed-user scope and must not be given private information outside the linked conversation context.

The admin may also temporarily allow a @username and choose any expiry window. After that, the user only needs to interact with the bot before the temporary authorization expires so the system can link the account and grant access. This can be a private chat, an @bot mention in a group, or a reply to the bot in a group.

Delayed Telegram delivery is delegated to the external at scheduler through the repository CLI rather than an internal durable queue.

Example usage

  • “Remember my passport number.”
  • “What is my home address?”
  • “Remind me tomorrow at 9am to submit the application.”
  • “Send this to @someone: dinner is ready.”
  • “Send this to the family group.”
  • “Set @someone to trusted.”

Commands

  • /help
  • /new
  • /model (admin only)

Testing

npm test
npm run test:nl
npm run test:live
just test

just serve starts the project-local OpenCode server with npm exec -- opencode serve --port 4096 before launching the bot.

The regression suite covers deterministic storage behavior and live natural-language flows, including schedule CRUD, user access-level changes, outbound delivery, persona-aware reply composition, and requester-timezone-aware time injection.

About

🤖 A 100% free personal memory integrated Telegram bot powered by OpenCode.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages