Skip to content

Commit 6f579d2

Browse files
authored
Merge pull request #106 from openSVM/copilot/fix-105
Hide debug info under --debug flag for AI queries (v0.7.0)
2 parents d77b247 + 71530a1 commit 6f579d2

File tree

9 files changed

+234
-34
lines changed

9 files changed

+234
-34
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "osvm"
3-
version = "0.6.4"
3+
version = "0.7.0"
44
edition = "2021"
55
license = "MIT"
66
description = "OpenSVM CLI tool for managing SVM nodes and deployments"

src/clparse.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ pub fn parse_command_line() -> clap::ArgMatches {
8080
.global(true)
8181
.help("Disable colorized output (also respects NO_COLOR environment variable)"),
8282
)
83+
.arg(
84+
Arg::new("debug")
85+
.long("debug")
86+
.action(ArgAction::SetTrue)
87+
.global(true)
88+
.help("Show debug information"),
89+
)
8390
.arg(
8491
Arg::new("json_rpc_url")
8592
.short('u')

src/main.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ fn is_known_command(sub_command: &str) -> bool {
5454
async fn handle_ai_query(
5555
sub_command: &str,
5656
sub_matches: &clap::ArgMatches,
57+
app_matches: &clap::ArgMatches,
5758
) -> Result<(), Box<dyn std::error::Error>> {
5859
// For external subcommands, clap provides the additional arguments differently
5960
// We need to collect them from the raw args since clap doesn't know about them
@@ -76,13 +77,20 @@ async fn handle_ai_query(
7677

7778
let query = query_parts.join(" ");
7879

80+
// Get debug flag from global args
81+
let debug_mode = app_matches.get_flag("debug");
82+
7983
// Make AI request
80-
println!("🔍 Interpreting as AI query: \"{}\"", query);
84+
if debug_mode {
85+
println!("🔍 Interpreting as AI query: \"{}\"", query);
86+
}
8187

82-
let ai_service = crate::services::ai_service::AiService::new();
83-
match ai_service.query(&query).await {
88+
let ai_service = crate::services::ai_service::AiService::new_with_debug(debug_mode);
89+
match ai_service.query_with_debug(&query, debug_mode).await {
8490
Ok(response) => {
85-
println!("🤖 AI Response:");
91+
if debug_mode {
92+
println!("🤖 AI Response:");
93+
}
8694
println!("{}", response);
8795
}
8896
Err(e) => {
@@ -316,7 +324,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
316324

317325
// Handle AI queries early to avoid config loading
318326
if !is_known_command(sub_command) {
319-
return handle_ai_query(sub_command, sub_matches).await;
327+
return handle_ai_query(sub_command, sub_matches, &app_matches).await;
320328
}
321329

322330
// Load configuration using the new Config module

src/services/ai_service.rs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,18 @@ pub struct AiService {
5858

5959
impl AiService {
6060
pub fn new() -> Self {
61-
Self::with_api_url(None)
61+
Self::new_with_debug(true)
62+
}
63+
64+
pub fn new_with_debug(debug_mode: bool) -> Self {
65+
Self::with_api_url_and_debug(None, debug_mode)
6266
}
6367

6468
pub fn with_api_url(custom_api_url: Option<String>) -> Self {
69+
Self::with_api_url_and_debug(custom_api_url, true)
70+
}
71+
72+
pub fn with_api_url_and_debug(custom_api_url: Option<String>, debug_mode: bool) -> Self {
6573
let (api_url, use_openai) = match custom_api_url {
6674
Some(url) => {
6775
// Check if it's an OpenAI URL and we have an API key
@@ -100,8 +108,10 @@ impl AiService {
100108
let mut template_manager = PromptTemplateManager::new();
101109

102110
// Initialize template manager
103-
if let Err(e) = template_manager.load_from_directory("./templates/ai_prompts") {
104-
println!("⚠️ Failed to load AI prompt templates: {}", e);
111+
if let Err(e) = template_manager.load_from_directory_with_debug("./templates/ai_prompts", debug_mode) {
112+
if debug_mode {
113+
println!("⚠️ Failed to load AI prompt templates: {}", e);
114+
}
105115
}
106116

107117
Self {
@@ -115,6 +125,10 @@ impl AiService {
115125
}
116126

117127
pub async fn query(&self, question: &str) -> Result<String> {
128+
self.query_with_debug(question, true).await
129+
}
130+
131+
pub async fn query_with_debug(&self, question: &str, debug_mode: bool) -> Result<String> {
118132
let endpoint = if self.use_openai {
119133
EndpointId::openai()
120134
} else {
@@ -127,29 +141,37 @@ impl AiService {
127141
}
128142

129143
if self.use_openai {
130-
println!("🤖 Asking OpenAI ({}): {}", self.api_url, question);
144+
if debug_mode {
145+
println!("🤖 Asking OpenAI ({}): {}", self.api_url, question);
146+
}
131147
} else {
132-
println!("🤖 Asking OSVM AI ({}): {}", self.api_url, question);
148+
if debug_mode {
149+
println!("🤖 Asking OSVM AI ({}): {}", self.api_url, question);
150+
}
133151
}
134152

135153
let result = if self.use_openai {
136-
self.query_openai(question).await
154+
self.query_openai(question, debug_mode).await
137155
} else {
138-
self.query_osvm_ai(question).await
156+
self.query_osvm_ai(question, debug_mode).await
139157
};
140158

141159
// Record success/failure with circuit breaker
142160
match &result {
143161
Ok(_) => {
144162
self.circuit_breaker.on_success_endpoint(&endpoint);
145-
println!(
146-
"🔍 AI Response received ({} chars)",
147-
result.as_ref().unwrap().len()
148-
);
163+
if debug_mode {
164+
println!(
165+
"🔍 AI Response received ({} chars)",
166+
result.as_ref().unwrap().len()
167+
);
168+
}
149169
}
150170
Err(e) => {
151171
self.circuit_breaker.on_failure_endpoint(&endpoint);
152-
println!("❌ AI Response error: {}", e);
172+
if debug_mode {
173+
println!("❌ AI Response error: {}", e);
174+
}
153175
}
154176
}
155177

@@ -228,15 +250,17 @@ impl AiService {
228250
}
229251
}
230252

231-
async fn query_osvm_ai(&self, question: &str) -> Result<String> {
253+
async fn query_osvm_ai(&self, question: &str, debug_mode: bool) -> Result<String> {
232254
let request_body = AiRequest {
233255
question: question.to_string(),
234256
};
235257

236-
println!(
237-
"📤 OSVM AI Request: {}",
238-
serde_json::to_string_pretty(&request_body)?
239-
);
258+
if debug_mode {
259+
println!(
260+
"📤 OSVM AI Request: {}",
261+
serde_json::to_string_pretty(&request_body)?
262+
);
263+
}
240264

241265
let response = self
242266
.client
@@ -249,7 +273,9 @@ impl AiService {
249273
let status = response.status();
250274
let response_text = response.text().await?;
251275

252-
println!("📥 OSVM AI Response ({}): {}", status, response_text);
276+
if debug_mode {
277+
println!("📥 OSVM AI Response ({}): {}", status, response_text);
278+
}
253279

254280
if !status.is_success() {
255281
// Try to parse error response as JSON first
@@ -286,7 +312,7 @@ impl AiService {
286312
}
287313
}
288314

289-
async fn query_openai(&self, question: &str) -> Result<String> {
315+
async fn query_openai(&self, question: &str, debug_mode: bool) -> Result<String> {
290316
let api_key = self.api_key.as_ref().unwrap();
291317

292318
let request_body = OpenAiRequest {
@@ -299,10 +325,12 @@ impl AiService {
299325
temperature: 0.7,
300326
};
301327

302-
println!(
303-
"📤 OpenAI Request: {}",
304-
serde_json::to_string_pretty(&request_body)?
305-
);
328+
if debug_mode {
329+
println!(
330+
"📤 OpenAI Request: {}",
331+
serde_json::to_string_pretty(&request_body)?
332+
);
333+
}
306334

307335
let response = self
308336
.client
@@ -316,7 +344,9 @@ impl AiService {
316344
let status = response.status();
317345
let response_text = response.text().await?;
318346

319-
println!("📥 OpenAI Response ({}): {}", status, response_text);
347+
if debug_mode {
348+
println!("📥 OpenAI Response ({}): {}", status, response_text);
349+
}
320350

321351
if !status.is_success() {
322352
anyhow::bail!(

src/utils/prompt_templates.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,17 @@ impl PromptTemplateManager {
135135

136136
/// Load templates from a directory
137137
pub fn load_from_directory(&mut self, dir_path: &str) -> Result<usize> {
138+
self.load_from_directory_with_debug(dir_path, true)
139+
}
140+
141+
pub fn load_from_directory_with_debug(&mut self, dir_path: &str, debug_mode: bool) -> Result<usize> {
138142
self.template_dirs.push(dir_path.to_string());
139143

140144
let dir = Path::new(dir_path);
141145
if !dir.exists() {
142-
println!("📁 Creating template directory: {}", dir_path);
146+
if debug_mode {
147+
println!("📁 Creating template directory: {}", dir_path);
148+
}
143149
fs::create_dir_all(dir)?;
144150
self.create_default_templates(dir)?;
145151
}
@@ -157,10 +163,14 @@ impl PromptTemplateManager {
157163
match self.load_template_file(&path) {
158164
Ok(count) => {
159165
loaded_count += count;
160-
println!("✅ Loaded {} templates from {}", count, path.display());
166+
if debug_mode {
167+
println!("✅ Loaded {} templates from {}", count, path.display());
168+
}
161169
}
162170
Err(e) => {
163-
println!("⚠️ Failed to load template file {}: {}", path.display(), e);
171+
if debug_mode {
172+
println!("⚠️ Failed to load template file {}: {}", path.display(), e);
173+
}
164174
}
165175
}
166176
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
id: deeplogic_economic_exploit
2+
name: DeepLogic Economic Exploit Analysis
3+
description: Analyzes code for potential economic exploitation vulnerabilities
4+
category: deeplogic
5+
analysis_vector: economic_exploit
6+
template: "You are an expert Solana security auditor specializing in economic vulnerability analysis.\n\nAnalyze the following code for potential economic exploitation vulnerabilities:\n\nFILE: {filename}\nCODE:\n```rust\n{code}\n```\n\nVULNERABILITY CONTEXT:\n{vulnerability_description}\n\nPlease provide a comprehensive analysis including:\n\n1. **Economic Risk Assessment**: How could this code be exploited for financial gain?\n2. **Attack Scenarios**: Describe specific step-by-step attack vectors\n3. **Impact Analysis**: Quantify potential financial losses or gains for attackers\n4. **Fix Recommendations**: Provide specific code changes to prevent exploitation\n\nFocus on:\n- Flash loan attacks\n- Arbitrage vulnerabilities \n- Price manipulation\n- Liquidity extraction\n- MEV (Maximal Extractable Value) opportunities\n- Economic state inconsistencies\n\nProvide your analysis in JSON format:\n{{\n \"risk_level\": \"Critical|High|Medium|Low\",\n \"confidence_score\": 0.0-1.0,\n \"attack_scenarios\": [\"scenario1\", \"scenario2\"],\n \"economic_impact\": \"description\",\n \"recommended_fixes\": [\"fix1\", \"fix2\"]\n}}"
7+
variables:
8+
- name: filename
9+
description: Path to the source file being analyzed
10+
required: true
11+
default_value: null
12+
variable_type: filename
13+
- name: code
14+
description: The source code to analyze
15+
required: true
16+
default_value: null
17+
variable_type: code
18+
- name: vulnerability_description
19+
description: Description of the identified vulnerability
20+
required: true
21+
default_value: null
22+
variable_type: string
23+
version: 1.0.0
24+
enabled: true
25+
metadata: {}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
id: fix_suggestion_general
2+
name: General Fix Suggestion Generator
3+
description: Generates specific code fixes for identified vulnerabilities
4+
category: fix_suggestion
5+
analysis_vector: general
6+
template: |-
7+
You are an expert Rust and Solana developer tasked with fixing security vulnerabilities.
8+
9+
PROBLEMATIC CODE:
10+
```rust
11+
{problematic_code}
12+
```
13+
14+
ISSUE DESCRIPTION:
15+
{issue_description}
16+
17+
VULNERABILITY TYPE: {vulnerability_type}
18+
19+
Please provide:
20+
21+
1. **Root Cause Analysis**: Why is this code vulnerable?
22+
2. **Specific Fix**: Provide the exact corrected code
23+
3. **Explanation**: Explain why your fix resolves the issue
24+
4. **Additional Considerations**: Any other security improvements
25+
26+
Requirements:
27+
- Maintain existing functionality
28+
- Follow Solana/Anchor best practices
29+
- Include proper error handling
30+
- Add necessary imports if required
31+
32+
Provide your response in this format:
33+
34+
## Root Cause
35+
[explanation]
36+
37+
## Fixed Code
38+
```rust
39+
[corrected code]
40+
```
41+
42+
## Explanation
43+
[why this fix works]
44+
45+
## Additional Considerations
46+
[other improvements or warnings]
47+
variables:
48+
- name: problematic_code
49+
description: The code that contains the vulnerability
50+
required: true
51+
default_value: null
52+
variable_type: code
53+
- name: issue_description
54+
description: Description of the security issue
55+
required: true
56+
default_value: null
57+
variable_type: string
58+
- name: vulnerability_type
59+
description: Type/category of the vulnerability
60+
required: false
61+
default_value: General Security Issue
62+
variable_type: string
63+
version: 1.0.0
64+
enabled: true
65+
metadata: {}

0 commit comments

Comments
 (0)