feat(kebab-cli): kebab schema subcommand (fb-27)
Text mode: doctor-style key/value layout. JSON mode: schema.v1 wire record. Honors `--config <path>` via the established `kebab_app::schema_with_config(&cfg)` facade pattern (per the P3-5 / P4-3 regression conventions). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,9 @@ enum Cmd {
|
|||||||
/// Health check.
|
/// Health check.
|
||||||
Doctor,
|
Doctor,
|
||||||
|
|
||||||
|
/// Print introspection report (wire schemas, capabilities, model versions, stats).
|
||||||
|
Schema,
|
||||||
|
|
||||||
/// Launch the Ratatui shell (P9-1 — Library pane only; search /
|
/// Launch the Ratatui shell (P9-1 — Library pane only; search /
|
||||||
/// ask / inspect panes land with p9-2 / p9-3 / p9-4).
|
/// ask / inspect panes land with p9-2 / p9-3 / p9-4).
|
||||||
Tui,
|
Tui,
|
||||||
@@ -604,6 +607,18 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cmd::Schema => {
|
||||||
|
let cfg = kebab_config::Config::load(cli.config.as_deref())?;
|
||||||
|
let report = kebab_app::schema_with_config(&cfg)?;
|
||||||
|
if cli.json {
|
||||||
|
let v = wire::wire_schema(&report);
|
||||||
|
println!("{}", serde_json::to_string(&v)?);
|
||||||
|
} else {
|
||||||
|
print_schema_text(&report);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
Cmd::Doctor => {
|
Cmd::Doctor => {
|
||||||
let report = kebab_app::doctor_with_config_path(cli.config.as_deref())?;
|
let report = kebab_app::doctor_with_config_path(cli.config.as_deref())?;
|
||||||
if cli.json {
|
if cli.json {
|
||||||
@@ -720,6 +735,49 @@ fn run(cli: &Cli) -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_schema_text(s: &kebab_app::SchemaV1) {
|
||||||
|
println!("kebab v{}\n", s.kebab_version);
|
||||||
|
|
||||||
|
println!("wire schemas");
|
||||||
|
println!(" {}", s.wire.schemas.join(", "));
|
||||||
|
println!();
|
||||||
|
|
||||||
|
println!("capabilities");
|
||||||
|
let caps = [
|
||||||
|
("json_mode", s.capabilities.json_mode),
|
||||||
|
("ingest_progress", s.capabilities.ingest_progress),
|
||||||
|
("ingest_cancellation", s.capabilities.ingest_cancellation),
|
||||||
|
("rag_multi_turn", s.capabilities.rag_multi_turn),
|
||||||
|
("search_cache", s.capabilities.search_cache),
|
||||||
|
("incremental_ingest", s.capabilities.incremental_ingest),
|
||||||
|
("streaming_ask", s.capabilities.streaming_ask),
|
||||||
|
("http_daemon", s.capabilities.http_daemon),
|
||||||
|
("mcp_server", s.capabilities.mcp_server),
|
||||||
|
("single_file_ingest", s.capabilities.single_file_ingest),
|
||||||
|
];
|
||||||
|
for (name, on) in caps {
|
||||||
|
let mark = if on { "✓" } else { "✗" };
|
||||||
|
println!(" {mark} {name}");
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
|
||||||
|
println!("models");
|
||||||
|
println!(" parser_version {}", s.models.parser_version);
|
||||||
|
println!(" chunker_version {}", s.models.chunker_version);
|
||||||
|
println!(" embedding_version {}", s.models.embedding_version);
|
||||||
|
println!(" prompt_template_version {}", s.models.prompt_template_version);
|
||||||
|
println!(" index_version {}", s.models.index_version);
|
||||||
|
println!(" corpus_revision {}", s.models.corpus_revision);
|
||||||
|
println!();
|
||||||
|
|
||||||
|
println!("stats");
|
||||||
|
println!(" doc_count {}", s.stats.doc_count);
|
||||||
|
println!(" chunk_count {}", s.stats.chunk_count);
|
||||||
|
println!(" asset_count {}", s.stats.asset_count);
|
||||||
|
let last = s.stats.last_ingest_at.as_deref().unwrap_or("(never)");
|
||||||
|
println!(" last_ingest_at {last}");
|
||||||
|
}
|
||||||
|
|
||||||
/// Minimal stdin/stdout confirm prompt for destructive ops. No new dep —
|
/// Minimal stdin/stdout confirm prompt for destructive ops. No new dep —
|
||||||
/// uses stdlib `IsTerminal` (the caller is expected to have already
|
/// uses stdlib `IsTerminal` (the caller is expected to have already
|
||||||
/// short-circuited the non-TTY case). Returns `Ok(true)` only when the
|
/// short-circuited the non-TTY case). Returns `Ok(true)` only when the
|
||||||
|
|||||||
Reference in New Issue
Block a user