KeiSeiKit-1.0/_primitives/_rust/kei-buddy
Parfii-bot fb7c1bf859 feat(kei-buddy): wire kei-chat-store — log every user/bot message with FTS5
After-Ready conversation was going to /dev/null. With this change every
inbound Telegram text + every bot response is persisted to a SQLite +
FTS5 archive via the existing kei-chat-store primitive (no new crate).

Each Telegram chat_id maps 1:1 to a kei-chat-store session
(project="kei-buddy", title="tg-<chat_id>", model="telegram"). Cache
prevents per-message session lookups.

New file:
  * src/chat_log.rs (198 LOC) — ChatLog adapter wrapping
    kei_chat_store::Store + a chat_id→session_id Mutex cache.
    API: from_path / from_memory / ensure_session / log_user /
    log_bot / search(query, chat_id?, limit). Errors map to
    BuddyError::Memory and never propagate from on_event — chat-log
    failure is logged but does not block the conversation.

Modified:
  * Cargo.toml — kei-chat-store path dep added.
  * src/lib.rs — pub mod chat_log + re-export ChatLog.
  * src/serve.rs — BuddyContext gains Arc<ChatLog>;
    process_text calls log_user before handle_step + log_bot after
    send_message; ServeConfig gains chat_log_db_path.
  * src/bin/kei-buddy.rs — KEI_BUDDY_CHAT_LOG_PATH env
    (default ./kei-buddy-chat.db); migrate subcommand applies the
    chat-store schema alongside buddy_state schema.

Tests (3 new in src/chat_log.rs, all pass):
  * log_user_creates_session_and_message
  * log_bot_uses_same_session_as_log_user
  * different_chats_get_different_sessions

Verify-before-commit:
  * cargo check -p kei-buddy (default): PASS
  * cargo check -p kei-buddy --features extractor-openai: PASS
  * cargo test -p kei-buddy --lib: 23 passed / 0 failed
    (was 20 before this commit; 3 new ChatLog tests)

NOT deployed — user is in active conversation with the live bot.
Will roll forward when user signals readiness.
2026-05-12 15:51:24 +08:00
..
src feat(kei-buddy): wire kei-chat-store — log every user/bot message with FTS5 2026-05-12 15:51:24 +08:00
Cargo.toml feat(kei-buddy): wire kei-chat-store — log every user/bot message with FTS5 2026-05-12 15:51:24 +08:00
README.md feat(kei-buddy): functional MVP — store + state-machine port + serve binary 2026-05-12 14:21:33 +08:00

kei-buddy

Maturity: concept / scaffold — no business logic yet.

Purpose

kei-buddy is the runtime crate that composes existing KeiSeiKit primitives (kei-pet, kei-memory-sqlite, kei-cortex, kei-notify-telegram) into a personal-assistant Telegram bot called KeiBuddy.

On first contact the bot walks the user through an 11-state onboarding flow: name, tone, interests, hobbies, per-topic decomposition (specifics → now-or-later → research preference → source selection), and digest schedule. After onboarding the bot enters ongoing conversation mode, drawing on the stored persona and memory.

This crate provides the state-machine enum and skeleton driver. The onboarding FSM is ported from keisei-marketplace/src/lib/keibuddy/chat-onboard.ts.

Status

Scaffold only. The OnboardState enum and TransitionInput struct are defined. All transition logic is stubbed (next() returns self.clone()). The binary entry point prints a placeholder message and exits 0.

Running

Environment variables

Variable Required Default Description
TELEGRAM_BOT_TOKEN yes (serve) Bot token from @BotFather
TELEGRAM_WEBHOOK_SECRET yes (serve) Secret token for webhook verification
KEI_BUDDY_PORT no 8080 HTTP port to bind
KEI_BUDDY_DB_PATH no ./kei-buddy.db SQLite database path
OPENAI_API_KEY no Enables OpenAiExtractor when set (requires extractor-openai feature)

Subcommands

# Apply schema (idempotent; run once before first serve)
kei-buddy migrate

# Register the webhook URL with Telegram
kei-buddy webhook-set https://your-domain.com/webhook

# Start the HTTP server
kei-buddy serve

# Remove the registered webhook (revert to polling)
kei-buddy webhook-delete

Example systemd unit

[Unit]
Description=KeiBuddy Telegram bot
After=network.target

[Service]
EnvironmentFile=/etc/kei-buddy/env
ExecStart=/usr/local/bin/kei-buddy serve
Restart=on-failure
User=keisei

[Install]
WantedBy=multi-user.target

Roadmap

  • OpenAiExtractor wiring — pass real OPENAI_API_KEY to OpenAiExtractor in serve.rs when feature enabled.
  • Persona binding — read persona manifest via kei-pet; apply tone overlay to outgoing replies.
  • Digest scheduling — wire kei-cron-scheduler for morning/evening digest delivery.