KeiSeiKit-1.0/_primitives/_rust/kei-crossdomain/src/auto_link.rs
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

60 lines
2 KiB
Rust

//! Auto-link heuristic — proposes edges based on URI-name component matching.
//! No-ML: intersect the last path segments (case-insensitive, normalized).
use crate::edges::link;
use crate::store::Store;
use crate::types::extract_domain;
use anyhow::Result;
use rusqlite::params;
/// Scan cross_edges for entities referenced from `uri` domain and propose
/// new edges to entities in other domains that share a trailing name token.
pub fn auto_link(store: &Store, uri: &str) -> Result<usize> {
let tail = tail_token(uri);
if tail.is_empty() {
return Ok(0);
}
let src_domain = extract_domain(uri);
let candidates = collect_candidates(store, uri, src_domain, &tail)?;
commit_candidates(store, uri, &candidates)
}
fn collect_candidates(store: &Store, uri: &str, src_domain: &str, tail: &str)
-> Result<Vec<String>>
{
let mut candidates: Vec<String> = Vec::new();
let mut stmt = store.conn().prepare(
"SELECT DISTINCT to_uri FROM cross_edges
UNION SELECT DISTINCT from_uri FROM cross_edges",
)?;
let rows = stmt.query_map([], |r| r.get::<_, String>(0))?;
for row in rows {
let u = row?;
if u == uri || extract_domain(&u) == src_domain { continue; }
if tail_token(&u).eq_ignore_ascii_case(tail) {
candidates.push(u);
}
}
Ok(candidates)
}
fn commit_candidates(store: &Store, uri: &str, candidates: &[String]) -> Result<usize> {
let mut added = 0;
for c in candidates {
if edge_exists(store, uri, c)? { continue; }
link(store, uri, c, "auto_related", 0.5, "E5")?;
added += 1;
}
Ok(added)
}
fn edge_exists(store: &Store, from: &str, to: &str) -> Result<bool> {
let n: i64 = store.conn().query_row(
"SELECT COUNT(*) FROM cross_edges WHERE from_uri=?1 AND to_uri=?2",
params![from, to], |r| r.get(0))?;
Ok(n > 0)
}
fn tail_token(uri: &str) -> String {
uri.rsplit('/').next().unwrap_or("").to_lowercase()
}