Bump version to 1.6.3

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ryan Ward
2026-06-12 14:17:06 -05:00
co-authored by Claude Opus 4.6
parent 4ba9706e35
commit 59cfd0e2f5
152 changed files with 8276 additions and 1664 deletions
@@ -0,0 +1,118 @@
use async_trait::async_trait;
use crate::InferenceTask;
use crate::engine::{CancellationToken, GenerationConfig, InferenceEngine};
pub struct InputClassificationTask;
#[derive(Clone)]
pub struct InputClassificationInput {
pub user_input: String,
pub recent_commands: Vec<String>,
pub is_follow_up: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum InputCategory {
Shell,
AgentPrompt,
}
pub struct InputClassificationResult {
pub category: InputCategory,
pub confidence: f32,
}
impl InputClassificationTask {
fn build_prompt(input: &InputClassificationInput) -> String {
let history = if input.recent_commands.is_empty() {
String::from("(none)")
} else {
input
.recent_commands
.iter()
.take(3)
.map(|c| format!("- {c}"))
.collect::<Vec<_>>()
.join("\n")
};
let follow_up_hint = if input.is_follow_up {
" The user just received an AI response, so this may be a follow-up."
} else {
""
};
format!(
"<|im_start|>system\n\
You classify terminal input. Respond with ONLY one word: \"shell\" or \"agent\".\n\
\"shell\" = a CLI command the user wants to execute.\n\
\"agent\" = a natural language prompt for an AI assistant.{follow_up_hint}\
<|im_end|>\n\
<|im_start|>user\n\
Recent commands:\n{history}\n\
Classify this input: \"{}\"\
<|im_end|>\n\
<|im_start|>assistant\n",
input.user_input
)
}
fn parse_output(output: &str) -> InputClassificationResult {
let output_lower = output.trim().to_lowercase();
let category = if output_lower.contains("shell") || output_lower.contains("command") {
InputCategory::Shell
} else {
InputCategory::AgentPrompt
};
let confidence = if output_lower == "shell" || output_lower == "agent" {
0.95
} else {
0.7
};
InputClassificationResult {
category,
confidence,
}
}
pub async fn run_cancellable(
&self,
engine: &InferenceEngine,
input: InputClassificationInput,
cancel: &CancellationToken,
) -> anyhow::Result<InputClassificationResult> {
let prompt = Self::build_prompt(&input);
let config = GenerationConfig {
max_tokens: 4,
temperature: 0.0,
top_p: 1.0,
};
let output = engine.generate_cancellable(&prompt, &config, cancel).await?;
Ok(Self::parse_output(&output))
}
}
#[async_trait]
impl InferenceTask for InputClassificationTask {
type Input = InputClassificationInput;
type Output = InputClassificationResult;
async fn run(
&self,
engine: &InferenceEngine,
input: Self::Input,
) -> anyhow::Result<InputClassificationResult> {
let prompt = Self::build_prompt(&input);
let config = GenerationConfig {
max_tokens: 4,
temperature: 0.0,
top_p: 1.0,
};
let output = engine.generate(&prompt, &config).await?;
Ok(Self::parse_output(&output))
}
}
+9
View File
@@ -0,0 +1,9 @@
mod input_classification;
mod prompt_suggestion;
mod tab_naming;
pub use input_classification::{
InputCategory, InputClassificationInput, InputClassificationResult, InputClassificationTask,
};
pub use prompt_suggestion::{PromptSuggestionInput, PromptSuggestionTask};
pub use tab_naming::{TabNamingInput, TabNamingTask};
@@ -0,0 +1,64 @@
use async_trait::async_trait;
use crate::InferenceTask;
use crate::engine::{GenerationConfig, InferenceEngine};
pub struct PromptSuggestionTask;
pub struct PromptSuggestionInput {
pub recent_commands: Vec<String>,
pub current_input: String,
pub working_directory: String,
}
#[async_trait]
impl InferenceTask for PromptSuggestionTask {
type Input = PromptSuggestionInput;
type Output = Vec<String>;
async fn run(
&self,
engine: &InferenceEngine,
input: Self::Input,
) -> anyhow::Result<Vec<String>> {
let history = input
.recent_commands
.iter()
.take(5)
.map(|c| format!("- {c}"))
.collect::<Vec<_>>()
.join("\n");
let prompt = format!(
"<|im_start|>system\n\
You suggest terminal commands. Give exactly 3 suggestions, one per line. \
No numbering, no explanation, just the commands.\
<|im_end|>\n\
<|im_start|>user\n\
Directory: {}\n\
Recent commands:\n{}\n\
Current partial input: \"{}\"\n\
Suggest 3 likely next commands:\
<|im_end|>\n\
<|im_start|>assistant\n",
input.working_directory, history, input.current_input
);
let config = GenerationConfig {
max_tokens: 64,
temperature: 0.6,
top_p: 0.9,
};
let output = engine.generate(&prompt, &config).await?;
let suggestions: Vec<String> = output
.lines()
.map(|l| l.trim().to_string())
.filter(|l| !l.is_empty())
.take(3)
.collect();
Ok(suggestions)
}
}
@@ -0,0 +1,60 @@
use async_trait::async_trait;
use crate::InferenceTask;
use crate::engine::{GenerationConfig, InferenceEngine};
pub struct TabNamingTask;
pub struct TabNamingInput {
pub recent_commands: Vec<String>,
pub working_directory: String,
}
#[async_trait]
impl InferenceTask for TabNamingTask {
type Input = TabNamingInput;
type Output = String;
async fn run(&self, engine: &InferenceEngine, input: Self::Input) -> anyhow::Result<String> {
let commands_str = input
.recent_commands
.iter()
.take(5)
.map(|c| format!("- {c}"))
.collect::<Vec<_>>()
.join("\n");
let prompt = format!(
"<|im_start|>system\n\
You name terminal tabs. Respond with ONLY a short name (2-4 words max). No explanation.\
<|im_end|>\n\
<|im_start|>user\n\
Directory: {}\n\
Recent commands:\n{}\n\
What should this tab be named?\
<|im_end|>\n\
<|im_start|>assistant\n",
input.working_directory, commands_str
);
let config = GenerationConfig {
max_tokens: 12,
temperature: 0.3,
top_p: 0.9,
};
let output = engine.generate(&prompt, &config).await?;
// Clean up: take only the first line, strip quotes
let name = output
.lines()
.next()
.unwrap_or(&output)
.trim()
.trim_matches('"')
.trim_matches('\'')
.to_string();
Ok(name)
}
}