use crate::cli::MemoryType;
use crate::output::JsonOutputFormat;
#[derive(clap::Args)]
#[command(after_long_help = "EXAMPLES:\n \
# Create a memory with inline body\n \
sqlite-graphrag remember --name design-auth --type decision \\\n \
--description \"auth design\" --body \"JWT for stateless auth\"\n\n \
# Create with curated graph via --graph-stdin\n \
echo '{\"body\":\"...\",\"entities\":[],\"relationships\":[]}' | \\\n \
sqlite-graphrag remember --name my-mem --type note --description \"desc\" --graph-stdin\n\n \
# Enable automatic URL extraction with --graph-stdin (URL-regex only since v1.0.79)\n \
echo '{\"body\":\"See https://docs.rs ...\",\"entities\":[],\"relationships\":[]}' | \\\n \
sqlite-graphrag remember --name url-test --type note --description \"test\" \\\n \
--graph-stdin --enable-ner\n\n \
# Idempotent upsert with --force-merge\n \
sqlite-graphrag remember --name my-mem --type note --description \"updated\" \\\n \
--body \"new content\" --force-merge\n\n\
NOTE:\n \
remember does NOT accept positional arguments.\n \
Use --body \"text\" for inline content\n \
Use --body-file path for file content\n \
Use --body-stdin for piped content\n \
Use --graph-stdin for JSON with entities and relationships\n\n\
ENTITY TYPES (for --graph-stdin entities, NOT memory --type):\n \
concept, tool, person, file, project, decision, incident,\n \
organization, location, date, dashboard, issue_tracker, memory\n \
WARNING: reference, skill, document, note, user, feedback are\n \
MEMORY types only — NOT valid for entities.\n \
Mapping: reference→concept, document→file, user→person")]
pub struct RememberArgs {
#[arg(long)]
pub name: String,
#[arg(
long,
value_enum,
long_help = "Memory kind stored in `memories.type`. Required when creating a new memory. Optional with --force-merge: if omitted the existing memory type is inherited. This is NOT the graph `entity_type` used in `--entities-file`. Valid values: user, feedback, project, reference, decision, incident, skill, document, note."
)]
pub r#type: Option<MemoryType>,
#[arg(long, allow_hyphen_values = true)]
pub description: Option<String>,
#[arg(
long,
allow_hyphen_values = true,
help = "Inline body content (max 500 KB / 512000 bytes and 30000 estimated tokens; split dense bodies into multiple memories at ~25000 tokens, or use --body-file)",
conflicts_with_all = ["body_file", "body_stdin", "graph_stdin"]
)]
pub body: Option<String>,
#[arg(
long,
help = "Read body from a file instead of --body",
conflicts_with_all = ["body", "body_stdin", "graph_stdin"]
)]
pub body_file: Option<std::path::PathBuf>,
#[arg(
long,
conflicts_with_all = ["body", "body_file", "graph_stdin"]
)]
pub body_stdin: bool,
#[arg(
long,
help = "JSON file containing entities to associate with this memory"
)]
pub entities_file: Option<std::path::PathBuf>,
#[arg(
long,
help = "JSON file containing relationships to associate with this memory"
)]
pub relationships_file: Option<std::path::PathBuf>,
#[arg(
long,
help = "Read graph JSON (body + entities + relationships) from stdin",
conflicts_with_all = [
"body",
"body_file",
"body_stdin",
"entities_file",
"relationships_file",
"graph_file"
]
)]
pub graph_stdin: bool,
#[arg(
long,
value_name = "PATH",
help = "Read graph JSON (body + entities + relationships) from a file (combines with --body/--body-file/--body-stdin)",
conflicts_with_all = ["graph_stdin", "entities_file", "relationships_file"]
)]
pub graph_file: Option<std::path::PathBuf>,
#[arg(long, help = "Namespace (flag / XDG namespace.default / global)")]
pub namespace: Option<String>,
#[arg(long)]
pub metadata: Option<String>,
#[arg(long, help = "JSON file containing metadata key-value pairs")]
pub metadata_file: Option<std::path::PathBuf>,
#[arg(long)]
pub force_merge: bool,
#[arg(
long,
value_name = "EPOCH_OR_RFC3339",
value_parser = crate::parsers::parse_expected_updated_at,
long_help = "Optimistic lock: reject if updated_at does not match. \
Accepts Unix epoch (e.g. 1700000000) or RFC 3339 (e.g. 2026-04-19T12:00:00Z)."
)]
pub expected_updated_at: Option<i64>,
#[arg(
long,
value_parser = crate::parsers::parse_bool_flexible,
action = clap::ArgAction::Set,
num_args = 0..=1,
default_missing_value = "true",
default_value = "false",
help = "Enable automatic URL-regex extraction from body (URL-regex only since v1.0.79)"
)]
pub enable_ner: bool,
#[arg(long, hide = true)]
pub skip_extraction: bool,
#[arg(
long,
default_value_t = false,
help = "Explicitly clear body content during --force-merge (without this flag, an empty body is ignored and the existing body is kept)"
)]
pub clear_body: bool,
#[arg(
long,
default_value_t = false,
help = "Validate input and report planned actions without persisting"
)]
pub dry_run: bool,
#[arg(
long,
default_value_t = false,
help = "Reject the write if --name would be normalized to kebab-case (preserve-name guard)"
)]
pub strict_name: bool,
#[arg(
long,
default_value_t = false,
help = "With --force-merge, replace (not merge) the memory's graph bindings; empty entities clears them"
)]
pub replace_graph: bool,
#[arg(long)]
pub session_id: Option<String>,
#[arg(long, value_enum, default_value_t = JsonOutputFormat::Json)]
pub format: JsonOutputFormat,
#[arg(long, hide = true, help = "No-op; JSON is always emitted on stdout")]
pub json: bool,
#[arg(long)]
pub db: Option<String>,
#[arg(long, default_value_t = crate::constants::DEFAULT_MAX_RSS_MB,
help = "Maximum process RSS in MiB; abort if exceeded during embedding (default: 8192)")]
pub max_rss_mb: u64,
#[arg(long, default_value_t = 4, value_name = "N",
value_parser = clap::value_parser!(u64).range(1..=32),
help = "Maximum simultaneous LLM embedding subprocesses (default: 4, clamp [1,32])")]
pub llm_parallelism: u64,
#[arg(long, default_value_t = false)]
pub enqueue_enrich: bool,
}