Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
06e9de1
adds persona definition
dingfeli Jun 3, 2025
361423f
adds persona custom deserialization logic
dingfeli Jun 4, 2025
b434480
adds impl for visitor permission eval
dingfeli Jun 5, 2025
e79678c
custom impl of PartialEq and Hash for PermissionSubject
dingfeli Jun 5, 2025
e3d8829
implements PermissionCandidate for all tools
dingfeli Jun 6, 2025
4f03263
flattens agent config
dingfeli Jun 10, 2025
84436e2
refactors states (context and tool managers) to accept agents
dingfeli Jun 12, 2025
d760e19
migrates context manager functions to agent collection
dingfeli Jun 13, 2025
212d445
adds test for agent collection
dingfeli Jun 14, 2025
46a19dd
reworks tool name translation
dingfeli Jun 17, 2025
e149533
handles tool name conflict
dingfeli Jun 17, 2025
9ff3e11
removes unneccessary returns
dingfeli Jun 18, 2025
f88a7aa
Merge branch 'main' into persona-enablement
dingfeli Jun 18, 2025
1dba97c
removes execute_bash
dingfeli Jun 18, 2025
d6e80bf
fixes tool permission prompting
dingfeli Jun 19, 2025
aef6461
Merge branch 'main' into persona-enablement
dingfeli Jun 19, 2025
579a08d
fixex permission with execute command tools
dingfeli Jun 19, 2025
288e6c4
Merge branch 'main' into persona-enablement
dingfeli Jun 19, 2025
8f646cf
rewires existing context functionalities
dingfeli Jun 20, 2025
eceedd6
awaits display task for to avoid buffer interleave
dingfeli Jun 20, 2025
9ba7616
adds hook name before they get executed
dingfeli Jun 20, 2025
bd03f06
wires up tool permissioning with agent persona
dingfeli Jun 20, 2025
c089634
Merge branch 'main' into persona-enablement
dingfeli Jun 21, 2025
c5172fc
fixes compilation errors from merge
dingfeli Jun 21, 2025
5ef34d1
fixes test
dingfeli Jun 24, 2025
740237b
fixes typos
dingfeli Jun 24, 2025
65de74f
Merge branch 'main' into persona-enablement
dingfeli Jun 24, 2025
cfb8d36
fixes errors from merge
dingfeli Jun 24, 2025
ec0c349
adds debug for permission eval result
dingfeli Jun 24, 2025
60e4db0
fixes typo
dingfeli Jun 24, 2025
f5c561f
Merge branch 'main' into persona-enablement
dingfeli Jun 24, 2025
d9ec92c
fixes errors from merge
dingfeli Jun 24, 2025
40d3edb
Merge branch 'main' into persona-enablement
dingfeli Jun 24, 2025
851e7d9
fixes clippy warnings
dingfeli Jun 24, 2025
838966a
addresses various comments
dingfeli Jun 24, 2025
905e6f1
modifies mcp cli command for agent
dingfeli Jun 25, 2025
d898fce
fixes built in tools permissioning not reading camel case
dingfeli Jun 25, 2025
e9b8bea
fixes tests for mcp subcommand
dingfeli Jun 25, 2025
3e847bf
adds migration routine for agent
dingfeli Jun 26, 2025
c52649b
refines migration logic
dingfeli Jun 26, 2025
4300e33
moves profile level migration to slash command
dingfeli Jun 27, 2025
1727b95
Merge branch 'main' into persona-enablement
dingfeli Jun 27, 2025
d46ec18
renames persona to agent
dingfeli Jun 27, 2025
d949af0
wip: reworks profile migration
dingfeli Jun 28, 2025
e2338c8
temp changes for lints
dingfeli Jun 30, 2025
d6606e7
fixes test
dingfeli Jun 30, 2025
9e85095
moves migrations to an interactive experience
dingfeli Jun 30, 2025
33e3b49
dedupes context merge
dingfeli Jun 30, 2025
b5119c2
adds migration routine for global mcp config
dingfeli Jul 1, 2025
ed523f5
fixes typo
dingfeli Jul 1, 2025
dec2a80
adds example agent config
dingfeli Jul 1, 2025
392f96d
deprecates use of profile flags
dingfeli Jul 1, 2025
2dcb345
Merge branch 'main' into persona-enablement
dingfeli Jul 1, 2025
da88dbb
fixes error from merge
dingfeli Jul 1, 2025
8b196df
gates migration workflow behind a flag
dingfeli Jul 1, 2025
e16e627
fixes permission for in memory default agent
dingfeli Jul 1, 2025
21d2239
fixes test
dingfeli Jul 2, 2025
17cb0e0
removes debug log
dingfeli Jul 2, 2025
c5c687d
Merge branch 'main' into persona-enablement
dingfeli Jul 2, 2025
ec4b489
fixes errors from merge
dingfeli Jul 2, 2025
d915779
Merge branch 'main' into persona-enablement
dingfeli Jul 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,082 changes: 1,082 additions & 0 deletions crates/chat-cli/src/cli/agent.rs

