Two parallel atoms in one commit. Both reuse existing KeiSeiKit
primitives (zero new crates) per RULE feedback_inventory_before_decompose.
## src/contacts.rs (200 LOC, +4 tests)
Adapter over kei-social-store. Address book + interaction log + relationship
graph for shared connections.
API:
* Contacts::from_path / from_memory
* add_contact / get_contact / search_contacts
* log_meet(person_id, target_id, channel, note) / interactions_for
* relationship_graph — returns Vec<Pair>, the kei-social-store output
* common_connections(a, b) — post-filters relationship_graph to find
target_ids that appear in pairs with BOTH a and b. This is the
"у нас с Денисом общий друг X" feature.
Pattern: Arc<Mutex<kei_social_store::Store>> + tokio::spawn_blocking,
mirroring chat_log.rs. Errors map to BuddyError::Memory.
Tests: add_and_get_contact_roundtrip / search_contacts_finds_by_name /
log_meet_and_list_interactions / common_connections_finds_shared_target.
## src/topics.rs (200 LOC, +4 tests)
Adapter over kei-sage. Topics + digest notes + FTS5 search. Each topic
is a sage Unit{unit_type="buddy_topic", category="kei-buddy",
source_path="kei-buddy/chat-{chat_id}/topic/{slug}"}. Digests are
Unit{unit_type="buddy_digest"} linked via add_edge(topic→digest,
edge_type="digest_for").
API:
* Topics::from_path / from_memory
* add_topic(chat_id, slug, title, content) — idempotent via path lookup
* add_digest(chat_id, topic_slug, timestamp, content) — creates Unit +
edge
* search(query, limit) — fts_search over all kei-buddy units
* digests_for(chat_id, topic_slug) — follows outgoing edges
* list_topics(chat_id) — raw SELECT scoped by source_path LIKE prefix
Tests: add_topic_then_search_finds_it / add_topic_is_idempotent /
add_digest_creates_edge_and_dest / list_topics_scopes_per_chat.
## Dependencies added
kei-social-store + kei-sage as local path deps. Both already in workspace,
no new external crates.
## Verify-before-commit
* cargo check -p kei-buddy: PASS
* cargo test -p kei-buddy --lib: 31/0 (was 23, +4 contacts +4 topics)
Net change: 4 files touched, ~400 LOC added across the two adapters.
NOT deployed. User still in active bot conversation.
57 lines
1.9 KiB
TOML
57 lines
1.9 KiB
TOML
[package]
|
|
name = "kei-buddy"
|
|
version = "0.1.0"
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
description = "KeiBuddy personal-assistant Telegram bot — onboarding state-machine + skeleton driver. Concept-level scaffold."
|
|
authors.workspace = true
|
|
license.workspace = true
|
|
|
|
[[bin]]
|
|
name = "kei-buddy"
|
|
path = "src/bin/kei-buddy.rs"
|
|
|
|
[lib]
|
|
name = "kei_buddy"
|
|
path = "src/lib.rs"
|
|
|
|
[dependencies]
|
|
serde = { workspace = true, features = ["derive"] }
|
|
serde_json = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "net"] }
|
|
tracing = "0.1"
|
|
clap = { workspace = true, features = ["derive"] }
|
|
async-trait = { workspace = true }
|
|
rusqlite = { workspace = true }
|
|
reqwest = { workspace = true }
|
|
anyhow = { workspace = true }
|
|
kei-memory-sqlite = { path = "../kei-memory-sqlite" }
|
|
kei-chat-store = { path = "../kei-chat-store" }
|
|
kei-social-store = { path = "../kei-social-store" }
|
|
kei-sage = { path = "../kei-sage" }
|
|
chrono = { workspace = true }
|
|
|
|
# serve feature deps
|
|
axum = { version = "0.7", features = ["json", "http1", "tokio"], optional = true }
|
|
kei-telegram-webhook = { path = "../kei-telegram-webhook", optional = true }
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true }
|
|
|
|
[dev-dependencies]
|
|
wiremock = { workspace = true }
|
|
tokio = { workspace = true }
|
|
|
|
[features]
|
|
default = ["serve"]
|
|
# HTTP server — axum router + webhook handler + Telegram send_message.
|
|
serve = ["axum", "kei-telegram-webhook", "tracing-subscriber"]
|
|
# Enables OpenAiExtractor — real HTTP to LiteLLM proxy using reqwest.
|
|
# Off by default; tests use MockExtractor which has no extra deps.
|
|
extractor-openai = []
|
|
# future: pulls in kei-notify-telegram for real Telegram transport
|
|
telegram = []
|
|
|
|
[package.metadata.keisei]
|
|
maturity = "concept"
|
|
description = "KeiBuddy personal-assistant: onboarding FSM + bot driver scaffold"
|
|
authors = ["Denis Parfionovich <parfionovich@keilab.io>"]
|