gobby-wiki 0.2.0

Gobby wiki CLI shell
pub(crate) mod ask;
pub(crate) mod audit;
pub(crate) mod backlinks;
pub(crate) mod collect;
pub(crate) mod compile;
pub(crate) mod export;
pub(crate) mod health;
pub(crate) mod index;
pub(crate) mod init;
pub(crate) mod lint;
pub(crate) mod read;
pub(crate) mod refresh;
pub(crate) mod research;
pub(crate) mod search;
pub(crate) mod setup;
pub(crate) mod sources;
pub(crate) mod status;

use std::path::Path;

use crate::support::scope::{resolve_command_scope, resolved_scope_identity};
use crate::{Command, CommandOutcome, CommandResult, ScopeIdentity, ScopeSelection, WikiError};

pub(crate) fn run(command: Command) -> Result<CommandOutcome, WikiError> {
    match command {
        Command::Init { scope } => init::execute(scope),
        Command::Setup { scope, options } => setup::execute(scope, options),
        Command::Index { scope } => index::execute(scope),
        Command::Collect { scope } => collect::execute(scope),
        Command::IngestFile {
            path,
            scope,
            options,
        } => index::execute_ingest_file(path, scope, options),
        Command::IngestUrl { urls, scope } => index::execute_ingest_url(urls, scope),
        Command::Refresh {
            scope,
            source_ids,
            dry_run,
        } => refresh::execute(scope, source_ids, dry_run),
        Command::Sources { scope } => sources::execute(scope),
        Command::RemoveSource {
            id,
            scope,
            dry_run,
            keep_asset,
        } => sources::execute_remove(id, scope, dry_run, keep_asset),
        Command::Search {
            query,
            scope,
            limit,
            include_semantic,
        } => search::execute(query, scope, limit, include_semantic),
        Command::Ask {
            query,
            scope,
            llm,
            ai,
            require_ai,
        } => ask::execute(query, scope, llm, ai, require_ai),
        Command::Read { target, scope } => read::execute(target, scope),
        Command::Backlinks { page, scope } => backlinks::execute(page, scope),
        Command::LinkSuggest { scope, limit } => backlinks::execute_link_suggest(scope, limit),
        Command::Research(options) => research::execute(options),
        Command::Compile {
            topic,
            outline,
            target_kind,
            target_page,
            write_intent,
            scope,
        } => compile::execute(
            topic,
            outline,
            target_kind,
            target_page,
            write_intent,
            scope,
        ),
        Command::Export { scope, command } => export::execute(scope, command),
        Command::Audit { scope } => audit::execute(scope),
        Command::Lint { scope } => lint::execute(scope),
        Command::Health { scope } => health::execute(scope),
        Command::Status { scope } => status::execute(scope),
    }
}

pub(crate) fn scoped_outcome(
    command: &'static str,
    scope: &ScopeIdentity,
    payload: serde_json::Value,
    text: String,
) -> CommandOutcome {
    CommandOutcome {
        status_messages: vec![format!("{command} resolved scope {scope}")],
        result: CommandResult { payload, text },
        exit_code: 0,
    }
}

pub(crate) fn run_analysis_command<T>(
    command: &'static str,
    selection: ScopeSelection,
    serialize_action: &'static str,
    run: impl FnOnce(&Path, ScopeIdentity) -> Result<T, WikiError>,
    render: impl FnOnce(&T) -> String,
) -> Result<CommandOutcome, WikiError>
where
    T: serde::Serialize,
{
    let scope = resolve_command_scope(&selection)?;
    let output_scope = resolved_scope_identity(&scope);
    let report = run(scope.root(), output_scope.clone())?;
    let payload = serde_json::to_value(&report).map_err(|error| WikiError::Json {
        action: serialize_action,
        path: None,
        source: error,
    })?;
    Ok(scoped_outcome(
        command,
        &output_scope,
        payload,
        render(&report),
    ))
}