Large diffs are not rendered by default.

162 changes: 21 additions & 141 deletions crates/chat-cli/src/cli/chat/cli/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ pub enum ContextSubcommand {
},
/// Add context rules (filenames or glob patterns)
Add {
/// Add to global rules (available in all profiles)
#[arg(short, long)]
global: bool,
/// Include even if matched files exceed size limits
#[arg(short, long)]
force: bool,
Expand All @@ -61,18 +58,11 @@ pub enum ContextSubcommand {
/// Remove specified rules from current profile
#[command(alias = "rm")]
Remove {
/// Remove specified rules globally
#[arg(short, long)]
global: bool,
#[arg(required = true)]
paths: Vec<String>,
},
/// Remove all rules from current profile
Clear {
/// Remove global rules
#[arg(short, long)]
global: bool,
},
Clear,
#[command(hide = true)]
Hooks,
}
Expand All @@ -94,66 +84,7 @@ impl ContextSubcommand {

match self {
Self::Show { expand } => {
// Display global context
execute!(
session.stderr,
style::SetAttribute(Attribute::Bold),
style::SetForegroundColor(Color::Magenta),
style::Print("\n🌍 global:\n"),
style::SetAttribute(Attribute::Reset),
)?;
let mut global_context_files = HashSet::new();
let mut profile_context_files = HashSet::new();
if context_manager.global_config.paths.is_empty() {
execute!(
session.stderr,
style::SetForegroundColor(Color::DarkGrey),
style::Print(" <none>\n"),
style::SetForegroundColor(Color::Reset)
)?;
} else {
for path in &context_manager.global_config.paths {
execute!(session.stderr, style::Print(format!(" {} ", path)))?;
if let Ok(context_files) = context_manager.get_context_files_by_path(os, path).await {
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
style::Print(format!(
"({} match{})",
context_files.len(),
if context_files.len() == 1 { "" } else { "es" }
)),
style::SetForegroundColor(Color::Reset)
)?;
global_context_files.extend(context_files);
}
execute!(session.stderr, style::Print("\n"))?;
}
}

if expand {
execute!(
session.stderr,
style::SetAttribute(Attribute::Bold),
style::SetForegroundColor(Color::DarkYellow),
style::Print("\n 🔧 Hooks:\n")
)?;
print_hook_section(
&mut session.stderr,
&context_manager.global_config.hooks,
HookTrigger::ConversationStart,
)
.map_err(map_chat_error)?;

print_hook_section(
&mut session.stderr,
&context_manager.global_config.hooks,
HookTrigger::PerPrompt,
)
.map_err(map_chat_error)?;
}

// Display profile context
let profile_context_files = HashSet::<(String, String)>::new();
execute!(
session.stderr,
style::SetAttribute(Attribute::Bold),
Expand Down Expand Up @@ -183,7 +114,6 @@ impl ContextSubcommand {
)),
style::SetForegroundColor(Color::Reset)
)?;
profile_context_files.extend(context_files);
}
execute!(session.stderr, style::Print("\n"))?;
}
Expand Down Expand Up @@ -212,23 +142,19 @@ impl ContextSubcommand {
execute!(session.stderr, style::Print("\n"))?;
}

