fix(filesystem): require target-first cat syntax

This commit is contained in:
BukeLy 2026-05-26 15:00:23 +08:00
parent 3d62293a1e
commit b9ee711087
5 changed files with 57 additions and 37 deletions

View file

@ -36,7 +36,8 @@ commands described in the workspace context. grep -R is lexical evidence search;
semantic search commands return candidate documents and do not guarantee literal
text matches. Errors are returned as text prefixed with ERROR. Do not call
commands that are not listed as available. When evidence is required, inspect it
with cat or grep before answering.
with cat or grep before answering. Prefer shell-like target-first cat syntax:
cat <ref> --structure, cat <ref> --page 31-59, and cat <ref> --node 0009.
"""
AGENT_TOOL_POLICY = """
@ -48,6 +49,8 @@ Tool policy:
- Semantic search commands are candidate-discovery tools and do not guarantee literal text matches.
- Tool errors are returned as ERROR text; recover by trying an available command.
- Use cat or grep to gather evidence before making source-backed claims.
- Prefer target-first cat syntax: cat <ref> --structure, cat <ref> --page 31-59, cat <ref> --node <node_id>.
- Do not call cat --page <ref> <start> <end>; if you need a page span, use cat <ref> --page <start>-<end>.
"""
STREAM_MODE_ALIASES = {

View file

@ -90,8 +90,8 @@ class PIFSCommandExecutor:
"- ls/tree: folder browsing",
"- find --where: exact/canonical metadata DSL filtering",
"- grep -R: recursive lexical/FTS search only; semantic vector prefilter is disabled",
"- cat --structure/--node/--page: cached PageIndex reads for PDF/Markdown files",
"- cat --all: full text artifact reads for txt/text files",
"- cat <ref> --structure/--node/--page: cached PageIndex reads for PDF/Markdown files",
"- cat <ref> --all: full text artifact reads for txt/text files",
]
if "entity" in semantic_channels:
lines.append("- find --name: entity semantic candidate discovery alias")
@ -405,12 +405,17 @@ class PIFSCommandExecutor:
def _cmd_cat(self, args: list[str]) -> Any:
if not args:
raise PIFSCommandError("cat requires a file target")
target = None
target = args[0]
if target.startswith("-"):
raise PIFSCommandError(
"cat syntax is target-first: cat <ref> --structure, "
"cat <ref> --page 31-59, or cat <ref> --node 0009"
)
location = "all"
structural_mode: str | None = None
node_id: str | None = None
page_range: str | None = None
i = 0
i = 1
while i < len(args):
arg = args[i]
if arg == "--range":
@ -437,16 +442,22 @@ class PIFSCommandExecutor:
elif arg.startswith("-"):
raise PIFSCommandError(f"Unsupported cat option: {arg}")
else:
target = arg
raise PIFSCommandError(
"cat accepts one file target. Use: cat <ref> --page <page-or-range>, "
"for example: cat ref_1 --page 31-59"
)
i += 1
if not target:
raise PIFSCommandError("cat requires a file target")
if structural_mode == "structure":
return self.filesystem.pageindex_structure(target)
if structural_mode == "node":
return self.filesystem.pageindex_node(target, str(node_id))
if structural_mode == "page":
return self.filesystem.pageindex_pages(target, str(page_range))
if not page_range or not re.fullmatch(r"\d+(?:-\d+)?", page_range):
raise PIFSCommandError(
"cat --page requires one page selector like 31 or 31-59. "
"Use: cat <ref> --page <page-or-range>"
)
return self.filesystem.pageindex_pages(target, page_range)
return self.filesystem.cat_text_artifact(target, location)
def _cmd_stat(self, args: list[str]) -> Any:

View file

@ -677,7 +677,8 @@ class PageIndexFileSystem:
raise ValueError(
f"{command} is only supported for txt/text files; "
f"got source_path={entry.source_path!r}, content_type={entry.content_type!r}. "
"Use cat --structure, cat --page, or cat --node for PDF/Markdown PageIndex files."
"Use cat <ref> --structure, cat <ref> --page, or cat <ref> --node "
"for PDF/Markdown PageIndex files."
)
def _require_pageindex_document_file(self, entry: Any, command: str) -> None:
@ -686,7 +687,7 @@ class PageIndexFileSystem:
raise ValueError(
f"{command} is only supported for PDF/Markdown PageIndex files; "
f"got source_path={entry.source_path!r}, content_type={entry.content_type!r}. "
"Use cat --all for txt/text files."
"Use cat <ref> --all for txt/text files."
)
@classmethod