use std::collections::HashSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(super) enum Intent {
Execution,
Delegation,
Cron,
FileDistribution,
FolderScan,
RandomToolUse,
ModelIdentity,
CurrentEvents,
Introspection,
Acknowledgement,
ProviderInventory,
PersonalityProfile,
CapabilitySummary,
WalletAddressScan,
ImageCountScan,
MarkdownCountScan,
ObsidianInsights,
EmailTriage,
LiteraryQuoteContext,
Contradiction,
ShortFollowup,
ReactiveSarcasm,
}
pub(super) enum IntentMatcher {
AnyKeyword(&'static [&'static str]),
AllGroups(&'static [&'static [&'static str]]),
Custom(fn(&str) -> bool),
}
impl IntentMatcher {
fn matches(&self, lower: &str) -> bool {
match self {
Self::AnyKeyword(keywords) => keywords.iter().any(|k| lower.contains(k)),
Self::AllGroups(groups) => groups
.iter()
.all(|group| group.iter().any(|k| lower.contains(k))),
Self::Custom(f) => f(lower),
}
}
}
pub(super) struct IntentDescriptor {
pub intent: Intent,
pub priority: u8,
pub bypasses_cache: bool,
pub matcher: IntentMatcher,
}
pub(super) struct IntentRegistry {
descriptors: Vec<IntentDescriptor>,
}
impl IntentRegistry {
pub fn default_registry() -> Self {
Self {
descriptors: vec![
IntentDescriptor {
intent: Intent::Execution,
priority: 10,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(EXECUTION_KEYWORDS),
},
IntentDescriptor {
intent: Intent::FileDistribution,
priority: 37,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(&["file distribution"]),
},
IntentDescriptor {
intent: Intent::ModelIdentity,
priority: 80,
bypasses_cache: false,
matcher: IntentMatcher::AnyKeyword(MODEL_IDENTITY_KEYWORDS),
},
IntentDescriptor {
intent: Intent::CurrentEvents,
priority: 65,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(CURRENT_EVENTS_KEYWORDS),
},
IntentDescriptor {
intent: Intent::Introspection,
priority: 60,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(INTROSPECTION_KEYWORDS),
},
IntentDescriptor {
intent: Intent::ProviderInventory,
priority: 75,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(PROVIDER_INVENTORY_KEYWORDS),
},
IntentDescriptor {
intent: Intent::CapabilitySummary,
priority: 71,
bypasses_cache: true,
matcher: IntentMatcher::AnyKeyword(CAPABILITY_SUMMARY_KEYWORDS),
},
IntentDescriptor {
intent: Intent::FolderScan,
priority: 39,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(FOLDER_SCAN_GROUPS),
},
IntentDescriptor {
intent: Intent::Acknowledgement,
priority: 85,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(ACKNOWLEDGEMENT_GROUPS),
},
IntentDescriptor {
intent: Intent::WalletAddressScan,
priority: 45,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(WALLET_SCAN_GROUPS),
},
IntentDescriptor {
intent: Intent::ImageCountScan,
priority: 43,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(IMAGE_COUNT_GROUPS),
},
IntentDescriptor {
intent: Intent::MarkdownCountScan,
priority: 41,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(MARKDOWN_COUNT_GROUPS),
},
IntentDescriptor {
intent: Intent::ObsidianInsights,
priority: 35,
bypasses_cache: true,
matcher: IntentMatcher::AllGroups(OBSIDIAN_INSIGHTS_GROUPS),
},
IntentDescriptor {
intent: Intent::Delegation,
priority: 55,
bypasses_cache: false,
matcher: IntentMatcher::Custom(match_delegation),
},
IntentDescriptor {
intent: Intent::Cron,
priority: 53,
bypasses_cache: false,
matcher: IntentMatcher::Custom(match_cron),
},
IntentDescriptor {
intent: Intent::RandomToolUse,
priority: 50,
bypasses_cache: true,
matcher: IntentMatcher::Custom(match_random_tool_use),
},
IntentDescriptor {
intent: Intent::PersonalityProfile,
priority: 73,
bypasses_cache: true,
matcher: IntentMatcher::Custom(match_personality_profile),
},
IntentDescriptor {
intent: Intent::EmailTriage,
priority: 63,
bypasses_cache: true,
matcher: IntentMatcher::Custom(match_email_triage),
},
IntentDescriptor {
intent: Intent::LiteraryQuoteContext,
priority: 30,
bypasses_cache: true,
matcher: IntentMatcher::Custom(match_literary_quote_context),
},
IntentDescriptor {
intent: Intent::Contradiction,
priority: 95,
bypasses_cache: false,
matcher: IntentMatcher::Custom(match_contradiction),
},
IntentDescriptor {
intent: Intent::ShortFollowup,
priority: 93,
bypasses_cache: false,
matcher: IntentMatcher::Custom(match_short_followup),
},
IntentDescriptor {
intent: Intent::ReactiveSarcasm,
priority: 91,
bypasses_cache: false,
matcher: IntentMatcher::Custom(match_reactive_sarcasm),
},
],
}
}
pub fn classify(&self, prompt: &str) -> Vec<Intent> {
let lower = prompt.to_ascii_lowercase();
let mut matches: Vec<(Intent, u8)> = self
.descriptors
.iter()
.filter(|d| d.matcher.matches(&lower))
.map(|d| (d.intent, d.priority))
.collect();
matches.sort_by(|a, b| b.1.cmp(&a.1));
matches.into_iter().map(|(intent, _)| intent).collect()
}
pub fn should_bypass_cache(&self, intents: &[Intent]) -> bool {
let set: HashSet<Intent> = intents.iter().copied().collect();
self.descriptors
.iter()
.any(|d| d.bypasses_cache && set.contains(&d.intent))
}
}
const EXECUTION_KEYWORDS: &[&str] = &[
" run ",
" execute ",
" use a tool",
"use the tool",
"tools you can use",
"pick one at random",
"introspection tool",
"introspection skill",
"introspect",
"list entries",
"list files",
"file distribution",
"schedule a cron",
"schedule cron",
"create cron",
"order a subagent",
"delegate",
"orchestrate",
"ls ",
"/status",
];
const MODEL_IDENTITY_KEYWORDS: &[&str] = &[
"current model",
"what model",
"which model",
"still on",
"still using",
"using moonshot",
"confirm for me",
"/status",
];
const CURRENT_EVENTS_KEYWORDS: &[&str] = &[
"geopolitical situation",
"geopolitical",
"geo political",
"geopolitical sitrep",
"sitrep",
"current events",
"latest news",
"what's happening",
"what is happening",
"goings on",
"going on in the",
"what does the",
"today's",
"as of today",
];
const INTROSPECTION_KEYWORDS: &[&str] = &[
"introspection tool",
"introspection skill",
"introspect",
"what tools can you use",
"what tools do you have",
"available tools",
"subagent functionality",
"current subagent functionality",
"summarize the results",
"summarize introspection",
];
const PROVIDER_INVENTORY_KEYWORDS: &[&str] = &[
"which llm providers",
"what llm providers",
"which providers",
"what providers",
];
const CAPABILITY_SUMMARY_KEYWORDS: &[&str] = &[
"what are you able to do",
"what can you do",
"what are you able",
"what can you help",
];
const FOLDER_SCAN_GROUPS: &[&[&str]] = &[
&["look in", "check my", "search", "scan", "inspect"],
&[
"folder",
"directory",
"~/downloads",
"~/documents",
"~/pictures",
"~/photos",
"~/desktop",
"~/",
"/users/",
],
];
const ACKNOWLEDGEMENT_GROUPS: &[&[&str]] = &[
&["acknowledge", "acknowledg"],
&["one sentence", "then wait"],
];
const WALLET_SCAN_GROUPS: &[&[&str]] = &[
&[
"wallet address",
"wallet addresses",
"wallet credential",
"wallet credentials",
"private key",
"seed phrase",
"mnemonic",
"keystore",
"xprv",
"xpub",
],
&[
"search",
"find",
"scan",
"recursively",
"look in",
"check",
"see if there are",
],
];
const IMAGE_COUNT_GROUPS: &[&[&str]] = &[
&["how many", "count", "number of", "total"],
&["image files", "images", "photos", "pictures"],
];
const MARKDOWN_COUNT_GROUPS: &[&[&str]] = &[
&["how many", "count", "number of", "total"],
&[
"markdown file",
"markdown files",
".md files",
"md files",
"files ending in .md",
],
];
const OBSIDIAN_INSIGHTS_GROUPS: &[&[&str]] = &[
&["obsidian", "vault"],
&[
"insight",
"summary",
"summarize",
"what",
"say about",
"status",
],
];
fn match_delegation(lower: &str) -> bool {
if lower.contains("delegate") || lower.contains("orchestrate") {
return true;
}
if lower.contains("assign") && (lower.contains("subagent") || lower.contains("sub agent")) {
return true;
}
(lower.contains("subagent") || lower.contains("sub agent"))
&& (lower.contains("order")
|| lower.contains("ask")
|| lower.contains("task")
|| lower.contains("run ")
|| lower.contains("to a subagent")
|| lower.contains("to a sub agent")
|| lower.contains("to the subagent")
|| lower.contains("to the sub agent"))
}
fn match_cron(lower: &str) -> bool {
lower.contains("cron") || (lower.contains("schedule") && lower.contains("minute"))
}
fn match_random_tool_use(lower: &str) -> bool {
lower.contains("tools you can use")
|| (lower.contains("pick one at random") && lower.contains("tool"))
}
fn match_personality_profile(lower: &str) -> bool {
(lower.contains("personality") && (lower.contains("your") || lower.contains("you")))
|| lower.contains("who are you")
}
fn match_email_triage(lower: &str) -> bool {
const EMAIL_MARKERS: &[&str] = &[
"check my email",
"check email",
"inbox",
"mailbox",
"important email",
"important emails",
"scan my email",
"email triage",
"email digest",
];
const BRIDGE_MARKERS: &[&str] = &["proton bridge", "protonbridge", "himalaya"];
EMAIL_MARKERS.iter().any(|m| lower.contains(m))
|| (lower.contains("email") && BRIDGE_MARKERS.iter().any(|m| lower.contains(m)))
}
fn match_literary_quote_context(lower: &str) -> bool {
if lower.contains("what's that from") || lower.contains("what is that from") {
return true;
}
let asks_for_quote = lower.contains("quote")
|| lower.contains("line from")
|| lower.contains("appropriate line")
|| lower.contains("what quote");
let literary_source = lower.contains("dune")
|| lower.contains("frank herbert")
|| lower.contains("litany against fear");
let contextual_target = lower.contains("conflict")
|| lower.contains("iran")
|| lower.contains("geopolitical")
|| lower.contains("situation");
asks_for_quote && (literary_source || contextual_target)
}
fn match_contradiction(lower: &str) -> bool {
let trimmed = lower.trim();
if trimmed.len() > 48 {
return false;
}
const MARKERS: &[&str] = &[
"that's not true",
"that is not true",
"not true",
"that's wrong",
"that is wrong",
"incorrect",
];
MARKERS.iter().any(|m| trimmed.contains(m))
}
fn match_short_followup(lower: &str) -> bool {
let trimmed = lower.trim();
if trimmed.len() > 80 {
return false;
}
const MARKERS: &[&str] = &[
"what's that from",
"what is that from",
"where is that from",
"no, your quote",
"your quote",
"what quote",
"source?",
];
MARKERS.iter().any(|m| trimmed.contains(m))
}
fn match_reactive_sarcasm(lower: &str) -> bool {
let trimmed = lower.trim();
if trimmed.len() > 32 {
return false;
}
const MARKERS: &[&str] = &[
"wow",
"great",
"fantastic",
"amazing",
"incredible",
"brilliant",
"sure",
"right",
];
MARKERS.iter().any(|m| {
trimmed == *m || {
let stripped = trimmed
.strip_suffix("...")
.or_else(|| trimmed.strip_suffix('.'));
stripped.is_some_and(|s| s == *m)
}
})
}
#[cfg(test)]
mod tests {
use super::*;
fn classify(prompt: &str) -> Vec<Intent> {
IntentRegistry::default_registry().classify(prompt)
}
fn has(prompt: &str, intent: Intent) -> bool {
classify(prompt).contains(&intent)
}
fn bypass(prompt: &str) -> bool {
let reg = IntentRegistry::default_registry();
let intents = reg.classify(prompt);
reg.should_bypass_cache(&intents)
}
#[test]
fn execution_markers_cover_shortcut_and_guard_triggers() {
assert!(has(
"tell me about the tools you can use, pick one at random, and use it",
Intent::Execution,
));
assert!(has("/status", Intent::Execution));
assert!(has("please execute ls /tmp", Intent::Execution));
}
#[test]
fn delegation_and_cron_markers_match_expected_prompts() {
assert!(has("order a subagent to do this", Intent::Delegation));
assert!(has("ask the sub agent to do this", Intent::Delegation));
assert!(!has(
"use your introspection tool to discover current subagent functionality",
Intent::Delegation,
));
assert!(has("schedule a cron job every 5 minute", Intent::Cron,));
}
#[test]
fn model_identity_markers_match_expected_prompts() {
assert!(has(
"can you confirm for me that you are still using moonshot?",
Intent::ModelIdentity,
));
assert!(has("/status", Intent::ModelIdentity));
}
#[test]
fn current_events_markers_match_expected_prompts() {
assert!(has(
"What's the geopolitical situation?",
Intent::CurrentEvents,
));
assert!(has("Give me a geopolitical sitrep", Intent::CurrentEvents,));
assert!(has(
"What does the geo political sub agent say about goings on in the US?",
Intent::CurrentEvents,
));
assert!(has(
"What are today's current events?",
Intent::CurrentEvents,
));
}
#[test]
fn introspection_markers_match_expected_prompts() {
assert!(has(
"I want you to use your introspection skill",
Intent::Introspection,
));
assert!(has(
"use your introspection tool to discover current subagent functionality",
Intent::Introspection,
));
assert!(has(
"what tools do you have available?",
Intent::Introspection,
));
}
#[test]
fn email_triage_markers_match_expected_prompts() {
assert!(has(
"Can you have a subagent check my email for anything important?",
Intent::EmailTriage,
));
assert!(has(
"Use proton bridge and triage inbox for urgent items",
Intent::EmailTriage,
));
assert!(!has("Check my calendar for tomorrow", Intent::EmailTriage,));
}
#[test]
fn literary_quote_markers_match_expected_prompts() {
assert!(has(
"Give me an appropriate dune quote for the conflict in Iran",
Intent::LiteraryQuoteContext,
));
assert!(has("What's that from?", Intent::LiteraryQuoteContext,));
assert!(!has(
"Give me a geopolitical situation update",
Intent::LiteraryQuoteContext,
));
}
#[test]
fn acknowledgement_markers_match_expected_prompts() {
assert!(has(
"Good evening Duncan. Acknowledge this request in one sentence, then wait.",
Intent::Acknowledgement,
));
assert!(has(
"acknowledge this in one sentence and then wait for my next command",
Intent::Acknowledgement,
));
assert!(!has("please acknowledge receipt", Intent::Acknowledgement,));
}
#[test]
fn provider_inventory_markers_match_expected_prompts() {
assert!(has("which llm providers?", Intent::ProviderInventory));
assert!(has(
"what providers are configured",
Intent::ProviderInventory,
));
assert!(!has("what model are you using", Intent::ProviderInventory));
}
#[test]
fn personality_and_capability_markers_match_expected_prompts() {
assert!(has(
"Tell me about your personality",
Intent::PersonalityProfile,
));
assert!(has("who are you", Intent::PersonalityProfile));
assert!(has(
"Duncan, what are you able to do for me right now?",
Intent::CapabilitySummary,
));
}
#[test]
fn wallet_scan_markers_match_expected_prompts() {
assert!(has(
"search the ~/code folder recursively and tell me files containing wallet address",
Intent::WalletAddressScan,
));
assert!(has(
"find wallet addresses in /tmp recursively",
Intent::WalletAddressScan,
));
assert!(has(
"I want you to check my ~/Downloads folder to see if there are any wallet credentials there",
Intent::WalletAddressScan,
));
assert!(has(
"Now look in my Downloads folder for wallet credentials",
Intent::WalletAddressScan,
));
assert!(has(
"Please check my Desktop folder for files containing private key and list full paths.",
Intent::WalletAddressScan,
));
assert!(!has(
"show me your wallet balance",
Intent::WalletAddressScan,
));
}
#[test]
fn image_count_markers_match_expected_prompts() {
assert!(has(
"How many image files are in my photos?",
Intent::ImageCountScan,
));
assert!(has(
"count images in ~/Downloads recursively",
Intent::ImageCountScan,
));
assert!(!has(
"show me photos from yesterday",
Intent::ImageCountScan,
));
}
#[test]
fn markdown_count_markers_match_expected_prompts() {
assert!(has(
"Count markdown files recursively in /Users/jmachen/code and return only the number.",
Intent::MarkdownCountScan,
));
assert!(has(
"how many .md files are in ~/code?",
Intent::MarkdownCountScan,
));
assert!(!has(
"count image files in ~/Pictures",
Intent::MarkdownCountScan,
));
}
#[test]
fn folder_scan_markers_match_expected_prompts() {
assert!(has(
"Now look in my Downloads folder and summarize what is there",
Intent::FolderScan,
));
assert!(has(
"please check my ~/Documents folder for wallet credentials",
Intent::FolderScan,
));
assert!(!has("what's your personality?", Intent::FolderScan));
}
#[test]
fn obsidian_insight_markers_match_expected_prompts() {
assert!(has(
"Any insights you care to draw from the obsidian vault?",
Intent::ObsidianInsights,
));
assert!(has("summarize my vault", Intent::ObsidianInsights));
assert!(!has("vault token price", Intent::ObsidianInsights));
}
#[test]
fn cache_bypass_markers_cover_shortcut_handled_prompts() {
assert!(bypass(
"tell me about the tools you can use, pick one at random, and use it",
));
assert!(bypass(
"Good evening Duncan. Acknowledge this request in one sentence, then wait.",
));
assert!(bypass(
"What does the geopolitical monitor have to say about today's news?",
));
assert!(!bypass("Summarize this paragraph in one sentence."));
}
#[test]
fn model_identity_wins_over_execution_for_status() {
let intents = classify("/status");
assert!(intents.contains(&Intent::ModelIdentity));
assert!(intents.contains(&Intent::Execution));
let mi_pos = intents
.iter()
.position(|i| *i == Intent::ModelIdentity)
.unwrap();
let ex_pos = intents
.iter()
.position(|i| *i == Intent::Execution)
.unwrap();
assert!(
mi_pos < ex_pos,
"ModelIdentity (priority 80) should precede Execution (priority 10)"
);
}
#[test]
fn acknowledgement_has_highest_shortcut_priority_among_standard_intents() {
let intents = classify(
"acknowledge this in one sentence, then wait. Also tell me the current events.",
);
assert!(intents.contains(&Intent::Acknowledgement));
assert!(intents.contains(&Intent::CurrentEvents));
let ack_pos = intents
.iter()
.position(|i| *i == Intent::Acknowledgement)
.unwrap();
let ce_pos = intents
.iter()
.position(|i| *i == Intent::CurrentEvents)
.unwrap();
assert!(ack_pos < ce_pos);
}
#[test]
fn contradiction_matches_short_prompts() {
assert!(has("that's not true", Intent::Contradiction));
assert!(has("That is wrong.", Intent::Contradiction));
assert!(has("incorrect", Intent::Contradiction));
assert!(!has(
"I think that is not true based on extensive research and evidence",
Intent::Contradiction,
));
}
#[test]
fn short_followup_matches_quote_references() {
assert!(has("what's that from?", Intent::ShortFollowup));
assert!(has("Where is that from?", Intent::ShortFollowup));
assert!(has("source?", Intent::ShortFollowup));
let long = format!(
"What's that from? I need to know because {}",
"a".repeat(80)
);
assert!(!has(&long, Intent::ShortFollowup));
}
#[test]
fn reactive_sarcasm_matches_exact_and_suffixed() {
assert!(has("wow", Intent::ReactiveSarcasm));
assert!(has("Great.", Intent::ReactiveSarcasm));
assert!(has("fantastic...", Intent::ReactiveSarcasm));
assert!(has(" sure ", Intent::ReactiveSarcasm));
assert!(!has("wow that was great", Intent::ReactiveSarcasm));
assert!(!has(
"wow this is incredibly amazing work",
Intent::ReactiveSarcasm,
));
}
#[test]
fn channel_intents_have_highest_priorities() {
let reg = IntentRegistry::default_registry();
let channel_priorities: Vec<u8> = reg
.descriptors
.iter()
.filter(|d| {
matches!(
d.intent,
Intent::Contradiction | Intent::ShortFollowup | Intent::ReactiveSarcasm
)
})
.map(|d| d.priority)
.collect();
let max_standard: u8 = reg
.descriptors
.iter()
.filter(|d| {
!matches!(
d.intent,
Intent::Contradiction | Intent::ShortFollowup | Intent::ReactiveSarcasm
)
})
.map(|d| d.priority)
.max()
.unwrap_or(0);
assert!(
channel_priorities.iter().all(|&p| p > max_standard),
"Channel intents must have higher priority than all standard intents"
);
}
#[test]
fn ordinary_prompt_matches_no_intents() {
let intents = classify("Tell me a joke about Rust programming.");
assert!(intents.is_empty());
}
#[test]
fn classify_lowercases_once_and_matches_case_insensitively() {
assert!(has("WHICH LLM PROVIDERS?", Intent::ProviderInventory));
assert!(has("What Model Are You Using?", Intent::ModelIdentity));
assert!(has("/STATUS", Intent::Execution));
}
}