Coverage for little_loops / cli / adapt_skills_for_codex.py: 85%
41 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-06-29 00:55 -0500
« prev ^ index » next coverage.py v7.12.0, created at 2026-06-29 00:55 -0500
1"""ll-adapt-skills-for-codex: thin alias for ``ll-adapt --host codex`` (skills + commands).
3The implementation now lives in :mod:`little_loops.adapters.codex` and
4:mod:`little_loops.adapters.core`. This module is kept for backward
5compatibility; it re-exports the original helper names used by tests and
6delegates processing to :class:`~little_loops.adapters.codex.CodexEmitter`.
7"""
9from __future__ import annotations
11import argparse
12import sys
13from pathlib import Path
15from little_loops.adapters.codex import (
16 CodexEmitter,
17 _extract_skill_short_desc as _extract_short_desc,
18 _insert_skill_fields as _insert_fields,
19 _make_openai_yaml_content as _make_openai_yaml,
20 _synthesized_skill_md,
21 _title_case,
22)
23from little_loops.adapters.core import process_commands as _core_process_commands
24from little_loops.adapters.core import process_skills as _core_process_skills
25from little_loops.session_store import DEFAULT_DB_PATH, cli_event_context
27__all__ = ["main_adapt_skills_for_codex"]
30def _find_plugin_root() -> Path:
31 from little_loops.skill_expander import _find_plugin_root as _fpr
33 return _fpr()
36# ---------------------------------------------------------------------------
37# Backward-compat process wrappers (original 3/4-arg signatures)
38# ---------------------------------------------------------------------------
41def _process_skills(
42 skills_dir: Path, apply: bool, quiet: bool
43) -> tuple[int, int, int]:
44 """Backward-compat wrapper: delegate to core traversal + CodexEmitter."""
45 return _core_process_skills(CodexEmitter(), skills_dir, apply, quiet)
48def _process_commands(
49 commands_dir: Path, skills_dir: Path, apply: bool, quiet: bool
50) -> tuple[int, int, int]:
51 """Backward-compat wrapper: delegate to core traversal + CodexEmitter."""
52 return _core_process_commands(CodexEmitter(), commands_dir, skills_dir, apply, quiet)
55# ---------------------------------------------------------------------------
56# CLI entry point
57# ---------------------------------------------------------------------------
60def main_adapt_skills_for_codex() -> int:
61 """Entry point for ll-adapt-skills-for-codex CLI."""
62 with cli_event_context(DEFAULT_DB_PATH, "ll-adapt-skills-for-codex", sys.argv[1:]):
63 parser = argparse.ArgumentParser(
64 prog="ll-adapt-skills-for-codex",
65 description=(
66 "Add Codex Skills API frontmatter to ll skill SKILL.md files and "
67 "bridge commands/*.md into skills/ll-<name>/ entries for Codex CLI. "
68 "Dry-run by default; use --apply to write changes. "
69 "(Thin alias for: ll-adapt --host codex)"
70 ),
71 formatter_class=argparse.RawDescriptionHelpFormatter,
72 epilog="""
73Examples:
74 ll-adapt-skills-for-codex # Dry-run: preview proposed changes
75 ll-adapt-skills-for-codex --apply # Write skill frontmatter + bridge commands
76 ll-adapt-skills-for-codex --quiet # Suppress per-entry output
77""",
78 )
79 parser.add_argument(
80 "--apply",
81 action="store_true",
82 default=False,
83 help="Write changes to SKILL.md files and create agents/openai.yaml (default: dry-run)",
84 )
85 parser.add_argument(
86 "--quiet",
87 action="store_true",
88 default=False,
89 help="Suppress per-skill output; only print final summary",
90 )
92 args = parser.parse_args()
94 plugin_root = _find_plugin_root()
95 skills_dir = plugin_root / "skills"
96 commands_dir = plugin_root / "commands"
98 if not skills_dir.exists():
99 print(f"ERROR: skills directory not found: {skills_dir}", file=sys.stderr)
100 return 1
102 mode = "APPLY" if args.apply else "DRY-RUN"
103 if not args.quiet:
104 print(f"ll-adapt-skills-for-codex [{mode}]")
105 print(f"Skills dir: {skills_dir}")
106 print(f"Commands dir: {commands_dir}")
107 print()
109 s_adapted, s_skipped, s_errors = _process_skills(skills_dir, args.apply, args.quiet)
110 c_adapted, c_skipped, c_errors = _process_commands(
111 commands_dir, skills_dir, args.apply, args.quiet
112 )
114 adapted = s_adapted + c_adapted
115 skipped = s_skipped + c_skipped
116 errors = s_errors + c_errors
118 print(f"\nDone: {adapted} adapted, {skipped} skipped, {errors} errors")
119 return 0 if errors == 0 else 1