// main.mbt — command-line interface (mirrors Python `cli.py` + `__main__.py`)
//
// Usage:
// moon run cmd/main -- remember "内容" [--type preference] [--source s] [--no-interactive] [--conflict-policy keep]
// moon run cmd/main -- recall "查询" [--top-k 5]
// moon run cmd/main -- evolve
// moon run cmd/main -- stats
// moon run cmd/main -- list
// Common: [--root ] [--passphrase ]
///|
let _COMMANDS : Array[String] = [
"remember", "recall", "evolve", "stats", "list",
]
///|
fn is_command(s : String) -> Bool {
for c in _COMMANDS {
if c == s {
return true
}
}
false
}
///|
fn parse_int_or(s : String, d : Int) -> Int {
@string.parse_int(s) catch {
_ => d
}
}
// Substring check delegates to String::contains.
///|
fn str_has(s : String, sub : String) -> Bool {
s.contains(sub)
}
///|
fn join_spaces(parts : Array[String]) -> String {
let mut s = ""
let mut first = true
for p in parts {
if first {
s = p
first = false
} else {
s = s + " " + p
}
}
s
}
///|
fn print_json(j : Json) -> Unit {
println(j.stringify(indent=2))
}
///|
fn run_cmd(
sys : @oc.MemorySystem,
cmd : String,
rest : Array[String],
mtype : String,
source : String,
no_interactive : Bool,
conflict_policy : String,
top_k : Int,
) -> Unit raise @fs.IOError {
match cmd {
"remember" => {
let content = join_spaces(rest)
let res = sys.remember(
content,
type_hint=mtype,
source~,
interactive=!no_interactive,
conflict_policy~,
)
print_json(Json::object(res))
}
"recall" => {
let query = join_spaces(rest)
let res = sys.recall(query, top_k~)
print_json(Json::array(res))
}
"evolve" => print_json(Json::object(sys.evolve()))
"stats" => print_json(Json::object(sys.stats()))
"list" => print_json(Json::array(sys.list_all()))
_ => println("未知命令: " + cmd)
}
}
///|
fn main {
let all = @env.args()
// Under the JS backend, args are [node, script.js, ...real args]; strip those.
let args = if all.length() >= 2 && str_has(all[0], "node") {
all.view(start=2).to_owned()
} else {
all
}
let mut root = "memory"
let mut passphrase = ""
let mut mtype = ""
let mut source = "user_input"
let mut no_interactive = false
let mut top_k = 5
let mut conflict_policy = "ask"
let positional : Array[String] = []
let mut i = 0
while i < args.length() {
let a = args[i]
if a == "--root" {
root = args[i + 1]
i = i + 2
} else if a == "--passphrase" {
passphrase = args[i + 1]
i = i + 2
} else if a == "--type" {
mtype = args[i + 1]
i = i + 2
} else if a == "--source" {
source = args[i + 1]
i = i + 2
} else if a == "--top-k" {
top_k = parse_int_or(args[i + 1], 5)
i = i + 2
} else if a == "--conflict-policy" {
conflict_policy = args[i + 1]
i = i + 2
} else if a == "--no-interactive" {
no_interactive = true
i = i + 1
} else {
positional.push(a)
i = i + 1
}
}
// Find the command (skip a possible program-name element at position 0).
let cmd_idx = if positional.length() > 0 && is_command(positional[0]) {
0
} else if positional.length() > 1 && is_command(positional[1]) {
1
} else {
-1
}
if cmd_idx < 0 {
println(
"用法: [text] [--root DIR] [--passphrase SECRET] [--type T] [--source S] [--top-k K] [--no-interactive] [--conflict-policy POLICY]",
)
return
}
let cmd = positional[cmd_idx]
let rest = positional.view(start=cmd_idx + 1).to_owned()
let sys = @oc.MemorySystem::new(root, passphrase~)
run_cmd(sys, cmd, rest, mtype, source, no_interactive, conflict_policy, top_k) catch {
_ => println("错误: 运行失败")
}
}