feat(main): Wire SIGPIPE, color, quiet, completions, and negation flag handling
Runtime setup: - Reset SIGPIPE to SIG_DFL on Unix at the very start of main() so piping to head/grep doesn't cause a panic. - Apply --color flag to console::set_colors_enabled() after CLI parse. - Extract quiet flag and thread it to handle_ingest. Command dispatch: - Add Completions match arm using clap_complete::generate(). - Resolve all --no-X negation flags in handlers: asc, has_due, open (issues/mrs), force/full (ingest/sync), check (stats), explain (search), retry_failed (embed). - Auto-enable --check when --repair is used in handle_stats. - Suppress deprecation warnings in robot mode for List, Show, AuthTest, and SyncStatus deprecated aliases. Stubs: - Change handle_backup/handle_reset from ok:true to structured error JSON on stderr with exit code 1. Remove unused NotImplementedOutput and NotImplementedData structs. Version: - Include GIT_HASH env var in handle_version output (human and robot). - Add git_hash field to VersionData with skip_serializing_if for None. Robot-docs: - Update exit code table with codes 14-18 (Ollama, NotFound, Ambiguous) and code 20 (ConfigNotFound). Clarify code 1 and 2 descriptions. Co-Authored-By: Claude (us.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
This commit is contained in:
211
src/main.rs
211
src/main.rs
@@ -20,6 +20,7 @@ use lore::cli::commands::{
|
|||||||
print_show_mr_json, print_sync_status, print_sync_status_json, run_auth_test, run_count,
|
print_show_mr_json, print_sync_status, print_sync_status_json, run_auth_test, run_count,
|
||||||
run_doctor, run_embed, run_generate_docs, run_ingest, run_init, run_list_issues, run_list_mrs,
|
run_doctor, run_embed, run_generate_docs, run_ingest, run_init, run_list_issues, run_list_mrs,
|
||||||
run_search, run_show_issue, run_show_mr, run_stats, run_sync, run_sync_status, SyncOptions,
|
run_search, run_show_issue, run_show_mr, run_stats, run_sync, run_sync_status, SyncOptions,
|
||||||
|
IngestDisplay,
|
||||||
};
|
};
|
||||||
use lore::cli::{
|
use lore::cli::{
|
||||||
Cli, Commands, CountArgs, EmbedArgs, GenerateDocsArgs, IngestArgs, IssuesArgs, MrsArgs,
|
Cli, Commands, CountArgs, EmbedArgs, GenerateDocsArgs, IngestArgs, IssuesArgs, MrsArgs,
|
||||||
@@ -32,6 +33,12 @@ use lore::core::paths::get_db_path;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
// Reset SIGPIPE to default behavior so piping (e.g. `lore issues | head`) doesn't panic
|
||||||
|
#[cfg(unix)]
|
||||||
|
unsafe {
|
||||||
|
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize logging with indicatif support for clean progress bar output
|
// Initialize logging with indicatif support for clean progress bar output
|
||||||
let indicatif_layer = tracing_indicatif::IndicatifLayer::new();
|
let indicatif_layer = tracing_indicatif::IndicatifLayer::new();
|
||||||
|
|
||||||
@@ -52,6 +59,16 @@ async fn main() {
|
|||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
let robot_mode = cli.is_robot_mode();
|
let robot_mode = cli.is_robot_mode();
|
||||||
|
|
||||||
|
// Apply color settings (console crate handles NO_COLOR/CLICOLOR natively in "auto" mode)
|
||||||
|
match cli.color.as_str() {
|
||||||
|
"never" => console::set_colors_enabled(false),
|
||||||
|
"always" => console::set_colors_enabled(true),
|
||||||
|
"auto" => {} // console crate handles this natively
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let quiet = cli.quiet;
|
||||||
|
|
||||||
let result = match cli.command {
|
let result = match cli.command {
|
||||||
Commands::Issues(args) => handle_issues(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Issues(args) => handle_issues(cli.config.as_deref(), args, robot_mode).await,
|
||||||
Commands::Mrs(args) => handle_mrs(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Mrs(args) => handle_mrs(cli.config.as_deref(), args, robot_mode).await,
|
||||||
@@ -59,7 +76,7 @@ async fn main() {
|
|||||||
Commands::Stats(args) => handle_stats(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Stats(args) => handle_stats(cli.config.as_deref(), args, robot_mode).await,
|
||||||
Commands::Embed(args) => handle_embed(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Embed(args) => handle_embed(cli.config.as_deref(), args, robot_mode).await,
|
||||||
Commands::Sync(args) => handle_sync_cmd(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Sync(args) => handle_sync_cmd(cli.config.as_deref(), args, robot_mode).await,
|
||||||
Commands::Ingest(args) => handle_ingest(cli.config.as_deref(), args, robot_mode).await,
|
Commands::Ingest(args) => handle_ingest(cli.config.as_deref(), args, robot_mode, quiet).await,
|
||||||
Commands::Count(args) => {
|
Commands::Count(args) => {
|
||||||
handle_count(cli.config.as_deref(), args, robot_mode).await
|
handle_count(cli.config.as_deref(), args, robot_mode).await
|
||||||
}
|
}
|
||||||
@@ -67,6 +84,7 @@ async fn main() {
|
|||||||
Commands::Auth => handle_auth_test(cli.config.as_deref(), robot_mode).await,
|
Commands::Auth => handle_auth_test(cli.config.as_deref(), robot_mode).await,
|
||||||
Commands::Doctor => handle_doctor(cli.config.as_deref(), robot_mode).await,
|
Commands::Doctor => handle_doctor(cli.config.as_deref(), robot_mode).await,
|
||||||
Commands::Version => handle_version(robot_mode),
|
Commands::Version => handle_version(robot_mode),
|
||||||
|
Commands::Completions { shell } => handle_completions(&shell),
|
||||||
Commands::Init {
|
Commands::Init {
|
||||||
force,
|
force,
|
||||||
non_interactive,
|
non_interactive,
|
||||||
@@ -116,10 +134,12 @@ async fn main() {
|
|||||||
target_branch,
|
target_branch,
|
||||||
source_branch,
|
source_branch,
|
||||||
} => {
|
} => {
|
||||||
eprintln!(
|
if !robot_mode {
|
||||||
"{}",
|
eprintln!(
|
||||||
style("warning: 'lore list' is deprecated, use 'lore issues' or 'lore mrs'").yellow()
|
"{}",
|
||||||
);
|
style("warning: 'lore list' is deprecated, use 'lore issues' or 'lore mrs'").yellow()
|
||||||
|
);
|
||||||
|
}
|
||||||
handle_list_compat(
|
handle_list_compat(
|
||||||
cli.config.as_deref(),
|
cli.config.as_deref(),
|
||||||
&entity,
|
&entity,
|
||||||
@@ -150,14 +170,16 @@ async fn main() {
|
|||||||
iid,
|
iid,
|
||||||
project,
|
project,
|
||||||
} => {
|
} => {
|
||||||
eprintln!(
|
if !robot_mode {
|
||||||
"{}",
|
eprintln!(
|
||||||
style(format!(
|
"{}",
|
||||||
"warning: 'lore show' is deprecated, use 'lore {}s {}'",
|
style(format!(
|
||||||
entity, iid
|
"warning: 'lore show' is deprecated, use 'lore {}s {}'",
|
||||||
))
|
entity, iid
|
||||||
.yellow()
|
))
|
||||||
);
|
.yellow()
|
||||||
|
);
|
||||||
|
}
|
||||||
handle_show_compat(
|
handle_show_compat(
|
||||||
cli.config.as_deref(),
|
cli.config.as_deref(),
|
||||||
&entity,
|
&entity,
|
||||||
@@ -168,17 +190,21 @@ async fn main() {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
Commands::AuthTest => {
|
Commands::AuthTest => {
|
||||||
eprintln!(
|
if !robot_mode {
|
||||||
"{}",
|
eprintln!(
|
||||||
style("warning: 'lore auth-test' is deprecated, use 'lore auth'").yellow()
|
"{}",
|
||||||
);
|
style("warning: 'lore auth-test' is deprecated, use 'lore auth'").yellow()
|
||||||
|
);
|
||||||
|
}
|
||||||
handle_auth_test(cli.config.as_deref(), robot_mode).await
|
handle_auth_test(cli.config.as_deref(), robot_mode).await
|
||||||
}
|
}
|
||||||
Commands::SyncStatus => {
|
Commands::SyncStatus => {
|
||||||
eprintln!(
|
if !robot_mode {
|
||||||
"{}",
|
eprintln!(
|
||||||
style("warning: 'lore sync-status' is deprecated, use 'lore status'").yellow()
|
"{}",
|
||||||
);
|
style("warning: 'lore sync-status' is deprecated, use 'lore status'").yellow()
|
||||||
|
);
|
||||||
|
}
|
||||||
handle_sync_status_cmd(cli.config.as_deref(), robot_mode).await
|
handle_sync_status_cmd(cli.config.as_deref(), robot_mode).await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -259,7 +285,10 @@ async fn handle_issues(
|
|||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
let order = if args.asc { "asc" } else { "desc" };
|
let asc = args.asc && !args.no_asc;
|
||||||
|
let has_due = args.has_due && !args.no_has_due;
|
||||||
|
let open = args.open && !args.no_open;
|
||||||
|
let order = if asc { "asc" } else { "desc" };
|
||||||
|
|
||||||
if let Some(iid) = args.iid {
|
if let Some(iid) = args.iid {
|
||||||
// Show mode
|
// Show mode
|
||||||
@@ -281,14 +310,14 @@ async fn handle_issues(
|
|||||||
milestone: args.milestone.as_deref(),
|
milestone: args.milestone.as_deref(),
|
||||||
since: args.since.as_deref(),
|
since: args.since.as_deref(),
|
||||||
due_before: args.due_before.as_deref(),
|
due_before: args.due_before.as_deref(),
|
||||||
has_due_date: args.has_due,
|
has_due_date: has_due,
|
||||||
sort: &args.sort,
|
sort: &args.sort,
|
||||||
order,
|
order,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = run_list_issues(&config, filters)?;
|
let result = run_list_issues(&config, filters)?;
|
||||||
|
|
||||||
if args.open {
|
if open {
|
||||||
open_issue_in_browser(&result);
|
open_issue_in_browser(&result);
|
||||||
} else if robot_mode {
|
} else if robot_mode {
|
||||||
print_list_issues_json(&result);
|
print_list_issues_json(&result);
|
||||||
@@ -306,7 +335,9 @@ async fn handle_mrs(
|
|||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
let order = if args.asc { "asc" } else { "desc" };
|
let asc = args.asc && !args.no_asc;
|
||||||
|
let open = args.open && !args.no_open;
|
||||||
|
let order = if asc { "asc" } else { "desc" };
|
||||||
|
|
||||||
if let Some(iid) = args.iid {
|
if let Some(iid) = args.iid {
|
||||||
// Show mode
|
// Show mode
|
||||||
@@ -337,7 +368,7 @@ async fn handle_mrs(
|
|||||||
|
|
||||||
let result = run_list_mrs(&config, filters)?;
|
let result = run_list_mrs(&config, filters)?;
|
||||||
|
|
||||||
if args.open {
|
if open {
|
||||||
open_mr_in_browser(&result);
|
open_mr_in_browser(&result);
|
||||||
} else if robot_mode {
|
} else if robot_mode {
|
||||||
print_list_mrs_json(&result);
|
print_list_mrs_json(&result);
|
||||||
@@ -353,8 +384,17 @@ async fn handle_ingest(
|
|||||||
config_override: Option<&str>,
|
config_override: Option<&str>,
|
||||||
args: IngestArgs,
|
args: IngestArgs,
|
||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
|
quiet: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
|
let display = if robot_mode || quiet {
|
||||||
|
IngestDisplay::silent()
|
||||||
|
} else {
|
||||||
|
IngestDisplay::interactive()
|
||||||
|
};
|
||||||
|
|
||||||
|
let force = args.force && !args.no_force;
|
||||||
|
let full = args.full && !args.no_full;
|
||||||
|
|
||||||
match args.entity.as_deref() {
|
match args.entity.as_deref() {
|
||||||
Some(resource_type) => {
|
Some(resource_type) => {
|
||||||
@@ -363,9 +403,9 @@ async fn handle_ingest(
|
|||||||
&config,
|
&config,
|
||||||
resource_type,
|
resource_type,
|
||||||
args.project.as_deref(),
|
args.project.as_deref(),
|
||||||
args.force,
|
force,
|
||||||
args.full,
|
full,
|
||||||
robot_mode,
|
display,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -377,7 +417,7 @@ async fn handle_ingest(
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Ingest everything: issues then MRs
|
// Ingest everything: issues then MRs
|
||||||
if !robot_mode {
|
if !robot_mode && !quiet {
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
style("Ingesting all content (issues + merge requests)...").blue()
|
style("Ingesting all content (issues + merge requests)...").blue()
|
||||||
@@ -389,9 +429,9 @@ async fn handle_ingest(
|
|||||||
&config,
|
&config,
|
||||||
"issues",
|
"issues",
|
||||||
args.project.as_deref(),
|
args.project.as_deref(),
|
||||||
args.force,
|
force,
|
||||||
args.full,
|
full,
|
||||||
robot_mode,
|
display,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -399,9 +439,9 @@ async fn handle_ingest(
|
|||||||
&config,
|
&config,
|
||||||
"mrs",
|
"mrs",
|
||||||
args.project.as_deref(),
|
args.project.as_deref(),
|
||||||
args.force,
|
force,
|
||||||
args.full,
|
full,
|
||||||
robot_mode,
|
display,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -823,65 +863,81 @@ struct VersionOutput {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct VersionData {
|
struct VersionData {
|
||||||
version: String,
|
version: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
git_hash: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_version(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_version(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let version = env!("CARGO_PKG_VERSION").to_string();
|
let version = env!("CARGO_PKG_VERSION").to_string();
|
||||||
|
let git_hash = env!("GIT_HASH").to_string();
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
let output = VersionOutput {
|
let output = VersionOutput {
|
||||||
ok: true,
|
ok: true,
|
||||||
data: VersionData { version },
|
data: VersionData {
|
||||||
|
version,
|
||||||
|
git_hash: if git_hash.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(git_hash)
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
println!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else if git_hash.is_empty() {
|
||||||
println!("lore version {}", version);
|
println!("lore version {}", version);
|
||||||
|
} else {
|
||||||
|
println!("lore version {} ({})", version, git_hash);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// JSON output for not-implemented commands.
|
fn handle_completions(shell: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
#[derive(Serialize)]
|
use clap::CommandFactory;
|
||||||
struct NotImplementedOutput {
|
use clap_complete::{Shell, generate};
|
||||||
ok: bool,
|
|
||||||
data: NotImplementedData,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
let shell = match shell {
|
||||||
struct NotImplementedData {
|
"bash" => Shell::Bash,
|
||||||
status: String,
|
"zsh" => Shell::Zsh,
|
||||||
command: String,
|
"fish" => Shell::Fish,
|
||||||
|
"powershell" => Shell::PowerShell,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cmd = Cli::command();
|
||||||
|
generate(shell, &mut cmd, "lore", &mut std::io::stdout());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_backup(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_backup(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
let output = NotImplementedOutput {
|
let output = RobotErrorWithSuggestion {
|
||||||
ok: true,
|
error: RobotErrorSuggestionData {
|
||||||
data: NotImplementedData {
|
code: "NOT_IMPLEMENTED".to_string(),
|
||||||
status: "not_implemented".to_string(),
|
message: "The 'backup' command is not yet implemented.".to_string(),
|
||||||
command: "backup".to_string(),
|
suggestion: "Use manual database backup: cp ~/.local/share/lore/lore.db ~/.local/share/lore/lore.db.bak".to_string(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
eprintln!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else {
|
||||||
println!("lore backup - not yet implemented");
|
eprintln!("{} The 'backup' command is not yet implemented.", style("Error:").red());
|
||||||
}
|
}
|
||||||
Ok(())
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_reset(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
fn handle_reset(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
let output = NotImplementedOutput {
|
let output = RobotErrorWithSuggestion {
|
||||||
ok: true,
|
error: RobotErrorSuggestionData {
|
||||||
data: NotImplementedData {
|
code: "NOT_IMPLEMENTED".to_string(),
|
||||||
status: "not_implemented".to_string(),
|
message: "The 'reset' command is not yet implemented.".to_string(),
|
||||||
command: "reset".to_string(),
|
suggestion: "Manually delete the database: rm ~/.local/share/lore/lore.db".to_string(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&output)?);
|
eprintln!("{}", serde_json::to_string(&output)?);
|
||||||
} else {
|
} else {
|
||||||
println!("lore reset - not yet implemented");
|
eprintln!("{} The 'reset' command is not yet implemented.", style("Error:").red());
|
||||||
}
|
}
|
||||||
Ok(())
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// JSON output for migrate command.
|
/// JSON output for migrate command.
|
||||||
@@ -987,7 +1043,9 @@ async fn handle_stats(
|
|||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
let result = run_stats(&config, args.check, args.repair)?;
|
// Auto-enable --check when --repair is used
|
||||||
|
let check = (args.check && !args.no_check) || args.repair;
|
||||||
|
let result = run_stats(&config, check, args.repair)?;
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
print_stats_json(&result);
|
print_stats_json(&result);
|
||||||
} else {
|
} else {
|
||||||
@@ -1002,6 +1060,7 @@ async fn handle_search(
|
|||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
|
let explain = args.explain && !args.no_explain;
|
||||||
|
|
||||||
let fts_mode = match args.fts_mode.as_str() {
|
let fts_mode = match args.fts_mode.as_str() {
|
||||||
"raw" => lore::search::FtsQueryMode::Raw,
|
"raw" => lore::search::FtsQueryMode::Raw,
|
||||||
@@ -1020,7 +1079,7 @@ async fn handle_search(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
let response = run_search(&config, &args.query, cli_filters, fts_mode, args.explain)?;
|
let response = run_search(&config, &args.query, cli_filters, fts_mode, explain)?;
|
||||||
let elapsed_ms = start.elapsed().as_millis() as u64;
|
let elapsed_ms = start.elapsed().as_millis() as u64;
|
||||||
|
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
@@ -1053,7 +1112,8 @@ async fn handle_embed(
|
|||||||
robot_mode: bool,
|
robot_mode: bool,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
let result = run_embed(&config, args.retry_failed).await?;
|
let retry_failed = args.retry_failed && !args.no_retry_failed;
|
||||||
|
let result = run_embed(&config, retry_failed).await?;
|
||||||
if robot_mode {
|
if robot_mode {
|
||||||
print_embed_json(&result);
|
print_embed_json(&result);
|
||||||
} else {
|
} else {
|
||||||
@@ -1069,10 +1129,11 @@ async fn handle_sync_cmd(
|
|||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::load(config_override)?;
|
let config = Config::load(config_override)?;
|
||||||
let options = SyncOptions {
|
let options = SyncOptions {
|
||||||
full: args.full,
|
full: args.full && !args.no_full,
|
||||||
force: args.force,
|
force: args.force && !args.no_force,
|
||||||
no_embed: args.no_embed,
|
no_embed: args.no_embed,
|
||||||
no_docs: args.no_docs,
|
no_docs: args.no_docs,
|
||||||
|
robot_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
@@ -1301,8 +1362,8 @@ fn handle_robot_docs(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>>
|
|||||||
|
|
||||||
let exit_codes = serde_json::json!({
|
let exit_codes = serde_json::json!({
|
||||||
"0": "Success",
|
"0": "Success",
|
||||||
"1": "Internal error / health check failed",
|
"1": "Internal error / health check failed / not implemented",
|
||||||
"2": "Config not found / missing flags",
|
"2": "Usage error (invalid flags or arguments)",
|
||||||
"3": "Config invalid",
|
"3": "Config invalid",
|
||||||
"4": "Token not set",
|
"4": "Token not set",
|
||||||
"5": "GitLab auth failed",
|
"5": "GitLab auth failed",
|
||||||
@@ -1313,7 +1374,13 @@ fn handle_robot_docs(robot_mode: bool) -> Result<(), Box<dyn std::error::Error>>
|
|||||||
"10": "Database error",
|
"10": "Database error",
|
||||||
"11": "Migration failed",
|
"11": "Migration failed",
|
||||||
"12": "I/O error",
|
"12": "I/O error",
|
||||||
"13": "Transform error"
|
"13": "Transform error",
|
||||||
|
"14": "Ollama unavailable",
|
||||||
|
"15": "Ollama model not found",
|
||||||
|
"16": "Embedding failed",
|
||||||
|
"17": "Not found",
|
||||||
|
"18": "Ambiguous match",
|
||||||
|
"20": "Config not found"
|
||||||
});
|
});
|
||||||
|
|
||||||
let workflows = serde_json::json!({
|
let workflows = serde_json::json!({
|
||||||
|
|||||||
Reference in New Issue
Block a user