feat(consume): one call over a folder asks every bundle under it
`okf consume <folder>` is the server's `okf_ask` with no bundle named, byte for byte: no ranking of its own, every excerpt carrying its bundle id. `--bundle-id` asks one bundle under the folder. A flag that acts on one bundle's cut is refused by name over a folder rather than dropped, because the server takes none of them. A bundle path reads as before. v1.1 order F, part F2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
df83c65e32
commit
718c064279
4 changed files with 194 additions and 4 deletions
|
|
@ -3101,11 +3101,27 @@ def serialise(payload: Mapping[str, object]) -> str:
|
|||
# --- The CLI ------------------------------------------------------------------
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
||||
def _parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("bundle", type=Path, help="the OKF bundle directory to read")
|
||||
parser.add_argument(
|
||||
"bundle",
|
||||
type=Path,
|
||||
help=(
|
||||
"the OKF bundle directory to read, or a FOLDER: then every bundle "
|
||||
"under it is asked in one call, exactly as the server's `okf_ask` "
|
||||
"asks them, and each answer names its bundle"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bundle-id",
|
||||
default=None,
|
||||
help=(
|
||||
"over a folder, ask only the bundle with this id instead of every "
|
||||
"one; refused when the path is itself a bundle"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--question",
|
||||
required=True,
|
||||
|
|
@ -3298,7 +3314,70 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
|||
"to prevent"
|
||||
),
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
return parser
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
||||
return _parser().parse_args(argv)
|
||||
|
||||
|
||||
#: The flags the folder door takes. Everything else changes how ONE bundle is
|
||||
#: cut, and the server that asks a folder takes none of it -- so over a folder
|
||||
#: such a flag is refused by name, never dropped: a flag silently ignored makes
|
||||
#: its caller believe in a cut that never happened.
|
||||
FOLDER_FLAGS = ("--question", "--k", "--limit", "--out", "--bundle-id")
|
||||
|
||||
|
||||
def _refused_over_a_folder(argv: Sequence[str]) -> list[str]:
|
||||
options = {
|
||||
option
|
||||
for action in _parser()._actions
|
||||
for option in action.option_strings
|
||||
if option.startswith("--") and option not in (*FOLDER_FLAGS, "--help")
|
||||
}
|
||||
return sorted({token.split("=", 1)[0] for token in argv} & options)
|
||||
|
||||
|
||||
def _main_over_a_folder(args: argparse.Namespace, argv: Sequence[str]) -> int:
|
||||
"""`okf consume <folder>`: the server's `okf_ask`, with its own bytes.
|
||||
|
||||
No ranking and no cut of its own. The reply is the one `okf_ask` gives
|
||||
with no bundle named -- or with `--bundle-id` as its `bundle_id` -- so the
|
||||
command line and the server cannot come to disagree about an answer.
|
||||
"""
|
||||
from . import mcp_server
|
||||
|
||||
refused = _refused_over_a_folder(argv)
|
||||
if refused:
|
||||
print(
|
||||
f"okf_consume: FAILED - {', '.join(refused)} act(s) on one bundle's cut; "
|
||||
f"over a folder the server's own reading is used. Point at one bundle "
|
||||
f"to use {'them' if len(refused) > 1 else 'it'}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
arguments: dict[str, object] = {
|
||||
"questions": list(args.question),
|
||||
"k": args.k,
|
||||
"limit": args.limit,
|
||||
}
|
||||
if args.bundle_id is not None:
|
||||
arguments["bundle_id"] = args.bundle_id
|
||||
try:
|
||||
surface = mcp_server.build_surface(bundle=None, roots=[args.bundle])
|
||||
reply = mcp_server.call_ask(surface, arguments)
|
||||
except mcp_server.ToolError as error:
|
||||
print(f"okf_consume: FAILED - refused ({error.code}): {error}", file=sys.stderr)
|
||||
return 1
|
||||
except OSError as error:
|
||||
print(f"okf_consume: FAILED - a bundle could not be read: {error}", file=sys.stderr)
|
||||
return 2
|
||||
text = serialise(reply)
|
||||
if args.out is None:
|
||||
sys.stdout.write(text)
|
||||
else:
|
||||
args.out.write_text(text, encoding="utf-8", newline="\n")
|
||||
return 0
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
|
|
@ -3308,10 +3387,20 @@ def main(argv: list[str] | None = None) -> int:
|
|||
run did not happen. Collapsing 2 into 1 would report an unread bundle as a
|
||||
failed cut -- two findings with different owners under one number.
|
||||
"""
|
||||
args = parse_args(argv)
|
||||
raw = list(argv) if argv is not None else sys.argv[1:]
|
||||
args = parse_args(raw)
|
||||
if not args.bundle.is_dir():
|
||||
print(f"okf_consume: FAILED - {args.bundle} is not a directory", file=sys.stderr)
|
||||
return 2
|
||||
if not (args.bundle / "index.md").is_file():
|
||||
return _main_over_a_folder(args, raw)
|
||||
if args.bundle_id is not None:
|
||||
print(
|
||||
f"okf_consume: FAILED - --bundle-id names a bundle under a folder, and "
|
||||
f"{args.bundle} is itself a bundle",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
try:
|
||||
if len(args.question) > 1:
|
||||
if args.cost_vocabulary or args.rarity_weight or args.reserve_top_rank:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue