feat(card): a folder shows every bundle under it, as the server does
`okf card <folder>` prints `okf_list` and `okf_describe` with no bundle named, joined by `mcp_server.overview`, and computes nothing of its own: one source, two doors. Chosen over a separate `--root` flag because the skill's first step must be the same command whether it was pointed at a bundle or at a folder of them; the rule that decides is discovery's own (a directory carrying an `index.md` is a bundle). A bundle path prints its card as before. v1.1 order F, part F1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3d149f955a
commit
df83c65e32
5 changed files with 212 additions and 4 deletions
|
|
@ -512,6 +512,35 @@ def call_describe(surface: Surface, arguments: Mapping[str, Any]) -> dict[str, A
|
|||
}
|
||||
|
||||
|
||||
def is_bundle(path: Path) -> bool:
|
||||
"""Whether `path` IS a bundle rather than a folder that may hold some.
|
||||
|
||||
The rule discovery already uses to stop descending: a directory carrying
|
||||
an `index.md`. The command line's two doors ask it to decide which shape
|
||||
they were pointed at, so a reader never has to say which one it holds.
|
||||
"""
|
||||
return (path / "index.md").is_file()
|
||||
|
||||
|
||||
def overview(surface: Surface) -> dict[str, Any]:
|
||||
"""Every bundle under the roots and each one's card, as the command line
|
||||
prints it for a FOLDER (`okf card <folder>`).
|
||||
|
||||
It is `okf_list` and `okf_describe` with no bundle named, joined, and it
|
||||
computes nothing of its own: one source, two doors. The listing carries
|
||||
what the cards do not -- the directory each bundle sits in, and the
|
||||
directories that look like a bundle and cannot be read as one.
|
||||
"""
|
||||
listing = call_list(surface, {})
|
||||
described = call_describe(surface, {})
|
||||
return {
|
||||
"shape": listing["shape"],
|
||||
"bundles": listing["bundles"],
|
||||
"unreadable": listing["unreadable"],
|
||||
"cards": described["cards"],
|
||||
}
|
||||
|
||||
|
||||
def _questions(arguments: Mapping[str, Any]) -> list[str]:
|
||||
"""`question` (one string) or `questions` (a list), never both.
|
||||
|
||||
|
|
|
|||
|
|
@ -1003,15 +1003,31 @@ def card_main(argv: list[str] | None = None) -> int:
|
|||
prog="okf card",
|
||||
description=(
|
||||
"Print one bundle's identity, concept count, conditional-field counts "
|
||||
"and whole-bundle cost as JSON. Derived from the bundle on every run."
|
||||
"and whole-bundle cost as JSON -- or, for a folder, every bundle under "
|
||||
"it with its card. Derived from the bundles on every run."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"bundle",
|
||||
type=Path,
|
||||
help=(
|
||||
"the OKF bundle to describe, or a FOLDER: then every bundle under it "
|
||||
"is listed with its card, as the server's `okf_list` and "
|
||||
"`okf_describe` give them"
|
||||
),
|
||||
)
|
||||
parser.add_argument("bundle", type=Path, help="the OKF bundle to describe")
|
||||
args = parser.parse_args(argv)
|
||||
from .mcp_server import card as build_card
|
||||
from . import mcp_server
|
||||
|
||||
try:
|
||||
payload = build_card(args.bundle.resolve(), profile=okf_consume.DEFAULT_PROFILE)
|
||||
if args.bundle.is_dir() and not mcp_server.is_bundle(args.bundle):
|
||||
surface = mcp_server.build_surface(bundle=None, roots=[args.bundle])
|
||||
payload = mcp_server.overview(surface)
|
||||
else:
|
||||
payload = mcp_server.card(args.bundle.resolve(), profile=okf_consume.DEFAULT_PROFILE)
|
||||
except mcp_server.ToolError as exc:
|
||||
print(f"refused ({exc.code}): {exc}", file=sys.stderr)
|
||||
return 1
|
||||
except okf_consume.ConsumeError as exc:
|
||||
print(f"refused ({exc.code}): {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue