Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 5 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions nocodo-agents/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,30 @@ imap = { version = "3.0.0-alpha.15", default-features = false, features = ["rust
rustls-connector = "0.19.0"

# New for tool execution
rusqlite = { version = "0.37", features = ["bundled"] }
chrono = { version = "0.4", features = ["serde"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
schemars = { version = "0.8", features = ["preserve_order"] }
serde_json = "1.0"
refinery = { version = "0.9", features = ["rusqlite"] }
tempfile = "3.0"
thiserror = { workspace = true }
uuid = { version = "1.0", features = ["v4"] }

[dev-dependencies]
tempfile = "3.0"

[features]
default = []
sqlite = ["nocodo-tools/sqlite"]

[[bin]]
name = "codebase-analysis-runner"
path = "bin/codebase_analysis_runner.rs"

[[bin]]
name = "sqlite-reader-runner"
path = "bin/sqlite_reader_runner.rs"
required-features = ["sqlite"]

[[bin]]
name = "structured-json-runner"
Expand Down
34 changes: 24 additions & 10 deletions nocodo-agents/bin/codebase_analysis_runner.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use clap::Parser;
use nocodo_agents::{config, factory::create_codebase_analysis_agent, Agent};
use nocodo_agents::{
config,
factory::create_codebase_analysis_agent,
storage::AgentStorage,
types::{Session, SessionStatus},
Agent,
};
use nocodo_llm_sdk::glm::zai::ZaiGlmClient;
use nocodo_tools::ToolExecutor;
use std::path::PathBuf;
Expand Down Expand Up @@ -65,20 +71,28 @@ async fn main() -> anyhow::Result<()> {
);

// Create codebase analysis agent
let (agent, database) = create_codebase_analysis_agent(client, tool_executor);
let agent = create_codebase_analysis_agent(client, tool_executor);

println!("Running agent: {}", agent.objective());
println!("User prompt: {}\n", args.prompt);

// Create session
let session_id = database.create_session(
"codebase-analysis",
"standalone",
"standalone",
Some(&agent.system_prompt()),
&args.prompt,
None,
)?;
let storage = Arc::new(nocodo_agents::storage::InMemoryStorage::new());
let session = Session {
id: None,
agent_name: "codebase-analysis".to_string(),
provider: "standalone".to_string(),
model: "standalone".to_string(),
system_prompt: Some(agent.system_prompt()),
user_prompt: args.prompt.clone(),
config: serde_json::json!({}),
status: SessionStatus::Running,
started_at: chrono::Utc::now().timestamp(),
ended_at: None,
result: None,
error: None,
};
let session_id = storage.create_session(session).await?;

// Execute agent
let result = agent.execute(&args.prompt, session_id).await?;
Expand Down
76 changes: 48 additions & 28 deletions nocodo-agents/bin/imap_email_runner.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use clap::Parser;
use nocodo_agents::{config, database::Database, imap_email::ImapEmailAgent, Agent};
use nocodo_agents::{
config,
imap_email::ImapEmailAgent,
storage::AgentStorage,
types::{Session, SessionStatus},
Agent,
};
use nocodo_llm_sdk::glm::zai::ZaiGlmClient;
use nocodo_tools::ToolExecutor;
use std::collections::HashMap;
Expand Down Expand Up @@ -72,8 +78,8 @@ async fn main() -> anyhow::Result<()> {
let tool_executor =
Arc::new(ToolExecutor::new(std::env::current_dir()?).with_max_file_size(10 * 1024 * 1024));

// Create database for session management
let database = Arc::new(Database::new(&PathBuf::from(":memory:"))?);
// Create storage for session management
let storage = Arc::new(nocodo_agents::storage::InMemoryStorage::new());

// Test IMAP connection before creating agent/loading LLM
println!("🔍 Testing IMAP connection...");
Expand Down Expand Up @@ -104,7 +110,7 @@ async fn main() -> anyhow::Result<()> {

let agent = ImapEmailAgent::from_settings(
client.clone(),
database.clone(),
storage.clone(),
tool_executor.clone(),
&settings,
)?;
Expand All @@ -116,32 +122,39 @@ async fn main() -> anyhow::Result<()> {

if args.interactive {
// Interactive mode - multiple queries in same session
run_interactive_mode(&agent, &database, &args.prompt).await?;
run_interactive_mode(&agent, &storage, &args.prompt).await?;
} else {
// Single query mode
run_single_query(&agent, &database, &args.prompt).await?;
run_single_query(&agent, &storage, &args.prompt).await?;
}

Ok(())
}

async fn run_single_query(
agent: &ImapEmailAgent,
database: &Arc<Database>,
async fn run_single_query<S: AgentStorage>(
agent: &ImapEmailAgent<S>,
storage: &Arc<S>,
prompt: &str,
) -> anyhow::Result<()> {
println!("💬 User prompt: {}\n", prompt);
println!("⏳ Processing...\n");

// Create session
let session_id = database.create_session(
"imap-email",
"standalone",
"standalone",
Some(&agent.system_prompt()),
prompt,
None,
)?;
let session = Session {
id: None,
agent_name: "imap-email".to_string(),
provider: "standalone".to_string(),
model: "standalone".to_string(),
system_prompt: Some(agent.system_prompt()),
user_prompt: prompt.to_string(),
config: serde_json::json!({}),
status: SessionStatus::Running,
started_at: chrono::Utc::now().timestamp(),
ended_at: None,
result: None,
error: None,
};
let session_id = storage.create_session(session).await?;

// Execute agent
let result = agent.execute(prompt, session_id).await?;
Expand All @@ -151,20 +164,27 @@ async fn run_single_query(
Ok(())
}

async fn run_interactive_mode(
agent: &ImapEmailAgent,
database: &Arc<Database>,
async fn run_interactive_mode<S: AgentStorage>(
agent: &ImapEmailAgent<S>,
storage: &Arc<S>,
initial_prompt: &str,
) -> anyhow::Result<()> {
// Create a single session for the entire interaction
let session_id = database.create_session(
"imap-email",
"standalone",
"standalone",
Some(&agent.system_prompt()),
initial_prompt,
None,
)?;
let session = Session {
id: None,
agent_name: "imap-email".to_string(),
provider: "standalone".to_string(),
model: "standalone".to_string(),
system_prompt: Some(agent.system_prompt()),
user_prompt: initial_prompt.to_string(),
config: serde_json::json!({}),
status: SessionStatus::Running,
started_at: chrono::Utc::now().timestamp(),
ended_at: None,
result: None,
error: None,
};
let session_id = storage.create_session(session).await?;

println!("🔄 Interactive mode enabled - session ID: {}", session_id);
println!("💡 Type your queries. Type 'quit' or 'exit' to end the session.\n");
Expand Down
37 changes: 25 additions & 12 deletions nocodo-agents/bin/requirements_gathering_runner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use clap::Parser;
use nocodo_agents::config;
use nocodo_agents::requirements_gathering::create_user_clarification_agent;
use nocodo_agents::Agent;
use nocodo_agents::{
config,
factory::create_user_clarification_agent,
storage::AgentStorage,
types::{Session, SessionStatus},
Agent,
};
use std::path::PathBuf;
use std::sync::Arc;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
Expand Down Expand Up @@ -47,21 +51,30 @@ async fn main() -> anyhow::Result<()> {
zai_config.coding_plan,
)?);

let (agent, database) = create_user_clarification_agent(client)?;
let agent = create_user_clarification_agent(client);

tracing::debug!("System prompt:\n{}", agent.system_prompt());

println!("Running agent: {}", agent.objective());
println!("User prompt: {}\n", args.prompt);

let session_id = database.create_session(
"user-clarification",
"standalone",
"standalone",
Some(&agent.system_prompt()),
&args.prompt,
None,
)?;
// Create session
let storage = Arc::new(nocodo_agents::storage::InMemoryStorage::new());
let session = Session {
id: None,
agent_name: "user-clarification".to_string(),
provider: "standalone".to_string(),
model: "standalone".to_string(),
system_prompt: Some(agent.system_prompt()),
user_prompt: args.prompt.clone(),
config: serde_json::json!({}),
status: SessionStatus::Running,
started_at: chrono::Utc::now().timestamp(),
ended_at: None,
result: None,
error: None,
};
let session_id = storage.create_session(session).await?;

let result = agent.execute(&args.prompt, session_id).await?;

Expand Down
46 changes: 30 additions & 16 deletions nocodo-agents/bin/settings_management_runner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use clap::Parser;
use nocodo_agents::config;
use nocodo_agents::settings_management::create_settings_management_agent;
use nocodo_agents::Agent;
use nocodo_agents::{
config,
factory::create_settings_management_agent,
storage::AgentStorage,
types::{Session, SessionStatus},
Agent,
};
use std::path::PathBuf;
use std::sync::Arc;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
Expand Down Expand Up @@ -46,26 +50,36 @@ async fn main() -> anyhow::Result<()> {
// Collect settings schemas from available agents
// Use static schemas to avoid circular dependency (can't instantiate SqliteReaderAgent
// without db_path, which is what we're trying to collect)
let agent_schemas = nocodo_agents::sqlite_reader::SqliteReaderAgent::static_settings_schema()
.map(|schema| vec![schema])
.unwrap_or_default();
let agent_schemas = nocodo_agents::sqlite_reader::SqliteReaderAgent::<
nocodo_agents::storage::InMemoryStorage,
>::static_settings_schema()
.map(|schema| vec![schema])
.unwrap_or_default();

let (agent, database) =
create_settings_management_agent(client, args.settings_file.clone(), agent_schemas)?;
let agent = create_settings_management_agent(client, args.settings_file.clone(), agent_schemas);

tracing::debug!("System prompt:\n{}", agent.system_prompt());

println!("Running agent: {}", agent.objective());
println!("User prompt: {}\n", args.prompt);

let session_id = database.create_session(
"settings-management",
"standalone",
"standalone",
Some(&agent.system_prompt()),
&args.prompt,
None,
)?;
// Create session
let storage = Arc::new(nocodo_agents::storage::InMemoryStorage::new());
let session = Session {
id: None,
agent_name: "settings-management".to_string(),
provider: "standalone".to_string(),
model: "standalone".to_string(),
system_prompt: Some(agent.system_prompt()),
user_prompt: args.prompt.clone(),
config: serde_json::json!({}),
status: SessionStatus::Running,
started_at: chrono::Utc::now().timestamp(),
ended_at: None,
result: None,
error: None,
};
let session_id = storage.create_session(session).await?;

let result = agent.execute(&args.prompt, session_id).await?;

Expand Down
Loading