fix: expose local index rebuild command

This commit is contained in:
HumbleTurtle
2026-08-27 00:41:28 -03:00
parent 35acd72e4e
commit 7eace14042
4 changed files with 55 additions and 1 deletions
+9
View File
@@ -6,6 +6,7 @@ Usage:
nap init nap init
nap status nap status
nap doctor nap doctor
nap reindex
nap auth login nap auth login
nap project create nap project create
nap project attach nap project attach
@@ -84,6 +85,7 @@ CANONICAL_COMMANDS = (
("init", "Initialize Napseer in the current folder."), ("init", "Initialize Napseer in the current folder."),
("status", "Show concise account, project, and runtime state."), ("status", "Show concise account, project, and runtime state."),
("doctor", "Diagnose local setup without changing it."), ("doctor", "Diagnose local setup without changing it."),
("reindex", "Rebuild the current project's local memory index."),
("auth", "Authenticate an account or repair credentials."), ("auth", "Authenticate an account or repair credentials."),
("project", "Create, attach, claim, or inspect a project."), ("project", "Create, attach, claim, or inspect a project."),
("mcp", "Install, update, inspect, or serve the local MCP runtime."), ("mcp", "Install, update, inspect, or serve the local MCP runtime."),
@@ -96,6 +98,7 @@ COMMAND_METADATA = {
"init": {"mutates": True, "visible": True}, "init": {"mutates": True, "visible": True},
"status": {"mutates": False, "visible": True}, "status": {"mutates": False, "visible": True},
"doctor": {"mutates": False, "visible": True}, "doctor": {"mutates": False, "visible": True},
"reindex": {"mutates": True, "visible": True},
"auth": {"mutates": True, "visible": True}, "auth": {"mutates": True, "visible": True},
"project": {"mutates": True, "visible": True}, "project": {"mutates": True, "visible": True},
"mcp": {"mutates": True, "visible": True}, "mcp": {"mutates": True, "visible": True},
@@ -1066,6 +1069,10 @@ def print_command_help(command):
"Usage: nap doctor\n" "Usage: nap doctor\n"
"Run read-only checks and print exact repair commands." "Run read-only checks and print exact repair commands."
), ),
"reindex": (
"Usage: nap reindex [--limit N]\n"
"Rebuild the current project's local search and graph index."
),
"auth": ( "auth": (
"Usage: nap auth [status|login|repair]\n" "Usage: nap auth [status|login|repair]\n"
" login Authenticate an account; does not select a project.\n" " login Authenticate an account; does not select a project.\n"
@@ -1445,6 +1452,8 @@ def main(argv):
if command == "doctor": if command == "doctor":
print_json(doctor_status()) print_json(doctor_status())
return 0 return 0
if command == "reindex":
return run_wrapper("reindex", args)
if command == "mcp": if command == "mcp":
return handle_mcp(args) return handle_mcp(args)
if command == "version": if command == "version":
+11
View File
@@ -17760,6 +17760,17 @@ class McpRequestRuntime:
def cli_main(argv): def cli_main(argv):
command = argv[1] if len(argv) > 1 else "" command = argv[1] if len(argv) > 1 else ""
if command == "reindex":
args = argv[2:]
validate_cli_options(
args,
value_options={"--limit"},
command_label="nap reindex",
)
print(json.dumps(reindex_project({
"limit": int(cli_option(args, "--limit", default="200")),
}), indent=2))
return
if command == "configure": if command == "configure":
print(json.dumps(cli_configure_status(), indent=2)) print(json.dumps(cli_configure_status(), indent=2))
return return
+19 -1
View File
@@ -33,7 +33,7 @@ def test_root_help_exposes_only_canonical_commands(capsys):
output = capsys.readouterr().out output = capsys.readouterr().out
visible = [name for name, metadata in module.COMMAND_METADATA.items() if metadata["visible"]] visible = [name for name, metadata in module.COMMAND_METADATA.items() if metadata["visible"]]
assert visible == [name for name, _summary in module.CANONICAL_COMMANDS] assert visible == [name for name, _summary in module.CANONICAL_COMMANDS]
assert len(visible) == 10 assert len(visible) == 11
for name in visible: for name in visible:
assert f" {name}" in output assert f" {name}" in output
for hidden in ("chat", "plan", "lineage", "agent", "feedback", "where", "install"): for hidden in ("chat", "plan", "lineage", "agent", "feedback", "where", "install"):
@@ -101,6 +101,24 @@ def test_init_and_auth_repair_normalize_to_existing_handlers(monkeypatch):
] ]
def test_reindex_routes_to_worker_and_has_side_effect_free_help(monkeypatch, capsys):
module = load_installer()
calls = []
monkeypatch.setattr(
module,
"run_wrapper",
lambda command, args: calls.append((command, args)) or 0,
)
assert module.main(["nap", "reindex", "--limit", "50"]) == 0
assert calls == [("reindex", ["--limit", "50"])]
calls.clear()
assert module.main(["nap", "reindex", "--help"]) == 0
assert calls == []
assert "Usage: nap reindex [--limit N]" in capsys.readouterr().out
def test_update_does_not_overwrite_repository_source(monkeypatch, capsys): def test_update_does_not_overwrite_repository_source(monkeypatch, capsys):
module = load_installer() module = load_installer()
calls = [] calls = []
+16
View File
@@ -36,6 +36,22 @@ def expect_unknown(mod, argv, expected_fragment):
raise AssertionError(f"expected RuntimeError for {argv}") raise AssertionError(f"expected RuntimeError for {argv}")
def test_reindex_cli_rebuilds_with_bounded_page_size():
mod = load_module()
calls = []
mod.reindex_project = lambda args: calls.append(dict(args)) or {
"indexed": 7,
"graph_complete": True,
}
output = io.StringIO()
with contextlib.redirect_stdout(output):
mod.cli_main(["napseer_mcp_server.py", "reindex", "--limit", "50"])
assert calls == [{"limit": 50}]
assert '"indexed": 7' in output.getvalue()
def test_auth_login_rejects_history_expansion_tail_before_browser(): def test_auth_login_rejects_history_expansion_tail_before_browser():
mod = load_module() mod = load_module()
mod.operator_account_login = lambda _args: (_ for _ in ()).throw( mod.operator_account_login = lambda _args: (_ for _ in ()).throw(