Skip to content

Commit 1f4e1ac

Browse files
committed
Add /resource command with indexed/pinned storage types
- Create new ResourceSubcommand with --type flag (indexed/pinned) - Default to pinned storage for backward compatibility - Preserve /context command unchanged for existing workflows - Support show/add/remove/clear/status operations - Case insensitive storage type values
1 parent ad41194 commit 1f4e1ac

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

crates/chat-cli/src/cli/chat/cli/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod model;
99
pub mod persist;
1010
pub mod profile;
1111
pub mod prompts;
12+
pub mod resource;
1213
pub mod subscribe;
1314
pub mod tools;
1415
pub mod unified_context;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use clap::{Subcommand, ValueEnum};
2+
use eyre::Result;
3+
4+
use crate::cli::chat::{ChatError, ChatSession, ChatState};
5+
use crate::os::Os;
6+
7+
use super::context::ContextSubcommand as OriginalContextSubcommand;
8+
use super::knowledge::KnowledgeSubcommand;
9+
10+
#[derive(Clone, Debug, PartialEq, Eq, ValueEnum)]
11+
pub enum StorageType {
12+
Indexed,
13+
Pinned,
14+
}
15+
16+
#[derive(Clone, Debug, PartialEq, Eq, Subcommand)]
17+
pub enum ResourceSubcommand {
18+
Show {
19+
#[arg(long)]
20+
expand: bool,
21+
#[arg(long, value_enum, ignore_case = true)]
22+
r#type: Option<StorageType>,
23+
},
24+
Add {
25+
#[arg(short, long)]
26+
force: bool,
27+
#[arg(long, value_enum, ignore_case = true)]
28+
r#type: Option<StorageType>,
29+
#[arg(required = true)]
30+
paths: Vec<String>,
31+
},
32+
#[command(alias = "rm")]
33+
Remove {
34+
#[arg(required = true)]
35+
paths: Vec<String>,
36+
},
37+
Clear {
38+
#[arg(long, value_enum, ignore_case = true)]
39+
r#type: Option<StorageType>,
40+
},
41+
Status,
42+
}
43+
44+
impl ResourceSubcommand {
45+
pub fn name(&self) -> &'static str {
46+
match self {
47+
Self::Show { .. } => "show",
48+
Self::Add { .. } => "add",
49+
Self::Remove { .. } => "remove",
50+
Self::Clear { .. } => "clear",
51+
Self::Status => "status",
52+
}
53+
}
54+
55+
pub async fn execute(self, os: &Os, session: &mut ChatSession) -> Result<ChatState, ChatError> {
56+
match self {
57+
Self::Show { expand, r#type } => {
58+
match r#type {
59+
Some(StorageType::Indexed) => KnowledgeSubcommand::Show.execute(os, session).await,
60+
Some(StorageType::Pinned) => OriginalContextSubcommand::Show { expand }.execute(os, session).await,
61+
None => {
62+
OriginalContextSubcommand::Show { expand }.execute(os, session).await?;
63+
KnowledgeSubcommand::Show.execute(os, session).await
64+
}
65+
}
66+
},
67+
Self::Add { force, r#type, paths } => {
68+
match r#type.unwrap_or(StorageType::Pinned) {
69+
StorageType::Indexed => {
70+
KnowledgeSubcommand::Add {
71+
path: paths.join(" "),
72+
include: vec![],
73+
exclude: vec![],
74+
index_type: None
75+
}.execute(os, session).await
76+
},
77+
StorageType::Pinned => {
78+
OriginalContextSubcommand::Add { paths, force }.execute(os, session).await
79+
},
80+
}
81+
},
82+
Self::Remove { paths } => {
83+
let _ = OriginalContextSubcommand::Remove { paths: paths.clone() }.execute(os, session).await;
84+
// Remove first path from knowledge (knowledge only supports single path)
85+
if let Some(first_path) = paths.first() {
86+
KnowledgeSubcommand::Remove { path: first_path.clone() }.execute(os, session).await
87+
} else {
88+
Ok(ChatState::PromptUser { skip_printing_tools: true })
89+
}
90+
},
91+
Self::Clear { r#type } => {
92+
match r#type {
93+
Some(StorageType::Indexed) => KnowledgeSubcommand::Clear.execute(os, session).await,
94+
Some(StorageType::Pinned) => OriginalContextSubcommand::Clear.execute(os, session).await,
95+
None => {
96+
OriginalContextSubcommand::Clear.execute(os, session).await?;
97+
KnowledgeSubcommand::Clear.execute(os, session).await
98+
}
99+
}
100+
},
101+
Self::Status => KnowledgeSubcommand::Status.execute(os, session).await,
102+
}
103+
}
104+
}

crates/chat-cli/src/cli/chat/cli/unified_slash_command.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use super::model::ModelArgs;
2020
use super::persist::PersistSubcommand;
2121
use super::prompts::PromptsArgs;
2222
use super::subscribe::SubscribeArgs;
23+
use super::resource::ResourceSubcommand;
2324
use super::tools::ToolsArgs;
2425
use super::unified_context::UnifiedContextSubcommand;
2526
use super::usage::UsageArgs;
@@ -44,6 +45,9 @@ pub enum UnifiedSlashCommand {
4445
/// Manage context files and knowledge base (unified interface)
4546
#[command(subcommand)]
4647
Context(UnifiedContextSubcommand),
48+
/// Manage resources (pinned and indexed)
49+
#[command(subcommand)]
50+
Resource(ResourceSubcommand),
4751
/// (Deprecated) Use /context instead - Legacy knowledge base management
4852
#[command(subcommand, hide = true)]
4953
Knowledge(KnowledgeSubcommand),
@@ -102,6 +106,10 @@ impl UnifiedSlashCommand {
102106
// Use the new unified context system
103107
subcommand.execute(os, session).await
104108
},
109+
Self::Resource(subcommand) => {
110+
// Use the new resource system
111+
subcommand.execute(os, session).await
112+
},
105113
Self::Knowledge(subcommand) => {
106114
// Show deprecation warning and redirect to unified context
107115
use crossterm::{queue, style};
@@ -141,6 +149,7 @@ impl UnifiedSlashCommand {
141149
Self::Agent(_) => "agent",
142150
Self::Profile => "profile",
143151
Self::Context(_) => "context",
152+
Self::Resource(_) => "resource",
144153
Self::Knowledge(_) => "knowledge",
145154
Self::PromptEditor(_) => "editor",
146155
Self::Compact(_) => "compact",
@@ -159,6 +168,7 @@ impl UnifiedSlashCommand {
159168
pub fn subcommand_name(&self) -> Option<&'static str> {
160169
match self {
161170
Self::Context(subcommand) => Some(subcommand.name()),
171+
Self::Resource(subcommand) => Some(subcommand.name()),
162172
Self::Knowledge(subcommand) => Some(subcommand.name()),
163173
Self::Agent(subcommand) => Some(subcommand.name()),
164174
Self::Persist(subcommand) => Some(subcommand.name()),

0 commit comments

Comments
 (0)