fn is_valid_slug(s: &str) -> bool {
let bytes = s.as_bytes();
if bytes.len() < 2 || bytes.len() > 64 {
return false;
}
let ok = |b: u8| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-';
if !ok(bytes[0]) || bytes[0] == b'-' {
return false;
}
if bytes[bytes.len() - 1] == b'-' {
return false;
}
bytes.iter().all(|&b| ok(b))
}
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
use super::ast::QueryParam;
pub const MAX_QUERIES_PER_NAMESPACE: usize = 100;
pub const MAX_QUERY_BODY_SIZE: usize = 8192;
pub const MAX_QUERY_PARAMS: usize = 10;
static QUERY_NAME_RE: std::sync::LazyLock<regex::Regex> =
std::sync::LazyLock::new(|| regex::Regex::new(r"^[a-zA-Z][a-zA-Z0-9 _-]{0,63}$").unwrap());
fn is_valid_agent_query_name(name: &str) -> bool {
let Some(rest) = name.strip_prefix("agent/") else {
return false;
};
let Some(slash) = rest.find('/') else {
return false;
};
let slug = &rest[..slash];
let suffix = &rest[slash + 1..];
if !is_valid_slug(slug) {
return false;
}
if suffix.is_empty() || suffix.len() > 16 {
return false;
}
suffix.bytes().all(|b| b.is_ascii_lowercase() || b == b'_')
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PersistedQuery {
pub body: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub params: Vec<QueryParam>,
#[serde(default)]
pub last_run_at: Option<u64>,
#[serde(default)]
pub updated_at: Option<u64>,
}
#[derive(Debug, Clone)]
pub struct QueryEntry {
pub body: String,
pub description: String,
pub params: Vec<QueryParam>,
pub last_run_at: Option<u64>,
pub updated_at: Option<u64>,
pub builtin: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryListEntry {
pub name: String,
pub description: String,
pub param_count: usize,
pub body_size: usize,
pub last_run_at: Option<u64>,
pub updated_at: Option<u64>,
pub builtin: bool,
}
#[derive(Debug)]
pub struct QueryRegistry {
queries: HashMap<String, QueryEntry>,
}
impl Default for QueryRegistry {
fn default() -> Self {
Self::new()
}
}
impl QueryRegistry {
pub fn new() -> Self {
let mut reg = Self {
queries: HashMap::new(),
};
reg.load_builtins();
reg
}
pub fn is_valid_name(name: &str) -> bool {
if name != name.trim() || name.contains(" ") {
return false;
}
if QUERY_NAME_RE.is_match(name) {
return true;
}
is_valid_agent_query_name(name)
}
pub fn register(
&mut self,
name: &str,
body: &str,
description: &str,
params: &[QueryParam],
) -> Result<(), String> {
self.register_with_last_run(name, body, description, params, None)
}
pub fn register_with_last_run(
&mut self,
name: &str,
body: &str,
description: &str,
params: &[QueryParam],
last_run_at: Option<u64>,
) -> Result<(), String> {
self.register_full(name, body, description, params, last_run_at, None)
}
pub fn register_full(
&mut self,
name: &str,
body: &str,
description: &str,
params: &[QueryParam],
last_run_at: Option<u64>,
updated_at: Option<u64>,
) -> Result<(), String> {
if !Self::is_valid_name(name) {
return Err(format!(
"invalid query name \"{name}\": must start with a letter, max 64 chars, only letters/digits/spaces/hyphens/underscores"
));
}
if body.len() > MAX_QUERY_BODY_SIZE {
return Err(format!(
"query body too large ({} bytes, max {})",
body.len(),
MAX_QUERY_BODY_SIZE
));
}
if params.len() > MAX_QUERY_PARAMS {
return Err(format!(
"too many parameters ({}, max {})",
params.len(),
MAX_QUERY_PARAMS
));
}
if let Some(existing) = self.queries.get(name) {
if existing.builtin {
return Err(format!("saved query \"{name}\" already exists"));
}
}
if self.queries.len() >= MAX_QUERIES_PER_NAMESPACE {
return Err(format!(
"too many saved queries ({}, max {})",
self.queries.len(),
MAX_QUERIES_PER_NAMESPACE
));
}
let ts = updated_at.unwrap_or_else(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
});
self.queries.insert(
name.to_string(),
QueryEntry {
body: body.to_string(),
description: description.to_string(),
params: params.to_vec(),
last_run_at,
updated_at: Some(ts),
builtin: false,
},
);
Ok(())
}
pub fn delete(&mut self, name: &str) -> Result<(), String> {
if let Some(entry) = self.queries.get(name) {
if entry.builtin {
return Err(format!("cannot delete built-in query \"{name}\""));
}
}
if self.queries.remove(name).is_none() {
return Err(format!("saved query \"{name}\" not found"));
}
Ok(())
}
pub fn is_builtin(&self, name: &str) -> bool {
self.queries.get(name).is_some_and(|e| e.builtin)
}
pub fn get(&self, name: &str) -> Option<&QueryEntry> {
self.queries.get(name)
}
pub fn list(&self) -> Vec<QueryListEntry> {
let mut entries: Vec<_> = self
.queries
.iter()
.map(|(name, entry)| QueryListEntry {
name: name.clone(),
description: entry.description.clone(),
param_count: entry.params.len(),
body_size: entry.body.len(),
last_run_at: entry.last_run_at,
updated_at: entry.updated_at,
builtin: entry.builtin,
})
.collect();
entries.sort_by_key(|b| std::cmp::Reverse(b.updated_at.unwrap_or(0)));
entries
}
pub fn len(&self) -> usize {
self.queries.len()
}
pub fn is_empty(&self) -> bool {
self.queries.is_empty()
}
fn insert_builtin(&mut self, name: &str, body: &str, description: &str, params: &[QueryParam]) {
self.queries.insert(
name.to_string(),
QueryEntry {
body: body.to_string(),
description: description.to_string(),
params: params.to_vec(),
last_run_at: None,
updated_at: None,
builtin: true,
},
);
}
fn load_builtins(&mut self) {
self.insert_builtin(
"Customer Support Context",
"ASSEMBLE \"Customer Support Context\" FROM\n\
\x20 preferences: (RECALL facts ABOUT $topic\n\
\x20 WHERE subject = $user_id\n\
\x20 AND relation IS PREFERENCE RECENT 10),\n\
\x20 history: (RECALL events ABOUT $topic\n\
\x20 WHERE subject = $user_id RECENT 20),\n\
\x20 knowledge: (RECALL facts ABOUT $topic\n\
\x20 WHERE subject = $user_id RECENT 15),\n\
\x20 tools: (RECALL tools ABOUT $topic\n\
\x20 WHERE user_id = $user_id RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, preference_enrichment, recency_weight(0.7)",
"Customer support agent context: topic-scoped user preferences, interaction history, knowledge, and recent actions",
&[
QueryParam { name: "user_id".to_string(), default: None },
QueryParam { name: "topic".to_string(), default: None },
],
);
self.insert_builtin(
"Conversation Resume",
"ASSEMBLE \"Conversation Resume\" FROM\n\
\x20 preferences: (RECALL facts WHERE subject = $user_id\n\
\x20 AND session_id = $session_id\n\
\x20 AND relation IS PREFERENCE RECENT 10),\n\
\x20 conversation:(RECALL events WHERE subject = $user_id\n\
\x20 AND session_id = $session_id RECENT 30),\n\
\x20 knowledge: (RECALL facts WHERE subject = $user_id\n\
\x20 AND session_id = $session_id RECENT 15),\n\
\x20 tools: (RECALL tools WHERE user_id = $user_id\n\
\x20 AND session_id = $session_id RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, recency_weight(0.8), annotate_relative_time",
"Resume a conversation: user preferences, session history, topic facts, and recent tools",
&[
QueryParam { name: "user_id".to_string(), default: None },
QueryParam { name: "session_id".to_string(), default: None },
],
);
self.insert_builtin(
"User Profile Briefing",
"ASSEMBLE \"User Profile\" FROM\n\
\x20 preferences: (RECALL facts WHERE subject = $user_id\n\
\x20 AND relation IS PREFERENCE RECENT 20),\n\
\x20 consents: (RECALL consents WHERE subject = $user_id RECENT 10),\n\
\x20 goals: (RECALL goals WHERE subject = $user_id\n\
\x20 AND goal_state = \"active\" RECENT 10),\n\
\x20 observations: (RECALL observations WHERE subject = $user_id\n\
\x20 RECENT 15)\n\
BUDGET 3000 tokens\n\
FORMAT markdown\n\
WITH dedup, preference_enrichment, subject_affinity(0.8)",
"User profile briefing: preferences, knowledge, active goals, and behavioral observations",
&[QueryParam { name: "user_id".to_string(), default: None }],
);
self.insert_builtin(
"Knowledge Researcher",
"ASSEMBLE \"Knowledge Research\" FROM\n\
\x20 evidence: (RECALL facts ABOUT $topic\n\
\x20 WHERE confidence >= 0.6 RECENT 25),\n\
\x20 analysis: (RECALL reasonings ABOUT $topic RECENT 10),\n\
\x20 field_notes:(RECALL observations ABOUT $topic RECENT 10),\n\
\x20 timeline: (RECALL events ABOUT $topic RECENT 10)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH contradiction_detection, dedup, score_breakdown",
"Deep research context: facts, reasoning chains, observations, and events with contradiction analysis",
&[QueryParam { name: "topic".to_string(), default: None }],
);
self.insert_builtin(
"Task Executor",
"ASSEMBLE \"Task Execution Context\" FROM\n\
\x20 goals: (RECALL goals WHERE subject = $user_id\n\
\x20 AND goal_state = \"active\" RECENT 10),\n\
\x20 workflows: (RECALL workflows WHERE subject = $user_id RECENT 5),\n\
\x20 tools: (RECALL tools WHERE user_id = $user_id RECENT 20),\n\
\x20 errors: (RECALL tools WHERE user_id = $user_id\n\
\x20 AND is_error = true RECENT 10),\n\
\x20 state: (RECALL states WHERE subject = $user_id RECENT 5),\n\
\x20 constraints:(RECALL facts WHERE subject = $user_id\n\
\x20 AND confidence >= 0.5 RECENT 10)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH conflict_resolution, dedup, recency_weight(0.8)",
"Task execution context: goals, workflows, tools, errors, state, and constraints for agentic task runners",
&[QueryParam { name: "user_id".to_string(), default: None }],
);
self.insert_builtin(
"Meeting Debrief",
"ASSEMBLE \"Meeting Debrief\" FROM\n\
\x20 conversation:(RECALL events WHERE subject = $user_id\n\
\x20 AND session_id = $session_id RECENT 50),\n\
\x20 decisions: (RECALL consensuses WHERE subject = $user_id\n\
\x20 AND session_id = $session_id RECENT 10),\n\
\x20 action_items:(RECALL tools WHERE user_id = $user_id\n\
\x20 AND session_id = $session_id RECENT 15),\n\
\x20 goals: (RECALL goals WHERE subject = $user_id\n\
\x20 AND session_id = $session_id RECENT 10)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH dedup, annotate_relative_time, session_affinity(0.9)",
"Meeting debrief: conversation events, decisions, action items, and goals from a session",
&[
QueryParam { name: "user_id".to_string(), default: None },
QueryParam { name: "session_id".to_string(), default: None },
],
);
self.insert_builtin(
"Recommendation Context",
"ASSEMBLE \"Recommendation Context\" FROM\n\
\x20 preferences: (RECALL facts ABOUT $topic\n\
\x20 WHERE subject = $user_id\n\
\x20 AND relation IS PREFERENCE RECENT 20),\n\
\x20 interactions:(RECALL events ABOUT $topic\n\
\x20 WHERE subject = $user_id RECENT 20),\n\
\x20 observations:(RECALL observations ABOUT $topic\n\
\x20 WHERE subject = $user_id RECENT 15),\n\
\x20 knowledge: (RECALL facts ABOUT $topic\n\
\x20 WHERE subject = $user_id AND confidence >= 0.6 RECENT 15)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH preference_enrichment, diversity(0.5), subject_affinity(0.8), dedup, recency_weight(0.6)",
"Recommendation agent context: topic-scoped user preferences, interactions, observations, and knowledge",
&[
QueryParam { name: "user_id".to_string(), default: None },
QueryParam { name: "topic".to_string(), default: None },
],
);
self.insert_builtin(
"Compliance Audit",
"ASSEMBLE \"Compliance Audit\" FROM\n\
\x20 consents: (RECALL consents WHERE subject = $user_id RECENT 20),\n\
\x20 data_activity: (RECALL events WHERE subject = $user_id RECENT 20),\n\
\x20 audit_notes: (RECALL observations WHERE subject = $user_id\n\
\x20 RECENT 15),\n\
\x20 permissions: (RECALL facts WHERE subject = $user_id\n\
\x20 AND relation IS PERMISSION RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH provenance, include_sources, annotate_relative_time, dedup",
"Compliance audit context: consents, data events, observations, and permissions for a user",
&[QueryParam { name: "user_id".to_string(), default: None }],
);
self.insert_builtin(
"Creative Collaborator",
"ASSEMBLE \"Creative Context\" FROM\n\
\x20 world: (RECALL facts ABOUT $topic RECENT 25),\n\
\x20 plot: (RECALL events ABOUT $topic RECENT 20),\n\
\x20 state: (RECALL states ABOUT $topic RECENT 5),\n\
\x20 goals: (RECALL goals ABOUT $topic\n\
\x20 WHERE goal_state = \"active\" RECENT 10),\n\
\x20 reasoning: (RECALL reasonings ABOUT $topic RECENT 10)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH conflict_resolution, contradiction_detection, dedup",
"Creative collaborator context: world facts, plot events, story state, narrative goals, and reasoning",
&[QueryParam { name: "topic".to_string(), default: None }],
);
self.insert_builtin(
"Scoped Namespace Context",
"ASSEMBLE \"Namespace Context\" FROM\n\
\x20 knowledge: (RECALL facts WHERE namespace = $namespace RECENT 20),\n\
\x20 activity: (RECALL events WHERE namespace = $namespace RECENT 15),\n\
\x20 operations: (RECALL tools WHERE namespace = $namespace RECENT 10),\n\
\x20 snapshots: (RECALL states WHERE namespace = $namespace RECENT 5)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, conflict_resolution, recency_weight(0.7)",
"Scoped namespace context: facts, events, tools, and state filtered by namespace for multi-tenant agents",
&[QueryParam { name: "namespace".to_string(), default: None }],
);
self.insert_builtin(
"agent_context",
"ASSEMBLE \"Agent Context\" FROM\n\
\x20 goal: (RECALL goals WHERE namespace = $def_ns RECENT 1),\n\
\x20 workflow: (RECALL workflows WHERE namespace = $def_ns RECENT 1),\n\
\x20 tools: (RECALL tools WHERE namespace = $def_ns LIMIT 20),\n\
\x20 history: (RECALL events WHERE session_id = $session_id RECENT 12),\n\
\x20 user_facts: (RECALL facts ABOUT $query RECENT 8)\n\
BUDGET 4000 tokens\n\
FORMAT sml\n\
WITH dedup, conflict_resolution, rerank, provenance, session_affinity(0.9), recency_weight(0.7), min_score(0.55)",
"Default harness runtime context: harness definition (goal/workflow/tools), recent conversation Events, and rerank-filtered user facts scoped to the active query.",
&[
QueryParam { name: "user".to_string(), default: None },
QueryParam { name: "def_ns".to_string(), default: None },
QueryParam { name: "query".to_string(), default: None },
QueryParam { name: "session_id".to_string(), default: None },
],
);
self.insert_builtin(
"Account 360 Context",
"ASSEMBLE \"Account 360\" FROM\n\
\x20 account: (RECALL states WHERE subject = $account_id RECENT 1),\n\
\x20 contacts: (RECALL states ABOUT $query\n\
\x20 WHERE tags CONTAINS \"account\" AND subject = $account_id RECENT 10),\n\
\x20 interactions: (RECALL events WHERE subject = $account_id RECENT 20),\n\
\x20 threads: (RECALL states ABOUT $query\n\
\x20 WHERE tags CONTAINS \"thread\" AND subject = $account_id RECENT 10)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH dedup, recency_weight(0.8), provenance, rerank, min_score(0.4)",
"Account 360 context: latest account state, contacts, interactions, and open threads for a named account",
&[
QueryParam { name: "account_id".to_string(), default: None },
QueryParam { name: "query".to_string(), default: None },
],
);
self.insert_builtin(
"Meeting Context",
"ASSEMBLE \"Meeting Context\" FROM\n\
\x20 meeting: (RECALL events WHERE subject = $meeting_id RECENT 1),\n\
\x20 decisions: (RECALL states WHERE subject = $meeting_id RECENT 20),\n\
\x20 actions: (RECALL goals WHERE subject = $meeting_id\n\
\x20 AND goal_state = \"active\" RECENT 20),\n\
\x20 topics: (RECALL observations ABOUT $query\n\
\x20 WHERE subject = $meeting_id RECENT 15)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH dedup, recency_weight(0.7), provenance, rerank",
"Meeting context: meeting event, decisions, active action items, and discussion topics",
&[
QueryParam {
name: "meeting_id".to_string(),
default: None,
},
QueryParam {
name: "query".to_string(),
default: None,
},
],
);
self.insert_builtin(
"Meeting Cross Query",
"ASSEMBLE \"Meeting Search\" FROM\n\
\x20 decisions: (RECALL states ABOUT $query RECENT 25),\n\
\x20 actions: (RECALL goals ABOUT $query\n\
\x20 WHERE goal_state = \"active\" RECENT 15),\n\
\x20 meetings: (RECALL events ABOUT $query RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, contradiction_detection, provenance, rerank, min_score(0.5)",
"Cross-meeting search: decisions, active goals, and meeting events matching a query",
&[
QueryParam {
name: "user".to_string(),
default: None,
},
QueryParam {
name: "query".to_string(),
default: None,
},
],
);
self.insert_builtin(
"Support CoPilot Context",
"ASSEMBLE \"Support Context\" FROM\n\
\x20 kb_articles: (RECALL facts ABOUT $query\n\
\x20 WHERE relation = \"documents\" RECENT 15),\n\
\x20 resolved: (RECALL events ABOUT $query\n\
\x20 WHERE tags CONTAINS \"resolved\" RECENT 10),\n\
\x20 runbooks: (RECALL workflows ABOUT $query RECENT 5)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH dedup, recency_weight(0.6), provenance, rerank, score_breakdown, min_score(0.45)",
"Support co-pilot context: KB articles, resolved tickets, and runbooks for a support query",
&[
QueryParam { name: "query".to_string(), default: None },
],
);
self.insert_builtin(
"Sales Playbook Context",
"ASSEMBLE \"Sales Playbook\" FROM\n\
\x20 competitor: (RECALL states ABOUT $competitor RECENT 3),\n\
\x20 objections: (RECALL facts ABOUT $query\n\
\x20 WHERE relation = \"countered-by\" RECENT 15),\n\
\x20 cases: (RECALL facts ABOUT $industry\n\
\x20 WHERE relation = \"demonstrated\" RECENT 10),\n\
\x20 pricing: (RECALL states ABOUT $query\n\
\x20 WHERE tags CONTAINS \"pricing\" RECENT 5)\n\
BUDGET 5000 tokens\n\
FORMAT markdown\n\
WITH dedup, provenance, rerank, diversity(0.5), min_score(0.4)",
"Sales playbook context: competitor profiles, objection counters, case studies, and pricing for battlecard generation",
&[
QueryParam { name: "competitor".to_string(), default: None },
QueryParam { name: "industry".to_string(), default: None },
QueryParam { name: "query".to_string(), default: None },
],
);
self.insert_builtin(
"Policy Library Context",
"ASSEMBLE \"Policy Context\" FROM\n\
\x20 policies: (RECALL states ABOUT $query\n\
\x20 WHERE tags CONTAINS \"active\" RECENT 10),\n\
\x20 exceptions: (RECALL consents WHERE subject = $user RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, provenance, rerank, include_sources, min_score(0.5)",
"Policy library context: active policies and user-scoped exceptions for policy questions",
&[
QueryParam { name: "user".to_string(), default: None },
QueryParam { name: "query".to_string(), default: None },
],
);
self.insert_builtin(
"RFP Questionnaire Context",
"ASSEMBLE \"RFP Context\" FROM\n\
\x20 qa_pairs: (RECALL facts ABOUT $query\n\
\x20 WHERE relation = \"answered-by\" RECENT 15),\n\
\x20 controls: (RECALL states ABOUT $query\n\
\x20 WHERE tags CONTAINS \"control\" RECENT 10)\n\
BUDGET 4000 tokens\n\
FORMAT markdown\n\
WITH dedup, provenance, rerank, score_breakdown, recency_weight(0.6), min_score(0.45)",
"RFP questionnaire context: existing QA pairs and compliance controls for questionnaire answering",
&[
QueryParam { name: "query".to_string(), default: None },
],
);
}
pub fn apply_timestamps(
&mut self,
name: &str,
last_run_at: Option<u64>,
updated_at: Option<u64>,
) {
if let Some(entry) = self.queries.get_mut(name) {
if last_run_at.is_some() {
entry.last_run_at = last_run_at;
}
if updated_at.is_some() && entry.updated_at.is_none() {
entry.updated_at = updated_at;
}
}
}
pub fn update_last_run(&mut self, name: &str) -> Result<(), String> {
let entry = self
.queries
.get_mut(name)
.ok_or_else(|| format!("saved query \"{name}\" not found"))?;
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
entry.last_run_at = Some(now);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
const BUILTIN_COUNT: usize = 18;
const BUILTIN_NAMES: [&str; BUILTIN_COUNT] = [
"Customer Support Context",
"Conversation Resume",
"User Profile Briefing",
"Knowledge Researcher",
"Task Executor",
"Meeting Debrief",
"Recommendation Context",
"Compliance Audit",
"Creative Collaborator",
"Scoped Namespace Context",
"agent_context",
"Account 360 Context",
"Meeting Context",
"Meeting Cross Query",
"Support CoPilot Context",
"Sales Playbook Context",
"Policy Library Context",
"RFP Questionnaire Context",
];
#[test]
fn test_valid_names() {
assert!(QueryRegistry::is_valid_name("abc"));
assert!(QueryRegistry::is_valid_name("a_b_c"));
assert!(QueryRegistry::is_valid_name("query123"));
assert!(QueryRegistry::is_valid_name("ABC"));
assert!(QueryRegistry::is_valid_name("a-b-c"));
assert!(QueryRegistry::is_valid_name("Customer Support Context"));
assert!(QueryRegistry::is_valid_name("My Query-1"));
assert!(!QueryRegistry::is_valid_name(""));
assert!(!QueryRegistry::is_valid_name("123abc"));
assert!(!QueryRegistry::is_valid_name("_starts_with_underscore"));
assert!(!QueryRegistry::is_valid_name("-starts-with-hyphen"));
assert!(!QueryRegistry::is_valid_name("trailing space "));
assert!(!QueryRegistry::is_valid_name(" leading space"));
assert!(!QueryRegistry::is_valid_name("double space"));
}
#[test]
fn test_agent_namespaced_names() {
assert!(QueryRegistry::is_valid_name("agent/support/ctx"));
assert!(QueryRegistry::is_valid_name("agent/bot-v2/ctx"));
assert!(QueryRegistry::is_valid_name("agent/support/tool_summary"));
assert!(!QueryRegistry::is_valid_name("agent/")); assert!(!QueryRegistry::is_valid_name("agent/support")); assert!(!QueryRegistry::is_valid_name("agent/support/")); assert!(!QueryRegistry::is_valid_name("agent/SUPPORT/ctx")); assert!(!QueryRegistry::is_valid_name("agent/-bad/ctx")); assert!(!QueryRegistry::is_valid_name("agent/support/CTX")); assert!(!QueryRegistry::is_valid_name("agents/support/ctx")); assert!(!QueryRegistry::is_valid_name("agent/support/ctx/extra")); assert!(!QueryRegistry::is_valid_name(&format!(
"agent/support/{}",
"x".repeat(17)
))); }
#[test]
fn test_agent_context_builtin_present() {
let reg = QueryRegistry::new();
let agent_ctx = reg.get("agent_context").expect("agent_context builtin");
assert!(agent_ctx.builtin);
let names: Vec<_> = agent_ctx.params.iter().map(|p| p.name.as_str()).collect();
assert_eq!(names, vec!["user", "def_ns", "query", "session_id"]);
}
#[test]
fn test_builtins_loaded() {
let reg = QueryRegistry::new();
assert_eq!(reg.len(), BUILTIN_COUNT);
for name in BUILTIN_NAMES {
let entry = reg.get(name).expect(name);
assert!(entry.builtin);
assert!(!entry.body.is_empty());
}
}
#[test]
fn test_builtin_has_params() {
let reg = QueryRegistry::new();
let support = reg.get("Customer Support Context").unwrap();
assert_eq!(support.params.len(), 2);
assert_eq!(support.params[0].name, "user_id");
assert!(support.params[0].default.is_none()); assert_eq!(support.params[1].name, "topic");
let executor = reg.get("Task Executor").unwrap();
assert_eq!(executor.params.len(), 1);
assert_eq!(executor.params[0].name, "user_id");
}
#[test]
fn test_cannot_delete_builtin() {
let mut reg = QueryRegistry::new();
let err = reg.delete("Task Executor").unwrap_err();
assert!(err.contains("cannot delete built-in"));
}
#[test]
fn test_cannot_overwrite_builtin() {
let mut reg = QueryRegistry::new();
let err = reg
.register("Task Executor", "RECALL facts", "", &[])
.unwrap_err();
assert!(err.contains("already exists"));
}
#[test]
fn test_is_builtin() {
let mut reg = QueryRegistry::new();
assert!(reg.is_builtin("Task Executor"));
assert!(!reg.is_builtin("nonexistent"));
reg.register("custom", "RECALL facts", "", &[]).unwrap();
assert!(!reg.is_builtin("custom"));
}
#[test]
fn test_register_and_get() {
let mut reg = QueryRegistry::new();
reg.register("test_query", "RECALL facts RECENT 10", "A test", &[])
.unwrap();
let entry = reg.get("test_query").unwrap();
assert_eq!(entry.body, "RECALL facts RECENT 10");
assert_eq!(entry.description, "A test");
assert!(!entry.builtin);
}
#[test]
fn test_duplicate_name_upserts() {
let mut reg = QueryRegistry::new();
reg.register("q", "RECALL facts", "", &[]).unwrap();
reg.register("q", "RECALL events", "", &[]).unwrap(); let entry = reg.get("q").unwrap();
assert_eq!(entry.body, "RECALL events"); }
#[test]
fn test_delete() {
let mut reg = QueryRegistry::new();
reg.register("q", "RECALL facts", "", &[]).unwrap();
reg.delete("q").unwrap();
assert!(reg.get("q").is_none());
}
#[test]
fn test_delete_not_found() {
let reg = QueryRegistry::new();
let mut reg = reg;
assert!(reg.delete("nonexistent").is_err());
}
#[test]
fn test_body_too_large() {
let mut reg = QueryRegistry::new();
let body = "x".repeat(MAX_QUERY_BODY_SIZE + 1);
assert!(reg.register("q", &body, "", &[]).is_err());
}
#[test]
fn test_too_many_params() {
let mut reg = QueryRegistry::new();
let params: Vec<QueryParam> = (0..11)
.map(|i| QueryParam {
name: format!("p{i}"),
default: None,
})
.collect();
assert!(reg.register("q", "RECALL facts", "", ¶ms).is_err());
}
#[test]
fn test_max_queries_limit() {
let mut reg = QueryRegistry::new();
for i in 0..(MAX_QUERIES_PER_NAMESPACE - BUILTIN_COUNT) {
let name = format!("q{:03}", i);
reg.register(&name, "RECALL facts", "", &[]).unwrap();
}
assert!(reg.register("overflow", "RECALL facts", "", &[]).is_err());
}
#[test]
fn test_list_sorted_includes_builtins() {
let mut reg = QueryRegistry::new();
reg.register("zebra", "RECALL facts", "", &[]).unwrap();
reg.register("alpha", "RECALL events", "desc", &[]).unwrap();
let list = reg.list();
assert_eq!(list.len(), BUILTIN_COUNT + 2);
let ts: Vec<u64> = list.iter().map(|e| e.updated_at.unwrap_or(0)).collect();
assert!(
ts.windows(2).all(|w| w[0] >= w[1]),
"list is not sorted by updated_at DESC: {:?}",
ts
);
let builtin_count = list.iter().filter(|e| e.builtin).count();
assert_eq!(builtin_count, BUILTIN_COUNT);
}
#[test]
fn test_all_builtins_parse() {
use crate::parser::parse;
let reg = QueryRegistry::new();
for name in BUILTIN_NAMES {
let entry = reg.get(name).unwrap();
let mut body = entry.body.clone();
for param in &entry.params {
body = body.replace(
&format!("${}", param.name),
&format!("\"test_{}\"", param.name),
);
}
let result = parse(&body);
assert!(
result.is_ok(),
"built-in query \"{name}\" failed to parse: {:?}\n--- body ---\n{}",
result.err(),
body,
);
}
}
#[test]
fn test_new_builtin_params() {
let reg = QueryRegistry::new();
let q = reg.get("Customer Support Context").unwrap();
assert_eq!(q.params.len(), 2);
assert_eq!(q.params[0].name, "user_id");
assert_eq!(q.params[1].name, "topic");
let q = reg.get("Conversation Resume").unwrap();
assert_eq!(q.params.len(), 2);
assert_eq!(q.params[0].name, "user_id");
assert_eq!(q.params[1].name, "session_id");
let q = reg.get("Task Executor").unwrap();
assert_eq!(q.params.len(), 1);
assert_eq!(q.params[0].name, "user_id");
let q = reg.get("Meeting Debrief").unwrap();
assert_eq!(q.params.len(), 2);
assert_eq!(q.params[0].name, "user_id");
assert_eq!(q.params[1].name, "session_id");
let q = reg.get("Scoped Namespace Context").unwrap();
assert_eq!(q.params.len(), 1);
assert_eq!(q.params[0].name, "namespace");
}
}