if global_context_files.is_empty() && profile_context_files.is_empty() {
if profile_context_files.is_empty() {
execute!(
session.stderr,
style::SetForegroundColor(Color::DarkGrey),
style::Print("No files in the current directory matched the rules above.\n\n"),
style::SetForegroundColor(Color::Reset)
)?;
} else {
let total = global_context_files.len() + profile_context_files.len();
let total_tokens = global_context_files
let total = profile_context_files.len();
let total_tokens = profile_context_files
.iter()
.map(|(_, content)| TokenCounter::count_tokens(content))
.sum::<usize>()
+ profile_context_files
.iter()
.map(|(_, content)| TokenCounter::count_tokens(content))
.sum::<usize>();
.sum::<usize>();
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
Expand All @@ -242,25 +168,6 @@ impl ContextSubcommand {
style::SetAttribute(Attribute::Reset)
)?;

for (filename, content) in &global_context_files {
let est_tokens = TokenCounter::count_tokens(content);
execute!(
session.stderr,
style::Print(format!("🌍 {} ", filename)),
style::SetForegroundColor(Color::DarkGrey),
style::Print(format!("(~{} tkns)\n", est_tokens)),
style::SetForegroundColor(Color::Reset),
)?;
if expand {
execute!(
session.stderr,
style::SetForegroundColor(Color::DarkGrey),
style::Print(format!("{}\n\n", content)),
style::SetForegroundColor(Color::Reset)
)?;
}
}

for (filename, content) in &profile_context_files {
let est_tokens = TokenCounter::count_tokens(content);
execute!(
Expand All @@ -284,13 +191,8 @@ impl ContextSubcommand {
execute!(session.stderr, style::Print(format!("{}\n\n", "▔".repeat(3))),)?;
}

let mut combined_files: Vec<(String, String)> = global_context_files
.iter()
.chain(profile_context_files.iter())
.cloned()
.collect();

let dropped_files = drop_matched_context_files(&mut combined_files, CONTEXT_FILES_MAX_SIZE).ok();
let mut files_as_vec = profile_context_files.iter().cloned().collect::<Vec<_>>();
let dropped_files = drop_matched_context_files(&mut files_as_vec, CONTEXT_FILES_MAX_SIZE).ok();

execute!(
session.stderr,
Expand Down Expand Up @@ -357,38 +259,12 @@ impl ContextSubcommand {
}
}
},
Self::Add { global, force, paths } => {
match context_manager.add_paths(os, paths.clone(), global, force).await {
Ok(_) => {
let target = if global { "global" } else { "profile" };
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
style::Print(format!("\nAdded {} path(s) to {} context.\n\n", paths.len(), target)),
style::SetForegroundColor(Color::Reset)
)?;
},
Err(e) => {
execute!(
session.stderr,
style::SetForegroundColor(Color::Red),
style::Print(format!("\nError: {}\n\n", e)),
style::SetForegroundColor(Color::Reset)
)?;
},
}
},
Self::Remove { global, paths } => match context_manager.remove_paths(os, paths.clone(), global).await {
Self::Add { force, paths } => match context_manager.add_paths(os, paths.clone(), force).await {
Ok(_) => {
let target = if global { "global" } else { "profile" };
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
style::Print(format!(
"\nRemoved {} path(s) from {} context.\n\n",
paths.len(),
target
)),
style::Print(format!("\nAdded {} path(s) to context.\n\n", paths.len())),
style::SetForegroundColor(Color::Reset)
)?;
},
Expand All @@ -401,17 +277,12 @@ impl ContextSubcommand {
)?;
},
},
Self::Clear { global } => match context_manager.clear(os, global).await {
Self::Remove { paths } => match context_manager.remove_paths(paths.clone()) {
Ok(_) => {
let target = if global {
"global".to_string()
} else {
format!("profile '{}'", context_manager.current_profile)
};
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
style::Print(format!("\nCleared context for {}\n\n", target)),
style::Print(format!("\nRemoved {} path(s) from context.\n\n", paths.len(),)),
style::SetForegroundColor(Color::Reset)
)?;
},
Expand All @@ -424,6 +295,15 @@ impl ContextSubcommand {
)?;
},
},
Self::Clear => {
context_manager.clear();
execute!(
session.stderr,
style::SetForegroundColor(Color::Green),
style::Print("\nCleared context\n\n"),
style::SetForegroundColor(Color::Reset)
)?;
},
Self::Hooks => {
execute!(
session.stderr,
Expand Down
Loading
Loading